]> err.no Git - scalable-opengroupware.org/blob - SOGo/UI/SOGoUI/UIxComponent.m
refactored some helper methods
[scalable-opengroupware.org] / SOGo / UI / SOGoUI / UIxComponent.m
1 /*
2   Copyright (C) 2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "UIxComponent.h"
24 #include "common.h"
25 #include <NGObjWeb/SoHTTPAuthenticator.h>
26
27 @interface UIxComponent (PrivateAPI)
28 - (void)_parseQueryString:(NSString *)_s;
29 @end
30
31 @implementation UIxComponent
32
33 static NSTimeZone *MET = nil;
34 static NSTimeZone *GMT = nil;
35
36 static NSMutableArray *dayLabelKeys       = nil;
37 static NSMutableArray *abbrDayLabelKeys   = nil;
38 static NSMutableArray *monthLabelKeys     = nil;
39 static NSMutableArray *abbrMonthLabelKeys = nil;
40
41 static BOOL uixDebugEnabled = NO;
42
43 + (void)initialize {
44   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
45     
46   uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"];
47
48   if (MET == nil) {
49     MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
50     GMT = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
51   }
52   if (dayLabelKeys == nil) {
53     dayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
54     [dayLabelKeys addObject:@"Sunday"];
55     [dayLabelKeys addObject:@"Monday"];
56     [dayLabelKeys addObject:@"Tuesday"];
57     [dayLabelKeys addObject:@"Wednesday"];
58     [dayLabelKeys addObject:@"Thursday"];
59     [dayLabelKeys addObject:@"Friday"];
60     [dayLabelKeys addObject:@"Saturday"];
61
62     abbrDayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7];
63     [abbrDayLabelKeys addObject:@"a2_Sunday"];
64     [abbrDayLabelKeys addObject:@"a2_Monday"];
65     [abbrDayLabelKeys addObject:@"a2_Tuesday"];
66     [abbrDayLabelKeys addObject:@"a2_Wednesday"];
67     [abbrDayLabelKeys addObject:@"a2_Thursday"];
68     [abbrDayLabelKeys addObject:@"a2_Friday"];
69     [abbrDayLabelKeys addObject:@"a2_Saturday"];
70
71     monthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
72     [monthLabelKeys addObject:@"January"];
73     [monthLabelKeys addObject:@"February"];
74     [monthLabelKeys addObject:@"March"];
75     [monthLabelKeys addObject:@"April"];
76     [monthLabelKeys addObject:@"May"];
77     [monthLabelKeys addObject:@"June"];
78     [monthLabelKeys addObject:@"July"];
79     [monthLabelKeys addObject:@"August"];
80     [monthLabelKeys addObject:@"September"];
81     [monthLabelKeys addObject:@"October"];
82     [monthLabelKeys addObject:@"November"];
83     [monthLabelKeys addObject:@"December"];
84
85     abbrMonthLabelKeys = [[NSMutableArray alloc] initWithCapacity:12];
86     [abbrMonthLabelKeys addObject:@"a3_January"];
87     [abbrMonthLabelKeys addObject:@"a3_February"];
88     [abbrMonthLabelKeys addObject:@"a3_March"];
89     [abbrMonthLabelKeys addObject:@"a3_April"];
90     [abbrMonthLabelKeys addObject:@"a3_May"];
91     [abbrMonthLabelKeys addObject:@"a3_June"];
92     [abbrMonthLabelKeys addObject:@"a3_July"];
93     [abbrMonthLabelKeys addObject:@"a3_August"];
94     [abbrMonthLabelKeys addObject:@"a3_September"];
95     [abbrMonthLabelKeys addObject:@"a3_October"];
96     [abbrMonthLabelKeys addObject:@"a3_November"];
97     [abbrMonthLabelKeys addObject:@"a3_December"];
98   }
99 }
100
101 - (id)init {
102   if ((self = [super init])) {
103     self->queryParameters = [[NSMutableDictionary alloc] initWithCapacity:8];
104   }
105   return self;
106 }
107
108 - (void)dealloc {
109   [self->queryParameters release];
110   [super dealloc];
111 }
112
113 /* notifications */
114
115 - (void)awake {
116   WORequest *req;
117   NSString  *uri;
118   NSRange   r;
119
120   [super awake];
121
122   req = [[self context] request];
123   uri = [req uri];
124   r   = [uri rangeOfString:@"?"];
125   if (r.length > 0) {
126     NSString *qs;
127     
128     qs = [uri substringFromIndex:(r.location + r.length)];
129     [self->queryParameters removeAllObjects];
130     [self _parseQueryString:qs];
131   }    
132 }
133
134 /* query parameters */
135
136 - (void)_parseQueryString:(NSString *)_s {
137   NSEnumerator *e;
138   NSString *part;
139     
140   e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
141   while ((part = [e nextObject])) {
142     NSRange  r;
143     NSString *key, *value;
144         
145     r = [part rangeOfString:@"="];
146     if (r.length == 0) {
147       /* missing value of query parameter */
148       key   = [part stringByUnescapingURL];
149       value = @"1";
150     }
151     else {
152       key   = [[part substringToIndex:r.location] stringByUnescapingURL];
153       value = [[part substringFromIndex:(r.location + r.length)] 
154                 stringByUnescapingURL];
155     }
156     [self->queryParameters setObject:value forKey:key];
157   }
158 }
159
160 - (NSString *)queryParameterForKey:(NSString *)_key {
161   return [self->queryParameters objectForKey:_key];
162 }
163
164 - (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
165   if(_key == nil)
166     return;
167
168   if(_param != nil)
169     [self->queryParameters setObject:_param forKey:_key];
170   else
171     [self->queryParameters removeObjectForKey:_key];
172 }
173
174 - (NSDictionary *)queryParameters {
175   return self->queryParameters;
176 }
177
178 - (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date{
179   NSMutableDictionary *qp;
180     
181   qp = [[self queryParameters] mutableCopy];
182   [self setSelectedDateQueryParameter:_date inDictionary:qp];
183   return [qp autorelease];
184 }
185
186 - (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
187                          inDictionary:(NSMutableDictionary *)_qp;
188 {
189   if(_newDate != nil)
190     [_qp setObject:[self dateStringForDate:_newDate] forKey:@"day"];
191   else
192     [_qp removeObjectForKey:@"day"];
193 }
194
195 - (NSString *)completeHrefForMethod:(NSString *)_method {
196   NSDictionary *qp;
197   NSString *qs;
198     
199   qp = [self queryParameters];
200   if([qp count] == 0)
201     return _method;
202     
203   qs = [[self context] queryStringFromDictionary:qp];
204   return [_method stringByAppendingFormat:@"?%@", qs];
205 }
206
207 - (NSString *)ownMethodName {
208   NSString *uri;
209   NSRange  r;
210     
211   uri = [[[self context] request] uri];
212     
213   /* first: cut off query parameters */
214     
215   r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
216   if (r.length > 0)
217     uri = [uri substringToIndex:r.location];
218     
219   /* next: strip trailing slash */
220     
221   if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
222   r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
223     
224   /* then: cut of last path component */
225     
226   if (r.length == 0) // no slash? are we at root?
227     return @"/";
228     
229   return [uri substringFromIndex:(r.location + 1)];
230 }
231
232 - (NSString *)userFolderPath {
233   WOContext *ctx;
234   NSArray   *traversalObjects;
235   NSString  *url;
236   
237   ctx = [self context];
238   traversalObjects = [ctx objectTraversalStack];
239   url = [[[traversalObjects objectAtIndex:1]
240                             baseURLInContext:ctx]
241                             stringByAppendingString:@"/"];
242   return [[NSURL URLWithString:url] path];
243 }
244
245 - (NSString *)ownPath {
246   NSString *url;
247   
248   url = [[self clientObject] baseURLInContext:[self context]];
249   return [[NSURL URLWithString:url] path];
250 }
251
252 - (NSString *)relativePathToUserFolderSubPath:(NSString *)_sub {
253   NSString *dst, *rel;
254
255   dst = [[self userFolderPath] stringByAppendingPathComponent:_sub];
256   rel = [dst urlPathRelativeToPath:[self ownPath]];
257   return rel;
258 }
259   
260 /* date */
261
262 - (NSTimeZone *)viewTimeZone {
263   // Note: also in the folder, should be based on a cookie?
264   return MET;
265 }
266
267 - (NSTimeZone *)backendTimeZone {
268   return GMT;
269 }
270
271 - (NSCalendarDate *)selectedDate {
272   NSString       *s;
273   NSCalendarDate *cdate;
274
275   s = [self queryParameterForKey:@"day"];
276   cdate = ([s length] > 0)
277     ? [self dateForDateString:s]
278     : [NSCalendarDate date];
279   [cdate setTimeZone:[self viewTimeZone]];
280   s = [self queryParameterForKey:@"hm"];
281   if([s length] == 4) {
282     unsigned hour, minute;
283       
284     hour = [[s substringToIndex:2] unsignedIntValue];
285     minute = [[s substringFromIndex:2] unsignedIntValue];
286     cdate = [cdate hour:hour minute:minute];
287   }
288   else {
289     cdate = [cdate hour:12 minute:0];
290   }
291   return cdate;
292 }
293
294 - (NSString *)dateStringForDate:(NSCalendarDate *)_date {
295   [_date setTimeZone:[self viewTimeZone]];
296   return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
297 }
298
299 - (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
300   return [NSCalendarDate dateWithString:_dateString 
301                          calendarFormat:@"%Y%m%d"];
302 }
303
304
305 /* SoUser */
306
307 - (SoUser *)user {
308   WOContext *ctx;
309   
310   ctx = [self context];
311   return [[[self clientObject] authenticatorInContext:ctx] userInContext:ctx];
312 }
313
314 - (NSString *)shortUserNameForDisplay {
315   // TODO: better use a SoUser formatter?
316   NSString *s;
317   NSRange  r;
318
319 #warning !! USE USER MANAGER INSTEAD!
320
321   s = [[self user] login];
322   if ([s length] < 10)
323     return s;
324     
325   // TODO: algorithm might be inappropriate, depends on the actual UID
326     
327   r = [s rangeOfString:@"."];
328   if (r.length == 0)
329     return s;
330     
331   return [s substringToIndex:r.location];
332 }
333
334 /* labels */
335
336 - (NSString *)labelForKey:(NSString *)_str {
337   WOResourceManager *rm;
338   NSArray           *languages;
339   WOContext         *ctx;
340   NSString          *label;
341   NSString          *lKey, *lTable, *lVal;
342   NSRange r;
343
344   if ([_str length] == 0) {
345     return nil;
346   }
347     
348   /* lookup languages */
349     
350   ctx = [self context];
351   languages = [ctx hasSession]
352     ? [[ctx session] languages]
353     : [[ctx request] browserLanguages];
354     
355   /* find resource manager */
356     
357   if ((rm = [self resourceManager]) == nil)
358     rm = [[WOApplication application] resourceManager];
359   if (rm == nil)
360     [self debugWithFormat:@"WARNING: missing resource manager!"];
361     
362   /* get parameters */
363     
364   r = [_str rangeOfString:@"/"];
365   if (r.length > 0) {
366     lTable = [_str substringToIndex:r.location];
367     lKey   = [_str substringFromIndex:(r.location + r.length)];
368   }
369   else {
370     lTable = nil;
371     lKey   = _str;
372   }
373   lVal = lKey;
374
375   if([lKey hasPrefix:@"$"]) {
376     lKey = [self valueForKeyPath:[lKey substringFromIndex:1]];
377   }
378   if([lTable hasPrefix:@"$"]) {
379     lTable = [self valueForKeyPath:[lTable substringFromIndex:1]];
380   }
381 #if 0
382   if([lVal hasPrefix:@"$"]) {
383     lVal = [self valueForKeyPath:[lVal substringFromIndex:1]];
384   }
385 #endif
386   /* lookup string */
387     
388   label = [rm stringForKey:lKey inTableNamed:lTable withDefaultValue:lVal
389               languages:languages];
390   return label;
391 }
392
393 - (NSString *)localizedNameForDayOfWeek:(unsigned)_dayOfWeek {
394   NSString *key =  [dayLabelKeys objectAtIndex:_dayOfWeek % 7];
395   return [self labelForKey:key];
396 }
397
398 - (NSString *)localizedAbbreviatedNameForDayOfWeek:(unsigned)_dayOfWeek {
399   NSString *key =  [abbrDayLabelKeys objectAtIndex:_dayOfWeek % 7];
400   return [self labelForKey:key];
401 }
402
403 - (NSString *)localizedNameForMonthOfYear:(unsigned)_monthOfYear {
404   NSString *key =  [monthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
405   return [self labelForKey:key];
406 }
407
408 - (NSString *)localizedAbbreviatedNameForMonthOfYear:(unsigned)_monthOfYear {
409   NSString *key =  [abbrMonthLabelKeys objectAtIndex:(_monthOfYear - 1) % 12];
410   return [self labelForKey:key];
411 }
412
413 /* locale */
414
415 - (NSDictionary *)locale {
416   /* we need no fallback here, as locale is guaranteed to be set by sogod */
417   return [[self context] valueForKey:@"locale"];
418 }
419
420 /* debugging */
421
422 - (BOOL)isUIxDebugEnabled {
423   return uixDebugEnabled;
424 }
425
426 @end /* UIxComponent */