2 Copyright (C) 2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include <SOGoUI/UIxComponent.h>
29 @class SOGoAppointment;
31 @interface UIxAppointmentEditor : UIxComponent
37 /* individual values */
38 NSCalendarDate *startDate;
39 NSCalendarDate *endDate;
43 NSArray *participants; /* array of iCalPerson's */
44 NSArray *resources; /* array of iCalPerson's */
47 - (NSString *)iCalStringTemplate;
48 - (NSString *)iCalString;
50 - (NSString *)_completeURIForMethod:(NSString *)_method;
52 - (iCalPerson *)getOrganizer;
53 - (NSArray *)getICalPersonsFromFormValues:(NSArray *)_values
54 treatAsResource:(BOOL)_isResource;
59 #include <SOGoUI/SOGoDateFormatter.h>
60 #include <SOGoLogic/SOGoAppointment.h>
61 #include <Appointments/SOGoAppointmentFolder.h>
62 #include <Appointments/SOGoAppointmentObject.h>
63 #include <NGiCal/NGiCal.h>
64 #include <SOGoLogic/AgenorUserManager.h>
65 #include "iCalPerson+UIx.h"
66 #include "UIxComponent+Agenor.h"
68 @interface NSDate(UsedPrivates)
69 - (NSString *)icalString; // TODO: this is in NGiCal
72 @implementation UIxAppointmentEditor
75 [self->errorText release];
76 [self->participants release];
77 [self->resources release];
78 [self->startDate release];
79 [self->endDate release];
80 [self->title release];
81 [self->location release];
82 [self->comment release];
83 [self->iCalString release];
90 - (void)setItem:(id)_item {
91 ASSIGN(self->item, _item);
97 - (void)setErrorText:(NSString *)_txt {
98 ASSIGNCOPY(self->errorText, _txt);
100 - (NSString *)errorText {
101 return self->errorText;
103 - (BOOL)hasErrorText {
104 return [self->errorText length] > 0 ? YES : NO;
107 - (NSFormatter *)titleDateFormatter {
108 SOGoDateFormatter *fmt;
110 fmt = [[[SOGoDateFormatter alloc] initWithLocale:[self locale]] autorelease];
111 [fmt setFullWeekdayNameAndDetails];
115 - (void)setAptStartDate:(NSCalendarDate *)_date {
116 ASSIGN(self->startDate, _date);
118 - (NSCalendarDate *)aptStartDate {
119 return self->startDate;
121 - (void)setAptEndDate:(NSCalendarDate *)_date {
122 ASSIGN(self->endDate, _date);
124 - (NSCalendarDate *)aptEndDate {
125 return self->endDate;
128 - (void)setTitle:(NSString *)_value {
129 ASSIGNCOPY(self->title, _value);
131 - (NSString *)title {
134 - (void)setLocation:(NSString *)_value {
135 ASSIGNCOPY(self->location, _value);
137 - (NSString *)location {
138 return self->location;
140 - (void)setComment:(NSString *)_value {
141 ASSIGNCOPY(self->comment, _value);
143 - (NSString *)comment {
144 return self->comment;
147 - (void)setParticipants:(NSArray *)_parts {
148 ASSIGN(self->participants, _parts);
150 - (NSArray *)participants {
151 return self->participants;
153 - (void)setResources:(NSArray *)_res {
154 ASSIGN(self->resources, _res);
156 - (NSArray *)resources {
157 return self->resources;
162 - (void)setICalString:(NSString *)_s {
163 ASSIGNCOPY(self->iCalString, _s);
165 - (NSString *)iCalString {
166 return self->iCalString;
169 - (NSString *)iCalStringTemplate {
170 static NSString *iCalStringTemplate = \
171 @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org SOGo 0.9\n"
176 @"STATUS:CONFIRMED\n"
184 NSCalendarDate *lStartDate, *lEndDate;
187 lStartDate = [self selectedDate];
188 lEndDate = [lStartDate dateByAddingYears:0 months:0 days:0
189 hours:1 minutes:0 seconds:0];
191 template = [NSString stringWithFormat:iCalStringTemplate,
192 [[self clientObject] nameInContainer],
193 [[NSCalendarDate date] icalString],
194 [lStartDate icalString],
195 [lEndDate icalString]];
201 - (NSString *)_completeURIForMethod:(NSString *)_method {
205 uri = [[[self context] request] uri];
207 /* first: identify query parameters */
208 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
210 uri = [uri substringToIndex:r.location];
212 /* next: append trailing slash */
213 if (![uri hasSuffix:@"/"])
214 uri = [uri stringByAppendingString:@"/"];
216 /* next: append method */
217 uri = [uri stringByAppendingString:_method];
219 /* next: append query parameters */
220 return [self completeHrefForMethod:uri];
227 This method creates a unique ID and redirects to the "edit" method on the
229 It is actually a folder method and should be defined on the folder.
231 Note: 'clientObject' is the SOGoAppointmentFolder!
232 Update: remember that there are group folders as well.
234 NSString *uri, *objectId, *nextMethod;
236 objectId = [NSClassFromString(@"SOGoAppointmentFolder")
237 globallyUniqueObjectId];
238 if ([objectId length] == 0) {
239 return [NSException exceptionWithHTTPStatus:500 /* Internal Error */
240 reason:@"could not create a unique ID"];
243 nextMethod = [NSString stringWithFormat:@"../%@/edit", objectId];
244 uri = [self _completeURIForMethod:nextMethod];
245 return [self redirectToLocation:uri];
250 /* returned dates are in GMT */
251 - (NSCalendarDate *)_dateFromString:(NSString *)_str {
252 NSCalendarDate *date;
254 date = [NSCalendarDate dateWithString:_str
255 calendarFormat:@"%Y-%m-%d %H:%M %Z"];
256 [date setTimeZone:[self backendTimeZone]];
260 - (iCalPerson *)getOrganizer {
264 emailProp = [@"mailto:" stringByAppendingString:[self emailForUser]];
265 p = [[[iCalPerson alloc] init] autorelease];
266 [p setEmail:emailProp];
267 [p setCn:[self cnForUser]];
271 - (NSArray *)getICalPersonsFromFormValues:(NSArray *)_values
272 treatAsResource:(BOOL)_isResource
275 NSMutableArray *result;
277 count = [_values count];
278 result = [[NSMutableArray alloc] initWithCapacity:count];
279 for (i = 0; i < count; i++) {
280 NSString *pString, *email, *cn;
284 pString = [_values objectAtIndex:i];
285 if ([pString length] == 0)
288 /* delimiter between email and cn */
289 r = [pString rangeOfString:@";"];
291 email = [pString substringToIndex:r.location];
292 cn = (r.location + 1 < [pString length])
293 ? [pString substringFromIndex:r.location + 1]
302 AgenorUserManager *um = [AgenorUserManager sharedUserManager];
303 cn = [um getCNForUID:[um getUIDForEmail:email]];
306 p = [[iCalPerson alloc] init];
307 [p setEmail:[@"mailto:" stringByAppendingString:email]];
308 if ([cn isNotNull]) [p setCn:cn];
310 /* see RFC2445, sect. 4.2.16 for details */
311 [p setRole:_isResource ? @"NON-PARTICIPANT" : @"REQ-PARTICIPANT"];
312 [result addObject:p];
315 return [result autorelease];
318 - (BOOL)isWriteableClientObject {
319 return [[self clientObject]
320 respondsToSelector:@selector(saveContentString:)];
323 - (void)loadValuesFromAppointment:(SOGoAppointment *)_appointment {
324 self->startDate = [[_appointment startDate] copy];
325 self->endDate = [[_appointment endDate] copy];
326 [self->startDate setTimeZone:[self viewTimeZone]];
327 [self->endDate setTimeZone:[self viewTimeZone]];
329 self->title = [[_appointment summary] copy];
330 self->location = [[_appointment location] copy];
331 self->comment = [[_appointment comment] copy];
333 self->participants = [[_appointment participants] retain];
334 self->resources = [[_appointment resources] retain];
337 - (void)saveValuesIntoAppointment:(SOGoAppointment *)_appointment {
338 /* merge in form values */
339 NSArray *attendees, *lResources;
341 [_appointment setStartDate:[self aptStartDate]];
342 [_appointment setEndDate:[self aptEndDate]];
344 [_appointment setSummary:[self title]];
345 [_appointment setLocation:[self location]];
347 attendees = [self participants];
348 lResources = [self resources];
349 if ([lResources count] > 0) {
350 attendees = ([attendees count] > 0)
351 ? [attendees arrayByAddingObjectsFromArray:lResources]
354 [_appointment setAttendees:attendees];
356 [_appointment setOrganizer:[self getOrganizer]];
359 - (void)loadValuesFromICalString:(NSString *)_ical {
360 SOGoAppointment *apt;
362 apt = [[SOGoAppointment alloc] initWithICalString:_ical];
363 [self loadValuesFromAppointment:apt];
369 - (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c{
374 /* for testing only */
377 NSLog(@"%s BEEN HERE!", __PRETTY_FUNCTION__);
379 req = [[self context] request];
380 NSLog(@"%@", [req formValues]);
384 - (id)defaultAction {
387 /* load iCalendar file */
389 ical = [[self clientObject] valueForKey:@"iCalString"];
390 if ([ical length] == 0) /* a new appointment */
391 ical = [self iCalStringTemplate];
393 [self setICalString:ical];
394 [self loadValuesFromICalString:ical];
400 SOGoAppointment *apt;
404 if (![self isWriteableClientObject]) {
405 /* return 400 == Bad Request */
406 return [NSException exceptionWithHTTPStatus:400
407 reason:@"method cannot be invoked on "
408 @"the specified object"];
411 apt = [[SOGoAppointment alloc] initWithICalString:[self iCalString]];
413 [self setErrorText:@"Invalid iCalendar data ..."]; // localize
417 [self saveValuesIntoAppointment:apt];
418 content = [apt iCalString];
419 [apt release]; apt = nil;
421 if (content == nil) {
422 [self setErrorText:@"Could not create iCalendar data ..."]; // localize
426 ex = [[self clientObject] saveContentString:content];
428 [self setErrorText:[ex reason]];
432 return [self redirectToLocation:[self _completeURIForMethod:@".."]];
435 @end /* UIxAppointmentEditor */