Index: branches/conrad/phase3/maintenance/parserTests.txt |
— | — | @@ -2022,6 +2022,41 @@ |
2023 | 2023 | !! end |
2024 | 2024 | |
2025 | 2025 | !! test |
| 2026 | +Magic Word: {{PIPETRICK}} |
| 2027 | +!! options |
| 2028 | +title=[[Some (page)]] |
| 2029 | +!! input |
| 2030 | +{{PIPETRICK}} |
| 2031 | +{{PIPETRICK:Hello (one)}} |
| 2032 | +{{PIPETRICK:World, hi|}} |
| 2033 | +{{PIPETRICK:|Other}} |
| 2034 | +!! result |
| 2035 | +<p>Some |
| 2036 | +Hello |
| 2037 | +World |
| 2038 | +Other (page) |
| 2039 | +</p> |
| 2040 | +!! end |
| 2041 | + |
| 2042 | +!! test |
| 2043 | +Magic Word: {{PIPETRICKE}} |
| 2044 | +!! options |
| 2045 | +title=[[Some other (page)]] |
| 2046 | +!! input |
| 2047 | +{{PIPETRICKE}} |
| 2048 | +{{PIPETRICKE:User:Ævar Arnfjörð Bjarmason}} |
| 2049 | +{{PIPETRICKE:#Something to do|}} |
| 2050 | +{{PIPETRICKE:|The?last}} |
| 2051 | +!! result |
| 2052 | +<p>Some_other |
| 2053 | +%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason |
| 2054 | +Something_to_do |
| 2055 | +The%3Flast_(page) |
| 2056 | +</p> |
| 2057 | +!! end |
| 2058 | + |
| 2059 | + |
| 2060 | +!! test |
2026 | 2061 | Magic Word: {{REVISIONID}} |
2027 | 2062 | !! input |
2028 | 2063 | {{REVISIONID}} |
— | — | @@ -2999,6 +3034,48 @@ |
3000 | 3035 | !! end |
3001 | 3036 | |
3002 | 3037 | !! test |
| 3038 | +pre-save transform: context links ("pipe trick") based on current page |
| 3039 | +!! options |
| 3040 | +pst |
| 3041 | +!! input |
| 3042 | +[[#section|]] |
| 3043 | +[[#section (context)|]] |
| 3044 | +[[/relative|]] |
| 3045 | +[[../context/relative|]] |
| 3046 | +[[../context/relative (extra)|]] |
| 3047 | +!! result |
| 3048 | +[[#section|section]] |
| 3049 | +[[#section (context)|section]] |
| 3050 | +[[/relative|relative]] |
| 3051 | +[[../context/relative|relative]] |
| 3052 | +[[../context/relative (extra)|relative]] |
| 3053 | +!! end |
| 3054 | + |
| 3055 | +!! test |
| 3056 | +pre-save transform: context links ("pipe trick") to sections on other pages |
| 3057 | +!! options |
| 3058 | +pst |
| 3059 | +!! input |
| 3060 | +[[other#page|]] |
| 3061 | +[[Help:Somewhere/completely (wierd)#section (two)|]] |
| 3062 | +!! result |
| 3063 | +[[other#page|page]] |
| 3064 | +[[Help:Somewhere/completely (wierd)#section (two)|section]] |
| 3065 | +!! end |
| 3066 | + |
| 3067 | +!! test |
| 3068 | +pre-save transform: context links ("pipe trick") with full-width characters |
| 3069 | +!! options |
| 3070 | +pst |
| 3071 | +!! input |
| 3072 | +[[title, context|]] |
| 3073 | +[[title (context)|]] |
| 3074 | +!! result |
| 3075 | +[[title, context|title]] |
| 3076 | +[[title (context)|title]] |
| 3077 | +!! end |
| 3078 | + |
| 3079 | +!! test |
3003 | 3080 | pre-save transform: context links ("pipe trick") with interwiki prefix |
3004 | 3081 | !! options |
3005 | 3082 | pst |
— | — | @@ -3112,7 +3189,66 @@ |
3113 | 3190 | [[Ns:Article, Context|Article]] |
3114 | 3191 | !! end |
3115 | 3192 | |
| 3193 | +!! test |
| 3194 | +pre-save transform: context links ("pipe trick") with url escaped page names |
| 3195 | +!! options |
| 3196 | +pst |
| 3197 | +!! input |
| 3198 | +[[Hello wo%52ld|]] |
| 3199 | +[[Hello wo%52ld (again)|]] |
| 3200 | +!! result |
| 3201 | +[[Hello wo%52ld|Hello woRld]] |
| 3202 | +[[Hello wo%52ld (again)|Hello woRld]] |
| 3203 | +!! end |
3116 | 3204 | |
| 3205 | +!! test |
| 3206 | +pre-save transform: context links ("pipe trick") with variables are not pre-empted |
| 3207 | +!! options |
| 3208 | +pst title=[[Test (page)]] |
| 3209 | +!! input |
| 3210 | +[[{{{1|}}}|]] |
| 3211 | +[[|{{{1|}}}]] |
| 3212 | +[[{{subst:PAGENAME}}|]] |
| 3213 | +!! result |
| 3214 | +[[{{{1|}}}|]] |
| 3215 | +[[|{{{1|}}}]] |
| 3216 | +[[Test (page)|Test]] |
| 3217 | +!! end |
| 3218 | + |
| 3219 | +!! article |
| 3220 | +Template:pipetest |
| 3221 | +!! text |
| 3222 | +[[{{{1}}}|]] |
| 3223 | +!! endarticle |
| 3224 | + |
| 3225 | +!! article |
| 3226 | +Template:testpipe |
| 3227 | +!! text |
| 3228 | +[[|{{{1}}}]] |
| 3229 | +!! endarticle |
| 3230 | + |
| 3231 | +!! test |
| 3232 | +("pipe trick") should work outside PST |
| 3233 | +!!options |
| 3234 | +title=[[Help:hello (world)]] |
| 3235 | +!! input |
| 3236 | +{{pipetest|hi (world)}} |
| 3237 | +{{pipetest|hi (world), world}} |
| 3238 | +{{pipetest|Help:hi (world), world}} |
| 3239 | +{{pipetest|:Help:hi (world), world}} |
| 3240 | +{{testpipe|hi}} |
| 3241 | +[[{{PAGENAME}}|]] |
| 3242 | +!! result |
| 3243 | +<p><a href="https://www.mediawiki.org/index.php?title=Hi_(world)&action=edit&redlink=1" class="new" title="Hi (world) (page does not exist)">hi</a> |
| 3244 | +<a href="https://www.mediawiki.org/index.php?title=Hi_(world),_world&action=edit&redlink=1" class="new" title="Hi (world), world (page does not exist)">hi</a> |
| 3245 | +<a href="https://www.mediawiki.org/index.php?title=Help:Hi_(world),_world&action=edit&redlink=1" class="new" title="Help:Hi (world), world (page does not exist)">hi</a> |
| 3246 | +<a href="https://www.mediawiki.org/index.php?title=Help:Hi_(world),_world&action=edit&redlink=1" class="new" title="Help:Hi (world), world (page does not exist)">hi</a> |
| 3247 | +<a href="https://www.mediawiki.org/index.php?title=Hi_(world)&action=edit&redlink=1" class="new" title="Hi (world) (page does not exist)">hi</a> |
| 3248 | +<a href="https://www.mediawiki.org/index.php?title=Hello_(world)&action=edit&redlink=1" class="new" title="Hello (world) (page does not exist)">Hello</a> |
| 3249 | +</p> |
| 3250 | +!! end |
| 3251 | + |
| 3252 | + |
3117 | 3253 | ### |
3118 | 3254 | ### Message transform tests |
3119 | 3255 | ### |
— | — | @@ -7609,6 +7745,17 @@ |
7610 | 7746 | <a href="https://www.mediawiki.org/wiki/Main_Page#section" title="Main Page">#section</a> |
7611 | 7747 | !! end |
7612 | 7748 | |
| 7749 | +!! test |
| 7750 | +Edit comment with pipe trick |
| 7751 | +!! options |
| 7752 | +comment |
| 7753 | +title=[[Article (context)]] |
| 7754 | +!! input |
| 7755 | +[[Hello (World)|]] [[|Entry]] |
| 7756 | +!! result |
| 7757 | +<a href="https://www.mediawiki.org/index.php?title=Hello_(World)&action=edit&redlink=1" class="new" title="Hello (World) (page does not exist)">Hello</a> <a href="https://www.mediawiki.org/index.php?title=Entry_(context)&action=edit&redlink=1" class="new" title="Entry (context) (page does not exist)">Entry</a> |
| 7758 | +!! end |
| 7759 | + |
7613 | 7760 | !!article |
7614 | 7761 | MediaWiki:bad image list |
7615 | 7762 | !!text |
Index: branches/conrad/phase3/includes/parser/Parser.php |
— | — | @@ -15,7 +15,7 @@ |
16 | 16 | * (which in turn the browser understands, and can display). |
17 | 17 | * |
18 | 18 | * <pre> |
19 | | - * There are five main entry points into the Parser class: |
| 19 | + * There are six main entry points into the Parser class: |
20 | 20 | * parse() |
21 | 21 | * produces HTML output |
22 | 22 | * preSaveTransform(). |
— | — | @@ -26,6 +26,8 @@ |
27 | 27 | * Cleans a signature before saving it to preferences |
28 | 28 | * extractSections() |
29 | 29 | * Extracts sections from an article for section editing |
| 30 | + * getTransclusionText() |
| 31 | + * Extracts the text of a template with only <includeonly>, etc., parsed |
30 | 32 | * |
31 | 33 | * Globals used: |
32 | 34 | * objects: $wgLang, $wgContLang |
— | — | @@ -82,6 +84,7 @@ |
83 | 85 | const OT_WIKI = 2; |
84 | 86 | const OT_PREPROCESS = 3; |
85 | 87 | const OT_MSG = 3; |
| 88 | + const OT_INCLUDES = 4; |
86 | 89 | |
87 | 90 | // Marker Suffix needs to be accessible staticly. |
88 | 91 | const MARKER_SUFFIX = "-QINU\x7f"; |
— | — | @@ -368,24 +371,29 @@ |
369 | 372 | |
370 | 373 | wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) ); |
371 | 374 | |
372 | | -//!JF Move to its own function |
| 375 | + if ( $this->mTransparentTagHooks ) { |
| 376 | + //!JF Move to its own function |
| 377 | + $uniq_prefix = $this->mUniqPrefix; |
| 378 | + $matches = array(); |
| 379 | + $elements = array_keys( $this->mTransparentTagHooks ); |
| 380 | + $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix ); |
373 | 381 | |
374 | | - $uniq_prefix = $this->mUniqPrefix; |
375 | | - $matches = array(); |
376 | | - $elements = array_keys( $this->mTransparentTagHooks ); |
377 | | - $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix ); |
378 | | - |
379 | | - foreach( $matches as $marker => $data ) { |
380 | | - list( $element, $content, $params, $tag ) = $data; |
381 | | - $tagName = strtolower( $element ); |
382 | | - if( isset( $this->mTransparentTagHooks[$tagName] ) ) { |
383 | | - $output = call_user_func_array( $this->mTransparentTagHooks[$tagName], |
384 | | - array( $content, $params, $this ) ); |
385 | | - } else { |
386 | | - $output = $tag; |
| 382 | + foreach( $matches as $marker => $data ) { |
| 383 | + list( $element, $content, $params, $tag ) = $data; |
| 384 | + $tagName = strtolower( $element ); |
| 385 | + if( isset( $this->mTransparentTagHooks[$tagName] ) ) { |
| 386 | + $output = call_user_func_array( $this->mTransparentTagHooks[$tagName], |
| 387 | + array( $content, $params, $this ) ); |
| 388 | + } else { |
| 389 | + $output = $tag; |
| 390 | + } |
| 391 | + $this->mStripState->general->setPair( $marker, $output ); |
387 | 392 | } |
388 | | - $this->mStripState->general->setPair( $marker, $output ); |
389 | 393 | } |
| 394 | + |
| 395 | + # This was originally inserted for transparent tag hooks (now deprecated) |
| 396 | + # but some extensions (notably <poem>) rely on the extra unstripGeneral() |
| 397 | + # after unstripNoWiki() so they can modify the contents of <nowiki> tags. |
390 | 398 | $text = $this->mStripState->unstripGeneral( $text ); |
391 | 399 | |
392 | 400 | $text = Sanitizer::normalizeCharReferences( $text ); |
— | — | @@ -490,6 +498,26 @@ |
491 | 499 | } |
492 | 500 | |
493 | 501 | /** |
| 502 | + * Get the wikitext of a page as though it was transcluded. |
| 503 | + * |
| 504 | + * Specifically <includeonly> etc. are parsed, redirects are followed, comments |
| 505 | + * are removed, but templates arguments and parser functions are untouched. |
| 506 | + * |
| 507 | + * This is not called by the parser itself, see braceSubstitution for its transclusion. |
| 508 | + */ |
| 509 | + public function getTransclusionText( $title, $options ) { |
| 510 | + // Must initialize first |
| 511 | + $this->clearState(); |
| 512 | + $this->setOutputType( self::OT_INCLUDES ); |
| 513 | + $this->mOptions = $options; |
| 514 | + $this->setTitle( new FakeTitle ); |
| 515 | + |
| 516 | + list( $text, $title ) = $this->getTemplateDom( $title ); |
| 517 | + $flags = PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES; |
| 518 | + return $this->getPreprocessor()->newFrame()->expand( $text, $flags ); |
| 519 | + } |
| 520 | + |
| 521 | + /** |
494 | 522 | * Get a random string |
495 | 523 | * |
496 | 524 | * @private |
— | — | @@ -1494,7 +1522,7 @@ |
1495 | 1523 | if ( !$tc ) { |
1496 | 1524 | $tc = Title::legalChars() . '#%'; |
1497 | 1525 | # Match a link having the form [[namespace:link|alternate]]trail |
1498 | | - $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; |
| 1526 | + $e1 = "/^([{$tc}]*)(\\|.*?)?]](.*)\$/sD"; |
1499 | 1527 | # Match cases where there is no "]]", which might still be images |
1500 | 1528 | $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; |
1501 | 1529 | } |
— | — | @@ -1574,7 +1602,15 @@ |
1575 | 1603 | |
1576 | 1604 | wfProfileIn( __METHOD__."-e1" ); |
1577 | 1605 | if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt |
1578 | | - $text = $m[2]; |
| 1606 | + |
| 1607 | + if( $m[2] === '' ) { |
| 1608 | + $text = ''; |
| 1609 | + } elseif( $m[2] === '|' ) { |
| 1610 | + $text = $this->getPipeTrickText( $m[1] ); |
| 1611 | + } else { |
| 1612 | + $text = substr( $m[2], 1 ); |
| 1613 | + } |
| 1614 | + |
1579 | 1615 | # If we get a ] at the beginning of $m[3] that means we have a link that's something like: |
1580 | 1616 | # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row fucks up, |
1581 | 1617 | # the real problem is with the $e1 regex |
— | — | @@ -1591,18 +1627,20 @@ |
1592 | 1628 | $text .= ']'; # so that replaceExternalLinks($text) works later |
1593 | 1629 | $m[3] = substr( $m[3], 1 ); |
1594 | 1630 | } |
| 1631 | + |
| 1632 | + # Handle pipe-trick for [[|<blah>]] |
| 1633 | + $lnk = $m[1] === '' ? $this->getPipeTrickLink( $text ) : $m[1]; |
1595 | 1634 | # fix up urlencoded title texts |
1596 | | - if( strpos( $m[1], '%' ) !== false ) { |
| 1635 | + if( strpos( $lnk, '%' ) !== false ) { |
1597 | 1636 | # Should anchors '#' also be rejected? |
1598 | | - $m[1] = str_replace( array('<', '>'), array('<', '>'), urldecode($m[1]) ); |
| 1637 | + $lnk = str_replace( array('<', '>'), array('<', '>'), urldecode($lnk) ); |
1599 | 1638 | } |
| 1639 | + |
1600 | 1640 | $trail = $m[3]; |
1601 | 1641 | } elseif( preg_match($e1_img, $line, $m) ) { # Invalid, but might be an image with a link in its caption |
1602 | 1642 | $might_be_img = true; |
1603 | 1643 | $text = $m[2]; |
1604 | | - if ( strpos( $m[1], '%' ) !== false ) { |
1605 | | - $m[1] = urldecode($m[1]); |
1606 | | - } |
| 1644 | + $lnk = strpos( $m[1], '%' ) === false ? $m[1] : urldecode( $m[1] ); |
1607 | 1645 | $trail = ""; |
1608 | 1646 | } else { # Invalid form; output directly |
1609 | 1647 | $s .= $prefix . '[[' . $line ; |
— | — | @@ -1615,7 +1653,7 @@ |
1616 | 1654 | # Don't allow internal links to pages containing |
1617 | 1655 | # PROTO: where PROTO is a valid URL protocol; these |
1618 | 1656 | # should be external links. |
1619 | | - if ( preg_match( '/^\b(?:' . wfUrlProtocols() . ')/', $m[1] ) ) { |
| 1657 | + if ( preg_match( '/^\b(?:' . wfUrlProtocols() . ')/', $lnk ) ) { |
1620 | 1658 | $s .= $prefix . '[[' . $line ; |
1621 | 1659 | wfProfileOut( __METHOD__."-misc" ); |
1622 | 1660 | continue; |
— | — | @@ -1623,12 +1661,12 @@ |
1624 | 1662 | |
1625 | 1663 | # Make subpage if necessary |
1626 | 1664 | if ( $useSubpages ) { |
1627 | | - $link = $this->maybeDoSubpageLink( $m[1], $text ); |
| 1665 | + $link = $this->maybeDoSubpageLink( $lnk, $text ); |
1628 | 1666 | } else { |
1629 | | - $link = $m[1]; |
| 1667 | + $link = $lnk; |
1630 | 1668 | } |
1631 | 1669 | |
1632 | | - $noforce = (substr( $m[1], 0, 1 ) !== ':'); |
| 1670 | + $noforce = (substr( $lnk, 0, 1 ) !== ':'); |
1633 | 1671 | if (!$noforce) { |
1634 | 1672 | # Strip off leading ':' |
1635 | 1673 | $link = substr( $link, 1 ); |
— | — | @@ -1876,6 +1914,25 @@ |
1877 | 1915 | return Linker::normalizeSubpageLink( $this->mTitle, $target, $text ); |
1878 | 1916 | } |
1879 | 1917 | |
| 1918 | + /** |
| 1919 | + * From the [[title|]] return link-text as though the used typed [[title|link-text]] |
| 1920 | + * @param string $link from [[$link|]] |
| 1921 | + * @return string $text for [[$link|$text]] |
| 1922 | + */ |
| 1923 | + function getPipeTrickText( $link ) { |
| 1924 | + return Linker::getPipeTrickText( $link ); |
| 1925 | + } |
| 1926 | + |
| 1927 | + /** |
| 1928 | + * From the [[|link-text]] return the title as though the user typed [[title|link-text]] |
| 1929 | + * @param string $text from [[|$text]] |
| 1930 | + * @param Title $title to resolve the link against |
| 1931 | + * @return string $link for [[$link|$text]] |
| 1932 | + */ |
| 1933 | + function getPipeTrickLink( $text ) { |
| 1934 | + return Linker::getPipeTrickLink( $text, $this->mTitle ); |
| 1935 | + } |
| 1936 | + |
1880 | 1937 | /**#@+ |
1881 | 1938 | * Used by doBlockLevels() |
1882 | 1939 | * @private |
— | — | @@ -2438,6 +2495,14 @@ |
2439 | 2496 | $subjPage = $this->mTitle->getSubjectPage(); |
2440 | 2497 | $value = $subjPage->getPrefixedUrl(); |
2441 | 2498 | break; |
| 2499 | + case 'pipetrick': |
| 2500 | + $text = $this->mTitle->getText(); |
| 2501 | + $value = $this->getPipeTrickText( $text ); |
| 2502 | + break; |
| 2503 | + case 'pipetricke': |
| 2504 | + $text = $this->mTitle->getText(); |
| 2505 | + $value = wfUrlEncode( str_replace( ' ', '_', $this->getPipeTrickText( $text ) ) ); |
| 2506 | + break; |
2442 | 2507 | case 'revisionid': |
2443 | 2508 | // Let the edit saving system know we should parse the page |
2444 | 2509 | // *after* a revision ID has been assigned. |
— | — | @@ -3980,33 +4045,12 @@ |
3981 | 4046 | '~~~' => $sigText |
3982 | 4047 | ) ); |
3983 | 4048 | |
3984 | | - # Context links: [[|name]] and [[name (context)|]] |
3985 | | - # |
| 4049 | + # Links of the form [[|<blah>]] or [[<blah>|]] perform pipe tricks |
| 4050 | + # Note this only allows the # in the position it works. |
3986 | 4051 | global $wgLegalTitleChars; |
3987 | | - $tc = "[$wgLegalTitleChars]"; |
3988 | | - $nc = '[ _0-9A-Za-z\x80-\xff-]'; # Namespaces can use non-ascii! |
| 4052 | + $pipeTrickRe = "/\[\[(?:(\\|)([$wgLegalTitleChars]+)|([#$wgLegalTitleChars]+)\\|)\]\]/"; |
| 4053 | + $text = preg_replace_callback( $pipeTrickRe, array( $this, 'pstPipeTrickCallback' ), $text ); |
3989 | 4054 | |
3990 | | - $p1 = "/\[\[(:?$nc+:|:|)($tc+?)( \\($tc+\\))\\|]]/"; # [[ns:page (context)|]] |
3991 | | - $p4 = "/\[\[(:?$nc+:|:|)($tc+?)(($tc+))\\|]]/"; # [[ns:page(context)|]] |
3992 | | - $p3 = "/\[\[(:?$nc+:|:|)($tc+?)( \\($tc+\\)|)(, $tc+|)\\|]]/"; # [[ns:page (context), context|]] |
3993 | | - $p2 = "/\[\[\\|($tc+)]]/"; # [[|page]] |
3994 | | - |
3995 | | - # try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]" |
3996 | | - $text = preg_replace( $p1, '[[\\1\\2\\3|\\2]]', $text ); |
3997 | | - $text = preg_replace( $p4, '[[\\1\\2\\3|\\2]]', $text ); |
3998 | | - $text = preg_replace( $p3, '[[\\1\\2\\3\\4|\\2]]', $text ); |
3999 | | - |
4000 | | - $t = $this->mTitle->getText(); |
4001 | | - $m = array(); |
4002 | | - if ( preg_match( "/^($nc+:|)$tc+?( \\($tc+\\))$/", $t, $m ) ) { |
4003 | | - $text = preg_replace( $p2, "[[$m[1]\\1$m[2]|\\1]]", $text ); |
4004 | | - } elseif ( preg_match( "/^($nc+:|)$tc+?(, $tc+|)$/", $t, $m ) && "$m[1]$m[2]" != '' ) { |
4005 | | - $text = preg_replace( $p2, "[[$m[1]\\1$m[2]|\\1]]", $text ); |
4006 | | - } else { |
4007 | | - # if there's no context, don't bother duplicating the title |
4008 | | - $text = preg_replace( $p2, '[[\\1]]', $text ); |
4009 | | - } |
4010 | | - |
4011 | 4055 | # Trim trailing whitespace |
4012 | 4056 | $text = rtrim( $text ); |
4013 | 4057 | |
— | — | @@ -4014,6 +4058,25 @@ |
4015 | 4059 | } |
4016 | 4060 | |
4017 | 4061 | /** |
| 4062 | + * Called from pstPass2 to perform the pipe trick on links. |
| 4063 | + * Original was either [[|text]] or [[link|]] |
| 4064 | + * |
| 4065 | + * @param Array ("|" or "", text, link) $m |
| 4066 | + */ |
| 4067 | + function pstPipeTrickCallback( $m ) |
| 4068 | + { |
| 4069 | + if( $m[1] ) { # [[|<blah>]] |
| 4070 | + $text = $m[2]; |
| 4071 | + $link = $this->getPipeTrickLink( $text ); |
| 4072 | + } else { # [[<blah>|]] |
| 4073 | + $link = $m[3]; |
| 4074 | + $text = $this->getPipeTrickText( $link ); |
| 4075 | + } |
| 4076 | + |
| 4077 | + return $link === $text ? "[[$link]]" : "[[$link|$text]]"; |
| 4078 | + } |
| 4079 | + |
| 4080 | + /** |
4018 | 4081 | * Fetch the user's signature text, if any, and normalize to |
4019 | 4082 | * validated, ready-to-insert wikitext. |
4020 | 4083 | * If you have pre-fetched the nickname or the fancySig option, you can |
— | — | @@ -4193,7 +4256,9 @@ |
4194 | 4257 | return $oldVal; |
4195 | 4258 | } |
4196 | 4259 | |
| 4260 | + /* An old work-around for bug 2257 - deprecated 2010-02-13 */ |
4197 | 4261 | function setTransparentTagHook( $tag, $callback ) { |
| 4262 | + wfDeprecated( __METHOD__ ); |
4198 | 4263 | $tag = strtolower( $tag ); |
4199 | 4264 | $oldVal = isset( $this->mTransparentTagHooks[$tag] ) ? $this->mTransparentTagHooks[$tag] : null; |
4200 | 4265 | $this->mTransparentTagHooks[$tag] = $callback; |
Index: branches/conrad/phase3/includes/parser/CoreParserFunctions.php |
— | — | @@ -67,6 +67,8 @@ |
68 | 68 | $parser->setFunctionHook( 'talkpagenamee', array( __CLASS__, 'talkpagenamee' ), SFH_NO_HASH ); |
69 | 69 | $parser->setFunctionHook( 'subjectpagename', array( __CLASS__, 'subjectpagename' ), SFH_NO_HASH ); |
70 | 70 | $parser->setFunctionHook( 'subjectpagenamee', array( __CLASS__, 'subjectpagenamee' ), SFH_NO_HASH ); |
| 71 | + $parser->setFunctionHook( 'pipetrick', array( __CLASS__, 'pipetrick' ), SFH_NO_HASH ); |
| 72 | + $parser->setFunctionHook( 'pipetricke', array( __CLASS__, 'pipetricke' ), SFH_NO_HASH ); |
71 | 73 | $parser->setFunctionHook( 'tag', array( __CLASS__, 'tagObj' ), SFH_OBJECT_ARGS ); |
72 | 74 | $parser->setFunctionHook( 'formatdate', array( __CLASS__, 'formatDate' ) ); |
73 | 75 | |
— | — | @@ -440,6 +442,27 @@ |
441 | 443 | } |
442 | 444 | |
443 | 445 | /** |
| 446 | + * Performs the pipe trick in the same manner as [[title|]] or [[|title]]. |
| 447 | + * {{#pipetrick:title}} == {{#pipetrick:title|}} -> Parser::getPipeTrickText |
| 448 | + * {{#pipetrick:|title}} -> Parser::getPipeTrickLink (rarer) |
| 449 | + * See http://en.wikipedia.org/wiki/Help:Pipe_trick and the Parser documentation |
| 450 | + * for more information. |
| 451 | + */ |
| 452 | + static function pipetrick( $parser, $link = '', $text = '' ) { |
| 453 | + if ( $link ) |
| 454 | + return $parser->getPipeTrickText( $link ); |
| 455 | + else |
| 456 | + return $parser->getPipeTrickLink( $text ); |
| 457 | + } |
| 458 | + |
| 459 | + /** |
| 460 | + * Performs the pipetrick and then url encodes the result |
| 461 | + */ |
| 462 | + static function pipetricke( $parser, $link = '', $text = '' ) { |
| 463 | + return wfUrlEncode( str_replace( ' ', '_', self::pipetrick( $parser, $link, $text ) ) ); |
| 464 | + } |
| 465 | + |
| 466 | + /** |
444 | 467 | * Return the number of pages in the given category, or 0 if it's nonexis- |
445 | 468 | * tent. This is an expensive parser function and can't be called too many |
446 | 469 | * times per page. |
Index: branches/conrad/phase3/includes/Linker.php |
— | — | @@ -1086,6 +1086,11 @@ |
1087 | 1087 | # Handle link renaming [[foo|text]] will show link as "text" |
1088 | 1088 | if( $match[3] != "" ) { |
1089 | 1089 | $text = $match[3]; |
| 1090 | + if( $match[1] === "" && $this->commentContextTitle ) { |
| 1091 | + $match[1] = Linker::getPipeTrickLink( $text, $this->commentContextTitle ); |
| 1092 | + } |
| 1093 | + } elseif( $match[2] == "|" ) { |
| 1094 | + $text = Linker::getPipeTrickText( $match[1] ); |
1090 | 1095 | } else { |
1091 | 1096 | $text = $match[1]; |
1092 | 1097 | } |
— | — | @@ -1206,6 +1211,79 @@ |
1207 | 1212 | } |
1208 | 1213 | |
1209 | 1214 | /** |
| 1215 | + * Returns valid title characters and namespace characters for pipe trick. |
| 1216 | + * |
| 1217 | + * FIXME: the namespace characters should not be specified like this... |
| 1218 | + */ |
| 1219 | + static function getPipeTrickCharacterClasses() { |
| 1220 | + global $wgLegalTitleChars; |
| 1221 | + return array( "[$wgLegalTitleChars]", '[ _0-9A-Za-z\x80-\xff-]' ); |
| 1222 | + } |
| 1223 | + |
| 1224 | + /** |
| 1225 | + * From the [[title|]] return link-text as though the used typed [[title|link-text]] |
| 1226 | + * |
| 1227 | + * For most links this be as though the user typed [[ns:title|title]] |
| 1228 | + * However [[ns:title (context)|]], [[ns:title, context|]] and [[ns:title (context), context|]] |
| 1229 | + * [[#title (context)|]] [[../context/title (context), context|]] |
| 1230 | + * all return the |title]] with no context or indicative punctuation. |
| 1231 | + * |
| 1232 | + * @param string $link from [[$link|]] |
| 1233 | + * @return string $text for [[$link|$text]] |
| 1234 | + */ |
| 1235 | + static function getPipeTrickText( $link ) { |
| 1236 | + static $rexps = FALSE; |
| 1237 | + if( !$rexps ) { |
| 1238 | + list( $tc, $nc ) = Linker::getPipeTrickCharacterClasses(); |
| 1239 | + $rexps = array ( |
| 1240 | + # try this first, to turn "[[A, B (C)|]]" into "A, B" |
| 1241 | + "/^(:?$nc+:|[:#\/]|$tc+[\\/#]|)($tc+?)( \\($tc+\\)| ($tc+))$/", # [[ns:page (context)|]] |
| 1242 | + "/^(:?$nc+:|[:#\/]|$tc+[\\/#]|)($tc+?)( \\($tc+\\)| ($tc+)|)((?:,|,) $tc+|)$/", # [[ns:page (context), context|]] |
| 1243 | + ); |
| 1244 | + } |
| 1245 | + $text = urldecode( $link ); |
| 1246 | + |
| 1247 | + for( $i = 0; $i < count( $rexps ); $i++) { |
| 1248 | + if( preg_match( $rexps[$i], $text, $m ) ) |
| 1249 | + return $m[2]; |
| 1250 | + } |
| 1251 | + return $text; |
| 1252 | + } |
| 1253 | + |
| 1254 | + /** |
| 1255 | + * From the [[|link-text]] return the title as though the user typed [[title|link-text]] |
| 1256 | + * |
| 1257 | + * On most pages this will return link-text or "" if the link-text is not a valid title |
| 1258 | + * On pages like [[ns:title (context)]] and [[ns:title, context]] it will act like |
| 1259 | + * [[ns:link-text (context)|link-text]] and [[ns:link-text, context|link-text]] |
| 1260 | + * |
| 1261 | + * @param string $text from [[|$text]] |
| 1262 | + * @param Title $title to resolve the link against |
| 1263 | + * @return string $link for [[$link|$text]] |
| 1264 | + */ |
| 1265 | + static function getPipeTrickLink( $text, $title ) { |
| 1266 | + static $rexps = FALSE, $tc; |
| 1267 | + if( !$rexps ) { |
| 1268 | + list( $tc, $nc ) = Linker::getPipeTrickCharacterClasses(); |
| 1269 | + $rexps = array ( |
| 1270 | + "/^($nc+:|)$tc+?( \\($tc+\\)| ($tc+))$/", # [[ns:page (context)|]] |
| 1271 | + "/^($nc+:|)$tc+?(?:(?: \\($tc+\\)| ($tc+)|)((?:,|,) $tc+|))$/" # [[ns:page (context), context|]] |
| 1272 | + ); |
| 1273 | + } |
| 1274 | + |
| 1275 | + if( !preg_match( "/^$tc+$/", $text ) ) |
| 1276 | + return ''; |
| 1277 | + |
| 1278 | + $t = $title->getText(); |
| 1279 | + |
| 1280 | + for( $i = 0; $i < count( $rexps ); $i++) { |
| 1281 | + if( preg_match( $rexps[$i], $t, $m ) ) |
| 1282 | + return "$m[1]$text$m[2]"; |
| 1283 | + } |
| 1284 | + return $text; |
| 1285 | + } |
| 1286 | + |
| 1287 | + /** |
1210 | 1288 | * Wrap a comment in standard punctuation and formatting if |
1211 | 1289 | * it's non-empty, otherwise return empty string. |
1212 | 1290 | * |
Index: branches/conrad/phase3/includes/EditPage.php |
— | — | @@ -227,22 +227,13 @@ |
228 | 228 | * @return string The contents of the page. |
229 | 229 | */ |
230 | 230 | protected function getPreloadedText( $preload ) { |
| 231 | + global $wgParser, $wgUser; |
231 | 232 | if ( !empty( $this->mPreloadText ) ) { |
232 | 233 | return $this->mPreloadText; |
233 | | - } elseif ( $preload === '' ) { |
234 | | - return ''; |
235 | 234 | } else { |
236 | 235 | $preloadTitle = Title::newFromText( $preload ); |
237 | 236 | if ( isset( $preloadTitle ) && $preloadTitle->userCanRead() ) { |
238 | | - $rev = Revision::newFromTitle( $preloadTitle ); |
239 | | - if ( is_object( $rev ) ) { |
240 | | - $text = $rev->getText(); |
241 | | - // TODO FIXME: AAAAAAAAAAA, this shouldn't be implementing |
242 | | - // its own mini-parser! -ævar |
243 | | - $text = preg_replace( '~</?includeonly>~', '', $text ); |
244 | | - return $text; |
245 | | - } else |
246 | | - return ''; |
| 237 | + return $wgParser->getTransclusionText( $preloadTitle, ParserOptions::newFromUser( $wgUser ) ); |
247 | 238 | } |
248 | 239 | } |
249 | 240 | } |
Index: branches/conrad/phase3/includes/MagicWord.php |
— | — | @@ -84,6 +84,8 @@ |
85 | 85 | 'revisionuser', |
86 | 86 | 'subpagename', |
87 | 87 | 'subpagenamee', |
| 88 | + 'pipetrick', |
| 89 | + 'pipetricke', |
88 | 90 | 'talkspace', |
89 | 91 | 'talkspacee', |
90 | 92 | 'subjectspace', |
Index: branches/conrad/phase3/languages/messages/MessagesEn.php |
— | — | @@ -263,6 +263,8 @@ |
264 | 264 | 'talkpagenamee' => array( 1, 'TALKPAGENAMEE' ), |
265 | 265 | 'subjectpagename' => array( 1, 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ), |
266 | 266 | 'subjectpagenamee' => array( 1, 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ), |
| 267 | + 'pipetrick' => array( 1, 'PIPETRICK' ), |
| 268 | + 'pipetricke' => array( 1, 'PIPETRICKE' ), |
267 | 269 | 'msg' => array( 0, 'MSG:' ), |
268 | 270 | 'subst' => array( 0, 'SUBST:' ), |
269 | 271 | 'safesubst' => array( 0, 'SAFESUBST:' ), |
Index: branches/conrad/phase3/RELEASE-NOTES |
— | — | @@ -321,6 +321,12 @@ |
322 | 322 | maintenance/tests/. |
323 | 323 | * importImages.php maintenance script can now use the original uploader and |
324 | 324 | comment from another wiki. |
| 325 | +* (bug 845) [[#foo|]], [[/bar|]] should be equivalent to [[#foo|foo]], |
| 326 | + [[/bar|bar]] (new use of "pipe trick") |
| 327 | +* (bug 21660) Support full-width commas for pipe trick |
| 328 | +* (bug 7264) Magic word to give Page Title as if pipe-trick performed on it |
| 329 | + {{pipetrick:}} |
| 330 | +* (bug 20339) Allow using the pipe trick in log reasons |
325 | 331 | * Support for Turck MMCache was removed |
326 | 332 | |
327 | 333 | === Bug fixes in 1.16 === |
— | — | @@ -750,6 +756,10 @@ |
751 | 757 | as it appears in extensions as was the case before r30117 where it |
752 | 758 | was unintentionally sorted along with other fields. |
753 | 759 | * (bug 19334) Textarea no longer jumps when editing longer articles in IE8 |
| 760 | +* (bug 5210) preload parser should parse <noinclude> (as well as <includeonly>) |
| 761 | +* (bug 8785) Pipe trick should work with colon functions |
| 762 | +* (bug 4099) Pipe trick doesn't work when emptiness is only provided by empty |
| 763 | + template parameter |
754 | 764 | * Truncate summary of page moves in revision comment field to avoid broken |
755 | 765 | multibyte characters |
756 | 766 | * (bug 22540) ForeignApiRepos no longer try to store thumbnails that don't exist |