Difference between revisions of "Extension:SimpleForms.php"

From Organic Design wiki
(setPageTitle doesn't work for OD, use an inline style instead)
(change query globals to constants and linke in processRequest())
Line 8: Line 8:
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
  
define('SIMPLEFORMS_VERSION','0.0.9, 2007-06-11');
+
define('SIMPLEFORMS_VERSION', '0.0.9, 2007-06-11');
 +
define('SIMPLEFORMS_UNTITLED','UNTITLED');
 +
define('SIMPLEFORMS_CONTENT', 'content');  # query-string item used for parsing wikitext content
 +
define('SIMPLEFORMS_CACTION', 'caction');  # query-string item to specify whether to prepend, append or replace existing content
 +
define('SIMPLEFORMS_SUMMARY', 'summary');  # query-string item to specify an edit summary when updating or creating content
  
 
$wgSimpleFormsFormMagic        = "form";    # the parser-function name for form containers
 
$wgSimpleFormsFormMagic        = "form";    # the parser-function name for form containers
Line 16: Line 20:
 
$wgSimpleFormsRequestPrefix    = "sf_";    # restricts #request and GET/POST variable names to their own namespace, set to "" to disable
 
$wgSimpleFormsRequestPrefix    = "sf_";    # restricts #request and GET/POST variable names to their own namespace, set to "" to disable
 
$wgSimpleFormsCreateAction    = true;      # whether or not to add an action button for article-creation
 
$wgSimpleFormsCreateAction    = true;      # whether or not to add an action button for article-creation
$wgSimpleFormsContentQuery    = 'content'; # the name of the query-string item used to parse content directly
 
$wgSimpleFormsCActionQuery    = 'caction'; # what to do with the content if the title already exists, values are replace(default),append,prepend
 
$wgSimpleFormsSummaryQuery    = 'summary'; # if the action causes a new revision, this specifies the edit summary text
 
 
$wgSimpleFormsServerUser      = '';        # Set this to an existing username so server IP doesn't show up in changes
 
$wgSimpleFormsServerUser      = '';        # Set this to an existing username so server IP doesn't show up in changes
 +
$wgSimpleFormsAllowCreate      = true;      # Allow creating new articles from content query item
 +
$wgSimpleFormsAllowEdit        = true;      # Allow appending, prepending or replacing of content in existing articles from query item
 
$wgSimpleFormsAllowRemoteAddr  = array($_SERVER['SERVER_ADDR'],'127.0.0.1'); # Allow anonymous edits from these addresses
 
$wgSimpleFormsAllowRemoteAddr  = array($_SERVER['SERVER_ADDR'],'127.0.0.1'); # Allow anonymous edits from these addresses
  
Line 41: Line 44:
 
# If there is content passed in the request but no title, set title to the dummy "UNTITLED" article, and add a hook to replace the content
 
# If there is content passed in the request but no title, set title to the dummy "UNTITLED" article, and add a hook to replace the content
 
# - there's probably a better way to do this, but this will do for now
 
# - there's probably a better way to do this, but this will do for now
if (!empty($wgSimpleFormsContentQuery) && isset($_REQUEST[$wgSimpleFormsContentQuery]) && !isset($_REQUEST['title'])) {
+
if (isset($_REQUEST[SIMPLEFORMS_CONTENT]) && !isset($_REQUEST['title'])) {
 
$wgHooks['ArticleAfterFetchContent'][] = 'wfSimpleFormsUntitledContent';
 
$wgHooks['ArticleAfterFetchContent'][] = 'wfSimpleFormsUntitledContent';
$_REQUEST['title'] = 'UNTITLED';
+
$_REQUEST['title'] = SIMPLEFORMS_UNTITLED;
 
}
 
}
 
function wfSimpleFormsUntitledContent(&$article,&$text) {
 
function wfSimpleFormsUntitledContent(&$article,&$text) {
global $wgOut,$wgRequest,$wgSimpleFormsContentQuery;
+
global $wgOut,$wgRequest;
if ($article->getTitle()->getText() == 'UNTITLED') {
+
if ($article->getTitle()->getText() == SIMPLEFORMS_UNTITLED) {
$text = $wgRequest->getText($wgSimpleFormsContentQuery);
+
$text = $wgRequest->getText(SIMPLEFORMS_CONTENT);
$wgOut->addScript('<style>h1.firstHeading{display:none}</style>');
+
$wgOut->addScript('<style>h1.firstHeading{display:none}</style>'); # Remove title for UNTITLED pages
 
}
 
}
 
  return true;
 
  return true;
Line 73: Line 76:
 
function SimpleForms() {
 
function SimpleForms() {
 
global $wgParser,$wgHooks,$wgSimpleFormsCreateAction,
 
global $wgParser,$wgHooks,$wgSimpleFormsCreateAction,
$wgSimpleFormsFormMagic,$wgSimpleFormsInputMagic,$wgSimpleFormsRequestMagic,$wgSimpleFormsEditFormMagic;
+
      $wgSimpleFormsFormMagic,$wgSimpleFormsInputMagic,$wgSimpleFormsRequestMagic,$wgSimpleFormsEditFormMagic;
 
$wgParser->setFunctionHook($wgSimpleFormsFormMagic,      array($this,'normalFormMagic'));
 
$wgParser->setFunctionHook($wgSimpleFormsFormMagic,      array($this,'normalFormMagic'));
 
$wgParser->setFunctionHook($wgSimpleFormsEditFormMagic,  array($this,'editFormMagic'));
 
$wgParser->setFunctionHook($wgSimpleFormsEditFormMagic,  array($this,'editFormMagic'));
Line 79: Line 82:
 
$wgParser->setFunctionHook($wgSimpleFormsRequestMagic,  array($this,'requestMagic'));
 
$wgParser->setFunctionHook($wgSimpleFormsRequestMagic,  array($this,'requestMagic'));
 
if ($wgSimpleFormsCreateAction) $wgHooks['SkinTemplateTabs'][] = $this;
 
if ($wgSimpleFormsCreateAction) $wgHooks['SkinTemplateTabs'][] = $this;
 
+
$this->createUntitled();
# Create a dummy article for rendering content not associated with any title (unless it already exists)
+
$this->processRequest();
# - there's probably a better way to do this
 
$untitled = 'UNTITLED';
 
$title = Title::newFromText($untitled);
 
if (!$title->exists()) {
 
$article = new Article($title);
 
$article->insertNewArticle(
 
'Dummy article used by [http://www.mediawiki.org/wiki/Extension:Simple_Forms Extension:SimpleForms]',
 
'Dummy article created for Simple Forms extension',
 
true,
 
false
 
);
 
}
 
 
}
 
}
  
Line 116: Line 107:
 
if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $args .= " $match[1]=\"$match[2]\""; else $form = $arg;
 
if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $args .= " $match[1]=\"$match[2]\""; else $form = $arg;
 
}
 
}
return array("<form {$args}id=\"$id\">$form</form>",'noparse'=>true);
+
return array("<form {$args}id=\"$id\">$form</form>",'noparse' => true);
 
}
 
}
  
Line 173: Line 164:
 
}
 
}
  
return array($input,'noparse'=>true);
+
return array($input,'noparse' => true);
 
}
 
}
  
Line 203: Line 194:
 
# Processes HTTP reuqests containing wikitext content
 
# Processes HTTP reuqests containing wikitext content
 
function processRequest() {
 
function processRequest() {
global $wgRequest,$wgSimpleFormsContentQuery,$wgSimpleFormsCActionQuery,$wgSimpleFormsAllowRemoteAddr;
+
global $wgRequest,$wgSimpleFormsAllowRemoteAddr,$wgSimpleFormsAllowCreate,$wgSimpleFormsAllowEdit;
if (empty($wgSimpleFormsContentQuery)) return;
 
 
$allow  = in_array($_SERVER['REMOTE_ADDR'],$wgSimpleFormsAllowRemoteAddr);
 
$allow  = in_array($_SERVER['REMOTE_ADDR'],$wgSimpleFormsAllowRemoteAddr);
$content = trim($wgReuqest->getText($wgSimpleFormsContentQuery));
+
$content = trim($wgReuqest->getText(SIMPLEFORMS_CONTENT));
$caction = strtolower($wgReuqest->getText($wgSimpleFormsCActionQuery));
+
$caction = strtolower($wgReuqest->getText(SIMPLEFORMS_CACTION));
$summary = $wgReuqest->getText($wgSimpleFormsSummaryQuery);
+
$summary = $wgReuqest->getText(SIMPLEFORMS_SUMMARY);
 
$title  = Title::newFromText($wgReuqest->getText('title'));
 
$title  = Title::newFromText($wgReuqest->getText('title'));
 
if (is_object($title) && !empty($content)) {
 
if (is_object($title) && !empty($content)) {
 
$article = new Article($title);
 
$article = new Article($title);
if ($title->exists() && ($allow || $title->userCan('edit'))) {
+
if ($title->exists() && $wgSimpleFormsAllowEdit && ($allow || $title->userCan('edit'))) {
 
# Title exists, prepend/append/replace content
 
# Title exists, prepend/append/replace content
 
if    ($caction == 'prepend') $content .= "\n".$article->getContent();
 
if    ($caction == 'prepend') $content .= "\n".$article->getContent();
Line 219: Line 209:
 
$article->updateArticle($text,wfMsg('sf_editsummary',$caction.'ed',false,false));
 
$article->updateArticle($text,wfMsg('sf_editsummary',$caction.'ed',false,false));
 
}
 
}
elseif ($allow || $title->userCan('create')) {
+
elseif ($wgSimpleFormsAllowCreate && ($allow || $title->userCan('create'))) {
 
# No such title, create from content
 
# No such title, create from content
 
$article->insertNewArticle($content,wfMsg('sf_editsummary','created',false,false));
 
$article->insertNewArticle($content,wfMsg('sf_editsummary','created',false,false));
Line 244: Line 234:
 
# Needed in some versions to prevent Special:Version from breaking
 
# Needed in some versions to prevent Special:Version from breaking
 
function __toString() { return 'SimpleForms'; }
 
function __toString() { return 'SimpleForms'; }
 +
 +
# Create a dummy article for rendering content not associated with any title (unless it already exists)
 +
# - there's probably a better way to do this
 +
function createUntitled() {
 +
$title = Title::newFromText(SIMPLEFORMS_UNTITLED);
 +
if (!$title->exists()) {
 +
$article = new Article($title);
 +
$article->insertNewArticle(
 +
'Dummy article used by [http://www.mediawiki.org/wiki/Extension:Simple_Forms Extension:SimpleForms]',
 +
'Dummy article created for Simple Forms extension',
 +
true,
 +
false
 +
);
 +
}
 +
}
  
 
}
 
}
Line 292: Line 297:
 
return true;
 
return true;
 
}
 
}
 
 
?>
 
?>

Revision as of 10:59, 11 June 2007

<?php

  1. MediaWiki SimpleForms ExtensionTemplate:Php
Info.svg These are the MediaWiki extensions we're using and/or developing. Please refer to the information on the mediawiki.org wiki for installation and usage details. Extensions here which have no corresponding mediawiki article are either not ready for use or have been superseded. You can also browse our extension code in our local Subversion repository or our GitHub mirror.
  1. - See http://www.mediawiki.org/wiki/Extension:Simple_Forms for installation and usage details
  2. - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
  3. - Author: http://www.organicdesign.co.nz/nad
  4. - Started: 2007-04-25, see article history

if (!defined('MEDIAWIKI')) die('Not an entry point.');

define('SIMPLEFORMS_VERSION', '0.0.9, 2007-06-11'); define('SIMPLEFORMS_UNTITLED','UNTITLED'); define('SIMPLEFORMS_CONTENT', 'content'); # query-string item used for parsing wikitext content define('SIMPLEFORMS_CACTION', 'caction'); # query-string item to specify whether to prepend, append or replace existing content define('SIMPLEFORMS_SUMMARY', 'summary'); # query-string item to specify an edit summary when updating or creating content

$wgSimpleFormsFormMagic = "form"; # the parser-function name for form containers $wgSimpleFormsEditFormMagic = "edit"; # the parser-function name for form which are for editing/creating articles $wgSimpleFormsInputMagic = "input"; # the parser-function name for form inputs $wgSimpleFormsRequestMagic = "request"; # the parser-function name for accessing the post/get variables $wgSimpleFormsRequestPrefix = "sf_"; # restricts #request and GET/POST variable names to their own namespace, set to "" to disable $wgSimpleFormsCreateAction = true; # whether or not to add an action button for article-creation $wgSimpleFormsServerUser = ; # Set this to an existing username so server IP doesn't show up in changes $wgSimpleFormsAllowCreate = true; # Allow creating new articles from content query item $wgSimpleFormsAllowEdit = true; # Allow appending, prepending or replacing of content in existing articles from query item $wgSimpleFormsAllowRemoteAddr = array($_SERVER['SERVER_ADDR'],'127.0.0.1'); # Allow anonymous edits from these addresses

$wgExtensionFunctions[] = 'wfSetupSimpleForms'; $wgHooks['LanguageGetMagic'][] = 'wfSimpleFormsLanguageGetMagic';

$wgExtensionCredits['parserhook'][] = array( 'name' => 'Simple Forms', 'author' => 'User:Nad', 'description' => 'Functions to make and process forms.', 'url' => 'http://www.mediawiki.org/wiki/Extension:Simple_Forms', 'version' => SIMPLEFORMS_VERSION );

  1. This extension also adds a specialpage for creating new articles

require_once "$IP/includes/SpecialPage.php";

  1. todo: handle action=edit by making $_REQUEST['preload']='UNTITLED' and still add the AAFC hook
  2. handle action=raw by changing action to render and adding SimpleForms::raw to an appropriate hook
  1. If there is content passed in the request but no title, set title to the dummy "UNTITLED" article, and add a hook to replace the content
  2. - there's probably a better way to do this, but this will do for now

if (isset($_REQUEST[SIMPLEFORMS_CONTENT]) && !isset($_REQUEST['title'])) { $wgHooks['ArticleAfterFetchContent'][] = 'wfSimpleFormsUntitledContent'; $_REQUEST['title'] = SIMPLEFORMS_UNTITLED; } function wfSimpleFormsUntitledContent(&$article,&$text) { global $wgOut,$wgRequest; if ($article->getTitle()->getText() == SIMPLEFORMS_UNTITLED) { $text = $wgRequest->getText(SIMPLEFORMS_CONTENT); $wgOut->addScript('<style>h1.firstHeading{display:none}</style>'); # Remove title for UNTITLED pages }

	return true;

}

  1. If the request originates locally, auto-authenticate the user to the server-user

if (!empty($wgSimpleFormsServerUser) && in_array($_SERVER['REMOTE_ADDR'],$wgSimpleFormsAllowRemoteAddr)) $wgHooks['AutoAuthenticate'][] = 'wfSimpleFormsAutoAuthenticate'; function wfSimpleFormsAutoAuthenticate(&$user) { global $wgSimpleFormsServerUser; $u = User::newFromName($wgSimpleFormsServerUser); if ($u->getID()) $user = $u; return true; }

  1. Define a singleton for SimpleForms operations

class SimpleForms {

var $id = 0; var $edit = false;

# Constructor function SimpleForms() { global $wgParser,$wgHooks,$wgSimpleFormsCreateAction, $wgSimpleFormsFormMagic,$wgSimpleFormsInputMagic,$wgSimpleFormsRequestMagic,$wgSimpleFormsEditFormMagic; $wgParser->setFunctionHook($wgSimpleFormsFormMagic, array($this,'normalFormMagic')); $wgParser->setFunctionHook($wgSimpleFormsEditFormMagic, array($this,'editFormMagic')); $wgParser->setFunctionHook($wgSimpleFormsInputMagic, array($this,'inputMagic')); $wgParser->setFunctionHook($wgSimpleFormsRequestMagic, array($this,'requestMagic')); if ($wgSimpleFormsCreateAction) $wgHooks['SkinTemplateTabs'][] = $this; $this->createUntitled(); $this->processRequest(); }

function normalFormMagic(&$parser) { $argv = func_get_args(); return $this->renderForm($argv); }

function editFormMagic(&$parser) { $argv = func_get_args(); return $this->renderForm($argv,true); }

# Renders a form and wraps it in tags for processing by tagHook # - if it's an edit-form it will return empty-string unless $this->edit is true # i.e. $this->edit would be set by the edit-hook or create-specialpage parsing it function renderForm(&$argv,$editform = false) { if ($editform && !$this->edit) return ; $id = $this->id++; $form = ; $args = ; foreach ($argv as $arg) if (!is_object($arg)) { if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $args .= " $match[1]=\"$match[2]\""; else $form = $arg; } return array("<form {$args}id=\"$id\">$form</form>",'noparse' => true); }

# Renders a form input function inputMagic(&$parser) { global $wgSimpleFormsRequestPrefix;

               $content = ;
               $method  = ;
               $type    = ;
               $args    = ;
               $argv    = array();

# Process args foreach (func_get_args() as $arg) if (!is_object($arg)) { if (preg_match('/^([a-z0-9_]+?)\\s*=(.+)$/is',$arg,$match)) $argv[trim($match[1])] = trim($match[2]); else $content = trim($arg); } if (isset($argv['type'])) $type = $argv['type']; else $type = ; if (isset($argv['name'])) $argv['name'] = $wgSimpleFormsRequestPrefix.$argv['name'];

# Textarea if ($type == 'textarea') { unset($argv['type']); foreach ($argv as $k => $v) $args .= " $k=\"$v\""; $input = "<textarea$args>$content</textarea>"; }

# Select list elseif ($type == 'select') {

                       unset($argv['type']);
                       if (isset($argv['value'])) {
                               $val = $argv['value'];
                               unset($argv['value']);
                               } else $val = ;
                       foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
                       preg_match_all('/^\\*\\s*(.*?)\\s*$/m',$content,$m);
                       $input = "<select$args>\n";
                       foreach ($m[1] as $opt) {
                               $sel = $opt == $val ? ' selected' : ;
                               $input .= "<option$sel>$opt</option>\n";
                               }
                       $input .= "</select>\n";

}

# Submit button (changes to onClick) elseif ($type == 'submit' && $method == 'live') { unset($argv['type']); foreach ($argv as $k => $v) $args .= " $k=\"$v\""; }

# Default: render as normal input element else { foreach ($argv as $k => $v) $args .= " $k=\"$v\""; $input = "<input$args/>"; }

return array($input,'noparse' => true); }

# Return value from the global $_REQUEST array (containing GET/POST variables) function requestMagic(&$parser,$key) { global $wgRequest,$wgSimpleFormsRequestPrefix; return $wgRequest->getText($wgSimpleFormsRequestPrefix.$key); }

# Add a "create" tab for creating new articles from creation forms function onSkinTemplateTabs(&$skin,&$actions) { global $wgRequest; $action = $wgRequest->getText('action'); $tmp = $actions; $actions = array(); foreach ($tmp as $k => $v) { if (strtolower($k) == 'delete') { $actions['sf_create'] = array( 'class' => ($action == 'sf_create') ? 'selected' : false, 'text' => 'create', 'href' => Title::makeTitle(NS_SPECIAL,'CreateArticle')->getLocalURL() ); } $actions[$k] = $v; } return true; }

# Processes HTTP reuqests containing wikitext content function processRequest() { global $wgRequest,$wgSimpleFormsAllowRemoteAddr,$wgSimpleFormsAllowCreate,$wgSimpleFormsAllowEdit; $allow = in_array($_SERVER['REMOTE_ADDR'],$wgSimpleFormsAllowRemoteAddr); $content = trim($wgReuqest->getText(SIMPLEFORMS_CONTENT)); $caction = strtolower($wgReuqest->getText(SIMPLEFORMS_CACTION)); $summary = $wgReuqest->getText(SIMPLEFORMS_SUMMARY); $title = Title::newFromText($wgReuqest->getText('title')); if (is_object($title) && !empty($content)) { $article = new Article($title); if ($title->exists() && $wgSimpleFormsAllowEdit && ($allow || $title->userCan('edit'))) { # Title exists, prepend/append/replace content if ($caction == 'prepend') $content .= "\n".$article->getContent(); elseif ($caction == 'append') $content = $article->getContent()."\n$content"; else $caction = 'replac'; $article->updateArticle($text,wfMsg('sf_editsummary',$caction.'ed',false,false)); } elseif ($wgSimpleFormsAllowCreate && ($allow || $title->userCan('create'))) { # No such title, create from content $article->insertNewArticle($content,wfMsg('sf_editsummary','created',false,false)); } else header('HTTP/1.0 403 Forbidden'); } }

# Return the raw content function raw() { global $wgParser,$wgRequest; $expand = $wgRequest->getText('templates') == 'expand'; $rev = Revision::newFromTitle($title,$this->mOldId); if ($rev) { $lastmod = wfTimestamp(TS_RFC2822,$rev->getTimestamp()); header("Last-modified: $lastmod"); $text = $rev->getText(); if ($text && $expand) $wgParser->preprocess($text,$title,new ParserOptions()); return $text; } else header('HTTP/1.0 404 Not Found'); }

# Needed in some versions to prevent Special:Version from breaking function __toString() { return 'SimpleForms'; }

# Create a dummy article for rendering content not associated with any title (unless it already exists) # - there's probably a better way to do this function createUntitled() { $title = Title::newFromText(SIMPLEFORMS_UNTITLED); if (!$title->exists()) { $article = new Article($title); $article->insertNewArticle( 'Dummy article used by Extension:SimpleForms', 'Dummy article created for Simple Forms extension', true, false ); } }

}

  1. Define a new class based on the SpecialPage class

class SpecialCreateArticle extends SpecialPage {

# Constructor function SpecialCreateArticle() { SpecialPage::SpecialPage('CreateArticle'); }

# Override SpecialPage::execute() function execute($param) { global $wgOut; $title = Title::makeTitle(NS_SPECIAL,'CreateArticle'); }

}

  1. Called from $wgExtensionFunctions array when initialising extensions

function wfSetupSimpleForms() { global $wgLanguageCode,$wgMessageCache,$wgHooks,$wgSimpleForms;

# Add messages if ($wgLanguageCode == 'en') { $wgMessageCache->addMessages(array( 'createarticle' => 'Create new article', # The friendly page title 'sf_create' => 'create', # title of create action button 'sf_editsummary' => 'Article $1 from HTTP request' )); }

# Add the specialpage to the environment SpecialPage::addPage(new SpecialCreateArticle());

# Instantiate a singleton for the extension $wgSimpleForms = new SimpleForms(); }

  1. Needed in MediaWiki >1.8.0 for magic word hooks to work properly

function wfSimpleFormsLanguageGetMagic(&$magicWords,$langCode = 0) { global $wgSimpleFormsFormMagic,$wgSimpleFormsInputMagic,$wgSimpleFormsEditFormMagic,$wgSimpleFormsRequestMagic; $magicWords[$wgSimpleFormsFormMagic] = array(0,$wgSimpleFormsFormMagic); $magicWords[$wgSimpleFormsEditFormMagic] = array(0,$wgSimpleFormsEditFormMagic); $magicWords[$wgSimpleFormsInputMagic] = array(0,$wgSimpleFormsInputMagic); $magicWords[$wgSimpleFormsRequestMagic] = array(0,$wgSimpleFormsRequestMagic); return true; } ?>