Monotone-Parent: f4b1c33458e395b67d8a7e5d8465de2e7bb1bc50
Monotone-Revision: bb0d71310c5e05a41e1acc07768c6ec4c2b2b5fe Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-06-19T18:31:18 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
ee5713f146
commit
b658f6890c
22
ChangeLog
22
ChangeLog
|
@ -1,3 +1,25 @@
|
|||
2008-06-19 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* 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 <wsourdeau@inverse.ca>
|
||||
|
||||
* 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
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
|
@ -36,9 +37,13 @@
|
|||
#import <SOGo/SOGoPermissions.h>
|
||||
|
||||
#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];
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
#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
|
||||
|
|
Loading…
Reference in New Issue