The form generator, formgen.pl, runs as a CGI script. It requires at least one argument, which tells the generator which instance of Docbase to use. For example, the CGI call:
/cgi-bin/Docbase/formgen.pl?app=ProductAnalysis
produces the form shown in Figure 6.1.
The assignment date, overridden by the
|assigndate|
marker, appears as static
text. All other fields are open for input. However, this CGI call:
/cgi-bin/Docbase/formgen.pl?app=ProductAnalysis&duedate=1999-05-01& analyst=Jon%20Udell&company=Netscape&product=Collabra%20Server%204.0
produces the form shown in Figure 6.2.
Here,
the generator, using the services of the
Docbase::Input module, has overridden every
replaceable marker with a computed or preassigned value. The analyst
who completes this form needs to fill in only four of the fields:
Title
, Summary
, Full Report
, and Contact Info
.
The form generator, formgen.pl, appears in Example 6.2. It’s brief, because most of the work is done by two modules: TinyCGI and Docbase::Input.
Example 6-2. The Docbase Form Generator
#!/usr/bin/perl -w use strict; use TinyCGI; # load basic CGI services my $tc = TinyCGI->new(); print $tc->printHeader(); my $vars = $tc->readParse(); # get form variables into hashref use Docbase::Input; my $di = # set up for this docbase Docbase::Input->new($vars->{app}); $di->formGen($vars); # pass form-variable hashref to form generator
TinyCGI, which I’ll use often, is a
minimalistic CGI library. In it I’ve collected the four simple
routines that are at the heart of all CGI
programming—printHeader( )
to emit the
all-important Content-type:
header,
readParse( )
to gather variables from
GET and POST transactions and
put them into a Perl hashtable, escape( )
to
encode data for HTTP transmission, and unescape(
)
to reverse the effects of escape(
)
. There’s nothing new here;
TinyCGI simply repackages, for efficiency and
convenience, the 1 percent of Perl’s standard
CGI module that I use 99 percent of the time.
As
we’ve seen, the generated form varies according to arguments
passed to formgen.pl.
Docbase::Input accomplishes that by matching
markers in the form template with arguments passed to it from
formgen.pl. The formGen( )
method of Docbase::Input, shown in Example 6.3, is a typical example of a Perl-based template
processor.
Example 6-3. The formGen Method
sub formGen # merge form template with form variables { my ($self,$vars) = @_; my $app = $self->{app}; my $form = # create the template's name "$cgi_absolute/$app/form-template.htm"; open(F,$form) or print "cannot open form template $form"; while (<F>) # for each line of form template { if ( m/(!ACTION!)/ ) # rewrite form action { s#$1#$cgi_relative/$app/submit.pl#; } if ( m#</form># ) # tack on $app for next script's use { print "<input type="hidden" name="app" value="$app"> "; } if ( m/|(w+)|/ ) # perform builtin function { my $fn = $1; # grab function's name s/|$1|/&{$builtins{$fn}}/e; # call function, replace marker with value } if ( m/~(w+)~/ ) # handle form variables that can be overridden { my $var = $1; # grab variable's name my $val = $vars->{$var}; # access corresponding hashtable slot if (defined $val) # if slot nonempty, print value on form { # and pass along in hidden variable s/~$var~/$val <input type="hidden" name="$var" value="$val">/; } else # turn other form variables into input boxes { s/~$var~/<input name=$var size=40>/; } } print $_; # emit the line } }
The drill is simple: read a line at a time, look for matches, do
substitutions. In this example the $vars
hashtable, which contains CGI name/value pairs received from
TinyCGI, affords a concise way to map between
those pairs and corresponding names that may or may not appear in the
form. Perl’s s///e
idiom likewise affords a
concise way to convert a name that appears in the form into the
result of a Perl function mapped to that name.
It’s trivial to build templates and Perl-based template processors, but the technique is very powerful. That’s why we’ll use it often.