diff options
Diffstat (limited to 'includes/Parser.php')
-rw-r--r-- | includes/Parser.php | 522 |
1 files changed, 161 insertions, 361 deletions
diff --git a/includes/Parser.php b/includes/Parser.php index 8d67279d..8e36e170 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -2,8 +2,7 @@ /** * File for Parser and related classes * - * @package MediaWiki - * @subpackage Parser + * @addtogroup Parser */ /** @@ -57,9 +56,10 @@ define( 'MW_COLON_STATE_COMMENTDASH', 6 ); define( 'MW_COLON_STATE_COMMENTDASHDASH', 7 ); /** - * PHP Parser - * - * Processes wiki markup + * PHP Parser - Processes wiki markup (which uses a more user-friendly + * syntax, such as "[[link]]" for making links), and provides a one-way + * transformation of that wiki markup it into XHTML output / markup + * (which in turn the browser understands, and can display). * * <pre> * There are four main entry points into the Parser class: @@ -86,10 +86,11 @@ define( 'MW_COLON_STATE_COMMENTDASHDASH', 7 ); * * only within ParserOptions * </pre> * - * @package MediaWiki + * @addtogroup Parser */ class Parser { + const VERSION = MW_PARSER_VERSION; /**#@+ * @private */ @@ -114,7 +115,7 @@ class Parser $ot, // Shortcut alias, see setOutputType() $mRevisionId, // ID to display in {{REVISIONID}} tags $mRevisionTimestamp, // The timestamp of the specified revision ID - $mRevIdForTs; // The revision ID which was used to fetch the timestamp + $mRevIdForTs; // The revision ID which was used to fetch the timestamp /**#@-*/ @@ -162,6 +163,7 @@ class Parser $this->setFunctionHook( 'numberofarticles', array( 'CoreParserFunctions', 'numberofarticles' ), SFH_NO_HASH ); $this->setFunctionHook( 'numberoffiles', array( 'CoreParserFunctions', 'numberoffiles' ), SFH_NO_HASH ); $this->setFunctionHook( 'numberofadmins', array( 'CoreParserFunctions', 'numberofadmins' ), SFH_NO_HASH ); + $this->setFunctionHook( 'numberofedits', array( 'CoreParserFunctions', 'numberofedits' ), SFH_NO_HASH ); $this->setFunctionHook( 'language', array( 'CoreParserFunctions', 'language' ), SFH_NO_HASH ); $this->setFunctionHook( 'padleft', array( 'CoreParserFunctions', 'padleft' ), SFH_NO_HASH ); $this->setFunctionHook( 'padright', array( 'CoreParserFunctions', 'padright' ), SFH_NO_HASH ); @@ -211,7 +213,7 @@ class Parser 'titles' => array() ); $this->mRevisionTimestamp = $this->mRevisionId = null; - + /** * Prefix for temporary replacement strings for the multipass parser. * \x07 should never appear in input as it's disallowed in XML. @@ -262,7 +264,6 @@ class Parser * Convert wikitext to HTML * Do not call this function recursively. * - * @private * @param string $text Text we want to parse * @param Title &$title A title object * @param array $options @@ -271,7 +272,7 @@ class Parser * @param int $revid number to pass in {{REVISIONID}} * @return ParserOutput a ParserOutput */ - function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null ) { + public function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null ) { /** * First pass--just handle <nowiki> sections, pass the rest off * to internalParse() which does all the real work. @@ -724,7 +725,7 @@ class Parser $descriptorspec = array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), - 2 => array('file', '/dev/null', 'a') + 2 => array('file', '/dev/null', 'a') // FIXME: this line in UNIX-specific, it generates a warning on Windows, because /dev/null is not a valid Windows file. ); $pipes = array(); $process = proc_open("$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes); @@ -872,7 +873,7 @@ class Parser array_push ( $td_history , false ); array_push ( $last_tag_history , '' ); } - else if ( $first_character == '|' || $first_character == '!' || substr ( $line , 0 , 2 ) == '|+' ) { + else if ( $first_character == '|' || $first_character == '!' || substr ( $line , 0 , 2 ) == '|+' ) { // This might be cell elements, td, th or captions if ( substr ( $line , 0 , 2 ) == '|+' ) { $first_character = '+'; @@ -1002,6 +1003,7 @@ class Parser $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) ); $text = $this->replaceVariables( $text, $args ); + wfRunHooks( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) ); // Tables need to come after variable replacement for things to work // properly; putting them before other transformations should keep @@ -1086,7 +1088,7 @@ class Parser } $url = wfMsg( $urlmsg, $id); - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); $la = $sk->getExternalLinkAttributes( $url, $keyword.$id ); $text = "<a href=\"{$url}\"{$la}>{$keyword} {$id}</a>"; } @@ -1287,7 +1289,8 @@ class Parser $output .= '</i>'; if ($state == 'bi') $output .= '</b>'; - if ($state == 'both') + # There might be lonely ''''', so make sure we have a buffer + if ($state == 'both' && $buffer) $output .= '<b><i>'.$buffer.'</i></b>'; return $output; } @@ -1306,7 +1309,7 @@ class Parser $fname = 'Parser::replaceExternalLinks'; wfProfileIn( $fname ); - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); $bits = preg_split( EXT_LINK_BRACKETED, $text, -1, PREG_SPLIT_DELIM_CAPTURE ); @@ -1395,7 +1398,7 @@ class Parser $s = array_shift( $bits ); $i = 0; - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); while ( $i < count( $bits ) ){ $protocol = $bits[$i++]; @@ -1468,7 +1471,7 @@ class Parser * @param string * @return string * @static - * @fixme This can merge genuinely required bits in the path or query string, + * @todo This can merge genuinely required bits in the path or query string, * breaking legit URLs. A proper fix would treat the various parts of * the URL differently; as a workaround, just use the output for * statistical records, not for actual linking/output. @@ -1503,7 +1506,7 @@ class Parser * @private */ function maybeMakeExternalImage( $url ) { - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); $imagesfrom = $this->mOptions->getAllowExternalImagesFrom(); $imagesexception = !empty($imagesfrom); $text = false; @@ -1533,7 +1536,7 @@ class Parser # the % is needed to support urlencoded titles as well if ( !$tc ) { $tc = Title::legalChars() . '#%'; } - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); #split the entire text string on occurences of [[ $a = explode( '[[', ' ' . $s ); @@ -1552,7 +1555,6 @@ class Parser $e2 = wfMsgForContent( 'linkprefix' ); $useLinkPrefixExtension = $wgContLang->linkPrefixExtension(); - if( is_null( $this->mTitle ) ) { throw new MWException( __METHOD__.": \$this->mTitle is null\n" ); } @@ -1569,10 +1571,11 @@ class Parser $prefix = ''; } - if($wgContLang->hasVariants()) + if($wgContLang->hasVariants()) { $selflink = $wgContLang->convertLinkToAllVariants($this->mTitle->getPrefixedText()); - else + } else { $selflink = array($this->mTitle->getPrefixedText()); + } $useSubpages = $this->areSubpagesAllowed(); wfProfileOut( $fname.'-setup' ); @@ -1626,7 +1629,7 @@ class Parser $might_be_img = true; $text = $m[2]; if ( strpos( $m[1], '%' ) !== false ) { - $m[1] = urldecode($m[1]); + $m[1] = urldecode($m[1]); } $trail = ""; } else { # Invalid form; output directly @@ -1640,7 +1643,7 @@ class Parser # Don't allow internal links to pages containing # PROTO: where PROTO is a valid URL protocol; these # should be external links. - if (preg_match('/^(\b(?:' . wfUrlProtocols() . '))/', $m[1])) { + if (preg_match('/^\b(?:' . wfUrlProtocols() . ')/', $m[1])) { $s .= $prefix . '[[' . $line ; continue; } @@ -1723,8 +1726,8 @@ class Parser wfProfileIn( "$fname-interwiki" ); if( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) { $this->mOutput->addLanguageLink( $nt->getFullText() ); - $s = rtrim($s . "\n"); - $s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail; + $s = rtrim($s . $prefix); + $s .= trim($trail, "\n") == '' ? '': $prefix . $trail; wfProfileOut( "$fname-interwiki" ); continue; } @@ -1778,11 +1781,12 @@ class Parser } } - if( ( in_array( $nt->getPrefixedText(), $selflink ) ) && - ( $nt->getFragment() === '' ) ) { - # Self-links are handled specially; generally de-link and change to bold. - $s .= $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail ); - continue; + # Self-link checking + if( $nt->getFragment() === '' ) { + if( in_array( $nt->getPrefixedText(), $selflink, true ) ) { + $s .= $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail ); + continue; + } } # Special and Media are pseudo-namespaces; no pages actually exist in them @@ -1862,7 +1866,7 @@ class Parser */ function makeKnownLinkHolder( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) { list( $inside, $trail ) = Linker::splitTrail( $trail ); - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); $link = $sk->makeKnownLinkObj( $nt, $text, $query, $inside, $prefix ); return $this->armorLinks( $link ) . $trail; } @@ -1923,9 +1927,9 @@ class Parser # Look at the first character if( $target != '' && $target{0} == '/' ) { # / at end means we don't want the slash to be shown - if( substr( $target, -1, 1 ) == '/' ) { - $target = substr( $target, 1, -1 ); - $noslash = $target; + $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m ); + if( $trailingSlashes ) { + $noslash = $target = substr( $target, 1, -strlen($m[0][0]) ); } else { $noslash = substr( $target, 1 ); } @@ -2134,9 +2138,9 @@ class Parser wfProfileIn( "$fname-paragraph" ); # No prefix (not in list)--go to paragraph mode // XXX: use a stack for nestable elements like span, table and div - $openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t ); + $openmatch = preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t ); $closematch = preg_match( - '/(<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'. + '/(?:<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'. '<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t ); if ( $openmatch or $closematch ) { $paragraphStack = false; @@ -2538,6 +2542,8 @@ class Parser return $varCache[$index] = $wgContLang->formatNum( SiteStats::pages() ); case 'numberofadmins': return $varCache[$index] = $wgContLang->formatNum( SiteStats::admins() ); + case 'numberofedits': + return $varCache[$index] = $wgContLang->formatNum( SiteStats::edits() ); case 'currenttimestamp': return $varCache[$index] = wfTimestampNow(); case 'localtimestamp': @@ -2852,7 +2858,7 @@ class Parser return $text; } - + /// Clean up argument array - refactored in 1.9 so parserfunctions can use it, too. static function createAssocArgs( $args ) { $assocArgs = array(); @@ -2872,10 +2878,10 @@ class Parser } } } - + return $assocArgs; } - + /** * Return the text of a template, after recursively * replacing any variables or templates within the template. @@ -2888,7 +2894,7 @@ class Parser * @private */ function braceSubstitution( $piece ) { - global $wgContLang, $wgLang, $wgAllowDisplayTitle; + global $wgContLang, $wgLang, $wgAllowDisplayTitle, $wgNonincludableNamespaces; $fname = __METHOD__ /*. '-L' . count( $this->mArgStack )*/; wfProfileIn( $fname ); wfProfileIn( __METHOD__.'-setup' ); @@ -3031,6 +3037,19 @@ class Parser } else { # set $text to cached message. $text = $linestart . $this->mTemplates[$piece['title']]; + #treat title for cached page the same as others + $ns = NS_TEMPLATE; + $subpage = ''; + $part1 = $this->maybeDoSubpageLink( $part1, $subpage ); + if ($subpage !== '') { + $ns = $this->mTitle->getNamespace(); + } + $title = Title::newFromText( $part1, $ns ); + //used by include size checking + $titleText = $title->getPrefixedText(); + //used by edit section links + $replaceHeadings = true; + } } @@ -3066,6 +3085,9 @@ class Parser $isHTML = true; $this->disableCache(); } + } else if ( $wgNonincludableNamespaces && in_array( $title->getNamespace(), $wgNonincludableNamespaces ) ) { + $found = false; //access denied + wfDebug( "$fname: template inclusion denied for " . $title->getPrefixedDBkey() ); } else { $articleContent = $this->fetchTemplate( $title ); if ( $articleContent !== false ) { @@ -3155,7 +3177,7 @@ class Parser # If the template begins with a table or block-level # element, it should be treated as beginning a new line. - if (!$piece['lineStart'] && preg_match('/^({\\||:|;|#|\*)/', $text)) /*}*/{ + if (!$piece['lineStart'] && preg_match('/^(?:{\\||:|;|#|\*)/', $text)) /*}*/{ $text = "\n" . $text; } } elseif ( !$noargs ) { @@ -3271,7 +3293,7 @@ class Parser return wfMsg('scarytranscludedisabled'); $url = $title->getFullUrl( "action=$action" ); - + if (strlen($url) > 255) return wfMsg('scarytranscludetoolong'); return $this->fetchScaryTemplateMaybeFromCache($url); @@ -3279,7 +3301,7 @@ class Parser function fetchScaryTemplateMaybeFromCache($url) { global $wgTranscludeCacheExpiry; - $dbr =& wfGetDB(DB_SLAVE); + $dbr = wfGetDB(DB_SLAVE); $obj = $dbr->selectRow('transcache', array('tc_time', 'tc_contents'), array('tc_url' => $url)); if ($obj) { @@ -3294,7 +3316,7 @@ class Parser if (!$text) return wfMsg('scarytranscludefailed', $url); - $dbw =& wfGetDB(DB_MASTER); + $dbw = wfGetDB(DB_MASTER); $dbw->replace('transcache', array('tc_url'), array( 'tc_url' => $url, 'tc_time' => time(), @@ -3395,7 +3417,7 @@ class Parser global $wgMaxTocLevel, $wgContLang; $doNumberHeadings = $this->mOptions->getNumberHeadings(); - if( !$this->mTitle->userCanEdit() ) { + if( !$this->mTitle->quickUserCan( 'edit' ) ) { $showEditLink = 0; } else { $showEditLink = $this->mOptions->getEditSection(); @@ -3437,7 +3459,7 @@ class Parser } # We need this to perform operations on the HTML - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); # headline counter $headlineCount = 0; @@ -3723,11 +3745,7 @@ class Parser } # Trim trailing whitespace - # __END__ tag allows for trailing - # whitespace to be deliberately included $text = rtrim( $text ); - $mw =& MagicWord::get( 'end' ); - $mw->matchAndRemove( $text ); return $text; } @@ -3847,7 +3865,7 @@ class Parser wfProfileIn($fname); - if ( $wgTitle ) { + if ( $wgTitle && !( $wgTitle instanceof FakeTitle ) ) { $this->mTitle = $wgTitle; } else { $this->mTitle = Title::newFromText('msg'); @@ -3966,12 +3984,12 @@ class Parser $pdbks = array(); $colours = array(); - $sk =& $this->mOptions->getSkin(); + $sk = $this->mOptions->getSkin(); $linkCache =& LinkCache::singleton(); if ( !empty( $this->mLinkHolders['namespaces'] ) ) { wfProfileIn( $fname.'-check' ); - $dbr =& wfGetDB( DB_SLAVE ); + $dbr = wfGetDB( DB_SLAVE ); $page = $dbr->tableName( 'page' ); $threshold = $wgUser->getOption('stubthreshold'); @@ -4161,8 +4179,8 @@ class Parser if(isset($categoryMap[$vardbk])){ $oldkey = $categoryMap[$vardbk]; if($oldkey != $vardbk) - $varCategories[$oldkey]=$vardbk; - } + $varCategories[$oldkey]=$vardbk; + } } // rebuild the categories in original order (if there are replacements) @@ -4303,6 +4321,7 @@ class Parser */ function renderImageGallery( $text, $params ) { $ig = new ImageGallery(); + $ig->setContextTitle( $this->mTitle ); $ig->setShowBytes( false ); $ig->setShowFilename( false ); $ig->setParsing(); @@ -4314,6 +4333,15 @@ class Parser $caption = $this->replaceInternalLinks( $caption ); $ig->setCaptionHtml( $caption ); } + if( isset( $params['perrow'] ) ) { + $ig->setPerRow( $params['perrow'] ); + } + if( isset( $params['widths'] ) ) { + $ig->setWidths( $params['widths'] ); + } + if( isset( $params['heights'] ) ) { + $ig->setHeights( $params['heights'] ); + } $lines = explode( "\n", $text ); foreach ( $lines as $line ) { @@ -4359,10 +4387,8 @@ class Parser * Parse image options text and use it to make an image */ function makeImage( $nt, $options ) { - global $wgUseImageResize, $wgDjvuRenderer; - - $align = ''; - + # @TODO: let the MediaHandler specify its transform parameters + # # Check if the options text is of the form "options|alt text" # Options are: # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang @@ -4372,61 +4398,74 @@ class Parser # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox # * center center the image # * framed Keep original image size, no magnify-button. - - $part = explode( '|', $options); - + # vertical-align values (no % or length right now): + # * baseline + # * sub + # * super + # * top + # * text-top + # * middle + # * bottom + # * text-bottom + + + $part = array_map( 'trim', explode( '|', $options) ); + + $mwAlign = array(); + $alignments = array( 'left', 'right', 'center', 'none', 'baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom' ); + foreach ( $alignments as $alignment ) { + $mwAlign[$alignment] =& MagicWord::get( 'img_'.$alignment ); + } $mwThumb =& MagicWord::get( 'img_thumbnail' ); $mwManualThumb =& MagicWord::get( 'img_manualthumb' ); - $mwLeft =& MagicWord::get( 'img_left' ); - $mwRight =& MagicWord::get( 'img_right' ); - $mwNone =& MagicWord::get( 'img_none' ); $mwWidth =& MagicWord::get( 'img_width' ); - $mwCenter =& MagicWord::get( 'img_center' ); $mwFramed =& MagicWord::get( 'img_framed' ); $mwPage =& MagicWord::get( 'img_page' ); $caption = ''; - $width = $height = $framed = $thumb = false; - $page = null; + $params = array(); + $framed = $thumb = false; $manual_thumb = '' ; + $align = $valign = ''; + $sk = $this->mOptions->getSkin(); foreach( $part as $val ) { - if ( $wgUseImageResize && ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) { + if ( !is_null( $mwThumb->matchVariableStartToEnd($val) ) ) { $thumb=true; } elseif ( ! is_null( $match = $mwManualThumb->matchVariableStartToEnd($val) ) ) { # use manually specified thumbnail $thumb=true; $manual_thumb = $match; - } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) { - # remember to set an alignment, don't render immediately - $align = 'right'; - } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) { - # remember to set an alignment, don't render immediately - $align = 'left'; - } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) { - # remember to set an alignment, don't render immediately - $align = 'center'; - } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) { - # remember to set an alignment, don't render immediately - $align = 'none'; - } elseif ( isset( $wgDjvuRenderer ) && $wgDjvuRenderer - && ! is_null( $match = $mwPage->matchVariableStartToEnd($val) ) ) { - # Select a page in a multipage document - $page = $match; - } elseif ( $wgUseImageResize && !$width && ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) { - wfDebug( "img_width match: $match\n" ); - # $match is the image width in pixels - $m = array(); - if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) { - $width = intval( $m[1] ); - $height = intval( $m[2] ); + } else { + foreach( $alignments as $alignment ) { + if ( ! is_null( $mwAlign[$alignment]->matchVariableStartToEnd($val) ) ) { + switch ( $alignment ) { + case 'left': case 'right': case 'center': case 'none': + $align = $alignment; break; + default: + $valign = $alignment; + } + continue 2; + } + } + if ( ! is_null( $match = $mwPage->matchVariableStartToEnd($val) ) ) { + # Select a page in a multipage document + $params['page'] = $match; + } elseif ( !isset( $params['width'] ) && ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) { + wfDebug( "img_width match: $match\n" ); + # $match is the image width in pixels + $m = array(); + if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) { + $params['width'] = intval( $m[1] ); + $params['height'] = intval( $m[2] ); + } else { + $params['width'] = intval($match); + } + } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) { + $framed=true; } else { - $width = intval($match); + $caption = $val; } - } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) { - $framed=true; - } else { - $caption = $val; } } # Strip bad stuff out of the alt text @@ -4439,8 +4478,7 @@ class Parser $alt = Sanitizer::stripAllTags( $alt ); # Linker does the rest - $sk =& $this->mOptions->getSkin(); - return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $width, $height, $framed, $thumb, $manual_thumb, $page ); + return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $params, $framed, $thumb, $manual_thumb, $valign ); } /** @@ -4518,24 +4556,6 @@ class Parser $uniq = preg_quote( $this->uniqPrefix(), '/' ); $comment = "(?:$uniq-!--.*?QINU)"; $secs = preg_split( - /* - "/ - ^( - (?:$comment|<\/?noinclude>)* # Initial comments will be stripped - (?: - (=+) # Should this be limited to 6? - .+? # Section title... - \\2 # Ending = count must match start - | - ^ - <h([1-6])\b.*?> - .*? - <\/h\\3\s*> - ) - (?:$comment|<\/?noinclude>|\s+)* # Trailing whitespace ok - )$ - /mix", - */ "/ ( ^ @@ -4559,7 +4579,8 @@ class Parser // "Section 0" returns the content before any other section. $rv = $secs[0]; } else { - $rv = ""; + //track missing section, will replace if found. + $rv = $newtext; } } elseif( $mode == "replace" ) { if( $section == 0 ) { @@ -4614,8 +4635,10 @@ class Parser } } } - # reinsert stripped tags - $rv = trim( $stripState->unstripBoth( $rv ) ); + if (is_string($rv)) + # reinsert stripped tags + $rv = trim( $stripState->unstripBoth( $rv ) ); + return $rv; } @@ -4628,34 +4651,35 @@ class Parser * * @param $text String: text to look in * @param $section Integer: section number + * @param $deftext: default to return if section is not found * @return string text of the requested section */ - function getSection( $text, $section ) { - return $this->extractSections( $text, $section, "get" ); + public function getSection( $text, $section, $deftext='' ) { + return $this->extractSections( $text, $section, "get", $deftext ); } - function replaceSection( $oldtext, $section, $text ) { + public function replaceSection( $oldtext, $section, $text ) { return $this->extractSections( $oldtext, $section, "replace", $text ); } /** - * Get the timestamp associated with the current revision, adjusted for + * Get the timestamp associated with the current revision, adjusted for * the default server-local timestamp */ function getRevisionTimestamp() { if ( is_null( $this->mRevisionTimestamp ) ) { wfProfileIn( __METHOD__ ); global $wgContLang; - $dbr =& wfGetDB( DB_SLAVE ); + $dbr = wfGetDB( DB_SLAVE ); $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', array( 'rev_id' => $this->mRevisionId ), __METHOD__ ); - + // Normalize timestamp to internal MW format for timezone processing. // This has the added side-effect of replacing a null value with // the current time, which gives us more sensible behavior for // previews. $timestamp = wfTimestamp( TS_MW, $timestamp ); - + // The cryptic '' timezone parameter tells to use the site-default // timezone offset instead of the user settings. // @@ -4663,12 +4687,12 @@ class Parser // to other users, and potentially even used inside links and such, // it needs to be consistent for all visitors. $this->mRevisionTimestamp = $wgContLang->userAdjust( $timestamp, '' ); - + wfProfileOut( __METHOD__ ); } return $this->mRevisionTimestamp; } - + /** * Mutator for $mDefaultSort * @@ -4677,7 +4701,7 @@ class Parser public function setDefaultSort( $sort ) { $this->mDefaultSort = $sort; } - + /** * Accessor for $mDefaultSort * Will use the title/prefixed title if none is set @@ -4693,241 +4717,13 @@ class Parser : $this->mTitle->getPrefixedText(); } } - -} - -/** - * @todo document - * @package MediaWiki - */ -class ParserOutput -{ - var $mText, # The output text - $mLanguageLinks, # List of the full text of language links, in the order they appear - $mCategories, # Map of category names to sort keys - $mContainsOldMagic, # Boolean variable indicating if the input contained variables like {{CURRENTDAY}} - $mCacheTime, # Time when this object was generated, or -1 for uncacheable. Used in ParserCache. - $mVersion, # Compatibility check - $mTitleText, # title text of the chosen language variant - $mLinks, # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken. - $mTemplates, # 2-D map of NS/DBK to ID for the template references. ID=zero for broken. - $mImages, # DB keys of the images used, in the array key only - $mExternalLinks, # External link URLs, in the key only - $mHTMLtitle, # Display HTML title - $mSubtitle, # Additional subtitle - $mNewSection, # Show a new section link? - $mNoGallery; # No gallery on category page? (__NOGALLERY__) - - function ParserOutput( $text = '', $languageLinks = array(), $categoryLinks = array(), - $containsOldMagic = false, $titletext = '' ) - { - $this->mText = $text; - $this->mLanguageLinks = $languageLinks; - $this->mCategories = $categoryLinks; - $this->mContainsOldMagic = $containsOldMagic; - $this->mCacheTime = ''; - $this->mVersion = MW_PARSER_VERSION; - $this->mTitleText = $titletext; - $this->mLinks = array(); - $this->mTemplates = array(); - $this->mImages = array(); - $this->mExternalLinks = array(); - $this->mHTMLtitle = "" ; - $this->mSubtitle = "" ; - $this->mNewSection = false; - $this->mNoGallery = false; - } - function getText() { return $this->mText; } - function &getLanguageLinks() { return $this->mLanguageLinks; } - function getCategoryLinks() { return array_keys( $this->mCategories ); } - function &getCategories() { return $this->mCategories; } - function getCacheTime() { return $this->mCacheTime; } - function getTitleText() { return $this->mTitleText; } - function &getLinks() { return $this->mLinks; } - function &getTemplates() { return $this->mTemplates; } - function &getImages() { return $this->mImages; } - function &getExternalLinks() { return $this->mExternalLinks; } - function getNoGallery() { return $this->mNoGallery; } - function getSubtitle() { return $this->mSubtitle; } - - function containsOldMagic() { return $this->mContainsOldMagic; } - function setText( $text ) { return wfSetVar( $this->mText, $text ); } - function setLanguageLinks( $ll ) { return wfSetVar( $this->mLanguageLinks, $ll ); } - function setCategoryLinks( $cl ) { return wfSetVar( $this->mCategories, $cl ); } - function setContainsOldMagic( $com ) { return wfSetVar( $this->mContainsOldMagic, $com ); } - function setCacheTime( $t ) { return wfSetVar( $this->mCacheTime, $t ); } - function setTitleText( $t ) { return wfSetVar($this->mTitleText, $t); } - function setSubtitle( $st ) { return wfSetVar( $this->mSubtitle, $st ); } - - function addCategory( $c, $sort ) { $this->mCategories[$c] = $sort; } - function addImage( $name ) { $this->mImages[$name] = 1; } - function addLanguageLink( $t ) { $this->mLanguageLinks[] = $t; } - function addExternalLink( $url ) { $this->mExternalLinks[$url] = 1; } - - function setNewSection( $value ) { - $this->mNewSection = (bool)$value; - } - function getNewSection() { - return (bool)$this->mNewSection; - } - - function addLink( $title, $id = null ) { - $ns = $title->getNamespace(); - $dbk = $title->getDBkey(); - if ( !isset( $this->mLinks[$ns] ) ) { - $this->mLinks[$ns] = array(); - } - if ( is_null( $id ) ) { - $id = $title->getArticleID(); - } - $this->mLinks[$ns][$dbk] = $id; - } - - function addTemplate( $title, $id ) { - $ns = $title->getNamespace(); - $dbk = $title->getDBkey(); - if ( !isset( $this->mTemplates[$ns] ) ) { - $this->mTemplates[$ns] = array(); - } - $this->mTemplates[$ns][$dbk] = $id; - } - - /** - * Return true if this cached output object predates the global or - * per-article cache invalidation timestamps, or if it comes from - * an incompatible older version. - * - * @param string $touched the affected article's last touched timestamp - * @return bool - * @public - */ - function expired( $touched ) { - global $wgCacheEpoch; - return $this->getCacheTime() == -1 || // parser says it's uncacheable - $this->getCacheTime() < $touched || - $this->getCacheTime() <= $wgCacheEpoch || - !isset( $this->mVersion ) || - version_compare( $this->mVersion, MW_PARSER_VERSION, "lt" ); - } } /** - * Set options of the Parser - * @todo document - * @package MediaWiki + * @todo document, briefly. + * @addtogroup Parser */ -class ParserOptions -{ - # All variables are supposed to be private in theory, although in practise this is not the case. - var $mUseTeX; # Use texvc to expand <math> tags - var $mUseDynamicDates; # Use DateFormatter to format dates - var $mInterwikiMagic; # Interlanguage links are removed and returned in an array - var $mAllowExternalImages; # Allow external images inline - var $mAllowExternalImagesFrom; # If not, any exception? - var $mSkin; # Reference to the preferred skin - var $mDateFormat; # Date format index - var $mEditSection; # Create "edit section" links - var $mNumberHeadings; # Automatically number headings - var $mAllowSpecialInclusion; # Allow inclusion of special pages - var $mTidy; # Ask for tidy cleanup - var $mInterfaceMessage; # Which lang to call for PLURAL and GRAMMAR - var $mMaxIncludeSize; # Maximum size of template expansions, in bytes - var $mRemoveComments; # Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS - - var $mUser; # Stored user object, just used to initialise the skin - - function getUseTeX() { return $this->mUseTeX; } - function getUseDynamicDates() { return $this->mUseDynamicDates; } - function getInterwikiMagic() { return $this->mInterwikiMagic; } - function getAllowExternalImages() { return $this->mAllowExternalImages; } - function getAllowExternalImagesFrom() { return $this->mAllowExternalImagesFrom; } - function getEditSection() { return $this->mEditSection; } - function getNumberHeadings() { return $this->mNumberHeadings; } - function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; } - function getTidy() { return $this->mTidy; } - function getInterfaceMessage() { return $this->mInterfaceMessage; } - function getMaxIncludeSize() { return $this->mMaxIncludeSize; } - function getRemoveComments() { return $this->mRemoveComments; } - - function &getSkin() { - if ( !isset( $this->mSkin ) ) { - $this->mSkin = $this->mUser->getSkin(); - } - return $this->mSkin; - } - - function getDateFormat() { - if ( !isset( $this->mDateFormat ) ) { - $this->mDateFormat = $this->mUser->getDatePreference(); - } - return $this->mDateFormat; - } - - function setUseTeX( $x ) { return wfSetVar( $this->mUseTeX, $x ); } - function setUseDynamicDates( $x ) { return wfSetVar( $this->mUseDynamicDates, $x ); } - function setInterwikiMagic( $x ) { return wfSetVar( $this->mInterwikiMagic, $x ); } - function setAllowExternalImages( $x ) { return wfSetVar( $this->mAllowExternalImages, $x ); } - function setAllowExternalImagesFrom( $x ) { return wfSetVar( $this->mAllowExternalImagesFrom, $x ); } - function setDateFormat( $x ) { return wfSetVar( $this->mDateFormat, $x ); } - function setEditSection( $x ) { return wfSetVar( $this->mEditSection, $x ); } - function setNumberHeadings( $x ) { return wfSetVar( $this->mNumberHeadings, $x ); } - function setAllowSpecialInclusion( $x ) { return wfSetVar( $this->mAllowSpecialInclusion, $x ); } - function setTidy( $x ) { return wfSetVar( $this->mTidy, $x); } - function setSkin( $x ) { $this->mSkin = $x; } - function setInterfaceMessage( $x ) { return wfSetVar( $this->mInterfaceMessage, $x); } - function setMaxIncludeSize( $x ) { return wfSetVar( $this->mMaxIncludeSize, $x ); } - function setRemoveComments( $x ) { return wfSetVar( $this->mRemoveComments, $x ); } - - function ParserOptions( $user = null ) { - $this->initialiseFromUser( $user ); - } - - /** - * Get parser options - * @static - */ - static function newFromUser( $user ) { - return new ParserOptions( $user ); - } - - /** Get user options */ - function initialiseFromUser( $userInput ) { - global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages; - global $wgAllowExternalImagesFrom, $wgAllowSpecialInclusion, $wgMaxArticleSize; - $fname = 'ParserOptions::initialiseFromUser'; - wfProfileIn( $fname ); - if ( !$userInput ) { - global $wgUser; - if ( isset( $wgUser ) ) { - $user = $wgUser; - } else { - $user = new User; - } - } else { - $user =& $userInput; - } - - $this->mUser = $user; - - $this->mUseTeX = $wgUseTeX; - $this->mUseDynamicDates = $wgUseDynamicDates; - $this->mInterwikiMagic = $wgInterwikiMagic; - $this->mAllowExternalImages = $wgAllowExternalImages; - $this->mAllowExternalImagesFrom = $wgAllowExternalImagesFrom; - $this->mSkin = null; # Deferred - $this->mDateFormat = null; # Deferred - $this->mEditSection = true; - $this->mNumberHeadings = $user->getOption( 'numberheadings' ); - $this->mAllowSpecialInclusion = $wgAllowSpecialInclusion; - $this->mTidy = false; - $this->mInterfaceMessage = false; - $this->mMaxIncludeSize = $wgMaxArticleSize * 1024; - $this->mRemoveComments = true; - wfProfileOut( $fname ); - } -} - class OnlyIncludeReplacer { var $output = ''; @@ -4940,6 +4736,10 @@ class OnlyIncludeReplacer { } } +/** + * @todo document, briefly. + * @addtogroup Parser + */ class StripState { var $general, $nowiki; |