var $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
var $mInterwikiLinkHolders, $mLinkHolders;
var $mIncludeSizes, $mPPNodeCount, $mDefaultSort;
- var $mTplExpandCache,// empty-frame expansion cache
- $mTemplatePath; // stores an unsorted hash of all the templates already loaded
- // in this path. Used for loop detection.
+ var $mTplExpandCache; // empty-frame expansion cache
var $mTplRedirCache, $mTplDomCache, $mHeadings;
# Temporary
$this->mUniqPrefix = "\x7fUNIQ" . Parser::getRandomString();
# Clear these on every parse, bug 4549
- $this->mTemplatePath = array();
$this->mTplExpandCache = $this->mTplRedirCache = $this->mTplDomCache = array();
$this->mShowToc = true;
foreach ( $parts as $partIndex => $part ) {
if ( isset( $piece['eqpos'][$partIndex] ) ) {
$eqpos = $piece['eqpos'][$partIndex];
- list( $ws1, $argName, $ws2 ) = self::splitWhitespace( substr( $part, 0, $eqpos ) );
- list( $ws3, $argValue, $ws4 ) = self::splitWhitespace( substr( $part, $eqpos + 1 ) );
- $element .= "<part>$ws1<name>$argName</name>$ws2=$ws3<value>$argValue</value>$ws4</part>";
+ $argName = substr( $part, 0, $eqpos );
+ $argValue = substr( $part, $eqpos + 1 );
+ $element .= "<part><name>$argName</name>=<value>$argValue</value></part>";
} else {
- list( $ws1, $value, $ws2 ) = self::splitWhitespace( $part );
- $element .= "<part>$ws1<name index=\"$argIndex\" /><value>$value</value>$ws2</part>";
+ $element .= "<part><name index=\"$argIndex\" /><value>$part</value></part>";
$argIndex++;
}
}
$id = $this->mVariables->matchStartToEnd( $part1 );
if ( $id !== false ) {
$text = $this->getVariableValue( $id );
- $this->mOutput->mContainsOldMagic = true;
+ if (MagicWord::getCacheTTL($id)>-1)
+ $this->mOutput->mContainsOldMagic = true;
$found = true;
}
}
}
wfProfileOut( __METHOD__.'-modifiers' );
- # Save path level before recursing into functions & templates.
- $lastPathLevel = $this->mTemplatePath;
-
# Parser functions
if ( !$found ) {
wfProfileIn( __METHOD__ . '-pfunc' );
$wgContLang->findVariantLink($part1, $title);
}
# Do infinite loop check
- if ( isset( $this->mTemplatePath[$titleText] ) ) {
+ if ( isset( $frame->loopCheckHash[$titleText] ) ) {
$found = true;
- $text = "[[$part1]]" . $this->insertStripItem( '<!-- WARNING: template loop detected -->' );
+ $text = "<span class=\"error\">Template loop detected: [[$titleText]]</span>";
wfDebug( __METHOD__.": template loop broken at '$titleText'\n" );
}
+ # Do recursion depth check
+ $limit = $this->mOptions->getMaxTemplateDepth();
+ if ( $frame->depth >= $limit ) {
+ $found = true;
+ $text = "<span class=\"error\">Template recursion depth limit exceeded ($limit)</span>";
+ }
}
}
# Recover the source wikitext and return it
if ( !$found ) {
$text = '{{' . $frame->implode( '|', $titleWithSpaces, $args ) . '}}';
- # Prune lower levels off the recursion check path
- $this->mTemplatePath = $lastPathLevel;
wfProfileOut( $fname );
return $text;
}
if ( $isDOM ) {
# Clean up argument array
$newFrame = $frame->newChild( $args, $title );
- # Add a new element to the templace recursion path
- $this->mTemplatePath[$titleText] = 1;
+ # Add a new element to the templace loop detection hashtable
+ $newFrame->loopCheckHash[$titleText] = true;
if ( $titleText !== false && count( $newFrame->args ) == 0 ) {
# Expansion is eligible for the empty-frame cache
$this->mTplExpandCache[$titleText] = $text;
}
} else {
+ # Uncached expansion
$text = $newFrame->expand( $text );
}
}
$text = "\n" . $text;
}
- # Prune lower levels off the recursion check path
- $this->mTemplatePath = $lastPathLevel;
-
if ( !$this->incrementIncludeSize( 'post-expand', strlen( $text ) ) ) {
# Error, oversize inclusion
$text = "[[$originalTitle]]" .
$arg = trim( $argWithSpaces );
if ( isset( $frame->args[$arg] ) ) {
+ # Found template argument
$text = $frame->parent->expand( $frame->args[$arg] );
} else if ( ( $this->ot['html'] || $this->ot['pre'] ) && $parts->length > 0 ) {
+ # No match in frame, use the supplied default
$text = $frame->expand( $parts->item( 0 ) );
}
if ( !$this->incrementIncludeSize( 'arg', strlen( $text ) ) ) {
}
if ( $text === false ) {
+ # No match anywhere
$text = '{{{' . $frame->implode( '|', $argWithSpaces, $parts ) . '}}}';
}
if ( $error !== false ) {
* found The text returned is valid, stop processing the template. This
* is on by default.
* nowiki Wiki markup in the return value should be escaped
- * noparse Unsafe HTML tags should not be stripped, etc.
- * noargs Don't replace triple-brace arguments in the return value
* isHTML The returned text is HTML, armour it against wikitext transformation
*
* @public
var $parser, $title;
var $titleCache;
+ /**
+ * Hashtable listing templates which are disallowed for expansion in this frame,
+ * having been encountered previously in parent frames.
+ */
+ var $loopCheckHash;
+
+ /**
+ * Recursion depth of this frame, top = 0
+ */
+ var $depth;
+
const NO_ARGS = 1;
const NO_TEMPLATES = 2;
const STRIP_COMMENTS = 4;
$this->parser = $parser;
$this->title = $parser->mTitle;
$this->titleCache = array( $this->title ? $this->title->getPrefixedDBkey() : false );
+ $this->loopCheckHash = array();
+ $this->depth = 0;
}
/**
* Expansion frame with template arguments
*/
class PPTemplateFrame extends PPFrame {
- var $parser, $args, $parent;
- var $titleCache;
+ var $args, $parent;
function __construct( $parser, $parent = false, $args = array(), $title = false ) {
$this->parser = $parser;
$this->title = $title;
$this->titleCache = $parent->titleCache;
$this->titleCache[] = $title ? $title->getPrefixedDBkey() : false;
+ $this->loopCheckHash = /*clone*/ $parent->loopCheckHash;
+ $this->depth = $parent->depth + 1;
}
function __toString() {