File Coverage

CGI/AppBuilder/Form.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package CGI::AppBuilder::Form;
2              
3             # Perl standard modules
4 1     1   30296 use strict;
  1         2  
  1         39  
5 1     1   5 use warnings;
  1         2  
  1         30  
6 1     1   2416 use Getopt::Std;
  1         48  
  1         66  
7 1     1   841 use POSIX qw(strftime);
  1         8840  
  1         6  
8 1     1   1248 use Carp;
  1         2  
  1         53  
9 1     1   11660 use CGI qw(:standard);
  1         25689  
  1         8  
10 1     1   5690 use CGI::AppBuilder;
  0            
  0            
11             use CGI::AppBuilder::Message qw(:echo_msg);
12              
13             our $VERSION = 0.10;
14             require Exporter;
15             our @ISA = qw(Exporter CGI::AppBuilder);
16             our @EXPORT = qw();
17             our @EXPORT_OK = qw(disp_form replace_named_variables
18             explode_variable explode_html
19             );
20             our %EXPORT_TAGS = (
21             form => [qw(disp_form)],
22             all => [@EXPORT_OK]
23             );
24              
25             =head1 NAME
26              
27             CGI::AppBuilder::Form - Configuration initializer
28              
29             =head1 SYNOPSIS
30              
31             use CGI::AppBuilder::Form;
32              
33             my $ab = CGI::AppBuilder::Form->new(
34             'ifn', 'my_init.cfg', 'opt', 'vhS:a:');
35             my ($q, $ar, $ar_log) = $ab->start_app($0, \%ARGV);
36             print $ab->disp_form($q, $ar);
37              
38             =head1 DESCRIPTION
39              
40             This class provides methods for reading and parsing configuration
41             files.
42              
43             =cut
44              
45             =head2 new (ifn => 'file.cfg', opt => 'hvS:')
46              
47             This is a inherited method from CGI::AppBuilder. See the same method
48             in CGI::AppBuilder for more details.
49              
50             =cut
51              
52             sub new {
53             my ($s, %args) = @_;
54             return $s->SUPER::new(%args);
55             }
56              
57             =head2 disp_form ($q, $ar)
58              
59             Input variables:
60              
61             $q - CGI object
62             $ar - array ref for parameters
63              
64             Variables used or routines called:
65              
66             CGI::AppBuilder::Message
67             echo_msg - echo messages
68             set_param - get a parameter from hash array
69             CGI::AppBuilder::Config
70             eval_variables - replace value names with their values.
71              
72             How to use:
73              
74             my $ifn = 'myConfig.ini';
75             my ($q,$ar) = $s->get_inputs($ifn);
76             $self->disp_form($q, $ar);
77              
78             Return: none
79              
80             This method expects the following varialbes in $ar:
81              
82             gk - GUI key items
83             gi - GUI items
84             gc - GUI columns
85             gf - GUI form
86             db - database connection varialbes (optional)
87             vars_keep - variables separated by comma for hidden variables
88             hr_form - hash ref containing attributes for
such as
89             -target = "main"
90              
91             This method performs the following tasks:
92              
93             1) checks whether GI, GC and GF variables being defined.
94             2) replaces AR, DB, GI, and GC variables with their contents
95             3) builds GF elements
96             4) add hidden variables
97             5) print the form
98              
99             =cut
100              
101             sub disp_form {
102             my $s = shift;
103             my ($q, $ar) = @_;
104              
105             # check required GUI variables
106             foreach my $k (split /,/, 'gi,gc,gf') {
107             # $s->echo_msg(" checking $k...", 3);
108             next if exists $ar->{$k};
109             print h1("GUI element - {$k} is not defined");
110             return;
111             }
112             if ($ar->{gi} =~ /db->/ && ! exists $ar->{db}) {
113             print h1("GUI element - {db} is not defined");
114             return;
115             }
116             my $mvs = {};
117             $mvs = $s->eval_variables($ar->{gk}, $ar) if exists $ar->{gk};
118             $mvs = $s->eval_variables($ar->{gi}, $ar) if exists $ar->{gi};
119             $mvs = $s->eval_variables($ar->{gc}, $ar) if exists $ar->{gc};
120             $mvs = $s->eval_variables($ar->{gf}, $ar) if exists $ar->{gf};
121              
122             my $db = (exists $ar->{db} && $ar->{db}) ? $ar->{db} : {};
123             my $pr = {ar=>$ar, db=>$db};
124             $s->replace_named_variables($ar, 'ar,db,gk,gi,gc','gk,gi,gc,gf');
125              
126             my $gk = $s->explode_variable($ar, 'gk', $pr);
127             $pr->{gk} = $gk;
128             my $gi = $s->explode_variable($ar, 'gi', $pr);
129             $pr->{gi} = $gi;
130              
131             # my $gi = eval $ar->{gi};
132             if ($gi !~ /HASH/) {
133             $s->echo_msg($ar->{gi},2);
134             $s->echo_msg("GI not properly defined." ,1);
135             } else {
136             $s->explode_html($gi, $pr);
137             }
138             # my $gc = eval $ar->{gc};
139             my $gc = $s->explode_variable($ar, 'gc', $pr);
140             $pr->{gc} = $gc;
141             if ($gc !~ /HASH/ || ! exists $gc->{td}) {
142             $s->echo_msg($ar->{gc},2);
143             $s->echo_msg("GC not properly defined." ,1);
144             } else {
145             $s->echo_msg($ar->{gc},5);
146             $s->echo_msg($gc,5);
147             }
148             $s->echo_msg($ar->{gf},5);
149             # my $gf = eval $ar->{gf};
150             my $gf = $s->explode_variable($ar, 'gf', $pr);
151              
152             my $fmn = 'fm1';
153             $fmn = $ar->{form_name}
154             if exists $ar->{form_name} && $ar->{form_name};
155             print "
\n";
156             my %fr = (-name => $fmn, -method=>uc $ar->{method},
157             -action=>"$ar->{action}?", -enctype=>$ar->{encoding} );
158             if (exists $ar->{hr_form} && $ar->{hr_form}) {
159             foreach my $k (keys %{$ar->{hr_form}}) {
160             $fr{$k} = $ar->{hr_form}{$k};
161             }
162             }
163             print start_form(%fr);
164             my $hvs = $s->set_param('vars_keep', $ar);
165             if ($hvs) {
166             foreach my $k (split /,/, $hvs) {
167             my $v = $s->set_param($k, $ar);
168             next if $v =~ /^\s*$/;
169             print hidden($k,$v);
170             }
171             }
172             print "$gf\n";
173             print end_form;
174             print "\n";
175             return;
176             }
177              
178             =head2 explode_html ($gi, $pr)
179              
180             Input variables:
181              
182             $gi - a hash ref
183             $pr - a parameter hash ref
184              
185             Variables used or routines called:
186              
187             CGI::AppBuilder::Message
188             echo_msg - echo messages
189              
190             How to use:
191              
192             my $ifn = 'myConfig.ini';
193             my ($q,$ar) = $s->get_inputs($ifn);
194             $self->explote_html($ar->{gi}, $ar);
195              
196             Return: none
197              
198             This method enables a 'x' command in your GUI definition and
199             processes the complex elements in the hash ref. For
200             instance, you have a GUI hash:
201              
202             gi = { # GUI Items
203             rts => ['rpt_src',['DataFax Generic','Study Specific'],
204             'DataFax Generic'],
205             xtd_rts => 'radio_group',
206             act1 => td('Action'),
207             act2 => td({-colspan=>'2',-align=>'center'},
208             gk->{opf} . submit('a','Go') . ' ' . submit('a','Update') .
209             ' ' . reset() ),
210             xcp_act => 'act1,act2',
211             act => submit('a','Go') . ' ' . reset(),
212             }
213              
214             and the method will copy (xcp_act) the results (HTML text)
215             of $gi->{act1} and and $gi->{act2} into one. The $gi->{xcp_act}
216             will contains the combined string.
217              
218             The 'xtd_' instructs the method to use $gi->{rts} as arguments for
219             the method name in $gi->{xtd_rts}.
220              
221             =cut
222              
223             sub explode_html {
224             my $s = shift;
225             my ($gi, $pr) = @_;
226              
227             my $ar = (exists $pr->{ar}) ? $pr->{ar} : {};
228             my $gk = (exists $pr->{gk}) ? $pr->{gk} : {};
229             my $gc = (exists $pr->{gc}) ? $pr->{gc} : {};
230             my $db = (exists $pr->{db}) ? $pr->{db} : {};
231             foreach my $k (keys %$gi) {
232             next if ($k !~ /^x(td|cp)_(.+)/i);
233             my ($k1, $k2) = ($1, $2);
234             if ($k1 =~ /^td/i) {
235             my $tmp_ar = [];
236             if (ref($gi->{$k2}) =~ /ARRAY/) {
237             $tmp_ar = $gi->{$k2};
238             } else {
239             $tmp_ar = eval $gi->{$k2};
240             }
241             if ($gi->{$k} =~ /^radio_group/i) {
242             $gi->{$k} = radio_group(@$tmp_ar);
243             } elsif ($gi->{$k} =~ /^popup_menu/i) {
244             $gi->{$k} = popup_menu(@$tmp_ar);
245             } else {
246             $gi->{$k} = td(@$tmp_ar);
247             }
248             } else {
249             my $txt = "";
250             foreach my $i (split /,/, $gi->{$k}) {
251             $txt .= $gi->{$i};
252             }
253             $gi->{$k} = $txt;
254             }
255             }
256             $s->echo_msg($gi,5);
257             return;
258             }
259              
260             =head2 explode_variable ($xr, $i, $pr)
261              
262             Input variables:
263              
264             $xr - a hash ref such as the elements of gi,gk,gc,gf in
265             GUI hash array
266             $i - one of gi, gk, gc and gf
267             $pr - a parameter hash ref containing the values for $i to be
268             used in $xr
269              
270             Variables used or routines called:
271              
272             CGI::AppBuilder::Message
273             echo_msg - echo messages
274              
275             How to use:
276              
277             my $ifn = 'myConfig.ini';
278             my ($q,$ar) = $s->get_inputs($ifn);
279             my $gi = $self->explode_variable($ar, 'gi', $ar);
280             my $gc = $self->explode_variable($ar, 'gc', $ar);
281              
282             Return: hash or hash ref for $i.
283              
284             This method replaces variable names with their values and HTML
285             commands with their results.
286              
287             =cut
288              
289             sub explode_variable {
290             my $s = shift;
291             my ($xr, $i, $pr) = @_;
292             my $hr = {};
293             return wantarray ? %$hr : $hr if ! exists $xr->{$i};
294            
295             my $ar = (exists $pr->{ar}) ? $pr->{ar} : {};
296             my $gi = (exists $pr->{gi}) ? $pr->{gi} : {};
297             my $gk = (exists $pr->{gk}) ? $pr->{gk} : {};
298             my $gc = (exists $pr->{gc}) ? $pr->{gc} : {};
299             my $db = (exists $pr->{db}) ? $pr->{db} : {};
300             if (ref($xr->{$i}) =~ /HASH/) {
301             foreach my $k (keys %{$xr->{$i}}) {
302             if (ref($xr->{$i}{$k}) =~ /^ARRAY/) {
303             for my $j (0..$#{$xr->{$i}{$k}}) {
304             $hr->{$k}[$j] =
305             (ref($xr->{$i}{$k}[$j]) =~ /^(ARRAY|HASH)/) ?
306             $xr->{$i}{$k}[$j] : eval $xr->{$i}{$k}[$j];
307             }
308             } elsif (ref($xr->{$i}{$k}) =~ /^HASH/) {
309             foreach my $j (keys %{$xr->{$i}{$k}}) {
310             $hr->{$k}{$j} =
311             (ref($xr->{$i}{$k}{$j}) =~ /^(ARRAY|HASH)/) ?
312             $xr->{$i}{$k}{$j} : eval $xr->{$i}{$k}{$j};
313             }
314             } else {
315             $hr->{$k} = ($k =~ /^x(td|cp)/i) ? $xr->{$i}{$k} :
316             eval $xr->{$i}{$k};
317             }
318             }
319             } else {
320             $hr = eval $xr->{$i};
321             }
322             $s->echo_msg($hr,5);
323             return wantarray ? %$hr : $hr;
324             }
325              
326             =head2 replace_named_variables ($ar, $vs, $ks)
327              
328             Input variables:
329              
330             $ar - a hash ref containing the elements of gi,gk,gc,gf in
331             GUI hash array
332             $vs - a list of variable names separated by comma such as
333             'ar,db,gi,gk,gc'
334             $ks - a list of key elements separated by comma such as
335             'gk,gi,gc,gf'
336              
337             Variables used or routines called:
338              
339             None
340              
341             How to use:
342              
343             my $ifn = 'myConfig.ini';
344             my ($q,$ar) = $s->get_inputs($ifn);
345             $self->replace_named_variables($ar, 'ar,db,gk,gi,gc','gk,gi,gc,gf');
346              
347             Return: None.
348              
349             This method replaces named variables with their values in $ar.
350              
351             =cut
352              
353             sub replace_named_variables {
354             my $s = shift;
355             my ($ar, $vs, $ks) = @_;
356              
357             return if !$vs || !$ks;
358             $vs =~ s/\s+//g; $ks =~ s/\s+//g; # remove any blanks
359              
360             foreach my $v (split /,/, $vs) { # variables: ar,db,gk,gi,gc
361             foreach my $k (split /,/, $ks) { # keys: gk,gi,gc,gf
362             next if ! exists $ar->{$k};
363             $ar->{$k} =~ s/$v\->/\$$v->/g if ref($ar->{$k}) !~ /^HASH/;
364             next if ref($ar->{$k}) !~ /^HASH/;
365             foreach my $i (keys %{$ar->{$k}}) {
366             if (ref($ar->{$k}{$i}) !~ /^(ARRAY|HASH)/) {
367             $ar->{$k}{$i} =~ s/$v\->/\$$v->/g;
368             next;
369             }
370             if (ref($ar->{$k}{$i}) =~ /^ARRAY/) {
371             for my $j (0..$#{$ar->{$k}{$i}}) {
372             $ar->{$k}{$i}[$j] =~ s/$v\->/\$$v->/g;
373             }
374             } else {
375             for my $j (keys %{$ar->{$k}{$i}}) {
376             $ar->{$k}{$i}{$j} =~ s/$v\->/\$$v->/g;
377             }
378             }
379             }
380             }
381             }
382             return;
383             }
384              
385             1;
386              
387             =head1 HISTORY
388              
389             =over 4
390              
391             =item * Version 0.10
392              
393             This version extracts the disp_form method from CGI::Getopt class,
394             inherits the new constructor from CGI::AppBuilder, and adds
395             new methods of replace_named_variables, explode_variable, and
396             explode_html.
397              
398             =item * Version 0.20
399              
400             =cut
401              
402             =head1 SEE ALSO (some of docs that I check often)
403              
404             Oracle::Loader, Oracle::Trigger, CGI::Getopt, File::Xcopy,
405             CGI::AppBuilder, CGI::AppBuilder::Message, CGI::AppBuilder::Log,
406             CGI::AppBuilder::Config, etc.
407              
408             =head1 AUTHOR
409              
410             Copyright (c) 2005 Hanming Tu. All rights reserved.
411              
412             This package is free software and is provided "as is" without express
413             or implied warranty. It may be used, redistributed and/or modified
414             under the terms of the Perl Artistic License (see
415             http://www.perl.com/perl/misc/Artistic.html)
416              
417             =cut
418