mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-03-13 02:41:24 +00:00
See ChangeLog.
Monotone-Parent: ed8a21d5648d8bc72dc33ad272987d8963be1285 Monotone-Revision: 12a15fd8afcf3963e3ec84c6a630972534773465 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-16T01:35:06 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
14
ChangeLog
14
ChangeLog
@@ -1,5 +1,19 @@
|
||||
2011-04-15 Francis Lachapelle <flachapelle@inverse.ca>
|
||||
|
||||
* SoObjects/Appointments/iCalEvent+SOGo.m (-firstOccurenceRange):
|
||||
we now compute the end date by looking at the occurrence
|
||||
interval. This way, we support events with an end date or a duration.
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
||||
(-_flattenCycleRecord:forRange:intoArray:): also compute the end
|
||||
date by looking at the occurrence interval.
|
||||
(-importCalendar:): added a duration to events with no end date nor duration.
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentObject.m
|
||||
(-_adjustEventsInRequest:): new method to verify the vCalendar for
|
||||
any inconsistency or missing attributes. Currently, it only adds a
|
||||
duration if no end date nor duration is found.
|
||||
|
||||
* UI/WebServerResources/ckeditor/config.js: Changed the default
|
||||
enter mode to use BR instead of P. This matches the behavior of Thunderbird.
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#import <SOGo/WOResponse+SOGo.h>
|
||||
|
||||
#import "iCalRepeatableEntityObject+SOGo.h"
|
||||
#import "iCalEvent+SOGo.h"
|
||||
#import "iCalPerson+SOGo.h"
|
||||
#import "SOGoAppointmentObject.h"
|
||||
#import "SOGoAppointmentFolders.h"
|
||||
@@ -849,9 +850,9 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||
NSArray *rules, *exRules, *exDates, *ranges;
|
||||
NSArray *elements, *components;
|
||||
NSString *content;
|
||||
iCalRepeatableEntityObject *component;
|
||||
id firstStartDate, firstEndDate;
|
||||
NSCalendarDate *checkStartDate, *checkEndDate;
|
||||
iCalEvent *component;
|
||||
iCalTimeZone *eventTimeZone;
|
||||
unsigned count, max, offset;
|
||||
|
||||
@@ -890,52 +891,54 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||
// Retrieve the range of the first/master event
|
||||
component = [components objectAtIndex: 0];
|
||||
firstStartDate = [component uniqueChildWithTag: @"dtstart"];
|
||||
firstEndDate = [component uniqueChildWithTag: @"dtend"];
|
||||
eventTimeZone = [(iCalDateTime*)firstStartDate timeZone];
|
||||
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate]
|
||||
endDate: [[[firstEndDate values] lastObject] asCalendarDate]];
|
||||
|
||||
if (eventTimeZone)
|
||||
{
|
||||
// Adjust the range to check with respect to the event timezone (extracted from the start date)
|
||||
checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]];
|
||||
checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]];
|
||||
recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate
|
||||
endDate: checkEndDate];
|
||||
|
||||
// Adjust the exception dates
|
||||
exDates = [eventTimeZone computedDatesForStrings: exDates];
|
||||
|
||||
// Adjust the recurrence rules "until" dates
|
||||
rules = [component recurrenceRulesWithTimeZone: eventTimeZone];
|
||||
exRules = [component exceptionRulesWithTimeZone: eventTimeZone];
|
||||
}
|
||||
else
|
||||
{
|
||||
recurrenceRange = theRange;
|
||||
if ([[theRecord objectForKey: @"c_isallday"] boolValue])
|
||||
{
|
||||
// The event lasts all-day and has no timezone (floating); we convert the range of the first event
|
||||
// to the user's timezone
|
||||
offset = [timeZone secondsFromGMTForDate: [firstRange startDate]];
|
||||
firstStartDate = (NSCalendarDate*)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
|
||||
seconds:-offset];
|
||||
firstEndDate = (NSCalendarDate*)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
|
||||
seconds:-offset];
|
||||
[firstStartDate setTimeZone: timeZone];
|
||||
[firstEndDate setTimeZone: timeZone];
|
||||
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate
|
||||
endDate: firstEndDate];
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the occurrences for the given range
|
||||
firstStartDate = [[[firstStartDate values] lastObject] asCalendarDate];
|
||||
firstEndDate = [firstStartDate addTimeInterval: [component occurenceInterval]];
|
||||
|
||||
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate
|
||||
endDate: firstEndDate];
|
||||
|
||||
eventTimeZone = [(iCalDateTime*)firstStartDate timeZone];
|
||||
if (eventTimeZone)
|
||||
{
|
||||
// Adjust the range to check with respect to the event timezone (extracted from the start date)
|
||||
checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]];
|
||||
checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]];
|
||||
recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate
|
||||
endDate: checkEndDate];
|
||||
|
||||
// Adjust the exception dates
|
||||
exDates = [eventTimeZone computedDatesForStrings: exDates];
|
||||
|
||||
// Adjust the recurrence rules "until" dates
|
||||
rules = [component recurrenceRulesWithTimeZone: eventTimeZone];
|
||||
exRules = [component exceptionRulesWithTimeZone: eventTimeZone];
|
||||
}
|
||||
else
|
||||
{
|
||||
recurrenceRange = theRange;
|
||||
if ([[theRecord objectForKey: @"c_isallday"] boolValue])
|
||||
{
|
||||
// The event lasts all-day and has no timezone (floating); we convert the range of the first event
|
||||
// to the user's timezone
|
||||
offset = [timeZone secondsFromGMTForDate: [firstRange startDate]];
|
||||
firstStartDate = (NSCalendarDate*)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
|
||||
seconds:-offset];
|
||||
firstEndDate = (NSCalendarDate*)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
|
||||
seconds:-offset];
|
||||
[firstStartDate setTimeZone: timeZone];
|
||||
[firstEndDate setTimeZone: timeZone];
|
||||
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate
|
||||
endDate: firstEndDate];
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the occurrences for the given range
|
||||
records = [NSMutableArray array];
|
||||
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange
|
||||
firstInstanceCalendarDateRange: firstRange
|
||||
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange
|
||||
firstInstanceCalendarDateRange: firstRange
|
||||
recurrenceRules: rules
|
||||
exceptionRules: exRules
|
||||
exceptionDates: exDates];
|
||||
exceptionRules: exRules
|
||||
exceptionDates: exDates];
|
||||
max = [ranges count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
@@ -947,15 +950,15 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||
if (fixedRow)
|
||||
[records addObject: fixedRow];
|
||||
}
|
||||
|
||||
|
||||
[self _appendCycleExceptionsFromRow: row
|
||||
firstInstanceCalendarDateRange: firstRange
|
||||
forRange: theRange
|
||||
toArray: records];
|
||||
|
||||
|
||||
[theRecords addObjectsFromArray: records];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
[self errorWithFormat:@"cyclic record doesn't have content -> %@", theRecord];
|
||||
@@ -2607,6 +2610,11 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||
return ([object saveContentString: content] == nil);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import all components of a vCalendar.
|
||||
* @param calendar the calendar to import
|
||||
* @return the number of components imported
|
||||
*/
|
||||
- (int) importCalendar: (iCalCalendar *) calendar
|
||||
{
|
||||
NSArray *vtimezones;
|
||||
@@ -2616,6 +2624,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||
iCalEntityObject *element;
|
||||
iCalDateTime *startDate;
|
||||
iCalTimeZone *timezone;
|
||||
iCalEvent *event;
|
||||
|
||||
int imported, count, i;
|
||||
|
||||
@@ -2651,6 +2660,20 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||
{
|
||||
timezone = [startDate timeZone];
|
||||
tz = [timezones valueForKey: [timezone tzId]];
|
||||
if ([element isKindOfClass: [iCalEvent class]])
|
||||
{
|
||||
event = (iCalEvent *)element;
|
||||
if (![event hasEndDate] && ![event hasDuration])
|
||||
{
|
||||
// No end date, no duration
|
||||
if ([event isAllDay])
|
||||
[event setDuration: @"P1D"];
|
||||
else
|
||||
[event setDuration: @"PT1H"];
|
||||
|
||||
[self errorWithFormat: @"Importing event with no end date; setting duration to %@", [event duration]];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ([self importComponent: element
|
||||
timezone: (tz == nil? @"" : tz)])
|
||||
|
||||
@@ -1336,6 +1336,44 @@
|
||||
[rq setContent: [[calendar versitString] dataUsingEncoding: [rq contentEncoding]]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify vCalendar for any inconsistency or missing attributes.
|
||||
* Currently only check if the events have an end date or a duration.
|
||||
* @param rq the HTTP PUT request
|
||||
*/
|
||||
- (void) _adjustEventsInRequest: (WORequest *) rq
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSArray *allEvents;
|
||||
iCalEvent *event;
|
||||
NSUInteger i;
|
||||
BOOL modified;
|
||||
|
||||
calendar = [iCalCalendar parseSingleFromSource: [rq contentAsString]];
|
||||
allEvents = [calendar events];
|
||||
modified = NO;
|
||||
|
||||
for (i = 0; i < [allEvents count]; i++)
|
||||
{
|
||||
event = [allEvents objectAtIndex: i];
|
||||
|
||||
if (![event hasEndDate] && ![event hasDuration])
|
||||
{
|
||||
// No end date, no duration
|
||||
if ([event isAllDay])
|
||||
[event setDuration: @"P1D"];
|
||||
else
|
||||
[event setDuration: @"PT1H"];
|
||||
|
||||
modified = YES;
|
||||
[self errorWithFormat: @"Invalid event: no end date; setting duration to %@", [event duration]];
|
||||
}
|
||||
}
|
||||
|
||||
if (modified)
|
||||
[rq setContent: [[calendar versitString] dataUsingEncoding: [rq contentEncoding]]];
|
||||
}
|
||||
|
||||
- (void) _decomposeGroupsInRequest: (WORequest *) rq
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
@@ -1471,6 +1509,8 @@
|
||||
{
|
||||
[self _adjustTransparencyInRequest: rq];
|
||||
}
|
||||
|
||||
[self _adjustEventsInRequest: rq];
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
@interface iCalEvent (SOGoExtensions)
|
||||
|
||||
- (BOOL) isStillRelevant;
|
||||
- (unsigned int) occurenceInterval;
|
||||
- (NSMutableDictionary *) quickRecord;
|
||||
- (void) updateRecurrenceRulesUntilDate: (NSCalendarDate *) previousEndDate;
|
||||
|
||||
|
||||
@@ -272,14 +272,22 @@
|
||||
*/
|
||||
- (NGCalendarDateRange *) firstOccurenceRange
|
||||
{
|
||||
iCalDateTime *firstStartDate, *firstEndDate;
|
||||
iCalDateTime *firstStartDate;
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *firstRange;
|
||||
|
||||
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
|
||||
firstEndDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtend"];
|
||||
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate]
|
||||
endDate: [[[firstEndDate values] lastObject] asCalendarDate]];
|
||||
firstRange = nil;
|
||||
|
||||
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
|
||||
if ([[firstStartDate values] count] > 0)
|
||||
{
|
||||
start = [[[firstStartDate values] lastObject] asCalendarDate];
|
||||
end = [start addTimeInterval: [self occurenceInterval]];
|
||||
|
||||
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: start
|
||||
endDate: end];
|
||||
}
|
||||
|
||||
return firstRange;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user