r29205 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r29204‎ | r29205 | r29206 >
Date:05:37, 3 January 2008
Author:tstarling
Status:old
Tags:
Comment:
* Removed noargs/noparse in braceSubstitution(), they have been largely obsolete since the introduction of replace_callback() and now just cause bugs and confusion. Did some related code cleanup.
* Fixed a bug 529 regression -- uncovered line-start syntax in parser function results was not recognised. Added a parser test for this failure plus another three bug 529 tests for good measure.
Modified paths:
  • /trunk/phase3/includes/Parser.php (modified) (history)
  • /trunk/phase3/maintenance/parserTests.txt (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/parserTests.txt
@@ -6569,7 +6569,56 @@
65706570 </p>
65716571 !! end
65726572
 6573+!!article
 6574+Template:Bullet
 6575+!!text
 6576+* Bar
 6577+!!endarticle
65736578
 6579+!! test
 6580+Bug 529: Uncovered bullet
 6581+!! input
 6582+* Foo {{bullet}}
 6583+!! result
 6584+<ul><li> Foo
 6585+</li><li> Bar
 6586+</li></ul>
 6587+
 6588+!! end
 6589+
 6590+!! test
 6591+Bug 529: Uncovered table already at line-start
 6592+!! input
 6593+x
 6594+
 6595+{{table}}
 6596+y
 6597+!! result
 6598+<p>x
 6599+</p>
 6600+<table>
 6601+<tr>
 6602+<td> 1 </td><td> 2
 6603+</td></tr>
 6604+<tr>
 6605+<td> 3 </td><td> 4
 6606+</td></tr></table>
 6607+<p>y
 6608+</p>
 6609+!! end
 6610+
 6611+!! test
 6612+Bug 529: Uncovered bullet in parser function result
 6613+!! input
 6614+* Foo {{lc:{{bullet}} }}
 6615+!! result
 6616+<ul><li> Foo
 6617+</li><li> bar
 6618+</li></ul>
 6619+
 6620+!! end
 6621+
 6622+
65746623 #
65756624 #
65766625 #
Index: trunk/phase3/includes/Parser.php
@@ -2593,6 +2593,10 @@
25942594 $rules = $normalRules;
25952595 }
25962596
 2597+ if ( $this->ot['html'] || ( $this->ot['pre'] && $this->mOptions->getRemoveComments() ) ) {
 2598+ $text = Sanitizer::removeHTMLcomments( $text );
 2599+ }
 2600+
25972601 $extElements = implode( '|', $this->getStripList() );
25982602 // Use "A" modifier (anchored) instead of "^", because ^ doesn't work with an offset
25992603 $extElementsRegex = "/($extElements)(?:\s|\/>|>)|(!--)/iA";
@@ -3018,6 +3022,27 @@
30193023 }
30203024
30213025 /**
 3026+ * Convert text to a document tree, like preprocessToDom(), but with some special handling
 3027+ * assuming the source text is from a template -- specifically noinclude/includeonly behaviour.
 3028+ */
 3029+ function preprocessTplToDom( $text ) {
 3030+ # If there are any <onlyinclude> tags, only include them
 3031+ if ( !$this->ot['msg'] ) {
 3032+ if ( in_string( '<onlyinclude>', $text ) && in_string( '</onlyinclude>', $text ) ) {
 3033+ $replacer = new OnlyIncludeReplacer;
 3034+ StringUtils::delimiterReplaceCallback( '<onlyinclude>', '</onlyinclude>',
 3035+ array( &$replacer, 'replace' ), $text );
 3036+ $text = $replacer->output;
 3037+ }
 3038+ # Remove <noinclude> sections and <includeonly> tags
 3039+ $text = StringUtils::delimiterReplace( '<noinclude>', '</noinclude>', '', $text );
 3040+ $text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) );
 3041+ }
 3042+
 3043+ return $this->preprocessToDom( $text );
 3044+ }
 3045+
 3046+ /**
30223047 * Replace magic variables, templates, and template arguments
30233048 * with the appropriate text. Templates are substituted recursively,
30243049 * taking care to avoid infinite loops.
@@ -3047,12 +3072,6 @@
30483073 throw new MWException( __METHOD__ . ' called using the old argument format' );
30493074 }
30503075
3051 - # Remove comments
3052 - # This could theoretically be merged into preprocessToDom()
3053 - if ( $this->ot['html'] || ( $this->ot['pre'] && $this->mOptions->getRemoveComments() ) ) {
3054 - $text = Sanitizer::removeHTMLcomments( $text );
3055 - }
3056 -
30573076 $dom = $this->preprocessToDom( $text );
30583077 $flags = $argsOnly ? PPFrame::NO_TEMPLATES : 0;
30593078 $text = $frame->expand( $dom, $flags );
@@ -3105,8 +3124,6 @@
31063125 # Flags
31073126 $found = false; # $text has been filled
31083127 $nowiki = false; # wiki markup in $text should be escaped
3109 - $noparse = false; # Unsafe HTML tags should not be stripped, etc.
3110 - $noargs = false; # Don't replace triple-brace arguments in $text
31113128 $isHTML = false; # $text is HTML, armour it against wikitext transformation
31123129 $forceRawInterwiki = false; # Force interwiki transclusion to be done in raw mode not rendered
31133130 $isDOM = false; # $text is a DOM node needing expansion
@@ -3138,8 +3155,6 @@
31393156 # In either case, return without further processing
31403157 $text = '{{' . $frame->implode( '|', $titleWithSpaces, $args ) . '}}';
31413158 $found = true;
3142 - $noparse = true;
3143 - $noargs = true;
31443159 }
31453160 }
31463161
@@ -3150,8 +3165,6 @@
31513166 $text = $this->getVariableValue( $id );
31523167 $this->mOutput->mContainsOldMagic = true;
31533168 $found = true;
3154 - $noparse = true;
3155 - $noargs = true;
31563169 }
31573170 }
31583171
@@ -3220,10 +3233,6 @@
32213234 $result = call_user_func_array( $callback, $allArgs );
32223235 $found = true;
32233236
3224 - // The text is usually already parsed, doesn't need triple-brace tags expanded, etc.
3225 - $noargs = true;
3226 - $noparse = true;
3227 -
32283237 if ( is_array( $result ) ) {
32293238 if ( isset( $result[0] ) ) {
32303239 $text = $result[0];
@@ -3231,7 +3240,7 @@
32323241 }
32333242
32343243 // Extract flags into the local scope
3235 - // This allows callers to set flags such as nowiki, noparse, found, etc.
 3244+ // This allows callers to set flags such as nowiki, found, etc.
32363245 extract( $result );
32373246 } else {
32383247 $text = $result;
@@ -3260,8 +3269,6 @@
32613270 }
32623271 # Do infinite loop check
32633272 if ( isset( $this->mTemplatePath[$titleText] ) ) {
3264 - $noparse = true;
3265 - $noargs = true;
32663273 $found = true;
32673274 $text = "[[$part1]]" . $this->insertStripItem( '<!-- WARNING: template loop detected -->' );
32683275 wfDebug( __METHOD__.": template loop broken at '$titleText'\n" );
@@ -3277,8 +3284,6 @@
32783285 $text = SpecialPage::capturePath( $title );
32793286 if ( is_string( $text ) ) {
32803287 $found = true;
3281 - $noparse = true;
3282 - $noargs = true;
32833288 $isHTML = true;
32843289 $this->disableCache();
32853290 }
@@ -3303,108 +3308,75 @@
33043309 if ( $this->ot['html'] && !$forceRawInterwiki ) {
33053310 $text = $this->interwikiTransclude( $title, 'render' );
33063311 $isHTML = true;
3307 - $noparse = true;
33083312 } else {
33093313 $text = $this->interwikiTransclude( $title, 'raw' );
 3314+ // Preprocess it like a template
 3315+ $text = $this->preprocessTplToDom( $text );
 3316+ $isDOM = true;
33103317 }
33113318 $found = true;
33123319 }
33133320 wfProfileOut( __METHOD__ . '-loadtpl' );
33143321 }
33153322
3316 - # Recursive parsing, escaping and link table handling
3317 - # Only for HTML output
3318 - if ( $nowiki && $found && ( $this->ot['html'] || $this->ot['pre'] ) ) {
3319 - if ( $isDOM ) {
3320 - $text = $frame->expand( $text );
3321 - }
3322 - $text = wfEscapeWikiText( $text );
3323 - } elseif ( !$this->ot['msg'] && $found ) {
3324 - if ( $noargs ) {
3325 - $newFrame = $frame->newChild();
3326 - } else {
3327 - # Clean up argument array
3328 - $newFrame = $frame->newChild( $args, $title );
3329 - # Add a new element to the templace recursion path
3330 - $this->mTemplatePath[$titleText] = 1;
3331 - }
 3323+ # If we haven't found text to substitute by now, we're done
 3324+ # Recover the source wikitext and return it
 3325+ if ( !$found ) {
 3326+ $text = '{{' . $frame->implode( '|', $titleWithSpaces, $args ) . '}}';
 3327+ # Prune lower levels off the recursion check path
 3328+ $this->mTemplatePath = $lastPathLevel;
 3329+ wfProfileOut( $fname );
 3330+ return $text;
 3331+ }
33323332
3333 - if ( !$noparse ) {
3334 - if ( $isDOM ) {
3335 - if ( $titleText !== false && count( $newFrame->args ) == 0 ) {
3336 - # Expansion is eligible for the empty-frame cache
3337 - if ( isset( $this->mTplExpandCache[$titleText] ) ) {
3338 - $text = $this->mTplExpandCache[$titleText];
3339 - } else {
3340 - $text = $newFrame->expand( $text );
3341 - $this->mTplExpandCache[$titleText] = $text;
3342 - }
3343 - } else {
3344 - $text = $newFrame->expand( $text );
3345 - }
3346 - } else {
3347 - $text = $this->replaceVariables( $text, $newFrame );
3348 - }
 3333+ # Expand DOM-style return values in a child frame
 3334+ if ( $isDOM ) {
 3335+ # Clean up argument array
 3336+ $newFrame = $frame->newChild( $args, $title );
 3337+ # Add a new element to the templace recursion path
 3338+ $this->mTemplatePath[$titleText] = 1;
33493339
3350 - # strip woz 'ere 2004-07
3351 -
3352 - # Bug 529: if the template begins with a table or block-level
3353 - # element, it should be treated as beginning a new line.
3354 - # This behaviour is somewhat controversial.
3355 - if (!$piece['lineStart'] && preg_match('/^(?:{\\||:|;|#|\*)/', $text)) /*}*/{
3356 - $text = "\n" . $text;
3357 - }
3358 - } elseif ( !$noargs ) {
3359 - # $noparse and !$noargs
3360 - # Just replace the arguments, not any double-brace items
3361 - # This is used for rendered interwiki transclusion
3362 - if ( $isDOM ) {
3363 - $text = $newFrame->expand( $text, PPFrame::NO_TEMPLATES );
 3340+ if ( $titleText !== false && count( $newFrame->args ) == 0 ) {
 3341+ # Expansion is eligible for the empty-frame cache
 3342+ if ( isset( $this->mTplExpandCache[$titleText] ) ) {
 3343+ $text = $this->mTplExpandCache[$titleText];
33643344 } else {
3365 - $text = $this->replaceVariables( $text, $newFrame, true );
 3345+ $text = $newFrame->expand( $text );
 3346+ $this->mTplExpandCache[$titleText] = $text;
33663347 }
3367 - } elseif ( $isDOM ) {
3368 - $text = $frame->expand( $text );
 3348+ } else {
 3349+ $text = $newFrame->expand( $text );
33693350 }
3370 - } elseif ( $isDOM ) {
3371 - $text = $frame->expand( $text, PPFrame::NO_TEMPLATES | PPFrame::NO_ARGS );
33723351 }
33733352
 3353+ # Replace raw HTML by a placeholder
 3354+ # Add a blank line preceding, to prevent it from mucking up
 3355+ # immediately preceding headings
 3356+ if ( $isHTML ) {
 3357+ $text = "\n\n" . $this->insertStripItem( $text );
 3358+ }
 3359+ # Escape nowiki-style return values
 3360+ elseif ( $nowiki && ( $this->ot['html'] || $this->ot['pre'] ) ) {
 3361+ $text = wfEscapeWikiText( $text );
 3362+ }
 3363+ # Bug 529: if the template begins with a table or block-level
 3364+ # element, it should be treated as beginning a new line.
 3365+ # This behaviour is somewhat controversial.
 3366+ elseif ( !$piece['lineStart'] && preg_match('/^(?:{\\||:|;|#|\*)/', $text)) /*}*/{
 3367+ $text = "\n" . $text;
 3368+ }
 3369+
33743370 # Prune lower levels off the recursion check path
33753371 $this->mTemplatePath = $lastPathLevel;
33763372
3377 - if ( $found && !$this->incrementIncludeSize( 'post-expand', strlen( $text ) ) ) {
 3373+ if ( !$this->incrementIncludeSize( 'post-expand', strlen( $text ) ) ) {
33783374 # Error, oversize inclusion
33793375 $text = "[[$originalTitle]]" .
33803376 $this->insertStripItem( '<!-- WARNING: template omitted, post-expand include size too large -->' );
3381 - $noparse = true;
3382 - $noargs = true;
33833377 }
33843378
3385 - if ( !$found ) {
3386 - wfProfileOut( $fname );
3387 - return '{{' . $frame->implode( '|', $titleWithSpaces, $args ) . '}}';
3388 - } else {
3389 - wfProfileIn( __METHOD__ . '-placeholders' );
3390 - if ( $isHTML ) {
3391 - # Replace raw HTML by a placeholder
3392 - # Add a blank line preceding, to prevent it from mucking up
3393 - # immediately preceding headings
3394 - $text = "\n\n" . $this->insertStripItem( $text );
3395 - }
3396 - wfProfileOut( __METHOD__ . '-placeholders' );
3397 - }
3398 -
3399 - # Prune lower levels off the recursion check path
3400 - $this->mTemplatePath = $lastPathLevel;
3401 -
3402 - if ( !$found ) {
3403 - wfProfileOut( $fname );
3404 - return '{{' . $frame->implode( '|', $titleWithSpaces, $args ) . '}}';
3405 - } else {
3406 - wfProfileOut( $fname );
3407 - return $text;
3408 - }
 3379+ wfProfileOut( $fname );
 3380+ return $text;
34093381 }
34103382
34113383 /**
@@ -3432,27 +3404,7 @@
34333405 return array( false, $title );
34343406 }
34353407
3436 - # If there are any <onlyinclude> tags, only include them
3437 - if ( !$this->ot['msg'] ) {
3438 - if ( in_string( '<onlyinclude>', $text ) && in_string( '</onlyinclude>', $text ) ) {
3439 - $replacer = new OnlyIncludeReplacer;
3440 - StringUtils::delimiterReplaceCallback( '<onlyinclude>', '</onlyinclude>',
3441 - array( &$replacer, 'replace' ), $text );
3442 - $text = $replacer->output;
3443 - }
3444 - # Remove <noinclude> sections and <includeonly> tags
3445 - $text = StringUtils::delimiterReplace( '<noinclude>', '</noinclude>', '', $text );
3446 - $text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) );
3447 - }
3448 -
3449 - # Remove comments
3450 - # This could theoretically be merged into preprocessToDom()
3451 - if ( $this->ot['html'] || ( $this->ot['pre'] && $this->mOptions->getRemoveComments() ) ) {
3452 - $text = Sanitizer::removeHTMLcomments( $text );
3453 - }
3454 -
3455 - $dom = $this->preprocessToDom( $text );
3456 -
 3408+ $dom = $this->preprocessTplToDom( $text );
34573409 $this->mTplDomCache[ $titleText ] = $dom;
34583410
34593411 if (! $title->equals($cacheTitle)) {

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r5479Fix two parser bugs: bug 41 and bug 529. For the former, I replaced...wmahan05:16, 25 September 2004

Status & tagging log