2 Copyright (C) 2004-2005 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
22 #import <NGCards/NGVCard.h>
23 #import <NGCards/NSArray+NGCards.h>
25 #import <NGObjWeb/SoObject.h>
27 #import <Contacts/SOGoContactObject.h>
28 #import <Contacts/SOGoContactFolder.h>
31 #import "UIxContactEditor.h"
33 @implementation UIxContactEditor
37 if ((self = [super init]))
39 snapshot = [[NSMutableDictionary alloc] initWithCapacity: 16];
49 [preferredEmail release];
55 - (NSArray *) htmlMailFormatList
57 static NSArray *htmlMailFormatItems = nil;
59 if (!htmlMailFormatItems)
61 htmlMailFormatItems = [NSArray arrayWithObjects: @"FALSE", @"TRUE", nil];
62 [htmlMailFormatItems retain];
65 return htmlMailFormatItems;
68 - (NSString *) itemHtmlMailFormatText
70 return [self labelForKey:
71 [NSString stringWithFormat: @"htmlMailFormat_%@", item]];
74 - (void) setItem: (NSString *) newItem
84 /* load/store content format */
86 - (void)_fixupSnapshot {
87 // TODO: perform sanity checking, eg build CN on demand
88 NSString *cn, *gn, *sn;
90 cn = [snapshot objectForKey:@"cn"];
91 gn = [snapshot objectForKey:@"givenName"];
92 sn = [snapshot objectForKey:@"sn"];
94 if (![sn isNotNull] || [sn length] == 0)
96 if (![cn isNotNull] || [cn length] == 0)
103 // TODO: need a better name parser here
106 r = [cn rangeOfString:@" "];
108 ? [cn substringFromIndex:(r.location + r.length)]
111 [snapshot setObject:sn forKey:@"sn"];
113 if (sn == nil && gn == nil)
120 cn = [[gn stringByAppendingString:@" "] stringByAppendingString:sn];
121 [snapshot setObject:cn forKey:@"cn"];
126 - (NSString *)_completeURIForMethod:(NSString *)_method {
127 // TODO: this is a DUP of UIxAppointmentEditor
131 uri = [[[self context] request] uri];
133 /* first: identify query parameters */
134 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
136 uri = [uri substringToIndex:r.location];
138 /* next: append trailing slash */
139 if (![uri hasSuffix:@"/"])
140 uri = [uri stringByAppendingString:@"/"];
142 /* next: append method */
143 uri = [uri stringByAppendingString:_method];
145 /* next: append query parameters */
146 return [self completeHrefForMethod:uri];
151 - (BOOL) shouldTakeValuesFromRequest: (WORequest *) _rq
152 inContext: (WOContext*) _c
157 - (void) _setSnapshotValue: (NSString *) key
158 to: (NSString *) aValue
163 [snapshot setObject: aValue forKey: key];
166 - (NSMutableDictionary *) snapshot
171 - (NSString *) _simpleValueForType: (NSString *) aType
172 inArray: (NSArray *) anArray
177 elements = [anArray cardElementsWithAttribute: @"type"
179 if ([elements count] > 0)
180 value = [[elements objectAtIndex: 0] value: 0];
187 - (void) _setupEmailFields
190 NSString *workMail, *homeMail, *prefMail, *potential;
193 elements = [card childrenWithTag: @"email"];
194 max = [elements count];
195 workMail = [self _simpleValueForType: @"work"
197 homeMail = [self _simpleValueForType: @"home"
199 prefMail = [self _simpleValueForType: @"pref"
204 potential = [[elements objectAtIndex: 0] value: 0];
207 if (homeMail && homeMail == potential && max > 1)
208 workMail = [[elements objectAtIndex: 1] value: 0];
210 workMail = potential;
212 if (!homeMail && max > 1)
214 if (workMail && workMail == potential)
215 homeMail = [[elements objectAtIndex: 1] value: 0];
217 homeMail = potential;
222 if (prefMail == workMail)
223 preferredEmail = @"work";
224 else if (prefMail == homeMail)
225 preferredEmail = @"home";
229 [self _setSnapshotValue: @"workMail" to: workMail];
230 [self _setSnapshotValue: @"homeMail" to: homeMail];
232 [self _setSnapshotValue: @"mozillaUseHtmlMail"
233 to: [[card uniqueChildWithTag: @"x-mozilla-html"] value: 0]];
236 - (void) _setupOrgFields
238 NSArray *org, *orgServices;
246 [self _setSnapshotValue: @"workCompany" to: [org objectAtIndex: 0]];
249 aRange = NSMakeRange (1, max - 1);
250 orgServices = [org subarrayWithRange: aRange];
251 [self _setSnapshotValue: @"workService"
252 to: [orgServices componentsJoinedByString: @", "]];
257 - (NSString *) preferredEmail
259 return preferredEmail;
262 - (void) setPreferredEmail: (NSString *) aString
264 preferredEmail = aString;
267 - (void) _retrieveQueryParameter: (NSString *) queryKey
268 intoSnapshotValue: (NSString *) snapshotKey
270 NSString *queryValue;
272 queryValue = [self queryParameterForKey: queryKey];
273 if (queryValue && [queryValue length] > 0)
274 [self _setSnapshotValue: snapshotKey to: queryValue];
277 - (void) initSnapshot
279 NSArray *n, *elements;
280 CardElement *element;
289 [self _setSnapshotValue: @"sn" to: [n objectAtIndex: 0]];
291 [self _setSnapshotValue: @"givenName" to: [n objectAtIndex: 1]];
294 [self _setSnapshotValue: @"fn" to: [card fn]];
295 [self _setSnapshotValue: @"nickname" to: [card nickname]];
297 elements = [card childrenWithTag: @"tel"];
298 [self _setSnapshotValue: @"telephoneNumber"
299 to: [self _simpleValueForType: @"work" inArray: elements]];
300 [self _setSnapshotValue: @"homeTelephoneNumber"
301 to: [self _simpleValueForType: @"home" inArray: elements]];
302 [self _setSnapshotValue: @"mobile"
303 to: [self _simpleValueForType: @"cell" inArray: elements]];
304 [self _setSnapshotValue: @"facsimileTelephoneNumber"
305 to: [self _simpleValueForType: @"fax" inArray: elements]];
306 [self _setSnapshotValue: @"pager"
307 to: [self _simpleValueForType: @"pager" inArray: elements]];
309 [self _setupEmailFields];
311 [self _setSnapshotValue: @"screenName"
312 to: [[card uniqueChildWithTag: @"x-aim"] value: 0]];
314 elements = [card childrenWithTag: @"adr"
315 andAttribute: @"type" havingValue: @"work"];
316 if (elements && [elements count] > 0)
318 element = [elements objectAtIndex: 0];
319 [self _setSnapshotValue: @"workStreetAddress"
320 to: [element value: 2]];
321 [self _setSnapshotValue: @"workCity"
322 to: [element value: 3]];
323 [self _setSnapshotValue: @"workState"
324 to: [element value: 4]];
325 [self _setSnapshotValue: @"workPostalCode"
326 to: [element value: 5]];
327 [self _setSnapshotValue: @"workCountry"
328 to: [element value: 6]];
331 elements = [card childrenWithTag: @"adr"
332 andAttribute: @"type" havingValue: @"home"];
333 if (elements && [elements count] > 0)
335 element = [elements objectAtIndex: 0];
336 [self _setSnapshotValue: @"homeStreetAddress"
337 to: [element value: 2]];
338 [self _setSnapshotValue: @"homeCity"
339 to: [element value: 3]];
340 [self _setSnapshotValue: @"homeState"
341 to: [element value: 4]];
342 [self _setSnapshotValue: @"homePostalCode"
343 to: [element value: 5]];
344 [self _setSnapshotValue: @"homeCountry"
345 to: [element value: 6]];
348 elements = [card childrenWithTag: @"url"];
349 [self _setSnapshotValue: @"workURL"
350 to: [self _simpleValueForType: @"work" inArray: elements]];
351 [self _setSnapshotValue: @"homeURL"
352 to: [self _simpleValueForType: @"home" inArray: elements]];
353 [self _setSnapshotValue: @"calFBURL"
354 to: [[card uniqueChildWithTag: @"FBURL"] value: 0]];
356 [self _setSnapshotValue: @"title" to: [card title]];
357 [self _setupOrgFields];
359 [self _setSnapshotValue: @"bday" to: [card bday]];
360 [self _setSnapshotValue: @"tz" to: [card tz]];
361 [self _setSnapshotValue: @"note" to: [card note]];
363 [self _retrieveQueryParameter: @"contactEmail"
364 intoSnapshotValue: @"workMail"];
365 [self _retrieveQueryParameter: @"contactFN"
366 intoSnapshotValue: @"fn"];
369 - (id <WOActionResults>) defaultAction
371 card = [[self clientObject] vCard];
375 return [NSException exceptionWithHTTPStatus:404 /* Not Found */
376 reason:@"could not open contact"];
381 - (NSString *) viewActionName
383 /* this is overridden in the mail based contacts UI to redirect to tb.edit */
387 - (NSString *) editActionName
389 /* this is overridden in the mail based contacts UI to redirect to tb.edit */
393 - (CardElement *) _elementWithTag: (NSString *) tag
394 ofType: (NSString *) type
397 CardElement *element;
399 elements = [card childrenWithTag: tag
400 andAttribute: @"type" havingValue: type];
401 if ([elements count] > 0)
402 element = [elements objectAtIndex: 0];
405 element = [CardElement new];
406 [element autorelease];
407 [element setTag: tag];
408 [element addType: type];
409 [card addChild: element];
415 - (void) _savePhoneValues
419 phone = [self _elementWithTag: @"tel" ofType: @"work"];
420 [phone setValue: 0 to: [snapshot objectForKey: @"telephoneNumber"]];
421 phone = [self _elementWithTag: @"tel" ofType: @"home"];
422 [phone setValue: 0 to: [snapshot objectForKey: @"homeTelephoneNumber"]];
423 phone = [self _elementWithTag: @"tel" ofType: @"cell"];
424 [phone setValue: 0 to: [snapshot objectForKey: @"mobile"]];
425 phone = [self _elementWithTag: @"tel" ofType: @"fax"];
427 to: [snapshot objectForKey: @"facsimileTelephoneNumber"]];
428 phone = [self _elementWithTag: @"tel" ofType: @"pager"];
430 to: [snapshot objectForKey: @"pager"]];
435 CardElement *workMail, *homeMail;
437 workMail = [self _elementWithTag: @"email" ofType: @"work"];
438 [workMail setValue: 0 to: [snapshot objectForKey: @"workMail"]];
439 homeMail = [self _elementWithTag: @"email" ofType: @"home"];
440 [homeMail setValue: 0 to: [snapshot objectForKey: @"homeMail"]];
443 if ([preferredEmail isEqualToString: @"work"])
444 [card setPreferred: workMail];
446 [card setPreferred: homeMail];
449 [[card uniqueChildWithTag: @"x-mozilla-html"]
451 to: [snapshot objectForKey: @"mozillaUseHtmlMail"]];
454 - (void) _saveSnapshot
456 CardElement *element;
458 [card setNWithFamily: [snapshot objectForKey: @"sn"]
459 given: [snapshot objectForKey: @"givenName"]
463 [card setNickname: [snapshot objectForKey: @"nickname"]];
464 [card setFn: [snapshot objectForKey: @"fn"]];
465 [card setTitle: [snapshot objectForKey: @"title"]];
466 [card setBday: [snapshot objectForKey: @"bday"]];
467 [card setNote: [snapshot objectForKey: @"note"]];
468 [card setTz: [snapshot objectForKey: @"tz"]];
470 element = [self _elementWithTag: @"adr" ofType: @"home"];
471 [element setValue: 2 to: [snapshot objectForKey: @"homeStreetAddress"]];
472 [element setValue: 3 to: [snapshot objectForKey: @"homeCity"]];
473 [element setValue: 4 to: [snapshot objectForKey: @"homeState"]];
474 [element setValue: 5 to: [snapshot objectForKey: @"homePostalCode"]];
475 [element setValue: 6 to: [snapshot objectForKey: @"homeCountry"]];
477 element = [self _elementWithTag: @"adr" ofType: @"work"];
478 [element setValue: 2 to: [snapshot objectForKey: @"workStreetAddress"]];
479 [element setValue: 3 to: [snapshot objectForKey: @"workCity"]];
480 [element setValue: 4 to: [snapshot objectForKey: @"workState"]];
481 [element setValue: 5 to: [snapshot objectForKey: @"workPostalCode"]];
482 [element setValue: 6 to: [snapshot objectForKey: @"workCountry"]];
484 element = [CardElement simpleElementWithTag: @"fburl"
485 value: [snapshot objectForKey: @"calFBURL"]];
486 [card setUniqueChild: element];
488 [self _savePhoneValues];
490 [[card uniqueChildWithTag: @"x-aim"]
491 setValue: 0 to: [snapshot objectForKey: @"screenName"]];
494 - (id <WOActionResults>) saveAction
496 id <SOGoContactObject> contact;
498 NSString *jsRefreshMethod;
500 contact = [self clientObject];
501 card = [contact vCard];
504 [self _saveSnapshot];
507 if ([[[[self context] request] formValueForKey: @"nojs"] intValue])
508 result = [self redirectToLocation: [self applicationPath]];
512 = [NSString stringWithFormat: @"refreshContacts(\"%@\")",
513 [contact nameInContainer]];
514 result = [self jsCloseWithRefreshMethod: jsRefreshMethod];
518 result = [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
519 reason: @"method cannot be invoked on "
520 @"the specified object"];
527 NSString *email, *url;
529 card = [[self clientObject] vCard];
531 if ([preferredEmail isEqualToString: @"home"])
532 email = [snapshot objectForKey: @"homeMail"];
534 email = [snapshot objectForKey: @"workMail"];
537 url = [NSString stringWithFormat: @"Mail/compose?mailto=%@", email];
539 url = @"Mail/compose";
542 [self redirectToLocation: [self relativePathToUserFolderSubPath: url]];
546 // TODO: this is almost a DUP of UIxAppointmentEditor
548 This method creates a unique ID and redirects to the "edit" method on the
550 It is actually a folder method and should be defined on the folder.
552 Note: 'clientObject' is the SOGoAppointmentFolder!
553 Update: remember that there are group folders as well.
555 NSString *uri, *objectId, *nextMethod;
556 id <SOGoContactFolder> co;
558 co = [self clientObject];
559 if ([[co class] respondsToSelector: @selector (globallyUniqueObjectId)])
560 objectId = [[[self clientObject] class] globallyUniqueObjectId];
564 if ([objectId length] == 0)
565 return [NSException exceptionWithHTTPStatus:500 /* Internal Error */
566 reason:@"could not create a unique ID"];
568 nextMethod = [NSString stringWithFormat:@"../%@/%@",
569 objectId, [self editActionName]];
570 uri = [self _completeURIForMethod:nextMethod];
571 return [self redirectToLocation:uri];
574 @end /* UIxContactEditor */