]> err.no Git - scalable-opengroupware.org/blobdiff - SoObjects/Appointments/SOGoAppointmentObject.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1263 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SoObjects / Appointments / SOGoAppointmentObject.m
index 33e14028227b76b2908e7d2c0dd14098843d6217..12f97b38a0e13f33b7df263f62e9f49f95c719c8 100644 (file)
@@ -22,6 +22,7 @@
 #import <Foundation/NSCalendarDate.h>
 
 #import <NGObjWeb/NSException+HTTP.h>
+#import <NGObjWeb/WOContext.h>
 #import <NGExtensions/NSNull+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
 #import <NGCards/iCalCalendar.h>
 #import <NGCards/iCalPerson.h>
 
 #import <SoObjects/SOGo/LDAPUserManager.h>
+#import <SoObjects/SOGo/NSArray+Utilities.h>
 #import <SoObjects/SOGo/SOGoObject.h>
 #import <SoObjects/SOGo/SOGoPermissions.h>
+#import <SoObjects/SOGo/WORequest+SOGo.h>
 
 #import "NSArray+Appointments.h"
+#import "SOGoAppointmentFolder.h"
+
 #import "SOGoAppointmentObject.h"
 
 @implementation SOGoAppointmentObject
   return uids;
 }
 
-/* folder management */
-
-- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx {
-  // TODO: what does this do? lookup the home of the organizer?
-  return [[self container] lookupHomeFolderForUID:_uid inContext:_ctx];
-}
-- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx {
-  return [[self container] lookupCalendarFoldersForUIDs:_uids inContext:_ctx];
-}
-
 /* store in all the other folders */
 
 - (NSException *) saveContentString: (NSString *) _iCal
   NSEnumerator *e;
   id folder;
   NSException *allErrors = nil;
-  
-  e = [[self lookupCalendarFoldersForUIDs:_uids inContext: context]
-            objectEnumerator];
-  while ((folder = [e nextObject]) != nil) {
-    NSException           *error;
-    SOGoAppointmentObject *apt;
-    
-    if (![folder isNotNull]) /* no folder was found for given UID */
-      continue;
-
-    apt = [folder lookupName: [self nameInContainer] inContext: context
-                 acquire: NO];
-    if ([apt isKindOfClass: [NSException class]])
-      {
-        [self logWithFormat:@"Note: an exception occured finding '%@' in folder: %@",
-             [self nameInContainer], folder];
-        [self logWithFormat:@"the exception reason was: %@",
-              [(NSException *) apt reason]];
-        continue;
-      }
+  NSException           *error;
+  SOGoAppointmentObject *apt;
 
-    if (![apt isNotNull]) {
-      [self logWithFormat:@"Note: did not find '%@' in folder: %@",
-             [self nameInContainer], folder];
-      continue;
-    }
-    if ([apt isKindOfClass: [NSException class]]) {
-      [self logWithFormat:@"Exception: %@", [(NSException *) apt reason]];
-      continue;
-    }
-    
-    if ((error = [apt primarySaveContentString:_iCal]) != nil) {
-      [self logWithFormat:@"Note: failed to save iCal in folder: %@", folder];
-      // TODO: make compound
-      allErrors = error;
+  e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
+       objectEnumerator];
+  while ((folder = [e nextObject]))
+    {
+      apt = [SOGoAppointmentObject objectWithName: nameInContainer
+                                  inContainer: folder];
+      error = [apt primarySaveContentString:_iCal];
+      if (error)
+       {
+         [self logWithFormat:@"Note: failed to save iCal in folder: %@", folder];
+         // TODO: make compound
+         allErrors = error;
+       }
     }
-  }
 
   return allErrors;
 }
 
-- (NSException *)deleteInUIDs:(NSArray *)_uids {
+- (NSException *) deleteInUIDs: (NSArray *) _uids
+{
   NSEnumerator *e;
   id folder;
   NSException *allErrors = nil;
+  NSException           *error;
+  SOGoAppointmentObject *apt;
   
-  e = [[self lookupCalendarFoldersForUIDs:_uids inContext: context]
-            objectEnumerator];
-  while ((folder = [e nextObject])) {
-    NSException           *error;
-    SOGoAppointmentObject *apt;
-    
-    apt = [folder lookupName:[self nameInContainer] inContext: context
-                 acquire:NO];
-    if ([apt isKindOfClass: [NSException class]]) {
-      [self logWithFormat: @"%@", [(NSException *) apt reason]];
-      continue;
-    }
+  e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
+       objectEnumerator];
+  while ((folder = [e nextObject]))
+    {
+      apt = [folder lookupName: [self nameInContainer]
+                   inContext: context
+                   acquire:NO];
+      if ([apt isKindOfClass: [NSException class]]) {
+       [self logWithFormat: @"%@", [(NSException *) apt reason]];
+       continue;
+      }
     
-    if ((error = [apt primaryDelete]) != nil) {
-      [self logWithFormat:@"Note: failed to delete in folder: %@", folder];
-      // TODO: make compound
-      allErrors = error;
+      if ((error = [apt primaryDelete]) != nil) {
+       [self logWithFormat:@"Note: failed to delete in folder: %@", folder];
+       // TODO: make compound
+       allErrors = error;
+      }
     }
-  }
+
   return allErrors;
 }
 
   NSException *storeError, *delError;
   BOOL updateForcesReconsider;
   
-  updateForcesReconsider = NO;
+  if ([[context request] handledByDefaultHandler])
+    {
+      updateForcesReconsider = NO;
 
-  if ([_iCal length] == 0)
-    return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
-                       reason: @"got no iCalendar content to store!"];
+      if ([_iCal length] == 0)
+       return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
+                           reason: @"got no iCalendar content to store!"];
 
-  um = [LDAPUserManager sharedUserManager];
+      um = [LDAPUserManager sharedUserManager];
 
-  /* handle old content */
+      /* handle old content */
   
-  oldContent = [self contentAsString]; /* if nil, this is a new appointment */
-  if ([oldContent length] == 0)
-    {
-    /* new appointment */
-      [self debugWithFormat:@"saving new appointment: %@", _iCal];
-      oldApt = nil;
-    }
-  else
-    oldApt = (iCalEvent *) [self component: NO];
+      oldContent = [self contentAsString]; /* if nil, this is a new appointment */
+      if ([oldContent length] == 0)
+       {
+         /* new appointment */
+         [self debugWithFormat:@"saving new appointment: %@", _iCal];
+         oldApt = nil;
+       }
+      else
+       oldApt = (iCalEvent *) [self component: NO];
   
-  /* compare sequence if requested */
-
-  if (_v != 0) {
-    // TODO
-  }
+      /* compare sequence if requested */
+      if (_v != 0) {
+       // TODO
+      }
   
-  /* handle new content */
+      /* handle new content */
   
-  newApt = (iCalEvent *) [self component: NO];
-  if (!newApt)
-    return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
-                       reason: @"could not parse iCalendar content!"];
+      newApt = (iCalEvent *) [self component: NO];
+      if (!newApt)
+       return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
+                           reason: @"could not parse iCalendar content!"];
 
-  /* diff */
+      /* diff */
   
-  changes = [iCalEventChanges changesFromEvent: oldApt toEvent: newApt];
-  uids = [self getUIDsForICalPersons: [changes deletedAttendees]];
-  removedUIDs = [NSMutableArray arrayWithArray: uids];
-
-  uids = [self getUIDsForICalPersons: [newApt attendees]];
-  storeUIDs = [NSMutableArray arrayWithArray: uids];
-  props = [changes updatedProperties];
-
-  /* detect whether sequence has to be increased */
-  if ([changes hasChanges])
-    [newApt increaseSequence];
-
-  /* preserve organizer */
-
-  organizer = [newApt organizer];
-  uid = [self getUIDForICalPerson: organizer];
-  if (!uid)
-    uid = [self ownerInContext: nil];
-  if (uid) {
-    if (![storeUIDs containsObject:uid])
-      [storeUIDs addObject:uid];
-    [removedUIDs removeObject:uid];
-  }
-
-  /* organizer might have changed completely */
-
-  if (oldApt && ([props containsObject: @"organizer"])) {
-    uid = [self getUIDForICalPerson:[oldApt organizer]];
-    if (uid) {
-      if (![storeUIDs containsObject:uid]) {
-        if (![removedUIDs containsObject:uid]) {
-          [removedUIDs addObject:uid];
-        }
-      }
-    }
-  }
-
-  [self debugWithFormat:@"UID ops:\n  store: %@\n  remove: %@",
-                        storeUIDs, removedUIDs];
-
-  /* if time did change, all participants have to re-decide ...
-   * ... exception from that rule: the organizer
-   */
-
-  if (oldApt != nil &&
-      ([props containsObject: @"startDate"] ||
-       [props containsObject: @"endDate"]   ||
-       [props containsObject: @"duration"]))
-  {
-    NSArray  *ps;
-    unsigned i, count;
+      changes = [iCalEventChanges changesFromEvent: oldApt toEvent: newApt];
+      uids = [self getUIDsForICalPersons: [changes deletedAttendees]];
+      removedUIDs = [NSMutableArray arrayWithArray: uids];
+
+      uids = [self getUIDsForICalPersons: [newApt attendees]];
+      storeUIDs = [NSMutableArray arrayWithArray: uids];
+      props = [changes updatedProperties];
+
+      /* detect whether sequence has to be increased */
+      if ([changes hasChanges])
+       [newApt increaseSequence];
+
+      /* preserve organizer */
+
+      organizer = [newApt organizer];
+      uid = [self getUIDForICalPerson: organizer];
+      if (!uid)
+       uid = [self ownerInContext: nil];
+      if (uid)
+       {
+         [storeUIDs addObjectUniquely: uid];
+         [removedUIDs removeObject: uid];
+       }
+
+      /* organizer might have changed completely */
+
+      if (oldApt && ([props containsObject: @"organizer"]))
+       {
+         uid = [self getUIDForICalPerson: [oldApt organizer]];
+         if (uid && ![storeUIDs containsObject: uid])
+           [removedUIDs addObjectUniquely: uid];
+       }
+
+      [self debugWithFormat: @"UID ops:\n  store: %@\n  remove: %@",
+           storeUIDs, removedUIDs];
+
+      /* if time did change, all participants have to re-decide ...
+       * ... exception from that rule: the organizer
+       */
+
+      if (oldApt
+         && ([props containsObject: @"startDate"]
+             || [props containsObject: @"endDate"]
+             || [props containsObject: @"duration"]))
+       {
+         NSArray  *ps;
+         unsigned i, count;
     
-    ps    = [newApt attendees];
-    count = [ps count];
-    for (i = 0; i < count; i++) {
-      iCalPerson *p;
+         ps    = [newApt attendees];
+         count = [ps count];
+         for (i = 0; i < count; i++) {
+           iCalPerson *p;
       
-      p = [ps objectAtIndex:i];
-      if (![p hasSameEmailAddress:organizer])
-        [p setParticipationStatus:iCalPersonPartStatNeedsAction];
-    }
-    _iCal = [[newApt parent] versitString];
-    updateForcesReconsider = YES;
-  }
-
-  /* perform storing */
-
-  storeError = [self saveContentString: _iCal inUIDs: storeUIDs];
-  delError = [self deleteInUIDs: removedUIDs];
+           p = [ps objectAtIndex:i];
+           if (![p hasSameEmailAddress:organizer])
+             [p setParticipationStatus:iCalPersonPartStatNeedsAction];
+         }
+         _iCal = [[newApt parent] versitString];
+         updateForcesReconsider = YES;
+       }
 
-  // TODO: make compound
-  if (storeError != nil) return storeError;
-  if (delError   != nil) return delError;
+      /* perform storing */
 
-  /* email notifications */
-  if ([self sendEMailNotifications]
-      && [self _aptIsStillRelevant: newApt])
-    {
-      attendees
-       = [NSMutableArray arrayWithArray: [changes insertedAttendees]];
-      [attendees removePerson: organizer];
-      [self sendEMailUsingTemplateNamed: @"Invitation"
-            forOldObject: nil
-            andNewObject: newApt
-            toAttendees: attendees];
-
-      if (updateForcesReconsider) {
-        attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
-        [attendees removeObjectsInArray:[changes insertedAttendees]];
-        [attendees removePerson:organizer];
-        [self sendEMailUsingTemplateNamed: @"Update"
-              forOldObject: oldApt
-              andNewObject: newApt
-              toAttendees: attendees];
-      }
+      storeError = [self saveContentString: _iCal inUIDs: storeUIDs];
+      delError = [self deleteInUIDs: removedUIDs];
 
-      attendees
-       = [NSMutableArray arrayWithArray: [changes deletedAttendees]];
-      [attendees removePerson: organizer];
-      if ([attendees count])
-        {
-          iCalEvent *cancelledApt;
+      // TODO: make compound
+      if (storeError != nil) return storeError;
+      if (delError   != nil) return delError;
+
+      /* email notifications */
+      if ([self sendEMailNotifications]
+         && [self _aptIsStillRelevant: newApt])
+       {
+         iCalEvent *requestApt;
+
+         requestApt = [newApt copy];
+         [(iCalCalendar *) [requestApt parent] setMethod: @"request"];
+         attendees
+           = [NSMutableArray arrayWithArray: [changes insertedAttendees]];
+         [attendees removePerson: organizer];
+         [self sendEMailUsingTemplateNamed: @"Invitation"
+               forOldObject: nil
+               andNewObject: requestApt
+               toAttendees: attendees];
+         [requestApt release];
+
+         if (updateForcesReconsider)
+           {
+             iCalEvent *updatedApt;
+    
+             updatedApt = [newApt copy];
+             [(iCalCalendar *) [updatedApt parent] setMethod: @"request"];
+             attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
+             [attendees removeObjectsInArray:[changes insertedAttendees]];
+             [attendees removePerson:organizer];
+             [self sendEMailUsingTemplateNamed: @"Update"
+                   forOldObject: oldApt
+                   andNewObject: updatedApt
+                   toAttendees: attendees];
+             [updatedApt release];
+           }
+
+         attendees
+           = [NSMutableArray arrayWithArray: [changes deletedAttendees]];
+         [attendees removePerson: organizer];
+         if ([attendees count])
+           {
+             iCalEvent *cancelledApt;
     
-          cancelledApt = [newApt copy];
-          [(iCalCalendar *) [cancelledApt parent] setMethod: @"cancel"];
-          [self sendEMailUsingTemplateNamed: @"Removal"
-                forOldObject: nil
-                andNewObject: cancelledApt
-                toAttendees: attendees];
-          [cancelledApt release];
-        }
+             cancelledApt = [newApt copy];
+             [(iCalCalendar *) [cancelledApt parent] setMethod: @"cancel"];
+             [self sendEMailUsingTemplateNamed: @"Removal"
+                   forOldObject: nil
+                   andNewObject: cancelledApt
+                   toAttendees: attendees];
+             [cancelledApt release];
+           }
+       }
     }
+  else
+    [self primarySaveContentString: _iCal];
 
   return nil;
 }
 
-- (NSException *)deleteWithBaseSequence:(int)_v {
+- (NSException *) deleteWithBaseSequence: (int)_v
+{
   /* 
      Note: We need to delete in all participants folders and send iMIP messages
            for all external accounts.
   */
   iCalEvent *apt;
   NSMutableArray *attendees, *removedUIDs;
+  NSException *error;
 
+  if ([[context request] handledByDefaultHandler])
+    {
   /* load existing content */
-
-  apt = (iCalEvent *) [self component: NO];
+      apt = (iCalEvent *) [self component: NO];
   
   /* compare sequence if requested */
 
 //     // TODO
 //   }
   
-  removedUIDs = [NSMutableArray arrayWithArray:
-                                 [self attendeeUIDsFromAppointment: apt]];
-  if (![removedUIDs containsObject: owner])
-    [removedUIDs addObject: owner];
-
-  if ([self sendEMailNotifications])
-    {
-      /* send notification email to attendees excluding organizer */
-      attendees = [NSMutableArray arrayWithArray:[apt attendees]];
-      [attendees removePerson:[apt organizer]];
+      removedUIDs = [NSMutableArray arrayWithArray:
+                                     [self attendeeUIDsFromAppointment: apt]];
+      if (![removedUIDs containsObject: owner])
+       [removedUIDs addObject: owner];
+
+      if ([self sendEMailNotifications]
+         && [self _aptIsStillRelevant: apt])
+       {
+         /* send notification email to attendees excluding organizer */
+         attendees = [NSMutableArray arrayWithArray: [apt attendees]];
+         [attendees removePerson: [apt organizer]];
   
-      /* flag appointment as being cancelled */
-      [(iCalCalendar *) [apt parent] setMethod: @"cancel"];
-      [apt increaseSequence];
-
-      /* remove all attendees to signal complete removal */
-      [apt removeAllAttendees];
-
-      /* send notification email */
-      [self sendEMailUsingTemplateNamed: @"Deletion"
-            forOldObject: nil
-            andNewObject: apt
-            toAttendees: attendees];
-    }
+         /* flag appointment as being cancelled */
+         [(iCalCalendar *) [apt parent] setMethod: @"cancel"];
+         [apt increaseSequence];
+
+         /* remove all attendees to signal complete removal */
+         [apt removeAllAttendees];
 
-  /* perform */
+         /* send notification email */
+         [self sendEMailUsingTemplateNamed: @"Deletion"
+               forOldObject: nil
+               andNewObject: apt
+               toAttendees: attendees];
+       }
+
+      error = [self deleteInUIDs: removedUIDs];
+    }
+  else
+    error = [self primaryDelete];
 
-  return [self deleteInUIDs: removedUIDs];
+  return error;
 }
 
 - (NSException *) saveContentString: (NSString *) _iCalString