var $mLinkHolders;
var $mLinkID;
- var $mIncludeSizes, $mPPNodeCount, $mHighestExpansionDepth, $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
*/
var $mUniqPrefix;
+ /**
+ * @var Array with the language name of each language link (i.e. the
+ * interwiki prefix) in the key, value arbitrary. Used to avoid sending
+ * duplicate language links to the ParserOutput.
+ */
+ var $mLangLinkLanguages;
+
/**
* Constructor
*
$this->mRevisionId = $this->mRevisionUser = null;
$this->mVarCache = array();
$this->mUser = null;
+ $this->mLangLinkLanguages = array();
/**
* Prefix for temporary replacement strings for the multipass parser.
'arg' => 0,
);
$this->mPPNodeCount = 0;
+ $this->mGeneratedPPNodeCount = 0;
$this->mHighestExpansionDepth = 0;
$this->mDefaultSort = false;
$this->mHeadings = array();
* to internalParse() which does all the real work.
*/
- global $wgUseTidy, $wgAlwaysUseTidy, $wgDisableLangConversion, $wgDisableTitleConversion;
+ global $wgUseTidy, $wgAlwaysUseTidy;
$fname = __METHOD__.'-' . wfGetCaller();
wfProfileIn( __METHOD__ );
wfProfileIn( $fname );
* 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;
* {{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 ) )
$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";
+
+ if ( $this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10 ) {
+ wfDebugLog( 'generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' .
+ $this->mTitle->getPrefixedDBkey() );
+ }
}
$this->mOutput->setText( $text );
*
* @since 1.19
*
+ * @throws MWException
* @return Language|null
*/
public function getTargetLanguage() {
*
* @param $text string
*
+ * @throws MWException
* @return string
*/
function replaceExternalLinks( $text ) {
/**
* Process [[ ]] wikilinks (RIL)
+ * @param $s
+ * @throws MWException
* @return LinkHolderArray
*
* @private
# Interwikis
wfProfileIn( __METHOD__."-interwiki" );
if ( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && Language::fetchLanguageName( $iw, null, 'mw' ) ) {
- // FIXME: the above check prevents links to sites with identifiers that are not language codes
- $this->mOutput->addLanguageLink( $nt->getFullText() );
+ // XXX: the above check prevents links to sites with identifiers that are not language codes
+
+ # Bug 24502: filter duplicates
+ if ( !isset( $this->mLangLinkLanguages[$iw] ) ) {
+ $this->mLangLinkLanguages[$iw] = true;
+ $this->mOutput->addLanguageLink( $nt->getFullText() );
+ }
+
$s = rtrim( $s . $prefix );
$s .= trim( $trail, "\n" ) == '' ? '': $prefix . $trail;
wfProfileOut( __METHOD__."-interwiki" );
* @param $str String the string to split
* @param &$before String set to everything before the ':'
* @param &$after String set to everything after the ':'
+ * @throws MWException
* @return String the position of the ':', or false if none found
*/
function findColonNoLinks( $str, &$before, &$after ) {
* @private
*
* @param $index integer
- * @param $frame PPFrame
+ * @param bool|\PPFrame $frame
*
+ * @throws MWException
* @return string
*/
function getVariableValue( $index, $frame = false ) {
* $piece['parts']: the parameter array
* $piece['lineStart']: whether the brace was at the start of a line
* @param $frame PPFrame The current frame, contains template arguments
+ * @throws MWException
* @return String: the text of the template
* @private
*/
return $obj->tc_contents;
}
- $text = Http::get( $url );
- if ( !$text ) {
+ $req = MWHttpRequest::factory( $url );
+ $status = $req->execute(); // Status object
+ if ( $status->isOK() ) {
+ $text = $req->getContent();
+ } elseif ( $req->getStatus() != 200 ) { // Though we failed to fetch the content, this status is useless.
+ return wfMessage( 'scarytranscludefailed-httpstatus', $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
+ } else {
return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
}
* noClose Original text did not have a close tag
* @param $frame PPFrame
*
+ * @throws MWException
* @return string
*/
function extensionSubstitution( $params, $frame ) {
$safeHeadline = $this->mStripState->unstripBoth( $safeHeadline );
# Strip out HTML (first regex removes any tag not allowed)
- # Allowed tags are <sup> and <sub> (bug 8393), <i> (bug 26375) and <b> (r105284)
- # We strip any parameter from accepted tags (second regex)
+ # Allowed tags are:
+ # * <sup> and <sub> (bug 8393)
+ # * <i> (bug 26375)
+ # * <b> (r105284)
+ # * <span dir="rtl"> and <span dir="ltr"> (bug 35167)
+ #
+ # We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from <span>,
+ # to allow setting directionality in toc items.
$tocline = preg_replace(
- array( '#<(?!/?(sup|sub|i|b)(?: [^>]*)?>).*?'.'>#', '#<(/?(sup|sub|i|b))(?: .*?)?'.'>#' ),
+ array( '#<(?!/?(span|sup|sub|i|b)(?: [^>]*)?>).*?'.'>#', '#<(/?(?:span(?: dir="(?:rtl|ltr)")?|sup|sub|i|b))(?: .*?)?'.'>#' ),
array( '', '<$1>' ),
$safeHeadline
);
*
* @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
+ * @throws MWException
* @return Mixed|null The old value of the mTagHooks array associated with the hook
*/
public function setHook( $tag, $callback ) {
*
* @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
+ * @throws MWException
* @return Mixed|null The old value of the mTagHooks array associated with the hook
*/
function setTransparentTagHook( $tag, $callback ) {
* Please read the documentation in includes/parser/Preprocessor.php for more information
* about the methods available in PPFrame and PPNode.
*
+ * @throws MWException
* @return string|callback The old callback function for this name, if any
*/
public function setFunctionHook( $id, $callback, $flags = 0 ) {
* 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.
+ * @param $tag
+ * @param $callback
+ * @param $flags
+ * @throws MWException
* @return null
*/
function setFunctionTagHook( $tag, $callback, $flags ) {
* check whether it is still valid, by calling isValidHalfParsedText().
*
* @param $data array Serialized data
+ * @throws MWException
* @return String
*/
function unserializeHalfParsedText( $data ) {