summaryrefslogtreecommitdiff
path: root/includes/parser/Parser.php
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2013-01-18 16:46:04 +0100
committerPierre Schmitz <pierre@archlinux.de>2013-01-18 16:46:04 +0100
commit63601400e476c6cf43d985f3e7b9864681695ed4 (patch)
treef7846203a952e38aaf66989d0a4702779f549962 /includes/parser/Parser.php
parent8ff01378c9e0207f9169b81966a51def645b6a51 (diff)
Update to MediaWiki 1.20.2
this update includes: * adjusted Arch Linux skin * updated FluxBBAuthPlugin * patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024
Diffstat (limited to 'includes/parser/Parser.php')
-rw-r--r--includes/parser/Parser.php373
1 files changed, 236 insertions, 137 deletions
diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php
index d4f167c9..2a24bee7 100644
--- a/includes/parser/Parser.php
+++ b/includes/parser/Parser.php
@@ -1,12 +1,29 @@
<?php
/**
- * @defgroup Parser Parser
+ * PHP parser that converts wiki markup to HTML.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Parser
- * File for Parser and related classes
*/
+/**
+ * @defgroup Parser Parser
+ */
/**
* PHP Parser - Processes wiki markup (which uses a more user-friendly
@@ -14,36 +31,38 @@
* transformation of that wiki markup it into XHTML output / markup
* (which in turn the browser understands, and can display).
*
- * <pre>
- * There are five main entry points into the Parser class:
- * parse()
+ * There are seven main entry points into the Parser class:
+ *
+ * - Parser::parse()
* produces HTML output
- * preSaveTransform().
+ * - Parser::preSaveTransform().
* produces altered wiki markup.
- * preprocess()
+ * - Parser::preprocess()
* removes HTML comments and expands templates
- * cleanSig() / cleanSigInSig()
+ * - Parser::cleanSig() and Parser::cleanSigInSig()
* Cleans a signature before saving it to preferences
- * getSection()
+ * - Parser::getSection()
* Return the content of a section from an article for section editing
- * replaceSection()
+ * - Parser::replaceSection()
* Replaces a section by number inside an article
- * getPreloadText()
+ * - Parser::getPreloadText()
* Removes <noinclude> sections, and <includeonly> tags.
*
* Globals used:
* object: $wgContLang
*
- * NOT $wgUser or $wgTitle or $wgRequest or $wgLang. Keep them away!
+ * @warning $wgUser or $wgTitle or $wgRequest or $wgLang. Keep them away!
*
- * settings:
- * $wgUseDynamicDates*, $wgInterwikiMagic*,
- * $wgNamespacesWithSubpages, $wgAllowExternalImages*,
- * $wgLocaltimezone, $wgAllowSpecialInclusion*,
- * $wgMaxArticleSize*
+ * @par Settings:
+ * $wgLocaltimezone
+ * $wgNamespacesWithSubpages
*
- * * only within ParserOptions
- * </pre>
+ * @par Settings only within ParserOptions:
+ * $wgAllowExternalImages
+ * $wgAllowSpecialInclusion
+ * $wgInterwikiMagic
+ * $wgMaxArticleSize
+ * $wgUseDynamicDates
*
* @ingroup Parser
*/
@@ -144,7 +163,8 @@ class Parser {
var $mLinkHolders;
var $mLinkID;
- var $mIncludeSizes, $mPPNodeCount, $mDefaultSort;
+ var $mIncludeSizes, $mPPNodeCount, $mGeneratedPPNodeCount, $mHighestExpansionDepth;
+ var $mDefaultSort;
var $mTplExpandCache; # empty-frame expansion cache
var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
var $mExpensiveFunctionCount; # number of expensive parser function calls
@@ -188,7 +208,7 @@ class Parser {
public function __construct( $conf = array() ) {
$this->mConf = $conf;
$this->mUrlProtocols = wfUrlProtocols();
- $this->mExtLinkBracketedRegex = '/\[((' . wfUrlProtocols() . ')'.
+ $this->mExtLinkBracketedRegex = '/\[(((?i)' . $this->mUrlProtocols . ')'.
self::EXT_LINK_URL_CLASS.'+)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F]*?)\]/Su';
if ( isset( $conf['preprocessorClass'] ) ) {
$this->mPreprocessorClass = $conf['preprocessorClass'];
@@ -273,8 +293,6 @@ class Parser {
* Must not consist of all title characters, or else it will change
* the behaviour of <nowiki> in a link.
*/
- # $this->mUniqPrefix = "\x07UNIQ" . Parser::getRandomString();
- # Changed to \x7f to allow XML double-parsing -- TS
$this->mUniqPrefix = "\x7fUNIQ" . self::getRandomString();
$this->mStripState = new StripState( $this->mUniqPrefix );
@@ -289,6 +307,8 @@ class Parser {
'arg' => 0,
);
$this->mPPNodeCount = 0;
+ $this->mGeneratedPPNodeCount = 0;
+ $this->mHighestExpansionDepth = 0;
$this->mDefaultSort = false;
$this->mHeadings = array();
$this->mDoubleUnderscores = array();
@@ -321,13 +341,18 @@ class Parser {
* to internalParse() which does all the real work.
*/
- global $wgUseTidy, $wgAlwaysUseTidy, $wgDisableLangConversion, $wgDisableTitleConversion;
+ global $wgUseTidy, $wgAlwaysUseTidy;
$fname = __METHOD__.'-' . wfGetCaller();
wfProfileIn( __METHOD__ );
wfProfileIn( $fname );
$this->startParse( $title, $options, self::OT_HTML, $clearState );
+ # Remove the strip marker tag prefix from the input, if present.
+ if ( $clearState ) {
+ $text = str_replace( $this->mUniqPrefix, '', $text );
+ }
+
$oldRevisionId = $this->mRevisionId;
$oldRevisionObject = $this->mRevisionObject;
$oldRevisionTimestamp = $this->mRevisionTimestamp;
@@ -343,6 +368,7 @@ class Parser {
# No more strip!
wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
$text = $this->internalParse( $text );
+ wfRunHooks( 'ParserAfterParse', array( &$this, &$text, &$this->mStripState ) );
$text = $this->mStripState->unstripGeneral( $text );
@@ -368,9 +394,8 @@ class Parser {
* c) It's a conversion table
* d) it is an interface message (which is in the user language)
*/
- if ( !( $wgDisableLangConversion
- || isset( $this->mDoubleUnderscores['nocontentconvert'] )
- || $this->mTitle->isConversionTable() ) )
+ if ( !( $options->getDisableContentConversion()
+ || isset( $this->mDoubleUnderscores['nocontentconvert'] ) ) )
{
# Run convert unconditionally in 1.18-compatible mode
global $wgBug34832TransitionalRollback;
@@ -389,8 +414,7 @@ class Parser {
* {{DISPLAYTITLE:...}} is present. DISPLAYTITLE takes precedence over
* automatic link conversion.
*/
- if ( !( $wgDisableLangConversion
- || $wgDisableTitleConversion
+ if ( !( $options->getDisableTitleConversion()
|| isset( $this->mDoubleUnderscores['nocontentconvert'] )
|| isset( $this->mDoubleUnderscores['notitleconvert'] )
|| $this->mOutput->getDisplayTitle() !== false ) )
@@ -442,9 +466,12 @@ class Parser {
array_values( $tidyregs ),
$text );
}
- global $wgExpensiveParserFunctionLimit;
- if ( $this->mExpensiveFunctionCount > $wgExpensiveParserFunctionLimit ) {
- $this->limitationWarn( 'expensive-parserfunction', $this->mExpensiveFunctionCount, $wgExpensiveParserFunctionLimit );
+
+ if ( $this->mExpensiveFunctionCount > $this->mOptions->getExpensiveParserFunctionLimit() ) {
+ $this->limitationWarn( 'expensive-parserfunction',
+ $this->mExpensiveFunctionCount,
+ $this->mOptions->getExpensiveParserFunctionLimit()
+ );
}
wfRunHooks( 'ParserAfterTidy', array( &$this, &$text ) );
@@ -452,12 +479,15 @@ class Parser {
# Information on include size limits, for the benefit of users who try to skirt them
if ( $this->mOptions->getEnableLimitReport() ) {
$max = $this->mOptions->getMaxIncludeSize();
- $PFreport = "Expensive parser function count: {$this->mExpensiveFunctionCount}/$wgExpensiveParserFunctionLimit\n";
+ $PFreport = "Expensive parser function count: {$this->mExpensiveFunctionCount}/{$this->mOptions->getExpensiveParserFunctionLimit()}\n";
$limitReport =
"NewPP limit report\n" .
- "Preprocessor node count: {$this->mPPNodeCount}/{$this->mOptions->getMaxPPNodeCount()}\n" .
+ "Preprocessor visited node count: {$this->mPPNodeCount}/{$this->mOptions->getMaxPPNodeCount()}\n" .
+ "Preprocessor generated node count: " .
+ "{$this->mGeneratedPPNodeCount}/{$this->mOptions->getMaxGeneratedPPNodeCount()}\n" .
"Post-expand include size: {$this->mIncludeSizes['post-expand']}/$max bytes\n" .
"Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n".
+ "Highest expansion depth: {$this->mHighestExpansionDepth}/{$this->mOptions->getMaxPPExpandDepth()}\n".
$PFreport;
wfRunHooks( 'ParserLimitReport', array( $this, &$limitReport ) );
$text .= "\n<!-- \n$limitReport-->\n";
@@ -497,6 +527,7 @@ class Parser {
/**
* Expand templates and variables in the text, producing valid, static wikitext.
* Also removes comments.
+ * @return mixed|string
*/
function preprocess( $text, Title $title, ParserOptions $options, $revid = null ) {
wfProfileIn( __METHOD__ );
@@ -530,10 +561,11 @@ class Parser {
}
/**
- * Process the wikitext for the ?preload= feature. (bug 5210)
+ * Process the wikitext for the "?preload=" feature. (bug 5210)
*
- * <noinclude>, <includeonly> etc. are parsed as for template transclusion,
- * comments, templates, arguments, tags hooks and parser functions are untouched.
+ * "<noinclude>", "<includeonly>" etc. are parsed as for template
+ * transclusion, comments, templates, arguments, tags hooks and parser
+ * functions are untouched.
*
* @param $text String
* @param $title Title
@@ -557,7 +589,7 @@ class Parser {
* @return string
*/
static public function getRandomString() {
- return dechex( mt_rand( 0, 0x7fffffff ) ) . dechex( mt_rand( 0, 0x7fffffff ) );
+ return wfRandomString( 16 );
}
/**
@@ -619,7 +651,7 @@ class Parser {
/**
* Accessor/mutator for the Title object
*
- * @param $x New Title object or null to just get the current one
+ * @param $x Title object or null to just get the current one
* @return Title object
*/
function Title( $x = null ) {
@@ -645,7 +677,7 @@ class Parser {
/**
* Accessor/mutator for the output type
*
- * @param $x New value or null to just get the current one
+ * @param $x int|null New value or null to just get the current one
* @return Integer
*/
function OutputType( $x = null ) {
@@ -673,8 +705,8 @@ class Parser {
/**
* Accessor/mutator for the ParserOptions object
*
- * @param $x New value or null to just get the current one
- * @return Current ParserOptions object
+ * @param $x ParserOptions New value or null to just get the current one
+ * @return ParserOptions Current ParserOptions object
*/
function Options( $x = null ) {
return wfSetVar( $this->mOptions, $x );
@@ -703,18 +735,24 @@ class Parser {
}
/**
- * Get the target language for the content being parsed. This is usually the
- * language that the content is in.
+ * Get the target language for the content being parsed. This is usually the
+ * language that the content is in.
+ *
+ * @since 1.19
+ *
+ * @return Language|null
*/
- function getTargetLanguage() {
+ public function getTargetLanguage() {
$target = $this->mOptions->getTargetLanguage();
+
if ( $target !== null ) {
return $target;
} elseif( $this->mOptions->getInterfaceMessage() ) {
return $this->mOptions->getUserLangObj();
} elseif( is_null( $this->mTitle ) ) {
- throw new MWException( __METHOD__.': $this->mTitle is null' );
+ throw new MWException( __METHOD__ . ': $this->mTitle is null' );
}
+
return $this->mTitle->getPageLanguage();
}
@@ -761,11 +799,14 @@ class Parser {
* in the text with a random marker and returns the next text. The output
* parameter $matches will be an associative array filled with data in
* the form:
+ *
+ * @code
* 'UNIQ-xxxxx' => array(
* 'element',
* 'tag content',
* array( 'param' => 'x' ),
* '<element param="x">tag content</element>' ) )
+ * @endcode
*
* @param $elements array list of element names. Comments are always extracted.
* @param $text string Source text string.
@@ -864,6 +905,7 @@ class Parser {
* parse the wiki syntax used to render tables
*
* @private
+ * @return string
*/
function doTableStuff( $text ) {
wfProfileIn( __METHOD__ );
@@ -1094,6 +1136,7 @@ class Parser {
$text = $this->replaceVariables( $text );
}
+ wfRunHooks( 'InternalParseBeforeSanitize', array( &$this, &$text, &$this->mStripState ) );
$text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ), false, array_keys( $this->mTransparentTagHooks ) );
wfRunHooks( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
@@ -1146,7 +1189,7 @@ class Parser {
'!(?: # Start cases
(<a[ \t\r\n>].*?</a>) | # m[1]: Skip link text
(<.*?>) | # m[2]: Skip stuff inside HTML elements' . "
- (\\b(?:$prots)$urlChar+) | # m[3]: Free external links" . '
+ (\\b(?i:$prots)$urlChar+) | # m[3]: Free external links" . '
(?:RFC|PMID)\s+([0-9]+) | # m[4]: RFC or PMID, capture number
ISBN\s+(\b # m[5]: ISBN, capture number
(?: 97[89] [\ \-]? )? # optional 13-digit ISBN prefix
@@ -1189,7 +1232,7 @@ class Parser {
throw new MWException( __METHOD__.': unrecognised match type "' .
substr( $m[0], 0, 20 ) . '"' );
}
- $url = wfMsgForContent( $urlmsg, $id );
+ $url = wfMessage( $urlmsg, $id )->inContentLanguage()->text();
return Linker::makeExternalLink( $url, "{$keyword} {$id}", true, $CssClass );
} elseif ( isset( $m[5] ) && $m[5] !== '' ) {
# ISBN
@@ -1249,7 +1292,7 @@ class Parser {
$text = $this->maybeMakeExternalImage( $url );
if ( $text === false ) {
# Not an image, make a link
- $text = Linker::makeExternalLink( $url,
+ $text = Linker::makeExternalLink( $url,
$this->getConverterLanguage()->markNoConversion($url), true, 'free',
$this->getExternalLinkAttribs( $url ) );
# Register it in the output object...
@@ -1646,7 +1689,7 @@ class Parser {
}
if ( !$text && $this->mOptions->getEnableImageWhitelist()
&& preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
- $whitelist = explode( "\n", wfMsgForContent( 'external_image_whitelist' ) );
+ $whitelist = explode( "\n", wfMessage( 'external_image_whitelist' )->inContentLanguage()->text() );
foreach ( $whitelist as $entry ) {
# Sanitize the regex fragment, make it case-insensitive, ignore blank entries/comments
if ( strpos( $entry, '#' ) === 0 || $entry === '' ) {
@@ -1698,7 +1741,7 @@ class Parser {
$holders = new LinkHolderArray( $this );
- # split the entire text string on occurences of [[
+ # split the entire text string on occurrences of [[
$a = StringUtils::explode( '[[', ' ' . $s );
# get the first element (all text up to first [[), and remove the space we added
$s = $a->current();
@@ -1711,7 +1754,7 @@ class Parser {
if ( $useLinkPrefixExtension ) {
# Match the end of a line for a word that's not followed by whitespace,
# e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched
- $e2 = wfMsgForContent( 'linkprefix' );
+ $e2 = wfMessage( 'linkprefix' )->inContentLanguage()->text();
}
if ( is_null( $this->mTitle ) ) {
@@ -1733,7 +1776,7 @@ class Parser {
}
if ( $this->getConverterLanguage()->hasVariants() ) {
- $selflink = $this->getConverterLanguage()->autoConvertToAllVariants(
+ $selflink = $this->getConverterLanguage()->autoConvertToAllVariants(
$this->mTitle->getPrefixedText() );
} else {
$selflink = array( $this->mTitle->getPrefixedText() );
@@ -1812,7 +1855,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( '/^(?:' . wfUrlProtocols() . ')/', $m[1] ) ) {
+ if ( preg_match( '/^(?i:' . $this->mUrlProtocols . ')/', $m[1] ) ) {
$s .= $prefix . '[[' . $line ;
wfProfileOut( __METHOD__."-misc" );
continue;
@@ -1902,11 +1945,9 @@ class Parser {
# Link not escaped by : , create the various objects
if ( $noforce ) {
- global $wgContLang;
-
# Interwikis
wfProfileIn( __METHOD__."-interwiki" );
- if ( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
+ if ( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && Language::fetchLanguageName( $iw, null, 'mw' ) ) {
$this->mOutput->addLanguageLink( $nt->getFullText() );
$s = rtrim( $s . $prefix );
$s .= trim( $trail, "\n" ) == '' ? '': $prefix . $trail;
@@ -2051,7 +2092,7 @@ class Parser {
* @return String: less-or-more HTML with NOPARSE bits
*/
function armorLinks( $text ) {
- return preg_replace( '/\b(' . wfUrlProtocols() . ')/',
+ return preg_replace( '/\b((?i)' . $this->mUrlProtocols . ')/',
"{$this->mUniqPrefix}NOPARSE$1", $text );
}
@@ -2122,7 +2163,7 @@ class Parser {
* element appropriate to the prefix character passed into them.
* @private
*
- * @param $char char
+ * @param $char string
*
* @return string
*/
@@ -2384,7 +2425,7 @@ class Parser {
}
/**
- * Split up a string on ':', ignoring any occurences inside tags
+ * Split up a string on ':', ignoring any occurrences inside tags
* to prevent illegal overlapping.
*
* @param $str String the string to split
@@ -2698,6 +2739,18 @@ class Parser {
$subjPage = $this->mTitle->getSubjectPage();
$value = wfEscapeWikiText( $subjPage->getPrefixedUrl() );
break;
+ case 'pageid': // requested in bug 23427
+ $pageid = $this->getTitle()->getArticleId();
+ if( $pageid == 0 ) {
+ # 0 means the page doesn't exist in the database,
+ # which means the user is previewing a new page.
+ # The vary-revision flag must be set, because the magic word
+ # will have a different value once the page is saved.
+ $this->mOutput->setFlag( 'vary-revision' );
+ wfDebug( __METHOD__ . ": {{PAGEID}} used in a new page, setting vary-revision...\n" );
+ }
+ $value = $pageid ? $pageid : null;
+ break;
case 'revisionid':
# Let the edit saving system know we should parse the page
# *after* a revision ID has been assigned.
@@ -2760,6 +2813,9 @@ class Parser {
case 'namespacee':
$value = wfUrlencode( $wgContLang->getNsText( $this->mTitle->getNamespace() ) );
break;
+ case 'namespacenumber':
+ $value = $this->mTitle->getNamespace();
+ break;
case 'talkspace':
$value = $this->mTitle->canTalk() ? str_replace( '_',' ',$this->mTitle->getTalkNsText() ) : '';
break;
@@ -2834,7 +2890,8 @@ class Parser {
$value = $pageLang->formatNum( SiteStats::edits() );
break;
case 'numberofviews':
- $value = $pageLang->formatNum( SiteStats::views() );
+ global $wgDisableCounters;
+ $value = !$wgDisableCounters ? $pageLang->formatNum( SiteStats::views() ) : '';
break;
case 'currenttimestamp':
$value = wfTimestamp( TS_MW, $ts );
@@ -2900,7 +2957,7 @@ class Parser {
*
* @param $text String: The text to parse
* @param $flags Integer: bitwise combination of:
- * self::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
+ * self::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.
@@ -3027,13 +3084,14 @@ class Parser {
* 'post-expand-template-inclusion' (corresponding messages:
* 'post-expand-template-inclusion-warning',
* 'post-expand-template-inclusion-category')
- * @param $current Current value
- * @param $max Maximum allowed, when an explicit limit has been
+ * @param $current int|null Current value
+ * @param $max int|null Maximum allowed, when an explicit limit has been
* exceeded, provide the values (optional)
*/
- function limitationWarn( $limitationType, $current=null, $max=null) {
+ function limitationWarn( $limitationType, $current = '', $max = '' ) {
# does no harm if $current and $max are present but are unnecessary for the message
- $warning = wfMsgExt( "$limitationType-warning", array( 'parsemag', 'escape' ), $current, $max );
+ $warning = wfMessage( "$limitationType-warning" )->numParams( $current, $max )
+ ->inContentLanguage()->escaped();
$this->mOutput->addWarning( $warning );
$this->addTrackingCategory( "$limitationType-category" );
}
@@ -3051,7 +3109,7 @@ class Parser {
* @private
*/
function braceSubstitution( $piece, $frame ) {
- global $wgNonincludableNamespaces, $wgContLang;
+ global $wgContLang;
wfProfileIn( __METHOD__ );
wfProfileIn( __METHOD__.'-setup' );
@@ -3238,7 +3296,8 @@ class Parser {
if ( $frame->depth >= $limit ) {
$found = true;
$text = '<span class="error">'
- . wfMsgForContent( 'parser-template-recursion-depth-warning', $limit )
+ . wfMessage( 'parser-template-recursion-depth-warning' )
+ ->numParams( $limit )->inContentLanguage()->text()
. '</span>';
}
}
@@ -3246,8 +3305,11 @@ class Parser {
# Load from database
if ( !$found && $title ) {
- $titleProfileIn = __METHOD__ . "-title-" . $title->getDBKey();
- wfProfileIn( $titleProfileIn ); // template in
+ if ( !Profiler::instance()->isPersistent() ) {
+ # Too many unique items can kill profiling DBs/collectors
+ $titleProfileIn = __METHOD__ . "-title-" . $title->getDBKey();
+ wfProfileIn( $titleProfileIn ); // template in
+ }
wfProfileIn( __METHOD__ . '-loadtpl' );
if ( !$title->isExternal() ) {
if ( $title->isSpecialPage()
@@ -3281,7 +3343,7 @@ class Parser {
$isHTML = true;
$this->disableCache();
}
- } elseif ( $wgNonincludableNamespaces && in_array( $title->getNamespace(), $wgNonincludableNamespaces ) ) {
+ } elseif ( MWNamespace::isNonincludable( $title->getNamespace() ) ) {
$found = false; # access denied
wfDebug( __METHOD__.": template inclusion denied for " . $title->getPrefixedDBkey() );
} else {
@@ -3315,7 +3377,9 @@ class Parser {
# This has to be done after redirect resolution to avoid infinite loops via redirects
if ( !$frame->loopCheck( $title ) ) {
$found = true;
- $text = '<span class="error">' . wfMsgForContent( 'parser-template-loop-warning', $titleText ) . '</span>';
+ $text = '<span class="error">'
+ . wfMessage( 'parser-template-loop-warning', $titleText )->inContentLanguage()->text()
+ . '</span>';
wfDebug( __METHOD__.": template loop broken at '$titleText'\n" );
}
wfProfileOut( __METHOD__ . '-loadtpl' );
@@ -3362,10 +3426,8 @@ class Parser {
}
# Replace raw HTML by a placeholder
- # Add a blank line preceding, to prevent it from mucking up
- # immediately preceding headings
if ( $isHTML ) {
- $text = "\n\n" . $this->insertStripItem( $text );
+ $text = $this->insertStripItem( $text );
} elseif ( $nowiki && ( $this->ot['html'] || $this->ot['pre'] ) ) {
# Escape nowiki-style return values
$text = wfEscapeWikiText( $text );
@@ -3476,7 +3538,7 @@ class Parser {
* Static function to get a template
* Can be overridden via ParserOptions::setTemplateCallback().
*
- * @parma $title Title
+ * @param $title Title
* @param $parser Parser
*
* @return array
@@ -3505,7 +3567,7 @@ class Parser {
# Get the revision
$rev = $id
? Revision::newFromId( $id )
- : Revision::newFromTitle( $title );
+ : Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
$rev_id = $rev ? $rev->getId() : 0;
# If there is no current revision, there is no page
if ( $id === false && !$rev ) {
@@ -3556,7 +3618,7 @@ class Parser {
* If 'broken' is a key in $options then the file will appear as a broken thumbnail.
* @param Title $title
* @param Array $options Array of options to RepoGroup::findFile
- * @return File|false
+ * @return File|bool
*/
function fetchFile( $title, $options = array() ) {
$res = $this->fetchFileAndTitle( $title, $options );
@@ -3607,13 +3669,13 @@ class Parser {
global $wgEnableScaryTranscluding;
if ( !$wgEnableScaryTranscluding ) {
- return wfMsgForContent('scarytranscludedisabled');
+ return wfMessage('scarytranscludedisabled')->inContentLanguage()->text();
}
$url = $title->getFullUrl( "action=$action" );
if ( strlen( $url ) > 255 ) {
- return wfMsgForContent( 'scarytranscludetoolong' );
+ return wfMessage( 'scarytranscludetoolong' )->inContentLanguage()->text();
}
return $this->fetchScaryTemplateMaybeFromCache( $url );
}
@@ -3634,7 +3696,7 @@ class Parser {
$text = Http::get( $url );
if ( !$text ) {
- return wfMsgForContent( 'scarytranscludefailed', $url );
+ return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
}
$dbw = wfGetDB( DB_MASTER );
@@ -3650,7 +3712,7 @@ class Parser {
* Triple brace replacement -- used for template arguments
* @private
*
- * @param $peice array
+ * @param $piece array
* @param $frame PPFrame
*
* @return array
@@ -3700,7 +3762,7 @@ class Parser {
* Return the text to be used for a given extension tag.
* This is the ghost of strip().
*
- * @param $params Associative array of parameters:
+ * @param $params array Associative array of parameters:
* name PPNode for the tag name
* attr PPNode for unparsed text where tag attributes are thought to be
* attributes Optional associative array of parsed attributes
@@ -3808,12 +3870,8 @@ class Parser {
* @return Boolean: false if the limit has been exceeded
*/
function incrementExpensiveFunctionCount() {
- global $wgExpensiveParserFunctionLimit;
$this->mExpensiveFunctionCount++;
- if ( $this->mExpensiveFunctionCount <= $wgExpensiveParserFunctionLimit ) {
- return true;
- }
- return false;
+ return $this->mExpensiveFunctionCount <= $this->mOptions->getExpensiveParserFunctionLimit();
}
/**
@@ -3921,6 +3979,7 @@ class Parser {
* @param $text String
* @param $origText String: original, untouched wikitext
* @param $isMain Boolean
+ * @return mixed|string
* @private
*/
function formatHeadings( $text, $origText, $isMain=true ) {
@@ -4147,7 +4206,7 @@ class Parser {
# Don't number the heading if it is the only one (looks silly)
if ( count( $matches[3] ) > 1 && $this->mOptions->getNumberHeadings() ) {
# the two are different if the line contains a link
- $headline = $numbering . ' ' . $headline;
+ $headline = Html::element( 'span', array( 'class' => 'mw-headline-number' ), $numbering ) . ' ' . $headline;
}
# Create the anchor for linking from the TOC to the section
@@ -4286,7 +4345,7 @@ class Parser {
}
/**
- * Transform wiki markup when saving a page by doing \r\n -> \n
+ * Transform wiki markup when saving a page by doing "\r\n" -> "\n"
* conversion, substitting signatures, {{subst:}} templates, etc.
*
* @param $text String: the text to transform
@@ -4362,7 +4421,7 @@ class Parser {
$text = $this->replaceVariables( $text );
# This works almost by chance, as the replaceVariables are done before the getUserSig(),
- # which may corrupt this parser instance via its wfMsgExt( parsemag ) call-
+ # which may corrupt this parser instance via its wfMessage()->text() call-
# Signatures
$sigText = $this->getUserSig( $user );
@@ -4373,13 +4432,12 @@ class Parser {
) );
# Context links: [[|name]] and [[name (context)|]]
- global $wgLegalTitleChars;
- $tc = "[$wgLegalTitleChars]";
+ $tc = '[' . Title::legalChars() . ']';
$nc = '[ _0-9A-Za-z\x80-\xff-]'; # Namespaces can use non-ascii!
$p1 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\))\\|]]/"; # [[ns:page (context)|]]
$p4 = "/\[\[(:?$nc+:|:|)($tc+?)( ?($tc+))\\|]]/"; # [[ns:page(context)|]]
- $p3 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\)|)(, $tc+|)\\|]]/"; # [[ns:page (context), context|]]
+ $p3 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\)|)((?:, |,)$tc+|)\\|]]/"; # [[ns:page (context), context|]]
$p2 = "/\[\[\\|($tc+)]]/"; # [[|page]]
# try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]"
@@ -4583,7 +4641,7 @@ class Parser {
}
/**
- * Create an HTML-style tag, e.g. <yourtag>special text</yourtag>
+ * Create an HTML-style tag, e.g. "<yourtag>special text</yourtag>"
* The callback should have the following form:
* function myParserHook( $text, $params, $parser, $frame ) { ... }
*
@@ -4601,13 +4659,15 @@ class Parser {
* this interface, as it is not documented and injudicious use could smash
* private variables.**
*
- * @param $tag Mixed: the tag to use, e.g. 'hook' for <hook>
+ * @param $tag Mixed: the tag to use, e.g. 'hook' for "<hook>"
* @param $callback Mixed: the callback function (and object) to use for the tag
- * @return The old value of the mTagHooks array associated with the hook
+ * @return Mixed|null The old value of the mTagHooks array associated with the hook
*/
public function setHook( $tag, $callback ) {
$tag = strtolower( $tag );
- if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) throw new MWException( "Invalid character {$m[0]} in setHook('$tag', ...) call" );
+ if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
+ throw new MWException( "Invalid character {$m[0]} in setHook('$tag', ...) call" );
+ }
$oldVal = isset( $this->mTagHooks[$tag] ) ? $this->mTagHooks[$tag] : null;
$this->mTagHooks[$tag] = $callback;
if ( !in_array( $tag, $this->mStripList ) ) {
@@ -4629,13 +4689,15 @@ class Parser {
* @since 1.10
* @todo better document or deprecate this
*
- * @param $tag Mixed: the tag to use, e.g. 'hook' for <hook>
+ * @param $tag Mixed: the tag to use, e.g. 'hook' for "<hook>"
* @param $callback Mixed: the callback function (and object) to use for the tag
- * @return The old value of the mTagHooks array associated with the hook
+ * @return Mixed|null The old value of the mTagHooks array associated with the hook
*/
function setTransparentTagHook( $tag, $callback ) {
$tag = strtolower( $tag );
- if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) throw new MWException( "Invalid character {$m[0]} in setTransparentHook('$tag', ...) call" );
+ if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
+ throw new MWException( "Invalid character {$m[0]} in setTransparentHook('$tag', ...) call" );
+ }
$oldVal = isset( $this->mTransparentTagHooks[$tag] ) ? $this->mTransparentTagHooks[$tag] : null;
$this->mTransparentTagHooks[$tag] = $callback;
@@ -4691,7 +4753,7 @@ class Parser {
* Please read the documentation in includes/parser/Preprocessor.php for more information
* about the methods available in PPFrame and PPNode.
*
- * @return The old callback function for this name, if any
+ * @return string|callback The old callback function for this name, if any
*/
public function setFunctionHook( $id, $callback, $flags = 0 ) {
global $wgContLang;
@@ -4735,9 +4797,10 @@ class Parser {
}
/**
- * Create a tag function, e.g. <test>some stuff</test>.
+ * Create a tag function, e.g. "<test>some stuff</test>".
* Unlike tag hooks, tag functions are parsed at preprocessor level.
* Unlike parser functions, their content is not preprocessed.
+ * @return null
*/
function setFunctionTagHook( $tag, $callback, $flags ) {
$tag = strtolower( $tag );
@@ -4755,7 +4818,7 @@ class Parser {
/**
* @todo FIXME: Update documentation. makeLinkObj() is deprecated.
- * Replace <!--LINK--> link placeholders with actual links, in the buffer
+ * Replace "<!--LINK-->" link placeholders with actual links, in the buffer
* Placeholders created in Skin::makeLinkObj()
*
* @param $text string
@@ -4768,7 +4831,7 @@ class Parser {
}
/**
- * Replace <!--LINK--> link placeholders with plain text of links
+ * Replace "<!--LINK-->" link placeholders with plain text of links
* (not HTML-formatted).
*
* @param $text String
@@ -4845,30 +4908,41 @@ class Parser {
$label = '';
$alt = '';
+ $link = '';
if ( isset( $matches[3] ) ) {
// look for an |alt= definition while trying not to break existing
// captions with multiple pipes (|) in it, until a more sensible grammar
// is defined for images in galleries
$matches[3] = $this->recursiveTagParse( trim( $matches[3] ) );
- $altmatches = StringUtils::explode('|', $matches[3]);
+ $parameterMatches = StringUtils::explode('|', $matches[3]);
$magicWordAlt = MagicWord::get( 'img_alt' );
+ $magicWordLink = MagicWord::get( 'img_link' );
- foreach ( $altmatches as $altmatch ) {
- $match = $magicWordAlt->matchVariableStartToEnd( $altmatch );
- if ( $match ) {
+ foreach ( $parameterMatches as $parameterMatch ) {
+ if ( $match = $magicWordAlt->matchVariableStartToEnd( $parameterMatch ) ) {
$alt = $this->stripAltText( $match, false );
}
+ elseif( $match = $magicWordLink->matchVariableStartToEnd( $parameterMatch ) ){
+ $link = strip_tags($this->replaceLinkHoldersText($match));
+ $chars = self::EXT_LINK_URL_CLASS;
+ $prots = $this->mUrlProtocols;
+ //check to see if link matches an absolute url, if not then it must be a wiki link.
+ if(!preg_match( "/^($prots)$chars+$/u", $link)){
+ $localLinkTitle = Title::newFromText($link);
+ $link = $localLinkTitle->getLocalURL();
+ }
+ }
else {
// concatenate all other pipes
- $label .= '|' . $altmatch;
+ $label .= '|' . $parameterMatch;
}
}
// remove the first pipe
$label = substr( $label, 1 );
}
- $ig->add( $title, $label, $alt );
+ $ig->add( $title, $label, $alt ,$link);
}
return $ig->toHTML();
}
@@ -4890,7 +4964,7 @@ class Parser {
'vertAlign' => array( 'baseline', 'sub', 'super', 'top', 'text-top', 'middle',
'bottom', 'text-bottom' ),
'frame' => array( 'thumbnail', 'manualthumb', 'framed', 'frameless',
- 'upright', 'border', 'link', 'alt' ),
+ 'upright', 'border', 'link', 'alt', 'class' ),
);
static $internalParamMap;
if ( !$internalParamMap ) {
@@ -4922,7 +4996,7 @@ class Parser {
*
* @param $title Title
* @param $options String
- * @param $holders LinkHolderArray|false
+ * @param $holders LinkHolderArray|bool
* @return string HTML
*/
function makeImage( $title, $options, $holders = false ) {
@@ -4940,6 +5014,7 @@ class Parser {
# * upright reduce width for upright images, rounded to full __0 px
# * border draw a 1px border around the image
# * alt Text for HTML alt attribute (defaults to empty)
+ # * class Set a class for img node
# * link Set the target of the image link. Can be external, interwiki, or local
# vertical-align values (no % or length right now):
# * baseline
@@ -4983,27 +5058,22 @@ class Parser {
# Special case; width and height come in one variable together
if ( $type === 'handler' && $paramName === 'width' ) {
- $m = array();
- # (bug 13500) In both cases (width/height and width only),
- # permit trailing "px" for backward compatibility.
- if ( preg_match( '/^([0-9]*)x([0-9]*)\s*(?:px)?\s*$/', $value, $m ) ) {
- $width = intval( $m[1] );
- $height = intval( $m[2] );
+ $parsedWidthParam = $this->parseWidthParam( $value );
+ if( isset( $parsedWidthParam['width'] ) ) {
+ $width = $parsedWidthParam['width'];
if ( $handler->validateParam( 'width', $width ) ) {
$params[$type]['width'] = $width;
$validated = true;
}
+ }
+ if( isset( $parsedWidthParam['height'] ) ) {
+ $height = $parsedWidthParam['height'];
if ( $handler->validateParam( 'height', $height ) ) {
$params[$type]['height'] = $height;
$validated = true;
}
- } elseif ( preg_match( '/^[0-9]*\s*(?:px)?\s*$/', $value ) ) {
- $width = intval( $value );
- if ( $handler->validateParam( 'width', $width ) ) {
- $params[$type]['width'] = $width;
- $validated = true;
- }
- } # else no validation -- bug 13436
+ }
+ # else no validation -- bug 13436
} else {
if ( $type === 'handler' ) {
# Validate handler parameter
@@ -5013,6 +5083,7 @@ class Parser {
switch( $paramName ) {
case 'manualthumb':
case 'alt':
+ case 'class':
# @todo FIXME: Possibly check validity here for
# manualthumb? downstream behavior seems odd with
# missing manual thumbs.
@@ -5026,8 +5097,8 @@ class Parser {
$paramName = 'no-link';
$value = true;
$validated = true;
- } elseif ( preg_match( "/^$prots/", $value ) ) {
- if ( preg_match( "/^($prots)$chars+$/u", $value, $m ) ) {
+ } elseif ( preg_match( "/^(?i)$prots/", $value ) ) {
+ if ( preg_match( "/^((?i)$prots)$chars+$/u", $value, $m ) ) {
$paramName = 'link-url';
$this->mOutput->addExternalLink( $value );
if ( $this->mOptions->getExternalLinkTarget() ) {
@@ -5116,11 +5187,11 @@ class Parser {
$params['frame']['title'] = $this->stripAltText( $caption, $holders );
}
- wfRunHooks( 'ParserMakeImageParams', array( $title, $file, &$params ) );
+ wfRunHooks( 'ParserMakeImageParams', array( $title, $file, &$params, $this ) );
# Linker does the rest
$time = isset( $options['time'] ) ? $options['time'] : false;
- $ret = Linker::makeImageLink2( $title, $file, $params['frame'], $params['handler'],
+ $ret = Linker::makeImageLink( $this, $title, $file, $params['frame'], $params['handler'],
$time, $descQuery, $this->mOptions->getThumbSize() );
# Give the handler a chance to modify the parser object
@@ -5229,13 +5300,13 @@ class Parser {
*
* @param $text String: Page wikitext
* @param $section String: a section identifier string of the form:
- * <flag1> - <flag2> - ... - <section number>
+ * "<flag1> - <flag2> - ... - <section number>"
*
* Currently the only recognised flag is "T", which means the target section number
* was derived during a template inclusion parse, in other words this is a template
* section edit link. If no flags are given, it was an ordinary section edit link.
* This flag is required to avoid a section numbering mismatch when a section is
- * enclosed by <includeonly> (bug 6563).
+ * enclosed by "<includeonly>" (bug 6563).
*
* The section number 0 pulls the text before the first heading; other numbers will
* pull the given section along with its lower-level subsections. If the section is
@@ -5381,7 +5452,7 @@ class Parser {
* section does not exist, $oldtext is returned unchanged.
*
* @param $oldtext String: former text of the article
- * @param $section Numeric: section identifier
+ * @param $section int section identifier
* @param $text String: replacing text
* @return String: modified text
*/
@@ -5464,7 +5535,7 @@ class Parser {
/**
* Mutator for $mDefaultSort
*
- * @param $sort New value
+ * @param $sort string New value
*/
public function setDefaultSort( $sort ) {
$this->mDefaultSort = $sort;
@@ -5542,7 +5613,7 @@ class Parser {
*
* @param $text String: text string to be stripped of wikitext
* for use in a Section anchor
- * @return Filtered text string
+ * @return string Filtered text string
*/
public function stripSectionName( $text ) {
# Strip internal link markup
@@ -5553,7 +5624,7 @@ class Parser {
# @todo FIXME: Not tolerant to blank link text
# I.E. [http://www.mediawiki.org] will render as [1] or something depending
# on how many empty links there are on the page - need to figure that out.
- $text = preg_replace( '/\[(?:' . wfUrlProtocols() . ')([^ ]+?) ([^[]+)\]/', '$2', $text );
+ $text = preg_replace( '/\[(?i:' . $this->mUrlProtocols . ')([^ ]+?) ([^[]+)\]/', '$2', $text );
# Parse wikitext quotes (italics & bold)
$text = $this->doQuotes( $text );
@@ -5691,7 +5762,7 @@ class Parser {
* If the $data array has been stored persistently, the caller should first
* check whether it is still valid, by calling isValidHalfParsedText().
*
- * @param $data Serialized data
+ * @param $data array Serialized data
* @return String
*/
function unserializeHalfParsedText( $data ) {
@@ -5722,4 +5793,32 @@ class Parser {
function isValidHalfParsedText( $data ) {
return isset( $data['version'] ) && $data['version'] == self::HALF_PARSED_VERSION;
}
+
+ /**
+ * Parsed a width param of imagelink like 300px or 200x300px
+ *
+ * @param $value String
+ *
+ * @return array
+ * @since 1.20
+ */
+ public function parseWidthParam( $value ) {
+ $parsedWidthParam = array();
+ if( $value === '' ) {
+ return $parsedWidthParam;
+ }
+ $m = array();
+ # (bug 13500) In both cases (width/height and width only),
+ # permit trailing "px" for backward compatibility.
+ if ( preg_match( '/^([0-9]*)x([0-9]*)\s*(?:px)?\s*$/', $value, $m ) ) {
+ $width = intval( $m[1] );
+ $height = intval( $m[2] );
+ $parsedWidthParam['width'] = $width;
+ $parsedWidthParam['height'] = $height;
+ } elseif ( preg_match( '/^[0-9]*\s*(?:px)?\s*$/', $value ) ) {
+ $width = intval( $value );
+ $parsedWidthParam['width'] = $width;
+ }
+ return $parsedWidthParam;
+ }
}