division - Anais division
emailForUser - default EMail
cnForUser - default CN
+ role - role for submitted attendees
Sample:
<var:component className="AnaisAttendeeSelector"
iCalPerson *attendee;
NSString *emailForUser;
NSString *cnForUser;
+ NSString *role;
struct {
int withCN:1;
int reserved:31;
@end
#include <NGiCal/NGiCal.h>
+#include <SOGoLogic/AgenorUserManager.h>
#include <Scheduler/iCalPerson+UIx.h>
#include <NGObjWeb/WOContext.h>
+#include <NGObjWeb/WORequest.h>
#include "common.h"
@implementation AnaisAttendeeSelector
- (void)dealloc {
+ [self->role release];
[self->emailForUser release];
[self->cnForUser release];
[self->division release];
return self->division;
}
+- (void)setRole:(NSString *)_value {
+ ASSIGNCOPY(self->role, _value);
+}
+- (NSString *)role {
+ return self->role;
+}
+
- (void)setEmailForUser:(NSString *)_value {
ASSIGNCOPY(self->emailForUser, _value);
}
/* handling requests */
+- (NSArray *)getICalPersonsFromFormValues:(NSArray *)_values {
+ unsigned i, count;
+ NSMutableArray *result;
+
+ count = [_values count];
+ result = [NSMutableArray arrayWithCapacity:count];
+ for (i = 0; i < count; i++) {
+ NSString *pString, *email, *cn;
+ NSRange r;
+ iCalPerson *p;
+
+ pString = [_values objectAtIndex:i];
+ if ([pString length] == 0)
+ continue;
+
+ /* delimiter between email and cn */
+ r = [pString rangeOfString:@";"];
+ if (r.length > 0) {
+ /* sample: 'test.et.di.cete-lyon@equipement.gouv.fr;test' */
+ email = [pString substringToIndex:r.location];
+ cn = [pString substringFromIndex:r.location + r.length];
+ if ([cn length] == 0) cn = nil;
+ }
+ else {
+ email = pString;
+ cn = nil;
+ }
+ if (cn == nil) {
+ /* fallback */
+ AgenorUserManager *um = [AgenorUserManager sharedUserManager];
+ cn = [um getCNForUID:[um getUIDForEmail:email]];
+ }
+
+ p = [[iCalPerson alloc] init];
+ [p setEmail:[@"mailto:" stringByAppendingString:email]];
+ if ([cn isNotNull]) [p setCn:cn];
+
+ /* see RFC2445, sect. 4.2.16 for details */
+ [p setRole:[self role]];
+ [result addObject:p];
+ [p release];
+ }
+ return result;
+}
- (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
- [self logWithFormat:@"Note: will take values ..."];
- [super takeValuesFromRequest:_rq inContext:_ctx];
+ /* OK, we have a special form value processor */
+ NSArray *tmp;
+
+ [self debugWithFormat:@"Note: will take values ..."];
+
+ tmp = [self getICalPersonsFromFormValues:
+ [_rq formValuesForKey:[self checkboxId]]];
+ [self debugWithFormat:@" got %i attendees: %@", [tmp count], tmp];
+ [self setAttendees:tmp];
}
/* response generation */
@interface UIxAppointmentEditor : UIxComponent
{
+ NSString *iCalString;
id appointment;
- id participants;
id item;
+
+ /* individual values */
+ NSCalendarDate *startDate;
+ NSCalendarDate *endDate;
+ NSString *title;
+ NSString *location;
+ NSString *comment;
+ NSArray *participants;
+ NSArray *resources;
}
- (SOGoAppointment *)appointment;
- (NSString *)icalString; // TODO: this is in NGiCal
@end
-@interface NSObject(AppointmentHack)
-- (BOOL)isAppointment;
-@end
-
-@implementation NSObject(AppointmentHack)
-- (BOOL)isAppointment {
- return [self isKindOfClass:NSClassFromString(@"SOGoAppointmentObject")];
-}
-@end
-
@implementation UIxAppointmentEditor
- (void)dealloc {
- [self->appointment release];
[self->participants release];
+ [self->resources release];
+ [self->startDate release];
+ [self->endDate release];
+ [self->title release];
+ [self->location release];
+ [self->comment release];
+ [self->iCalString release];
+ [self->appointment release];
[self->item release];
[super dealloc];
}
return fmt;
}
+- (void)setAptStartDate:(NSCalendarDate *)_date {
+ ASSIGN(self->startDate, _date);
+}
- (NSCalendarDate *)aptStartDate {
- NSCalendarDate *date;
-
- date = [[[[self appointment] startDate] copy] autorelease];
- [date setTimeZone:[self viewTimeZone]];
- return date;
+ return self->startDate;
+}
+- (void)setAptEndDate:(NSCalendarDate *)_date {
+ ASSIGN(self->endDate, _date);
}
-
- (NSCalendarDate *)aptEndDate {
- NSCalendarDate *date;
-
- date = [[[[self appointment] endDate] copy] autorelease];
- [date setTimeZone:[self viewTimeZone]];
- return date;
+ return self->endDate;
+}
+
+- (void)setTitle:(NSString *)_value {
+ ASSIGNCOPY(self->title, _value);
+}
+- (NSString *)title {
+ return self->title;
+}
+- (void)setLocation:(NSString *)_value {
+ ASSIGNCOPY(self->location, _value);
+}
+- (NSString *)location {
+ return self->location;
+}
+- (void)setComment:(NSString *)_value {
+ ASSIGNCOPY(self->comment, _value);
+}
+- (NSString *)comment {
+ return self->comment;
}
-- (BOOL)isNewAppointment {
- /* that doesn't work! (TODO: explain why!) */
- // TODO: is this actually used?
- return ![[self clientObject] isAppointment];
+- (void)setParticipants:(NSArray *)_parts {
+ ASSIGN(self->participants, _parts);
+}
+- (NSArray *)participants {
+ return self->participants;
+}
+- (void)setResources:(NSArray *)_res {
+ ASSIGN(self->resources, _res);
+}
+- (NSArray *)resources {
+ return self->resources;
}
+/* iCal */
+
+- (void)setICalString:(NSString *)_s {
+ ASSIGNCOPY(self->iCalString, _s);
+}
- (NSString *)iCalString {
- // TODO: improve check for new appointment
- NSString *ical;
-
- ical = [[self clientObject] valueForKey:@"iCalString"];
- if ([ical length] == 0) /* a new appointment */
- ical = [self iCalStringTemplate];
-
- return ical;
+ return self->iCalString;
}
- (NSString *)iCalStringTemplate {
@"SEQUENCE:1\n"
@"END:VEVENT\n"
@"END:VCALENDAR";
- NSCalendarDate *startDate, *endDate;
+ NSCalendarDate *lStartDate, *lEndDate;
NSString *template;
- startDate = [self selectedDate];
- endDate = [startDate dateByAddingYears:0 months:0 days:0
+ lStartDate = [self selectedDate];
+ lEndDate = [lStartDate dateByAddingYears:0 months:0 days:0
hours:1 minutes:0 seconds:0];
template = [NSString stringWithFormat:iCalStringTemplate,
[[self clientObject] nameInContainer],
[[NSCalendarDate date] icalString],
- [startDate icalString],
- [endDate icalString]];
+ [lStartDate icalString],
+ [lEndDate icalString]];
return template;
}
-
-/* backend */
-
- (SOGoAppointment *)appointment {
- if (self->appointment == nil) {
- self->appointment = [[SOGoAppointment alloc]
- initWithICalString:[self iCalString]];
- }
return self->appointment;
}
return [result autorelease];
}
+- (BOOL)isWriteableClientObject {
+ return [[self clientObject]
+ respondsToSelector:@selector(saveContentString:)];
+}
+
+- (void)loadValuesFromAppointment:(SOGoAppointment *)_appointment {
+ self->startDate = [[_appointment startDate] copy];
+ self->endDate = [[_appointment endDate] copy];
+ [self->startDate setTimeZone:[self viewTimeZone]];
+ [self->endDate setTimeZone:[self viewTimeZone]];
+
+ self->title = [[_appointment summary] copy];
+ self->location = [[_appointment location] copy];
+ self->comment = [[_appointment comment] copy];
+
+ self->participants = [[_appointment participants] retain];
+ self->resources = [[_appointment resources] retain];
+}
+
/* actions */
+- (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c{
+ return YES;
+}
+
- (id)testAction {
/* for testing only */
WORequest *req;
return self;
}
+- (id)defaultAction {
+ NSString *ical;
+
+ /* load iCalendar file */
+
+ ical = [[self clientObject] valueForKey:@"iCalString"];
+ if ([ical length] == 0) /* a new appointment */
+ ical = [self iCalStringTemplate];
+
+ [self setICalString:ical];
+
+ /* parse */
+
+ self->appointment =
+ [[SOGoAppointment alloc] initWithICalString:[self iCalString]];
+
+ /* load values */
+
+ [self loadValuesFromAppointment:[self appointment]];
+
+ return self;
+}
+
- (id)saveAction {
- SOGoAppointment *apt;
- NSString *iCalString;
NSString *uri;
NSCalendarDate *sd, *ed;
- NSArray *attendees, *resources;
+ NSArray *attendees, *lResources;
WORequest *req;
- if (![[self clientObject] respondsToSelector:@selector(saveContentString:)]){
+ if (![self isWriteableClientObject]) {
/* return 400 == Bad Request */
return [NSException exceptionWithHTTPStatus:400
reason:@"method cannot be invoked on "
}
req = [[self context] request];
-
+
/* get iCalString from hidden input */
- iCalString = [req formValueForKey:@"ical"];
- if ([iCalString length] == 0) {
- // TODO: improve user experience ... (eg error panel like Zope)
- /* return 400 == Bad Request */
- return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
- reason:@"missing iCalendar form data in request"];
- }
+ [self setICalString:[req formValueForKey:@"ical"]];
+
+ self->appointment =
+ [[SOGoAppointment alloc] initWithICalString:[self iCalString]];
- apt = [[SOGoAppointment alloc] initWithICalString:iCalString];
- if (apt == nil) {
+ if (self->appointment == nil) {
return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
reason:@"invalid iCalendar form data in request"];
}
sd = [self _dateFromString:[req formValueForKey:@"startDate"]];
ed = [self _dateFromString:[req formValueForKey:@"endDate"]];
- [apt setStartDate:sd];
- [apt setEndDate:ed];
+ [self->appointment setStartDate:sd];
+ [self->appointment setEndDate:ed];
- [apt setSummary:[req formValueForKey:@"summary"]];
- [apt setLocation:[req formValueForKey:@"location"]];
+ [self->appointment setSummary:[req formValueForKey:@"summary"]];
+ [self->appointment setLocation:[req formValueForKey:@"location"]];
attendees = [self getICalPersonsFromFormValues:
[req formValuesForKey:@"participants"]
treatAsResource:NO];
- resources = [self getICalPersonsFromFormValues:
+ lResources = [self getICalPersonsFromFormValues:
[req formValuesForKey:@"resources"]
treatAsResource:YES];
- if ([resources count] > 0) {
+ if ([lResources count] > 0) {
attendees = ([attendees count] > 0)
- ? [attendees arrayByAddingObjectsFromArray:resources]
- : resources;
+ ? [attendees arrayByAddingObjectsFromArray:lResources]
+ : lResources;
}
- [apt setAttendees:attendees];
+ [self->appointment setAttendees:attendees];
- [apt setOrganizer:[self getOrganizer]];
+ [self->appointment setOrganizer:[self getOrganizer]];
/* receive current representation for save operation */
- iCalString = [apt iCalString];
- [apt release]; apt = nil;
-
{
NSException *ex;
+ NSString *content;
+
+ content = [self->appointment iCalString];
+ if (content == nil) {
+ return [NSException exceptionWithHTTPStatus:500 /* Internal Error */
+ reason:@"failed to create iCal content for apt"];
+ }
- ex = [[self clientObject] saveContentString:iCalString];
+ ex = [[self clientObject] saveContentString:content];
if (ex) return ex;
// TODO: add some error handling in form! (eg like in Zope)
}