File Coverage

blib/lib/Text/FormBuilder.pm
Criterion Covered Total %
statement 108 227 47.5
branch 18 96 18.7
condition 7 40 17.5
subroutine 15 22 68.1
pod 8 8 100.0
total 156 393 39.6


line stmt bran cond sub pod time code
1             package Text::FormBuilder;
2              
3 1     1   13643 use strict;
  1         1  
  1         24  
4 1     1   3 use warnings;
  1         1  
  1         25  
5              
6 1     1   4 use base qw(Exporter Class::ParseText::Base);
  1         4  
  1         426  
7 1     1   4 use vars qw($VERSION @EXPORT);
  1         1  
  1         47  
8              
9             $VERSION = '0.09_01';
10             @EXPORT = qw(create_form);
11              
12 1     1   3 use Carp;
  1         1  
  1         42  
13 1     1   2045 use Text::FormBuilder::Parser;
  1         1  
  1         31  
14 1     1   668 use CGI::FormBuilder;
  1         15812  
  1         1487  
15              
16             # the static default options passed to CGI::FormBuilder->new
17             my %DEFAULT_OPTIONS = (
18             method => 'GET',
19             javascript => 0,
20             keepextras => 1,
21             );
22              
23             # the built in CSS for the template
24             my $DEFAULT_CSS = <
25             table { padding: 1em; }
26             #author, #footer { font-style: italic; }
27             caption h2 { padding: .125em .5em; background: #ccc; text-align: left; }
28             th { text-align: left; }
29             th h3 { padding: .125em .5em; background: #eee; }
30             th.label { font-weight: normal; text-align: right; vertical-align: top; }
31             td ul { list-style: none; padding-left: 0; margin-left: 0; }
32             .note { background: #eee; }
33             .sublabel { color: #999; }
34             .invalid { background: red; }
35             END
36              
37             # default messages that can be localized
38             my %DEFAULT_MESSAGES = (
39             text_author => 'Created by %s',
40             text_madewith => 'Made with %s version %s',
41             text_required => '(Required fields are marked in bold.)',
42             text_invalid => 'Missing or invalid value.',
43             );
44              
45             my $DEFAULT_CHARSET = 'iso-8859-1';
46              
47             # options to clean up the code with Perl::Tidy
48             my $TIDY_OPTIONS = '-nolq -ci=4 -ce';
49              
50             my $HTML_EXTS = qr/\.html?$/;
51             my $MODULE_EXTS = qr/\.pm$/;
52             my $SCRIPT_EXTS = qr/\.(pl|cgi)$/;
53              
54             # superautomagical exported function
55             sub create_form {
56 0     0 1 0 my ($source, $options, $destination) = @_;
57 0         0 my $parser = __PACKAGE__->parse($source);
58 0 0       0 $parser->build(%{ $options || {} });
  0         0  
59 0 0       0 if ($destination) {
60 0 0       0 if (ref $destination) {
61 0         0 croak '[' . (caller(0))[3] . "] Don't know what to do with a ref for $destination";
62             #TODO: what DO ref dests mean?
63             } else {
64             # write webpage, script, or module
65 0 0       0 if ($destination =~ $MODULE_EXTS) {
    0          
66 0         0 $parser->write_module($destination, 1);
67             } elsif ($destination =~ $SCRIPT_EXTS) {
68 0         0 $parser->write_script($destination, 1);
69             } else {
70 0         0 $parser->write($destination);
71             }
72             }
73             } else {
74 0 0       0 defined wantarray ? return $parser->form : $parser->write;
75             }
76             }
77              
78             # subclass of Class::ParseText::Base
79             sub init {
80 3     3 1 73 my $self = shift;
81 3         16 $self->{parser} = Text::FormBuilder::Parser->new;
82 3         6 $self->{start_rule} = 'form_spec';
83 3         7 $self->{ensure_newline} = 1;
84 3         7 return $self;
85             }
86              
87             # this is where a lot of the magic happens
88             sub build {
89 3     3 1 6 my ($self, %options) = @_;
90            
91             # our custom %options:
92             # form_only: use only the form part of the template
93 3         3 my $form_only = $options{form_only};
94            
95             # css, extra_css: allow for custom inline stylesheets
96             # neat trick: css => '@import(my_external_stylesheet.css);'
97             # will let you use an external stylesheet
98             # CSS Hint: to get multiple sections to all line up their fields,
99             # set a standard width for th.label
100 3         5 my $css;
101 3   33     12 $css = $options{css} || $DEFAULT_CSS;
102 3 50       10 $css .= $options{extra_css} if $options{extra_css};
103            
104             # messages
105             # code pulled (with modifications) from CGI::FormBuilder
106 3 50       8 if ($options{messages}) {
107             # if its a hashref, we'll just pass it on to CGI::FormBuilder
108            
109 0 0       0 if (my $ref = ref $options{messages}) {
110             # hashref pass on to CGI::FormBuilder
111 0 0       0 croak "[Text::FormBuilder] Argument to 'messages' option must be a filename or hashref" unless $ref eq 'HASH';
112 0         0 while (my ($key,$value) = each %DEFAULT_MESSAGES) {
113 0   0     0 $options{messages}{$key} ||= $DEFAULT_MESSAGES{$key};
114             }
115             } else {
116             # filename, just *warn* on missing, and use defaults
117 0 0 0     0 if (-f $options{messages} && -r _ && open(MESSAGES, "< $options{messages}")) {
      0        
118 0         0 $options{messages} = { %DEFAULT_MESSAGES };
119 0         0 while() {
120 0 0 0     0 next if /^\s*#/ || /^\s*$/;
121 0         0 chomp;
122 0         0 my($key,$value) = split ' ', $_, 2;
123 0         0 ($options{messages}{$key} = $value) =~ s/\s+$//;
124             }
125 0         0 close MESSAGES;
126             } else {
127 0         0 carp '[' . (caller(0))[3] . "] Could not read messages file $options{messages}: $!";
128             }
129             }
130             } else {
131 3         18 $options{messages} = { %DEFAULT_MESSAGES };
132             }
133            
134             # character set
135 3         6 my $charset = $options{charset};
136            
137             # save the build options so they can be used from write_module
138 3         8 $self->{build_options} = { %options };
139            
140             # remove our custom options before we hand off to CGI::FormBuilder
141 3         17 delete $options{$_} foreach qw(form_only css extra_css charset);
142            
143             # expand groups
144 3 50       3 if (my %groups = %{ $self->{form_spec}{groups} || {} }) {
  3 50       15  
145 0 0       0 for my $section (@{ $self->{form_spec}{sections} || [] }) {
  0         0  
146 0         0 foreach (grep { $$_[0] eq 'group' } @{ $$section{lines} }) {
  0         0  
  0         0  
147 0         0 $$_[1]{group} =~ s/^\%//; # strip leading % from group var name
148            
149 0 0       0 if (exists $groups{$$_[1]{group}}) {
150 0         0 my @fields; # fields in the group
151 0         0 push @fields, { %$_ } foreach @{ $groups{$$_[1]{group}} };
  0         0  
152 0         0 for my $field (@fields) {
153 0   0     0 $$field{label} ||= ucfirst $$field{name};
154 0         0 $$field{name} = "$$_[1]{name}_$$field{name}";
155             }
156 0   0     0 $_ = [ 'group', { label => $$_[1]{label} || ucfirst(join(' ',split('_',$$_[1]{name}))), group => \@fields } ];
157             }
158             }
159             }
160             }
161            
162             # the actual fields that are given to CGI::FormBuilder
163             # make copies so that when we trim down the sections
164             # we don't lose the form field information
165 3         9 $self->{form_spec}{fields} = [];
166            
167 3 50       4 for my $section (@{ $self->{form_spec}{sections} || [] }) {
  3         10  
168 1         2 for my $line (@{ $$section{lines} }) {
  1         2  
169 3 50       9 if ($$line[0] eq 'group') {
    50          
170 0         0 push @{ $self->{form_spec}{fields} }, { %{$_} } foreach @{ $$line[1]{group} };
  0         0  
  0         0  
  0         0  
171             } elsif ($$line[0] eq 'field') {
172 3         2 push @{ $self->{form_spec}{fields} }, { %{$$line[1]} };
  3         4  
  3         14  
173             }
174             }
175             }
176            
177             # substitute in custom validation subs and pattern definitions for field validation
178 3 50       4 my %patterns = %{ $self->{form_spec}{patterns} || {} };
  3         10  
179 3 50       4 my %subs = %{ $self->{form_spec}{subs} || {} };
  3         8  
180            
181 3         3 foreach (@{ $self->{form_spec}{fields} }) {
  3         8  
182 3 50       6 if ($$_{validate}) {
183 0 0       0 if (exists $patterns{$$_{validate}}) {
    0          
184 0         0 $$_{validate} = $patterns{$$_{validate}};
185             # TODO: need the Data::Dumper code to work for this
186             # for now, we just warn that it doesn't work
187             } elsif (exists $subs{$$_{validate}}) {
188 0         0 warn '[' . (caller(0))[3] . "] validate coderefs don't work yet";
189 0         0 delete $$_{validate};
190             ## $$_{validate} = $subs{$$_{validate}};
191             }
192             }
193             }
194            
195             # get user-defined lists; can't make this conditional because
196             # we need to be able to fall back to CGI::FormBuilder's lists
197             # even if the user didn't define any
198 3 50       3 my %lists = %{ $self->{form_spec}{lists} || {} };
  3         11  
199            
200             # substitute in list names
201 3         3 foreach (@{ $self->{form_spec}{fields} }) {
  3         7  
202 3 50       7 next unless $$_{list};
203            
204 0         0 $$_{list} =~ s/^\@//; # strip leading @ from list var name
205            
206             # a hack so we don't get screwy reference errors
207 0 0       0 if (exists $lists{$$_{list}}) {
208 0         0 my @list;
209 0         0 push @list, { %$_ } foreach @{ $lists{$$_{list}} };
  0         0  
210 0         0 $$_{options} = \@list;
211             } else {
212             # assume that the list name is a builtin
213             # and let it fall through to CGI::FormBuilder
214 0         0 $$_{options} = $$_{list};
215             }
216             } continue {
217 3         2 delete $$_{list};
218             }
219            
220             # special case single-value checkboxes
221 3 50       3 foreach (grep { $$_{type} && $$_{type} eq 'checkbox' } @{ $self->{form_spec}{fields} }) {
  3         7  
  3         8  
222 0 0       0 unless ($$_{options}) {
223 0   0     0 $$_{options} = [ { $$_{name} => $$_{label} || ucfirst join(' ',split(/_/,$$_{name})) } ];
224             }
225             }
226            
227             # use the list for displaying checkbox groups
228 3         5 foreach (@{ $self->{form_spec}{fields} }) {
  3         9  
229 3 50 33     7 $$_{ulist} = 1 if ref $$_{options} and @{ $$_{options} } >= 3;
  0         0  
230             }
231            
232             # remove extraneous undefined values
233 3         3 for my $field (@{ $self->{form_spec}{fields} }) {
  3         8  
234 3   100     3 defined $$field{$_} or delete $$field{$_} foreach keys %{ $field };
  3         25  
235             }
236            
237             # remove false $$_{required} params because this messes up things at
238             # the CGI::FormBuilder::field level; it seems to be marking required
239             # based on the existance of a 'required' param, not whether it is
240             # true or defined
241 3   50     3 $$_{required} or delete $$_{required} foreach @{ $self->{form_spec}{fields} };
  3         11  
242              
243 3         4 foreach (@{ $self->{form_spec}{sections} }) {
  3         8  
244             #for my $line (grep { $$_[0] eq 'field' } @{ $$_{lines} }) {
245 1         2 for my $line (@{ $$_{lines} }) {
  1         2  
246 3 50       5 if ($$line[0] eq 'field') {
247 3         7 $$line[1] = $$line[1]{name};
248             ## $_ eq 'name' or delete $$line[1]{$_} foreach keys %{ $$line[1] };
249             ## } elsif ($$line[0] eq 'group') {
250             ## $$line[1] = [ map { $$_{name} } @{ $$line[1]{group} } ];
251             }
252             }
253             }
254            
255             $self->{form} = CGI::FormBuilder->new(
256             %DEFAULT_OPTIONS,
257             # need to explicity set the fields so that simple text fields get picked up
258 3         6 fields => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ],
  3         7  
259 0         0 required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ],
  3         8  
  3         20  
260             title => $self->{form_spec}{title},
261             text => $self->{form_spec}{description},
262             template => {
263             type => 'Text',
264             engine => {
265             TYPE => 'STRING',
266             SOURCE => $form_only ? $self->_form_template : $self->_template($css, $charset),
267             DELIMITERS => [ qw(<% %>) ],
268             },
269             data => {
270             sections => $self->{form_spec}{sections},
271             author => $self->{form_spec}{author},
272             description => $self->{form_spec}{description},
273             },
274             },
275 3 50       11 %options,
276             );
277 3         27225 $self->{form}->field(%{ $_ }) foreach @{ $self->{form_spec}{fields} };
  3         30  
  3         217  
278            
279             # mark structures as built
280 3         73 $self->{built} = 1;
281            
282 3         10 return $self;
283             }
284              
285             sub write {
286 0     0 1 0 my ($self, $outfile) = @_;
287            
288             # automatically call build if needed to
289             # allow the new->parse->write shortcut
290 0 0       0 $self->build unless $self->{built};
291            
292 0 0       0 if ($outfile) {
293 0         0 open FORM, "> $outfile";
294 0         0 print FORM $self->form->render;
295 0         0 close FORM;
296             } else {
297 0         0 print $self->form->render;
298             }
299             }
300              
301             # generates the core code to create the $form object
302             # the generated code assumes that you have a CGI.pm
303             # object named $q
304             sub _form_code {
305 0     0   0 my $self = shift;
306            
307             # automatically call build if needed to
308             # allow the new->parse->write shortcut
309 0 0       0 $self->build unless $self->{built};
310            
311             # conditionally use Data::Dumper
312 0         0 eval 'use Data::Dumper;';
313 0 0       0 die "Can't write module; need Data::Dumper. $@" if $@;
314            
315 0         0 $Data::Dumper::Terse = 1; # don't dump $VARn names
316 0         0 $Data::Dumper::Quotekeys = 0; # don't quote simple string keys
317            
318 0         0 my $css;
319 0   0     0 $css = $self->{build_options}{css} || $DEFAULT_CSS;
320 0 0       0 $css .= $self->{build_options}{extra_css} if $self->{build_options}{extra_css};
321            
322             my %options = (
323             %DEFAULT_OPTIONS,
324             title => $self->{form_spec}{title},
325             text => $self->{form_spec}{description},
326 0         0 fields => [ map { $$_{name} } @{ $self->{form_spec}{fields} } ],
  0         0  
327 0         0 required => [ map { $$_{name} } grep { $$_{required} } @{ $self->{form_spec}{fields} } ],
  0         0  
  0         0  
328             template => {
329             type => 'Text',
330             engine => {
331             TYPE => 'STRING',
332             SOURCE => $self->{build_options}{form_only} ?
333             $self->_form_template :
334             $self->_template($css, $self->{build_options}{charset}),
335             DELIMITERS => [ qw(<% %>) ],
336             },
337             data => {
338             sections => $self->{form_spec}{sections},
339             author => $self->{form_spec}{author},
340             description => $self->{form_spec}{description},
341             },
342             },
343 0 0       0 %{ $self->{build_options} },
  0         0  
344             );
345            
346             # remove our custom options
347 0         0 delete $options{$_} foreach qw(form_only css extra_css);
348            
349 0         0 my %module_subs;
350 0         0 my $d = Data::Dumper->new([ \%options ], [ '*options' ]);
351            
352 1     1   5 use B::Deparse;
  1         2  
  1         834  
353 0         0 my $deparse = B::Deparse->new;
354             ##
355             ## #TODO: need a workaround/better solution since Data::Dumper doesn't like dumping coderefs
356             ## foreach (@{ $self->{form_spec}{fields} }) {
357             ## if (ref $$_{validate} eq 'CODE') {
358             ## my $body = $deparse->coderef2text($$_{validate});
359             ## #$d->Seen({ "*_validate_$$_{name}" => $$_{validate} });
360             ## #$module_subs{$$_{name}} = "sub _validate_$$_{name} $$_{validate}";
361             ## }
362             ## }
363             ## my $sub_code = join("\n", each %module_subs);
364            
365 0 0       0 my $form_options = keys %options > 0 ? $d->Dump : '';
366            
367             my $field_setup = join(
368             "\n",
369 0         0 map { '$form->field' . Data::Dumper->Dump([$_],['*field']) . ';' } @{ $self->{form_spec}{fields} }
  0         0  
  0         0  
370             );
371            
372 0         0 return <
373             my \$form = CGI::FormBuilder->new(
374             params => \$q,
375             $form_options
376             );
377              
378             $field_setup
379             END
380             }
381              
382             sub write_module {
383 0     0 1 0 my ($self, $package, $use_tidy) = @_;
384              
385 0 0       0 croak '[' . (caller(0))[3] . '] Expecting a package name' unless $package;
386            
387             # remove a trailing .pm
388 0         0 $package =~ s/\.pm$//;
389             ## warn "[Text::FromBuilder::write_module] Removed extra '.pm' from package name\n" if $package =~ s/\.pm$//;
390            
391 0         0 my $form_code = $self->_form_code;
392            
393 0         0 my $module = <
394             package $package;
395             use strict;
396             use warnings;
397              
398             use CGI::FormBuilder;
399              
400             sub get_form {
401             my \$q = shift;
402              
403             $form_code
404            
405             return \$form;
406             }
407              
408             # module return
409             1;
410             END
411              
412 0         0 _write_output_file($module, (split(/::/, $package))[-1] . '.pm', $use_tidy);
413 0         0 return $self;
414             }
415              
416             sub write_script {
417 0     0 1 0 my ($self, $script_name, $use_tidy) = @_;
418              
419 0 0       0 croak '[' . (caller(0))[3] . '] Expecting a script name' unless $script_name;
420            
421 0         0 my $form_code = $self->_form_code;
422            
423 0         0 my $script = <
424             #!/usr/bin/perl
425             use strict;
426             use warnings;
427              
428             use CGI;
429             use CGI::FormBuilder;
430              
431             my \$q = CGI->new;
432              
433             $form_code
434            
435             unless (\$form->submitted && \$form->validate) {
436             print \$form->render;
437             } else {
438             # do something with the entered data
439             }
440             END
441            
442 0         0 _write_output_file($script, $script_name, $use_tidy);
443 0         0 return $self;
444             }
445              
446             sub _write_output_file {
447 0     0   0 my ($source_code, $outfile, $use_tidy) = @_;
448 0 0       0 if ($use_tidy) {
449             # clean up the generated code, if asked
450 0         0 eval 'use Perl::Tidy';
451 0 0       0 unless ($@) {
452 0         0 Perl::Tidy::perltidy(source => \$source_code, destination => $outfile, argv => $TIDY_OPTIONS);
453             } else {
454 0 0       0 carp '[' . (caller(0))[3] . "] Can't tidy the code: $@" if $@;
455             # fallback to just writing it as-is
456 0 0       0 open OUT, "> $outfile" or die $!;
457 0         0 print OUT $source_code;
458 0         0 close OUT;
459             }
460             } else {
461             # otherwise, just print as is
462 0 0       0 open OUT, "> $outfile" or die $!;
463 0         0 print OUT $source_code;
464 0         0 close OUT;
465             }
466             }
467              
468              
469             sub form {
470 3     3 1 5 my $self = shift;
471            
472             # automatically call build if needed to
473             # allow the new->parse->write shortcut
474 3 100       15 $self->build unless $self->{built};
475              
476 3         12 return $self->{form};
477             }
478              
479             sub _form_template {
480 3     3   3 my $self = shift;
481 3         6 my $msg_required = $self->{build_options}{messages}{text_required};
482 3         3 my $msg_invalid = $self->{build_options}{messages}{text_invalid};
483 3         40 return q{<% $description ? qq[

$description

] : '' %>
484             <% (grep { $_->{required} } @fields) ? qq[

} . $msg_required . q{

] : '' %>
485             <% $start %>
486             <%
487             # drop in the hidden fields here
488             $OUT = join("\n", map { $$_{field} } grep { $$_{type} eq 'hidden' } @fields);
489             %>} .
490             q[
491             <%
492             SECTION: while (my $section = shift @sections) {
493             $OUT .= qq[\n]; ] if $$section{head}; \n] \n] ] : qq[ ]; ]; '; "; ]; \n]; \n] : qq[ \n]; \n]; \n];
494             $OUT .= qq[

$$section{head}

495             TABLE_LINE: for my $line (@{ $$section{lines} }) {
496             if ($$line[0] eq 'head') {
497             $OUT .= qq[

$$line[1]

498             } elsif ($$line[0] eq 'note') {
499             $OUT .= qq[
$$line[1]
500             } elsif ($$line[0] eq 'field') {
501             local $_ = $field{$$line[1]};
502            
503             # skip hidden fields in the table
504             next TABLE_LINE if $$_{type} eq 'hidden';
505            
506             $OUT .= $$_{invalid} ? qq[
507            
508             # special case single value checkboxes
509             if ($$_{type} eq 'checkbox' && @{ $$_{options} } == 1) {
510             $OUT .= qq[
511             } else {
512             $OUT .= '' . ($$_{required} ? qq[$$_{label}:] : "$$_{label}:") . '
513             }
514            
515             # mark invalid fields
516             if ($$_{invalid}) {
517             $OUT .= "$$_{field} $$_{comment} ] . $msg_invalid . q[
518             } else {
519             $OUT .= qq[$$_{field} $$_{comment}
520             }
521            
522             $OUT .= qq[
523            
524             } elsif ($$line[0] eq 'group') {
525             my @group_fields = map { $field{$_} } map { $$_{name} } @{ $$line[1]{group} };
526             $OUT .= (grep { $$_{invalid} } @group_fields) ? qq[
527            
528             $OUT .= ' ';
529             $OUT .= (grep { $$_{required} } @group_fields) ? qq[$$line[1]{label}:] : "$$line[1]{label}:";
530             $OUT .= qq[\n];
531            
532             $OUT .= qq[ ];
533             $OUT .= join(' ', map { qq[$$_{label} $$_{field} $$_{comment}] } @group_fields);
534             $OUT .= " $msg_invalid" if $$_{invalid};
535              
536             $OUT .= qq[
537             $OUT .= qq[
538             }
539             }
540             # close the table if there are sections remaining
541             # but leave the last one open for the submit button
542             $OUT .= qq[
\n] if @sections;
543             }
544             %>
545            
<% $submit %>
546            
547             <% $end %> 548             ]; 549             } 550               551             # usage: $self->_pre_template($css, $charset) 552             sub _pre_template { 553 3     3   3 my $self = shift; 554 3   33     7 my $css = shift || $DEFAULT_CSS; 555 3   33     10 my $charset = shift || $DEFAULT_CHARSET; 556 3         12 my $msg_author = 'sprintf("' . quotemeta($self->{build_options}{messages}{text_author}) . '", $author)'; 557             return 558 3         18 q[ 559             560             561             <% $title %><% $author ? ' - ' . ucfirst $author : '' %> 562             564             <% $jshead %> 565             566             567               568            

<% $title %>

569             <% $author ? qq[

] . ] . $msg_author . q{ . q[

] : '' %> 570             }; 571             } 572               573             sub _post_template { 574 3     3   5 my $self = shift; 575 3         10 my $msg_madewith = 'sprintf("' . quotemeta($self->{build_options}{messages}{text_madewith}) . 576             '", q[CGI::FormBuilder], CGI::FormBuilder->VERSION)'; 577             578 3         70 return qq[
579             582             583             584             ]; 585             } 586               587             # usage: $self->_template($css, $charset) 588             sub _template { 589 3     3   4 my $self = shift; 590 3         9 return $self->_pre_template(@_) . $self->_form_template . $self->_post_template; 591             } 592               593             sub dump { 594 0     0 1   eval "use YAML;"; 595 0 0         unless ($@) { 596 0           print YAML::Dump(shift->{form_spec}); 597             } else { 598 0           warn '[' . (caller(0))[3] . "] Can't dump form spec structure using YAML: $@"; 599             } 600             } 601               602               603             # module return 604             1; 605               606             =head1 NAME 607               608             Text::FormBuilder - Create CGI::FormBuilder objects from simple text descriptions 609               610             =head1 SYNOPSIS 611               612             use Text::FormBuilder; 613             614             my $parser = Text::FormBuilder->new; 615             $parser->parse($src_file); 616             617             # returns a new CGI::FormBuilder object with 618             # the fields from the input form spec 619             my $form = $parser->form; 620             621             # write a My::Form module to Form.pm 622             $parser->write_module('My::Form'); 623               624             =head1 REQUIRES 625               626             L, 627             L, 628             L, 629             L 630               631             =head1 DESCRIPTION 632               633             This module is intended to extend the idea of making it easy to create 634             web forms by allowing you to describe them with a simple langauge. These 635             I are then passed through this module's parser and converted 636             into L objects that you can easily use in your CGI 637             scripts. In addition, this module can generate code for standalone modules 638             which allow you to separate your form design from your script code. 639               640             A simple formspec looks like this: 641               642             name//VALUE 643             email//EMAIL 644             langauge:select{English,Spanish,French,German} 645             moreinfo|Send me more information:checkbox 646             interests:checkbox{Perl,karate,bass guitar} 647               648             This will produce a required C test field, a required C text 649             field that must look like an email address, an optional select dropdown 650             field C with the choices English, Spanish, French, and German, 651             an optional C checkbox labeled ``Send me more information'', and 652             finally a set of checkboxes named C with the choices Perl, 653             karate, and bass guitar. 654               655             =head1 METHODS 656               657             =head2 new 658               659             my $parser = Text::FormBuilder->new; 660               661             =head2 parse 662               663             # parse a file (regular scalar) 664             $parser->parse($filename); 665             666             # or pass a scalar ref for parse a literal string 667             $parser->parse(\$string); 668             669             # or an array ref to parse lines 670             $parser->parse(\@lines); 671               672             Parse the file or string. Returns the parser object. This method, 673             along with all of its C siblings, may be called as a class 674             method to construct a new object. 675               676             =head2 parse_file 677               678             $parser->parse_file($src_file); 679             680             # or as a class method 681             my $parser = Text::FormBuilder->parse($src_file); 682               683             =head2 parse_text 684               685             $parser->parse_text($src); 686               687             Parse the given C<$src> text. Returns the parser object. 688               689             =head2 parse_array 690               691             $parser->parse_array(@lines); 692               693             Concatenates and parses C<@lines>. Returns the parser object. 694               695             =head2 build 696               697             $parser->build(%options); 698               699             Builds the CGI::FormBuilder object. Options directly used by C are: 700               701             =over 702               703             =item C 704               705             Only uses the form portion of the template, and omits the surrounding html, 706             title, author, and the standard footer. This does, however, include the 707             description as specified with the C directive. 708               709             =item C, C 710               711             These options allow you to tell Text::FormBuilder to use different 712             CSS styles for the built in template. A value given a C will 713             replace the existing CSS, and a value given as C will be 714             appended to the CSS. If both options are given, then the CSS that is 715             used will be C concatenated with C. 716               717             If you want to use an external stylesheet, a quick way to get this is 718             to set the C parameter to import your file: 719               720             css => '@import(my_external_stylesheet.css);' 721               722             =item C 723               724             This works the same way as the C parameter to 725             C<< CGI::FormBuilder->new >>; you can provide either a hashref of messages 726             or a filename. 727               728             The default messages used by Text::FormBuilder are: 729               730             text_author Created by %s 731             text_madewith Made with %s version %s 732             text_required (Required fields are marked in bold.) 733             text_invalid Missing or invalid value. 734               735             Any messages you set here get passed on to CGI::FormBuilder, which means 736             that you should be able to put all of your customization messages in one 737             big file. 738               739             =item C 740               741             Sets the character encoding for the generated page. The default is ISO-8859-1. 742               743             =back 744               745             All other options given to C are passed on verbatim to the 746             L constructor. Any options given here override the 747             defaults that this module uses. 748               749             The C
, C, and C methods will all call 750             C with no options for you if you do not do so explicitly. 751             This allows you to say things like this: 752               753             my $form = Text::FormBuilder->new->parse('formspec.txt')->form; 754               755             However, if you need to specify options to C, you must call it 756             explictly after C. 757               758             =head2 form 759               760             my $form = $parser->form; 761               762             Returns the L object. Remember that you can modify 763             this object directly, in order to (for example) dynamically populate 764             dropdown lists or change input types at runtime. 765               766             =head2 write 767               768             $parser->write($out_file); 769             # or just print to STDOUT 770             $parser->write; 771               772             Calls C on the FormBuilder form, and either writes the resulting 773             HTML to a file, or to STDOUT if no filename is given. 774               775             =head2 write_module 776               777             $parser->write_module($package, $use_tidy); 778               779             Takes a package name, and writes out a new module that can be used by your 780             CGI script to render the form. This way, you only need CGI::FormBuilder on 781             your server, and you don't have to parse the form spec each time you want 782             to display your form. The generated module has one function (not exported) 783             called C, that takes a CGI object as its only argument, and returns 784             a CGI::FormBuilder object. 785               786             First, you parse the formspec and write the module, which you can do as a one-liner: 787               788             $ perl -MText::FormBuilder -e"Text::FormBuilder->parse('formspec.txt')->write_module('My::Form')" 789               790             And then, in your CGI script, use the new module: 791               792             #!/usr/bin/perl -w 793             use strict; 794             795             use CGI; 796             use My::Form; 797             798             my $q = CGI->new; 799             my $form = My::Form::get_form($q); 800             801             # do the standard CGI::FormBuilder stuff 802             if ($form->submitted && $form->validate) { 803             # process results 804             } else { 805             print $q->header; 806             print $form->render; 807             } 808               809             If you pass a true value as the second argument to C, the parser 810             will run L on the generated code before writing the module file. 811               812             # write tidier code 813             $parser->write_module('My::Form', 1); 814               815             =head2 write_script 816               817             $parser->write_script($filename, $use_tidy); 818               819             If you don't need the reuseability of a separate module, you can have 820             Text::FormBuilder write the form object to a script for you, along with 821             the simplest framework for using it, to which you can add your actual 822             form processing code. 823               824             The generated script looks like this: 825               826             #!/usr/bin/perl 827             use strict; 828             use warnings; 829             830             use CGI; 831             use CGI::FormBuilder; 832             833             my $q = CGI->new; 834             835             my $form = CGI::FormBuilder->new( 836             params => $q, 837             # ... lots of other stuff to set up the form ... 838             ); 839             840             $form->field( name => 'month' ); 841             $form->field( name => 'day' ); 842             843             unless ( $form->submitted && $form->validate ) { 844             print $form->render; 845             } else { 846             # do something with the entered data ... 847             # this is where your form processing code should go 848             } 849               850             Like C, you can optionally pass a true value as the second 851             argument to have Perl::Tidy make the generated code look nicer. 852               853             =head2 dump 854               855             Uses L to print out a human-readable representation of the parsed 856             form spec. 857               858             =head1 EXPORTS 859               860             There is one exported function, C, that is intended to ``do the 861             right thing'' in simple cases. 862               863             =head2 create_form 864               865             # get a CGI::FormBuilder object 866             my $form = create_form($source, $options, $destination); 867             868             # or just write the form immediately 869             create_form($source, $options, $destination); 870               871             C<$source> accepts any of the types of arguments that C does. C<$options> 872             is a hashref of options that should be passed to C. Finally, C<$destination> 873             is a simple scalar that determines where and what type of output C 874             should generate. 875               876             /\.pm$/ ->write_module($destination) 877             /\.(cgi|pl)$/ ->write_script($destination) 878             everything else ->write($destination) 879               880             For anything more than simple, one-off cases, you are usually better off using the 881             object-oriented interface, since that gives you more control over things. 882               883             =head1 DEFAULTS 884               885             These are the default settings that are passed to C<< CGI::FormBuilder->new >>: 886               887             method => 'GET' 888             javascript => 0 889             keepextras => 1 890               891             Any of these can be overriden by the C method: 892               893             # use POST instead 894             $parser->build(method => 'POST')->write; 895               896             =head1 LANGUAGE 897               898             field_name[size]|descriptive label[hint]:type=default{option1[display string],...}//validate 899             900             !title ... 901             902             !author ... 903             904             !description { 905             ... 906             } 907             908             !pattern NAME /regular expression/ 909             910             !list NAME { 911             option1[display string], 912             option2[display string], 913             ... 914             } 915             916             !list NAME &{ CODE } 917             918             !group NAME { 919             field1 920             field2 921             ... 922             } 923             924             !section id heading 925             926             !head ... 927             928             !note { 929             ... 930             } 931               932             =head2 Directives 933               934             =over 935               936             =item C 937               938             Defines a validation pattern. 939               940             =item C 941               942             Defines a list for use in a C, C, or C, C, and 1053             C), here's how you do it: 1054               1055             color|Favorite color:select{red,blue,green} 1056               1057             Values are in a comma-separated list of single words or multiword strings 1058             inside curly braces. Whitespace between values is irrelevant. 1059               1060             To add more descriptive display text to a value in a list, add a square-bracketed 1061             ``subscript,'' as in: 1062               1063             ...:select{red[Scarlet],blue[Azure],green[Olive Drab]} 1064               1065             If you have a list of options that is too long to fit comfortably on one line, 1066             you should use the C directive: 1067               1068             !list MONTHS { 1069             1[January], 1070             2[February], 1071             3[March], 1072             # and so on... 1073             } 1074             1075             month:select@MONTHS 1076               1077             There is another form of the C directive: the dynamic list: 1078               1079             !list RANDOM &{ map { rand } (0..5) } 1080               1081             The code inside the C<&{ ... }> is Ced by C, and the results 1082             are stuffed into the list. The Ced code can either return a simple 1083             list, as the example does, or the fancier C<< ( { value1 => 'Description 1'}, 1084             { value2 => 'Description 2}, ... ) >> form. 1085               1086             I This feature of the language may go away unless I find a compelling 1087             reason for it in the next few versions. What I really wanted was lists that 1088             were filled in at run-time (e.g. from a database), and that can be done easily 1089             enough with the CGI::FormBuilder object directly.> 1090               1091             If you want to have a single checkbox (e.g. for a field that says ``I want to 1092             recieve more information''), you can just specify the type as checkbox without 1093             supplying any options: 1094               1095             moreinfo|I want to recieve more information:checkbox 1096               1097             In this case, the label ``I want to recieve more information'' will be 1098             printed to the right of the checkbox. 1099               1100             You can also supply a default value to the field. To get a default value of 1101             C for the color field: 1102               1103             color|Favorite color:select=green{red,blue,green} 1104               1105             Default values can also be either single words or multiword strings. 1106               1107             To validate a field, include a validation type at the end of the field line: 1108               1109             email|Email address//EMAIL 1110               1111             Valid validation types include any of the builtin defaults from L, 1112             or the name of a pattern that you define with the C directive elsewhere 1113             in your form spec: 1114               1115             !pattern DAY /^([1-3][0-9])|[1-9]$/ 1116             1117             last_day//DAY 1118               1119             If you just want a required value, use the builtin validation type C: 1120               1121             title//VALUE 1122               1123             By default, adding a validation type to a field makes that field required. To 1124             change this, add a C to the end of the validation type: 1125               1126             contact//EMAIL? 1127               1128             In this case, you would get a C field that was optional, but if it 1129             were filled in, would have to validate as an C. 1130               1131             =head2 Field Groups 1132               1133             You can define groups of fields using the C directive: 1134               1135             !group DATE { 1136             month:select@MONTHS//INT 1137             day[2]//INT 1138             year[4]//INT 1139             } 1140               1141             You can then include instances of this group using the C directive: 1142               1143             !field %DATE birthday 1144               1145             This will create a line in the form labeled ``Birthday'' which contains 1146             a month dropdown, and day and year text entry fields. The actual input field 1147             names are formed by concatenating the C name (e.g. C) with 1148             the name of the subfield defined in the group (e.g. C, C, C). 1149             Thus in this example, you would end up with the form fields C, 1150             C, and C. 1151               1152             =head2 Comments 1153               1154             # comment ... 1155               1156             Any line beginning with a C<#> is considered a comment. 1157               1158             =head1 TODO 1159               1160             Document the commmand line tool 1161               1162             Allow renaming of the submit button; allow renaming and inclusion of a 1163             reset button 1164               1165             Allow groups to be used in normal field lines something like this: 1166               1167             !group DATE { 1168             month 1169             day 1170             year 1171             } 1172             1173             dob|Your birthday:DATE 1174               1175             Pieces that wouldn't make sense in a group field: size, row/col, options, 1176             validate. These should cause C to emit a warning before ignoring them. 1177               1178             Make the generated modules into subclasses of CGI::FormBuilder 1179               1180             Allow for custom wrappers around the C 1181               1182             Maybe use HTML::Template instead of Text::Template for the built in template 1183             (since CGI::FormBuilder users may be more likely to already have HTML::Template) 1184               1185             C directive to include external formspec files 1186               1187             Better tests! 1188               1189             =head1 BUGS 1190               1191             Creating two $parsers in the same script causes the second one to get the data 1192             from the first one. 1193               1194             I'm sure there are more in there, I just haven't tripped over any new ones lately. :-) 1195               1196             Suggestions on how to improve the (currently tiny) test suite would be appreciated. 1197               1198             =head1 SEE ALSO 1199               1200             L 1201               1202             L, L 1203               1204             =head1 THANKS 1205               1206             Thanks to eszpee for pointing out some bugs in the default value parsing, 1207             as well as some suggestions for i18n/l10n and splitting up long forms into 1208             sections. 1209               1210             =head1 AUTHOR 1211               1212             Peter Eichman C<< >> 1213               1214             =head1 COPYRIGHT AND LICENSE 1215             1216             Copyright E2004-2005 by Peter Eichman. 1217             1218             This program is free software; you can redistribute it and/or 1219             modify it under the same terms as Perl itself. 1220             1221             =cut