CleanCode Perl Libraries
Multi-Lingual Library Maintainability
available: Perl not available: Java not available: JavaScript not available: Certified
Class
not available: Testable
Class
not available: Standalone
Mode
available: Diagnostic
Enabled

NAME

CGI::PageSequencer - Creates navigation between static or dynamic web pages.

SYNOPSIS

  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) { ... }

REQUIRES

Perl5.005, Config::General, Data::Dumper, Data::Diagnostic, Data::Handy, File::Handy

DESCRIPTION

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.

Bootstrapping a Configuration File

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.)

Configuration File Definition

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.

Top-level elements

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.

Node-level elements

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.

Configuration File Sample

        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>

CLASS VARIABLES

VERSION

Current version of this class.

CONSTRUCTOR

new

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.

Parameters:

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

Returns:

a newly created object

METHODS

success

OBJ->success()

Indicates whether sequencer initialization was successful.

Returns:

boolean indicating whether sequencer initialization was successful.

getFields

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.

Returns:

array reference to list of field names for the current node.

getSeqName

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

Returns:

name of the current sequence

getNodeName

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

Returns:

name of the current node

getExitUrl

OBJ->getExitUrl()

Returns:

exitUrl for the curent node, if any

getLinkName

OBJ->getLinkName()

Returns:

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...
  }
Returns:

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).

Parameters:

link - a link object (one element of the array returned by getLinks).

name - a name of a link button.

Returns:

boolean indicating whether the specified link should be validated.

getTemplatePath

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.

Returns:

name of path to template files

getTemplate

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.

Returns:

name of template file

getTemplateFatal

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.

Returns:

name of fatal template file

getConnector

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.

Returns:

name of connector

getDefault

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.

Parameters:

defaultName - string

Returns:

value of specified default

isStartNode

OBJ->isStartNode()

Identifies whether current node is the START node.

Returns:

boolean indicating whether current node is the START node.

isEndNode

OBJ->isEndNode()

Identifies whether current node is the END node.

Returns:

boolean indicating whether current node is the END node.

processNode

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).

Parameters:

inputData - an InputOptions object;

getNodeOutput

OBJ->getNodeOutput()

The processNode method processes the plugin for this node and stores its output in an instance variable; this method retrieves that output.

Returns:

output of the node plugin

advanceNode

OBJ->advanceNode(link)

Returns next node or a false value if no more nodes, as specified by the connector parameter.

Parameters:

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:

Returns next node or a false value if no more nodes.

dump

OBJ->dump(traverse)

Returns textual dump of sequencer semantics as defined by the configuration file.

Parameters:

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.

Returns:

String; representation of sequencer semantics.

BUGS

None

AUTHOR

Michael Sorens

VERSION

$Revision: 8 $ $Date: 2006-12-19 21:13:43 -0800 (Tue, 19 Dec 2006) $

SINCE

CleanCode 0.9

SEE ALSO

CGI::PageGenerator, CGI::PageValidator

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 398:

=back doesn't take any parameters, but you said =back -- end of CONSTRUCTOR section

Around line 956:

=back doesn't take any parameters, but you said =back -- end of METHOD section


CleanCode Perl Libraries Copyright © 2001-2013 Michael Sorens - Revised 2013.06.30 Get CleanCode at SourceForge.net. Fast, secure and Free Open Source software downloads