$this->clearState();
}
+ $options->resetUsage();
$this->mOptions = $options;
$this->setTitle( $title ); # Page title has to be set for the pre-processor
$uniq_prefix = $this->mUniqPrefix;
$matches = array();
$elements = array_keys( $this->mTransparentTagHooks );
- $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
+ $text = $this->extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
foreach ( $matches as $marker => $data ) {
list( $element, $content, $params, $tag ) = $data;
$text = Sanitizer::normalizeCharReferences( $text );
- if ( ( $wgUseTidy && $this->mOptions->mTidy ) || $wgAlwaysUseTidy ) {
+ if ( ( $wgUseTidy && $this->mOptions->getTidy() ) || $wgAlwaysUseTidy ) {
$text = MWTidy::tidy( $text );
} else {
# attempt to sanitize at least some nesting problems
$PFreport = "Expensive parser function count: {$this->mExpensiveFunctionCount}/$wgExpensiveParserFunctionLimit\n";
$limitReport =
"NewPP limit report\n" .
- "Preprocessor node count: {$this->mPPNodeCount}/{$this->mOptions->mMaxPPNodeCount}\n" .
+ "Preprocessor node count: {$this->mPPNodeCount}/{$this->mOptions->getMaxPPNodeCount()}\n" .
"Post-expand include size: {$this->mIncludeSizes['post-expand']}/$max bytes\n" .
"Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n".
$PFreport;
wfProfileIn( __METHOD__ );
$this->clearState();
$this->setOutputType( self::OT_PREPROCESS );
+ $options->resetUsage();
$this->mOptions = $options;
$this->setTitle( $title );
if ( $revid !== null ) {
# Parser (re)initialisation
$this->clearState();
$this->setOutputType( self::OT_PLAIN );
+ $options->resetUsage();
$this->mOptions = $options;
$this->setTitle( $title );
* @private
* @static
*/
- function getRandomString() {
+ static private function getRandomString() {
return dechex( mt_rand( 0, 0x7fffffff ) ) . dechex( mt_rand( 0, 0x7fffffff ) );
}
*
* @return Title object
*/
- function &getTitle() {
+ function getTitle() {
return $this->mTitle;
}
*
* @param $elements list of element names. Comments are always extracted.
* @param $text Source text string.
- * @param $matches Out parameter, Array: extarcted tags
+ * @param $matches Out parameter, Array: extracted tags
* @param $uniq_prefix
* @return String: stripped text
*
wfProfileIn( __METHOD__ );
$lines = StringUtils::explode( "\n", $text );
- $text = null;
$out = '';
$td_history = array(); # Is currently a td tag open?
$last_tag_history = array(); # Save history of last lag activated (td, th or caption)
$last_tag = array_pop( $last_tag_history );
if ( array_pop( $td_history ) ) {
- $previous = "</{$last_tag}>{$previous}";
+ $previous = "</{$last_tag}>\n{$previous}";
}
if ( $first_character === '|' ) {
$df = DateFormatter::getInstance();
$text = $df->reformat( $this->mOptions->getDateFormat(), $text );
}
- $text = $this->doAllQuotes( $text );
$text = $this->replaceInternalLinks( $text );
+ $text = $this->doAllQuotes( $text );
$text = $this->replaceExternalLinks( $text );
# replaceInternalLinks may sometimes leave behind
return $this->makeFreeExternalLink( $m[0] );
} elseif ( isset( $m[4] ) && $m[4] !== '' ) {
# RFC or PMID
- $CssClass = '';
if ( substr( $m[0], 0, 3 ) === 'RFC' ) {
$keyword = 'RFC';
$urlmsg = 'rfcurl';
throw new MWException( __METHOD__.': unrecognised match type "' .
substr( $m[0], 0, 20 ) . '"' );
}
- $url = wfMsg( $urlmsg, $id);
- $sk = $this->mOptions->getSkin();
+ $url = wfMsgForContent( $urlmsg, $id);
+ $sk = $this->mOptions->getSkin( $this->mTitle );
$la = $sk->getExternalLinkAttributes( "external $CssClass" );
return "<a href=\"{$url}\"{$la}>{$keyword} {$id}</a>";
} elseif ( isset( $m[5] ) && $m[5] !== '' ) {
global $wgContLang;
wfProfileIn( __METHOD__ );
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
$trail = '';
# The characters '<' and '>' (which were escaped by
# First, do some preliminary work. This may shift some apostrophes from
# being mark-up to being text. It also counts the number of occurrences
# of bold and italics mark-ups.
- $i = 0;
$numbold = 0;
$numitalics = 0;
- foreach ( $arr as $r ) {
+ for ( $i = 0; $i < count( $arr ); $i++ ) {
if ( ( $i % 2 ) == 1 ) {
# If there are ever four apostrophes, assume the first is supposed to
# be text, and the remaining three constitute mark-up for bold text.
$numbold++;
}
}
- $i++;
}
# If there is an odd number of both bold and italics, it is likely
global $wgContLang;
wfProfileIn( __METHOD__ );
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
$bits = preg_split( $this->mExtLinkBracketedRegex, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
$s = array_shift( $bits );
* @private
*/
function maybeMakeExternalImage( $url ) {
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
$imagesfrom = $this->mOptions->getAllowExternalImagesFrom();
$imagesexception = !empty( $imagesfrom );
$text = false;
/**
* Process [[ ]] wikilinks
- * @return processed text
+ * @return String: processed text
*
* @private
*/
$e1_img = "/^([{$tc}]+)\\|(.*)\$/sD";
}
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
$holders = new LinkHolderArray( $this );
# split the entire text string on occurences of [[
}
if ( $wgContLang->hasVariants() ) {
- $selflink = $wgContLang->convertLinkToAllVariants( $this->mTitle->getPrefixedText() );
+ $selflink = $wgContLang->autoConvertToAllVariants( $this->mTitle->getPrefixedText() );
} else {
$selflink = array( $this->mTitle->getPrefixedText() );
}
$wasblank = ( $text == '' );
if ( $wasblank ) {
$text = $link;
+ } else {
+ # Bug 4598 madness. Handle the quotes only if they come from the alternate part
+ # [[Lista d''e paise d''o munno]] -> <a href="">Lista d''e paise d''o munno</a>
+ # [[Criticism of Harry Potter|Criticism of ''Harry Potter'']] -> <a href="Criticism of Harry Potter">Criticism of <i>Harry Potter</i></a>
+ $text = $this->doQuotes($text);
}
# Link not escaped by : , create the various objects
*/
function makeKnownLinkHolder( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
list( $inside, $trail ) = Linker::splitTrail( $trail );
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
# FIXME: use link() instead of deprecated makeKnownLinkObj()
$link = $sk->makeKnownLinkObj( $nt, $text, $query, $inside, $prefix );
return $this->armorLinks( $link ) . $trail;
if ( $preOpenMatch and !$preCloseMatch ) {
$this->mInPre = true;
}
- if ( $closematch ) {
- $inBlockElem = false;
- } else {
- $inBlockElem = true;
- }
+ $inBlockElem = !$closematch;
} elseif ( !$inBlockElem && !$this->mInPre ) {
if ( ' ' == substr( $t, 0, 1 ) and ( $this->mLastSection === 'pre' || trim( $t ) != '' ) ) {
# pre
* @private
*/
function getVariableValue( $index, $frame=false ) {
- global $wgContLang, $wgSitename, $wgServer, $wgServerName;
- global $wgScriptPath, $wgStylePath;
+ global $wgContLang, $wgSitename, $wgServer;
+ global $wgArticlePath, $wgScriptPath, $wgStylePath;
/**
* Some of these require message or data lookups and can be
case 'currentversion':
$value = SpecialVersion::getVersion();
break;
+ case 'articlepath':
+ return $wgArticlePath;
case 'sitename':
return $wgSitename;
case 'server':
return $wgServer;
case 'servername':
- return $wgServerName;
+ wfSuppressWarnings(); # May give an E_WARNING in PHP < 5.3.3
+ $serverName = parse_url( $wgServer, PHP_URL_HOST );
+ wfRestoreWarnings();
+ return $serverName ? $serverName : $wgServer;
case 'scriptpath':
return $wgScriptPath;
case 'stylepath':
case 'directionmark':
return $wgContLang->getDirMark();
case 'contentlanguage':
- global $wgContLanguageCode;
- return $wgContLanguageCode;
+ global $wgLanguageCode;
+ return $wgLanguageCode;
default:
$ret = null;
if ( wfRunHooks( 'ParserGetVariableValueSwitch', array( &$this, &$this->mVarCache, &$index, &$ret, &$frame ) ) ) {
if ( $id !== false ) {
$text = $this->getVariableValue( $id, $frame );
if ( MagicWord::getCacheTTL( $id ) > -1 ) {
- $this->mOutput->mContainsOldMagic = true;
+ $this->mOutput->updateCacheExpiry( MagicWord::getCacheTTL( $id ) );
}
$found = true;
}
if ( !$title->equals( $cacheTitle ) ) {
$this->mTplRedirCache[$cacheTitle->getPrefixedDBkey()] =
- array( $title->getNamespace(),$cdb = $title->getDBkey() );
+ array( $title->getNamespace(), $cdb = $title->getDBkey() );
}
return array( $dom, $title );
* Fetch the unparsed text of a template and register a reference to it.
*/
function fetchTemplateAndTitle( $title ) {
- $templateCb = $this->mOptions->getTemplateCallback();
+ $templateCb = $this->mOptions->getTemplateCallback(); # Defaults to Parser::statelessFetchTemplate()
$stuff = call_user_func( $templateCb, $title, $this );
$text = $stuff['text'];
$finalTitle = isset( $stuff['finalTitle'] ) ? $stuff['finalTitle'] : $title;
global $wgEnableScaryTranscluding;
if ( !$wgEnableScaryTranscluding ) {
- return wfMsg('scarytranscludedisabled');
+ return wfMsgForContent('scarytranscludedisabled');
}
$url = $title->getFullUrl( "action=$action" );
if ( strlen( $url ) > 255 ) {
- return wfMsg( 'scarytranscludetoolong' );
+ return wfMsgForContent( 'scarytranscludetoolong' );
}
return $this->fetchScaryTemplateMaybeFromCache( $url );
}
$text = Http::get( $url );
if ( !$text ) {
- return wfMsg( 'scarytranscludefailed', $url );
+ return wfMsgForContent( 'scarytranscludefailed', $url );
}
$dbw = wfGetDB( DB_MASTER );
* @param $frame PPFrame
*/
function extensionSubstitution( $params, $frame ) {
- global $wgRawHtml, $wgContLang;
-
$name = $frame->expand( $params['name'] );
$attrText = !isset( $params['attr'] ) ? null : $frame->expand( $params['attr'] );
$content = !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] );
$this->mShowToc = false;
}
if ( isset( $this->mDoubleUnderscores['hiddencat'] ) && $this->mTitle->getNamespace() == NS_CATEGORY ) {
- $this->mOutput->setProperty( 'hiddencat', 'y' );
$this->addTrackingCategory( 'hidden-category-category' );
}
# (bug 8068) Allow control over whether robots index a page.
$this->mOutput->setIndexPolicy( 'index' );
$this->addTrackingCategory( 'index-category' );
}
+
+ # Cache all double underscores in the database
+ foreach ( $this->mDoubleUnderscores as $key => $val ) {
+ $this->mOutput->setProperty( $key, '' );
+ }
wfProfileOut( __METHOD__ );
return $text;
global $wgMaxTocLevel, $wgContLang, $wgHtml5, $wgExperimentalHtmlIds;
$doNumberHeadings = $this->mOptions->getNumberHeadings();
- $showEditLink = $this->mOptions->getEditSection();
-
- # Do not call quickUserCan unless necessary
- if ( $showEditLink && !$this->mTitle->quickUserCan( 'edit' ) ) {
- $showEditLink = 0;
- }
-
+
# Inhibit editsection links if requested in the page
- if ( isset( $this->mDoubleUnderscores['noeditsection'] ) || $this->mOptions->getIsPrintable() ) {
+ if ( isset( $this->mDoubleUnderscores['noeditsection'] ) ) {
$showEditLink = 0;
+ } else {
+ $showEditLink = $this->mOptions->getEditSection();
}
# Get all headlines for numbering them and adding funky stuff like [edit]
}
# We need this to perform operations on the HTML
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
# headline counter
$headlineCount = 0;
$head = array();
$sublevelCount = array();
$levelCount = array();
- $toclevel = 0;
$level = 0;
$prevlevel = 0;
$toclevel = 0;
$node = $root->getFirstChild();
$byteOffset = 0;
$tocraw = array();
+ $refers = array();
foreach ( $matches[3] as $headline ) {
$isTemplate = false;
if ( $toclevel ) {
$prevlevel = $level;
- $prevtoclevel = $toclevel;
}
$level = $matches[1][$headlineCount];
'noninitial' );
}
- # HTML names must be case-insensitively unique (bug 10721). FIXME:
- # Does this apply to Unicode characters? Because we aren't
- # handling those here.
+ # HTML names must be case-insensitively unique (bug 10721).
+ # This does not apply to Unicode characters per
+ # http://dev.w3.org/html5/spec/infrastructure.html#case-sensitivity-and-string-comparison
+ # FIXME: We may be changing them depending on the current locale.
$arrayKey = strtolower( $safeHeadline );
if ( $legacyHeadline === false ) {
$legacyArrayKey = false;
while ( $node && !$isTemplate ) {
if ( $node->getName() === 'h' ) {
$bits = $node->splitHeading();
- if ( $bits['i'] == $sectionIndex )
+ if ( $bits['i'] == $sectionIndex ) {
break;
+ }
}
$byteOffset += mb_strlen( $this->mStripState->unstripBoth(
$frame->expand( $node, PPFrame::RECOVER_ORIG ) ) );
if ( $isTemplate ) {
# Put a T flag in the section identifier, to indicate to extractSections()
# that sections inside <includeonly> should be counted.
- $editlink = $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex" );
+ $editlink = $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex", null, $this->mOptions->getUserLang() );
} else {
- $editlink = $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint );
+ $editlink = $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint, $this->mOptions->getUserLang() );
}
} else {
$editlink = '';
}
}
- /**
- * Merge $tree2 into $tree1 by replacing the section with index
- * $section in $tree1 and its descendants with the sections in $tree2.
- * Note that in the returned section tree, only the 'index' and
- * 'byteoffset' fields are guaranteed to be correct.
- *
- * @param $tree1 Array: section tree from ParserOutput::getSectons()
- * @param $tree2 Array: section tree
- * @param $section Integer: section index
- * @param $title Title: Title both section trees come from
- * @param $len2 Integer: length of the original wikitext for $tree2
- * @return Array: merged section tree
- */
- public static function mergeSectionTrees( $tree1, $tree2, $section, $title, $len2 ) {
- global $wgContLang;
- $newTree = array();
- $targetLevel = false;
- $merged = false;
- $lastLevel = 1;
- $nextIndex = 1;
- $numbering = array( 0 );
- $titletext = $title->getPrefixedDBkey();
- foreach ( $tree1 as $s ) {
- if ( $targetLevel !== false ) {
- if ( $s['level'] <= $targetLevel ) {
- # We've skipped enough
- $targetLevel = false;
- } else {
- continue;
- }
- }
- if ( $s['index'] != $section ||
- $s['fromtitle'] != $titletext ) {
- self::incrementNumbering( $numbering,
- $s['toclevel'], $lastLevel );
-
- # Rewrite index, byteoffset and number
- if ( $s['fromtitle'] == $titletext ) {
- $s['index'] = $nextIndex++;
- if ( $merged ) {
- $s['byteoffset'] += $len2;
- }
- }
- $s['number'] = implode( '.', array_map(
- array( $wgContLang, 'formatnum' ),
- $numbering ) );
- $lastLevel = $s['toclevel'];
- $newTree[] = $s;
- } else {
- # We're at $section
- # Insert sections from $tree2 here
- foreach ( $tree2 as $s2 ) {
- # Rewrite the fields in $s2
- # before inserting it
- $s2['toclevel'] += $s['toclevel'] - 1;
- $s2['level'] += $s['level'] - 1;
- $s2['index'] = $nextIndex++;
- $s2['byteoffset'] += $s['byteoffset'];
-
- self::incrementNumbering( $numbering,
- $s2['toclevel'], $lastLevel );
- $s2['number'] = implode( '.', array_map(
- array( $wgContLang, 'formatnum' ),
- $numbering ) );
- $lastLevel = $s2['toclevel'];
- $newTree[] = $s2;
- }
- # Skip all descendants of $section in $tree1
- $targetLevel = $s['level'];
- $merged = true;
- }
- }
- return $newTree;
- }
-
- /**
- * Increment a section number. Helper function for mergeSectionTrees()
- *
- * @param $number Array representing a section number
- * @param $level Integer: current TOC level (depth)
- * @param $lastLevel Integer: level of previous TOC entry
- */
- private static function incrementNumbering( &$number, $level, $lastLevel ) {
- if ( $level > $lastLevel ) {
- $number[$level - 1] = 1;
- } elseif ( $level < $lastLevel ) {
- foreach ( $number as $key => $unused )
- if ( $key >= $level ) {
- unset( $number[$key] );
- }
- $number[$level - 1]++;
- } else {
- $number[$level - 1]++;
- }
- }
-
/**
* 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
- * @param &$title Title: the Title object for the current article
+ * @param $title Title: the Title object for the current article
* @param $user User: the User object describing the current user
* @param $options ParserOptions: parsing options
* @param $clearState Boolean: whether to clear the parser state first
* @return String: the altered wiki markup
*/
public function preSaveTransform( $text, Title $title, $user, $options, $clearState = true ) {
+ $options->resetUsage();
$this->mOptions = $options;
$this->setTitle( $title );
$this->setOutputType( self::OT_WIKI );
*/
public function startExternalParse( &$title, $options, $outputType, $clearState = true ) {
$this->setTitle( $title );
+ $options->resetUsage();
$this->mOptions = $options;
$this->setOutputType( $outputType );
if ( $clearState ) {
$ig->setParser( $this );
$ig->setHideBadImages();
$ig->setAttributes( Sanitizer::validateTagAttributes( $params, 'table' ) );
- $ig->useSkin( $this->mOptions->getSkin() );
+ $ig->useSkin( $this->mOptions->getSkin( $this->mTitle ) );
$ig->mRevisionId = $this->mRevisionId;
if ( isset( $params['showfilename'] ) ) {
# * text-bottom
$parts = StringUtils::explode( "|", $options );
- $sk = $this->mOptions->getSkin();
+ $sk = $this->mOptions->getSkin( $this->mTitle );
# Give extensions a chance to select the file revision for us
$skip = $time = $descQuery = false;
}
# Get the file
- $imagename = $title->getDBkey();
$file = wfFindFile( $title, array( 'time' => $time ) );
# Get parameter map
$handler = $file ? $file->getHandler() : false;
if ( preg_match( "/^($prots)$chars+$/", $value, $m ) ) {
$paramName = 'link-url';
$this->mOutput->addExternalLink( $value );
+ if ( $this->mOptions->getExternalLinkTarget() ) {
+ $params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
+ }
$validated = true;
}
} else {
wfRunHooks( 'ParserMakeImageParams', array( $title, $file, &$params ) );
# Linker does the rest
- $ret = $sk->makeImageLink2( $title, $file, $params['frame'], $params['handler'], $time, $descQuery );
+ $ret = $sk->makeImageLink2( $title, $file, $params['frame'], $params['handler'], $time, $descQuery, $this->mOptions->getThumbSize() );
# Give the handler a chance to modify the parser object
if ( $handler ) {
*/
public function setDefaultSort( $sort ) {
$this->mDefaultSort = $sort;
+ $this->mOutput->setProperty( 'defaultsort', $sort );
}
/**
* @return string
*/
public function getDefaultSort() {
- global $wgCategoryPrefixedDefaultSortkey;
if ( $this->mDefaultSort !== false ) {
return $this->mDefaultSort;
- } elseif ( $this->mTitle->getNamespace() == NS_CATEGORY ||
- !$wgCategoryPrefixedDefaultSortkey )
- {
- return $this->mTitle->getText();
} else {
- return $this->mTitle->getPrefixedText();
+ return $this->mTitle->getCategorySortkey();
}
}
return '#' . Sanitizer::escapeId( $text, 'noninitial' );
}
+ /**
+ * Same as guessSectionNameFromWikiText(), but produces legacy anchors
+ * instead. For use in redirects, since IE6 interprets Redirect: headers
+ * as something other than UTF-8 (apparently?), resulting in breakage.
+ *
+ * @param $text String: The section name
+ * @return string An anchor
+ */
+ public function guessLegacySectionNameFromWikiText( $text ) {
+ # Strip out wikitext links(they break the anchor)
+ $text = $this->stripSectionName( $text );
+ $text = Sanitizer::normalizeSectionNameWhitespace( $text );
+ return '#' . Sanitizer::escapeId( $text, array( 'noninitial', 'legacy' ) );
+ }
+
/**
* Strips a text string of wikitext for use in a section anchor
*
return $text;
}
- function srvus( $text ) {
- return $this->testSrvus( $text, $this->mOutputType );
- }
-
/**
* strip/replaceVariables/unstrip for preprocessor regression testing
*/
$title = Title::newFromText( $title );
}
$this->mTitle = $title;
+ $options->resetUsage();
$this->mOptions = $options;
$this->setOutputType( $outputType );
$text = $this->replaceVariables( $text );
*/
function unserialiseHalfParsedText( $data, $intPrefix = null ) {
if ( !$intPrefix ) {
- $intPrefix = $this->getRandomString();
+ $intPrefix = self::getRandomString();
}
# First, extract the strip state.