File Coverage

blib/lib/AxKit/XSP/PerForm.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             # $Id: PerForm.pm,v 1.24 2003/08/10 16:43:56 matt Exp $
2              
3             package AxKit::XSP::PerForm;
4              
5             $VERSION = "1.83";
6              
7 1     1   7597 use AxKit 1.4;
  0            
  0            
8             use Apache;
9             use Apache::AxKit::Language::XSP::TaglibHelper;
10             use AxKit::XSP::WebUtils 1.5;
11              
12             $NS = 'http://axkit.org/NS/xsp/perform/v1';
13              
14             @ISA = qw(Apache::AxKit::Language::XSP);
15              
16             @EXPORT_TAGLIB = (
17             'textfield($name;$default,$width,$maxlength,$index,$onvalidate,$onload,$disabled,$onchange)',
18             'password($name;$default,$width,$maxlength,$index,$onvalidate,$onload,$disabled,$onchange)',
19             'submit($name;$value,$image,$alt,$border,$align,$goto,$index,$onsubmit,$disabled,$onclick)',
20             'cancel($name;$value,$image,$alt,$border,$align,$goto,$index,$oncancel,$disabled,$onclick)',
21             'checkbox($name;$value,$checked,$label,$index,$onvalidate,$onload,$disabled,$onclick)',
22             'file_upload($name;$value,$accept,$onvalidate,$onload,$disabled,$onclick)',
23             'hidden($name;$value,$index,$onload)',
24             'textarea($name;$cols,$rows,$wrap,$default,$index,$onvalidate,$onload,$disabled,$onchange)',
25             'single_select($name;$default,$index,$onvalidate,$onload,$disabled,$onchange,*options):itemtag=option',
26             'multi_select($name;@default,$index,$onvalidate,$onload,$disabled,$onclick,*option):itemtag=option',
27             );
28              
29             use strict;
30              
31             sub parse_char {
32             Apache::AxKit::Language::XSP::TaglibHelper::parse_char(@_);
33             }
34              
35             sub parse_start {
36             my ($e, $tag, %attribs) = @_;
37            
38             if ($tag eq 'form') {
39             $e->manage_text(0);
40            
41             my $form_el = {
42             Name => "form",
43             NamespaceURI => "",
44             Attributes => [
45             { Name => "name", Value => $attribs{name} },
46             { Name => "method", Value => "POST" },
47             { Name => "enctype", Value => "multipart/form-data" },
48             ],
49             };
50             #MSS
51             # if (Apache->args) {
52             # $form_el->{Attributes}[1]{Value} .='?'.Apache->args;
53             # }
54             #end MSS
55            
56             $e->start_element($form_el);
57            
58             my $submitting = {
59             Name => "hidden",
60             NamespaceURI => "",
61             Attributes => [
62             { Name => "name", Value => "__submitting_$attribs{name}" },
63             { Name => "value", Value => "1" },
64             ],
65             };
66             $e->start_element($submitting);
67             $e->end_element($submitting);
68            
69             return <
70             {
71             use vars qw(\$_form_ctxt \@_submit_buttons \%_submit_goto \%_submit_index \@_cancel_buttons \%_cancel_goto \%_cancel_index );
72             local \$_form_ctxt = { Form => \$cgi->parms, Apache => \$r, Name => '$attribs{name}' };
73             local \@_submit_buttons;
74             local \@_cancel_buttons;
75             local \%_submit_goto;
76             local \%_cancel_goto;
77             local \%_submit_index;
78             local \%_cancel_index;
79             start_form_$attribs{name}(\$_form_ctxt, \$cgi->param('__submitting_$attribs{name}'))
80             if defined \&start_form_$attribs{name};
81             EOT
82             }
83             else {
84             return Apache::AxKit::Language::XSP::TaglibHelper::parse_start(@_);
85             }
86             }
87              
88             sub end_element {
89             my ($e, $element) = @_;
90            
91             if ($element->{Name} eq 'form') {
92             my $form_el = {
93             Name => "form",
94             NamespaceURI => "",
95             Attributes => [],
96             };
97            
98             my $name;
99             my $onsubmit;
100             my $oncancel;
101             my $onformend;
102            
103             for my $attr (@{$element->{Attributes}}) {
104             if ($attr->{Name} eq 'name') {
105             $name = $attr->{Value};
106             }
107             elsif ($attr->{Name} eq 'onformend') {
108             $onformend = $attr->{Value};
109             }
110             elsif ($attr->{Name} eq 'onsubmit') {
111             $onsubmit = $attr->{Value};
112             }
113             elsif ($attr->{Name} eq 'oncancel') {
114             $oncancel = $attr->{Value};
115             }
116             }
117            
118             $e->end_element($form_el);
119             return <
120             my \$package = __PACKAGE__;
121             if (my \$sub = \$package->can('$onformend' || 'end_form_$name')) {
122             \$sub->(\$_form_ctxt, \$cgi->param('__submitting_$name'));
123             }
124              
125             # warn("submitting? ".(\$cgi->param('__submitting_$name')?"yes":"no").", failed? ".(\$_form_ctxt->{_Failed}?"yes":"no"));
126              
127             if (\$cgi->param('__submitting_$name')) {
128             foreach my \$cancel (\@_cancel_buttons) {
129             if (\$cgi->param(\$cancel)) {
130             no strict 'refs';
131             my \$redirect;
132             \$redirect = \$_cancel_goto{\$cancel};
133             if (my \$sub = \$package->can(\$_cancel_index{\$cancel}{oncancel} || '$oncancel' || "cancel_\$_cancel_index{\$cancel}{name}")) {
134             \$redirect = \$sub->(\$_form_ctxt, \$_cancel_index{\$cancel}{'index'});
135             }
136             if (\$redirect) {
137             return AxKit::XSP::WebUtils::redirect(\$redirect,undef,undef,1);
138             }
139             }
140             }
141             }
142              
143             if (\$cgi->param('__submitting_$name') && !\$_form_ctxt->{_Failed}) {
144             foreach my \$submit (\@_submit_buttons) {
145             if (\$cgi->param(\$submit)) {
146             no strict 'refs';
147             my \$redirect;
148             \$redirect = \$_submit_goto{\$submit};
149             if (my \$sub = \$package->can(\$_submit_index{\$submit}{onsubmit} || '$onsubmit' || "submit_\$_submit_index{\$submit}{name}")) {
150             \$redirect = \$sub->(\$_form_ctxt, \$_submit_index{\$submit}{'index'});
151             }
152             if (\$redirect) {
153             return AxKit::XSP::WebUtils::redirect(\$redirect,undef,undef,1);
154             }
155             }
156             }
157             }
158              
159             # catch the case where IE submitted the form without any buttons used
160             if (\$cgi->param('__submitting_$name') && !\$_form_ctxt->{_Failed}) {
161             no strict 'refs';
162             my \$redirect;
163             if (my \$sub = \$package->can('$onsubmit')) {
164             \$redirect = \$sub->(\$_form_ctxt);
165             }
166             if (\$redirect) {
167             return AxKit::XSP::WebUtils::redirect(\$redirect, undef, undef, 1);
168             }
169             }
170              
171             }
172             EOT
173             }
174             else {
175             return Apache::AxKit::Language::XSP::TaglibHelper::parse_end($e, $element->{Name});
176             }
177             }
178              
179             sub textfield ($;$$$$$$$$) {
180             my ($name, $default, $width, $maxlength, $index, $onval, $onload,
181             $disabled, $onchange) = @_;
182             my ($package) = caller;
183            
184             no strict 'refs';
185            
186             my $ctxt = ${"${package}::_form_ctxt"};
187            
188             my $params = $ctxt->{Form};
189             my $fname = $ctxt->{Name};
190            
191             my $error;
192            
193             # validate
194             if ($params->{"__submitting_$fname"}) {
195             # warn("Checking if $package can " . ($onval || "validate_${name}") . "\n");
196             if (my $sub = $package->can($onval || "validate_${name}")) {
197             eval {
198             $sub->($ctxt, ($params->get($name.$index))[-1], $index);
199             $params->{$name.$index} = ($params->get($name.$index))[-1];
200             };
201             $error = $@;
202             $ctxt->{_Failed}++ if $error;
203             $error =~ s/(.*) at .*? line \d+\.$/$1/;
204             }
205             }
206             # load
207             elsif (my $sub = $package->can($onload || "load_${name}")) {
208             $params->{$name.$index} = $sub->($ctxt, $default, ($params->get($name.$index))[-1], $index);
209             }
210             else{
211             $params->{$name.$index} = $default;
212             }
213            
214             return {
215             textfield => {
216             width => $width,
217             maxlength => $maxlength,
218             name => $name,
219             value => ($params->get($name.$index))[-1],
220             index => $index,
221             ($disabled ? (disabled => $disabled) : ()),
222             ($onchange ? (onchange => $onchange) : ()),
223             ($error ? (error => $error) : ()),
224             }
225             };
226             }
227              
228             sub submit ($;$$$$$$$$$$) {
229             my ($name, $value, $image, $alt, $border, $align, $goto, $index,
230             $onsubmit, $disabled, $onclick) = @_;
231             my ($package) = caller;
232            
233             no strict 'refs';
234            
235             my $ctxt = ${"${package}::_form_ctxt"};
236             my $params = $ctxt->{Form};
237            
238             push @{"${package}::_submit_buttons"}, "$name$index";
239             ${"${package}::_submit_goto"}{$name.$index} = $goto if $goto;
240             ${"${package}::_submit_index"}{$name.$index}{'index'} = $index;
241             ${"${package}::_submit_index"}{$name.$index}{'name'} = $name;
242             ${"${package}::_submit_index"}{$name.$index}{'onsubmit'} = $onsubmit;
243            
244             # save
245             if ($image) {
246             return {
247             image_button => {
248             name => $name,
249             value => $value,
250             src => $image,
251             alt => $alt,
252             border => $border || 0,
253             align => $align || "bottom",
254             ($disabled ? (disabled => $disabled) : ()),
255             ($onclick ? (onclick => $onclick) : ()),
256             index => $index,
257             }
258             };
259             }
260             else {
261             return {
262             submit_button => {
263             name => $name,
264             value => $value,
265             index => $index,
266             ($disabled ? (disabled => $disabled) : ()),
267             ($onclick ? (onclick => $onclick) : ()),
268             }
269             };
270             }
271             }
272              
273             sub cancel ($;$$$$$$$$$$) {
274             my ($name, $value, $image, $alt, $border, $align, $goto, $index,
275             $oncancel, $disabled, $onclick) = @_;
276             my ($package) = caller;
277            
278             no strict 'refs';
279            
280             my $ctxt = ${"${package}::_form_ctxt"};
281             my $params = $ctxt->{Form};
282            
283             push @{"${package}::_cancel_buttons"}, $name.$index;
284             ${"${package}::_cancel_goto"}{$name.$index} = $goto if $goto;
285             ${"${package}::_cancel_index"}{$name.$index}{'index'} = $index;
286             ${"${package}::_cancel_index"}{$name.$index}{'name'} = $name;
287             ${"${package}::_cancel_index"}{$name.$index}{'oncancel'} = $oncancel;
288            
289             # save
290             if ($image) {
291             return {
292             image_button => {
293             name => $name,
294             value => $value,
295             src => $image,
296             alt => $alt,
297             border => $border || 0,
298             align => $align || "bottom",
299             index => $index,
300             ($disabled ? (disabled => $disabled) : ()),
301             ($onclick ? (onclick => $onclick) : ()),
302             }
303             };
304             }
305             else {
306             return {
307             submit_button => {
308             name => $name,
309             value => $value,
310             index => $index,
311             ($disabled ? (disabled => $disabled) : ()),
312             ($onclick ? (onclick => $onclick) : ()),
313             }
314             };
315             }
316             }
317              
318             sub button ($;$$) {
319             my ($name, $value, $index) = @_;
320            
321             my ($package) = caller;
322            
323             no strict 'refs';
324            
325             my $ctxt = ${"${package}::_form_ctxt"};
326             my $params = $ctxt->{Form};
327            
328             # TODO: What do we want buttons to do?
329             }
330              
331             sub checkbox ($;$$$$$$$$) {
332             my ($name, $value, $checked, $label, $index, $onval, $onload,
333             $disabled, $onclick) = @_;
334              
335             my ($package) = caller;
336             $value = 1 unless $value;
337            
338             no strict 'refs';
339            
340             my $ctxt = ${"${package}::_form_ctxt"};
341            
342             my $params = $ctxt->{Form};
343             my $fname = $ctxt->{Name};
344            
345             my $error;
346            
347             # validate
348             if ($params->{"__submitting_$fname"}) {
349             if (my $sub = $package->can($onval || "validate_${name}")) {
350             eval {
351             $sub->($ctxt, ($params->get($name.$index))[-1], $index);
352             $params->{$name.$index} = ($params->get($name.$index))[-1];
353             };
354             $error = $@;
355             $ctxt->{_Failed}++ if $error;
356             $error =~ s/(.*) at .*? line \d+\.$/$1/;
357             }
358             }
359             # load
360             elsif (my $sub = $package->can($onload || "load_${name}")) {
361             my @vals = $sub->($ctxt, $value, ($params->get($name.$index))[-1], $index);
362             $checked = shift @vals;
363             $value = shift @vals if @vals;
364             }
365             else {
366             $checked = 1 if defined(($params->get($name.$index))[-1]);
367             }
368            
369             if ($checked && $checked eq 'yes') {
370             $checked = 1;
371             }
372             elsif ($checked && $checked eq 'no') {
373             $checked = 0;
374             }
375            
376             return {
377             checkbox => {
378             name => $name,
379             value => $value,
380             ( $checked ? (checked => "checked") : () ),
381             label => $label,
382             ( $error ? (error => $error) : () ),
383             index => $index,
384             ($disabled ? (disabled => $disabled) : ()),
385             ($onclick ? (onclick => $onclick) : ()),
386             }
387             };
388             }
389              
390             sub file_upload ($;$$$$$$) {
391             my ($name, $value, $accept, $onval, $onload, $disabled, $onclick) = @_;
392             my ($package) = caller;
393            
394             no strict 'refs';
395            
396             my $ctxt = ${"${package}::_form_ctxt"};
397            
398             my $params = $ctxt->{Form};
399             my $fname = $ctxt->{Name};
400            
401             my $error;
402            
403             # validate
404             if ($params->{"__submitting_$fname"}) {
405             if (my $sub = $package->can($onval || "validate_${name}")) {
406             my $upload = Apache::Request->instance(Apache->request)->upload($name);
407            
408             my $filename;
409             if ($upload) {
410             $filename = $upload->filename;
411             $filename =~ s/.*[\\\/]//; # strip to just a filename
412             $filename =~ s/[^\w\.-]//g; # strip non-word chars
413             }
414            
415             eval {
416             $sub->($ctxt,
417             ($upload ?
418             ( $filename,
419             $upload->fh,
420             $upload->size,
421             $upload->type,
422             $upload->info
423             ) :
424             ()
425             )
426             );
427             };
428             $error = $@;
429             $ctxt->{_Failed}++ if $error;
430             $error =~ s/(.*) at .*? line \d+\.$/$1/;
431             }
432             }
433             # load
434             elsif (my $sub = $package->can($onload || "load_${name}")) {
435             $params->{$name} = $sub->($ctxt, $value, $params->{$name});
436             }
437             else {
438             $params->{$name} = $value;
439             }
440            
441             return {
442             file_upload => {
443             name => $name,
444             value => $params->{$name},
445             accept => $accept,
446             ($disabled ? (disabled => $disabled) : ()),
447             ($onclick ? (onclick => $onclick) : ()),
448             ($error ? (error => $error) : ()),
449             }
450             };
451             }
452              
453             sub hidden ($;$$$) {
454             my ($name, $value, $index, $onload) = @_;
455             my ($package) = caller;
456            
457             no strict 'refs';
458            
459             my $ctxt = ${"${package}::_form_ctxt"};
460             my $params = $ctxt->{Form};
461             my $fname = $ctxt->{Name};
462              
463             if (!defined($value) && $package->can($onload || "load_${name}")) {
464             # load value if not defined
465             my $sub = $package->can($onload || "load_${name}");
466             $value = $sub->($ctxt, $value, $index);
467             }
468             if ($params->{"__submitting_$fname"} && ($value ne ($params->get($name.$index))[-1])) {
469             die "Someone tried to change your hidden form value!";
470             }
471              
472             return {
473             hidden => {
474             name => $name,
475             value => $value,
476             index => $index,
477             }
478             };
479             }
480              
481             sub multi_select ($;$$$$$$$) {
482             my ($name, $default, $index, $onval, $onload, $disabled, $onclick, $option) = @_;
483             my ($package) = caller;
484            
485             no strict 'refs';
486            
487             my $ctxt = ${"${package}::_form_ctxt"};
488            
489             my $params = $ctxt->{Form};
490             my $fname = $ctxt->{Name};
491            
492             my $error;
493             my ($selected, @options);
494            
495             # validate
496             if ($params->{"__submitting_$fname"}) {
497             if (my $sub = $package->can($onval || "validate_${name}")) {
498             eval {
499             $sub->($ctxt, [$params->get($name.$index)], $index);
500             };
501             $error = $@;
502             $ctxt->{_Failed}++ if $error;
503             $error =~ s/(.*) at .*? line \d+\.$/$1/;
504             }
505             }
506             # load
507             if (my $sub = $package->can($onload || "load_${name}")) {
508             ($selected, @options) = $sub->($ctxt, [$params->get($name.$index)], $default, $index);
509             }
510             else {
511             $selected = [@{$default}];
512             @options = map { $$_{name}, $$_{value} } @{$option};
513             }
514            
515             my %selected = map { $_ => 1 } @$selected;
516            
517             my (@keys, @vals);
518             while (@options) {
519             my ($val, $key) = splice(@options, 0, 2);
520             push @keys, $key;
521             push @vals, $val;
522             }
523            
524             return {
525             multi_select => {
526             name => $name,
527             ($error ? ( error => $error ) : ()),
528             index => $index,
529             ($disabled ? (disabled => $disabled) : ()),
530             ($onclick ? (onclick => $onclick) : ()),
531             options => [
532             map {
533             {
534             ( ( $selected{$_} ) ? (selected => "selected") : () ),
535             value => $_,
536             text => shift(@vals),
537             }
538             } @keys,
539             ],
540             }
541             };
542             }
543              
544             sub password ($;$$$$$$$$) {
545             my ($name, $default, $width, $maxlength, $index, $onval, $onload,
546             $disabled, $onchange) = @_;
547             my ($package) = caller;
548            
549             no strict 'refs';
550            
551             my $ctxt = ${"${package}::_form_ctxt"};
552            
553             my $params = $ctxt->{Form};
554             my $fname = $ctxt->{Name};
555            
556             my $error;
557            
558             # validate
559             if ($params->{"__submitting_$fname"}) {
560             if (my $sub = $package->can($onval || "validate_${name}")) {
561             eval {
562             $sub->($ctxt, ($params->get($name.$index))[-1], $index);
563             $params->{$name.$index} = ($params->get($name.$index))[-1];
564             };
565             $error = $@;
566             $ctxt->{_Failed}++ if $error;
567             $error =~ s/(.*) at .*? line \d+\.$/$1/;
568             }
569             }
570             # load
571             elsif (my $sub = $package->can($onload || "load_${name}")) {
572             $params->{$name.$index} = $sub->($ctxt, $default, ($params->get($name.$index))[-1], $index);
573             }
574             else {
575             $params->{$name.$index} = $default;
576             }
577            
578             return {
579             password => {
580             width => $width,
581             maxlength => $maxlength,
582             name => $name,
583             value => ($params->get($name.$index))[-1],
584             ($error ? (error => $error) : ()),
585             index => $index,
586             ($disabled ? (disabled => $disabled) : ()),
587             ($onchange ? (onchange => $onchange) : ()),
588             }
589             };
590             }
591              
592             sub radio {
593             die "NOT YET IMPLEMENTED";
594             }
595              
596             sub reset ($;$) {
597             my ($name, $value) = @_;
598            
599             return {
600             reset => {
601             name => $name,
602             ( $value ? (value => $value) : () ),
603             }
604             };
605             }
606              
607             sub single_select ($;$$$$$$$) {
608             my ($name, $default, $index, $onval, $onload,
609             $disabled, $onchange, $option) = @_;
610              
611             my ($package) = caller;
612            
613             no strict 'refs';
614            
615             my $ctxt = ${"${package}::_form_ctxt"};
616            
617             my $params = $ctxt->{Form};
618             my $fname = $ctxt->{Name};
619            
620             my $error;
621             my ($selected, @options);
622            
623             # validate
624             if ($params->{"__submitting_$fname"}) {
625             if (my $sub = $package->can($onval || "validate_${name}")) {
626             eval {
627             $sub->($ctxt, ($params->get($name.$index))[-1], $index);
628             $params->{$name.$index} = ($params->get($name.$index))[-1];
629             };
630             $error = $@;
631             $ctxt->{_Failed}++ if $error;
632             $error =~ s/(.*) at .*? line \d+\.$/$1/;
633             }
634             }
635             # load
636             if (my $sub = $package->can($onload || "load_${name}")) {
637             ($selected, @options) = $sub->($ctxt, ($params->get($name.$index))[-1], $default, $index);
638             }
639             else {
640             $selected = $default;
641             @options = map { $$_{name}, $$_{value} } @{$option};
642             }
643            
644             my (@keys, @vals);
645             while (@options) {
646             my ($val, $key) = splice(@options, 0, 2);
647             push @keys, $key;
648             push @vals, $val;
649             }
650            
651             return {
652             single_select => {
653             name => $name,
654             ($error ? ( error => $error ) : ()),
655             index => $index,
656             ($disabled ? (disabled => $disabled) : ()),
657             ($onchange ? (onchange => $onchange) : ()),
658             options => [
659             map {
660             {
661             ( ($selected eq $_) ? (selected => "selected") : () ),
662             value => $_,
663             text => shift(@vals),
664             }
665             } @keys,
666             ],
667             }
668             };
669             }
670              
671             sub textarea ($;$$$$$$$$$) {
672             my ($name, $cols, $rows, $wrap, $default, $index, $onval, $onload,
673             $disabled, $onchange) = @_;
674            
675             my ($package) = caller;
676            
677             no strict 'refs';
678            
679             my $ctxt = ${"${package}::_form_ctxt"};
680            
681             my $params = $ctxt->{Form};
682             my $fname = $ctxt->{Name};
683            
684             my $error;
685            
686             # validate
687             if ($params->{"__submitting_$fname"}) {
688             if (my $sub = $package->can($onval || "validate_${name}")) {
689             eval {
690             $sub->($ctxt, ($params->get($name.$index))[-1], $index);
691             $params->{$name.$index} = ($params->get($name.$index))[-1];
692             };
693             $error = $@;
694             $ctxt->{_Failed}++ if $error;
695             $error =~ s/(.*) at .*? line \d+\.$/$1/;
696             }
697             }
698             # load
699             elsif (my $sub = $package->can($onload || "load_${name}")) {
700             $params->{$name.$index} = $sub->($ctxt, $default, ($params->get($name.$index))[-1], $index);
701             }
702             else {
703             $params->{$name.$index} = $default;
704             }
705            
706             if ($wrap) {
707             if ($wrap eq 'no') {
708             undef $wrap;
709             }
710             if ($wrap ne 'yes' && $wrap ne 'y') {
711             undef $wrap;
712             }
713             }
714            
715             return {
716             textarea => {
717             cols => $cols,
718             rows => $rows,
719             ($wrap ? (wrap => 'wrap') : ()),
720             name => $name,
721             value => $params->{$name.$index},
722             ($error ? (error => $error) : ()),
723             index => $index,
724             ($disabled ? (disabled => $disabled) : ()),
725             ($onchange ? (onchange => $onchange) : ()),
726             }
727             };
728             }
729              
730             1;
731             __END__