r26285 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r26284‎ | r26285 | r26286 >
Date:20:23, 1 October 2007
Author:evan
Status:old
Tags:
Comment:
Initial (well, OK, 0.2) version of Special:Form, a special page for
creating new, structured pages according to an output template.
Modified paths:
  • /trunk/extensions/SpecialForm (added) (history)
  • /trunk/extensions/SpecialForm/MediaWiki:Sample-form.wiki (added) (history)
  • /trunk/extensions/SpecialForm/README (added) (history)
  • /trunk/extensions/SpecialForm/SpecialForm.body.php (added) (history)
  • /trunk/extensions/SpecialForm/SpecialForm.i18n.php (added) (history)
  • /trunk/extensions/SpecialForm/SpecialForm.setup.php (added) (history)
  • /trunk/extensions/SpecialForm/TODO (added) (history)
  • /trunk/extensions/SpecialForm/Template:Sample.wiki (added) (history)

Diff [purge]

Index: trunk/extensions/SpecialForm/MediaWiki:Sample-form.wiki
@@ -0,0 +1,9 @@
 2+title=Ew-nay Ample-say
 3+namePattern={{{topic}}}
 4+instructions=You can use this page to create a new article on a sample topic.
 5+topic|Topic|text|Topic of the article.
 6+purpose|Purpose|select|Purpose of the
 7+article|items=Business;Pleasure;Other
 8+intro|Introduction|textarea|An introductory paragraph about the topic.
 9+color|Color|radio|Color of the article|items=Red;Blue;Green
 10+conclusion|Conclusion|textarea|The conclusions of the topic.
Index: trunk/extensions/SpecialForm/TODO
@@ -0,0 +1,16 @@
 2++ set title correctly
 3+- add a token to session, store it in the form, and check that they
 4+ match on submit, to prevent automated creation
 5++ create a new article on submit
 6+- required/optional fields
 7++ check for existing article before saving
 8++ add a default value if passed in using GET
 9++ test setting custom title in form description
 10++ test setting custom template in form description
 11++ parse instructions from wikitext to HTML
 12++ parse descriptions from wikitext to HTML
 13+- automatic type-ahead fields
 14+- create more than one article from one form
 15+- text field validation with regexes on client and server
 16+- file upload fields (for uploading an associated image)
 17+
Index: trunk/extensions/SpecialForm/SpecialForm.body.php
@@ -0,0 +1,351 @@
 2+<?php
 3+/**
 4+ * SpecialForm.php -- Use a form-based interface to start new articles
 5+ * Copyright 2007 Vinismo, Inc. (http://vinismo.com/)
 6+ *
 7+ * This program is free software; you can redistribute it and/or modify
 8+ * it under the terms of the GNU General Public License as published by
 9+ * the Free Software Foundation; either version 2 of the License, or
 10+ * (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU General Public License
 18+ * along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20+ *
 21+ * @author Evan Prodromou <evan@vinismo.com>
 22+ * @addtogroup Extensions
 23+ */
 24+
 25+if (!defined('MEDIAWIKI')) {
 26+ exit( 1 );
 27+}
 28+
 29+require_once('XmlFunctions.php');
 30+
 31+class SpecialForm extends SpecialPage
 32+{
 33+ function SpecialForm() {
 34+ SpecialPage::SpecialPage("Form");
 35+ self::loadMessages();
 36+ }
 37+
 38+ function execute( $par ) {
 39+ global $wgRequest, $wgOut;
 40+
 41+ if (!$par) {
 42+ $wgOut->showErrorPage('formnoname', 'formnonametext');
 43+ return;
 44+ }
 45+
 46+ $form = $this->loadForm($par);
 47+
 48+ if (!$form) {
 49+ $wgOut->showErrorPage('formbadname', 'formbadnametext');
 50+ return;
 51+ }
 52+
 53+ if ($wgRequest->wasPosted()) {
 54+ $this->createArticle($form);
 55+ } else {
 56+ $this->showForm($form);
 57+ }
 58+ }
 59+
 60+ function loadMessages() {
 61+ static $messagesLoaded = false;
 62+ global $wgMessageCache;
 63+
 64+ if ( $messagesLoaded ) return;
 65+
 66+ require( dirname( __FILE__ ) . '/SpecialForm.i18n.php' );
 67+ foreach ( $SpecialFormMessages as $lang => $langMessages ) {
 68+ $wgMessageCache->addMessages( $langMessages, $lang );
 69+ }
 70+
 71+ $messagesLoaded = true;
 72+
 73+ return true;
 74+ }
 75+
 76+ function loadForm($name) {
 77+ $nt = Title::makeTitleSafe(NS_MEDIAWIKI, wfMsg('formpattern', $name));
 78+
 79+ # article exists?
 80+
 81+ if (!$nt || $nt->getArticleID() == 0) {
 82+ return NULL;
 83+ }
 84+
 85+ $article = new Article($nt);
 86+
 87+ assert($article);
 88+
 89+ $text = $article->getContent(true);
 90+
 91+ return new Form($name, $text);
 92+ }
 93+
 94+ function showForm($form) {
 95+ global $wgOut, $wgRequest, $wgParser, $wgTitle;
 96+
 97+ $self = SpecialPage::getTitleFor("Form/$form->name");
 98+
 99+ $wgOut->setPageTitle($form->title);
 100+
 101+ if (!is_null($form->instructions)) {
 102+
 103+ $wgOut->addHtml(wfOpenElement('div', array('class' => 'instructions')) .
 104+ $wgOut->parse($form->instructions) .
 105+ wfCloseElement('div') .
 106+ wfElement('br'));
 107+ }
 108+
 109+ $wgOut->addHtml(wfOpenElement('form',
 110+ array('method' => 'POST',
 111+ 'action' => $self->getLocalURL())));
 112+
 113+ foreach ($form->fields as $field) {
 114+ $wgOut->addHtml($field->render($wgRequest->getText($field->name)) . wfElement('br') . "\n");
 115+ }
 116+
 117+ $wgOut->addHtml(wfElement('input', array('type' => 'submit',
 118+ 'value' => wfMsg('formsave'))));
 119+
 120+ $wgOut->addHtml(wfCloseElement('form'));
 121+ }
 122+
 123+ function createArticle($form) {
 124+
 125+ global $wgOut, $wgRequest;
 126+
 127+ $title = $this->makeTitle($form);
 128+
 129+ wfDebug("SpecialForm: saving article '$title'\n");
 130+
 131+ $nt = Title::newFromText($title);
 132+
 133+ if ($nt->getArticleID() != 0) {
 134+ $wgOut->showErrorPage('formarticleexists', 'formarticleexists', array($title));
 135+ return;
 136+ }
 137+
 138+ $text = "{{subst:$form->template";
 139+
 140+ foreach ($form->fields as $name => $field) {
 141+ # XXX: check for required fields
 142+ # FIXME: strip/escape template-related chars (|, =, }})
 143+ $text .= "|$name=" . $wgRequest->getText($name);
 144+ }
 145+
 146+ $text .= "}}";
 147+
 148+ $article = new Article($nt);
 149+
 150+ if ($article->doEdit($text, wfMsg('formsavesummary', $form->name), EDIT_NEW)) {
 151+ $wgOut->redirect($nt->getFullURL());
 152+ } else {
 153+ $wgOut->showErrorPage('formsaveerror', 'formsaveerrortext', array($title));
 154+ }
 155+ }
 156+
 157+ function makeTitle($form) {
 158+ global $wgRequest;
 159+
 160+ $title = $form->namePattern;
 161+
 162+ foreach ($form->fields as $name => $field) {
 163+ $title = preg_replace("/{{\{$name\}}}/", $wgRequest->getText($name), $title);
 164+ }
 165+
 166+ return $title;
 167+ }
 168+
 169+}
 170+
 171+class Form {
 172+ var $name;
 173+ var $title;
 174+ var $template;
 175+ var $instructions;
 176+ var $fields;
 177+ var $namePattern;
 178+
 179+ function Form($name, $text) {
 180+
 181+ $this->name = $name;
 182+ $this->title = wfMsg('formtitlepattern', $name);
 183+ $this->template = wfMsg('formtemplatepattern', $name);
 184+
 185+ $this->fields = array();
 186+ $this->namePattern = NULL;
 187+ $this->instructions = NULL;
 188+
 189+ # XXX: may be some faster ways to do this
 190+
 191+ $lines = explode("\n", $text);
 192+
 193+ foreach ($lines as $line) {
 194+
 195+ if (preg_match('/^(\w+)=(.*)$/', $line, $matches)) {
 196+ if (strcasecmp($matches[1], 'template') == 0) {
 197+ $this->template = $matches[2];
 198+ } else if (strcasecmp($matches[1], 'title') == 0) {
 199+ $this->title = $matches[2];
 200+ } else if (strcasecmp($matches[1], 'namePattern') == 0) {
 201+ $this->namePattern = $matches[2];
 202+ } else if (strcasecmp($matches[1], 'instructions') == 0) {
 203+ $this->instructions = $matches[2];
 204+ wfDebug("Got instructions: '" . $this->instructions . "'.\n");
 205+ } else {
 206+ wfDebug("SpecialForm: unknown form attribute '$matches[1]'; skipping.\n");
 207+ }
 208+ } else if (preg_match('/^(\w+)\|([^\|]+)\|(\w+)(\|([^\|]+)(\|(.*))?)?$/', $line, $matches)) {
 209+ # XXX: build an inheritance tree for different kinds of fields
 210+ $field = new FormField();
 211+ $field->setName($matches[1]);
 212+ $field->setLabel($matches[2]);
 213+ $field->setFieldType($matches[3]);
 214+ if ($matches[4]) {
 215+ $field->setDescription($matches[5]);
 216+ if ($matches[6]) {
 217+ $rawOptions = explode(',', $matches[7]);
 218+ foreach ($rawOptions as $rawOption) {
 219+ if (preg_match('/^(\w+)=(.+)/', $rawOption, $optMatches)) {
 220+ $field->setOption($optMatches[1], $optMatches[2]);
 221+ } else {
 222+ wfDebug("SpecialForm: unrecognized form field option: '$rawOption'; skipping.\n");
 223+ }
 224+ }
 225+ }
 226+ }
 227+ $this->fields[$field->name] = $field;
 228+ } else {
 229+ wfDebug("SpecialForm: unrecognized form line: '$line'; skipping.\n");
 230+ }
 231+ }
 232+ }
 233+}
 234+
 235+class FormField {
 236+
 237+ var $name;
 238+ var $type;
 239+ var $label;
 240+ var $description;
 241+ var $options;
 242+
 243+ function FormField() {
 244+ $this->name = NULL;
 245+ $this->type = NULL;
 246+ $this->label = NULL;
 247+ $this->description = NULL;
 248+ $this->options = array();
 249+ }
 250+
 251+ function setName($name) {
 252+ $this->name = $name;
 253+ }
 254+
 255+ function setFieldType($type) {
 256+ $this->type = $type;
 257+ }
 258+
 259+ function setLabel($label) {
 260+ $this->label = $label;
 261+ }
 262+
 263+ function setDescription($description) {
 264+ $this->description = $description;
 265+ }
 266+
 267+ function setOption($key, $value) {
 268+ $this->options[$key] = $value;
 269+ }
 270+
 271+ function getOption($key, $default = NULL) {
 272+ if (array_key_exists($key, $this->options)) {
 273+ return $this->options[$key];
 274+ } else {
 275+ return $default;
 276+ }
 277+ }
 278+
 279+ function render($def = NULL) {
 280+ global $wgOut;
 281+
 282+ switch ($this->type) {
 283+ case 'textarea':
 284+ return wfOpenElement('h2') .
 285+ wfElement('label', array('for' => $this->name), $this->label) .
 286+ wfCloseElement('h2') .
 287+ (($this->description) ?
 288+ (wfOpenElement('div') . $wgOut->parse($this->description) . wfCloseElement('div')) : '') .
 289+ wfOpenElement('textarea', array('name' => $this->name,
 290+ 'id' => $this->name,
 291+ 'rows' => $this->getOption('rows', 6),
 292+ 'cols' => $this->getOption('cols', 80))) .
 293+ ((is_null($def)) ? '' : $def) .
 294+ wfCloseElement('textarea');
 295+ break;
 296+ case 'text':
 297+ return wfElement('label', array('for' => $this->name), $this->label) . ": " .
 298+ wfElement('input', array('type' => 'text',
 299+ 'name' => $this->name,
 300+ 'id' => $this->name,
 301+ 'value' => ((is_null($def)) ? '' : $def),
 302+ 'size' => $this->getOption('size', 30)));
 303+ break;
 304+ case 'checkbox':
 305+ $attrs = array('type' => 'checkbox',
 306+ 'name' => $this->name,
 307+ 'id' => $this->name);
 308+ if ($def == 'checked') {
 309+ $attrs['checked'] = 'checked';
 310+ }
 311+ return wfElement('label', array('for' => $this->name), $this->label) . ": " .
 312+ wfElement('input', $attrs);
 313+ break;
 314+ case 'radio':
 315+ $items = array();
 316+ $rawitems = explode(';', $this->getOption('items'));
 317+ foreach ($rawitems as $item) {
 318+ $attrs = array('type' => 'radio',
 319+ 'name' => $this->name,
 320+ 'value' => $item);
 321+ if ($item == $def) {
 322+ $attrs['checked'] = 'checked';
 323+ }
 324+ $items[] = wfOpenElement('input', $attrs) .
 325+ wfElement('label', null, $item) .
 326+ wfCloseElement('input');
 327+ }
 328+ return wfElement('span', null, $this->label) . wfElement('br') . implode("", $items);
 329+ break;
 330+ case 'select':
 331+ $items = array();
 332+ $rawitems = explode(';', $this->getOption('items'));
 333+ foreach ($rawitems as $item) {
 334+ $items[] = wfElement('option',
 335+ ($item == $def) ? array('selected' => 'selected') : null,
 336+ $item);
 337+ }
 338+
 339+ return wfElement('label', array('for' => $this->name), $this->label) . ": " .
 340+ wfOpenElement('select', array('name' => $this->name, 'id' => $this->name)) .
 341+ implode("", $items) .
 342+ wfCloseElement('select');
 343+
 344+ break;
 345+ default:
 346+ wfDebug("SpecialForm: unknown form field type '$this->type', skipping.\n");
 347+ return '';
 348+ }
 349+ }
 350+}
 351+
 352+?>
\ No newline at end of file
Index: trunk/extensions/SpecialForm/SpecialForm.i18n.php
@@ -0,0 +1,45 @@
 2+<?php
 3+/**
 4+ * SpecialForm.i18n.php -- I18N for form-based interface to start new articles
 5+ * Copyright 2007 Vinismo, Inc. (http://vinismo.com/)
 6+ *
 7+ * This program is free software; you can redistribute it and/or modify
 8+ * it under the terms of the GNU General Public License as published by
 9+ * the Free Software Foundation; either version 2 of the License, or
 10+ * (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU General Public License
 18+ * along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20+ *
 21+ * @author Evan Prodromou <evan@vinismo.com>
 22+ * @addtogroup Extensions
 23+ */
 24+
 25+if (!defined('MEDIAWIKI')) {
 26+ exit( 1 );
 27+}
 28+
 29+$SpecialFormMessages =
 30+ array('en' => array('form' => 'Form',
 31+ 'formnoname' => 'No Form Name',
 32+ 'formnonametext' => 'You must provide a form name, like "Special:Form/Nameofform".',
 33+ 'formbadname' => 'Bad Form Name',
 34+ 'formbadnametext' => 'There is no form by that name.',
 35+ 'formpattern' => '$1-form',
 36+ 'formtemplatepattern' => '$1',
 37+ 'formtitlepattern' => 'Add New $1',
 38+ 'formsave' => 'Save',
 39+ 'formarticleexists' => 'Article Exists',
 40+ 'formarticleexiststext' => 'The article [[$1]] already exists.',
 41+ 'formsavesummary' => 'New article using [[Special:Form/$1]]',
 42+ 'formsaveerror' => 'Error Saving Form',
 43+ 'formsaveerrortext' => 'There was an unknown error saving article \'$1\'.'),
 44+ 'fr' => array('form' => 'Formule'));
 45+
 46+?>
\ No newline at end of file
Index: trunk/extensions/SpecialForm/SpecialForm.setup.php
@@ -0,0 +1,53 @@
 2+<?php
 3+/**
 4+ * SpecialForm.php -- Use a form-based interface to start new articles
 5+ * Copyright 2007 Vinismo, Inc. (http://vinismo.com/)
 6+ *
 7+ * This program is free software; you can redistribute it and/or modify
 8+ * it under the terms of the GNU General Public License as published by
 9+ * the Free Software Foundation; either version 2 of the License, or
 10+ * (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU General Public License for more details.
 16+ *
 17+ * You should have received a copy of the GNU General Public License
 18+ * along with this program; if not, write to the Free Software
 19+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20+ *
 21+ * @author Evan Prodromou <evan@vinismo.com>
 22+ * @addtogroup Extensions
 23+ */
 24+
 25+if (!defined('MEDIAWIKI')) {
 26+ exit( 1 );
 27+}
 28+
 29+define('SPECIALFORM_VERSION', '0.2');
 30+
 31+$wgAutoloadClasses['SpecialForm'] = dirname(__FILE__) . '/SpecialForm.body.php'; # Tell MediaWiki to load the extension body.
 32+$wgSpecialPages['Form'] = 'SpecialForm'; # Let MediaWiki know about your new special page.
 33+$wgHooks['LoadAllMessages'][] = 'SpecialForm::loadMessages'; # Load the internationalization messages for your special page.
 34+$wgHooks['LanguageGetSpecialPageAliases'][] = 'formLocalizedPageName'; # Add any aliases for the special page.
 35+
 36+$wgExtensionCredits['specialpage'][] = array('name' => 'Form',
 37+ 'version' => SPECIALFORM_VERSION,
 38+ 'author' => 'Evan Prodromou',
 39+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Form',
 40+ 'description' => 'A form interface to start new articles');
 41+
 42+function formLocalizedPageName(&$specialPageArray, $code) {
 43+ # The localized title of the special page is among the messages of the extension:
 44+ MyExtension::loadMessages();
 45+ $text = wfMsg('form');
 46+
 47+ # Convert from title in text form to DBKey and put it into the alias array:
 48+ $title = Title::newFromText($text);
 49+ $specialPageArray['Form'][] = $title->getDBKey();
 50+
 51+ return true;
 52+}
 53+
 54+?>
\ No newline at end of file
Index: trunk/extensions/SpecialForm/Template:Sample.wiki
@@ -0,0 +1,15 @@
 2+The topic is {{{topic}}}.
 3+
 4+The purpose is {{{purpose}}}.
 5+
 6+== Introduction ==
 7+
 8+{{{intro}}}
 9+
 10+== Color ==
 11+
 12+{{{color}}}
 13+
 14+== Conclusion ==
 15+
 16+{{{conclusion}}}
Index: trunk/extensions/SpecialForm/README
@@ -0,0 +1,206 @@
 2+MediaWiki Form extension
 3+
 4+version 0.2
 5+1 Oct 2007
 6+
 7+This is the README file for the Form extension for MediaWiki
 8+software. The extension is only useful if you've got a MediaWiki
 9+installation; it can only be installed by the administrator of the site.
 10+
 11+The extension lets users create new articles with a form interface.
 12+Administrators configure a "form definition" in the MediaWiki namespace,
 13+and the form can be used to create a new article using a particular
 14+template.
 15+
 16+Typical uses:
 17+
 18+* "New X" interfaces for wiki newbies.
 19+
 20+This is a testing version of the extension and it's almost sure to
 21+have bugs. See the BUGS section below for info on how to report
 22+problems.
 23+
 24+== License ==
 25+
 26+Copyright 2007 Vinismo, Inc. (http://vinismo.com/)
 27+
 28+This program is free software; you can redistribute it and/or modify
 29+it under the terms of the GNU General Public License as published by
 30+the Free Software Foundation; either version 2 of the License, or
 31+(at your option) any later version.
 32+
 33+This program is distributed in the hope that it will be useful,
 34+but WITHOUT ANY WARRANTY; without even the implied warranty of
 35+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 36+GNU General Public License for more details.
 37+
 38+You should have received a copy of the GNU General Public License
 39+along with this program; if not, write to the Free Software
 40+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 41+
 42+== Author ==
 43+
 44+Evan Prodromou <evan@vinismo.com>
 45+
 46+== Pre-requisites ==
 47+
 48+This software was tested with MediaWiki 1.10.0 (which is what
 49+Vinismo was running at the time.) It may or may not work with
 50+earlier or later versions, but please test it.
 51+
 52+== Installation ==
 53+
 54+To install, copy all the files in the archive you downloaded to the
 55+SpecialForm subdirectory of the extensions subdirectory of your
 56+MediaWiki installation. Note that the software depends on having its
 57+code all in the "SpecialForm" sub-directory; naming it
 58+"SpecialForm-Test" or "newextension1" or whatever won't work.
 59+
 60+In your MediaWiki LocalSettings.php, add the following line some place
 61+towards the bottom of the file:
 62+
 63+ require_once("$IP/extensions/SpecialForm/SpecialForm.setup.php");
 64+
 65+Theoretically it should work out of the box.
 66+
 67+== Preparing forms ==
 68+
 69+To create a new form, you need to do two things:
 70+
 71+* Create a "form definition" in the MediaWiki namespace.
 72+* Create an output template that describes the structure of the
 73+ resulting articles.
 74+
 75+Form definitions use a special idiosyncratic syntax that may change in
 76+the future.
 77+
 78+Output templates are just regular ol' MediaWiki templates. They should
 79+use ''named'' parameters rather than numbered parameters.
 80+
 81+There is a sample form definition article in
 82+"MediaWiki:Sample-form.wiki" that came with this package, and a
 83+corresponding output template in "Template:Sample.wiki".
 84+
 85+== Form definitions ==
 86+
 87+A form definition article must be named "MediaWiki:nameofform-form",
 88+where "nameofform" is the name you're going to use for the form. (You
 89+can change this pattern by changing MediaWiki:Formpattern, but note
 90+that this will affect all of your forms.)
 91+
 92+Each line in the form definition file is either a form attribute or a
 93+form field definition. Each is described below.
 94+
 95+=== Form attributes ===
 96+
 97+Form attributes define information for the form as a whole. Each
 98+attribute line looks like:
 99+
 100+ name=value
 101+
 102+Note that no whitespace is tolerated before and after the name.
 103+Typically form attributes appear at the beginning of an article, but
 104+they are tolerated anywhere in the article, if you need things that way.
 105+
 106+Valid names for form attributes are as follows:
 107+
 108+* template: name of the output template (without the namespace prefix)
 109+ that will be used for creating new articles. If this is not defined,
 110+ the default name will be "Template:Name", where "name" is the name
 111+ of the form.
 112+* title: title that's shown on the form. By default, this is "Add New
 113+ $1", where $1 is the name of the form. You can change the
 114+ default title pattern with by changing MediaWiki:Formtemplatepattern.
 115+* namePattern: the pattern for new article names. This is based on the
 116+ fields in the form, and uses MediaWiki template-substitution syntax
 117+ (badly... only the simplest syntax is now supported). For example,
 118+ if you are creating articles about sporting events results, and
 119+ there are two form fields "year" and "event", the name pattern might
 120+ be "{{{year}}} {{{event}}} Results". If the user fills in "2004" and
 121+ "World Series", the resulting article will be "2004 World Series
 122+ Results".
 123+* instructions: plain text (no wikitext or HTML... yet) instructions
 124+ for users of the form. Will be shown at the top of the form before
 125+ any fields.
 126+
 127+=== Form field definitions ===
 128+
 129+Each field in the form has a line defining it in the form definition
 130+file. The structure of the field definition lines is:
 131+
 132+ name|label|type|description|options
 133+
 134+The parts of the field definition are separated by pipe ("|")
 135+characters and cannot include pipes themselves (even with "escape"
 136+characters). The parts of the definition are defined below:
 137+
 138+* name: name of the field. It must be unique, and contain only
 139+ alphabetic or numeric characters or the underscore ("_"). This will
 140+ be the parameter name used for the output template.
 141+* label: readable name for the field, used for labels. No
 142+ restrictions, except for the lack of a pipe. No HTML or wikitext
 143+ allowed (yet).
 144+* type: type of the form field (see below).
 145+* description: a user-readable description of the purpose and
 146+ restrictions on the form field. Only shown for 'textarea' fields
 147+ right now, but will eventually be shown for all fields once I figure
 148+ out the layout correctly.
 149+* options: optional parameters for the field, mostly dependent on the
 150+ field type. options always take the form "name=value", and are
 151+ separated by commas (",").
 152+
 153+The description and options parts are optional.
 154+
 155+=== Form field types ===
 156+
 157+The following types of form fields can be created.
 158+
 159+* textarea: an HTML textarea, e.g. a big multi-line entry area. These
 160+ are usually used for lots of paragraphs. The following options are
 161+ supported:
 162+** rows: number of rows; defaults to 6.
 163+** cols: number of columns; defaults to 80.
 164+* text: a one-line text input. Takes these options:
 165+** size: length of the text input; defaults to 30.
 166+* checkbox: a yes-no, on-off choice for the user. Takes no options.
 167+* radio: a group of radio buttons; exclusive choices. Radion button
 168+ groups take the following options:
 169+** items: semicolon-separated (";") list of choices for the user. For
 170+ example, "Blue;Green;Red" will give the user three radio buttons
 171+ labeled "Blue", "Green", and "Red".
 172+* select: a drop-down box showing multiple exclusive choices for the
 173+ user. Select boxes take the following options:
 174+** items: semicolon-separated (";") list of choices for the user. For
 175+ example, "Blue;Green;Red" will give the user a drop-down box with
 176+ three choices, "Blue", "Green", and "Red".
 177+
 178+== Using forms ==
 179+
 180+To show a user a form, use the following special-page format:
 181+
 182+ Special:Form/Name
 183+
 184+Where "name" is the name of the form. This will load the form
 185+definition from "MediaWiki:Name-form", and by default use
 186+Template:Name for the output template.
 187+
 188+The user can fill in the form fields and hit "save" to save the
 189+article. Note that currently no validation is performed; if the user
 190+fails to complete a required field, it will be rendered empty.
 191+
 192+== Translation ==
 193+
 194+The user interface strings for this extension are configurable through
 195+the same Special:Allmessages page as MediaWiki itself. They all start
 196+with "form", and they're no more or less cryptic than MediaWiki's.
 197+
 198+Translations to other languages besides English are welcome; please
 199+send them along.
 200+
 201+== Bugs and enhancements ==
 202+
 203+Bugs or feature requests can be sent to the author at
 204+evan@vinismo.com. The TODO file in this distribution has stuff I
 205+think needs to be todone; + marks show things I've already done, and -
 206+shows things that are yet to be done.
 207+

Status & tagging log