| Index: trunk/phase3/includes/MagicWord.php | ||
| — | — | @@ -69,6 +69,7 @@ |
| 70 | 70 | 'MAG_UC', |
| 71 | 71 | 'MAG_FULLPAGENAME', |
| 72 | 72 | 'MAG_FULLPAGENAMEE', |
| 73 | + 'MAG_RAW', | |
| 73 | 74 | ); |
| 74 | 75 | if ( ! defined( 'MEDIAWIKI_INSTALL' ) ) |
| 75 | 76 | wfRunHooks( 'MagicWordMagicWords', array( &$magicWords ) ); |
| Index: trunk/phase3/includes/Title.php | ||
| — | — | @@ -494,7 +494,7 @@ |
| 495 | 495 | function isTrans() { |
| 496 | 496 | global $wgTitleInterwikiCache, $wgDBname; |
| 497 | 497 | |
| 498 | ||
| 498 | + if ($this->mInterwiki == '') | |
| 499 | 499 | return false; |
| 500 | 500 | # Make sure key is loaded into cache |
| 501 | 501 | $this->getInterwikiLink( $this->mInterwiki ); |
| — | — | @@ -752,6 +752,13 @@ |
| 753 | 753 | |
| 754 | 754 | if ( $this->isExternal() ) { |
| 755 | 755 | $url = $this->getFullURL(); |
| 756 | + if ( $query ) { | |
| 757 | + // This is currently only used for edit section links in the | |
| 758 | + // context of interwiki transclusion. In theory we should | |
| 759 | + // append the query to the end of any existing query string, | |
| 760 | + // but interwiki transclusion is already broken in that case. | |
| 761 | + $url .= "?$query"; | |
| 762 | + } | |
| 756 | 763 | } else { |
| 757 | 764 | $dbkey = wfUrlencode( $this->getPrefixedDBkey() ); |
| 758 | 765 | if ( $query == '' ) { |
| — | — | @@ -1344,6 +1351,13 @@ |
| 1345 | 1352 | # Do another namespace split... |
| 1346 | 1353 | continue; |
| 1347 | 1354 | } |
| 1355 | + | |
| 1356 | + # If there's an initial colon after the interwiki, that also | |
| 1357 | + # resets the default namespace | |
| 1358 | + if ( $t !== '' && $t[0] == ':' ) { | |
| 1359 | + $this->mNamespace = NS_MAIN; | |
| 1360 | + $t = substr( $t, 1 ); | |
| 1361 | + } | |
| 1348 | 1362 | } |
| 1349 | 1363 | # If there's no recognized interwiki or namespace, |
| 1350 | 1364 | # then let the colon expression be part of the title. |
| Index: trunk/phase3/includes/HttpFunctions.php | ||
| — | — | @@ -9,7 +9,7 @@ |
| 10 | 10 | * if $timeout is 'default', $wgHTTPTimeout is used |
| 11 | 11 | */ |
| 12 | 12 | function wfGetHTTP( $url, $timeout = 'default' ) { |
| 13 | ||
| 13 | + global $wgHTTPTimeout, $wgHTTPProxy, $wgVersion, $wgTitle, $wgCommandLineMode; | |
| 14 | 14 | |
| 15 | 15 | # Use curl if available |
| 16 | 16 | if ( function_exists( 'curl_init' ) ) { |
| — | — | @@ -25,6 +25,16 @@ |
| 26 | 26 | } |
| 27 | 27 | curl_setopt( $c, CURLOPT_TIMEOUT, $timeout ); |
| 28 | 28 | curl_setopt( $c, CURLOPT_USERAGENT, "MediaWiki/$wgVersion" ); |
| 29 | + | |
| 30 | + # Set the referer to $wgTitle, even in command-line mode | |
| 31 | + # This is useful for interwiki transclusion, where the foreign | |
| 32 | + # server wants to know what the referring page is. | |
| 33 | + # $_SERVER['REQUEST_URI'] gives a less reliable indication of the | |
| 34 | + # referring page. | |
| 35 | + if ( is_object( $wgTitle ) ) { | |
| 36 | + curl_setopt( $c, CURLOPT_REFERER, $wgTitle->getFullURL() ); | |
| 37 | + } | |
| 38 | + | |
| 29 | 39 | ob_start(); |
| 30 | 40 | curl_exec( $c ); |
| 31 | 41 | $text = ob_get_contents(); |
| Index: trunk/phase3/includes/Parser.php | ||
| — | — | @@ -2253,9 +2253,10 @@ |
| 2254 | 2254 | * |
| 2255 | 2255 | * @param string $tex The text to transform |
| 2256 | 2256 | * @param array $args Key-value pairs representing template parameters to substitute |
| 2257 | + * @param bool $argsOnly Only do argument (triple-brace) expansion, not double-brace expansion | |
| 2257 | 2258 | * @access private |
| 2258 | 2259 | */ |
| 2259 | ||
| 2260 | + function replaceVariables( $text, $args = array(), $argsOnly = false ) { | |
| 2260 | 2261 | # Prevent too big inclusions |
| 2261 | 2262 | if( strlen( $text ) > MAX_INCLUDE_SIZE ) { |
| 2262 | 2263 | return $text; |
| — | — | @@ -2268,7 +2269,9 @@ |
| 2269 | 2270 | array_push( $this->mArgStack, $args ); |
| 2270 | 2271 | |
| 2271 | 2272 | $braceCallbacks = array(); |
| 2272 | ||
| 2273 | + if ( !$argsOnly ) { | |
| 2274 | + $braceCallbacks[2] = array( &$this, 'braceSubstitution' ); | |
| 2275 | + } | |
| 2273 | 2276 | if ( $this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI ) { |
| 2274 | 2277 | $braceCallbacks[3] = array( &$this, 'argSubstitution' ); |
| 2275 | 2278 | } |
| — | — | @@ -2356,12 +2359,16 @@ |
| 2357 | 2360 | $fname = 'Parser::braceSubstitution'; |
| 2358 | 2361 | wfProfileIn( $fname ); |
| 2359 | 2362 | |
| 2360 | ||
| 2361 | ||
| 2362 | ||
| 2363 | ||
| 2364 | ||
| 2363 | + # Flags | |
| 2364 | + $found = false; # $text has been filled | |
| 2365 | + $nowiki = false; # wiki markup in $text should be escaped | |
| 2366 | + $noparse = false; # Unsafe HTML tags should not be stripped, etc. | |
| 2367 | + $noargs = false; # Don't replace triple-brace arguments in $text | |
| 2368 | + $replaceHeadings = false; # Make the edit section links go to the template not the article | |
| 2369 | + $isHTML = false; # $text is HTML, armour it against wikitext transformation | |
| 2370 | + $forceRawInterwiki = false; # Force interwiki transclusion to be done in raw mode not rendered | |
| 2365 | 2371 | |
| 2372 | + # Title object, where $text came from | |
| 2366 | 2373 | $title = NULL; |
| 2367 | 2374 | |
| 2368 | 2375 | $linestart = ''; |
| — | — | @@ -2378,6 +2385,7 @@ |
| 2379 | 2386 | $text = $replaceWith; |
| 2380 | 2387 | $found = true; |
| 2381 | 2388 | $noparse = true; |
| 2389 | + $noargs = true; | |
| 2382 | 2390 | } |
| 2383 | 2391 | } |
| 2384 | 2392 | |
| — | — | @@ -2395,10 +2403,11 @@ |
| 2396 | 2404 | $text = $piece['text']; |
| 2397 | 2405 | $found = true; |
| 2398 | 2406 | $noparse = true; |
| 2407 | + $noargs = true; | |
| 2399 | 2408 | } |
| 2400 | 2409 | } |
| 2401 | 2410 | |
| 2402 | ||
| 2411 | + # MSG, MSGNW, INT and RAW | |
| 2403 | 2412 | if ( !$found ) { |
| 2404 | 2413 | # Check for MSGNW: |
| 2405 | 2414 | $mwMsgnw =& MagicWord::get( MAG_MSGNW ); |
| — | — | @@ -2409,7 +2418,13 @@ |
| 2410 | 2419 | $mwMsg =& MagicWord::get( MAG_MSG ); |
| 2411 | 2420 | $mwMsg->matchStartAndRemove( $part1 ); |
| 2412 | 2421 | } |
| 2413 | ||
| 2422 | + | |
| 2423 | + # Check for RAW: | |
| 2424 | + $mwRaw =& MagicWord::get( MAG_RAW ); | |
| 2425 | + if ( $mwRaw->matchStartAndRemove( $part1 ) ) { | |
| 2426 | + $forceRawInterwiki = true; | |
| 2427 | + } | |
| 2428 | + | |
| 2414 | 2429 | # Check if it is an internal message |
| 2415 | 2430 | $mwInt =& MagicWord::get( MAG_INT ); |
| 2416 | 2431 | if ( $mwInt->matchStartAndRemove( $part1 ) ) { |
| — | — | @@ -2515,12 +2530,13 @@ |
| 2516 | 2531 | |
| 2517 | 2532 | # Did we encounter this template already? If yes, it is in the cache |
| 2518 | 2533 | # and we need to check for loops. |
| 2519 | ||
| 2534 | + if ( !$found && isset( $this->mTemplates[$piece['title']] ) ) { | |
| 2520 | 2535 | $found = true; |
| 2521 | 2536 | |
| 2522 | 2537 | # Infinite loop test |
| 2523 | 2538 | if ( isset( $this->mTemplatePath[$part1] ) ) { |
| 2524 | 2539 | $noparse = true; |
| 2540 | + $noargs = true; | |
| 2525 | 2541 | $found = true; |
| 2526 | 2542 | $text = $linestart . |
| 2527 | 2543 | '{{' . $part1 . '}}' . |
| — | — | @@ -2528,7 +2544,7 @@ |
| 2529 | 2545 | wfDebug( "$fname: template loop broken at '$part1'\n" ); |
| 2530 | 2546 | } else { |
| 2531 | 2547 | # set $text to cached message. |
| 2532 | ||
| 2548 | + $text = $linestart . $this->mTemplates[$piece['title']]; | |
| 2533 | 2549 | } |
| 2534 | 2550 | } |
| 2535 | 2551 | |
| — | — | @@ -2553,6 +2569,7 @@ |
| 2554 | 2570 | if ( is_string( $text ) ) { |
| 2555 | 2571 | $found = true; |
| 2556 | 2572 | $noparse = true; |
| 2573 | + $noargs = true; | |
| 2557 | 2574 | $isHTML = true; |
| 2558 | 2575 | $this->disableCache(); |
| 2559 | 2576 | } |
| — | — | @@ -2571,23 +2588,26 @@ |
| 2572 | 2589 | $text = '[['.$title->getPrefixedText().']]'; |
| 2573 | 2590 | $found = true; |
| 2574 | 2591 | } |
| 2575 | ||
| 2576 | ||
| 2577 | ||
| 2578 | ||
| 2579 | ||
| 2580 | ||
| 2581 | 2592 | } elseif ( $title->isTrans() ) { |
| 2582 | 2593 | // Interwiki transclusion |
| 2583 | ||
| 2594 | + if ( $this->mOutputType == OT_HTML && !$forceRawInterwiki ) { | |
| 2584 | 2595 | $text = $this->interwikiTransclude( $title, 'render' ); |
| 2585 | 2596 | $isHTML = true; |
| 2586 | 2597 | $noparse = true; |
| 2587 | 2598 | } else { |
| 2588 | 2599 | $text = $this->interwikiTransclude( $title, 'raw' ); |
| 2600 | + $replaceHeadings = true; | |
| 2589 | 2601 | } |
| 2590 | 2602 | $found = true; |
| 2591 | 2603 | } |
| 2604 | + | |
| 2605 | + # Template cache array insertion | |
| 2606 | + # Use the original $piece['title'] not the mangled $part1, so that | |
| 2607 | + # modifiers such as RAW: produce separate cache entries | |
| 2608 | + if( $found ) { | |
| 2609 | + $this->mTemplates[$piece['title']] = $text; | |
| 2610 | + $text = $linestart . $text; | |
| 2611 | + } | |
| 2592 | 2612 | } |
| 2593 | 2613 | } |
| 2594 | 2614 | |
| — | — | @@ -2595,52 +2615,61 @@ |
| 2596 | 2616 | # Only for HTML output |
| 2597 | 2617 | if ( $nowiki && $found && $this->mOutputType == OT_HTML ) { |
| 2598 | 2618 | $text = wfEscapeWikiText( $text ); |
| 2599 | ||
| 2600 | ||
| 2601 | ||
| 2602 | ||
| 2603 | ||
| 2604 | ||
| 2605 | ||
| 2606 | ||
| 2607 | ||
| 2608 | ||
| 2609 | ||
| 2610 | ||
| 2611 | ||
| 2619 | + } elseif ( ($this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI) && $found ) { | |
| 2620 | + if ( !$noargs ) { | |
| 2621 | + # Clean up argument array | |
| 2622 | + $assocArgs = array(); | |
| 2623 | + $index = 1; | |
| 2624 | + foreach( $args as $arg ) { | |
| 2625 | + $eqpos = strpos( $arg, '=' ); | |
| 2626 | + if ( $eqpos === false ) { | |
| 2627 | + $assocArgs[$index++] = $arg; | |
| 2628 | + } else { | |
| 2629 | + $name = trim( substr( $arg, 0, $eqpos ) ); | |
| 2630 | + $value = trim( substr( $arg, $eqpos+1 ) ); | |
| 2631 | + if ( $value === false ) { | |
| 2632 | + $value = ''; | |
| 2633 | + } | |
| 2634 | + if ( $name !== false ) { | |
| 2635 | + $assocArgs[$name] = $value; | |
| 2636 | + } | |
| 2612 | 2637 | } |
| 2613 | ||
| 2614 | ||
| 2615 | ||
| 2616 | 2638 | } |
| 2639 | + | |
| 2640 | + # Add a new element to the templace recursion path | |
| 2641 | + $this->mTemplatePath[$part1] = 1; | |
| 2617 | 2642 | } |
| 2618 | 2643 | |
| 2619 | ||
| 2620 | ||
| 2644 | + if ( !$noparse ) { | |
| 2645 | + # If there are any <onlyinclude> tags, only include them | |
| 2646 | + if ( in_string( '<onlyinclude>', $text ) && in_string( '</onlyinclude>', $text ) ) { | |
| 2647 | + preg_match_all( '/<onlyinclude>(.*?)\n?<\/onlyinclude>/s', $text, $m ); | |
| 2648 | + $text = ''; | |
| 2649 | + foreach ($m[1] as $piece) | |
| 2650 | + $text .= $piece; | |
| 2651 | + } | |
| 2652 | + # Remove <noinclude> sections and <includeonly> tags | |
| 2653 | + $text = preg_replace( '/<noinclude>.*?<\/noinclude>/s', '', $text ); | |
| 2654 | + $text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) ); | |
| 2621 | 2655 | |
| 2622 | ||
| 2623 | ||
| 2624 | ||
| 2625 | ||
| 2626 | ||
| 2627 | ||
| 2628 | ||
| 2629 | ||
| 2630 | ||
| 2631 | ||
| 2656 | + if( $this->mOutputType == OT_HTML ) { | |
| 2657 | + # Strip <nowiki>, <pre>, etc. | |
| 2658 | + $text = $this->strip( $text, $this->mStripState ); | |
| 2659 | + $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $assocArgs ); | |
| 2660 | + } | |
| 2661 | + $text = $this->replaceVariables( $text, $assocArgs ); | |
| 2632 | 2662 | |
| 2633 | ||
| 2634 | ||
| 2635 | ||
| 2636 | ||
| 2663 | + # If the template begins with a table or block-level | |
| 2664 | + # element, it should be treated as beginning a new line. | |
| 2665 | + if (!$piece['lineStart'] && preg_match('/^({\\||:|;|#|\*)/', $text)) { | |
| 2666 | + $text = "\n" . $text; | |
| 2667 | + } | |
| 2668 | + } elseif ( !$noargs ) { | |
| 2669 | + # $noparse and !$noargs | |
| 2670 | + # Just replace the arguments, not any double-brace items | |
| 2671 | + # This is used for rendered interwiki transclusion | |
| 2672 | + $text = $this->replaceVariables( $text, $assocArgs, true ); | |
| 2637 | 2673 | } |
| 2638 | ||
| 2639 | ||
| 2640 | ||
| 2641 | ||
| 2642 | ||
| 2643 | ||
| 2644 | ||
| 2645 | 2674 | } |
| 2646 | 2675 | # Prune lower levels off the recursion check path |
| 2647 | 2676 | $this->mTemplatePath = $lastPathLevel; |
| Index: trunk/phase3/RELEASE-NOTES | ||
| — | — | @@ -258,6 +258,7 @@ |
| 259 | 259 | character before doing anything with them. This prevents certain kinds of |
| 260 | 260 | spam filter evasion. |
| 261 | 261 | * (bug 4783) : Fix for "{{ns:0}} does not render" |
| 262 | +* Improved support for interwiki transclusion | |
| 262 | 263 | |
| 263 | 264 | Upload: |
| 264 | 265 | * (bug 2527) Always set destination filename when new file is selected |
| Index: trunk/phase3/languages/Language.php | ||
| — | — | @@ -253,10 +253,11 @@ |
| 254 | 254 | MAG_PLURAL => array( 0, 'PLURAL:' ), |
| 255 | 255 | MAG_FULLURL => array( 0, 'FULLURL:' ), |
| 256 | 256 | MAG_FULLURLE => array( 0, 'FULLURLE:' ), |
| 257 | ||
| 258 | ||
| 259 | ||
| 260 | ||
| 257 | + MAG_LCFIRST => array( 0, 'LCFIRST:' ), | |
| 258 | + MAG_UCFIRST => array( 0, 'UCFIRST:' ), | |
| 259 | + MAG_LC => array( 0, 'LC:' ), | |
| 260 | + MAG_UC => array( 0, 'UC:' ), | |
| 261 | + MAG_RAW => array( 0, 'RAW:' ), | |
| 261 | 262 | ); |
| 262 | 263 | |
| 263 | 264 | if (!$wgCachedMessageArrays) { |
US