From: znek Date: Wed, 6 Jul 2005 20:56:09 +0000 (+0000) Subject: fixed free/busy calculation, added freebusy.ifb object for access via DAV (helpful... X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=363cec31615981738b39743a6bbc958e87481a57;p=scalable-opengroupware.org fixed free/busy calculation, added freebusy.ifb object for access via DAV (helpful for debugging) git-svn-id: http://svn.opengroupware.org/SOGo/trunk@675 d1b88da0-ebda-0310-925b-ed51d893ca5b --- diff --git a/SOGo/SoObjects/Appointments/ChangeLog b/SOGo/SoObjects/Appointments/ChangeLog index 4e8bb904..81ccb122 100644 --- a/SOGo/SoObjects/Appointments/ChangeLog +++ b/SOGo/SoObjects/Appointments/ChangeLog @@ -1,3 +1,21 @@ +2005-07-06 Marcus Mueller + + * v0.9.35 + + * GNUMakefile: added SOGoFreeBusyObject.m + + * product.plist: added SOGoFreeBusyObject + + * SOGoFreeBusyObject.[hm]: new class resembling free/busy information + for a particular user. Because free/busy information isn't solely + based upon appointments, this is now a part of the user folder. + However the information contained therein is still based on + information provided by appointments, only. This should be fixed in + a later release. + + * SOGoAppointmentFolder.m: new API to lookup freeBusyObjects for an + array of uids. + 2005-07-05 Marcus Mueller * SOGoAppointmentFolder.m: fetch new priority field in core infos diff --git a/SOGo/SoObjects/Appointments/GNUmakefile b/SOGo/SoObjects/Appointments/GNUmakefile index c4709e5d..0cd04c8e 100644 --- a/SOGo/SoObjects/Appointments/GNUmakefile +++ b/SOGo/SoObjects/Appointments/GNUmakefile @@ -12,6 +12,7 @@ Appointments_OBJC_FILES = \ SOGoAppointmentObject.m \ SOGoAppointmentFolder.m \ SOGoGroupAppointmentFolder.m \ + SOGoFreeBusyObject.m \ Appointments_RESOURCE_FILES += \ Version \ diff --git a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h index 7019e761..9214e38a 100644 --- a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -76,6 +76,7 @@ - (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx; - (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx; +- (NSArray *)lookupFreeBusyObjectsForUIDs:(NSArray *)_uids inContext:(id)_ctx; - (NSArray *)uidsFromICalPersons:(NSArray *)_persons; - (NSArray *)lookupCalendarFoldersForICalPerson:(NSArray *)_persons diff --git a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m index d0da865f..ebd25966 100644 --- a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -382,7 +382,7 @@ static NSTimeZone *MET = nil; { static NSArray *infos = nil; // TODO: move to a plist file if (infos == nil) { - infos = [[NSArray alloc] init]; + infos = [[NSArray alloc] initWithObjects:@"partmails", @"partstates", nil]; } return [self fetchFields:infos from:_startDate to:_endDate]; } @@ -500,6 +500,33 @@ static NSTimeZone *MET = nil; return folders; } +- (NSArray *)lookupFreeBusyObjectsForUIDs:(NSArray *)_uids inContext:(id)_ctx { + /* Note: can return NSNull objects in the array! */ + NSMutableArray *objs; + NSEnumerator *e; + NSString *uid; + + if ([_uids count] == 0) return nil; + objs = [NSMutableArray arrayWithCapacity:16]; + e = [_uids objectEnumerator]; + while ((uid = [e nextObject])) { + id obj; + + obj = [self lookupHomeFolderForUID:uid inContext:nil]; + if ([obj isNotNull]) { + obj = [obj lookupName:@"freebusy.ifb" inContext:nil acquire:NO]; + if ([obj isKindOfClass:[NSException class]]) + obj = nil; + } + if (![obj isNotNull]) + [self logWithFormat:@"Note: did not find freebusy.ifb for uid: '%@'", uid]; + + /* Note: intentionally add 'null' folders to allow a mapping */ + [objs addObject:obj ? obj : [NSNull null]]; + } + return objs; +} + - (NSArray *)uidsFromICalPersons:(NSArray *)_persons { /* Note: can return NSNull objects in the array! */ NSMutableArray *uids; diff --git a/SOGo/SoObjects/Appointments/SOGoFreeBusyObject.h b/SOGo/SoObjects/Appointments/SOGoFreeBusyObject.h new file mode 100644 index 00000000..16994a04 --- /dev/null +++ b/SOGo/SoObjects/Appointments/SOGoFreeBusyObject.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2000-2004 SKYRIX Software AG + + This file is part of OGo + + OGo is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + OGo is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with OGo; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ +// $Id$ + + +#ifndef __Appointments_SOGoFreeBusyObject_H_ +#define __Appointments_SOGoFreeBusyObject_H_ + +#include + +/* + SOGoFreeBusyObject + + Represents Free/Busy information for a single user as specified in RFC2445. +*/ + +@class NSArray, NSCalendarDate; + +@interface SOGoFreeBusyObject : SOGoContentObject +{ +} + +/* accessors */ + +- (NSString *)iCalString; + +- (NSString *)contentAsStringFrom:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate; + +- (NSArray *)fetchFreebusyInfosFrom:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate; + +@end + +#endif /* __Appointments_SOGoFreeBusyObject_H_ */ diff --git a/SOGo/SoObjects/Appointments/SOGoFreeBusyObject.m b/SOGo/SoObjects/Appointments/SOGoFreeBusyObject.m new file mode 100644 index 00000000..d3021fdf --- /dev/null +++ b/SOGo/SoObjects/Appointments/SOGoFreeBusyObject.m @@ -0,0 +1,213 @@ +/* + Copyright (C) 2000-2004 SKYRIX Software AG + + This file is part of OGo + + OGo is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + OGo is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with OGo; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ +// $Id$ + +#include "SOGoFreeBusyObject.h" +#include "common.h" +#include +#include +#include + +@interface NSDate(UsedPrivates) +- (NSString *)icalString; // declared in NGiCal +@end + +@interface SOGoFreeBusyObject (PrivateAPI) +- (NSString *)iCalStringForFreeBusyInfos:(NSArray *)_infos + from:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate; +@end + +@implementation SOGoFreeBusyObject + +- (NSString *)iCalString { + // for UI-X appointment viewer + return [self contentAsString]; +} + +- (NSString *)contentAsString { + NSCalendarDate *startDate, *endDate; + + startDate = [[[NSCalendarDate calendarDate] mondayOfWeek] beginOfDay]; + endDate = [startDate dateByAddingYears:0 + months:0 + days:7 + hours:23 + minutes:59 + seconds:59]; + return [self contentAsStringFrom:startDate to:endDate]; +} + +- (NSString *)contentAsStringFrom:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate +{ + NSArray *infos; + + infos = [self fetchFreebusyInfosFrom:_startDate to:_endDate]; + return [self iCalStringForFreeBusyInfos:infos from:_startDate to:_endDate]; +} + +- (NSArray *)fetchFreebusyInfosFrom:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate +{ + id userFolder, calFolder; + NSArray *infos; + AgenorUserManager *um; + NSString *email; + NSMutableArray *filtered; + unsigned i, count; + + userFolder = [self container]; + calFolder = [userFolder lookupName:@"Calendar" inContext:nil acquire:NO]; + infos = [calFolder fetchFreebusyInfosFrom:_startDate to:_endDate]; + um = [AgenorUserManager sharedUserManager]; + email = [um getEmailForUID:[userFolder login]]; + count = [infos count]; + filtered = [[[NSMutableArray alloc] initWithCapacity:count] autorelease]; + + for (i = 0; i < count; i++) { + NSDictionary *info; + NSArray *partmails; + unsigned p, pCount; + + info = [infos objectAtIndex:i]; + partmails = [[info objectForKey:@"partmails"] + componentsSeparatedByString:@"\n"]; + pCount = [partmails count]; + for (p = 0; p < pCount; p++) { + NSString *pEmail; + + pEmail = [partmails objectAtIndex:p]; + if ([pEmail isEqualToString:email]) { + NSArray *partstates; + NSString *state; + + partstates = [[info objectForKey:@"partstates"] + componentsSeparatedByString:@"\n"]; + state = [partstates objectAtIndex:p]; + if ([state intValue] == iCalPersonPartStatAccepted) { + // TODO: add tentative apts as well, but put state and email + // into info + [filtered addObject:info]; + } + break; + } + } + } + return filtered; +} + +/* Private API */ + +- (NSString *)iCalStringForFreeBusyInfos:(NSArray *)_infos + from:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate +{ + AgenorUserManager *um; + NSMutableString *ms; + NSString *uid, *x; + unsigned i, count; + + um = [AgenorUserManager sharedUserManager]; + uid = [[self container] login]; + ms = [[[NSMutableString alloc] initWithCapacity:128] autorelease]; + + /* preamble */ + [ms appendString:@"BEGIN:VCALENDAR\r\n"]; + [ms appendString:@"BEGIN:VFREEBUSY\r\n"]; + /* PRODID */ + [ms appendString:@"PRODID:SOGo/0.9\r\n"]; + /* VERSION */ + [ms appendString:@"VERSION:2.0\r\n"]; + /* DTSTAMP */ + [ms appendString:@"DTSTAMP:"]; + [ms appendString:[[NSCalendarDate calendarDate] icalString]]; + [ms appendString:@"\r\n"]; + + /* ORGANIZER - strictly required but missing for now */ + + /* ATTENDEE */ + [ms appendString:@"ATTENDEE"]; + if ((x = [um getCNForUID:uid])) { + [ms appendString:@";CN=\""]; + [ms appendString:[x iCalDQUOTESafeString]]; + [ms appendString:@"\""]; + } + if ((x = [um getEmailForUID:uid])) { + [ms appendString:@":"]; /* sic! */ + [ms appendString:[x iCalSafeString]]; + } + [ms appendString:@"\r\n"]; + + /* DTSTART */ + [ms appendString:@"DTSTART:"]; + [ms appendString:[_startDate icalString]]; + [ms appendString:@"\r\n"]; + + /* DTEND */ + [ms appendString:@"DTEND:"]; + [ms appendString:[_endDate icalString]]; + [ms appendString:@"\r\n"]; + + /* FREEBUSY */ + count = [_infos count]; + for (i = 0; i < count; i++) { + NSDictionary *info; + NSCalendarDate *startDate, *endDate; + + info = [_infos objectAtIndex:i]; + startDate = [info objectForKey:@"startDate"]; + endDate = [info objectForKey:@"endDate"]; + + /* NOTE: currently we cannot differentiate between all the types defined + * in RFC2445, Section 4.2.9. + * These are: FREE" / "BUSY" / "BUSY-UNAVAILABLE" / "BUSY-TENTATIVE" + */ + + [ms appendString:@"FREEBUSY;FBTYPE=BUSY:"]; + [ms appendString:[startDate icalString]]; + [ms appendString:@"/"]; + [ms appendString:[endDate icalString]]; + [ms appendString:@"\r\n"]; + } + + /* postamble */ + [ms appendString:@"END:VFREEBUSY\r\n"]; + [ms appendString:@"END:VCALENDAR\r\n"]; + return ms; +} + +/* deliver content without need for view method */ + +- (id)GETAction:(id)_ctx { + WOResponse *r; + NSData *contentData; + + contentData = [[self contentAsString] dataUsingEncoding:NSUTF8StringEncoding]; + + r = [(WOContext *)_ctx response]; + [r setHeader:@"text/calendar" forKey:@"content-type"]; + [r setContent:contentData]; + [r setStatus:200]; + return r; +} + +@end diff --git a/SOGo/SoObjects/Appointments/Version b/SOGo/SoObjects/Appointments/Version index 9b34cb77..ffe201b8 100644 --- a/SOGo/SoObjects/Appointments/Version +++ b/SOGo/SoObjects/Appointments/Version @@ -1,6 +1,6 @@ # Version file -SUBMINOR_VERSION:=34 +SUBMINOR_VERSION:=35 # v0.9.32 requires libGDLContentStore v4.5.26 # v0.9.28 requires libNGiCal v4.5.47 diff --git a/SOGo/SoObjects/Appointments/product.plist b/SOGo/SoObjects/Appointments/product.plist index 781de9bc..8692cfd8 100644 --- a/SOGo/SoObjects/Appointments/product.plist +++ b/SOGo/SoObjects/Appointments/product.plist @@ -18,5 +18,9 @@ SOGoAppointmentObject = { superclass = "SOGoContentObject"; }; + + SOGoFreeBusyObject = { + superclass = "SOGoContentObject"; + }; }; } diff --git a/SOGo/SoObjects/SOGo/AgenorUserManager.h b/SOGo/SoObjects/SOGo/AgenorUserManager.h index 363c30fa..5f591082 100644 --- a/SOGo/SoObjects/SOGo/AgenorUserManager.h +++ b/SOGo/SoObjects/SOGo/AgenorUserManager.h @@ -46,6 +46,8 @@ /* i.e. amelie-ida01.melanie2.i2 */ - (NSString *)getServerForUID:(NSString *)_uid; +- (NSURL *)getFreeBusyURLForUID:(NSString *)_uid; + @end #endif /* __AgenorUserManager_H_ */ diff --git a/SOGo/SoObjects/SOGo/AgenorUserManager.m b/SOGo/SoObjects/SOGo/AgenorUserManager.m index 7702a9d2..c73b6935 100644 --- a/SOGo/SoObjects/SOGo/AgenorUserManager.m +++ b/SOGo/SoObjects/SOGo/AgenorUserManager.m @@ -444,41 +444,41 @@ static NSString *defaultMailDomain = @"equipement.gouv.fr"; - (NSArray *)_serverCandidatesForMineqMelRoutage:(NGLdapAttribute *)attr { NSMutableArray *serverCandidates; - unsigned i, count; - - count = [attr count]; - serverCandidates = [NSMutableArray arrayWithCapacity:count]; - for(i = 0; i < count; i++) { - NSRange r; - NSString *route; - - route = [attr stringValueAtIndex:i]; - r = [route rangeOfString:@".melanie2.i2" options:NSBackwardsSearch]; + unsigned i, count; + + count = [attr count]; + serverCandidates = [NSMutableArray arrayWithCapacity:count]; + for(i = 0; i < count; i++) { + NSRange r; + NSString *route; + + route = [attr stringValueAtIndex:i]; + r = [route rangeOfString:@".melanie2.i2" options:NSBackwardsSearch]; + if(r.length > 0) { + unsigned length; + + /* be clever */ + length = [route length]; + r = NSMakeRange(0, length - r.length); + r = [route rangeOfString:@"@" options:NSBackwardsSearch range:r]; + if(r.length > 0) { + unsigned start; + NSRange serverNameRange; + + start = NSMaxRange(r); + serverNameRange = NSMakeRange(start, length - start); + r = NSMakeRange(0, length - start); + r = [route rangeOfString:@"%" options:NSBackwardsSearch range:r]; if(r.length > 0) { - unsigned length; - - /* be clever */ - length = [route length]; - r = NSMakeRange(0, length - r.length); - r = [route rangeOfString:@"@" options:NSBackwardsSearch range:r]; - if(r.length > 0) { - unsigned start; - NSRange serverNameRange; - - start = NSMaxRange(r); - serverNameRange = NSMakeRange(start, length - start); - r = NSMakeRange(0, length - start); - r = [route rangeOfString:@"%" options:NSBackwardsSearch range:r]; - if(r.length > 0) { - NSString *serverName; - - serverName = [route substringWithRange:serverNameRange]; - [serverCandidates addObject:serverName]; - } - } + NSString *serverName; + + serverName = [route substringWithRange:serverNameRange]; + [serverCandidates addObject:serverName]; } } - return serverCandidates; + } + } + return serverCandidates; } - (NSString *)primaryGetServerForAgenorUID:(NSString *)_uid { @@ -569,6 +569,10 @@ static NSString *defaultMailDomain = @"equipement.gouv.fr"; return server; } +- (NSURL *)getFreeBusyURLForUID:(NSString *)_uid { + return nil; +} + /* debugging */ - (BOOL)isDebuggingEnabled { diff --git a/SOGo/SoObjects/SOGo/ChangeLog b/SOGo/SoObjects/SOGo/ChangeLog index 1fe25bae..c89cf327 100644 --- a/SOGo/SoObjects/SOGo/ChangeLog +++ b/SOGo/SoObjects/SOGo/ChangeLog @@ -1,3 +1,16 @@ +2005-07-06 Marcus Mueller + + * v0.9.37 + + * SOGoUserFolder.m: added 'freebusy.ifb' as an object to the + collection for proper display via DAV. + + * SOGoAppointmentICalRenderer.m: fixed header inclusion + + * AgenorUserManager.[hm]: added proposed future API for discovering + URLs for free/busy information (implementation currently returns + nil) + 2005-07-05 Marcus Mueller * SOGoAppointment.m: fixed a wrong -release (v0.9.36) diff --git a/SOGo/SoObjects/SOGo/SOGoAppointmentICalRenderer.m b/SOGo/SoObjects/SOGo/SOGoAppointmentICalRenderer.m index d0e53fdc..e377d05f 100644 --- a/SOGo/SoObjects/SOGo/SOGoAppointmentICalRenderer.m +++ b/SOGo/SoObjects/SOGo/SOGoAppointmentICalRenderer.m @@ -21,8 +21,8 @@ #include "SOGoAppointmentICalRenderer.h" #include "SOGoAppointment.h" -#include "NSString+iCal.h" #include +#include #include "common.h" // TODO: the basic renderer should be part of NGiCal diff --git a/SOGo/SoObjects/SOGo/SOGoUserFolder.h b/SOGo/SoObjects/SOGo/SOGoUserFolder.h index dce2605a..c071b7c2 100644 --- a/SOGo/SoObjects/SOGo/SOGoUserFolder.h +++ b/SOGo/SoObjects/SOGo/SOGoUserFolder.h @@ -55,6 +55,8 @@ - (NSString *)ocsUserPath; - (NSString *)ocsPrivateCalendarPath; +- (id)lookupFreeBusyObject; + @end #endif /* __SOGo_SOGoUserFolder_H__ */ diff --git a/SOGo/SoObjects/SOGo/SOGoUserFolder.m b/SOGo/SoObjects/SOGo/SOGoUserFolder.m index 92ab6507..4156e6b8 100644 --- a/SOGo/SoObjects/SOGo/SOGoUserFolder.m +++ b/SOGo/SoObjects/SOGo/SOGoUserFolder.m @@ -146,6 +146,21 @@ return [folder autorelease]; } +- (id)freeBusyObject:(NSString *)_key inContext:(id)_ctx { + static Class fbClass = Nil; + id fb; + + if (fbClass == Nil) + fbClass = NSClassFromString(@"SOGoFreeBusyObject"); + if (fbClass == Nil) { + [self errorWithFormat:@"missing SOGoFreeBusyObject class!"]; + return nil; + } + + fb = [[fbClass alloc] initWithName:_key inContainer:self]; + return [fb autorelease]; +} + - (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag { id obj; @@ -172,7 +187,10 @@ if ([_key isEqualToString:@"Mail"]) return [self mailAccountsFolder:_key inContext:_ctx]; - + + if ([_key isEqualToString:@"freebusy.ifb"]) + return [self freeBusyObject:_key inContext:_ctx]; + /* return 404 to stop acquisition */ return [NSException exceptionWithHTTPStatus:404 /* Not Found */]; } @@ -180,8 +198,12 @@ /* WebDAV */ - (NSArray *)fetchContentObjectNames { - /* the SOGoUserFolder has no 'files', only subfolders */ - return nil; + static NSArray *cos = nil; + + if (!cos) { + cos = [[NSArray alloc] initWithObjects:@"freebusy.ifb", nil]; + } + return cos; } - (BOOL)davIsCollection { diff --git a/SOGo/SoObjects/SOGo/Version b/SOGo/SoObjects/SOGo/Version index d4e9aac0..e46a17bd 100644 --- a/SOGo/SoObjects/SOGo/Version +++ b/SOGo/SoObjects/SOGo/Version @@ -1,6 +1,6 @@ # version file -SUBMINOR_VERSION:=36 +SUBMINOR_VERSION:=37 # v0.9.34 requires libGDLContentStore v4.5.26 # v0.9.26 requires libOGoContentStore v0.9.13 diff --git a/SOGo/UI/Scheduler/ChangeLog b/SOGo/UI/Scheduler/ChangeLog index a67b00ac..e1caccf9 100644 --- a/SOGo/UI/Scheduler/ChangeLog +++ b/SOGo/UI/Scheduler/ChangeLog @@ -1,3 +1,9 @@ +2005-07-06 Marcus Mueller + + * UIxAppointmentProposal.m: changed implementation of + -proposalSearchAction to use the new SOGoFreeBusyObject API + (v0.9.124) + 2005-07-05 Marcus Mueller * v0.9.123 diff --git a/SOGo/UI/Scheduler/UIxAppointmentProposal.m b/SOGo/UI/Scheduler/UIxAppointmentProposal.m index 9bcb00d8..c6be40ab 100644 --- a/SOGo/UI/Scheduler/UIxAppointmentProposal.m +++ b/SOGo/UI/Scheduler/UIxAppointmentProposal.m @@ -55,6 +55,7 @@ @end #include +#include #include #include #include "common.h" @@ -389,11 +390,10 @@ } - (id)proposalSearchAction { - NSArray *attendees, *uids; - SOGoAppointmentFolder *groupCalendar; - NSArray *infos; - NSArray *ranges; - + NSArray *attendees, *uids, *fbos, *ranges; + unsigned i, count; + NSMutableArray *allInfos; + [self logWithFormat:@"search from %@ to %@", [self startDate], [self endDate]]; @@ -403,23 +403,27 @@ [self logWithFormat:@"Note: no UIDs selected."]; return self; } - - groupCalendar = [[self clientObject] lookupGroupCalendarFolderForUIDs:uids - inContext:[self context]]; - [self debugWithFormat:@"group calendar: %@", groupCalendar]; - - if (![groupCalendar respondsToSelector:@selector(fetchFreebusyInfosFrom:to:)]) { - return [NSException exceptionWithHTTPStatus:500 /* Internal Error */ - reason:@"invalid folder to run proposal query on!"]; - } - - infos = [groupCalendar fetchFreebusyInfosFrom:[self startDate] - to:[self endDate]]; - [self debugWithFormat:@" process: %d events", [infos count]]; - ranges = [infos arrayByCreatingDateRangesFromObjectsWithStartDateKey: - @"startDate" - andEndDateKey:@"endDate"]; + fbos = [[self clientObject] lookupFreeBusyObjectsForUIDs:uids + inContext:[self context]]; + count = [fbos count]; + // wild guess at capacity + allInfos = [[[NSMutableArray alloc] initWithCapacity:count * 10] autorelease]; + + for (i = 0; i < count; i++) { + SOGoFreeBusyObject *fb; + NSArray *infos; + + fb = [fbos objectAtIndex:i]; + if (fb != (SOGoFreeBusyObject *)[NSNull null]) { + infos = [fb fetchFreebusyInfosFrom:[self startDate] to:[self endDate]]; + [allInfos addObjectsFromArray:infos]; + } + } + [self debugWithFormat:@" processing: %d infos", [allInfos count]]; + ranges = [allInfos arrayByCreatingDateRangesFromObjectsWithStartDateKey: + @"startDate" + andEndDateKey:@"endDate"]; ranges = [ranges arrayByCompactingContainedDateRanges]; [self debugWithFormat:@" ranges: %@", ranges]; diff --git a/SOGo/UI/Scheduler/Version b/SOGo/UI/Scheduler/Version index 82292a3e..8d3f6d07 100644 --- a/SOGo/UI/Scheduler/Version +++ b/SOGo/UI/Scheduler/Version @@ -1,7 +1,8 @@ # Version file -SUBMINOR_VERSION:=123 +SUBMINOR_VERSION:=124 +# v0.9.123 requires Appointments v0.9.35 # v0.9.123 requires SOGoUI v0.9.24 # v0.9.115 requires NGiCal v4.5.44 # v0.9.113 requires libSOGo v0.9.30