WikiForms

Summary: Use a form template to create, edit and list wiki pages
Version: 1.1.1 (2014-02-13, compatible with php 5.5)
Status: Stable
Prerequisites: PmWiki 2.2.56 or above and php 5.3 or above
Maintainer: jr
Categories: Forms, PHP55

<< Input | Forms-related | >>

Goals

Provide a mechanism for forms-based entry and updating of structured wiki pages. Uses include:

  • issue tracking
  • risk tracking
  • task tracking
  • limited database functionality using wikipages as flatfile records

Make the form template a wiki page, so you can set up new forms for new purposes.

Use the form to create new pages and edit existing pages.

Information is stored on the basis 1 issue = 1 page. For appending issues to existing pages, use a different recipe like CommentBox (for example).

The script automatically adds form links to the template page, to create a new page, and to each issues page (ie those with names of 5 digits), to edit the page.

(see CompareFormsRecipes)

Solution

Version compatible with php 5.5 and PmWiki 2.2.56 or above:

wikiform1_0.phpΔ and wikiform-i18n-en.phpΔ -- this is mature and stable (but incompatible with php 5.5). Use the WikiFormSample to get a quick-start on a template. WikiFormCSS.phpΔ is a sample style script. There is a working, live example of an issues register for a real project and a tips register for how-to tips. These both contain real data; at the moment there isn't a "playground" for people to experiment.

Those people who want to take advantage of the page title options and refer to a form-generated page by its title also need to install formtitle.phpΔ (updated 2009-01-11).

Internationalised versions:

(Please note. The PublishPDF library includes the WikiForms recipe.)

Installation

To enable the wikiform capability, download the scripts wikiform.phpΔ and wikiform-i18n-en.phpΔ and install them in the cookbook/ directory. Then add the following line to your local/config.php file:

    include_once("cookbook/wikiform.php");

You also need to download and install the MarkupExtensions, if you haven't already done so.

To use the form styles, download the WikiFormCSS.phpΔ script, put it in your local/ directory and rename it to the name of the group which contains the form-based pages.

Configuration Options

By default, the "Edit Form" link is at the bottom of the page.

To move it to the top of the page, add the following line before the include wikiform.php line in config.php:

    $FormNavFooter= false;

History

  • 23 March 2013 -- fix calls to htmlspecialchars to include charset
  • 11 January 2009 -- add title! option to prevent editing a title field value
  • 12 November 2008 -- support a default value for text field type: (text Rain of the Children)
  • 20 July 2008 -- add ! option to prevent editing a text field value
  • 28 June 2008 -- added (email"example.com") option for default email (at)
  • 20 June 2008 -- further improve view template handling and use heading markup to break form into sections
  • 13 November 2007 -- improve handling of view template when field contains $
  • 30 October 2007 -- add field==value1|value2 for exact match 1 or 2; ability to pass field value as $_REQUEST
  • 26 October 2007 -- add field==value for exact value matches and further improve view template
  • 20 September 2007 -- improve handling of view templates when field values contain ' and "
  • 13 September 2007 -- add attach field type with file extension radio buttons
  • 23 March 2007 -- add authorplain (i.e. no link) option and a today's date checkbox to date fields
  • 27 Sep 2006 -- trial fix for error when edit password set; add field comment option
  • 05 Sep 2006 -- fix bug introduced when PmWiki changed FmtPageName
  • 13 April 2006 -- add page view template proof of concept
  • 11April 2006 -- support simultaneous edits and add count to wikilist
  • 27 February 2006 -- improve suport for title option
  • 22 February 2006 -- add support for title option to allow non-numeric page titles
  • 02 February 2006 -- add support for !page to omit page name from wikilist directive
  • 21 Dec 2005 -- add search=field option to wikilist directive: search box for a field
  • 28 Nov 2005 -- add $PublishForm=2 option and fix last modified date sort bug
  • 18 Nov 2005 -- add +lastmodified and group=options to wikilist, update i18n-en
  • 15 Nov 2005 -- add i18n file and ability to use forms on any wiki page
  • 21 Sep 2005 -- removed bug inadvertently introduced :(
  • 01 Sep 2005 -- use $PageUrl instead of $ScriptUrl when saving edits
  • 01 Aug 2005 -- share template across groups, various minor enhancements
  • 12 Jul 2005 -- add support for reversing sort order in (:wikilist:)
  • 06 Jul 2005 -- fix special character problem in author names
  • 04 Jul 2005 -- add support for 'or' wikilist selection logic and *author
  • 28 Jun 2005 -- fix warning message if wikilist returns no entries
  • 27 Jun 2005 -- make publish button optional and add $FormNavFooter option
  • 19 Jun 2005 -- add group field type for links and fix a couple of bugs
  • 19 Apr 2005 -- fix last modified date display fault in Edit Form mode
  • 14 Mar 2005 -- fix a $Variable bug and include sample form page styles
  • 09 Mar 2005 -- add automatic next and previous item navigation
  • 07 Mar 2005 -- fix htmlentities bug and enhance list capability
  • 03 Mar 2005 -- minor fixes and enhancements to field handling
  • 02 Mar 2005 -- fix omission of Edit Form link if pagename is Group/Page
  • 21 Feb 2005 -- minor enhancements
  • 11 Feb 2005 -- first beta release

Contributor

jr

Discussion

To set up a new form, create a template page. The script looks for $Group.FormTemplate -- that is, a page called FormTemplate in the current group. If you expect to have several forms, consider putting the templates in a separate group, perhaps with an edit password. The script looks for a form template in the following sequence:

  1. $Group.FormTemplate (eg Issues.FormTemplate)
  2. Forms.$Group (eg Forms.Issues)
  3. $Suffix.FormTemplate where $Suffix is any text after a hyphen in the group name (eg PmWiki-Issues)
  4. Forms.$Suffix

The form template name is defined in $FormTemplatePage (default value = 'FormTemplate'). The forms group name is defined in $FormsGroup (default value = 'Forms').

It turns out that it's important that the $FormTemplatePage and $FormsGroup declarations are placed before the include_once("cookbook/wikiform.php"); statement. -- Patrick Linskey March 30, 2005, at 12:00 AM

There are 2 directives:

(:wikiform:) generates a form
(:wikilist name=value:) lists pages where 'name' matches 'value'
(:wikilist group=GroupName:) lists pages from the GroupName group

(if the value includes spaces, write name='some value')

The script generates the form from any :term:definition markup on the template page. The general structure of a form field definition extends the :term:definition markup to...

:<prompt text>:<variable> <tool tip text> <field type> <sort> <sum>

For example, with all options set:

:Urgency:urgency do we need to solve this now or later? (1|1 - later;2;*3;4;5|5 - now) - 0+

Taking each piece in turn...

Urgency
the field prompt; required
It is wise to choose prompts with a single word -- this allows you to access your data as page text variables later on. If you have any non-variablename-characters (like a space) in your prompt then you cannot do this. —Peter Bowers April 17, 2011, at 02:15 PM
urgency
the name of the variable and must be unique within a form; optional, if omitted it uses the field prompt, shifted to lower case with spaces removed
Avoid the use of underscores or dashes in variable names - letters only, please. --PeterBowers October 22, 2007
Avoid the use of uppercase letters in variable names - lowercase alpha only, please. --PeterBowers November 6, 2007
do we need to solve this now or later?
a tool tip, revealed by mousing over the field prompt in the form; optional, if used you must supply a variable name, or the first word of the tool tip becomes the name
Avoid the use of parentheses, + or - or * characters. --PeterBowers May 16, 2008, at 01:24 PM
(1|1 - later;2;*3;4;5|5 - now)
field type - in this example a radio button list with values 1 to 5, where the 1 and 5 values have alternate text displayed and 3 is selected; optional, if omitted the default is a simple text box
-
sort/list directive - this example will include this field in the (:wikilist:) output and make the column heading sort in descending order; optional, if omitted the field is omitted from the list
0+
keep a sum for each record and add this value to it (1 digit only), with an adjustment of 0; optional

Field types supported

The following values for <field type> are supported.

  • The default is a plain text box. To supply a default value, enter ("default value") eg
:Summary:summary ("If you think education's expensive, try ignorance")
  • To supply a defined text field size, enter ("default value"=size) eg
:Summary:summary ("If you think education's expensive, try ignorance"=55)
  • (text) produces a textarea.
  • ([1-9][0-9]*) the number of lines for several text boxes; these get joined with \\ markup
  • (email) produces boxes for a name and email address; this creates [[name -> mailto:address]]
  • (date) produces a date field; (*date) sets the default value for new pages to today; if the date value is blank, it inserts a checkbox which sets the date to today
  • (author) produces a text box containing the PmWiki Author, saved as [[~author]]; (*author) sets the default value to $Author; and (authorplain) or (*authorplain) suppresses the profile link
  • (group Groupname) produces a link to Groupname/value of field
  • (title) treats the field contents as the text for a (:title:) directive
Be aware that a field designated with this "title" field-type will always contain (a) the text you enter followed by (b) a newline followed by (c) the (:title ...:) markup -- all 3 parts make up the contents of that field. That newline can wreak havoc if you attempt to format the data with [++...++] or '''...''' since markups such as this expect the beginning and ending tags to be on the same line. —Peter Bowers April 17, 2011, at 02:15 PM
Note: Using (title) can mess up the form if wikiforms is used alongside other Pmwiki cookbooks which also use (title). I found other scripts were confusing this directive so multiple (titles) would appear when editing a saved form. You should aim to test entries by editing them to see if all looks ok and if not to comment out other cookbooks in your config to see which is causing the conflict. A good way to see if your edits are good is to view the source ?action=source. With thanks to jr --david
  • (check) produces a checkbox with value set to Yes if checked; (*check) sets it to checked; (check value) sets name to value; (*check value) does what you'd expect
  • (hide) produces a hidden variable with value set to name; (hide value) sets name to value
  • (category) adds the markup [[!exampletext]] round the text entered to make use of PmWiki:Categories
  • (attach extension1|extension2|...) produces a link to Attach:fieldvalue.extension where "extension" is selected from a radio button list and ext1|ext2|...|*extn|... causes extn to be selected as the default extension on new pages
    • (attach extn) produces a link to Attach:fieldvalue.extn
    • (*attach ...) produces a link to [[(Attach:)fieldvalue.extension]]
  • (value1,value2,...) comma separators produce a pick list of values with the first selected; (value1,...,*valuen,...) causes valuen to be selected for new pages
  • (value1;value2;...) semicolons produce a radio button list with none selected; (value1;...;*valuen;...) causes valuen to be selected for new pages
    valuen|text causes 'text' to be displayed against the button, with the value of 'valuen'
  • (value1:value2:...) colons produce a set of checkboxes with none selected; any with a leading * are checked for new pages; (!value1:value2:...) applies category markup [[!valuen]] to any selected
  • sometimes, we want to let an author enter a field value when creating a new page, but not change it; we can do this for a plain text box by using the ! qualifier: (!) or ("default text"!) or (!=nn) or ("default text"!=nn) will create a text box of size nn when creating a new page and display the current value when editing the page

Any field can have a comment displayed in the resulting form, e.g. as help text. In the form template, start the line after the field definition with :: followed by the comment text. At this time, the comment may not contain wiki markup -- plain text only.

(NOTE: Avoid colons in this comment text after the initial double-colon. They mess up your form big-time. --PeterBowers)
(Now fixed --jr)

Sorting columns in the list view

The list directive lets you click on any column heading to sort the selected pages based on that column. After the resorted list displays, clicking the column heading again reverses the sort order.

<sort> matches the pattern "[-+]\\*?" -- a plus sign or a minus sign followed by an optional asterix.

A plus sign denotes include this item and sort in ascending order; a minus sign denotes include this item and sort in descending order.

An asterix denotes include this field in the default sort order. The script adds the page name to the end of the list of default sort fields.

For example:

:Fee:fee +

:Fie:fie

:Foe:foe +*

:Foo:foo

:Bar:bar -*

The (:wikilist:) directive will list Page, Fee, Foe, Bar sorted by foe then bar (descending) then page.

To sort by the date of the last modfication of each page, you need to specify +*lastmodified or -*lastmodified in your wikilist directive, for ascending or descending sort order respectively. Because it sorts left to right and the last modified date is the right hand field, you need to disable the default sort order for all other columns.

Assigning a score to a page

Suppose we are setting up a risk register. Each risk has the components of likelihood that it will happen and impact if it does happen. We want to monitor high likelihood, high impact risks. We would use the <sum> option, which matches "\d[-+]" -- a digit followed by a plus sign or a minus sign.

For example:

:Risk:risk

:Likelihood:likelihood (1;2;3;4;5) 0+

:Impact:impact (1;2;3;4;5) 1+

This will generate 2 sets of radio buttons and add a Score column to the (:wikilist:) that adds the values together, with a descending sort, and subtract 1 from the second number. This will bring high risks to the top (score 09) and drop low risks to the bottom (score 01).

    score = + (likelihood -0) + (impact -1)

Using \d- now works. Why do we need this? Suppose we are carrying out an end of project review. We might set up:

:Benefit area:benefit

:Benefit potential:potential (1;2;3;4;5) 0+

:Benefit achieved:achieved (1;2;3;4;5) 5- 

We want to look for areas of high potential benefit and low achievement, to take remedial action. The score values range from 09 (high potential, low achievement) to 01 (low potential, high achievement). The sort works on positive numbers, so we have to shift the second number up by 5:

    score = + (potential - 0) - (achieved - 5)

Changing default field sizes

The designer has some control over the field sizes. The following options for selected <field type> are supported.

(=50)
produces a plain text box 50 columns wide
(text=10*50)
produces a textarea 10 rows by 50 columns
(3*30)
produces 3 text boxes each 30 columns wide; these get joined with \\ markup on save
(email=30 10)
produces a 30 column box for a name and two 10 column boxes for the email address
(author=50)
produces a 50 column text box containing the PmWiki Author
(group=40 Groupname)
produces a 40 column text box

(:wikilist:) options

By default, the list uses the columns specified in the template. But an author can create custom lists that override this. For example:

    (:wikilist !category:) omits the category element from the list
    (:wikilist +priority:) adds the priority element, sorted ascending
    (:wikilist -urgency:) adds the urgency element, sorted descending

To include a new element in the default sort, add an asterisk; for example:

    (:wikilist +*priority:) adds the priority element, ascending and included

To include the page's last modified date (ensure that there is not a form field called 'lastmodified'), write

    (:wikilist +lastmodified:)

Element settings in wikilist override the template settings. If the wikilist includes a name=value option, the selection works whether or not the named element is one of the output columns.

"page" is a special element. It is not a field but rather for setting an option for what will happen when you click on the page links.

To turn the page browse links into links to the edit form view (i.e., edit as a normal wikipage being edited - no wikiforms functionality), enter

    (:wikilist page=edit:)

To turn the page browse links into links to the standard form view (i.e., the wikiforms form from FormTemplate), enter

    (:wikilist page=form:)

Note that this setting alters the NUMERIC page links, not the TITLE page links if you are using the formtitle.php addon.

Template options (new feature)

Sometimes, a site wants to use the same template for multiple groups. Here's how. Suppose there is a need for multiple Risks registers, all using the same risk form template.

  1. Create a suitable template page called Risks.FormTemplate
  2. Create a page called Group1-Risks.HomePage with a (:wikiform:) directive; it will find and use the Risks.FormTemplate
  3. Create another page called Group2-Risks.HomePage with a (:wikiform:) directive; it will also find and use the Risks.FormTemplate

Inter-group links

This describes a projects and tasks application -- many projects, each can have many tasks, but each task is associated with only one project.

Sometimes, a site wants to create a 1-to-many relationship between pages in one group (GroupA) and pages in another, forms-controlled group (GroupB). Suppose the form entry page is GroupB.NewPage:

  1. in the GroupB.FormTemplate, define a field for the link to GroupA, of type (group GroupA) -- in this example, we'll call it keyfield
  2. in GroupA.GroupFooter, write [[GroupB.NewPage?keyfield={$Name} |new GroupB entry]]
  3. That's it; when you click on the link, keyfield will be pre-filled and when you save the new page, it will link back to the page in GroupA that originated the request
  4. You may wish to create a wikilist in GroupA like this: (:wikilist group=GroupB keyfield=GroupA.{$Name}:) to list the related entries in GroupB (e.g. the tasks for this project)

Of course, GroupA can also be a forms-controlled group. In relational terms, this is GroupA---keyfield--<GroupB where keyfield is the name of the entry in GroupA and appears as a foreign key in GroupB.

Issues

It currently requires installation of MarkupExtensions, as it makes use of => right alignment markup. See the modified $GroupFooterFmt.

Messages are in English. These are now in an wikiform-i18n-en.phpΔ file.

Markup to define fields may change. It could be simplified.

What do we do about wiki tables? It would be useful if this could support table editing.

What do we do about vote fields? These could be simple (votes = for - against) or complex (strongly for, for, against, strongly against). For example, the page might look like this:

Votes
7
Forxxxxx xxxx
Againstxx

The form view would let an author vote for or against via a radio button. If we support strongly for and against, such votes might count double.

List Selection Criteria

The = operator matches partial strings ("contains"), so markup of the type (:wikilist status=o:) will display all pages which include the letter o somewhere in the status field.

It is possible to use markup like (:wikilist status=!open:) as well to exclude pages which match a certain criterion.

It is also possible to use 'or' logic, for example (:wikilist status=open|active:). The comma separator means 'and' logic. Status=a,b returns items where status includes a and b. Status=a|b returns items where status includes a or b.

Combining selections with a space implies "and". So (:wikilist status="a b":) means that the status must contain a AND b.

The space and vertical-bar "operators" combine as expected: (:wikilist status="a|b c d|e":) results in "(contains a OR b) AND (contains c) AND (contains d OR e)".

The == operator requires an exact match rather than a "contains." (Like a pattern anchored at beginning and end.) Note that if you use quotes around your query value then the second "=" must be INSIDE the quotes with this syntax: (:wikilist status="=full text":)

Sort order

Click a column once and it sorts according to the template. Click it again and it reverses the sort order.

Immediate Save

You can force the forms recipe to save the page when you press 'Submit'. Add the following line to local/config.php above the line that includes wikiform.php:

  $WikiFormSubmit = 'post'; ## or 'postedit'
Note that if you have $EnablePostAuthorRequired=1; set (in order to require an author) and your form does not include an author field then it will appear that wikiforms is ignoring this setting. In actual fact it is an error in site configuration but instead of reporting the error wikiforms just asks you for the author. —Peter Bowers

Field comment text

To add comment text to a form, use ::definition text, like this:

::comment will appear below the form field

At the moment, it does not recognise wiki markup in such comments.

(NOTE: Avoid colons in this comment text after the initial double-colon. They mess up your form big-time. --PeterBowers)

Dividing the form into groups of fields

Use heading markup. The first heading will be the overall page heading. Subsequent headings are treated as <th> tags in the table of form fields. Use of this feature makes long forms more usable.

More on the overall inner workings of WikiForms

Here is more info on how to setup WikiForms.

Bugs and Feature Requests

(I have tried to organize the numerous comments on this recipe in a useful fasion and separate them from the "bare bones" of the documentation. I hope that makes everything easier to read and a bit more user- (and author-)friendly :-) --Henning August 23, 2006, at 09:35 AM)

See also

  • PmForm   Form processing engine for PmWiki
  • PmForm   Home page for PmForm group, with pagelist

User notes +2: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.