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
23 #include "WOElement+private.h"
25 #include "WOContext+private.h"
26 #include <NGObjWeb/WOApplication.h>
29 @implementation WOForm
31 static int debugTakeValues = -1;
37 - (id)initWithName:(NSString *)_name
38 associations:(NSDictionary *)_config
39 template:(WOElement *)_c
41 if (debugTakeValues == -1) {
43 [[NSUserDefaults standardUserDefaults] boolForKey:@"WODebugTakeValues"]
45 if (debugTakeValues) NSLog(@"WOForm: WODebugTakeValues on.");
48 if ((self = [super initWithName:_name associations:_config template:_c])) {
49 WOAssociation *sidInUrlAssoc;
51 self->containsForm = YES;
53 sidInUrlAssoc = OWGetProperty(_config, @"?wosid");
54 self->action = OWGetProperty(_config, @"action");
55 self->href = OWGetProperty(_config, @"href");
56 self->pageName = OWGetProperty(_config, @"pageName");
57 self->queryDictionary = OWGetProperty(_config, @"queryDictionary");
58 self->queryParameters = OWExtractQueryParameters(_config);
59 self->actionClass = OWGetProperty(_config, @"actionClass");
60 self->directActionName = OWGetProperty(_config, @"directActionName");
61 self->method = OWGetProperty(_config, @"method");
63 self->sidInUrl = (sidInUrlAssoc != nil)
64 ? [sidInUrlAssoc boolValueInComponent:nil]
67 self->template = [_c retain];
73 [self->method release];
74 [self->template release];
75 [self->actionClass release];
76 [self->directActionName release];
77 [self->queryDictionary release];
78 [self->queryParameters release];
79 [self->action release];
80 [self->pageName release];
85 /* handle active form elements */
87 - (WOElement *)template {
88 return self->template;
91 // ******************** responder ********************
93 - (void)takeValuesFromRequest:(WORequest *)_request
94 inContext:(WOContext *)_ctx
96 static int alwaysPassIn = -1;
98 if (alwaysPassIn == -1) {
99 alwaysPassIn = [[[NSUserDefaults standardUserDefaults]
100 objectForKey:@"WOFormAlwaysPassDown"]
104 if ([_ctx isInForm]) {
105 NSLog(@"ERROR(%s): another form is already active in context !",
106 __PRETTY_FUNCTION__);
109 [_ctx setInForm:YES];
111 WOComponent *sComponent = [_ctx component];
112 BOOL doTakeValues = NO;
114 if (self->queryParameters) {
115 /* apply values to ?style parameters */
119 keys = [self->queryParameters keyEnumerator];
120 while ((key = [keys nextObject])) {
121 WOAssociation *assoc;
124 assoc = [self->queryParameters objectForKey:key];
125 value = [_request formValueForKey:key];
127 [assoc setValue:value inComponent:sComponent];
131 if ([[self->href stringValueInComponent:sComponent]
132 isEqualToString:[_request uri]]) {
133 if (debugTakeValues) {
134 NSArray *formValues = [_request formValueKeys];
135 NSLog(@"%s: we are uri active (uri=%@): %@ ..", __PRETTY_FUNCTION__,
136 [_request uri], formValues);
140 else if ([[_ctx elementID] isEqualToString:[_ctx senderID]]) {
141 if (debugTakeValues) {
142 NSArray *formValues = [_request formValueKeys];
143 NSLog(@"%s: we are elem active (eid=%@): %@ ..", __PRETTY_FUNCTION__,
144 [_ctx elementID], formValues);
148 else if (alwaysPassIn) {
150 NSLog(@"%s: taking values from foreign request ",__PRETTY_FUNCTION__);
154 /* finally, let the component decide */
155 doTakeValues = [sComponent shouldTakeValuesFromRequest:_request
157 if (debugTakeValues) {
158 NSLog(@"%s: component should take values: %s ", __PRETTY_FUNCTION__,
159 doTakeValues ? "yes" : "no");
165 NSLog(@"%s: taking values ...", __PRETTY_FUNCTION__);
167 [self->template takeValuesFromRequest:_request inContext:_ctx];
170 NSLog(@"%s: did take values.", __PRETTY_FUNCTION__);
172 else if (debugTakeValues) {
175 @"WOForm: *not* taking values from foreign request "
176 @"(id='%@' vs sid='%@') ...",
177 [_ctx elementID], [_ctx senderID]];
181 if (![_ctx isInForm]) {
183 logWithFormat:@"ERROR(%s:%d): -isInForm is NO !!!",
184 __PRETTY_FUNCTION__, __LINE__];
190 - (id)invokeActionForRequest:(WORequest *)_request
191 inContext:(WOContext *)_ctx
195 [_ctx setInForm:YES];
197 if ([_ctx currentElementID] == nil) {
200 if ((element = [_ctx activeFormElement])) {
202 result = [self->template invokeActionForRequest:_request inContext:_ctx];
205 /* wrong - need to setup correct component stack */
206 result = [[element invokeActionForRequest:_request
211 else if (self->action) {
212 result = [self executeAction:self->action inContext:_ctx];
214 else if (self->pageName) {
215 NSString *pname = nil;
216 WOComponent *page = nil;
218 pname = [self->pageName stringValueInComponent:[_ctx component]];
219 page = [[_ctx application] pageWithName:pname inContext:_ctx];
222 [[_ctx session] logWithFormat:
223 @"%@[0x%08X]: did not find page with name %@ !",
224 NSStringFromClass([self class]), self, pname];
226 NSLog(@"showing page %@", page);
231 result = [self->template invokeActionForRequest:_request inContext:_ctx];
238 - (NSString *)_addHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx {
239 /* post to a fixed hyperlink */
240 WOComponent *sComponent = [_ctx component];
244 s = [self->href stringValueInComponent:sComponent];
245 d = [self->queryDictionary valueInComponent:sComponent];
247 WOResponse_AddString(_r, s);
249 return [self queryStringForQueryDictionary:d
250 andQueryParameters:self->queryParameters
254 - (NSString *)_addActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c {
255 /* post to a component action */
258 WOResponse_AddString(_r, [_c componentActionURL]);
260 d = [self->queryDictionary valueInComponent:[_c component]];
261 return [self queryStringForQueryDictionary:d
262 andQueryParameters:self->queryParameters
266 - (void)_addDirectActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c {
267 /* a direct action link */
268 WOComponent *sComponent;
269 NSString *daClass = nil;
270 NSString *daName = nil;
271 NSMutableDictionary *qd;
275 sComponent = [_c component];
276 daClass = [self->actionClass stringValueInComponent:sComponent];
277 daName = [self->directActionName stringValueInComponent:sComponent];
281 if (![daClass isEqualToString:@"DirectAction"])
282 daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
288 qd = [NSMutableDictionary dictionaryWithCapacity:16];
290 /* add query dictionary */
292 if (self->queryDictionary) {
293 if ((tmp = [self->queryDictionary valueInComponent:sComponent]))
294 [qd addEntriesFromDictionary:tmp];
297 /* add ?style parameters */
299 if (self->queryParameters) {
303 keys = [self->queryParameters keyEnumerator];
304 while ((key = [keys nextObject])) {
307 assoc = [self->queryParameters objectForKey:key];
308 value = [assoc stringValueInComponent:sComponent];
310 [qd setObject:(value ? value : @"") forKey:key];
315 if (self->sidInUrl && [_c hasSession]) {
319 [qd setObject:[sn sessionID] forKey:WORequestValueSessionID];
321 if (![sn isDistributionEnabled]) {
322 [qd setObject:[[WOApplication application] number]
323 forKey:WORequestValueInstance];
326 else if (self->sidInUrl) {
327 [self debugWithFormat:
328 @"Note: session-id is requested, but no session is active?"];
331 uri = [_c directActionURLForActionNamed:daName queryDictionary:qd];
332 WOResponse_AddString(_r, uri);
335 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
336 WOComponent *sComponent;
337 NSString *queryString = nil;
339 if ([[_ctx request] isFromClientComponent]) {
340 [self->template appendToResponse:_response inContext:_ctx];
344 [_ctx setInForm:YES];
345 sComponent = [_ctx component];
347 WOResponse_AddCString(_response, "<form action=\"");
350 queryString = [self _addHrefToResponse:_response inContext:_ctx];
351 else if (self->directActionName != nil || self->actionClass != nil)
352 [self _addDirectActionToResponse:_response inContext:_ctx];
354 queryString = [self _addActionToResponse:_response inContext:_ctx];
357 [_response appendContentCharacter:'?'];
358 WOResponse_AddString(_response, queryString);
361 WOResponse_AddCString(_response, "\" method=\"");
362 WOResponse_AddString(_response,
363 [self->method stringValueInComponent:sComponent]);
364 WOResponse_AddCString(_response, "\"");
367 WOResponse_AddCString(_response, "\" method=\"post\"");
369 [self appendExtraAttributesToResponse:_response inContext:_ctx];
371 if (self->otherTagString) {
372 WOResponse_AddChar(_response, ' ');
373 WOResponse_AddString(_response,
374 [self->otherTagString stringValueInComponent:
377 WOResponse_AddChar(_response, '>');
379 [self->template appendToResponse:_response inContext:_ctx];
381 WOResponse_AddCString(_response, "</form>");
387 - (NSString *)associationDescription {
388 NSMutableString *str = [NSMutableString stringWithCapacity:64];
389 //[str appendString:[super associationDescription]];
391 if (self->action) [str appendFormat:@" action=%@", self->action];
392 if (self->href) [str appendFormat:@" href=%@", self->href];
393 if (self->pageName) [str appendFormat:@" page=%@", self->pageName];
395 if (self->actionClass)
396 [str appendFormat:@" actionClass=%@", self->actionClass];
397 if (self->directActionName)
398 [str appendFormat:@" directAction=%@", self->directActionName];
400 [str appendFormat:@" template=%@", self->template];