2 Copyright (C) 2000-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
24 #include "WOElement+private.h"
26 #include "WOContext+private.h"
27 #include <NGObjWeb/WOApplication.h>
30 @implementation WOForm
32 static int debugTakeValues = -1;
38 - (id)initWithName:(NSString *)_name
39 associations:(NSDictionary *)_config
40 template:(WOElement *)_c
42 if (debugTakeValues == -1) {
44 [[NSUserDefaults standardUserDefaults] boolForKey:@"WODebugTakeValues"]
46 if (debugTakeValues) NSLog(@"WOForm: WODebugTakeValues on.");
49 if ((self = [super initWithName:_name associations:_config template:_c])) {
50 WOAssociation *sidInUrlAssoc;
52 self->containsForm = YES;
54 sidInUrlAssoc = OWGetProperty(_config, @"?wosid");
55 self->action = OWGetProperty(_config, @"action");
56 self->href = OWGetProperty(_config, @"href");
57 self->pageName = OWGetProperty(_config, @"pageName");
58 self->queryDictionary = OWGetProperty(_config, @"queryDictionary");
59 self->queryParameters = OWExtractQueryParameters(_config);
60 self->actionClass = OWGetProperty(_config, @"actionClass");
61 self->directActionName = OWGetProperty(_config, @"directActionName");
62 self->method = OWGetProperty(_config, @"method");
64 self->sidInUrl = (sidInUrlAssoc != nil)
65 ? [sidInUrlAssoc boolValueInComponent:nil]
68 self->template = [_c retain];
74 [self->method release];
75 [self->template release];
76 [self->actionClass release];
77 [self->directActionName release];
78 [self->queryDictionary release];
79 [self->queryParameters release];
80 [self->action release];
81 [self->pageName release];
86 /* handle active form elements */
88 - (WOElement *)template {
89 return self->template;
92 // ******************** responder ********************
94 - (void)takeValuesFromRequest:(WORequest *)_request
95 inContext:(WOContext *)_ctx
97 static int alwaysPassIn = -1;
99 if (alwaysPassIn == -1) {
100 alwaysPassIn = [[[NSUserDefaults standardUserDefaults]
101 objectForKey:@"WOFormAlwaysPassDown"]
105 if ([_ctx isInForm]) {
106 NSLog(@"ERROR(%s): another form is already active in context !",
107 __PRETTY_FUNCTION__);
110 [_ctx setInForm:YES];
112 WOComponent *sComponent = [_ctx component];
113 BOOL doTakeValues = NO;
115 if (self->queryParameters) {
116 /* apply values to ?style parameters */
120 keys = [self->queryParameters keyEnumerator];
121 while ((key = [keys nextObject])) {
122 WOAssociation *assoc;
125 assoc = [self->queryParameters objectForKey:key];
126 value = [_request formValueForKey:key];
128 [assoc setValue:value inComponent:sComponent];
132 if ([[self->href stringValueInComponent:sComponent]
133 isEqualToString:[_request uri]]) {
134 if (debugTakeValues) {
135 NSArray *formValues = [_request formValueKeys];
136 NSLog(@"%s: we are uri active (uri=%@): %@ ..", __PRETTY_FUNCTION__,
137 [_request uri], formValues);
141 else if ([[_ctx elementID] isEqualToString:[_ctx senderID]]) {
142 if (debugTakeValues) {
143 NSArray *formValues = [_request formValueKeys];
144 NSLog(@"%s: we are elem active (eid=%@): %@ ..", __PRETTY_FUNCTION__,
145 [_ctx elementID], formValues);
149 else if (alwaysPassIn) {
151 NSLog(@"%s: taking values from foreign request ",__PRETTY_FUNCTION__);
155 /* finally, let the component decide */
156 doTakeValues = [sComponent shouldTakeValuesFromRequest:_request
158 if (debugTakeValues) {
159 NSLog(@"%s: component should take values: %s ", __PRETTY_FUNCTION__,
160 doTakeValues ? "yes" : "no");
166 NSLog(@"%s: taking values ...", __PRETTY_FUNCTION__);
168 [self->template takeValuesFromRequest:_request inContext:_ctx];
171 NSLog(@"%s: did take values.", __PRETTY_FUNCTION__);
173 else if (debugTakeValues) {
176 @"WOForm: *not* taking values from foreign request "
177 @"(id='%@' vs sid='%@') ...",
178 [_ctx elementID], [_ctx senderID]];
182 if (![_ctx isInForm]) {
184 logWithFormat:@"ERROR(%s:%d): -isInForm is NO !!!",
185 __PRETTY_FUNCTION__, __LINE__];
191 - (id)invokeActionForRequest:(WORequest *)_request
192 inContext:(WOContext *)_ctx
196 [_ctx setInForm:YES];
198 if ([_ctx currentElementID] == nil) {
201 if ((element = [_ctx activeFormElement])) {
203 result = [self->template invokeActionForRequest:_request inContext:_ctx];
206 /* wrong - need to setup correct component stack */
207 result = [[element invokeActionForRequest:_request
212 else if (self->action) {
213 result = [self executeAction:self->action inContext:_ctx];
215 else if (self->pageName) {
216 NSString *pname = nil;
217 WOComponent *page = nil;
219 pname = [self->pageName stringValueInComponent:[_ctx component]];
220 page = [[_ctx application] pageWithName:pname inContext:_ctx];
223 [[_ctx session] logWithFormat:
224 @"%@[0x%08X]: did not find page with name %@ !",
225 NSStringFromClass([self class]), self, pname];
227 NSLog(@"showing page %@", page);
232 result = [self->template invokeActionForRequest:_request inContext:_ctx];
239 - (NSString *)_addHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx {
240 /* post to a fixed hyperlink */
241 WOComponent *sComponent = [_ctx component];
245 s = [self->href stringValueInComponent:sComponent];
246 d = [self->queryDictionary valueInComponent:sComponent];
248 WOResponse_AddString(_r, s);
250 return [self queryStringForQueryDictionary:d
251 andQueryParameters:self->queryParameters
255 - (NSString *)_addActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c {
256 /* post to a component action */
259 WOResponse_AddString(_r, [_c componentActionURL]);
261 d = [self->queryDictionary valueInComponent:[_c component]];
262 return [self queryStringForQueryDictionary:d
263 andQueryParameters:self->queryParameters
267 - (void)_addDirectActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c {
268 /* a direct action link */
269 WOComponent *sComponent;
270 NSString *daClass = nil;
271 NSString *daName = nil;
272 NSMutableDictionary *qd;
276 sComponent = [_c component];
277 daClass = [self->actionClass stringValueInComponent:sComponent];
278 daName = [self->directActionName stringValueInComponent:sComponent];
282 if (![daClass isEqualToString:@"DirectAction"])
283 daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
289 qd = [NSMutableDictionary dictionaryWithCapacity:16];
291 /* add query dictionary */
293 if (self->queryDictionary) {
294 if ((tmp = [self->queryDictionary valueInComponent:sComponent]))
295 [qd addEntriesFromDictionary:tmp];
298 /* add ?style parameters */
300 if (self->queryParameters) {
304 keys = [self->queryParameters keyEnumerator];
305 while ((key = [keys nextObject])) {
308 assoc = [self->queryParameters objectForKey:key];
309 value = [assoc stringValueInComponent:sComponent];
311 [qd setObject:(value ? value : @"") forKey:key];
316 if (self->sidInUrl && [_c hasSession]) {
320 [qd setObject:[sn sessionID] forKey:WORequestValueSessionID];
322 if (![sn isDistributionEnabled]) {
323 [qd setObject:[[WOApplication application] number]
324 forKey:WORequestValueInstance];
327 else if (self->sidInUrl) {
328 [self debugWithFormat:
329 @"Note: session-id is requested, but no session is active?"];
332 uri = [_c directActionURLForActionNamed:daName queryDictionary:qd];
333 WOResponse_AddString(_r, uri);
336 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
337 WOComponent *sComponent;
338 NSString *queryString = nil;
340 if ([[_ctx request] isFromClientComponent]) {
341 [self->template appendToResponse:_response inContext:_ctx];
345 [_ctx setInForm:YES];
346 sComponent = [_ctx component];
348 WOResponse_AddCString(_response, "<form action=\"");
351 queryString = [self _addHrefToResponse:_response inContext:_ctx];
352 else if (self->directActionName != nil || self->actionClass != nil)
353 [self _addDirectActionToResponse:_response inContext:_ctx];
355 queryString = [self _addActionToResponse:_response inContext:_ctx];
358 [_response appendContentCharacter:'?'];
359 WOResponse_AddString(_response, queryString);
362 WOResponse_AddCString(_response, "\" method=\"");
363 WOResponse_AddString(_response,
364 [self->method stringValueInComponent:sComponent]);
365 WOResponse_AddCString(_response, "\"");
368 WOResponse_AddCString(_response, "\" method=\"post\"");
370 [self appendExtraAttributesToResponse:_response inContext:_ctx];
372 if (self->otherTagString) {
375 s = [self->otherTagString stringValueInComponent:sComponent];
376 if ([s length] > 0) WOResponse_AddString(_response, s);
378 WOResponse_AddChar(_response, '>');
380 [self->template appendToResponse:_response inContext:_ctx];
382 WOResponse_AddCString(_response, "</form>");
388 - (NSString *)associationDescription {
389 NSMutableString *str = [NSMutableString stringWithCapacity:64];
390 //[str appendString:[super associationDescription]];
392 if (self->action) [str appendFormat:@" action=%@", self->action];
393 if (self->href) [str appendFormat:@" href=%@", self->href];
394 if (self->pageName) [str appendFormat:@" page=%@", self->pageName];
396 if (self->actionClass)
397 [str appendFormat:@" actionClass=%@", self->actionClass];
398 if (self->directActionName)
399 [str appendFormat:@" directAction=%@", self->directActionName];
401 [str appendFormat:@" template=%@", self->template];