diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2014-12-27 15:41:37 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2014-12-31 11:43:28 +0100 |
commit | c1f9b1f7b1b77776192048005dcc66dcf3df2bfb (patch) | |
tree | 2b38796e738dd74cb42ecd9bfd151803108386bc /includes/parser/Preprocessor_DOM.php | |
parent | b88ab0086858470dd1f644e64cb4e4f62bb2be9b (diff) |
Update to MediaWiki 1.24.1
Diffstat (limited to 'includes/parser/Preprocessor_DOM.php')
-rw-r--r-- | includes/parser/Preprocessor_DOM.php | 485 |
1 files changed, 328 insertions, 157 deletions
diff --git a/includes/parser/Preprocessor_DOM.php b/includes/parser/Preprocessor_DOM.php index 3138f483..2edb79a2 100644 --- a/includes/parser/Preprocessor_DOM.php +++ b/includes/parser/Preprocessor_DOM.php @@ -23,19 +23,21 @@ /** * @ingroup Parser + * @codingStandardsIgnoreStart */ class Preprocessor_DOM implements Preprocessor { + // @codingStandardsIgnoreEnd /** * @var Parser */ - var $parser; + public $parser; - var $memoryLimit; + public $memoryLimit; const CACHE_VERSION = 1; - function __construct( $parser ) { + public function __construct( $parser ) { $this->parser = $parser; $mem = ini_get( 'memory_limit' ); $this->memoryLimit = false; @@ -51,40 +53,57 @@ class Preprocessor_DOM implements Preprocessor { /** * @return PPFrame_DOM */ - function newFrame() { + public function newFrame() { return new PPFrame_DOM( $this ); } /** - * @param $args array + * @param array $args * @return PPCustomFrame_DOM */ - function newCustomFrame( $args ) { + public function newCustomFrame( $args ) { return new PPCustomFrame_DOM( $this, $args ); } /** - * @param $values + * @param array $values * @return PPNode_DOM */ - function newPartNodeArray( $values ) { + public function newPartNodeArray( $values ) { //NOTE: DOM manipulation is slower than building & parsing XML! (or so Tim sais) $xml = "<list>"; foreach ( $values as $k => $val ) { if ( is_int( $k ) ) { - $xml .= "<part><name index=\"$k\"/><value>" . htmlspecialchars( $val ) . "</value></part>"; + $xml .= "<part><name index=\"$k\"/><value>" + . htmlspecialchars( $val ) . "</value></part>"; } else { - $xml .= "<part><name>" . htmlspecialchars( $k ) . "</name>=<value>" . htmlspecialchars( $val ) . "</value></part>"; + $xml .= "<part><name>" . htmlspecialchars( $k ) + . "</name>=<value>" . htmlspecialchars( $val ) . "</value></part>"; } } $xml .= "</list>"; + wfProfileIn( __METHOD__ . '-loadXML' ); $dom = new DOMDocument(); - $dom->loadXML( $xml ); - $root = $dom->documentElement; + wfSuppressWarnings(); + $result = $dom->loadXML( $xml ); + wfRestoreWarnings(); + if ( !$result ) { + // Try running the XML through UtfNormal to get rid of invalid characters + $xml = UtfNormal::cleanUp( $xml ); + // 1 << 19 == XML_PARSE_HUGE, needed so newer versions of libxml2 + // don't barf when the XML is >256 levels deep + $result = $dom->loadXML( $xml, 1 << 19 ); + } + wfProfileOut( __METHOD__ . '-loadXML' ); + if ( !$result ) { + throw new MWException( 'Parameters passed to ' . __METHOD__ . ' result in invalid XML' ); + } + + $root = $dom->documentElement; $node = new PPNode_DOM( $root->childNodes ); return $node; } @@ -93,7 +112,7 @@ class Preprocessor_DOM implements Preprocessor { * @throws MWException * @return bool */ - function memCheck() { + public function memCheck() { if ( $this->memoryLimit === false ) { return true; } @@ -109,10 +128,11 @@ class Preprocessor_DOM implements Preprocessor { * Preprocess some wikitext and return the document tree. * This is the ghost of Parser::replace_variables(). * - * @param string $text the text to parse - * @param $flags Integer: bitwise combination of: - * Parser::PTD_FOR_INCLUSION Handle "<noinclude>" and "<includeonly>" as if the text is being - * included. Default is to assume a direct page view. + * @param string $text The text to parse + * @param int $flags Bitwise combination of: + * Parser::PTD_FOR_INCLUSION Handle "<noinclude>" and "<includeonly>" + * as if the text is being included. Default + * is to assume a direct page view. * * The generated DOM tree must depend only on the input text and the flags. * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899. @@ -128,7 +148,7 @@ class Preprocessor_DOM implements Preprocessor { * @throws MWException * @return PPNode_DOM */ - function preprocessToObj( $text, $flags = 0 ) { + public function preprocessToObj( $text, $flags = 0 ) { wfProfileIn( __METHOD__ ); global $wgMemc, $wgPreprocessorCacheThreshold; @@ -160,7 +180,6 @@ class Preprocessor_DOM implements Preprocessor { $xml = $this->preprocessToXml( $text, $flags ); } - // Fail if the number of elements exceeds acceptable limits // Do not attempt to generate the DOM $this->parser->mGeneratedPPNodeCount += substr_count( $xml, '<' ); @@ -181,7 +200,8 @@ class Preprocessor_DOM implements Preprocessor { if ( !$result ) { // Try running the XML through UtfNormal to get rid of invalid characters $xml = UtfNormal::cleanUp( $xml ); - // 1 << 19 == XML_PARSE_HUGE, needed so newer versions of libxml2 don't barf when the XML is >256 levels deep + // 1 << 19 == XML_PARSE_HUGE, needed so newer versions of libxml2 + // don't barf when the XML is >256 levels deep. $result = $dom->loadXML( $xml, 1 << 19 ); } if ( $result ) { @@ -202,11 +222,11 @@ class Preprocessor_DOM implements Preprocessor { } /** - * @param $text string - * @param $flags int + * @param string $text + * @param int $flags * @return string */ - function preprocessToXml( $text, $flags = 0 ) { + public function preprocessToXml( $text, $flags = 0 ) { wfProfileIn( __METHOD__ ); $rules = array( '{' => array( @@ -234,7 +254,9 @@ class Preprocessor_DOM implements Preprocessor { $ignoredTags = array( 'includeonly', '/includeonly' ); $ignoredElements = array( 'noinclude' ); $xmlishElements[] = 'noinclude'; - if ( strpos( $text, '<onlyinclude>' ) !== false && strpos( $text, '</onlyinclude>' ) !== false ) { + if ( strpos( $text, '<onlyinclude>' ) !== false + && strpos( $text, '</onlyinclude>' ) !== false + ) { $enableOnlyinclude = true; } } else { @@ -250,19 +272,28 @@ class Preprocessor_DOM implements Preprocessor { $stack = new PPDStack; $searchBase = "[{<\n"; #} - $revText = strrev( $text ); // For fast reverse searches + // For fast reverse searches + $revText = strrev( $text ); $lengthText = strlen( $text ); - $i = 0; # Input pointer, starts out pointing to a pseudo-newline before the start - $accum =& $stack->getAccum(); # Current accumulator + // Input pointer, starts out pointing to a pseudo-newline before the start + $i = 0; + // Current accumulator + $accum =& $stack->getAccum(); $accum = '<root>'; - $findEquals = false; # True to find equals signs in arguments - $findPipe = false; # True to take notice of pipe characters + // True to find equals signs in arguments + $findEquals = false; + // True to take notice of pipe characters + $findPipe = false; $headingIndex = 1; - $inHeading = false; # True if $i is inside a possible heading - $noMoreGT = false; # True if there are no more greater-than (>) signs right of $i - $findOnlyinclude = $enableOnlyinclude; # True to ignore all input up to the next <onlyinclude> - $fakeLineStart = true; # Do a line-start run without outputting an LF character + // True if $i is inside a possible heading + $inHeading = false; + // True if there are no more greater-than (>) signs right of $i + $noMoreGT = false; + // True to ignore all input up to the next <onlyinclude> + $findOnlyinclude = $enableOnlyinclude; + // Do a line-start run without outputting an LF character + $fakeLineStart = true; while ( true ) { //$this->memCheck(); @@ -347,7 +378,9 @@ class Preprocessor_DOM implements Preprocessor { if ( $found == 'angle' ) { $matches = false; // Handle </onlyinclude> - if ( $enableOnlyinclude && substr( $text, $i, strlen( '</onlyinclude>' ) ) == '</onlyinclude>' ) { + if ( $enableOnlyinclude + && substr( $text, $i, strlen( '</onlyinclude>' ) ) == '</onlyinclude>' + ) { $findOnlyinclude = true; continue; } @@ -400,14 +433,14 @@ class Preprocessor_DOM implements Preprocessor { // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but // it's a possible beneficial b/c break. if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n" - && substr( $text, $wsEnd + 1, 1 ) == "\n" ) - { + && substr( $text, $wsEnd + 1, 1 ) == "\n" + ) { // Remove leading whitespace from the end of the accumulator // Sanity check first though $wsLength = $i - $wsStart; if ( $wsLength > 0 - && strspn( $accum, " \t", -$wsLength ) === $wsLength ) - { + && strspn( $accum, " \t", -$wsLength ) === $wsLength + ) { $accum = substr( $accum, 0, -$wsLength ); } @@ -461,7 +494,9 @@ class Preprocessor_DOM implements Preprocessor { // Handle ignored tags if ( in_array( $lowerName, $ignoredTags ) ) { - $accum .= '<ignore>' . htmlspecialchars( substr( $text, $i, $tagEndPos - $i + 1 ) ) . '</ignore>'; + $accum .= '<ignore>' + . htmlspecialchars( substr( $text, $i, $tagEndPos - $i + 1 ) ) + . '</ignore>'; $i = $tagEndPos + 1; continue; } @@ -476,8 +511,8 @@ class Preprocessor_DOM implements Preprocessor { $attrEnd = $tagEndPos; // Find closing tag if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i", - $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) ) - { + $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) + ) { $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 ); $i = $matches[0][1] + strlen( $matches[0][0] ); $close = '<close>' . htmlspecialchars( $matches[0][0] ) . '</close>'; @@ -521,9 +556,11 @@ class Preprocessor_DOM implements Preprocessor { $count = strspn( $text, '=', $i, 6 ); if ( $count == 1 && $findEquals ) { - // DWIM: This looks kind of like a name/value separator - // Let's let the equals handler have it and break the potential heading - // This is heuristic, but AFAICT the methods for completely correct disambiguation are very complex. + // DWIM: This looks kind of like a name/value separator. + // Let's let the equals handler have it and break the + // potential heading. This is heuristic, but AFAICT the + // methods for completely correct disambiguation are very + // complex. } elseif ( $count > 0 ) { $piece = array( 'open' => "\n", @@ -542,8 +579,9 @@ class Preprocessor_DOM implements Preprocessor { // A heading must be open, otherwise \n wouldn't have been in the search list assert( '$piece->open == "\n"' ); $part = $piece->getCurrentPart(); - // Search back through the input to see if it has a proper close - // Do this using the reversed string since the other solutions (end anchor, etc.) are inefficient + // Search back through the input to see if it has a proper close. + // Do this using the reversed string since the other solutions + // (end anchor, etc.) are inefficient. $wsLength = strspn( $revText, " \t", $lengthText - $i ); $searchStart = $i - $wsLength; if ( isset( $part->commentEnd ) && $searchStart - 1 == $part->commentEnd ) { @@ -737,18 +775,18 @@ class Preprocessor_DOM implements Preprocessor { * @ingroup Parser */ class PPDStack { - var $stack, $rootAccum; + public $stack, $rootAccum; /** * @var PPDStack */ - var $top; - var $out; - var $elementClass = 'PPDStackElement'; + public $top; + public $out; + public $elementClass = 'PPDStackElement'; - static $false = false; + public static $false = false; - function __construct() { + public function __construct() { $this->stack = array(); $this->top = false; $this->rootAccum = ''; @@ -758,15 +796,15 @@ class PPDStack { /** * @return int */ - function count() { + public function count() { return count( $this->stack ); } - function &getAccum() { + public function &getAccum() { return $this->accum; } - function getCurrentPart() { + public function getCurrentPart() { if ( $this->top === false ) { return false; } else { @@ -774,7 +812,7 @@ class PPDStack { } } - function push( $data ) { + public function push( $data ) { if ( $data instanceof $this->elementClass ) { $this->stack[] = $data; } else { @@ -785,7 +823,7 @@ class PPDStack { $this->accum =& $this->top->getAccum(); } - function pop() { + public function pop() { if ( !count( $this->stack ) ) { throw new MWException( __METHOD__ . ': no elements remaining' ); } @@ -801,7 +839,7 @@ class PPDStack { return $temp; } - function addPart( $s = '' ) { + public function addPart( $s = '' ) { $this->top->addPart( $s ); $this->accum =& $this->top->getAccum(); } @@ -809,7 +847,7 @@ class PPDStack { /** * @return array */ - function getFlags() { + public function getFlags() { if ( !count( $this->stack ) ) { return array( 'findEquals' => false, @@ -826,15 +864,15 @@ class PPDStack { * @ingroup Parser */ class PPDStackElement { - var $open, // Opening character (\n for heading) + public $open, // Opening character (\n for heading) $close, // Matching closing character $count, // Number of opening characters found (number of "=" for heading) $parts, // Array of PPDPart objects describing pipe-separated parts. $lineStart; // True if the open char appeared at the start of the input line. Not set for headings. - var $partClass = 'PPDPart'; + public $partClass = 'PPDPart'; - function __construct( $data = array() ) { + public function __construct( $data = array() ) { $class = $this->partClass; $this->parts = array( new $class ); @@ -843,23 +881,23 @@ class PPDStackElement { } } - function &getAccum() { + public function &getAccum() { return $this->parts[count( $this->parts ) - 1]->out; } - function addPart( $s = '' ) { + public function addPart( $s = '' ) { $class = $this->partClass; $this->parts[] = new $class( $s ); } - function getCurrentPart() { + public function getCurrentPart() { return $this->parts[count( $this->parts ) - 1]; } /** * @return array */ - function getFlags() { + public function getFlags() { $partCount = count( $this->parts ); $findPipe = $this->open != "\n" && $this->open != '['; return array( @@ -872,9 +910,10 @@ class PPDStackElement { /** * Get the output string that would result if the close is not found. * + * @param bool|int $openingCount * @return string */ - function breakSyntax( $openingCount = false ) { + public function breakSyntax( $openingCount = false ) { if ( $this->open == "\n" ) { $s = $this->parts[0]->out; } else { @@ -900,14 +939,14 @@ class PPDStackElement { * @ingroup Parser */ class PPDPart { - var $out; // Output accumulator string + public $out; // Output accumulator string // Optional member variables: // eqpos Position of equals sign in output accumulator // commentEnd Past-the-end input pointer for the last comment encountered // visualEnd Past-the-end input pointer for the end of the accumulator minus comments - function __construct( $out = '' ) { + public function __construct( $out = '' ) { $this->out = $out; } } @@ -915,57 +954,71 @@ class PPDPart { /** * An expansion frame, used as a context to expand the result of preprocessToObj() * @ingroup Parser + * @codingStandardsIgnoreStart */ class PPFrame_DOM implements PPFrame { + // @codingStandardsIgnoreEnd /** * @var Preprocessor */ - var $preprocessor; + public $preprocessor; /** * @var Parser */ - var $parser; + public $parser; /** * @var Title */ - var $title; - var $titleCache; + public $title; + public $titleCache; /** * Hashtable listing templates which are disallowed for expansion in this frame, * having been encountered previously in parent frames. */ - var $loopCheckHash; + public $loopCheckHash; /** * Recursion depth of this frame, top = 0 * Note that this is NOT the same as expansion depth in expand() */ - var $depth; + public $depth; + + private $volatile = false; + private $ttl = null; + + /** + * @var array + */ + protected $childExpansionCache; /** * Construct a new preprocessor frame. - * @param $preprocessor Preprocessor The parent preprocessor + * @param Preprocessor $preprocessor The parent preprocessor */ - function __construct( $preprocessor ) { + public function __construct( $preprocessor ) { $this->preprocessor = $preprocessor; $this->parser = $preprocessor->parser; $this->title = $this->parser->mTitle; $this->titleCache = array( $this->title ? $this->title->getPrefixedDBkey() : false ); $this->loopCheckHash = array(); $this->depth = 0; + $this->childExpansionCache = array(); } /** * Create a new child frame * $args is optionally a multi-root PPNode or array containing the template arguments * + * @param bool|array $args + * @param Title|bool $title + * @param int $indexOffset * @return PPTemplateFrame_DOM */ - function newChild( $args = false, $title = false, $indexOffset = 0 ) { + public function newChild( $args = false, $title = false, $indexOffset = 0 ) { $namedArgs = array(); $numberedArgs = array(); if ( $title === false ) { @@ -980,7 +1033,7 @@ class PPFrame_DOM implements PPFrame { if ( $arg instanceof PPNode ) { $arg = $arg->node; } - if ( !$xpath ) { + if ( !$xpath || $xpath->document !== $arg->ownerDocument ) { $xpath = new DOMXPath( $arg->ownerDocument ); } @@ -1005,11 +1058,23 @@ class PPFrame_DOM implements PPFrame { /** * @throws MWException - * @param $root - * @param $flags int + * @param string|int $key + * @param string|PPNode_DOM|DOMDocument $root + * @param int $flags + * @return string + */ + public function cachedExpand( $key, $root, $flags = 0 ) { + // we don't have a parent, so we don't have a cache + return $this->expand( $root, $flags ); + } + + /** + * @throws MWException + * @param string|PPNode_DOM|DOMDocument $root + * @param int $flags * @return string */ - function expand( $root, $flags = 0 ) { + public function expand( $root, $flags = 0 ) { static $expansionDepth = 0; if ( is_string( $root ) ) { return $root; @@ -1142,17 +1207,16 @@ class PPFrame_DOM implements PPFrame { # Remove it in HTML, pre+remove and STRIP_COMMENTS modes if ( $this->parser->ot['html'] || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() ) - || ( $flags & PPFrame::STRIP_COMMENTS ) ) - { + || ( $flags & PPFrame::STRIP_COMMENTS ) + ) { $out .= ''; - } - # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result - # Not in RECOVER_COMMENTS mode (extractSections) though - elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) { + } elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) { + # Add a strip marker in PST mode so that pstPass2() can + # run some old-fashioned regexes on the result. + # Not in RECOVER_COMMENTS mode (extractSections) though. $out .= $this->parser->insertStripItem( $contextNode->textContent ); - } - # Recover the literal comment in RECOVER_COMMENTS and pre+no-remove - else { + } else { + # Recover the literal comment in RECOVER_COMMENTS and pre+no-remove $out .= $contextNode->textContent; } } elseif ( $contextNode->nodeName == 'ignore' ) { @@ -1160,7 +1224,9 @@ class PPFrame_DOM implements PPFrame { # OT_WIKI will only respect <ignore> in substed templates. # The other output types respect it unless NO_IGNORE is set. # extractSections() sets NO_IGNORE and so never respects it. - if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] ) || ( $flags & PPFrame::NO_IGNORE ) ) { + if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] ) + || ( $flags & PPFrame::NO_IGNORE ) + ) { $out .= $contextNode->textContent; } else { $out .= ''; @@ -1172,13 +1238,29 @@ class PPFrame_DOM implements PPFrame { $attrs = $xpath->query( 'attr', $contextNode ); $inners = $xpath->query( 'inner', $contextNode ); $closes = $xpath->query( 'close', $contextNode ); - $params = array( - 'name' => new PPNode_DOM( $names->item( 0 ) ), - 'attr' => $attrs->length > 0 ? new PPNode_DOM( $attrs->item( 0 ) ) : null, - 'inner' => $inners->length > 0 ? new PPNode_DOM( $inners->item( 0 ) ) : null, - 'close' => $closes->length > 0 ? new PPNode_DOM( $closes->item( 0 ) ) : null, - ); - $out .= $this->parser->extensionSubstitution( $params, $this ); + if ( $flags & PPFrame::NO_TAGS ) { + $s = '<' . $this->expand( $names->item( 0 ), $flags ); + if ( $attrs->length > 0 ) { + $s .= $this->expand( $attrs->item( 0 ), $flags ); + } + if ( $inners->length > 0 ) { + $s .= '>' . $this->expand( $inners->item( 0 ), $flags ); + if ( $closes->length > 0 ) { + $s .= $this->expand( $closes->item( 0 ), $flags ); + } + } else { + $s .= '/>'; + } + $out .= $s; + } else { + $params = array( + 'name' => new PPNode_DOM( $names->item( 0 ) ), + 'attr' => $attrs->length > 0 ? new PPNode_DOM( $attrs->item( 0 ) ) : null, + 'inner' => $inners->length > 0 ? new PPNode_DOM( $inners->item( 0 ) ) : null, + 'close' => $closes->length > 0 ? new PPNode_DOM( $closes->item( 0 ) ) : null, + ); + $out .= $this->parser->extensionSubstitution( $params, $this ); + } } elseif ( $contextNode->nodeName == 'h' ) { # Heading $s = $this->expand( $contextNode->childNodes, $flags ); @@ -1231,11 +1313,12 @@ class PPFrame_DOM implements PPFrame { } /** - * @param $sep - * @param $flags + * @param string $sep + * @param int $flags + * @param string|PPNode_DOM|DOMDocument $args,... * @return string */ - function implodeWithFlags( $sep, $flags /*, ... */ ) { + public function implodeWithFlags( $sep, $flags /*, ... */ ) { $args = array_slice( func_get_args(), 2 ); $first = true; @@ -1263,9 +1346,11 @@ class PPFrame_DOM implements PPFrame { * Implode with no flags specified * This previously called implodeWithFlags but has now been inlined to reduce stack depth * + * @param string $sep + * @param string|PPNode_DOM|DOMDocument $args,... * @return string */ - function implode( $sep /*, ... */ ) { + public function implode( $sep /*, ... */ ) { $args = array_slice( func_get_args(), 1 ); $first = true; @@ -1293,9 +1378,11 @@ class PPFrame_DOM implements PPFrame { * Makes an object that, when expand()ed, will be the same as one obtained * with implode() * + * @param string $sep + * @param string|PPNode_DOM|DOMDocument $args,... * @return array */ - function virtualImplode( $sep /*, ... */ ) { + public function virtualImplode( $sep /*, ... */ ) { $args = array_slice( func_get_args(), 1 ); $out = array(); $first = true; @@ -1321,9 +1408,13 @@ class PPFrame_DOM implements PPFrame { /** * Virtual implode with brackets + * @param string $start + * @param string $sep + * @param string $end + * @param string|PPNode_DOM|DOMDocument $args,... * @return array */ - function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) { + public function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) { $args = array_slice( func_get_args(), 3 ); $out = array( $start ); $first = true; @@ -1348,11 +1439,11 @@ class PPFrame_DOM implements PPFrame { return $out; } - function __toString() { + public function __toString() { return 'frame{}'; } - function getPDBK( $level = false ) { + public function getPDBK( $level = false ) { if ( $level === false ) { return $this->title->getPrefixedDBkey(); } else { @@ -1363,21 +1454,21 @@ class PPFrame_DOM implements PPFrame { /** * @return array */ - function getArguments() { + public function getArguments() { return array(); } /** * @return array */ - function getNumberedArguments() { + public function getNumberedArguments() { return array(); } /** * @return array */ - function getNamedArguments() { + public function getNamedArguments() { return array(); } @@ -1386,20 +1477,21 @@ class PPFrame_DOM implements PPFrame { * * @return bool */ - function isEmpty() { + public function isEmpty() { return true; } - function getArgument( $name ) { + public function getArgument( $name ) { return false; } /** * Returns true if the infinite loop check is OK, false if a loop is detected * + * @param Title $title * @return bool */ - function loopCheck( $title ) { + public function loopCheck( $title ) { return !isset( $this->loopCheckHash[$title->getPrefixedDBkey()] ); } @@ -1408,7 +1500,7 @@ class PPFrame_DOM implements PPFrame { * * @return bool */ - function isTemplate() { + public function isTemplate() { return false; } @@ -1417,32 +1509,75 @@ class PPFrame_DOM implements PPFrame { * * @return Title */ - function getTitle() { + public function getTitle() { return $this->title; } + + /** + * Set the volatile flag + * + * @param bool $flag + */ + public function setVolatile( $flag = true ) { + $this->volatile = $flag; + } + + /** + * Get the volatile flag + * + * @return bool + */ + public function isVolatile() { + return $this->volatile; + } + + /** + * Set the TTL + * + * @param int $ttl + */ + public function setTTL( $ttl ) { + if ( $ttl !== null && ( $this->ttl === null || $ttl < $this->ttl ) ) { + $this->ttl = $ttl; + } + } + + /** + * Get the TTL + * + * @return int|null + */ + public function getTTL() { + return $this->ttl; + } } /** * Expansion frame with template arguments * @ingroup Parser + * @codingStandardsIgnoreStart */ class PPTemplateFrame_DOM extends PPFrame_DOM { - var $numberedArgs, $namedArgs; + // @codingStandardsIgnoreEnd + + public $numberedArgs, $namedArgs; /** * @var PPFrame_DOM */ - var $parent; - var $numberedExpansionCache, $namedExpansionCache; + public $parent; + public $numberedExpansionCache, $namedExpansionCache; /** - * @param $preprocessor - * @param $parent PPFrame_DOM - * @param $numberedArgs array - * @param $namedArgs array - * @param $title Title + * @param Preprocessor $preprocessor + * @param bool|PPFrame_DOM $parent + * @param array $numberedArgs + * @param array $namedArgs + * @param bool|Title $title */ - function __construct( $preprocessor, $parent = false, $numberedArgs = array(), $namedArgs = array(), $title = false ) { + public function __construct( $preprocessor, $parent = false, $numberedArgs = array(), + $namedArgs = array(), $title = false + ) { parent::__construct( $preprocessor ); $this->parent = $parent; @@ -1460,7 +1595,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { $this->numberedExpansionCache = $this->namedExpansionCache = array(); } - function __toString() { + public function __toString() { $s = 'tplframe{'; $first = true; $args = $this->numberedArgs + $this->namedArgs; @@ -1478,15 +1613,33 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { } /** + * @throws MWException + * @param string|int $key + * @param string|PPNode_DOM|DOMDocument $root + * @param int $flags + * @return string + */ + public function cachedExpand( $key, $root, $flags = 0 ) { + if ( isset( $this->parent->childExpansionCache[$key] ) ) { + return $this->parent->childExpansionCache[$key]; + } + $retval = $this->expand( $root, $flags ); + if ( !$this->isVolatile() ) { + $this->parent->childExpansionCache[$key] = $retval; + } + return $retval; + } + + /** * Returns true if there are no arguments in this frame * * @return bool */ - function isEmpty() { + public function isEmpty() { return !count( $this->numberedArgs ) && !count( $this->namedArgs ); } - function getArguments() { + public function getArguments() { $arguments = array(); foreach ( array_merge( array_keys( $this->numberedArgs ), @@ -1496,7 +1649,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { return $arguments; } - function getNumberedArguments() { + public function getNumberedArguments() { $arguments = array(); foreach ( array_keys( $this->numberedArgs ) as $key ) { $arguments[$key] = $this->getArgument( $key ); @@ -1504,7 +1657,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { return $arguments; } - function getNamedArguments() { + public function getNamedArguments() { $arguments = array(); foreach ( array_keys( $this->namedArgs ) as $key ) { $arguments[$key] = $this->getArgument( $key ); @@ -1512,18 +1665,21 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { return $arguments; } - function getNumberedArgument( $index ) { + public function getNumberedArgument( $index ) { if ( !isset( $this->numberedArgs[$index] ) ) { return false; } if ( !isset( $this->numberedExpansionCache[$index] ) ) { # No trimming for unnamed arguments - $this->numberedExpansionCache[$index] = $this->parent->expand( $this->numberedArgs[$index], PPFrame::STRIP_COMMENTS ); + $this->numberedExpansionCache[$index] = $this->parent->expand( + $this->numberedArgs[$index], + PPFrame::STRIP_COMMENTS + ); } return $this->numberedExpansionCache[$index]; } - function getNamedArgument( $name ) { + public function getNamedArgument( $name ) { if ( !isset( $this->namedArgs[$name] ) ) { return false; } @@ -1535,7 +1691,7 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { return $this->namedExpansionCache[$name]; } - function getArgument( $name ) { + public function getArgument( $name ) { $text = $this->getNumberedArgument( $name ); if ( $text === false ) { $text = $this->getNamedArgument( $name ); @@ -1548,24 +1704,37 @@ class PPTemplateFrame_DOM extends PPFrame_DOM { * * @return bool */ - function isTemplate() { + public function isTemplate() { return true; } + + public function setVolatile( $flag = true ) { + parent::setVolatile( $flag ); + $this->parent->setVolatile( $flag ); + } + + public function setTTL( $ttl ) { + parent::setTTL( $ttl ); + $this->parent->setTTL( $ttl ); + } } /** * Expansion frame with custom arguments * @ingroup Parser + * @codingStandardsIgnoreStart */ class PPCustomFrame_DOM extends PPFrame_DOM { - var $args; + // @codingStandardsIgnoreEnd + + public $args; - function __construct( $preprocessor, $args ) { + public function __construct( $preprocessor, $args ) { parent::__construct( $preprocessor ); $this->args = $args; } - function __toString() { + public function __toString() { $s = 'cstmframe{'; $first = true; foreach ( $this->args as $name => $value ) { @@ -1584,48 +1753,50 @@ class PPCustomFrame_DOM extends PPFrame_DOM { /** * @return bool */ - function isEmpty() { + public function isEmpty() { return !count( $this->args ); } - function getArgument( $index ) { + public function getArgument( $index ) { if ( !isset( $this->args[$index] ) ) { return false; } return $this->args[$index]; } - function getArguments() { + public function getArguments() { return $this->args; } } /** * @ingroup Parser + * @codingStandardsIgnoreStart */ class PPNode_DOM implements PPNode { + // @codingStandardsIgnoreEnd /** * @var DOMElement */ - var $node; - var $xpath; + public $node; + public $xpath; - function __construct( $node, $xpath = false ) { + public function __construct( $node, $xpath = false ) { $this->node = $node; } /** * @return DOMXPath */ - function getXPath() { + public function getXPath() { if ( $this->xpath === null ) { $this->xpath = new DOMXPath( $this->node->ownerDocument ); } return $this->xpath; } - function __toString() { + public function __toString() { if ( $this->node instanceof DOMNodeList ) { $s = ''; foreach ( $this->node as $node ) { @@ -1640,37 +1811,37 @@ class PPNode_DOM implements PPNode { /** * @return bool|PPNode_DOM */ - function getChildren() { + public function getChildren() { return $this->node->childNodes ? new self( $this->node->childNodes ) : false; } /** * @return bool|PPNode_DOM */ - function getFirstChild() { + public function getFirstChild() { return $this->node->firstChild ? new self( $this->node->firstChild ) : false; } /** * @return bool|PPNode_DOM */ - function getNextSibling() { + public function getNextSibling() { return $this->node->nextSibling ? new self( $this->node->nextSibling ) : false; } /** - * @param $type + * @param string $type * * @return bool|PPNode_DOM */ - function getChildrenOfType( $type ) { + public function getChildrenOfType( $type ) { return new self( $this->getXPath()->query( $type, $this->node ) ); } /** * @return int */ - function getLength() { + public function getLength() { if ( $this->node instanceof DOMNodeList ) { return $this->node->length; } else { @@ -1679,10 +1850,10 @@ class PPNode_DOM implements PPNode { } /** - * @param $i + * @param int $i * @return bool|PPNode_DOM */ - function item( $i ) { + public function item( $i ) { $item = $this->node->item( $i ); return $item ? new self( $item ) : false; } @@ -1690,7 +1861,7 @@ class PPNode_DOM implements PPNode { /** * @return string */ - function getName() { + public function getName() { if ( $this->node instanceof DOMNodeList ) { return '#nodelist'; } else { @@ -1707,7 +1878,7 @@ class PPNode_DOM implements PPNode { * @throws MWException * @return array */ - function splitArg() { + public function splitArg() { $xpath = $this->getXPath(); $names = $xpath->query( 'name', $this->node ); $values = $xpath->query( 'value', $this->node ); @@ -1729,7 +1900,7 @@ class PPNode_DOM implements PPNode { * @throws MWException * @return array */ - function splitExt() { + public function splitExt() { $xpath = $this->getXPath(); $names = $xpath->query( 'name', $this->node ); $attrs = $xpath->query( 'attr', $this->node ); @@ -1755,7 +1926,7 @@ class PPNode_DOM implements PPNode { * @throws MWException * @return array */ - function splitHeading() { + public function splitHeading() { if ( $this->getName() !== 'h' ) { throw new MWException( 'Invalid h node passed to ' . __METHOD__ ); } |