]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOActionURL.m
Add libxml2-dev to libsope-xml4.7-dev deps
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOActionURL.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #include <NGObjWeb/WOActionURL.h>
23 #include "WOElement+private.h"
24 #include <NGObjWeb/WOApplication.h>
25 #include <NGObjWeb/WOResourceManager.h>
26 #include "decommon.h"
27
28 @interface _WOActionActionURL : WOActionURL
29 {
30   WOAssociation *action;
31 }
32 @end
33
34 @interface _WOPageActionURL : WOActionURL
35 {
36   WOAssociation *pageName;
37 }
38 @end
39
40 @interface _WODirectActionActionURL : WOActionURL
41 {
42   WOAssociation *actionClass;
43   WOAssociation *directActionName;
44   BOOL          sidInUrl;          /* include session-id in wa URL ? */
45 }
46 @end
47
48 @interface WOActionURL(PrivateMethods)
49
50 - (id)_initWithName:(NSString *)_name
51   associations:(NSDictionary *)_config
52   template:(WOElement *)_t;
53
54 - (NSString *)associationDescription;
55
56 @end
57
58 @implementation WOActionURL
59
60 + (int)version {
61   return 1;
62 }
63 + (void)initialize {
64   NSAssert2([super version] == 2,
65             @"invalid superclass (%@) version %i !",
66             NSStringFromClass([self superclass]), [super version]);
67 }
68
69 + (BOOL)containsLinkInAssociations:(NSDictionary *)_assocs {
70   if (_assocs == nil) return NO;
71   if ([_assocs objectForKey:@"href"])             return YES;
72   if ([_assocs objectForKey:@"directActionName"]) return YES;
73   if ([_assocs objectForKey:@"pageName"])         return YES;
74   if ([_assocs objectForKey:@"action"])           return YES;
75   if ([_assocs objectForKey:@"actionClass"])      return YES;
76   return NO;
77 }
78
79 - (id)initWithName:(NSString *)_name
80   associations:(NSDictionary *)_config
81   template:(WOElement *)_t
82 {
83   Class linkClass = Nil;
84   
85   if ([_config objectForKey:@"action"])
86     linkClass = [_WOActionActionURL class];
87   else if ([_config objectForKey:@"pageName"])
88     linkClass = [_WOPageActionURL class];
89   else
90     linkClass = [_WODirectActionActionURL class];
91
92   [self release];
93   return
94     [[linkClass alloc] initWithName:_name associations:_config template:_t];
95 }
96
97 - (id)_initWithName:(NSString *)_name
98   associations:(NSDictionary *)_config
99   template:(WOElement *)_t
100 {
101   if ((self = [super initWithName:_name associations:_config template:_t])) {
102     self->fragmentIdentifier = OWGetProperty(_config, @"fragmentIdentifier");
103     self->queryDictionary    = OWGetProperty(_config, @"queryDictionary");
104     self->queryParameters    = OWExtractQueryParameters(_config);
105     self->template           = [_t retain];
106     self->containsForm       = self->queryParameters ? YES : NO;
107   }
108   return self;
109 }
110
111 - (void)dealloc {
112   [self->template           release];
113   [self->queryDictionary    release];
114   [self->queryParameters    release];
115   [self->fragmentIdentifier release];
116   [super dealloc];
117 }
118
119 /* accessors */
120
121 - (id)template {
122   return self->template;
123 }
124
125 /* handling requests */
126
127 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
128   /* links can take form values !!!! (for query-parameters) */
129
130   if (self->queryParameters) {
131     /* apply values to ?style parameters */
132     WOComponent  *sComponent = [_ctx component];
133     NSEnumerator *keys;
134     NSString     *key;
135
136     keys = [self->queryParameters keyEnumerator];
137     while ((key = [keys nextObject])) {
138       id assoc, value;
139
140       assoc = [self->queryParameters objectForKey:key];
141       value = [_req formValueForKey:key];
142
143       [assoc setValue:value inComponent:sComponent];
144     }
145   }
146   
147   [self->template takeValuesFromRequest:_req inContext:_ctx];
148 }
149
150 - (id)invokeActionForRequest:(WORequest *)_request
151   inContext:(WOContext *)_ctx
152 {
153   [[_ctx session] logWithFormat:@"%@[0x%p]: no action/page set !",
154                     NSStringFromClass([self class]), self];
155   return nil;
156 }
157
158 - (BOOL)_appendHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx {
159 #if APPLE_FOUNDATION_LIBRARY || NeXT_Foundation_LIBRARY || \
160     COCOA_Foundation_LIBRARY
161   NSLog(@"subclass responsibility ...");
162 #else
163   [self subclassResponsibility:_cmd];
164 #endif
165   return NO;
166 }
167
168 /* generate response */
169
170 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
171   WOComponent *sComponent;
172   NSString *queryString = nil;
173   
174   if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent]) {
175     [self->template appendToResponse:_response inContext:_ctx];
176     return;
177   }
178
179   sComponent = [_ctx component];
180   
181   if ([self _appendHrefToResponse:_response inContext:_ctx]) {
182     queryString = [self queryStringForQueryDictionary:
183                           [self->queryDictionary valueInComponent:sComponent]
184                         andQueryParameters:self->queryParameters
185                         inContext:_ctx];
186   }
187   
188   if (self->fragmentIdentifier != nil) {
189     [_response appendContentCharacter:'#'];
190     WOResponse_AddString(_response,
191          [self->fragmentIdentifier stringValueInComponent:sComponent]);
192   }
193   if (queryString != nil) {
194     [_response appendContentCharacter:'?'];
195     WOResponse_AddString(_response, queryString);
196   }
197     
198   /* content */
199   [self->template appendToResponse:_response inContext:_ctx];
200 }
201
202 /* description */
203
204 - (NSString *)associationDescription {
205   NSMutableString *str = [NSMutableString stringWithCapacity:256];
206
207   if (self->fragmentIdentifier)
208     [str appendFormat:@" fragment=%@", self->fragmentIdentifier];
209
210   return str;
211 }
212
213 @end /* WOActionURL */
214
215 @implementation _WOActionActionURL
216
217 - (id)initWithName:(NSString *)_name
218   associations:(NSDictionary *)_config
219   template:(WOElement *)_t
220 {
221   if ((self = [super _initWithName:_name associations:_config template:_t])) {
222     self->action = OWGetProperty(_config, @"action");
223
224     if (self->action == nil) {
225       NSLog(@"missing action association for WOActionURL ..");
226       RELEASE(self);
227       return nil;
228     }
229
230 #if DEBUG
231     if ([_config objectForKey:@"pageName"] ||
232         [_config objectForKey:@"href"]     ||
233         [_config objectForKey:@"directActionName"] ||
234         [_config objectForKey:@"actionClass"]) {
235       NSLog(@"WARNING: inconsistent association settings in WOActionURL !"
236             @" (assign only one of pageName, href, "
237             @"directActionName or action)");
238     }
239 #endif
240   }
241   return self;
242 }
243
244 - (void)dealloc {
245   [self->action release];
246   [super dealloc];
247 }
248
249 /* dynamic invocation */
250
251 - (id)invokeActionForRequest:(WORequest *)_request
252   inContext:(WOContext *)_ctx
253 {
254   /* link is active */
255   return [self executeAction:self->action inContext:_ctx];
256 }
257
258 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
259   inContext:(WOContext *)_ctx
260 {
261   WOResponse_AddString(_response, [_ctx componentActionURL]);
262   return YES;
263 }
264
265 /* description */
266
267 - (NSString *)associationDescription {
268   NSMutableString *str = [NSMutableString stringWithCapacity:256];
269
270   [str appendFormat:@" action=%@", self->action];
271   [str appendString:[super associationDescription]];
272   return str;
273 }
274
275 @end /* _WOActionActionURL */
276
277 @implementation _WOPageActionURL
278
279 - (id)initWithName:(NSString *)_name
280   associations:(NSDictionary *)_config
281   template:(WOElement *)_t
282 {
283   if ((self = [super _initWithName:_name associations:_config template:_t])) {
284     self->pageName = OWGetProperty(_config, @"pageName");
285
286     if (self->pageName == nil) {
287       NSLog(@"missing pageName association for WOActionURL ..");
288       RELEASE(self);
289       return nil;
290     }
291
292 #if DEBUG
293     if ([_config objectForKey:@"action"] ||
294         [_config objectForKey:@"href"]     ||
295         [_config objectForKey:@"directActionName"] ||
296         [_config objectForKey:@"actionClass"]) {
297       NSLog(@"WARNING: inconsistent association settings in WOActionURL !"
298             @" (assign only one of pageName, href, "
299             @"directActionName or action)");
300     }
301 #endif
302   }
303   return self;
304 }
305
306 - (void)dealloc {
307   [self->pageName release];
308   [super dealloc];
309 }
310
311 /* actions */
312
313 - (id)invokeActionForRequest:(WORequest *)_request
314   inContext:(WOContext *)_ctx
315 {
316   WOComponent *page = nil;
317   NSString    *name = nil;
318
319   name = [self->pageName stringValueInComponent:[_ctx component]];
320   page = [[_ctx application] pageWithName:name inContext:_ctx];
321
322   if (page == nil) {
323     [[_ctx session] logWithFormat:
324                       @"%@[0x%p]: did not find page with name %@ !",
325                       NSStringFromClass([self class]), self, name];
326   }
327   return page;
328 }
329
330 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
331   inContext:(WOContext *)_ctx
332 {
333   WOResponse_AddString(_response, [_ctx componentActionURL]);
334   return YES;
335 }
336
337 /* description */
338
339 - (NSString *)associationDescription {
340   NSMutableString *str = [NSMutableString stringWithCapacity:256];
341
342   [str appendFormat:@" pageName=%@", self->pageName];
343   [str appendString:[super associationDescription]];
344   return str;
345 }
346
347 @end /* _WOPageActionURL */
348
349 @implementation _WODirectActionActionURL
350
351 - (id)initWithName:(NSString *)_name
352   associations:(NSDictionary *)_config
353   template:(WOElement *)_t
354 {
355   if ((self = [super _initWithName:_name associations:_config template:_t])) {
356     WOAssociation *sidInUrlAssoc;
357     
358     sidInUrlAssoc          = OWGetProperty(_config, @"?wosid");
359     self->actionClass      = OWGetProperty(_config, @"actionClass");
360     self->directActionName = OWGetProperty(_config, @"directActionName");
361
362     self->sidInUrl = (sidInUrlAssoc)
363       ? [sidInUrlAssoc boolValueInComponent:nil]
364       : YES;
365     
366 #if DEBUG
367     if ([_config objectForKey:@"action"] ||
368         [_config objectForKey:@"href"]     ||
369         [_config objectForKey:@"pageName"]) {
370       NSLog(@"WARNING: inconsistent association settings in WOActionURL !"
371             @" (assign only one of pageName, href, "
372             @"directActionName or action)");
373     }
374 #endif
375   }
376   return self;
377 }
378
379 - (void)dealloc {
380   [self->actionClass      release];
381   [self->directActionName release];
382   [super dealloc];
383 }
384
385 /* href */
386
387 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
388   inContext:(WOContext *)_ctx
389 {
390   WOComponent         *sComponent;
391   NSString            *daClass;
392   NSString            *daName;
393   NSMutableDictionary *qd;
394   NSDictionary        *tmp;
395
396   sComponent = [_ctx component];
397   daClass = [self->actionClass stringValueInComponent:sComponent];
398   daName  = [self->directActionName stringValueInComponent:sComponent];
399
400   if (daClass) {
401     if (daName) {
402       if (![daClass isEqualToString:@"DirectAction"])
403         daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
404     }
405     else
406       daName = daClass;
407   }
408
409   qd = [NSMutableDictionary dictionaryWithCapacity:16];
410
411       /* add query dictionary */
412       
413   if (self->queryDictionary) {
414     if ((tmp = [self->queryDictionary valueInComponent:sComponent]))
415       [qd addEntriesFromDictionary:tmp];
416   }
417       
418   /* add ?style parameters */
419
420   if (self->queryParameters) {
421     NSEnumerator *keys;
422     NSString     *key;
423
424     keys = [self->queryParameters keyEnumerator];
425     while ((key = [keys nextObject]) != nil) {
426       id assoc, value;
427
428       assoc = [self->queryParameters objectForKey:key];
429       value = [assoc stringValueInComponent:sComponent];
430           
431       [qd setObject:(value != nil ? value : (id)@"") forKey:key];
432     }
433   }
434       
435   /* add session ID */
436
437   if (self->sidInUrl) {
438     if ([_ctx hasSession]) {
439       WOSession *sn = [_ctx session];
440           
441       [qd setObject:[sn sessionID] forKey:WORequestValueSessionID];
442           
443       if (![sn isDistributionEnabled]) {
444         [qd setObject:[[WOApplication application] number]
445             forKey:WORequestValueInstance];
446       }
447     }
448   }
449
450   WOResponse_AddString(_response,
451                        [_ctx directActionURLForActionNamed:daName
452                              queryDictionary:qd]);
453   return NO;
454 }
455
456 /* description */
457
458 - (NSString *)associationDescription {
459   NSMutableString *str = [NSMutableString stringWithCapacity:256];
460
461   if (self->actionClass != nil)
462     [str appendFormat:@" actionClass=%@", self->actionClass];
463   if (self->directActionName != nil)
464     [str appendFormat:@" directAction=%@", self->directActionName];
465   
466   [str appendString:[super associationDescription]];
467   return str;
468 }
469
470 @end /* _WODirectActionActionURL */