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 | + |