Difference between revisions of "Extension:SimpleForms.php"

From Organic Design wiki
(0.4.10 - fixed index bug for win users)
(reformat and fix action bug)
Line 1: Line 1:
 
<?php
 
<?php
# MediaWiki SimpleForms Extension{{php}}{{Category:Extensions|SimpleForms}}{{Category:Extensions in progress|SimpleForms}}
+
/**
# - See http://www.mediawiki.org/wiki/Extension:Simple_Forms for installation and usage details
+
* SimpleForms extension - Provides functions to make and process forms
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
+
* {{php}}{{Category:Extensions|SimpleForms}}{{Category:Extensions in progress|SimpleForms}}
# - Author: http://www.organicdesign.co.nz/nad
+
* See http://www.mediawiki.org/Extension:Simple_Forms for installation and usage details
# - Started: 2007-04-25, see article history
+
* See http://www.organicdesign.co.nz/Extension_talk:SimpleForms.php for development notes and disucssion
 +
*
 +
* Started: 2007-04-25, see article history
 +
*
 +
* @package MediaWiki
 +
* @subpackage Extensions
 +
* @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad]
 +
* @copyright © 2007 Aran Dunkley
 +
* @licence GNU General Public Licence 2.0 or later
 +
*/
  
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
define('SIMPLEFORMS_VERSION', '0.4.10, 2008-07-12');
+
define('SIMPLEFORMS_VERSION', '0.4.11, 2009-01-14');
  
 
# index.php parameter names
 
# index.php parameter names
define('SIMPLEFORMS_CONTENT', 'content');  # used for parsing wikitext content
+
define('SIMPLEFORMS_CONTENT', 'content');  # used for parsing wikitext content
define('SIMPLEFORMS_CACTION', 'caction');  # specify whether to prepend, append or replace existing content
+
define('SIMPLEFORMS_CACTION', 'caction');  # specify whether to prepend, append or replace existing content
define('SIMPLEFORMS_SUMMARY', 'summary');  # specify an edit summary when updating or creating content
+
define('SIMPLEFORMS_SUMMARY', 'summary');  # specify an edit summary when updating or creating content
define('SIMPLEFORMS_PAGENAME','pagename');  # specify a page heading to use when rendering content with no title
+
define('SIMPLEFORMS_PAGENAME', 'pagename');  # specify a page heading to use when rendering content with no title
define('SIMPLEFORMS_MINOR',   'minor');    # specify that the edit/create be flagged as a minor edit
+
define('SIMPLEFORMS_MINOR',   'minor');    # specify that the edit/create be flagged as a minor edit
define('SIMPLEFORMS_TACTION', 'templates'); # specify that the edit/create be flagged as a minor edit
+
define('SIMPLEFORMS_TACTION', 'templates'); # specify that the edit/create be flagged as a minor edit
define('SIMPLEFORMS_USERNAME','username');  # specify a different username to use when the server is editing
+
define('SIMPLEFORMS_USERNAME', 'username');  # specify a different username to use when the server is editing
define('SIMPLEFORMS_RETURN', 'returnto');  # specify a page to return to after processing the request
+
define('SIMPLEFORMS_RETURN',   'returnto');  # specify a page to return to after processing the request
define('SIMPLEFORMS_REGEXP', 'regexp');    # if the content-action is replace, a perl regular expression can be used
+
define('SIMPLEFORMS_REGEXP',   'regexp');    # if the content-action is replace, a perl regular expression can be used
  
 
# Parser function names
 
# Parser function names
$wgSimpleFormsFormMagic       = "form";     # the parser-function name for form containers
+
$wgSimpleFormsFormMagic     = "form";       # the parser-function name for form containers
$wgSimpleFormsInputMagic     = "input";   # the parser-function name for form inputs
+
$wgSimpleFormsInputMagic   = "input";       # the parser-function name for form inputs
$wgSimpleFormsRequestMagic   = "request"; # the parser-function name for accessing the post/get variables
+
$wgSimpleFormsRequestMagic = "request";     # the parser-function name for accessing the post/get variables
$wgSimpleFormsParaTypeMagic   = "paratype"; # the parser-function name for checking post/get parameter types
+
$wgSimpleFormsParaTypeMagic = "paratype";   # the parser-function name for checking post/get parameter types
  
 
# Configuration
 
# Configuration
$wgSimpleFormsRequestPrefix   = "";         # restricts #request and GET/POST variable names to their own namespace, set to "" to disable
+
$wgSimpleFormsRequestPrefix = "";           # restricts #request and GET/POST variable names to their own namespace, set to "" to disable
$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
+
$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
+
$wgSimpleFormsAllowEdit     = true;         # Allow appending, prepending or replacing of content in existing articles from query item
  
 
# Allow anonymous edits from these addresses
 
# Allow anonymous edits from these addresses
Line 37: Line 46:
  
 
$wgSimpleFormsEnableCaching = true;
 
$wgSimpleFormsEnableCaching = true;
define('SIMPLEFORMS_UNTITLED','UNTITLED');
+
define('SIMPLEFORMS_UNTITLED', 'UNTITLED');
define('SFEB_NAME', 0);
+
define('SFEB_NAME',   0);
define('SFEB_OFFSET',1);
+
define('SFEB_OFFSET', 1);
define('SFEB_LENGTH',2);
+
define('SFEB_LENGTH', 2);
define('SFEB_DEPTH', 3);
+
define('SFEB_DEPTH', 3);
  
$wgExtensionFunctions[]       = 'wfSetupSimpleForms';
+
$wgExtensionFunctions[] = 'wfSetupSimpleForms';
 
$wgHooks['LanguageGetMagic'][] = 'wfSimpleFormsLanguageGetMagic';
 
$wgHooks['LanguageGetMagic'][] = 'wfSimpleFormsLanguageGetMagic';
  
 
$wgExtensionCredits['parserhook'][] = array(
 
$wgExtensionCredits['parserhook'][] = array(
    'name'        => 'Simple Forms',
+
'name'        => 'Simple Forms',
    'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
+
'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
    'description' => 'Functions to make and process forms.',
+
'description' => 'Functions to make and process forms.',
    'url'        => 'http://www.mediawiki.org/wiki/Extension:Simple_Forms',
+
'url'        => 'http://www.mediawiki.org/wiki/Extension:Simple_Forms',
    'version'    => SIMPLEFORMS_VERSION
+
'version'    => SIMPLEFORMS_VERSION
    );
+
);
  
 
# If it's a simple-forms ajax call, don't use dispatcher
 
# If it's a simple-forms ajax call, don't use dispatcher
 
if ($wgUseAjax && isset($_REQUEST['action']) && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == 'wfSimpleFormsAjax') {
 
if ($wgUseAjax && isset($_REQUEST['action']) && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == 'wfSimpleFormsAjax') {
    $_REQUEST['action'] = 'render';
+
$_REQUEST['action'] = 'render';
    if (is_array($_REQUEST['rsargs']))
+
if (is_array($_REQUEST['rsargs']))
        foreach ($_REQUEST['rsargs'] as $arg)
+
foreach ($_REQUEST['rsargs'] as $arg)
            if (preg_match('/^(.+?)=(.+)$/',$arg,$m))
+
if (preg_match('/^(.+?)=(.+)$/', $arg, $m))
                $_REQUEST[$m[1]] = $m[2];
+
$_REQUEST[$m[1]] = $m[2];
    }
+
}
  
 
# todo: handle action=edit by making $_REQUEST['preload']='UNTITLED' and still add the AAFC hook
 
# todo: handle action=edit by making $_REQUEST['preload']='UNTITLED' and still add the AAFC hook
#       handle action=raw by changing action to render and adding SimpleForms::raw to an appropriate hook
+
#   handle action=raw by changing action to render and adding SimpleForms::raw to an appropriate hook
  
 
# 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 (isset($_REQUEST[SIMPLEFORMS_CONTENT]) && !isset($_REQUEST['title'])) {
 
if (isset($_REQUEST[SIMPLEFORMS_CONTENT]) && !isset($_REQUEST['title'])) {
    $wgHooks['ArticleAfterFetchContent'][] = 'wfSimpleFormsUntitledContent';
+
$wgHooks['ArticleAfterFetchContent'][] = 'wfSimpleFormsUntitledContent';
    $_REQUEST['title'] = SIMPLEFORMS_UNTITLED;
+
$_REQUEST['title'] = SIMPLEFORMS_UNTITLED;
    $wgSimpleFormsEnableCaching = false;
+
$wgSimpleFormsEnableCaching = false;
    }
+
}
function wfSimpleFormsUntitledContent(&$article,&$text) {
+
    global $wgOut,$wgRequest;
+
function wfSimpleFormsUntitledContent(&$article, &$text) {
    if ($article->getTitle()->getText() == SIMPLEFORMS_UNTITLED) {
+
global $wgOut, $wgRequest;
        $text = $wgRequest->getText(SIMPLEFORMS_CONTENT);
+
if ($article->getTitle()->getText() == SIMPLEFORMS_UNTITLED) {
        if ($title = $wgRequest->getText(SIMPLEFORMS_PAGENAME)) $wgOut->setPageTitle($title);
+
$text = $wgRequest->getText(SIMPLEFORMS_CONTENT);
        else {
+
if ($title = $wgRequest->getText(SIMPLEFORMS_PAGENAME)) $wgOut->setPageTitle($title);
            $wgOut->setPageTitle(' ');
+
else {
            $wgOut->addScript('<style>h1.firstHeading{display:none}</style>');
+
$wgOut->setPageTitle(' ');
            }
+
$wgOut->addScript('<style>h1.firstHeading{display:none}</style>');
        }
+
}
    return true;
+
}
    }
+
return true;
 +
}
  
 
# If the request originates locally, auto-authenticate the user to the server-user
 
# If the request originates locally, auto-authenticate the user to the server-user
 
$wgHooks['AutoAuthenticate'][] = 'wfSimpleFormsAutoAuthenticate';
 
$wgHooks['AutoAuthenticate'][] = 'wfSimpleFormsAutoAuthenticate';
 
function wfSimpleFormsAutoAuthenticate(&$user) {
 
function wfSimpleFormsAutoAuthenticate(&$user) {
    global $wgRequest,$wgSimpleFormsServerUser,$wgSimpleFormsAllowRemoteAddr;
+
global $wgRequest, $wgSimpleFormsServerUser, $wgSimpleFormsAllowRemoteAddr;
    if ($username = $wgRequest->getText(SIMPLEFORMS_USERNAME)) $wgSimpleFormsServerUser = $username;
+
if ($username = $wgRequest->getText(SIMPLEFORMS_USERNAME)) $wgSimpleFormsServerUser = $username;
    if (!empty($wgSimpleFormsServerUser) && in_array($_SERVER['REMOTE_ADDR'],$wgSimpleFormsAllowRemoteAddr))
+
if (!empty($wgSimpleFormsServerUser) && in_array($_SERVER['REMOTE_ADDR'], $wgSimpleFormsAllowRemoteAddr))
        $user = User::newFromName($wgSimpleFormsServerUser);
+
$user = User::newFromName($wgSimpleFormsServerUser);
    return true;
+
return true;
    }
+
}
  
# Define a singleton for SimpleForms operations
+
/**
 +
* Define a singleton for SimpleForms operations
 +
*/
 
class SimpleForms {
 
class SimpleForms {
  
    var $id = 0;
+
var $id = 0;
  
    # Constructor
+
/**
    function SimpleForms() {
+
* Constructor
        global $wgParser,$wgHooks,$wgTitle,$wgSimpleFormsFormMagic,$wgSimpleFormsInputMagic,$wgSimpleFormsRequestMagic,$wgSimpleFormsParaTypeMagic,$wgSimpleFormsEnableCaching;
+
*/
        $wgParser->setFunctionHook($wgSimpleFormsFormMagic,    array($this,'formMagic'));
+
function SimpleForms() {
        $wgParser->setFunctionHook($wgSimpleFormsInputMagic,    array($this,'inputMagic'));
+
global $wgParser, $wgHooks, $wgTitle, $wgSimpleFormsFormMagic, $wgSimpleFormsInputMagic,
        $wgParser->setFunctionHook($wgSimpleFormsRequestMagic,  array($this,'requestMagic'));
+
$wgSimpleFormsRequestMagic, $wgSimpleFormsParaTypeMagic, $wgSimpleFormsEnableCaching;
        $wgParser->setFunctionHook($wgSimpleFormsParaTypeMagic, array($this,'paramTypeMagic'));
+
$wgParser->setFunctionHook($wgSimpleFormsFormMagic,    array($this,'formMagic'));
        $this->createUntitled();
+
$wgParser->setFunctionHook($wgSimpleFormsInputMagic,    array($this,'inputMagic'));
        $this->processRequest();
+
$wgParser->setFunctionHook($wgSimpleFormsRequestMagic,  array($this,'requestMagic'));
        if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'render' && (!is_object($wgTitle) || isset($_REQUEST['content']))) {
+
$wgParser->setFunctionHook($wgSimpleFormsParaTypeMagic, array($this,'paramTypeMagic'));
            $wgHooks['OutputPageBeforeHTML'][] = array($this,'render');
+
$this->createUntitled();
            $wgSimpleFormsEnableCaching = false;
+
$this->processRequest();
            }
+
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'render' && (!is_object($wgTitle) || isset($_REQUEST['content']))) {
        $this->id = uniqid('sf-');
+
$wgHooks['OutputPageBeforeHTML'][] = array($this, 'render');
        }
+
$wgSimpleFormsEnableCaching = false;
 +
}
 +
$this->id = uniqid('sf-');
 +
}
  
    # 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
+
* Renders a form and wraps it in tags for processing by tagHook
    #  i.e. $this->edit would be set by the edit-hook or create-specialpage parsing it
+
* - if it's an edit-form it will return empty-string unless $this->edit is true
    function formMagic(&$parser) {
+
* i.e. $this->edit would be set by the edit-hook or create-specialpage parsing it
        global $wgScript,$wgSimpleFormsEnableCaching;
+
*/
        if (!$wgSimpleFormsEnableCaching) $parser->disableCache();
+
function formMagic(&$parser) {
        $argv = func_get_args();
+
global $wgScript, $wgSimpleFormsEnableCaching;
        $id = $this->id;
+
if (!$wgSimpleFormsEnableCaching) $parser->disableCache();
        if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'render' && isset($_REQUEST['wiklet']))
+
$argv = func_get_args();
            $hidden = '<input type="hidden" name="action" value="render"/>
+
$id = $this->id;
            <input type="hidden" name="wiklet"/>';
+
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'render' && isset($_REQUEST['wiklet']))
        else $hidden = '';
+
$hidden = '<input type="hidden" name="action" value="render"/>
        $action = isset($argv['action']) ? $argv['action'] : $wgScript;
+
<input type="hidden" name="wiklet"/>';
        unset($argv['action']);
+
else $hidden = '';
        $form  = '';
+
unset($argv['action']);
        $args  = '';
+
$form = '';
        foreach ($argv as $arg) if (!is_object($arg)) {
+
$args = '';
            if (preg_match('/^([a-z0-9_]+?)\\s*=\\s*(.+)$/is',$arg,$match)) $args .= " $match[1]=\"$match[2]\""; else $form = $arg;
+
$argl = array();
            }
+
foreach ($argv as $arg) if (!is_object($arg)) {
        $form = "<form$args action=\"$action\" id=\"$id\">$hidden$form</form>";
+
if (preg_match('/^([a-z0-9_]+?)\\s*=\\s*(.+)$/is', $arg, $match)) {
        $this->id = uniqid('sf-');
+
$args .= " $match[1]=\"$match[2]\"";
        $form = preg_replace("/^\\s+/m",'',$form);
+
$argl[$match[1]] = $match[2];
        return array($form,'noparse' => true, 'isHTML' => true);
+
} else $form = $arg;
        }
+
}
 +
$action = isset($argl['action']) ? $argl['action'] : $wgScript;
 +
$form = "<form$args action=\"$action\" id=\"$id\">$hidden$form</form>";
 +
$this->id = uniqid('sf-');
 +
$form = preg_replace("/^\\s+/m",'',$form);
 +
return array($form, 'noparse' => true, 'isHTML' => true);
 +
}
  
    # Renders a form input
+
/**
    function inputMagic(&$parser) {
+
* Renders a form input
        global $wgSimpleFormsRequestPrefix,$wgSimpleFormsEnableCaching;
+
*/
        if (!$wgSimpleFormsEnableCaching) $parser->disableCache();
+
function inputMagic(&$parser) {
 +
global $wgSimpleFormsRequestPrefix, $wgSimpleFormsEnableCaching;
 +
if (!$wgSimpleFormsEnableCaching) $parser->disableCache();
  
                $content = '';
+
$content = '';
                $method  = '';
+
$method  = '';
                $type    = '';
+
$type    = '';
                $args    = '';
+
$args    = '';
                $argv    = array();
+
$argv    = array();
  
        # Process args
+
# Process args
        foreach (func_get_args() as $arg) if (!is_object($arg)) {
+
foreach (func_get_args() as $arg) if (!is_object($arg)) {
            if (preg_match('/^([a-z0-9_]+?)\\s*=\\s*(.+)$/is',$arg,$match)) $argv[trim($match[1])] = trim($match[2]);
+
if (preg_match('/^([a-z0-9_]+?)\\s*=\\s*(.+)$/is', $arg, $match)) $argv[trim($match[1])] = trim($match[2]);
            else $content = trim($arg);
+
else $content = trim($arg);
            }
+
}
        if (isset($argv['type'])) $type = $argv['type']; else $type = '';
+
if (isset($argv['type'])) $type = $argv['type']; else $type = '';
        if (isset($argv['name'])) $argv['name'] = $wgSimpleFormsRequestPrefix.$argv['name'];
+
if (isset($argv['name'])) $argv['name'] = $wgSimpleFormsRequestPrefix.$argv['name'];
  
        # Textarea
+
# Textarea
        if ($type == 'textarea') {
+
if ($type == 'textarea') {
            unset($argv['type']);
+
unset($argv['type']);
            foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
+
foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
            $input = "<textarea$args>$content</textarea>";
+
$input = "<textarea$args>$content</textarea>";
            }
+
}
  
        # Select list
+
# Select list
        elseif ( $type == 'select' )
+
elseif ($type == 'select' ) {
        {
+
unset($argv['type']);
            unset( $argv['type'] );
 
  
            if ( isset( $argv['multiple'] ) )
+
if (isset($argv['multiple'])) {
            {
+
if (isset($argv['name'])) $argv['name'] .= '[]';
                if ( isset( $argv['name'] ) )
+
}
                    $argv['name'] .= '[]';
 
            }
 
  
            if ( isset( $argv['value'] ) )
+
if (isset($argv['value'])) {
            {
+
$val = $argv['value'];
                $val = $argv['value'];
+
unset($argv['value']);
                unset( $argv['value'] );
+
} else $val = '';
            }
 
            else
 
                $val = '';
 
  
            foreach ( $argv as $k => $v )
+
foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
                $args .= " $k=\"$v\"";
 
  
            preg_match_all( '/^\\*\\s*(.*?)\\s*$/m', $content, $m );
+
preg_match_all( '/^\\*\\s*(.*?)\\s*$/m', $content, $m );
            $input = "<select$args>\n";
+
$input = "<select$args>\n";
            foreach ( $m[1] as $opt )
+
foreach ($m[1] as $opt ) {
            {
+
$sel = $opt == $val ? ' selected' : '';
                $sel = $opt == $val ? ' selected' : '';
+
$input .= "<option$sel>$opt</option>\n";
                $input .= "<option$sel>$opt</option>\n";
+
}
            }
 
  
            $input .= "</select>\n";
+
$input .= "</select>\n";
        }
+
}
  
        # Ajax link or button
+
# Ajax link or button
        elseif ($type == 'ajax') {
+
elseif ($type == 'ajax') {
            $update = isset($argv['update']) ? $argv['update'] : $this->id;
+
$update = isset($argv['update']) ? $argv['update'] : $this->id;
            $format = isset($argv['format']) ? $argv['format'] : 'button';
+
$format = isset($argv['format']) ? $argv['format'] : 'button';
            unset($argv['update']);
+
unset($argv['update']);
            unset($argv['format']);
+
unset($argv['format']);
                        if (isset($argv['template'])) {
+
if (isset($argv['template'])) {
                                $template = '{'.'{'.$argv['template'];
+
$template = '{'.'{'.$argv['template'];
                                $template = "var t = '$template\\n';
+
$template = "var t = '$template\\n';
                    inputs = f.getElementsByTagName('select');
+
inputs = f.getElementsByTagName('select');
                    for (i = 0; i < inputs.length; i++)
+
for (i = 0; i < inputs.length; i++)
                        if (n = inputs[i].getAttribute('name'))
+
if (n = inputs[i].getAttribute('name'))
                            t += '|' + n + '=' + inputs[i].getAttribute('selected') + '\\n';
+
t += '|' + n + '=' + inputs[i].getAttribute('selected') + '\\n';
                                        t = t + '}'+'}\\n';
+
t = t + '}'+'}\\n';
                    alert(t);/*
+
alert(t);/*
                                        i = document.createElement('input');
+
i = document.createElement('input');
                                        i.setAttribute('type','hidden');
+
i.setAttribute('type','hidden');
                                        i.setAttribute('name','templates');
+
i.setAttribute('name','templates');
                                        i.setAttribute('value','update');
+
i.setAttribute('value','update');
                                        f.appendChild(i);
+
f.appendChild(i);
                                        i = document.createElement('input');
+
i = document.createElement('input');
                                        i.setAttribute('type','hidden');
+
i.setAttribute('type','hidden');
                                        i.setAttribute('name','content');
+
i.setAttribute('name','content');
                                        i.setAttribute('value',t);
+
i.setAttribute('value',t);
                                        f.appendChild(i);*/";
+
f.appendChild(i);*/";
                                unset($argv['template']);
+
unset($argv['template']);
                                } else $template = '';
+
} else $template = '';
            if ($format == 'link') {
+
                # Render the Ajax input as a link independent of any form
+
if ($format == 'link') {
                $element = 'a';
+
# Render the Ajax input as a link independent of any form
                $t = isset($argv['title']) ? $argv['title'] : false;
+
$element = 'a';
                if ($content == '') $content = $t;
+
$t = isset($argv['title']) ? $argv['title'] : false;
                if ($t) $t = Title::newFromText($t);
+
if ($content == '') $content = $t;
                $argv['class'] = !$t || $t->exists() ? 'ajax' : 'new ajax';
+
if ($t) $t = Title::newFromText($t);
                unset($argv['type']);
+
$argv['class'] = !$t || $t->exists() ? 'ajax' : 'new ajax';
                $params = array();
+
unset($argv['type']);
                foreach ($argv as $k => $v) if ($k != 'class') $params[] = "'$k=$v'";
+
$params = array();
                $params = join(',',$params);
+
foreach ($argv as $k => $v) if ($k != 'class') $params[] = "'$k=$v'";
                $argv['href'] = "javascript:var x = sajax_do_call('wfSimpleFormsAjax',[$params],document.getElementById('$update'))";
+
$params = join(',',$params);
                }
+
$argv['href'] = "javascript:var x = sajax_do_call('wfSimpleFormsAjax',[$params],document.getElementById('$update'))";
            else {
+
}
                # Render the Ajax input as a form submit button
+
else {
                $argv['type'] = 'button';
+
# Render the Ajax input as a form submit button
                $element     = 'input';
+
$argv['type'] = 'button';
                if (!isset($argv['onClick'])) $argv['onClick'] = '';
+
$element   = 'input';
                $argv['onClick'] .= "a = [];
+
if (!isset($argv['onClick'])) $argv['onClick'] = '';
                    f = document.getElementById('{$this->id}');
+
$argv['onClick'] .= "a = [];
                    i = f.elements;
+
f = document.getElementById('{$this->id}');
                    for (var k = 0; k < f.elements.length; k++) {
+
i = f.elements;
                      if (i[k].type == 'select-one') {
+
for (var k = 0; k < f.elements.length; k++) {
                        if (i[k].selectedIndex !== undefined ) {
+
  if (i[k].type == 'select-one') {
                          a.push(i[k].name+'='+i[k].options[i[k].selectedIndex].text);
+
if (i[k].selectedIndex !== undefined ) {
                        }
+
  a.push(i[k].name+'='+i[k].options[i[k].selectedIndex].text);
                      } else if (i[k].name && i[k].value &&
+
}
                          (i[k].type != 'radio' || i[k].checked) &&
+
  } else if (i[k].name && i[k].value &&
                          (i[k].type != 'checkbox' || i[k].checked)) {
+
  (i[k].type != 'radio' || i[k].checked) &&
                            a.push(i[k].name+'='+i[k].value);
+
  (i[k].type != 'checkbox' || i[k].checked)) {
                      }
+
a.push(i[k].name+'='+i[k].value);
                    }
+
  }
                    sajax_request_type = 'POST';
+
}
                    x = sajax_do_call('wfSimpleFormsAjax',a,document.getElementById('$update'))";
+
sajax_request_type = 'POST';
                }
+
x = sajax_do_call('wfSimpleFormsAjax',a,document.getElementById('$update'))";
 +
}
  
            foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
+
foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
            $input = "<$element$args>$content</$element>\n";
+
$input = "<$element$args>$content</$element>\n";
            }
+
}
  
        # Default: render as normal input element
+
# Default: render as normal input element
        else {
+
else {
            foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
+
foreach ($argv as $k => $v) $args .= " $k=\"$v\"";
            $input = "<input$args/>";
+
$input = "<input$args/>";
            }
+
}
  
        $input = preg_replace("/^\\s+/m",'',$input);
+
$input = preg_replace("/^\\s+/m",'',$input);
        return array($input,'noparse' => true, 'isHTML' => true);
+
return array($input,'noparse' => true, 'isHTML' => true);
        }
+
}
  
    # Return value from the global $_REQUEST array (containing GET/POST variables)
+
/**
    function requestMagic( &$parser )
+
* Return value from the global $_REQUEST array (containing GET/POST variables)
    {
+
*/
        global $wgRequest, $wgSimpleFormsRequestPrefix, $wgContLang;
+
function requestMagic(&$parser) {
 +
global $wgRequest, $wgSimpleFormsRequestPrefix, $wgContLang;
  
        $args = func_get_args();
+
$args = func_get_args();
  
        // the first arg is the parser.  We already have it (by
+
# the first arg is the parser.  We already have it (by
        // reference even), so we can remove it from the array
+
# reference even), so we can remove it from the array
        array_shift( $args );
+
array_shift($args);
  
        // get the request parameter name
+
# get the request parameter name
        $paramName = array_shift( $args );
+
$paramName = array_shift($args);
        // only thing left in $args at this point are the array keys
+
 +
# only thing left in $args at this point are the array keys
 +
# If no keys are specified, we just call getText()
 +
if (count($args) == 0) {
 +
$paramValue = $wgRequest->getText($wgSimpleFormsRequestPrefix.$paramName);
 +
return $paramValue;
 +
}
  
        // If no keys are specified, we just call getText()
+
# when the parameter is a scalar calling getArray() puts it in an
        if ( count( $args ) == 0 )
+
# array and returns the array, so we need to do a scalar check
        {
+
if (!is_null($wgRequest->getVal($wgSimpleFormsRequestPrefix.$paramName))) return '';
            $paramValue = $wgRequest->getText(
 
                $wgSimpleFormsRequestPrefix . $paramName );
 
  
            return $paramValue;
+
# get the array associated with this parameter name
        }
+
$paramValue = $wgRequest->getArray($wgSimpleFormsRequestPrefix.$paramName);
  
        // when the parameter is a scalar calling getArray() puts it in an
+
# time to descend into the depths of the array associated with the
        // array and returns the array, so we need to do a scalar check
+
# parameter name
        if ( !is_null( $wgRequest->getVal(
+
while (count($args) > 0) {
            $wgSimpleFormsRequestPrefix . $paramName ) ) )
+
$key = array_shift($args);
            return '';
 
  
        // get the array associated with this parameter name
+
# do we have more keys than we have array nests?
        $paramValue = $wgRequest->getArray( $wgSimpleFormsRequestPrefix .
+
if (!is_array($paramValue)) return '';
            $paramName );
 
  
        // time to descend into the depths of the array associated with the
+
# a little closer to the value we want
        // parameter name
+
$paramValue = $paramValue[$key];
        while ( count( $args ) > 0 )
+
}
        {
 
            $key = array_shift( $args );
 
  
            // do we have more keys than we have array nests?
+
# do we have more array nests than we have keys, or a null?
            if ( !is_array( $paramValue ) )
+
if (is_array($paramValue) || is_null($paramValue)) return '';
                return '';
 
  
            // a little closer to the value we want
+
# we've found a param value!
            $paramValue = $paramValue[$key];
+
$paramValue = str_replace("\r\n", "\n", $wgContLang->recodeInput($paramValue));
        }
 
  
        // do we have more array nests than we have keys, or a null?
+
return $paramValue;
        if ( is_array( $paramValue ) || is_null( $paramValue ) )
+
}
            return '';
 
  
        // we've found a param value!
+
/**
        $paramValue = str_replace( "\r\n", "\n",
+
* requestMagic() returns an empty string under three conditions:
            $wgContLang->recodeInput( $paramValue ) );
+
*  1) no such parameter was passed via the request,
 +
*  2) the specified parameter is an array, and
 +
*  3) the specified parameter was set to an empty string.
 +
* Because of this we need a function to determine which is the case.  This
 +
* function returns '0' if the parameter doesn't exist, '1' if the parameter
 +
* is a scalar, and '2' if the parameter is an array.
 +
*/
 +
function paramTypeMagic(&$parser) {
 +
global $wgRequest, $wgSimpleFormsRequestPrefix;
  
        return $paramValue;
+
$args = func_get_args();
    }
 
  
    /**
+
# the first arg is the parser, we already have it by
    * requestMagic() returns an empty string under three conditions:
+
# reference, so we can remove it from the array
    *  1) no such parameter was passed via the request,
+
array_shift($args);
    *  2) the specified parameter is an array, and
 
    *  3) the specified parameter was set to an empty string.
 
    * Because of this we need a function to determine which is the case.  This
 
    * function returns '0' if the parameter doesn't exist, '1' if the parameter
 
    * is a scalar, and '2' if the parameter is an array.
 
    */
 
    function paramTypeMagic( &$parser )
 
    {
 
        global $wgRequest, $wgSimpleFormsRequestPrefix;
 
  
        $args = func_get_args();
+
# get the request parameter name
 +
$paramName = array_shift($args);
  
        // the first arg is the parser, we already have it by
+
# only thing left in $args at this point are the array keys
        // reference, so we can remove it from the array
+
# If no keys are specified, we just try to get a scalar
        array_shift( $args );
+
if ( count($args) == 0) {
 +
$paramValue = $wgRequest->getVal($wgSimpleFormsRequestPrefix.$paramName);
 +
if (is_null($paramValue)) {
 +
# getVal() returns null if the reqest parameter is an array, so
 +
# we need to verify that the parameter was not passed.
 +
$paramValue = $wgRequest->getArray($wgSimpleFormsRequestPrefix.$paramName);
 +
return is_null($paramValue) ? '0' : '2';
 +
}
  
        // get the request parameter name
+
# found a scalar
        $paramName = array_shift( $args );
+
return '1';
        // only thing left in $args at this point are the array keys
+
}
  
        // If no keys are specified, we just try to get a scalar
+
# when the parameter is a scalar calling getArray() puts it in an
        if ( count( $args ) == 0 )
+
# array and returns the array, so we need to do a scalar check
        {
+
if (!is_null($wgRequest->getVal($wgSimpleFormsRequestPrefix.$paramName))) return '0';
            $paramValue = $wgRequest->getVal(
 
                $wgSimpleFormsRequestPrefix . $paramName );
 
  
            if ( is_null( $paramValue ) )
+
# get the array associated with this parameter name
            {
+
$paramValue = $wgRequest->getArray($wgSimpleFormsRequestPrefix.$paramName);
                // getVal() returns null if the reqest parameter is an array, so
 
                // we need to verify that the parameter was not passed.
 
                $paramValue = $wgRequest->getArray(
 
                    $wgSimpleFormsRequestPrefix . $paramName );
 
  
                return is_null( $paramValue ) ? '0' : '2';
+
# descend into the depths of the array
            }
+
while (count($args) > 0) {
 +
$key = array_shift($args);
  
            // found a scalar
+
# do we have more keys than we have array nests?
            return '1';
+
if (!is_array($paramValue) || !array_key_exists($key, $paramValue)) return '0';
        }
 
  
        // when the parameter is a scalar calling getArray() puts it in an
+
# a little closer to the value we want
        // array and returns the array, so we need to do a scalar check
+
$paramValue = $paramValue[$key];
        if ( !is_null( $wgRequest->getVal(
+
}
            $wgSimpleFormsRequestPrefix . $paramName ) ) )
 
            return '0';
 
  
        // get the array associated with this parameter name
+
# do we have more array nests than we have keys?
        $paramValue = $wgRequest->getArray( $wgSimpleFormsRequestPrefix .
+
return is_array($paramValue) ? '2' : '1';
            $paramName );
+
}
  
        // descend into the depths of the array
+
/**
        while ( count( $args ) > 0 )
+
* Return the raw content
        {
+
*/
            $key = array_shift( $args );
+
function raw($text) {
 +
global $wgOut,$wgParser,$wgRequest;
 +
$this->setCaching();
 +
$expand = $wgRequest->getText('templates') == 'expand';
 +
if ($expand) $text = $wgParser->preprocess($text,new Title(),new ParserOptions());
 +
$wgOut->disable();
 +
wfResetOutputBuffers();
 +
header('Content-Type: application/octet-stream');
 +
echo($text);
 +
return false;
 +
}
  
            // do we have more keys than we have array nests?
+
/**
            if ( !is_array( $paramValue ) ||
+
* Return rendered content of page
                !array_key_exists( $key, $paramValue ) )
+
*/
                return '0';
+
function render(&$out, &$text) {
 +
$this->setCaching();
 +
$out->disable();
 +
wfResetOutputBuffers();
 +
echo($text);
 +
return false;
 +
}
  
            // a little closer to the value we want
+
/**
            $paramValue = $paramValue[$key];
+
* Disable caching if necessary
        }
+
*/
 +
function setCaching() {
 +
global $wgOut, $wgEnableParserCache, $wgSimpleFormsEnableCaching;
 +
if ($wgSimpleFormsEnableCaching) return;
 +
$wgOut->enableClientCache(false);
 +
header("Cache-Control: no-cache, must-revalidate");
 +
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
 +
}
  
        // do we have more array nests than we have keys?
+
/**
        return is_array( $paramValue ) ? '2' : '1';
+
* Processes HTTP requests containing wikitext content
    }
+
*/
 +
function processRequest() {
 +
global $wgOut, $wgRequest, $wgUser, $wgTitle,
 +
  $wgSimpleFormsAllowRemoteAddr, $wgSimpleFormsAllowCreate, $wgSimpleFormsAllowEdit;
  
    # Return the raw content
+
$content = trim($wgRequest->getText(SIMPLEFORMS_CONTENT));
    function raw($text) {
+
$action  = $wgRequest->getText('action');
        global $wgOut,$wgParser,$wgRequest;
+
$title  = $wgRequest->getText('title');
        $this->setCaching();
 
        $expand = $wgRequest->getText('templates') == 'expand';
 
        if ($expand) $text = $wgParser->preprocess($text,new Title(),new ParserOptions());
 
        $wgOut->disable();
 
        wfResetOutputBuffers();
 
        header('Content-Type: application/octet-stream');
 
        echo($text);
 
        return false;
 
        }
 
  
    # Return rendered content of page
+
# Handle content with action=raw case (allows templates=expand too)
    function render(&$out,&$text) {
+
if ($action == 'raw' && isset($_REQUEST[SIMPLEFORMS_CONTENT])) $this->raw($content);
        $this->setCaching();
 
        $out->disable();
 
        wfResetOutputBuffers();
 
        echo($text);
 
        return false;
 
        }
 
  
    # Disable caching if necessary
+
# Handle content and title case (will either update or create an article)
    function setCaching() {
+
if ($title != SIMPLEFORMS_UNTITLED && isset($_REQUEST[SIMPLEFORMS_CONTENT])) {
        global $wgOut,$wgEnableParserCache,$wgSimpleFormsEnableCaching;
 
        if ($wgSimpleFormsEnableCaching) return;
 
        $wgOut->enableClientCache(false);
 
        header("Cache-Control: no-cache, must-revalidate");
 
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
 
        }
 
  
    # Processes HTTP requests containing wikitext content
+
$title  = Title::newFromText($wgRequest->getText('title'));
    function processRequest() {
+
if ($title->getNamespace() == NS_SPECIAL) return;
        global $wgOut,$wgRequest,$wgUser,$wgTitle,
+
if (!is_object($wgTitle)) $wgTitle = $title; # hack to stop DPL crashing
              $wgSimpleFormsAllowRemoteAddr,$wgSimpleFormsAllowCreate,$wgSimpleFormsAllowEdit;
+
$article = new Article($title);
 +
$allow  = in_array($_SERVER['REMOTE_ADDR'], $wgSimpleFormsAllowRemoteAddr);
 +
$summary = $wgRequest->getText(SIMPLEFORMS_SUMMARY);
 +
$minor  = $wgRequest->getText(SIMPLEFORMS_MINOR);
 +
$return  = $wgRequest->getText(SIMPLEFORMS_RETURN);
  
        $content = trim($wgRequest->getText(SIMPLEFORMS_CONTENT));
+
# If title exists and allowed to edit, prepend/append/replace content
        $action  = $wgRequest->getText('action');
+
if ($title->exists()) {
        $title  = $wgRequest->getText('title');
+
if ($wgSimpleFormsAllowEdit && ($allow || $wgUser->isAllowed('edit'))) {
 +
$update = $this->updateTemplates($article->getContent(),$content);
 +
$article->updateArticle($update, $summary ? $summary : wfMsg('sf_editsummary'), false, false);
 +
}
 +
else $wgOut->setPageTitle(wfMsg('whitelistedittitle'));
 +
}
  
        # Handle content with action=raw case (allows templates=expand too)
+
# No such title, create new article from content if allowed to create
        if ($action == 'raw' && isset($_REQUEST[SIMPLEFORMS_CONTENT])) $this->raw($content);
+
else {
 +
if ($wgSimpleFormsAllowCreate && ($allow || $wgUser->isAllowed('edit')))
 +
$article->insertNewArticle($content, $summary ? $summary : wfMsg('sf_editsummary', 'created'), false, false);
 +
else $wgOut->setPageTitle(wfMsg('whitelistedittitle'));
 +
}
  
        # Handle content and title case (will either update or create an article)
+
# If returnto is set, add a redirect header and die
        if ($title != SIMPLEFORMS_UNTITLED && isset($_REQUEST[SIMPLEFORMS_CONTENT])) {
+
if ($return) die(header('Location: '.Title::newFromText($return)->getFullURL()));
 +
}
 +
}
  
            $title   = Title::newFromText($wgRequest->getText('title'));
+
/**
            if ($title->getNamespace() == NS_SPECIAL) return;
+
* Create a dummy article for rendering content not associated with any title (unless it already exists)
            if (!is_object($wgTitle)) $wgTitle = $title; # hack to stop DPL crashing
+
* - there's probably a better way to do this
            $article = new Article($title);
+
*/
            $allow  = in_array($_SERVER['REMOTE_ADDR'],$wgSimpleFormsAllowRemoteAddr);
+
function createUntitled() {
            $summary = $wgRequest->getText(SIMPLEFORMS_SUMMARY);
+
$title = Title::newFromText(SIMPLEFORMS_UNTITLED);
            $minor  = $wgRequest->getText(SIMPLEFORMS_MINOR);
+
if (!$title->exists()) {
            $return  = $wgRequest->getText(SIMPLEFORMS_RETURN);
+
$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
 +
);
 +
}
 +
}
  
            # If title exists and allowed to edit, prepend/append/replace content
+
/**
            if ($title->exists()) {
+
* Update templates wikitext content
                if ($wgSimpleFormsAllowEdit && ($allow || $wgUser->isAllowed('edit'))) {
+
* - $updates must start and end with double-braces
                    $update = $this->updateTemplates($article->getContent(),$content);
+
* - $updates may contain multiple template updates
                    $article->updateArticle($update,$summary?$summary:wfMsg('sf_editsummary'),false,false);
+
* - each update must only match one template, comparison of args will reduce multiple matches
                    }
+
*/
                else $wgOut->setPageTitle(wfMsg('whitelistedittitle'));
+
function updateTemplates($content, $updates) {
                }
+
global $wgRequest;
 +
$caction = $wgRequest->getText(SIMPLEFORMS_CACTION);
 +
$taction = $wgRequest->getText(SIMPLEFORMS_TACTION);
 +
$regexp  = $wgRequest->getText(SIMPLEFORMS_REGEXP);
  
            # No such title, create new article from content if allowed to create
+
# Resort to normal content-action if $updates is not exclusively template definitions or updating templates disabled
            else {
+
if ($taction == 'update' and preg_match('/^\\{\\{.+\\}\\}$/is', $updates, $match)) {
                if ($wgSimpleFormsAllowCreate && ($allow || $wgUser->isAllowed('edit')))
 
                    $article->insertNewArticle($content,$summary ? $summary : wfMsg('sf_editsummary','created'),false,false);
 
                else $wgOut->setPageTitle(wfMsg('whitelistedittitle'));
 
                }
 
  
            # If returnto is set, add a redirect header and die
+
# pattern to extract the first name and value of the first arg from template definition
            if ($return) die(header('Location: '.Title::newFromText($return)->getFullURL()));
+
$pattern = '/^.+?[:\\|]\\s*(\\w+)\\s*=\\s*(.*?)\\s*[\\|\\}]/s';
            }
+
$addtext = '';
        }
 
  
    # Create a dummy article for rendering content not associated with any title (unless it already exists)
+
# Get the offsets and lengths of template definitions in content and updates wikitexts
    # - there's probably a better way to do this
+
$cbraces = $this->examineBraces($content);
    function createUntitled() {
+
$ubraces = $this->examineBraces($updates);
        $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
 
                );
 
            }
 
        }
 
  
    # Update templates wikitext content
+
# Loop through the top-level braces in $updates
    # - $updates must start and end with double-braces
+
foreach ($ubraces as $ubrace) if ($ubrace[SFEB_DEPTH] == 1) {
    # - $updates may contain multiple template updates
 
    # - each update must only match one template, comparison of args will reduce multiple matches
 
    function updateTemplates($content,$updates) {
 
        global $wgRequest;
 
        $caction = $wgRequest->getText(SIMPLEFORMS_CACTION);
 
        $taction = $wgRequest->getText(SIMPLEFORMS_TACTION);
 
        $regexp  = $wgRequest->getText(SIMPLEFORMS_REGEXP);
 
  
        # Resort to normal content-action if $updates is not exclusively template definitions or updating templates disabled
+
# Get the update text
        if ($taction == 'update' and preg_match('/^\\{\\{.+\\}\\}$/is',$updates,$match)) {
+
$utext = substr($updates,$ubrace[SFEB_OFFSET],$ubrace[SFEB_LENGTH]);
  
            # pattern to extract the first name and value of the first arg from template definition
+
# Get braces in content with the same name as this update
            $pattern = '/^.+?[:\\|]\\s*(\\w+)\\s*=\\s*(.*?)\\s*[\\|\\}]/s';
+
$matches = array();
            $addtext = '';
+
$uname  = $ubrace[SFEB_NAME];
 +
foreach ($cbraces as $ci => $cbrace) if ($cbrace[SFEB_NAME] == $uname) $matches[] = $ci;
  
            # Get the offsets and lengths of template definitions in content and updates wikitexts
+
# If more than one matches, try to reduce to one by comparing the first arg of each with the updates first arg
            $cbraces = $this->examineBraces($content);
+
if (count($matches) > 1 && preg_match($pattern, $utext, $uarg)) {
            $ubraces = $this->examineBraces($updates);
+
$tmp = array();
 +
foreach ($matches as $ci) {
 +
$cbrace = &$cbraces[$ci];
 +
$cbtext = substr($content, $cbrace[SFEB_OFFSET], $cbrace[SFEB_LENGTH]);
 +
if (preg_match($pattern, $cbtext, $carg) && $carg[1] == $uarg[1] && $carg[2] == $uarg[2])
 +
$tmp[] = $ci;
 +
}
 +
$matches = &$tmp;
 +
}
  
            # Loop through the top-level braces in $updates
+
# If matches has been reduced to a single item, update the template in the content
            foreach ($ubraces as $ubrace) if ($ubrace[SFEB_DEPTH] == 1) {
+
if (count($matches) == 1) {
 +
$coffset = $cbraces[$matches[0]][SFEB_OFFSET];
 +
$clength = $cbraces[$matches[0]][SFEB_LENGTH];
 +
$content = substr_replace($content, $utext, $coffset, $clength);
 +
}
  
                # Get the update text
+
# Otherwise (if no matches, or many matches) do normal content-action on the update
                $utext = substr($updates,$ubrace[SFEB_OFFSET],$ubrace[SFEB_LENGTH]);
+
else $addtext .= "$utext\n";
 +
}
 +
}
  
                # Get braces in content with the same name as this update
+
# Do normal content-action if $updates was not purely templates
                $matches = array();
+
else $addtext = $updates;
                $uname  = $ubrace[SFEB_NAME];
 
                foreach ($cbraces as $ci => $cbrace) if ($cbrace[SFEB_NAME] == $uname) $matches[] = $ci;
 
  
                # If more than one matches, try to reduce to one by comparing the first arg of each with the updates first arg
+
# Do regular expression replacement if regexp parameter set
                if (count($matches) > 1 && preg_match($pattern,$utext,$uarg)) {
+
$addtext = trim($addtext);
                    $tmp = array();
+
$content = trim($content);
                    foreach ($matches as $ci) {
+
if ($regexp) {
                        $cbrace = &$cbraces[$ci];
+
$content = preg_replace("|$regexp|", $addtext, $content, -1, $count);
                        $cbtext = substr($content,$cbrace[SFEB_OFFSET],$cbrace[SFEB_LENGTH]);
+
if ($count) $addtext = false;
                        if (preg_match($pattern,$cbtext,$carg) && $carg[1] == $uarg[1] && $carg[2] == $uarg[2])
+
}
                            $tmp[] = $ci;
 
                        }
 
                    $matches = &$tmp;
 
                    }
 
  
                # If matches has been reduced to a single item, update the template in the content
+
# Add any prepend/append updates using the content-action
                if (count($matches) == 1) {
+
if ($addtext) {
                    $coffset = $cbraces[$matches[0]][SFEB_OFFSET];
+
if ($caction == 'prepend') $content = "$addtext\n$content";
                    $clength = $cbraces[$matches[0]][SFEB_LENGTH];
+
elseif ($caction == 'append')  $content = "$content\n$addtext";
                    $content = substr_replace($content,$utext,$coffset,$clength);
+
elseif ($caction == 'replace') $content = $addtext;
                    }
+
}
  
                # Otherwise (if no matches, or many matches) do normal content-action on the update
+
return $content;
                else $addtext .= "$utext\n";
+
}
                }
 
            }
 
  
        # Do normal content-action if $updates was not purely templates
+
/**
        else $addtext = $updates;
+
* Return a list of info about each template definition in the passed wikitext content
 +
* - list item format is NAME, OFFSET, LENGTH, DEPTH
 +
*/
 +
function examineBraces(&$content) {
 +
$braces = array();
 +
$depths = array();
 +
$depth = 1;
 +
$index = 0;
 +
while (preg_match('/\\{\\{\\s*([#a-z0-9_]*)|\\}\\}/is', $content, $match, PREG_OFFSET_CAPTURE, $index)) {
 +
$index = $match[0][1]+2;
 +
if ($match[0][0] == '}}') {
 +
$brace = &$braces[$depths[$depth-1]];
 +
$brace[SFEB_LENGTH] = $match[0][1]-$brace[SFEB_OFFSET]+2;
 +
$brace[SFEB_DEPTH] = --$depth;
 +
}
 +
else {
 +
$depths[$depth++] = count($braces);
 +
$braces[] = array(SFEB_NAME => $match[1][0], SFEB_OFFSET => $match[0][1]);
 +
}
 +
}
 +
return $braces;
 +
}
  
        # Do regular expression replacement if regexp parameter set
+
/**
        $addtext = trim($addtext);
+
* Needed in some versions to prevent Special:Version from breaking
        $content = trim($content);
+
*/
        if ($regexp) {
+
function __toString() { return 'SimpleForms'; }
            $content = preg_replace("|$regexp|",$addtext,$content,-1,$count);
 
            if ($count) $addtext = false;
 
            }
 
  
        # Add any prepend/append updates using the content-action
+
}
        if ($addtext) {
 
            if    ($caction == 'prepend') $content = "$addtext\n$content";
 
            elseif ($caction == 'append')  $content = "$content\n$addtext";
 
            elseif ($caction == 'replace') $content = $addtext;
 
            }
 
  
        return $content;
+
/**
        }
+
  * Called from $wgExtensionFunctions array when initialising extensions
 
+
*/
    # Return a list of info about each template definition in the passed wikitext content
 
    # - list item format is NAME,OFFSET,LENGTH,DEPTH
 
    function examineBraces(&$content) {
 
        $braces = array();
 
        $depths = array();
 
        $depth = 1;
 
        $index = 0;
 
        while (preg_match('/\\{\\{\\s*([#a-z0-9_]*)|\\}\\}/is',$content,$match,PREG_OFFSET_CAPTURE,$index)) {
 
            $index = $match[0][1]+2;
 
            if ($match[0][0] == '}}') {
 
                $brace              = &$braces[$depths[$depth-1]];
 
                $brace[SFEB_LENGTH] = $match[0][1]-$brace[SFEB_OFFSET]+2;
 
                $brace[SFEB_DEPTH] = --$depth;
 
                }
 
            else {
 
                $depths[$depth++]  = count($braces);
 
                $braces[]          = array(SFEB_NAME => $match[1][0],SFEB_OFFSET => $match[0][1]);
 
                }
 
            }
 
        return $braces;
 
        }
 
 
 
    # Needed in some versions to prevent Special:Version from breaking
 
    function __toString() { return 'SimpleForms'; }
 
 
 
    }
 
 
 
# Called from $wgExtensionFunctions array when initialising extensions
 
 
function wfSetupSimpleForms() {
 
function wfSetupSimpleForms() {
    global $wgLanguageCode,$wgMessageCache,$wgHooks,$wgRequest,$wgSimpleForms;
+
global $wgLanguageCode,$wgMessageCache,$wgHooks,$wgRequest,$wgSimpleForms;
  
    # Add messages
+
# Add messages
    if ($wgLanguageCode == 'en') {
+
if ($wgLanguageCode == 'en') {
        $wgMessageCache->addMessages(array(
+
$wgMessageCache->addMessages(array(
            'sf_editsummary' => 'Article updated via HTTP request'
+
'sf_editsummary' => 'Article updated via HTTP request'
            ));
+
));
        }
+
}
  
    # Instantiate a singleton for the extension
+
# Instantiate a singleton for the extension
    $wgSimpleForms = new SimpleForms();
+
$wgSimpleForms = new SimpleForms();
    }
+
}
  
# Needed in MediaWiki >1.8.0 for magic word hooks to work properly
+
/**
 +
* Needed in MediaWiki >1.8.0 for magic word hooks to work properly
 +
*/
 
function wfSimpleFormsLanguageGetMagic(&$magicWords,$langCode = 0) {
 
function wfSimpleFormsLanguageGetMagic(&$magicWords,$langCode = 0) {
    global $wgSimpleFormsFormMagic,$wgSimpleFormsInputMagic,$wgSimpleFormsRequestMagic,$wgSimpleFormsParaTypeMagic;
+
global $wgSimpleFormsFormMagic, $wgSimpleFormsInputMagic, $wgSimpleFormsRequestMagic, $wgSimpleFormsParaTypeMagic;
    $magicWords[$wgSimpleFormsFormMagic]    = array(0,$wgSimpleFormsFormMagic);
+
$magicWords[$wgSimpleFormsFormMagic]    = array(0, $wgSimpleFormsFormMagic);
    $magicWords[$wgSimpleFormsInputMagic]    = array(0,$wgSimpleFormsInputMagic);
+
$magicWords[$wgSimpleFormsInputMagic]    = array(0, $wgSimpleFormsInputMagic);
    $magicWords[$wgSimpleFormsRequestMagic]  = array(0,$wgSimpleFormsRequestMagic);
+
$magicWords[$wgSimpleFormsRequestMagic]  = array(0, $wgSimpleFormsRequestMagic);
    $magicWords[$wgSimpleFormsParaTypeMagic] = array(0,$wgSimpleFormsParaTypeMagic);
+
$magicWords[$wgSimpleFormsParaTypeMagic] = array(0, $wgSimpleFormsParaTypeMagic);
    return true;
+
return true;
    }
+
}

Revision as of 06:41, 14 January 2009

<?php /**

* SimpleForms extension - Provides functions to make and process forms
* Template: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.

Category:Extensions in progress

* See http://www.mediawiki.org/Extension:Simple_Forms for installation and usage details
* See http://www.organicdesign.co.nz/Extension_talk:SimpleForms.php for development notes and disucssion
* 
* Started: 2007-04-25, see article history
* 
* @package MediaWiki
* @subpackage Extensions
* @author Aran Dunkley User:Nad
* @copyright © 2007 Aran Dunkley
* @licence GNU General Public Licence 2.0 or later
*/

if (!defined('MEDIAWIKI')) die('Not an entry point.'); define('SIMPLEFORMS_VERSION', '0.4.11, 2009-01-14');

  1. index.php parameter names

define('SIMPLEFORMS_CONTENT', 'content'); # used for parsing wikitext content define('SIMPLEFORMS_CACTION', 'caction'); # specify whether to prepend, append or replace existing content define('SIMPLEFORMS_SUMMARY', 'summary'); # specify an edit summary when updating or creating content define('SIMPLEFORMS_PAGENAME', 'pagename'); # specify a page heading to use when rendering content with no title define('SIMPLEFORMS_MINOR', 'minor'); # specify that the edit/create be flagged as a minor edit define('SIMPLEFORMS_TACTION', 'templates'); # specify that the edit/create be flagged as a minor edit define('SIMPLEFORMS_USERNAME', 'username'); # specify a different username to use when the server is editing define('SIMPLEFORMS_RETURN', 'returnto'); # specify a page to return to after processing the request define('SIMPLEFORMS_REGEXP', 'regexp'); # if the content-action is replace, a perl regular expression can be used

  1. Parser function names

$wgSimpleFormsFormMagic = "form"; # the parser-function name for form containers $wgSimpleFormsInputMagic = "input"; # the parser-function name for form inputs $wgSimpleFormsRequestMagic = "request"; # the parser-function name for accessing the post/get variables $wgSimpleFormsParaTypeMagic = "paratype"; # the parser-function name for checking post/get parameter types

  1. Configuration

$wgSimpleFormsRequestPrefix = ""; # restricts #request and GET/POST variable names to their own namespace, set to "" to disable $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

  1. Allow anonymous edits from these addresses

$wgSimpleFormsAllowRemoteAddr = array('127.0.0.1'); if (isset($_SERVER['SERVER_ADDR'])) $wgSimpleFormsAllowRemoteAddr[] = $_SERVER['SERVER_ADDR'];

$wgSimpleFormsEnableCaching = true; define('SIMPLEFORMS_UNTITLED', 'UNTITLED'); define('SFEB_NAME', 0); define('SFEB_OFFSET', 1); define('SFEB_LENGTH', 2); define('SFEB_DEPTH', 3);

$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. If it's a simple-forms ajax call, don't use dispatcher

if ($wgUseAjax && isset($_REQUEST['action']) && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == 'wfSimpleFormsAjax') { $_REQUEST['action'] = 'render'; if (is_array($_REQUEST['rsargs'])) foreach ($_REQUEST['rsargs'] as $arg) if (preg_match('/^(.+?)=(.+)$/', $arg, $m)) $_REQUEST[$m[1]] = $m[2]; }

  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; $wgSimpleFormsEnableCaching = false; }

function wfSimpleFormsUntitledContent(&$article, &$text) { global $wgOut, $wgRequest; if ($article->getTitle()->getText() == SIMPLEFORMS_UNTITLED) { $text = $wgRequest->getText(SIMPLEFORMS_CONTENT); if ($title = $wgRequest->getText(SIMPLEFORMS_PAGENAME)) $wgOut->setPageTitle($title); else { $wgOut->setPageTitle(' '); $wgOut->addScript('<style>h1.firstHeading{display:none}</style>'); } } return true; }

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

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

/**

* Define a singleton for SimpleForms operations
*/

class SimpleForms {

var $id = 0;

/** * Constructor */ function SimpleForms() { global $wgParser, $wgHooks, $wgTitle, $wgSimpleFormsFormMagic, $wgSimpleFormsInputMagic, $wgSimpleFormsRequestMagic, $wgSimpleFormsParaTypeMagic, $wgSimpleFormsEnableCaching; $wgParser->setFunctionHook($wgSimpleFormsFormMagic, array($this,'formMagic')); $wgParser->setFunctionHook($wgSimpleFormsInputMagic, array($this,'inputMagic')); $wgParser->setFunctionHook($wgSimpleFormsRequestMagic, array($this,'requestMagic')); $wgParser->setFunctionHook($wgSimpleFormsParaTypeMagic, array($this,'paramTypeMagic')); $this->createUntitled(); $this->processRequest(); if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'render' && (!is_object($wgTitle) || isset($_REQUEST['content']))) { $wgHooks['OutputPageBeforeHTML'][] = array($this, 'render'); $wgSimpleFormsEnableCaching = false; } $this->id = uniqid('sf-'); }

/** * 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 formMagic(&$parser) { global $wgScript, $wgSimpleFormsEnableCaching; if (!$wgSimpleFormsEnableCaching) $parser->disableCache(); $argv = func_get_args(); $id = $this->id; if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'render' && isset($_REQUEST['wiklet'])) $hidden = '<input type="hidden" name="action" value="render"/> <input type="hidden" name="wiklet"/>'; else $hidden = ; unset($argv['action']); $form = ; $args = ; $argl = array(); foreach ($argv as $arg) if (!is_object($arg)) { if (preg_match('/^([a-z0-9_]+?)\\s*=\\s*(.+)$/is', $arg, $match)) { $args .= " $match[1]=\"$match[2]\""; $argl[$match[1]] = $match[2]; } else $form = $arg; } $action = isset($argl['action']) ? $argl['action'] : $wgScript; $form = "<form$args action=\"$action\" id=\"$id\">$hidden$form</form>"; $this->id = uniqid('sf-'); $form = preg_replace("/^\\s+/m",,$form); return array($form, 'noparse' => true, 'isHTML' => true); }

/** * Renders a form input */ function inputMagic(&$parser) { global $wgSimpleFormsRequestPrefix, $wgSimpleFormsEnableCaching; if (!$wgSimpleFormsEnableCaching) $parser->disableCache();

$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*=\\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['multiple'])) { if (isset($argv['name'])) $argv['name'] .= '[]'; }

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"; }

# Ajax link or button elseif ($type == 'ajax') { $update = isset($argv['update']) ? $argv['update'] : $this->id; $format = isset($argv['format']) ? $argv['format'] : 'button'; unset($argv['update']); unset($argv['format']); if (isset($argv['template'])) { $template = '{'.'{'.$argv['template']; $template = "var t = '$template\\n'; inputs = f.getElementsByTagName('select'); for (i = 0; i < inputs.length; i++) if (n = inputs[i].getAttribute('name')) t += '|' + n + '=' + inputs[i].getAttribute('selected') + '\\n'; t = t + '}'+'}\\n'; alert(t);/* i = document.createElement('input'); i.setAttribute('type','hidden'); i.setAttribute('name','templates'); i.setAttribute('value','update'); f.appendChild(i); i = document.createElement('input'); i.setAttribute('type','hidden'); i.setAttribute('name','content'); i.setAttribute('value',t); f.appendChild(i);*/"; unset($argv['template']); } else $template = ;

if ($format == 'link') { # Render the Ajax input as a link independent of any form $element = 'a'; $t = isset($argv['title']) ? $argv['title'] : false; if ($content == ) $content = $t; if ($t) $t = Title::newFromText($t); $argv['class'] = !$t || $t->exists() ? 'ajax' : 'new ajax'; unset($argv['type']); $params = array(); foreach ($argv as $k => $v) if ($k != 'class') $params[] = "'$k=$v'"; $params = join(',',$params); $argv['href'] = "javascript:var x = sajax_do_call('wfSimpleFormsAjax',[$params],document.getElementById('$update'))"; } else { # Render the Ajax input as a form submit button $argv['type'] = 'button'; $element = 'input'; if (!isset($argv['onClick'])) $argv['onClick'] = ; $argv['onClick'] .= "a = []; f = document.getElementById('{$this->id}'); i = f.elements; for (var k = 0; k < f.elements.length; k++) { if (i[k].type == 'select-one') { if (i[k].selectedIndex !== undefined ) { a.push(i[k].name+'='+i[k].options[i[k].selectedIndex].text); } } else if (i[k].name && i[k].value && (i[k].type != 'radio' || i[k].checked) && (i[k].type != 'checkbox' || i[k].checked)) { a.push(i[k].name+'='+i[k].value); } } sajax_request_type = 'POST'; x = sajax_do_call('wfSimpleFormsAjax',a,document.getElementById('$update'))"; }

foreach ($argv as $k => $v) $args .= " $k=\"$v\""; $input = "<$element$args>$content</$element>\n"; }

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

$input = preg_replace("/^\\s+/m",,$input); return array($input,'noparse' => true, 'isHTML' => true); }

/** * Return value from the global $_REQUEST array (containing GET/POST variables) */ function requestMagic(&$parser) { global $wgRequest, $wgSimpleFormsRequestPrefix, $wgContLang;

$args = func_get_args();

# the first arg is the parser. We already have it (by # reference even), so we can remove it from the array array_shift($args);

# get the request parameter name $paramName = array_shift($args);

# only thing left in $args at this point are the array keys # If no keys are specified, we just call getText() if (count($args) == 0) { $paramValue = $wgRequest->getText($wgSimpleFormsRequestPrefix.$paramName); return $paramValue; }

# when the parameter is a scalar calling getArray() puts it in an # array and returns the array, so we need to do a scalar check if (!is_null($wgRequest->getVal($wgSimpleFormsRequestPrefix.$paramName))) return ;

# get the array associated with this parameter name $paramValue = $wgRequest->getArray($wgSimpleFormsRequestPrefix.$paramName);

# time to descend into the depths of the array associated with the # parameter name while (count($args) > 0) { $key = array_shift($args);

# do we have more keys than we have array nests? if (!is_array($paramValue)) return ;

# a little closer to the value we want $paramValue = $paramValue[$key]; }

# do we have more array nests than we have keys, or a null? if (is_array($paramValue) || is_null($paramValue)) return ;

# we've found a param value! $paramValue = str_replace("\r\n", "\n", $wgContLang->recodeInput($paramValue));

return $paramValue; }

/** * requestMagic() returns an empty string under three conditions: * 1) no such parameter was passed via the request, * 2) the specified parameter is an array, and * 3) the specified parameter was set to an empty string. * Because of this we need a function to determine which is the case. This * function returns '0' if the parameter doesn't exist, '1' if the parameter * is a scalar, and '2' if the parameter is an array. */ function paramTypeMagic(&$parser) { global $wgRequest, $wgSimpleFormsRequestPrefix;

$args = func_get_args();

# the first arg is the parser, we already have it by # reference, so we can remove it from the array array_shift($args);

# get the request parameter name $paramName = array_shift($args);

# only thing left in $args at this point are the array keys # If no keys are specified, we just try to get a scalar if ( count($args) == 0) { $paramValue = $wgRequest->getVal($wgSimpleFormsRequestPrefix.$paramName); if (is_null($paramValue)) { # getVal() returns null if the reqest parameter is an array, so # we need to verify that the parameter was not passed. $paramValue = $wgRequest->getArray($wgSimpleFormsRequestPrefix.$paramName); return is_null($paramValue) ? '0' : '2'; }

# found a scalar return '1'; }

# when the parameter is a scalar calling getArray() puts it in an # array and returns the array, so we need to do a scalar check if (!is_null($wgRequest->getVal($wgSimpleFormsRequestPrefix.$paramName))) return '0';

# get the array associated with this parameter name $paramValue = $wgRequest->getArray($wgSimpleFormsRequestPrefix.$paramName);

# descend into the depths of the array while (count($args) > 0) { $key = array_shift($args);

# do we have more keys than we have array nests? if (!is_array($paramValue) || !array_key_exists($key, $paramValue)) return '0';

# a little closer to the value we want $paramValue = $paramValue[$key]; }

# do we have more array nests than we have keys? return is_array($paramValue) ? '2' : '1'; }

/** * Return the raw content */ function raw($text) { global $wgOut,$wgParser,$wgRequest; $this->setCaching(); $expand = $wgRequest->getText('templates') == 'expand'; if ($expand) $text = $wgParser->preprocess($text,new Title(),new ParserOptions()); $wgOut->disable(); wfResetOutputBuffers(); header('Content-Type: application/octet-stream'); echo($text); return false; }

/** * Return rendered content of page */ function render(&$out, &$text) { $this->setCaching(); $out->disable(); wfResetOutputBuffers(); echo($text); return false; }

/** * Disable caching if necessary */ function setCaching() { global $wgOut, $wgEnableParserCache, $wgSimpleFormsEnableCaching; if ($wgSimpleFormsEnableCaching) return; $wgOut->enableClientCache(false); header("Cache-Control: no-cache, must-revalidate"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); }

/** * Processes HTTP requests containing wikitext content */ function processRequest() { global $wgOut, $wgRequest, $wgUser, $wgTitle, $wgSimpleFormsAllowRemoteAddr, $wgSimpleFormsAllowCreate, $wgSimpleFormsAllowEdit;

$content = trim($wgRequest->getText(SIMPLEFORMS_CONTENT)); $action = $wgRequest->getText('action'); $title = $wgRequest->getText('title');

# Handle content with action=raw case (allows templates=expand too) if ($action == 'raw' && isset($_REQUEST[SIMPLEFORMS_CONTENT])) $this->raw($content);

# Handle content and title case (will either update or create an article) if ($title != SIMPLEFORMS_UNTITLED && isset($_REQUEST[SIMPLEFORMS_CONTENT])) {

$title = Title::newFromText($wgRequest->getText('title')); if ($title->getNamespace() == NS_SPECIAL) return; if (!is_object($wgTitle)) $wgTitle = $title; # hack to stop DPL crashing $article = new Article($title); $allow = in_array($_SERVER['REMOTE_ADDR'], $wgSimpleFormsAllowRemoteAddr); $summary = $wgRequest->getText(SIMPLEFORMS_SUMMARY); $minor = $wgRequest->getText(SIMPLEFORMS_MINOR); $return = $wgRequest->getText(SIMPLEFORMS_RETURN);

# If title exists and allowed to edit, prepend/append/replace content if ($title->exists()) { if ($wgSimpleFormsAllowEdit && ($allow || $wgUser->isAllowed('edit'))) { $update = $this->updateTemplates($article->getContent(),$content); $article->updateArticle($update, $summary ? $summary : wfMsg('sf_editsummary'), false, false); } else $wgOut->setPageTitle(wfMsg('whitelistedittitle')); }

# No such title, create new article from content if allowed to create else { if ($wgSimpleFormsAllowCreate && ($allow || $wgUser->isAllowed('edit'))) $article->insertNewArticle($content, $summary ? $summary : wfMsg('sf_editsummary', 'created'), false, false); else $wgOut->setPageTitle(wfMsg('whitelistedittitle')); }

# If returnto is set, add a redirect header and die if ($return) die(header('Location: '.Title::newFromText($return)->getFullURL())); } }

/** * 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 ); } }

/** * Update templates wikitext content * - $updates must start and end with double-braces * - $updates may contain multiple template updates * - each update must only match one template, comparison of args will reduce multiple matches */ function updateTemplates($content, $updates) { global $wgRequest; $caction = $wgRequest->getText(SIMPLEFORMS_CACTION); $taction = $wgRequest->getText(SIMPLEFORMS_TACTION); $regexp = $wgRequest->getText(SIMPLEFORMS_REGEXP);

# Resort to normal content-action if $updates is not exclusively template definitions or updating templates disabled if ($taction == 'update' and preg_match('/^\\{\\{.+\\}\\}$/is', $updates, $match)) {

# pattern to extract the first name and value of the first arg from template definition $pattern = '/^.+?[:\\|]\\s*(\\w+)\\s*=\\s*(.*?)\\s*[\\|\\}]/s'; $addtext = ;

# Get the offsets and lengths of template definitions in content and updates wikitexts $cbraces = $this->examineBraces($content); $ubraces = $this->examineBraces($updates);

# Loop through the top-level braces in $updates foreach ($ubraces as $ubrace) if ($ubrace[SFEB_DEPTH] == 1) {

# Get the update text $utext = substr($updates,$ubrace[SFEB_OFFSET],$ubrace[SFEB_LENGTH]);

# Get braces in content with the same name as this update $matches = array(); $uname = $ubrace[SFEB_NAME]; foreach ($cbraces as $ci => $cbrace) if ($cbrace[SFEB_NAME] == $uname) $matches[] = $ci;

# If more than one matches, try to reduce to one by comparing the first arg of each with the updates first arg if (count($matches) > 1 && preg_match($pattern, $utext, $uarg)) { $tmp = array(); foreach ($matches as $ci) { $cbrace = &$cbraces[$ci]; $cbtext = substr($content, $cbrace[SFEB_OFFSET], $cbrace[SFEB_LENGTH]); if (preg_match($pattern, $cbtext, $carg) && $carg[1] == $uarg[1] && $carg[2] == $uarg[2]) $tmp[] = $ci; } $matches = &$tmp; }

# If matches has been reduced to a single item, update the template in the content if (count($matches) == 1) { $coffset = $cbraces[$matches[0]][SFEB_OFFSET]; $clength = $cbraces[$matches[0]][SFEB_LENGTH]; $content = substr_replace($content, $utext, $coffset, $clength); }

# Otherwise (if no matches, or many matches) do normal content-action on the update else $addtext .= "$utext\n"; } }

# Do normal content-action if $updates was not purely templates else $addtext = $updates;

# Do regular expression replacement if regexp parameter set $addtext = trim($addtext); $content = trim($content); if ($regexp) { $content = preg_replace("|$regexp|", $addtext, $content, -1, $count); if ($count) $addtext = false; }

# Add any prepend/append updates using the content-action if ($addtext) { if ($caction == 'prepend') $content = "$addtext\n$content"; elseif ($caction == 'append') $content = "$content\n$addtext"; elseif ($caction == 'replace') $content = $addtext; }

return $content; }

/** * Return a list of info about each template definition in the passed wikitext content * - list item format is NAME, OFFSET, LENGTH, DEPTH */ function examineBraces(&$content) { $braces = array(); $depths = array(); $depth = 1; $index = 0; while (preg_match('/\\{\\{\\s*([#a-z0-9_]*)|\\}\\}/is', $content, $match, PREG_OFFSET_CAPTURE, $index)) { $index = $match[0][1]+2; if ($match[0][0] == '}}') { $brace = &$braces[$depths[$depth-1]]; $brace[SFEB_LENGTH] = $match[0][1]-$brace[SFEB_OFFSET]+2; $brace[SFEB_DEPTH] = --$depth; } else { $depths[$depth++] = count($braces); $braces[] = array(SFEB_NAME => $match[1][0], SFEB_OFFSET => $match[0][1]); } } return $braces; }

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

}

/**

* Called from $wgExtensionFunctions array when initialising extensions
*/

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

# Add messages if ($wgLanguageCode == 'en') { $wgMessageCache->addMessages(array( 'sf_editsummary' => 'Article updated via HTTP request' )); }

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

/**

* Needed in MediaWiki >1.8.0 for magic word hooks to work properly
*/

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