JSONinfy [SOGoUserHomePage readFreeBusyAction]
parent
8124faa6d4
commit
4cece88a42
|
@ -87,20 +87,42 @@
|
|||
return [self redirectToLocation: [moduleURL absoluteString]];
|
||||
}
|
||||
|
||||
- (void) _fillFreeBusyItems: (unsigned int *) items
|
||||
count: (unsigned int) itemCount
|
||||
withRecords: (NSArray *) records
|
||||
fromStartDate: (NSCalendarDate *) startDate
|
||||
- (NSDictionary *) _freeBusyFromStartDate: (NSCalendarDate *) startDate
|
||||
toEndDate: (NSCalendarDate *) endDate
|
||||
forFreeBusy: (SOGoFreeBusyObject *) fb
|
||||
andContact: (NSString *) uid
|
||||
{
|
||||
NSCalendarDate *start, *end;
|
||||
NSMutableDictionary *freeBusy, *dayData, *hourData;
|
||||
NSArray *records;
|
||||
NSArray *emails, *partstates;
|
||||
NSCalendarDate *currentDate;
|
||||
NSCalendarDate *currentDate, *currentStartDate, *currentEndDate;
|
||||
NSDictionary *record;
|
||||
NSString *dayKey, *hourKey, *minuteKey;
|
||||
NSEnumerator *freeBusyList, *dayList, *hourList;
|
||||
SOGoUser *user;
|
||||
int quarter, lastQuarter, recordCount, recordMax, count, i, type, maxBookings, isResource;
|
||||
|
||||
int recordCount, recordMax, count, startInterval, endInterval, i, type, maxBookings, isResource, delta;
|
||||
// We "copy" the start/end date because -fetchFreeBusyInfosFrom will mess
|
||||
// with the timezone and we don't want that to properly calculate the delta
|
||||
// DO NOT USE -copy HERE - it'll simply return [self retain].
|
||||
start = [NSCalendarDate dateWithYear: [startDate yearOfCommonEra]
|
||||
month: [startDate monthOfYear]
|
||||
day: [startDate dayOfMonth]
|
||||
hour: [startDate hourOfDay]
|
||||
minute: [startDate minuteOfHour]
|
||||
second: [startDate secondOfMinute]
|
||||
timeZone: [startDate timeZone]];
|
||||
|
||||
recordMax = [records count];
|
||||
end = [NSCalendarDate dateWithYear: [endDate yearOfCommonEra]
|
||||
month: [endDate monthOfYear]
|
||||
day: [endDate dayOfMonth]
|
||||
hour: [endDate hourOfDay]
|
||||
minute: [endDate minuteOfHour]
|
||||
second: [endDate secondOfMinute]
|
||||
timeZone: [endDate timeZone]];
|
||||
|
||||
freeBusy = [NSMutableDictionary dictionary];
|
||||
user = [SOGoUser userWithLogin: [[self clientObject] ownerInContext: context] roles: nil];
|
||||
maxBookings = [user numberOfSimultaneousBookings];
|
||||
isResource = [user isResource];
|
||||
|
@ -108,6 +130,8 @@
|
|||
// Fetch freebusy information if the user is NOT a resource or if multiplebookings isn't unlimited
|
||||
if (!isResource || maxBookings != 0)
|
||||
{
|
||||
records = [fb fetchFreeBusyInfosFrom: start to: end forContact: uid];
|
||||
recordMax = [records count];
|
||||
for (recordCount = 0; recordCount < recordMax; recordCount++)
|
||||
{
|
||||
record = [records objectAtIndex: recordCount];
|
||||
|
@ -147,35 +171,111 @@
|
|||
|
||||
if (type == 1)
|
||||
{
|
||||
// User is busy for this event; update items bit string
|
||||
currentDate = [record objectForKey: @"startDate"];
|
||||
if ([currentDate earlierDate: startDate] == currentDate)
|
||||
startInterval = 0;
|
||||
else
|
||||
startInterval = ([currentDate timeIntervalSinceDate: startDate]
|
||||
/ INTERVALSECONDS);
|
||||
|
||||
delta = [[currentDate timeZoneDetail] timeZoneSecondsFromGMT] - [[startDate timeZoneDetail] timeZoneSecondsFromGMT];
|
||||
startInterval += (delta/INTERVALSECONDS);
|
||||
startInterval = (startInterval < -(HALFPADDING) ? -(HALFPADDING) : startInterval);
|
||||
|
||||
currentDate = [record objectForKey: @"endDate"];
|
||||
if ([currentDate earlierDate: endDate] == endDate)
|
||||
endInterval = itemCount - 1;
|
||||
else
|
||||
endInterval = ([currentDate timeIntervalSinceDate: startDate]
|
||||
/ INTERVALSECONDS);
|
||||
|
||||
delta = [[currentDate timeZoneDetail] timeZoneSecondsFromGMT] - [[startDate timeZoneDetail] timeZoneSecondsFromGMT];
|
||||
endInterval += (delta/INTERVALSECONDS);
|
||||
endInterval = (endInterval < 0 ? 0 : endInterval);
|
||||
endInterval = (endInterval > itemCount+HALFPADDING ? itemCount+HALFPADDING : endInterval);
|
||||
|
||||
// Update bit string representation
|
||||
// If the user is a resource with restristed amount of bookings, keep the sum of overlapping events
|
||||
for (count = startInterval; count < endInterval; count++)
|
||||
// User is busy for this event
|
||||
currentStartDate = [record objectForKey: @"startDate"];
|
||||
currentEndDate = [record objectForKey: @"endDate"];
|
||||
dayKey = [currentStartDate shortDateString];
|
||||
dayData = [freeBusy objectForKey: dayKey];
|
||||
if (!dayData)
|
||||
{
|
||||
*(items + count) = (isResource && maxBookings > 0) ? *(items + count) + 1 : 1;
|
||||
dayData = [NSMutableDictionary dictionary];
|
||||
[freeBusy setObject: dayData forKey: dayKey];
|
||||
}
|
||||
if ([currentStartDate earlierDate: startDate] == currentStartDate)
|
||||
currentStartDate = startDate;
|
||||
|
||||
currentDate = [NSCalendarDate dateWithYear: [currentStartDate yearOfCommonEra]
|
||||
month: [currentStartDate monthOfYear]
|
||||
day: [currentStartDate dayOfMonth]
|
||||
hour: [currentStartDate hourOfDay]
|
||||
minute: 0
|
||||
second: 0
|
||||
timeZone: [currentStartDate timeZone]];
|
||||
|
||||
// Increment counters for quarters of first hour
|
||||
hourKey = [NSString stringWithFormat: @"%u", [currentDate hourOfDay]];
|
||||
hourData = [dayData objectForKey: hourKey];
|
||||
if (!hourData)
|
||||
{
|
||||
hourData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInt: 0], @"0",
|
||||
[NSNumber numberWithInt: 0], @"15",
|
||||
[NSNumber numberWithInt: 0], @"30",
|
||||
[NSNumber numberWithInt: 0], @"45",
|
||||
nil];
|
||||
[dayData setObject: hourData forKey: hourKey];
|
||||
}
|
||||
quarter = (int)([currentStartDate minuteOfHour] / 15 + 0.5);
|
||||
if ([currentEndDate timeIntervalSinceDate: currentDate] < 3600)
|
||||
lastQuarter = (int)([currentEndDate minuteOfHour] / 15 + 0.5);
|
||||
else
|
||||
lastQuarter = 4;
|
||||
for (i = 0; i < lastQuarter; i++) {
|
||||
if (i >= quarter)
|
||||
{
|
||||
minuteKey = [NSString stringWithFormat: @"%u", i*15];
|
||||
count = [[hourData objectForKey: minuteKey] intValue] + 1;
|
||||
[hourData setObject: [NSNumber numberWithInt: count] forKey: minuteKey];
|
||||
}
|
||||
}
|
||||
currentDate = [currentDate dateByAddingYears:0 months:0 days:0 hours:1 minutes:0 seconds:0];
|
||||
|
||||
// Increment counters of fully busy hours
|
||||
while ([currentDate compare: currentEndDate] == NSOrderedAscending &&
|
||||
[currentEndDate timeIntervalSinceDate: currentDate] >= 3600) // 1 hour
|
||||
{
|
||||
hourKey = [NSString stringWithFormat: @"%u", [currentDate hourOfDay]];
|
||||
hourData = [dayData objectForKey: hourKey];
|
||||
if (!hourData)
|
||||
{
|
||||
hourData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInt: 1], @"0",
|
||||
[NSNumber numberWithInt: 1], @"15",
|
||||
[NSNumber numberWithInt: 1], @"30",
|
||||
[NSNumber numberWithInt: 1], @"45",
|
||||
nil];
|
||||
[dayData setObject: hourData forKey: hourKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
minuteKey = [NSString stringWithFormat: @"%u", i*15];
|
||||
count = [[hourData objectForKey: minuteKey] intValue] + 1;
|
||||
[hourData setObject: [NSNumber numberWithInt: count] forKey: minuteKey];
|
||||
}
|
||||
}
|
||||
currentDate = [currentDate dateByAddingYears:0 months:0 days:0 hours:1 minutes:0 seconds:0];
|
||||
}
|
||||
|
||||
// Increment counters for quarters of last hour
|
||||
if ([currentEndDate timeIntervalSinceDate: currentDate] > 0)
|
||||
{
|
||||
hourKey = [NSString stringWithFormat: @"%u", [currentDate hourOfDay]];
|
||||
hourData = [dayData objectForKey: hourKey];
|
||||
if (!hourData)
|
||||
{
|
||||
hourData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInt: 0], @"0",
|
||||
[NSNumber numberWithInt: 0], @"15",
|
||||
[NSNumber numberWithInt: 0], @"30",
|
||||
[NSNumber numberWithInt: 0], @"45",
|
||||
nil];
|
||||
[dayData setObject: hourData forKey: hourKey];
|
||||
}
|
||||
quarter = (int)([currentEndDate minuteOfHour] / 15 + 0.5);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i < quarter)
|
||||
{
|
||||
minuteKey = [NSString stringWithFormat: @"%u", i*15];
|
||||
if (isResource)
|
||||
count = [[hourData objectForKey: minuteKey] intValue] + 1;
|
||||
else
|
||||
count = 1;
|
||||
[hourData setObject: [NSNumber numberWithInt: count] forKey: minuteKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,88 +283,44 @@
|
|||
if (maxBookings > 0)
|
||||
{
|
||||
// Reset the freebusy for the periods that are bellow the maximum number of bookings
|
||||
for (count = 0; count < itemCount; count++)
|
||||
freeBusyList = [freeBusy objectEnumerator];
|
||||
while ((dayData = [freeBusyList nextObject]))
|
||||
{
|
||||
if (*(items + count) < maxBookings)
|
||||
*(items + count) = 0;
|
||||
dayList = [dayData objectEnumerator];
|
||||
while ((hourData = [dayList nextObject]))
|
||||
{
|
||||
hourList = [hourData keyEnumerator];
|
||||
while ((minuteKey = [hourList nextObject]))
|
||||
{
|
||||
count = [[hourData objectForKey: minuteKey] intValue];
|
||||
if (count < maxBookings)
|
||||
i = 0;
|
||||
else
|
||||
*(items + count) = 1;
|
||||
i = 1;
|
||||
if (i != count)
|
||||
[hourData setObject: [NSNumber numberWithInt: i] forKey: minuteKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSString *) _freeBusyFromStartDate: (NSCalendarDate *) startDate
|
||||
toEndDate: (NSCalendarDate *) endDate
|
||||
forFreeBusy: (SOGoFreeBusyObject *) fb
|
||||
andContact: (NSString *) uid
|
||||
{
|
||||
NSCalendarDate *start, *end;
|
||||
NSMutableArray *freeBusy;
|
||||
unsigned int *freeBusyItems;
|
||||
NSTimeInterval interval;
|
||||
unsigned int count, intervals;
|
||||
|
||||
// We "copy" the start/end date because -fetchFreeBusyInfosFrom will mess
|
||||
// with the timezone and we don't want that to properly calculate the delta
|
||||
// DO NOT USE -copy HERE - it'll simply return [self retain].
|
||||
start = [NSCalendarDate dateWithYear: [startDate yearOfCommonEra]
|
||||
month: [startDate monthOfYear]
|
||||
day: [startDate dayOfMonth]
|
||||
hour: [startDate hourOfDay]
|
||||
minute: [startDate minuteOfHour]
|
||||
second: [startDate secondOfMinute]
|
||||
timeZone: [startDate timeZone]];
|
||||
|
||||
end = [NSCalendarDate dateWithYear: [endDate yearOfCommonEra]
|
||||
month: [endDate monthOfYear]
|
||||
day: [endDate dayOfMonth]
|
||||
hour: [endDate hourOfDay]
|
||||
minute: [endDate minuteOfHour]
|
||||
second: [endDate secondOfMinute]
|
||||
timeZone: [endDate timeZone]];
|
||||
|
||||
interval = [endDate timeIntervalSinceDate: startDate] + 60;
|
||||
|
||||
// Slices of 15 minutes. The +8 is to take into account that we can
|
||||
// have a timezone change during the freebusy lookup. We have +4 at the
|
||||
// beginning and +4 at the end.
|
||||
intervals = interval / INTERVALSECONDS + PADDING;
|
||||
|
||||
// Build a bit string representation of the freebusy data for the period
|
||||
freeBusyItems = calloc(intervals, sizeof (unsigned int));
|
||||
[self _fillFreeBusyItems: (freeBusyItems+HALFPADDING)
|
||||
count: (intervals-PADDING)
|
||||
withRecords: [fb fetchFreeBusyInfosFrom: start to: end forContact: uid]
|
||||
fromStartDate: startDate
|
||||
toEndDate: endDate];
|
||||
|
||||
// Convert bit string to a NSArray. We also skip by the default the non-requested information.
|
||||
freeBusy = [NSMutableArray arrayWithCapacity: intervals];
|
||||
for (count = HALFPADDING; count < (intervals-HALFPADDING); count++)
|
||||
{
|
||||
[freeBusy addObject: [NSString stringWithFormat: @"%d", *(freeBusyItems + count)]];
|
||||
}
|
||||
free(freeBusyItems);
|
||||
|
||||
// Return a NSString representation
|
||||
return [freeBusy componentsJoinedByString: @","];
|
||||
return freeBusy;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) readFreeBusyAction
|
||||
{
|
||||
WOResponse *response;
|
||||
SOGoFreeBusyObject *freebusy;
|
||||
NSCalendarDate *startDate, *endDate;
|
||||
NSDictionary *jsonResponse;
|
||||
NSString *queryDay, *uid;
|
||||
NSTimeZone *uTZ;
|
||||
SOGoUser *user;
|
||||
unsigned int httpStatus;
|
||||
|
||||
user = [context activeUser];
|
||||
uTZ = [[user userDefaults] timeZone];
|
||||
httpStatus = 200;
|
||||
|
||||
uid = [self queryParameterForKey: @"uid"];
|
||||
queryDay = [self queryParameterForKey: @"sday"];
|
||||
|
@ -281,28 +337,42 @@
|
|||
inTimeZone: uTZ];
|
||||
|
||||
if ([startDate earlierDate: endDate] == endDate)
|
||||
response = [self responseWithStatus: 403
|
||||
andString: @"Start date is later than end date."];
|
||||
{
|
||||
httpStatus = 403;
|
||||
jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"failure", @"status",
|
||||
@"Start date is later than end date.", @"message",
|
||||
nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
freebusy = [self clientObject];
|
||||
response
|
||||
= [self responseWithStatus: 200
|
||||
andString: [self _freeBusyFromStartDate: startDate
|
||||
jsonResponse = [self _freeBusyFromStartDate: startDate
|
||||
toEndDate: endDate
|
||||
forFreeBusy: freebusy
|
||||
andContact: uid]];
|
||||
andContact: uid];
|
||||
}
|
||||
}
|
||||
else
|
||||
response = [self responseWithStatus: 403
|
||||
andString: @"Invalid end date."];
|
||||
{
|
||||
httpStatus = 403;
|
||||
jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"failure", @"status",
|
||||
@"Invalid end date.", @"message",
|
||||
nil];
|
||||
}
|
||||
}
|
||||
else
|
||||
response = [self responseWithStatus: 403
|
||||
andString: @"Invalid start date."];
|
||||
{
|
||||
httpStatus = 403;
|
||||
jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"failure", @"status",
|
||||
@"Invalid start date.", @"message",
|
||||
nil];
|
||||
}
|
||||
|
||||
return response;
|
||||
return [self responseWithStatus: httpStatus
|
||||
andJSONRepresentation: jsonResponse];
|
||||
}
|
||||
|
||||
- (NSString *) _logoutRedirectURL
|
||||
|
|
Loading…
Reference in New Issue