diff --git a/ChangeLog b/ChangeLog index c9318a25e..1cc14f34e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2008-06-19 Wolfgang Sourdeau + + * UI/MainUI/SOGoUserHomePage.m ([SOGoUserHomePage + -readFreeBusyAction]): accelerated the process of rendering free + busy information by using ptr** instead of NSArray. + + * SoObjects/Appointments/SOGoFreeBusyObject.m ([SOGoFreeBusyObject + +initialize]): initialize the default interval based on the new + "SOGoFreeBusyDefaultInterval" user default array. + ([SOGoFreeBusyObject + -fetchFreeBusyInfosFrom:startDateto:endDate]): fetch the events + from all the owner calendars. + + * SoObjects/Appointments/SOGoAppointmentFolder.m + ([SOGoAppointmentFolder + -fetchFields:_fieldsfrom:_startDateto:_endDatetitle:titlecomponent:_componentadditionalFilters:filters]): + add processed recurrent events to the list of records. + ([SOGoAppointmentFolder + -fetchFreeBusyInfosFrom:_startDateto:_endDate]): request the + "c_cycleinfo" field in order for the recurrent events to be taken + into account. + 2008-06-13 Wolfgang Sourdeau * SoObjects/Appointments/SOGoAppointmentFolder.m diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index aaebf530a..0ba6b50ab 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -512,29 +512,29 @@ static Class sogoAppointmentFolderKlass = Nil; fetchRange: (NGCalendarDateRange *) _r { NSMutableDictionary *md; - id tmp; - - md = [[_record mutableCopy] autorelease]; - - if ((tmp = [_record objectForKey:@"c_startdate"])) { - tmp = [[NSCalendarDate alloc] initWithTimeIntervalSince1970: - (NSTimeInterval)[tmp unsignedIntValue]]; - [tmp setTimeZone: timeZone]; - if (tmp) [md setObject:tmp forKey:@"startDate"]; - [tmp release]; - } - else - [self logWithFormat:@"missing 'startdate' in record?"]; + static NSString *fields[] = { @"c_startdate", @"startDate", + @"c_enddate", @"endDate" }; + unsigned int count; + NSCalendarDate *date; + NSNumber *dateValue; - if ((tmp = [_record objectForKey:@"c_enddate"])) { - tmp = [[NSCalendarDate alloc] initWithTimeIntervalSince1970: - (NSTimeInterval)[tmp unsignedIntValue]]; - [tmp setTimeZone: timeZone]; - if (tmp) [md setObject:tmp forKey:@"endDate"]; - [tmp release]; - } - else - [self logWithFormat:@"missing 'enddate' in record?"]; + md = [[_record mutableCopy] autorelease]; + for (count = 0; count < 2; count++) + { + dateValue = [_record objectForKey: fields[count * 2]]; + if (dateValue) + { + date = [NSCalendarDate dateWithTimeIntervalSince1970: + (NSTimeInterval) [dateValue unsignedIntValue]]; + if (date) + { + [date setTimeZone: timeZone]; + [md setObject: date forKey: fields[count * 2 + 1]]; + } + } + else + [self logWithFormat:@"missing '%@' in record?", fields[count * 2]]; + } return md; } @@ -797,11 +797,11 @@ static Class sogoAppointmentFolderKlass = Nil; records = [folder fetchFields: fields matchingQualifier: qualifier]; if (records) { - if (r) { + if (r) records = [self fixupCyclicRecords: records fetchRange: r]; - } if (!ma) ma = [NSMutableArray arrayWithCapacity: [records count]]; + [ma addObjectsFromArray: records]; } else if (!ma) { @@ -1772,7 +1772,7 @@ _selectorForProperty (NSString *property) if (!infos) infos = [[NSArray alloc] initWithObjects: @"c_partmails", @"c_partstates", - @"c_isopaque", @"c_status", nil]; + @"c_isopaque", @"c_status", @"c_cycleinfo", nil]; return [self fetchFields: infos from: _startDate to: _endDate diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.m b/SoObjects/Appointments/SOGoFreeBusyObject.m index d8c3ea433..3bdd2f25d 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.m +++ b/SoObjects/Appointments/SOGoFreeBusyObject.m @@ -23,6 +23,7 @@ #import #import #import +#import #import #import @@ -36,9 +37,13 @@ #import #import "SOGoAppointmentFolder.h" +#import "SOGoAppointmentFolders.h" #import "SOGoFreeBusyObject.h" +static unsigned int freebusyRangeStart = 0; +static unsigned int freebusyRangeEnd = 0; + @interface SOGoFreeBusyObject (PrivateAPI) - (NSString *) iCalStringForFreeBusyInfos: (NSArray *) _infos from: (NSCalendarDate *) _startDate @@ -47,6 +52,25 @@ @implementation SOGoFreeBusyObject ++ (void) initialize +{ + NSArray *freebusyDateRange; + NSUserDefaults *ud; + + ud = [NSUserDefaults standardUserDefaults]; + freebusyDateRange = [ud arrayForKey: @"SOGoFreeBusyDefaultInterval"]; + if (freebusyDateRange && [freebusyDateRange count] > 1) + { + freebusyRangeStart = [[freebusyDateRange objectAtIndex: 0] unsignedIntValue]; + freebusyRangeEnd = [[freebusyDateRange objectAtIndex: 1] unsignedIntValue]; + } + else + { + freebusyRangeStart = 7; + freebusyRangeEnd = 7; + } +} + - (NSString *) contentAsString { NSCalendarDate *today, *startDate, *endDate; @@ -56,9 +80,9 @@ timeZone = [[context activeUser] timeZone]; [today setTimeZone: timeZone]; - startDate = [today dateByAddingYears: 0 months: 0 days: -14 + startDate = [today dateByAddingYears: 0 months: 0 days: -freebusyRangeStart hours: 0 minutes: 0 seconds: 0]; - endDate = [startDate dateByAddingYears: 0 months: 1 days: 0 + endDate = [startDate dateByAddingYears: 0 months: 0 days: freebusyRangeEnd hours: 0 minutes: 0 seconds: 0]; return [self contentAsStringFrom: startDate to: endDate]; @@ -70,29 +94,32 @@ NSArray *infos; infos = [self fetchFreeBusyInfosFrom:_startDate to:_endDate]; + return [self iCalStringForFreeBusyInfos:infos from:_startDate to:_endDate]; } -- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate - to: (NSCalendarDate *) _endDate +- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) startDate + to: (NSCalendarDate *) endDate { SOGoAppointmentFolder *calFolder; // SoSecurityManager *sm; - NSArray *infos; + NSArray *folders; + NSMutableArray *infos; + unsigned int count, max; - calFolder = [[container lookupName: @"Calendar" inContext: context acquire: NO] - lookupName: @"personal" inContext: context acquire: NO]; -// sm = [SoSecurityManager sharedSecurityManager]; -// if (![sm validatePermission: SOGoPerm_FreeBusyLookup -// onObject: calFolder -// inContext: context]) - infos = [calFolder fetchFreeBusyInfosFrom: _startDate - to: _endDate]; -// else -// { -// infos = [NSArray new]; -// [infos autorelease]; -// } + infos = [NSMutableArray array]; + + folders = [[container lookupName: @"Calendar" + inContext: context + acquire: NO] subFolders]; + max = [folders count]; + for (count = 0; count < max; count++) + { + calFolder = [folders objectAtIndex: count]; + if (![calFolder isSubscription]) + [infos addObjectsFromArray: [calFolder fetchFreeBusyInfosFrom: startDate + to: endDate]]; + } return infos; } @@ -169,18 +196,14 @@ /* FREEBUSY */ events = [_infos objectEnumerator]; - info = [events nextObject]; - while (info) - { - if ([[info objectForKey: @"c_isopaque"] boolValue]) - { - type = [self _fbTypeForEventStatus: [info objectForKey: @"c_status"]]; - [freebusy addFreeBusyFrom: [info objectForKey: @"startDate"] - to: [info objectForKey: @"endDate"] - type: type]; - } - info = [events nextObject]; - } + while ((info = [events nextObject])) + if ([[info objectForKey: @"c_isopaque"] boolValue]) + { + type = [self _fbTypeForEventStatus: [info objectForKey: @"c_status"]]; + [freebusy addFreeBusyFrom: [info objectForKey: @"startDate"] + to: [info objectForKey: @"endDate"] + type: type]; + } [calendar setUniqueChild: freebusy]; diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index 08ac31b6c..38ea2a446 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -52,21 +52,6 @@ @implementation SOGoUserFolder -// + (void) initialize -// { -// SoClassSecurityInfo *sInfo; -// NSArray *basicRoles; - -// sInfo = [self soClassSecurityInfo]; -// [sInfo declareObjectProtected: SoPerm_View]; - -// basicRoles = [NSArray arrayWithObject: SoRole_Authenticated]; - -// /* require Authenticated role for View and WebDAV */ -// [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View]; -// [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess]; -// } - /* hierarchy */ - (NSArray *) toManyRelationshipKeys @@ -413,20 +398,6 @@ return r; } -// - (SOGoGroupsFolder *) lookupGroupsFolder -// { -// return [self lookupName: @"Groups" inContext: nil acquire: NO]; -// } - -/* name lookup */ - -// - (NSString *) permissionForKey: (NSString *) key -// { -// return ([key isEqualToString: @"freebusy.ifb"] -// ? SoPerm_WebDAVAccess -// : [super permissionForKey: key]); -// } - - (SOGoAppointmentFolders *) privateCalendars: (NSString *) key inContext: (WOContext *) localContext { @@ -456,12 +427,6 @@ return contacts; } -// - (id) groupsFolder: (NSString *) _key -// inContext: (WOContext *) _ctx -// { -// return [$(@"SOGoGroupsFolder") objectWithName: _key inContainer: self]; -// } - - (id) mailAccountsFolder: (NSString *) _key inContext: (WOContext *) _ctx { @@ -489,13 +454,8 @@ if ([_key isEqualToString: @"Calendar"] && [currentUser canAccessModule: _key]) obj = [self privateCalendars: @"Calendar" inContext: _ctx]; -// if (![_key isEqualToString: @"Calendar"]) -// obj = [obj lookupName: [_key pathExtension] -// inContext: _ctx acquire: NO]; else if ([_key isEqualToString: @"Contacts"]) obj = [self privateContacts: _key inContext: _ctx]; -// else if ([_key isEqualToString: @"Groups"]) -// obj = [self groupsFolder: _key inContext: _ctx]; else if ([_key isEqualToString: @"Mail"] && [currentUser canAccessModule: _key]) obj = [self mailAccountsFolder: _key inContext: _ctx]; @@ -511,39 +471,6 @@ return obj; } -// /* FIXME: here is a vault of hackish ways to gain access to subobjects by -// granting ro access to the homepage depending on the subobject in question. -// This is wrong and dangerous. */ -// - (NSString *) roleOfUser: (NSString *) uid -// inContext: (WOContext *) context -// { -// NSArray *roles, *traversalPath; -// NSString *objectName, *role; - -// role = nil; -// traversalPath = [context objectForKey: @"SoRequestTraversalPath"]; -// if ([traversalPath count] > 1) -// { -// objectName = [traversalPath objectAtIndex: 1]; -// if ([objectName isEqualToString: @"Calendar"] -// || [objectName isEqualToString: @"Contacts"]) -// { -// roles = [[context activeUser] -// rolesForObject: [self lookupName: objectName -// inContext: context -// acquire: NO] -// inContext: context]; -// if ([roles containsObject: SOGoRole_Assistant] -// || [roles containsObject: SOGoRole_Delegate]) -// role = SOGoRole_Assistant; -// } -// else if ([objectName isEqualToString: @"freebusy.ifb"]) -// role = SOGoRole_Assistant; -// } - -// return role; -// } - /* WebDAV */ - (NSArray *) fetchContentObjectNames diff --git a/UI/MainUI/SOGoUserHomePage.m b/UI/MainUI/SOGoUserHomePage.m index 002e93d41..7dac5b558 100644 --- a/UI/MainUI/SOGoUserHomePage.m +++ b/UI/MainUI/SOGoUserHomePage.m @@ -41,6 +41,8 @@ #import #import +#define intervalSeconds 900 /* 15 minutes */ + static NSString *defaultModule = nil; @interface SOGoUserHomePage : UIxComponent @@ -87,60 +89,65 @@ static NSString *defaultModule = nil; return [self redirectToLocation: [moduleURL absoluteString]]; } -- (void) _fillFreeBusyItems: (NSMutableArray *) items - withRecords: (NSEnumerator *) records +- (void) _fillFreeBusyItems: (unsigned int *) items + count: (unsigned int) itemCount + withRecords: (NSArray *) records fromStartDate: (NSCalendarDate *) startDate toEndDate: (NSCalendarDate *) endDate { NSDictionary *record; - int count, startInterval, endInterval, value; - NSNumber *status; + int recordCount, recordMax, count, startInterval, endInterval; NSCalendarDate *currentDate; - - while ((record = [records nextObject])) + + recordMax = [records count]; + for (recordCount = 0; recordCount < recordMax; recordCount++) { - status = [record objectForKey: @"c_status"]; - - value = [[record objectForKey: @"c_startdate"] intValue]; - currentDate = [NSCalendarDate dateWithTimeIntervalSince1970: value]; - if ([currentDate earlierDate: startDate] == currentDate) - startInterval = 0; - else - startInterval - = ([currentDate timeIntervalSinceDate: startDate] / 900); + record = [records objectAtIndex: recordCount]; + if ([[record objectForKey: @"c_isopaque"] boolValue]) + { + currentDate = [record objectForKey: @"startDate"]; + if ([currentDate earlierDate: startDate] == currentDate) + startInterval = 0; + else + startInterval = ([currentDate timeIntervalSinceDate: startDate] + / intervalSeconds); - value = [[record objectForKey: @"c_enddate"] intValue]; - currentDate = [NSCalendarDate dateWithTimeIntervalSince1970: value]; - if ([currentDate earlierDate: endDate] == endDate) - endInterval = [items count] - 1; - else - endInterval = ([currentDate timeIntervalSinceDate: startDate] / 900); + currentDate = [record objectForKey: @"endDate"]; + if ([currentDate earlierDate: endDate] == endDate) + endInterval = itemCount - 1; + else + endInterval = ([currentDate timeIntervalSinceDate: startDate] + / intervalSeconds); - for (count = startInterval; count < endInterval; count++) - [items replaceObjectAtIndex: count withObject: status]; + for (count = startInterval; count < endInterval; count++) + *(items + count) = 1; + } } } - + - (NSString *) _freeBusyAsTextFromStartDate: (NSCalendarDate *) startDate toEndDate: (NSCalendarDate *) endDate forFreeBusy: (SOGoFreeBusyObject *) fb { - NSEnumerator *records; - NSMutableArray *freeBusyItems; + NSMutableString *response; + unsigned int *freeBusyItems; NSTimeInterval interval; - int count, intervals; + unsigned int count, intervals; interval = [endDate timeIntervalSinceDate: startDate] + 60; - intervals = interval / 900; /* slices of 15 minutes */ - freeBusyItems = [NSMutableArray arrayWithCapacity: intervals]; - for (count = 1; count < intervals; count++) - [freeBusyItems addObject: @"0"]; - - records = [[fb fetchFreeBusyInfosFrom: startDate to: endDate] objectEnumerator]; - [self _fillFreeBusyItems: freeBusyItems withRecords: records + intervals = interval / intervalSeconds; /* slices of 15 minutes */ + freeBusyItems = calloc (intervals, sizeof (int)); + [self _fillFreeBusyItems: freeBusyItems count: intervals + withRecords: [fb fetchFreeBusyInfosFrom: startDate to: endDate] fromStartDate: startDate toEndDate: endDate]; - return [freeBusyItems componentsJoinedByString: @","]; + response = [NSMutableString string]; + for (count = 0; count < intervals; count++) + [response appendFormat: @"%d,", *(freeBusyItems + count)]; + [response deleteCharactersInRange: NSMakeRange (intervals * 2 - 1, 1)]; + free (freeBusyItems); + + return response; } - (NSString *) _freeBusyAsText