Extension talk:SimpleForms.php
Contents
SimpleForms 1.0
I was going to do a complete rewrite of SimpleForms (see "SimpleForms 2" thread below). But after reviewing the main problems, I think it can be made much more robust and useful with some key modifications to the current version.
- No need for UNTITLED article, just set a variable at the start to say its an untitled request, then set to MediaWiki:Mainpage
- Use Treeview5 method of GUID's and ParserAfterTidy replacement
- Change templates=update to work also with template specified instead of content which would update from post vars
- Add a section to the standard edit form allowing any existent forms associated with templates used in the article to have their inputs added above the normal form, so that the normal save or preview posts all the data. Before extension setup, the posted data is checked, and if template forms posted, then wptextbox is modified accordingly.
- The problem of forms not being able to be used within another parser-function is due to the parser-function subjecting its content to the wiki-parser. This can be fixed by protecting them in the same way as TreeView5.
Selenium tests
There is a lot of diverse functionality involved in simple forms, and developing some features can break others without anyone realising for long periods. To avoid this, we need to create a decisive list of features that the extension creates clearly enough that each feature has a corresponding Selenium test.
Using MediaWiki Ajax instead of MooTools
0.3.13 has had the following snippet of code added in preparation for the 0.4 release which will no longer depend on Mootools for its ajax functionality. <php> if ($wgUseAjax && $_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]; } </php> This allows us to use the sajax_do_call function from MediaWiki's ajax.js, but this works by requesting the AjaxDispatcher class to execute a function specified in the request and to return the results of the function. This is not quite the way SimpleForms needs it to work because the AjaxDispatcher is instantiated before any high-level MediaWiki objects have been instantiated, but SimpleForms needs to return the fully rendered page content with all extension activated etc.
The code above gets around this problem by detecting if incoming requests from sajax_do_call are specifying a function called "wfSimpleFormsAjax", and if so the action is changed to render so the request will no be handled by the AjaxDispatcher. The sajax_do_call argument list is shifted into the main $_REQUEST array as if it came from a normal GET or POST request. Note that there is actually no function called wfSimpleFormsAjax, it is just a dummy value used to identify the 'sajax_do_call request as one for SimpleForms to handle instead of the AjaxDispatcher.
Here is an example SimpleForms input which makes an ajax request using the sajax_do_call function:
MediaWiki API
There is a MediaWiki API under development which will allow modifcation of content via request variables inherently.
- It appears that links do not parser in the edit summary e.g. this diff. Would be a nice to be able to link to the form deriving content--Sven 21:29, 30 June 2007 (NZST)
- SimpleForms expects wikitext with links etc to be passed, but you have to put <nowiki> around it so that it's not parsed before being assigned to the form attribute. --Nad 22:01, 30 June 2007 (NZST)
Edit forms
Initially I was thinking of having an #edit parser-function which extends the #form functionality to behave differently from action=edit and the CreateArticle specialpage.
After starting the SimpleDatabase specialpage I realised that being able to open a form ajaxly that is connected to another articles content (that article acts as the forms data-source) is more intuitive, and doesn't require two different ways of defining forms.
Possibly a better solution still could be to use an editform parameter with action=edit. The parameter would determine which definition to update (by template name, with id too if necessary to disambiguate). The parameter should also be able to specify to update all (which could be a good setting for the normal edit action's url too). Maybe allowing a list of template/id's would be good too.
- Each template definition needs to be able specify a list of forms which are able to edit it.
- Using action=edit with forms could be the best way to handle article updating since it would use MediaWiki's edit tokens properly
- Alternatively the form to edit with could be specified in the query string as well
Semantic Forms
This way of integrating with the existing edit system is how the SemanticForms CreateForm special-page works. Maybe SimpleForms should not try and handle the structured data side of things at all and should only handle the functionality-based inputs.
Source Edit Policy
So what's the policy on editing the source of this extension? I see registered users are allowed to edit it, so I'm concluding it's not "Keep your damn dirty hands off of it." But is there any sort additional etiquette other than "make sure it works?" Ask for permission? Provide purpose and details of the edit? —Sledged (talk) 13:44, 7 March 2008 (NZDT)
- Go for it :) make sure that updates are runnable and not broken though. I've been working on a new version 0.4 but haven't had time for a few months to make any progress. The new one is designed to use the MediaWiki API for updating content, and will make it simple to map forms to template fields. --Nad 16:10, 7 March 2008 (NZDT)
- That sounds a lot like Semantic Forms without the need for Semantic MediaWiki. —Sledged (talk) 13:48, 8 March 2008 (NZDT)
- We'll be making heavy use of SMW too, but we want to have our forms work with AJAX and skip the edit form, but that's not in the Semantic Forms road map --Nad 14:51, 8 March 2008 (NZDT)
- I wouldn't mind seeing that functionality in this extension, but there's a few pitfalls you should avoid.
- Don't require headings be put inside templates. This is quite an annoyance for me with SF. Putting headings in templates is a bad policy to begin with, but to require it such a thing in order to use the forms...
- Follow redirects to the underlying template.
- Make sure the extension recognizes subst:SomeTemplate and SomeTemplate as the same template.
- Give users control of newline characters between templates. I've had a number of templates that require that templates begin on the same line where the last one ended. Conversely, a user may want more than on newline between a pair of template calls.
- With the loops extension I don't have to define a finite number of template arguments. A user can enter |arg1=val1 |arg2=val2 |arg3=val3 ... |argN=valN so long as the arguments are consecutively numbered. So the form should be allow more fields to be added dynamically by the user. SF does this with respect to a set of fields associated with a template call, but not a specific field within a template call.
- Handle pipes and braces entered by users that prematurely end template arguments and template calls. Or any other aberrant wiki-markup that would affect the template call.
- —Sledged (talk) 18:30, 8 March 2008 (NZDT)
- I wouldn't mind seeing that functionality in this extension, but there's a few pitfalls you should avoid.
- We'll be making heavy use of SMW too, but we want to have our forms work with AJAX and skip the edit form, but that's not in the Semantic Forms road map --Nad 14:51, 8 March 2008 (NZDT)
- Nad, with your "Go for it" policy, I've applied a fix where radio and checkbox inputs weren't working for Ajax, since the code was sending those values regardless of their checked status. I have to admit, I originally made the fix to 0.4.6 and tested it there - and wasn't able to test it under 0.4.7 because I'm still back on MW 1.11 and I assume that's why I'm having the UNIQ issue with 0.4.7. But this is just a change to the javascript, so I think it's a pretty safe change.--Danbrice 17:46, 29 March 2008 (NZST)
- That sounds a lot like Semantic Forms without the need for Semantic MediaWiki. —Sledged (talk) 13:48, 8 March 2008 (NZDT)
Simple Forms 2
I should just make the new one 2.0 because it's a complete rewrite. I'd like to incorporate the points you've made in the section above into the new version, as well as a number of concerns that have cropped up for us here at OD with the current version:
- Use tags instead of parser-function syntax so that the syntax is the same as for normal forms
- Filter parameters and JS from syntax to prevent malicious code injection using forms
- Allow forms to work properly inside other parser-functions
- Use MediaWiki API for all article update operations
- Make templates=update automatically map form fields to template fields
- I actually like Simple Forms as a set of parser functions. There's been a few times I've encountered issues with mixing parser functions with tags (though may have changed with v1.12alpha MW's preprocessor). Also, one other thing I've noticed is that MediaWiki discourages global variables, you may want to use static class members and methods, and class constants. —Sledged (talk) 15:36, 10 March 2008 (NZDT)
- I agree parser functions seem to work well for this extension.--Danbrice 17:14, 29 March 2008 (NZST)
- Ok I'll stick with parser-functions, or at least allow both. --Nad 07:55, 30 March 2008 (NZST)
Usage of templates=update flawed?
I'm trying to use the functionality of SimpleForms to create an online voting system (i.e. select your score, then click vote). The underlying storage of this vote goes to a new page: Vote_MyVoteName. The idea is that I will be storing the username and score each user granted in a template like this: {{Rating|user=XYZ|num=123}} Now the idea is that the user can change their score at any time, but their vote shouldn't double count. I.e., I should replace their existing Rating template with their updated score. Sounds simple enough. Here is my source:
{{#form:method=submit| {{#input:type=hidden|name=content|id={{{name}}}_content}} {{#input:type=hidden|name=title|value=Vote_{{{name}}}}} {{#input:type=hidden|name=summary|id={{{name}}}_summary}} {{#input:type=hidden|name=caction|value=append}} {{#input:type=hidden|id={{{name}}}_num|value=5}} {{#input:type=hidden|name=returnto|value={{PAGENAMEE}}}} {{#input:type=hidden|name=templates|value=update}} {{#input:type=submit|value=Click to Vote|onClick= var username='{{USERNAME}}'; var num=document.getElementById('{{{name}}}_num').value; var cont= '{' + '{' + 'Rating|user=' + username + '|num=' + num + '}' + '}'; document.getElementById('{{{name}}}_content').setAttribute('value', cont); document.getElementById('{{{name}}}_summary').setAttribute('value','User: {{USERNAME}} - Voted:'+ num);}} }}
Note that I call this as a template itself, where {{USERNAME}} is a magic variable I've written to get the username, {{{name}}} is the name of the vote provided by the calling page.
OK, well if the page Vote_MyVoteName has no {{Rating|user=XYZ|num=123}} on it, then it successfully creates this page, and appends the template to it. If however, I log out and log in as a different user (say ABC), then run this template again, on the page that only has one template {{Rating|user=XYZ|num=123}}, then the result is actually {{Rating|user=ABC|num=123}}. However, if the Vote_MyVoteName has two lines with the same Rating, but different users, the code works as expected, i.e. it updates the correct users voting. Am I using this wrongly, or should it be doing as I'm expecting? --David Hayes 02:36, 21 March 2008 (NZST)
- Sorry I don't quite get what you're meaning... how do you want it to work that it's not working like? If it's a problem with the current version I'll try and think of a solution for the new version --Nad 08:00, 30 March 2008 (NZST)
Error listing sub-categories (from example)
Having problems producing a list of sub-categories as taken from Mediawiki' SimpleForms page. It produces "�UNIQ1894d9d14ac9bc67-nowiki-00000002-QINU�" and nothing else. Acolyte 00:01, 2 April 2008 (NZST)
updateTemplate()
<php> /**
* Replace parameters in a template call using examineBraces * - $content can be an array of name/value pairs or a string of content * - allows for empty array or string * - allows names to be either templates or parser-functions (must include trailing colon for parser-functions) * - allows for multiple templates of same name by matching first param if ambiguous */
function updateTemplate(&$text, $template, $content, $comment = , $minor = false) {
# get info on positioning and params of all braces structures in $text $braces = $this->examineBraces($text);
# reduce the braces candidates for replacement to one (or return with error) $brace = false; $matches = array(); foreach ($braces as $b) if ($b[SFEB_NAME] == $template) $matches[] = $b; if (count($matches) < 1) return false; # no braces of matching name elseif (count($matches) == 1) $brace = $matches[0]; # single match else { # ambiguous if (!is_array($content) || count($content) < 1) return false; # no params $idkey = array_keys($content)->[0]; $idval = $content[$idkey]; foreach ($matches as $match) if (in_array($idkey, $match[SFEB_PARAMS]) && $match[SFEB_PARAMS][$idkey] === $idval) $brace = $match; if ($brace === false) return false; # none with matching id param }
if (is_array($content)) { # todo: rebuild $content array as a string } else $content = trim($content);
# replace final brace candidate with content $text = substr_replace($text, $content, $brace[SFEB_OFFSET], $brace[SFEB_LENGTH]);
return true; # successful replacement into $text } </php>