Page MenuHomePhabricator

Nested extension calls inside templates cause incomplete rendering
Closed, ResolvedPublic

Assigned To
None
Authored By
bzimport
Nov 6 2005, 7:21 PM
Referenced Files
F2419: testbug.txt
Nov 21 2014, 8:54 PM
F2420: ATemplate.txt
Nov 21 2014, 8:54 PM
F2418: test.php
Nov 21 2014, 8:54 PM

Description

Author: efeins

Description:
A form of extension call inside a template will cause another extension not to
be called. Instead, an intermediate of the wikitext is rendered.

Version info:
MediaWiki: 1.5.2
PHP: 4.3.10-16etch1 (apache2handler)
MySQL: 4.1.14-Debian_6-log

Example:
The following extension:
<code>
<?php
$wgExtensionFunctions[] = "wfTestExtension";

function wfTestExtension() {
global $wgParser;

$wgParser->setHook( "inner", "innerHook" );
$wgParser->setHook( "inside", "insideHook" );
}

function innerHook( $input, $argv ) {

  1. set a variable

global $wgOut;

$output = $output.$wgOut->parse($input, false);

return $output;
}

function insideHook( $input, $argv ) {
return "(inside)";
}

?>
</code>

And the following wikitext (in a page called Test_Page):
<code>
Here is the test:
<p>outer text 1</p>
<inner>
<p>inner text 1</p>
<inside></inside>
{{:ATemplate}}
<p>inner text 2</p>
</inner>
<p>outer text 2</p>
</code>

And the following Wikitext in ATemplate:
<code>
<inner>
<inside></inside>
</inner>
</code>

Renders Test_Page as:
<pre>
Here is the test:

outer text 1

inner text 1

NaodW29-inside593e7feb7eece2e700000001

(inside)

inner text 2

outer text 2
</pre>

Note that it's the <inside></inside> call in Test_Page that is failing. The one
in ATemplate works correctly.

IF ATemplate is changed to:
<code>
<inside></inside>
</code>
removing the calls to inner, it renders correctly as:
<pre>
Here is the test:

outer text 1

inner text 1

(inside) (inside)

inner text 2

outer text 2
</pre>

So, the nested call to inner inside a template fails.

Nested extension calls outside a template never work because the inner instance
of the /inner tag will close the outer call to inner.


Version: 1.5.x
Severity: normal
OS: Linux
Platform: PC

Details

Reference
bz3896

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 8:54 PM
bzimport set Reference to bz3896.
bzimport added a subscriber: Unknown Object (MLST).

efeins wrote:

The extension file

Attached:

efeins wrote:

Test wikitext (Test_page)

Attached:

efeins wrote:

Test ATemplate

Attached:

I don't really understand the question that's being asked, or
what you're trying to accomplish.

efeins wrote:

The extension I'm trying to write is a variation on page-specific variables.
You could then so something like this:

<set flag="x"> <-- sets a given flag to true
<flag name="x"></flag> <-- returns the value of the flag
{{:Template_with_conditional_text}} <-- this template has a conditional
expression in it that depends on the value of flag x. It should also be able to
reset the value of the flag and call other templates
</set>
{{:Template_with_conditional_text}} <-- this template has a conditional
expression in it that depends on the value of flag x and will output different
text than the first time it was called

In the test-case, inner is analogous to "set." And "inside" is analogous to
"flag." But, any time "flag" ("inside" in the test case) is called from inside
a nested "set" call in the template ("inner", in the test case), one instance of
"flag"/"inside" is left as a MediaWiki internal representation of the call.

I claim that I should never see text resembling:
NaodW29-inside593e7feb7eece2e700000001
It's some kind of intermediate form of an extension call generated in
Parser.php. And, that's a bug.

The attached test-case is a very simple example of the phenomenon that is
independent of anything I'm trying to accomplish. But, it does demonstrate the
effect without the complication of the rest of my code.

Nested extensions are really not something the current parser expects or
is designed to work with, so by using them you're likely to have all
kinds of trouble. (Consider software other than MediaWiki; MediaWiki
text is not meant to be a programming language.)

Register your hooks in the other order, so the <inside> bits are
replaced before the <inner> bits:

$wgParser->setHook( "inside", "insideHook" );
$wgParser->setHook( "inner", "innerHook" );

efeins wrote:

I tried reversing the order and it works in this case. I am evaluating
MediaWiki because it has a long list of other features that I want (good
interface, full UTF-8 and multilingual support). If I can extend it to do what
I want it to do, I'll use it, if not, I'll use the software that will come
closest to what I want it to do. Thanks.

piotr.bieganski wrote:

I wrote very simple extension rendering coloured text inside extension tags.
It worked correctly until I enabled parsing internal text.
I found this bug when using ext in templates, but observed also without them.

Extension file: Test.php

<?php
  $wgExtensionFunctions[] = "wfTestExtension";
  function wfTestExtension() {
    global $wgParser;
    $wgParser->setHook( "test", "renderTest" );
  }
  
  function renderTest( $input, $params ) {
    global $wgOut;
    $result = "<span style=\"color: red\">";
    $result .= $wgOut->parse( $input, false );
    $result .= "</span>";
    return $result;
  }
?>

Two wiki pages defined as:

Sandbox          = {{Template:Sandbox}} aka <test>PLAYGROUND</test>
Template:Sandbox = <test>SANDBOX</test>

Output on "Sandbox" page:

SANDBOX aka UNIQ23f6a50866512e57-test21156fe8641c796200000001

Details:

http://meta.wikimedia.org/w/index.php?title=MediaWiki_extensions_FAQ#Templates_with_extension_tags

This works fine on trunk if you use the parser parameter
passed to your extension hook. See Cite.php in the Cite
extension for an example.