CleanCode Perl Libraries |
Home | Perl | Java | PowerShell | C# | SQL | Index | Tools | Download | What's New |
Multi-Lingual Library | Maintainability | ||||||||||||
Perl | Java | JavaScript | Certified Class |
Testable Class |
Standalone Mode |
Diagnostic Enabled |
CGI::PageSequencer - Creates navigation between static or dynamic web pages.
use CGI::PageSequencer;
# This first example usage outlines how to hook up the sequencer
# in your top level script to navigate between web pages.
$sequencer = CGI::PageSequencer->new($seqFile, $libMgr, $nodeName);
if ($seq->success()) {
if ($seq->isStartNode()) {
$seq->advanceNode();
}
elsif ($actionName) {
if (!$seq->isValidateLink($actionName)) {
# always go to next node
$seq->advanceNode($actionName);
}
else {
# go to next node IF valid data; otherwise show errors
...
$seq->advanceNode($actionName) if ...
}
}
else { # no actionName; just use current node
}
if ($seq->getExitUrl()) { # use redirect url, if any
...
}
else { # generate page for current node
... print ...
}
}
# lower level example usage (such as used by CGI::PageGenerator)
$fieldRef = $seq->getFields();
foreach $field (@$fieldRef) { ... }
$fieldRef = $seq->getFormattedFields();
foreach $field (@$fieldRef) { ... }
$linkList = $seq->getLinks();
foreach $linkName (@$linkRef) { ... }
Perl5.005, Config::General, Data::Dumper, Data::Diagnostic, Data::Handy, File::Handy
This module provides a data-driven mechanism for automating website creation statically or dynamically. For dynamic web page creation, you create a sequencing file which describes the contents of each web page and the connections between web pages. Also, you must provide a LibraryMgr which defines the characteristics of each field you have specified in your sequencing file. Finally, you need an instrumented CGI script which creates and uses an instance of CGI::PageSequencer
. An outline of this is shown in the Synopsis section.
PageSequencer is designed to work in conjunction with PageGenerator to create dynamic web pages and navigate amongst them. In particular (using a LibraryMgr), you may create a complete web page containing a form for the user to fill out by simply specifying a field list in the configuration file for PageSequencer. It will then ask PageGenerator to create the page and serve it up to the user. Once filled out by the user, PageSequencer will ask PageValidator to validate the fields, then either send the page back to the user for corrections, or send the follow-on page to the user. Besides simple field handling, you may also specify plugins in the configuration file that will perform ancillary processing. A typical example is a feedback page: collect input from a user, then send email to a system administrator. The CleanCode Contact Us web page uses this precise mechanism. The initial contact page asking the user to fill in information and the subsequent page confirming what has been sent require no coding: you just specify a list of fields in the configuration file, as mentioned, and define the characteristics of those fields in the dictionary. The only bit of coding is to actual assemble and send the piece of e-mail.
Here's complete code for a bootstrapping example, to see if you've created a good sequencer file.
use Data::Diagnostic;
use CGI::PageSequencer;
my $configFile = shift @ARGV || "";
die "$0: '$configFile' not found" unless $configFile && -f $configFile;
Data::Diagnostic->init(@ARGV);
my $seq = CGI::PageSequencer->new($configFile, undef, "START");
print "Sequencer result: " . ($seq->success()? "OK" : "FAILED") . "\n\n";
print "========= Nodes scanned =========\n";
print $seq->dump() . "\n\n";
print "========= Ordered nodes =========\n";
print $seq->dump(1) . "\n";
If you call this script test.pl, and your sequencer file sequence.conf, invoke the script with either of these:
test.pl sequence.conf 1
test.pl sequence.conf "CGI::PageSequencer"
The final argument is a diagnostic mask, which will produce different output. Try it with the sample sequencer configuration file shown below. If you receive any errors, then you haven't hooked up all the settings right; typically, a path is most common. (You will receive a warning about a missing library manager, which can be ignored for this test.)
The configuration file uses an Apache-compatible syntax. A definition line consists simply of name=value. (You may optionally use whitespace instead of the equals sign.) The octothorp (#) is the inline comment character; any text following it is ignored, as are blank lines.
connector = link-name
templatePath = directory-name
template = file-name
templateFatal = file-name
defaultFieldWidth = integer
defaultFieldHeight = integer
defaultFieldMaxlen = integer
pageTitle = string
node
The top-level elements are global defaults. If not explicitly provided in node-level elements, these will be inherited. Additionally, you may specify any arbitrary defaultxxx property you wish, then access them via the getDefault
method.
field = field-name | field-picture
link
plus all of the top-level elements...
Each node is defined with a <Node name>...< /Node> bracket pair. Within the brackets, define any of the elements shown above, each on a separate line. Multiple field elements may be used, with different clauses. Multiple link elements may also be used. For both fields and links, the order you have them in your file determines the order they will appear on your web page. You must have a node named START as your initial node, and a node named END as your final node. Intermediate nodes may use any other names you choose. Any top-level definition may be overridden with a node-level definition. This override acts only on the node which defines it.
name = link-name
gotoNode = node-name
gotoUrl = url
validate = boolean
processObject = plugin-class-name
Each link is defined with a <Link>...< /Link> bracket pair. Only one of gotoNode or gotoUrl are permitted in each link block. The START and END virtual nodes must each have a link named TRANSIT. The START node's TRANSIT typically specifies a gotoNode clause indicating your first actual node. The END node's TRANSIT typically specifies a gotoUrl clause indicating a new URL to load at the end of your sequence of pages. The validate element should have a true clause for those links which should invoke the CGI::PageValidator
before transiting to the link destination.
The processObject element should specify a complete plugin class name, e.g. "CGI::PagePlugin::FormMail". The plugin must implement the following interface. (1) The constructor takes two parameters, an array reference listing the field names to process, and an an InputOptions object. (2) A no-argument process method to do whatever processing you wish.
connector = Next
template = generic.thtml
templateFatal = fatal.thtml
<Node START>
<Link>
name = TRANSIT
gotoNode contactInfo
</Link>
</Node>
<Node contactInfo>
pageTitle=Contact Information
field FirstName
field LastName
field Address
field City
field PostCode
<Link>
name=Next
gotoNode subscriptionDetails
validate = 1
</Link>
<Link>
name=Exit
gotoUrl http : //exit.home.com
</Link>
</Node>
<Node subscriptionDetails>
pageTitle=Subscription Information
template = subs.thtml
field CCName
field CCNumber
field CCType
field CCExpiry
<Link>
name=Next
gotoNode END
</Link>
<Link>
name=Back
gotoNode contactInfo
</Link>
<Link>
name=Exit
gotoUrl http : //exit.home.com
</Link>
</Node>
<Node END>
<Link>
name = TRANSIT
gotoUrl http : //home.com
</Link>
</Node>
Current version of this class.
PACKAGE->new(seqPath, seqName, libMgr, nodeName)
Returns a newly created object for the specified sequence file and library manager, and sets the current node. If a nodeName is not specified, the initial START node is used.
seqPath
- string; path to directory containing sequence files
seqName
- string; sequence name for this particular sequence; used to select a corresponding sequence specification file, having the path "seqPath/seqName.conf
".
libMgr
- LibraryMgr object
nodeName
- optional; string; node to use in subsequent method calls
a newly created object
OBJ->success()
Indicates whether sequencer initialization was successful.
boolean indicating whether sequencer initialization was successful.
OBJ->getFields()
Return array reference to list of field name strings for the current node. This list of fields specifies the required fields for the node, so may be used to verify that all required fields have been supplied. Also, each field name may be used as an index into an element library as provided by LibraryMgr, for example.
array reference to list of field names for the current node.
OBJ->getSeqName()
Returns the current sequence name, extracted from the PATH_INFO portion of the URL, having the general form: .../cgi-bin/program/sequenceName/nodeName
name of the current sequence
OBJ->getNodeName()
Returns the current node name, extracted from the PATH_INFO portion of the URL, having the general form: .../cgi-bin/program/sequenceName/nodeName
name of the current node
OBJ->getExitUrl()
exitUrl for the curent node, if any
OBJ->getLinkName()
name of the current link.
OBJ->getLinks()
Return hash reference to list of links for the current node. Each link in the list defines a named connector from the current node to another node or an external URL. The hash consists of (connector-name
, path
) pairs. A path
is itself a hash containing either a gotonode
key or a gotourl
key, defining the target of the connector. So here is one way to create a URL for each connector:
foreach my $link (keys %$linkRef) {
my $buttonHash = $linkRef->{$link};
if ($buttonHash->{gotonode}) {
$url = $cgi->url(-relative=>1) . "/" . $buttonHash->{gotonode};
}
elsif ($buttonHash->{gotourl}) {
$url = $buttonHash->{gotourl};
}
# process $url here...
}
hash reference to links for the current node.
OBJ->isValidateLink(link)
OBJ->isValidateLink(name)
Returns a boolean indicating whether the specified link should be validated. If the current node does not contain a link of the specified name, returns false (0).
link
- a link object (one element of the array returned by getLinks).
name
- a name of a link button.
boolean indicating whether the specified link should be validated.
OBJ->getTemplatePath()
Returns the path name for template files for the current node, if defined; otherwise, returns the global template path name, if defined; otherwise, returns undef.
name of path to template files
OBJ->getTemplate()
Returns the template file name for the current node, if defined; otherwise, returns the global template file name, if defined; otherwise, returns undef. In the sequence file, templates should be specified as a pure file name with no path prepended. The path is specified with the templatePath element.
name of template file
OBJ->getTemplateFatal()
Returns a template file name, just like getTemplate
. This one is used in case of fatal errors, (where you have determined that the regular web page could not be generated). In the sequence file, templates should be specified as a pure file name with no path prepended. The path is specified with the templatePath element.
name of fatal template file
OBJ->getConnector()
Returns a connector name, i.e. the name of the link which traverses the node set from the START node to the END node. In a typical scenario this might be the Next link. It does not have to be unique. Note that if you also have a Back link, it may also traverse all your nodes, but in the opposite direction.
name of connector
OBJ->getDefault(defaultName)
Returns a named default value. Pre-defined ones include fieldWidth
, fieldHeight
, and fieldMaxlen
. In your sequence file, these would be denoted as defaultFieldWidth
, defaultFieldHeight
, and defaultFieldMaxlen
, respectively. Retrieve each with the pre-defined name, e.g. getDefault("fieldWidth")
returns the value of defaultFieldWidth
from the file. Also, for any arbitrary field xyz
, call getDefault("xyz")
to retrieve the defaultXyz
property value.
defaultName
- string
value of specified default
OBJ->isStartNode()
Identifies whether current node is the START node.
boolean indicating whether current node is the START node.
OBJ->isEndNode()
Identifies whether current node is the END node.
boolean indicating whether current node is the END node.
OBJ->processNode(inputData)
Performs desired processing for this node via a plugin. Loads the plugin class specified for this node, instantiates an object of that class, invokes its process
method, then stores its output from its output
method (as a single string).
inputData
- an InputOptions object;
OBJ->getNodeOutput()
The processNode
method processes the plugin for this node and stores its output in an instance variable; this method retrieves that output.
output of the node plugin
OBJ->advanceNode(link)
Returns next node or a false value if no more nodes, as specified by the connector
parameter.
connector
- optional; string; name of Link field in the configuration file which connects to the next node in a normal progression (e.g. if currently at "Step 1" and pressing Next goes to "Step 2", then Next is the connector). If no connector is specified, the value defined in the configuration file will be used.
Returns next node or a false value if no more nodes.
OBJ->dump(traverse)
Returns textual dump of sequencer semantics as defined by the configuration file.
traverse
- optional; boolean. If true, lists nodes in traversal order, beginning at the START node, progressing towards the END node, based on the connector specification in the configuration file. If false, lists nodes in sorted order and verifies semantics of all nodes.
String; representation of sequencer semantics.
None
Michael Sorens
$Revision: 8 $ $Date: 2006-12-19 21:13:43 -0800 (Tue, 19 Dec 2006) $
CleanCode 0.9
CGI::PageGenerator, CGI::PageValidator
Hey! The above document had some coding errors, which are explained below:
=back doesn't take any parameters, but you said =back -- end of CONSTRUCTOR section
=back doesn't take any parameters, but you said =back -- end of METHOD section
Home | Perl | Java | PowerShell | C# | SQL | Index | Tools | Download | What's New |
CleanCode Perl Libraries | Copyright © 2001-2013 Michael Sorens - Revised 2013.06.30 |