(C) Jørn Lind-Nielsen 2004
The Guppy framework is a web forms handling system that adds a few extra features to the standard HTML forms handling. It allows the programmer to specify a web form using a few XML files—two for each form (plus an additional PHP handler file). The use of a relatively simple XML specification removes the burden of creating a lot of complex HTML and JavaScript from the programmer at the cost of design flexibility.
With Guppy one can design different components: cards that show a single record, tables that show multiple records, and trees that shows multiple nested records. Each kind of component may contain one or more fields of different kinds. Fields can currently only be input fields with support for booleans (checkboxes), integers, reals, dates, times, strings, html, and selectors. Most of the input fields can be marked as mandatory which forces the user to enter something in the field.
The benefits of Guppy are:
The Guppy system is event based. The programmer supplies a form specification XML file, a layout XML file, and a handler PHP object. The framework then renders the HTML and based on the user input it calls various event methods in the PHP handler.
The event handler object must inherit from the GuppyDecodeHandler class. It's event handling methods are passed an event object describing the current event. The inheritance from GuppyDecodeHandler ensures that $this has a reference to a Guppy command handler (the "commander") which must handle all output from any event handler.
To be written ... this will descript how a Guppy form is specified (without layout information).
This section deals with the format of the layout definition file. The layout XML is a recursive structure that allows you to place your components in a grid structure (a table) much like done in a normal HTML table. A layout begins and ends with the tag "layout":
<?xml version="1.0"?> <layout> ... layout ... </layout>
The layout tag begins a grid (in the same way as a table tag does it in HTML) so the content must define the rows of this grid. This is done with the row tag:
<?xml version="1.0"?> <layout> <row> ... row layout ... </row> </layout>
Now we are ready to put some content in the rows. The most import tag is the component tag which specifies where a component should be placed. The component tag must specify which component it refers to. In the examples here we use the Pagesetter "edit publication" form which defines only one component named "pubedit".
If we drop the initial xml tag we now get:
<layout> <row> <component name="pubedit"> .. component layout ... </component> </row> </layout>
Inside the component tags we can sprinkle out field tags where ever we want to place one of the input fields available for the component. But before we do that we must first setup a layout structure for the component. Again we use the layout tag which places the layout in grid mode, so we must also add rows to place our fields in:
<layout> <row> <component name="pubedit"> <layout> <row><field name="title"/></row> <row><field name="text"/></row> </layout> </component> </row> </layout>
As you can see you must also supply a field name that refers to one of the fields specified for that component. You need not consider what kind of field it is since Guppy already nows that and will create what ever is needed. Almost. You do need to specify how you want a text field to display. It can be displayed as a one line text input field, a textarea tag, or as an HTML editor using HTMLArea. Use the view attribute on the field tag for this. In our example we want the "text" field to be shown as an HTML editor. Let us resize the input field a bit at the same time by setting a height attribute:
<layout> <row> <component name="pubedit"> <layout> <row><field name="title"/></row> <row><field name="text" view="html" height="300"/></row> </layout> </component> </row> </layout>
It further more seems sensible to require that the title must be entered. So we mark the "title" field as mandatory, and set the width to 400 pixels at the same time:
<layout> <row> <component name="pubedit"> <layout> <row><field name="title" mandatory="true" width="400"/></row> <row><field name="text" view="html" height="300"/></row> </layout> </component> </row> </layout>
At last we also want to be able to interact with out form, so we must add some buttons. In this example we add the three core buttons that Pagesetter supplies—the preview, Update, and Cancel buttons.
<layout> <row> <component name="pubedit"> <layout> <row><field name="title" mandatory="true" width="400"/></row> <row><field name="text" view="html" height="300"/></row> </layout> <buttonsBottom> <button name="corePreview"/> <button name="coreUpdate"/> <button name="coreCancel"/> </buttonsBottom> </component> </row> </layout>
The button tag places a single button in the layout. You must at least specifiy the name of the button using the name attribute.
name | Name of the referenced button. |
title | Title for this button. If no title is supplied then the one defined in the specification is used. |
hint | A hint describing what the button is for. If no hint is supplied then the one defined in the specification is used. The hint is used as a "title" attribute in the generated HTML. |
The buttonsBottom tag defines a singe-row container for buttons. It must be placed inside a component tag. Buttons placed inside the buttonsBottom tag will be placed below the associated component pane.
The buttonsTop tag defines a singe-row container for buttons. It must be placed inside a component tag. Buttons placed inside the buttonsTop tag will be placed above the associated component pane.
The field tag places a single input field in the layout.
kind | The kind of field. Defaults to "input" but can also be "action" to reference an action. |
name | Name of the referenced field. |
title | Title for this input field. This will be used as a label placed in a separate title tag immediately before the input field. If no title is supplied then the one defined in the specification is used. |
width | The width of the field in pixels. |
height | The height of the field in pixels. |
colspan | Column span as for a HTML td tag. |
view | Defines how the field should be displayed. Can be "string" (default), "text", or "html". The result is either a simple one line input (string), a textarea (text), or an HTML editor (html). |
hint | A hint describing what the input field is for. The exact rendering of the hint is not yet defined. |
mandatory | Forces the user to enter something in the field. Must be set to "true" or "yes". |
readonly | Inhibits the user from entering something in the field. Must be set to "true" or "yes". |
The island element is a grid container that adds a visual box around it's contained elements.
title | Title for this button. If no title is supplied then the one defined in the specification is used. |
colspan | Column span as for a HTML td tag. |
The layout element defines a grid container in which rows must be placed.
The row element defines a single row in a grid and must contain cell elements like the component tag or a nested layout.
The title element adds a label for some input field. To do so it must refer to an input element by name. The title of that element is then placed where the title element is. All input fields automatically expands to a title element followed by an input element unless otherwise specified.
title | Title for this button. If no title is supplied then the one defined in the specification is used. |
colspan | Column span as for a HTML td tag. |
All usage of Guppy starts with a call to guppy_decode to see if the script has been initiated from Guppy or from else-where. If the script is not started as a result of a Guppy event then guppy_decode will return the boolean value true. If it is a result of a Guppy event then it will return an associative array with the following elements.
The action object contains the following properties:
Parsing of the XML files for forms specification and layout is handled in guppy_parser.php. The code here creates a large associative array that describes the form. The data is stored in a PHP session variable. New attributes for the XML structure must be parsed here.
Rendering of the HTML and handling of user input is done in guppy.php. New attributes returned from the XML parser must be handled here.
99% of the stuff that is PostNuke related is implemented in guppy_postnuke.php in the hope that this makes it possible to reuse Guppy in another framework.