X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FParser.php;h=ca7340086fd1ab4692b46a8368984ce086261b3e;hb=7fb4f4d58efb99ed3427008a6cebf448423e9450;hp=7325323a025789a615ed17a9fbb5774d7a806e35;hpb=8ce19a62762b198aa2d1a5ceb013d0a8b53dd4ab;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Parser.php b/includes/Parser.php index 7325323a02..ca7340086f 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -83,7 +83,7 @@ define( 'EXT_IMAGE_REGEX', * settings: * $wgUseTex*, $wgUseDynamicDates*, $wgInterwikiMagic*, * $wgNamespacesWithSubpages, $wgAllowExternalImages*, - * $wgLocaltimezone + * $wgLocaltimezone, $wgAllowSpecialInclusion* * * * only within ParserOptions * @@ -101,6 +101,7 @@ class Parser # Cleared with clearState(): var $mOutput, $mAutonumber, $mDTopen, $mStripState = array(); var $mVariables, $mIncludeCount, $mArgStack, $mLastSection, $mInPre; + var $mInterwikiLinkHolders, $mLinkHolders; # Temporary: var $mOptions, $mTitle, $mOutputType, @@ -117,6 +118,7 @@ class Parser * @access public */ function Parser() { + global $wgContLang; $this->mTemplates = array(); $this->mTemplatePath = array(); $this->mTagHooks = array(); @@ -138,6 +140,14 @@ class Parser $this->mStripState = array(); $this->mArgStack = array(); $this->mInPre = false; + $this->mInterwikiLinkHolders = array(); + $this->mLinkHolders = array( + 'namespaces' => array(), + 'dbkeys' => array(), + 'queries' => array(), + 'texts' => array(), + 'titles' => array() + ); } /** @@ -165,58 +175,54 @@ class Parser $this->mTitle =& $title; $this->mOutputType = OT_HTML; - $stripState = NULL; - global $fnord; $fnord = 1; + $this->mStripState = NULL; + //$text = $this->strip( $text, $this->mStripState ); // VOODOO MAGIC FIX! Sometimes the above segfaults in PHP5. $x =& $this->mStripState; $text = $this->strip( $text, $x ); - $text = $this->internalParse( $text, $linestart ); + $text = $this->internalParse( $text ); - $dashReplace = array( - '/ - /' => " – ", # N dash - '/(?<=[0-9])-(?=[0-9])/' => "–", # N dash between numbers - '/ -- /' => " — " # M dash - ); - $text = preg_replace( array_keys($dashReplace), array_values($dashReplace), $text ); - $text = $this->unstrip( $text, $this->mStripState ); + # Clean up special characters, only run once, next-to-last before doBlockLevels - global $wgUseTidy; - if(!$wgUseTidy) { - $fixtags = array( - # french spaces, last one Guillemet-left - # only if there is something before the space - '/(.) (?=\\?|:|;|!|\\302\\273)/' => '\\1 \\2', - # french spaces, Guillemet-right - '/(\\302\\253) /' => '\\1 ', - '/
/i' => '
', - '/
/i' => '
', - '/
/i' => '
', - '/<\\/center *>/i' => '
', - ); - $text = preg_replace( array_keys($fixtags), array_values($fixtags), $text ); - $text = Sanitizer::normalizeCharReferences( $text ); - } else { - $fixtags = array( - # french spaces, last one Guillemet-left - '/ (\\?|:|;|!|\\302\\273)/' => ' \\1', - # french spaces, Guillemet-right - '/(\\302\\253) /' => '\\1 ', - '/
/i' => '
', - '/<\\/center *>/i' => '
' - ); - $text = preg_replace( array_keys($fixtags), array_values($fixtags), $text ); - } + $fixtags = array( + # french spaces, last one Guillemet-left + # only if there is something before the space + '/(.) (?=\\?|:|;|!|\\302\\273)/' => '\\1 \\2', + # french spaces, Guillemet-right + '/(\\302\\253) /' => '\\1 ', + '/
/i' => '
', + '/
/i' => '
', + '/
/i' => '
', + '/<\\/center *>/i' => '
', + ); + $text = preg_replace( array_keys($fixtags), array_values($fixtags), $text ); + # only once and last $text = $this->doBlockLevels( $text, $linestart ); $this->replaceLinkHolders( $text ); + + $dashReplace = array( + '/ - /' => " – ", # N dash + '/(?<=[\d])-(?=[\d])/' => "–", # N dash between numbers + '/ -- /' => " — " # M dash + ); + $text = preg_replace( array_keys($dashReplace), array_values($dashReplace), $text ); + + # the position of the convert() call should not be changed. it + # assumes that the links are all replaces and the only thing left + # is the mark. $text = $wgContLang->convert($text); $this->mOutput->setTitleText($wgContLang->getParsedTitle()); + $text = $this->unstripNoWiki( $text, $this->mStripState ); + + $text = Sanitizer::normalizeCharReferences( $text ); + global $wgUseTidy; if ($wgUseTidy) { $text = Parser::tidy($text); } @@ -377,7 +383,7 @@ class Parser # Extensions foreach ( $this->mTagHooks as $tag => $callback ) { - $ext_contents[$tag] = array(); + $ext_content[$tag] = array(); $text = Parser::extractTags( $tag, $text, $ext_content[$tag], $uniq_prefix ); foreach( $ext_content[$tag] as $marker => $content ) { if ( $render ) { @@ -527,6 +533,7 @@ class Parser 1 => array('pipe', 'w'), 2 => array('file', '/dev/null', 'a') ); + $pipes = array(); $process = proc_open("$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes); if (is_resource($process)) { fwrite($pipes[0], $text); @@ -535,7 +542,7 @@ class Parser $cleansource .= fgets($pipes[1], 1024); } fclose($pipes[1]); - $return_value = proc_close($process); + proc_close($process); } wfProfileOut( $fname ); @@ -686,7 +693,6 @@ class Parser } $t = implode ( "\n" , $t ) ; - # $t = Sanitizer::removeHTMLtags( $t ); wfProfileOut( $fname ); return $t ; } @@ -697,9 +703,10 @@ class Parser * * @access private */ - function internalParse( $text, $linestart, $args = array(), $isMain=true ) { + function internalParse( $text ) { global $wgContLang; - + $args = array(); + $isMain = true; $fname = 'Parser::internalParse'; wfProfileIn( $fname ); @@ -964,12 +971,11 @@ class Parser * @access private */ function replaceExternalLinks( $text ) { + global $wgContLang; $fname = 'Parser::replaceExternalLinks'; wfProfileIn( $fname ); $sk =& $this->mOptions->getSkin(); - global $wgContLang; - $linktrail = $wgContLang->linkTrail(); $bits = preg_split( EXT_LINK_BRACKETED, $text, -1, PREG_SPLIT_DELIM_CAPTURE ); @@ -992,7 +998,7 @@ class Parser # If the link text is an image URL, replace it with an tag # This happened by accident in the original parser, but some people used it extensively - $img = $this->maybeMakeImageLink( $text ); + $img = $this->maybeMakeExternalImage( $text ); if ( $img !== false ) { $text = $img; } @@ -1016,21 +1022,21 @@ class Parser } else { # Have link text, e.g. [http://domain.tld/some.link text]s # Check for trail - if ( preg_match( $linktrail, $trail, $m2 ) ) { - $dtrail = $m2[1]; - $trail = $m2[2]; - } + list( $dtrail, $trail ) = Linker::splitTrail( $trail ); } + $text = $wgContLang->markNoConversion($text); + # Replace & from obsolete syntax with &. # All HTML entities will be escaped by makeExternalLink() - # or maybeMakeImageLink() + # or maybeMakeExternalImage() $url = str_replace( '&', '&', $url ); # Process the trail (i.e. everything after this link up until start of the next link), # replacing any non-bracketed links $trail = $this->replaceFreeExternalLinks( $trail ); + # Use the encoded URL # This means that users can paste URLs directly into the text # Funny characters like ö aren't valid in URLs anyway @@ -1047,6 +1053,7 @@ class Parser * @access private */ function replaceFreeExternalLinks( $text ) { + global $wgContLang; $fname = 'Parser::replaceFreeExternalLinks'; wfProfileIn( $fname ); @@ -1088,14 +1095,14 @@ class Parser # Replace & from obsolete syntax with &. # All HTML entities will be escaped by makeExternalLink() - # or maybeMakeImageLink() + # or maybeMakeExternalImage() $url = str_replace( '&', '&', $url ); # Is this an external image? - $text = $this->maybeMakeImageLink( $url ); + $text = $this->maybeMakeExternalImage( $url ); if ( $text === false ) { # Not an image, make a link - $text = $sk->makeExternalLink( $url, $url, true, 'free' ); + $text = $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free' ); } $s .= $text . $trail; } else { @@ -1110,13 +1117,13 @@ class Parser * make an image if it's allowed * @access private */ - function maybeMakeImageLink( $url ) { + function maybeMakeExternalImage( $url ) { $sk =& $this->mOptions->getSkin(); $text = false; if ( $this->mOptions->getAllowExternalImages() ) { if ( preg_match( EXT_IMAGE_REGEX, $url ) ) { # Image found - $text = $sk->makeImage( htmlspecialchars( $url ) ); + $text = $sk->makeExternalImage( htmlspecialchars( $url ) ); } } return $text; @@ -1128,8 +1135,7 @@ class Parser * @access private */ function replaceInternalLinks( $s ) { - global $wgLang, $wgContLang, $wgLinkCache; - global $wgDisableLangConversion; + global $wgContLang, $wgLinkCache; static $fname = 'Parser::replaceInternalLinks' ; wfProfileIn( $fname ); @@ -1140,12 +1146,6 @@ class Parser if ( !$tc ) { $tc = Title::legalChars() . '#%'; } $sk =& $this->mOptions->getSkin(); - global $wgUseOldExistenceCheck; - # "Post-parse link colour check" works only on wiki text since it's now - # in Parser. Enable it, then disable it when we're done. - $saveParseColour = $sk->postParseLinkColour( !$wgUseOldExistenceCheck ); - - $redirect = MagicWord::get ( MAG_REDIRECT ) ; #split the entire text string on occurences of [[ $a = explode( '[[', ' ' . $s ); @@ -1214,7 +1214,11 @@ class Parser # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row fucks up, # the real problem is with the $e1 regex # See bug 1300. - if (preg_match( "/^\](.*)/s", $m[3], $n ) ) { + # + # Still some problems for cases where the ] is meant to be outside punctuation, + # and no image is in sight. See bug 2095. + # + if( $text !== '' && preg_match( "/^\](.*)/s", $m[3], $n ) ) { $text .= ']'; # so that replaceExternalLinks($text) works later $m[3] = $n[1]; } @@ -1329,7 +1333,7 @@ class Parser $text = $this->replaceInternalLinks($text); # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them - $s .= $prefix . str_replace('http://', 'http-noparse://', $sk->makeImageLinkObj( $nt, $text ) ) . $trail; + $s .= $prefix . str_replace('http://', 'http-noparse://', $this->makeImage( $nt, $text ) ) . $trail; $wgLinkCache->addImageLinkObj( $nt ); wfProfileOut( "$fname-image" ); @@ -1341,14 +1345,11 @@ class Parser if ( $ns == NS_CATEGORY ) { wfProfileIn( "$fname-category" ); - $t = $nt->getText(); + $t = $wgContLang->convert($nt->getText()); $s = rtrim($s . "\n"); # bug 87 $wgLinkCache->suspend(); # Don't save in links/brokenlinks - $pPLC=$sk->postParseLinkColour(); - $sk->postParseLinkColour( false ); $t = $sk->makeLinkObj( $nt, $t, '', '' , $prefix ); - $sk->postParseLinkColour( $pPLC ); $wgLinkCache->resume(); if ( $wasblank ) { @@ -1360,6 +1361,7 @@ class Parser } else { $sortkey = $text; } + $sortkey = $wgContLang->convertCategoryKey( $sortkey ); $wgLinkCache->addCategoryLinkObj( $nt, $sortkey ); $this->mOutput->addCategoryLink( $t ); @@ -1390,13 +1392,53 @@ class Parser $s .= $prefix . $sk->makeKnownLinkObj( $nt, $text, '', $trail ); continue; } - $s .= $sk->makeLinkObj( $nt, $text, '', $trail, $prefix ); + if ( $nt->isAlwaysKnown() ) { + $s .= $sk->makeKnownLinkObj( $nt, $text, '', $trail, $prefix ); + } else { + /** + * Add a link placeholder + * Later, this will be replaced by a real link, after the existence or + * non-existence of all the links is known + */ + $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix ); + } } - $sk->postParseLinkColour( $saveParseColour ); wfProfileOut( $fname ); return $s; } + /** + * Make a link placeholder. The text returned can be later resolved to a real link with + * replaceLinkHolders(). This is done for two reasons: firstly to avoid further + * parsing of interwiki links, and secondly to allow all extistence checks and + * article length checks (for stub links) to be bundled into a single query. + * + */ + function makeLinkHolder( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) { + if ( ! is_object($nt) ) { + # Fail gracefully + $retVal = "{$prefix}{$text}{$trail}"; + } else { + # Separate the link trail from the rest of the link + list( $inside, $trail ) = Linker::splitTrail( $trail ); + + if ( $nt->isExternal() ) { + $iwRecord = array( $nt->getPrefixedDBkey(), $prefix.$text.$inside ); + $nr = array_push($this->mInterwikiLinkHolders, $iwRecord); + $retVal = '{$trail}"; + } else { + $nr = array_push( $this->mLinkHolders['namespaces'], $nt->getNamespace() ); + $this->mLinkHolders['dbkeys'][] = $nt->getDBkey(); + $this->mLinkHolders['queries'][] = $query; + $this->mLinkHolders['texts'][] = $prefix.$text.$inside; + $this->mLinkHolders['titles'][] =& $nt; + + $retVal = '{$trail}"; + } + } + return $retVal; + } + /** * Return true if subpage links should be expanded on this page. * @return bool @@ -1568,7 +1610,7 @@ class Parser # $textLines = explode( "\n", $text ); - $lastPrefix = $output = $lastLine = ''; + $lastPrefix = $output = ''; $this->mDTopen = $inBlockElem = false; $prefixLength = 0; $paragraphStack = false; @@ -1607,6 +1649,7 @@ class Parser # ; title : definition text # So we check for : in the remainder text to split up the # title and definition, without b0rking links. + $term = $t2 = ''; if ($this->findColonNoLinks($t, $term, $t2) !== false) { $t = $t2; $output .= $term . $this->nextItem( ':' ); @@ -1843,7 +1886,6 @@ class Parser * @access private */ function replaceVariables( $text, $args = array() ) { - global $wgLang, $wgScript, $wgArticlePath; # Prevent too big inclusions if( strlen( $text ) > MAX_INCLUDE_SIZE ) { @@ -1994,13 +2036,9 @@ class Parser $mwMsgnw =& MagicWord::get( MAG_MSGNW ); if ( $mwMsgnw->matchStartAndRemove( $part1 ) ) { $nowiki = true; - } else { - # Remove obsolete MSG: - $mwMsg =& MagicWord::get( MAG_MSG ); - $mwMsg->matchStartAndRemove( $part1 ); } - # Check if it is an internal message + # int: is the wikitext equivalent of wfMsg() $mwInt =& MagicWord::get( MAG_INT ); if ( $mwInt->matchStartAndRemove( $part1 ) ) { if ( $this->incrementIncludeCount( 'int:'.$part1 ) ) { @@ -2008,6 +2046,15 @@ class Parser $found = true; } } + + # msg: is the wikitext equivalent of wfMsgForContent() + $mwMsg =& MagicWord::get( MAG_MSG ); + if ( $mwMsg->matchStartAndRemove( $part1 ) ) { + if ( $this->incrementIncludeCount( 'msg:'.$part1 ) ) { + $text = $linestart . wfMsgReal( $part1, $args, true, true ); + $found = true; + } + } } # NS @@ -2085,7 +2132,8 @@ class Parser } # Load from database - $itcamefromthedatabase = false; + $replaceHeadings = false; + $isHTML = false; $lastPathLevel = $this->mTemplatePath; if ( !$found ) { $ns = NS_TEMPLATE; @@ -2098,13 +2146,23 @@ class Parser # Check for excessive inclusion $dbk = $title->getPrefixedDBkey(); if ( $this->incrementIncludeCount( $dbk ) ) { - # This should never be reached. - $article = new Article( $title ); - $articleContent = $article->getContentWithoutUsingSoManyDamnGlobals(); - if ( $articleContent !== false ) { - $found = true; - $text = $linestart . $articleContent; - $itcamefromthedatabase = true; + if ( $title->getNamespace() == NS_SPECIAL && $this->mOptions->getAllowSpecialInclusion() ) { + # Capture special page output + $text = SpecialPage::capturePath( $title ); + if ( $text && !is_object( $text ) ) { + $found = true; + $noparse = true; + $isHTML = true; + $this->mOutput->setCacheTime( -1 ); + } + } else { + $article = new Article( $title ); + $articleContent = $article->getContentWithoutUsingSoManyDamnGlobals(); + if ( $articleContent !== false ) { + $found = true; + $text = $linestart . $articleContent; + $replaceHeadings = true; + } } } @@ -2148,8 +2206,10 @@ class Parser # Add a new element to the templace recursion path $this->mTemplatePath[$part1] = 1; - $text = $this->strip( $text, $this->mStripState ); - $text = Sanitizer::removeHTMLtags( $text ); + if( $this->mOutputType == OT_HTML ) { + $text = $this->strip( $text, $this->mStripState ); + $text = Sanitizer::removeHTMLtags( $text ); + } $text = $this->replaceVariables( $text, $assocArgs ); # Resume the link cache and register the inclusion as a link @@ -2170,33 +2230,41 @@ class Parser wfProfileOut( $fname ); return $matches[0]; } else { - # replace ==section headers== - # XXX this needs to go away once we have a better parser. - if ( $this->mOutputType != OT_WIKI && $itcamefromthedatabase ) { - if( !is_null( $title ) ) - $encodedname = base64_encode($title->getPrefixedDBkey()); - else - $encodedname = base64_encode(""); - $m = preg_split('/(^={1,6}.*?={1,6}\s*?$)/m', $text, -1, - PREG_SPLIT_DELIM_CAPTURE); - $text = ''; - $nsec = 0; - for( $i = 0; $i < count($m); $i += 2 ) { - $text .= $m[$i]; - if (!isset($m[$i + 1]) || $m[$i + 1] == "") continue; - $hl = $m[$i + 1]; - if( strstr($hl, "" . $m2[3]; + + $nsec++; } - preg_match('/^(={1,6})(.*?)(={1,6})\s*?$/m', $hl, $m2); - $text .= $m2[1] . $m2[2] . "" . $m2[3]; - - $nsec++; } } } + # Prune lower levels off the recursion check path $this->mTemplatePath = $lastPathLevel; @@ -2409,10 +2477,10 @@ class Parser # turns into # link text with suffix $canonized_headline = preg_replace( '//e', - "\$wgLinkHolders['texts'][\$1]", + "\$this->mLinkHolders['texts'][\$1]", $canonized_headline ); $canonized_headline = preg_replace( '//e', - "\$wgInterwikiLinkHolders[\$1]", + "\$this->mInterwikiLinkHolders[\$1][1]", $canonized_headline ); # strip out HTML @@ -2424,7 +2492,7 @@ class Parser '%' => '.' ); $canonized_headline = str_replace(array_keys($replacearray),array_values($replacearray),$canonized_headline); - $refer[$headlineCount] = $canonized_headline; + $refers[$headlineCount] = $canonized_headline; # count how many in assoc. array so we can track dupes in anchors @$refers[$canonized_headline]++; @@ -2463,7 +2531,6 @@ class Parser } if( $doShowToc ) { - $toclines = $headlineCount; $toc .= $sk->tocUnindent( $toclevel - 1 ); $toc = $sk->tocList( $toc ); } @@ -2506,7 +2573,6 @@ class Parser * @access private */ function magicISBN( $text ) { - global $wgLang; $fname = 'Parser::magicISBN'; wfProfileIn( $fname ); @@ -2560,7 +2626,6 @@ class Parser * @return string */ function magicRFC( $text, $keyword='RFC ', $urlmsg='rfcurl' ) { - global $wgLang; $valid = '0123456789'; $internal = false; @@ -2644,7 +2709,7 @@ class Parser $stripState = false; $pairs = array( "\r\n" => "\n", - ); + ); $text = str_replace( array_keys( $pairs ), array_values( $pairs ), $text ); $text = $this->strip( $text, $stripState, false ); $text = $this->pstPass2( $text, $user ); @@ -2658,7 +2723,7 @@ class Parser * @access private */ function pstPass2( $text, &$user ) { - global $wgLang, $wgContLang, $wgLocaltimezone; + global $wgContLang, $wgLocaltimezone; # Variable replacement # Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags @@ -2682,7 +2747,7 @@ class Parser $d = $wgContLang->timeanddate( wfTimestampNow(), false, false) . ' (' . date( 'T' ) . ')'; if ( isset( $wgLocaltimezone ) ) { - putenv( 'TZ='.$oldtzs ); + putenv( 'TZ='.$oldtz ); } if( $user->getOption( 'fancysig' ) ) { @@ -2794,36 +2859,30 @@ class Parser * $options is a bit field, RLH_FOR_UPDATE to select for update */ function replaceLinkHolders( &$text, $options = 0 ) { - global $wgUser, $wgLinkCache, $wgUseOldExistenceCheck, $wgLinkHolders; - global $wgInterwikiLinkHolders; - global $outputReplace; - - if ( $wgUseOldExistenceCheck ) { - return array(); - } + global $wgUser, $wgLinkCache; + global $wgOutputReplace; $fname = 'Parser::replaceLinkHolders'; wfProfileIn( $fname ); $pdbks = array(); $colours = array(); + $sk = $this->mOptions->getSkin(); - #if ( !empty( $tmpLinks[0] ) ) { #TODO - if ( !empty( $wgLinkHolders['namespaces'] ) ) { + if ( !empty( $this->mLinkHolders['namespaces'] ) ) { wfProfileIn( $fname.'-check' ); $dbr =& wfGetDB( DB_SLAVE ); $page = $dbr->tableName( 'page' ); - $sk = $wgUser->getSkin(); $threshold = $wgUser->getOption('stubthreshold'); # Sort by namespace - asort( $wgLinkHolders['namespaces'] ); + asort( $this->mLinkHolders['namespaces'] ); # Generate query $query = false; - foreach ( $wgLinkHolders['namespaces'] as $key => $val ) { + foreach ( $this->mLinkHolders['namespaces'] as $key => $val ) { # Make title object - $title = $wgLinkHolders['titles'][$key]; + $title = $this->mLinkHolders['titles'][$key]; # Skip invalid entries. # Result will be ugly, but prevents crash. @@ -2853,7 +2912,7 @@ class Parser $query .= ', '; } - $query .= $dbr->addQuotes( $wgLinkHolders['dbkeys'][$key] ); + $query .= $dbr->addQuotes( $this->mLinkHolders['dbkeys'][$key] ); } } if ( $query ) { @@ -2871,7 +2930,7 @@ class Parser while ( $s = $dbr->fetchObject($res) ) { $title = Title::makeTitle( $s->page_namespace, $s->page_title ); $pdbk = $title->getPrefixedDBkey(); - $wgLinkCache->addGoodLink( $s->page_id, $pdbk ); + $wgLinkCache->addGoodLinkObj( $s->page_id, $title ); if ( $threshold > 0 ) { $size = $s->page_len; @@ -2889,25 +2948,25 @@ class Parser # Construct search and replace arrays wfProfileIn( $fname.'-construct' ); - $outputReplace = array(); - foreach ( $wgLinkHolders['namespaces'] as $key => $ns ) { + $wgOutputReplace = array(); + foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) { $pdbk = $pdbks[$key]; - $searchkey = ''; - $title = $wgLinkHolders['titles'][$key]; + $searchkey = ""; + $title = $this->mLinkHolders['titles'][$key]; if ( empty( $colours[$pdbk] ) ) { - $wgLinkCache->addBadLink( $pdbk ); + $wgLinkCache->addBadLinkObj( $title ); $colours[$pdbk] = 0; - $outputReplace[$searchkey] = $sk->makeBrokenLinkObj( $title, - $wgLinkHolders['texts'][$key], - $wgLinkHolders['queries'][$key] ); + $wgOutputReplace[$searchkey] = $sk->makeBrokenLinkObj( $title, + $this->mLinkHolders['texts'][$key], + $this->mLinkHolders['queries'][$key] ); } elseif ( $colours[$pdbk] == 1 ) { - $outputReplace[$searchkey] = $sk->makeKnownLinkObj( $title, - $wgLinkHolders['texts'][$key], - $wgLinkHolders['queries'][$key] ); + $wgOutputReplace[$searchkey] = $sk->makeKnownLinkObj( $title, + $this->mLinkHolders['texts'][$key], + $this->mLinkHolders['queries'][$key] ); } elseif ( $colours[$pdbk] == 2 ) { - $outputReplace[$searchkey] = $sk->makeStubLinkObj( $title, - $wgLinkHolders['texts'][$key], - $wgLinkHolders['queries'][$key] ); + $wgOutputReplace[$searchkey] = $sk->makeStubLinkObj( $title, + $this->mLinkHolders['texts'][$key], + $this->mLinkHolders['queries'][$key] ); } } wfProfileOut( $fname.'-construct' ); @@ -2917,17 +2976,26 @@ class Parser $text = preg_replace_callback( '/()/', - "outputReplaceMatches", + "wfOutputReplaceMatches", $text); + wfProfileOut( $fname.'-replace' ); } - if ( !empty( $wgInterwikiLinkHolders ) ) { + # Now process interwiki link holders + # This is quite a bit simpler than internal links + if ( !empty( $this->mInterwikiLinkHolders ) ) { wfProfileIn( $fname.'-interwiki' ); - $outputReplace = $wgInterwikiLinkHolders; + # Make interwiki link HTML + $wgOutputReplace = array(); + foreach( $this->mInterwikiLinkHolders as $i => $lh ) { + $s = $sk->makeLink( $lh[0], $lh[1] ); + $wgOutputReplace[] = $s; + } + $text = preg_replace_callback( '//', - "outputReplaceMatches", + "wfOutputReplaceMatches", $text ); wfProfileOut( $fname.'-interwiki' ); } @@ -2944,6 +3012,8 @@ class Parser * given as text will return the HTML of a gallery with two images, * labeled 'The number "1"' and * 'A tree'. + * + * @static */ function renderImageGallery( $text ) { # Setup the parser @@ -2983,6 +3053,85 @@ class Parser } return $ig->toHTML(); } + + /** + * Parse image options text and use it to make an image + */ + function makeImage( &$nt, $options ) { + global $wgContLang, $wgUseImageResize; + global $wgUser, $wgThumbLimits; + + $align = ''; + + # 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 + # * left no resizing, just left align. label is used for alt= only + # * right same, but right aligned + # * none same, but not aligned + # * ___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); + + $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL ); + $mwLeft =& MagicWord::get( MAG_IMG_LEFT ); + $mwRight =& MagicWord::get( MAG_IMG_RIGHT ); + $mwNone =& MagicWord::get( MAG_IMG_NONE ); + $mwWidth =& MagicWord::get( MAG_IMG_WIDTH ); + $mwCenter =& MagicWord::get( MAG_IMG_CENTER ); + $mwFramed =& MagicWord::get( MAG_IMG_FRAMED ); + $caption = ''; + + $width = $height = $framed = $thumb = false; + $manual_thumb = "" ; + + foreach( $part as $key => $val ) { + $val_parts = explode ( "=" , $val , 2 ) ; + $left_part = array_shift ( $val_parts ) ; + if ( $wgUseImageResize && ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) { + $thumb=true; + } elseif ( $wgUseImageResize && count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) { + # use manually specified thumbnail + $thumb=true; + $manual_thumb = array_shift ( $val_parts ) ; + } 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 ( $wgUseImageResize && ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) { + wfDebug( "MAG_IMG_WIDTH match: $match\n" ); + # $match is the image width in pixels + if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) { + $width = intval( $m[1] ); + $height = intval( $m[2] ); + } else { + $width = intval($match); + } + } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) { + $framed=true; + } else { + $caption = $val; + } + } + # Strip bad stuff out of the alt text + $alt = $caption; + $this->replaceLinkHolders( $alt ); + $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 ); + } } /** @@ -2992,7 +3141,7 @@ class Parser class ParserOutput { var $mText, $mLanguageLinks, $mCategoryLinks, $mContainsOldMagic; - var $mCacheTime; # Used in ParserCache + var $mCacheTime; # Timestamp on this article, or -1 for uncacheable. Used in ParserCache. var $mVersion; # Compatibility check var $mTitleText; # title text of the chosen language variant @@ -3040,7 +3189,8 @@ class ParserOutput */ function expired( $touched ) { global $wgCacheEpoch; - return $this->getCacheTime() <= $touched || + 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" ); @@ -3063,6 +3213,7 @@ class ParserOptions var $mDateFormat; # Date format index var $mEditSection; # Create "edit section" links var $mNumberHeadings; # Automatically number headings + var $mAllowSpecialInclusion; # Allow inclusion of special pages function getUseTeX() { return $this->mUseTeX; } function getUseDynamicDates() { return $this->mUseDynamicDates; } @@ -3072,6 +3223,8 @@ class ParserOptions function getDateFormat() { return $this->mDateFormat; } function getEditSection() { return $this->mEditSection; } function getNumberHeadings() { return $this->mNumberHeadings; } + function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; } + function setUseTeX( $x ) { return wfSetVar( $this->mUseTeX, $x ); } function setUseDynamicDates( $x ) { return wfSetVar( $this->mUseDynamicDates, $x ); } @@ -3080,9 +3233,15 @@ class ParserOptions 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 setSkin( &$x ) { $this->mSkin =& $x; } + function ParserOptions() { + global $wgUser; + $this->initialiseFromUser( $wgUser ); + } + /** * Get parser options * @static @@ -3095,7 +3254,8 @@ class ParserOptions /** Get user options */ function initialiseFromUser( &$userInput ) { - global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages; + global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages, + $wgAllowSpecialInclusion; $fname = 'ParserOptions::initialiseFromUser'; wfProfileIn( $fname ); if ( !$userInput ) { @@ -3115,6 +3275,7 @@ class ParserOptions $this->mDateFormat = $user->getOption( 'date' ); $this->mEditSection = $user->getOption( 'editsection' ); $this->mNumberHeadings = $user->getOption( 'numberheadings' ); + $this->mAllowSpecialInclusion = $wgAllowSpecialInclusion; wfProfileOut( $fname ); } } @@ -3123,9 +3284,9 @@ class ParserOptions * Callback function used by Parser::replaceLinkHolders() * to substitute link placeholders. */ -function &outputReplaceMatches( $matches ) { - global $outputReplace; - return $outputReplace[$matches[1]]; +function &wfOutputReplaceMatches( $matches ) { + global $wgOutputReplace; + return $wgOutputReplace[$matches[1]]; } /**