http://www.mediawiki.org/wiki/Special:Code/MediaWiki/62069
Revision: 62069 Author: conrad Date: 2010-02-06 15:00:45 +0000 (Sat, 06 Feb 2010) Log Message: ----------- Allow pipe trick to work after PST. Fixes bug 4099, bug 8785, partially bug 16714, bug 2700. Modified Paths: -------------- trunk/phase3/RELEASE-NOTES trunk/phase3/includes/parser/Parser.php trunk/phase3/maintenance/parserTests.txt Modified: trunk/phase3/RELEASE-NOTES =================================================================== --- trunk/phase3/RELEASE-NOTES 2010-02-06 14:56:54 UTC (rev 62068) +++ trunk/phase3/RELEASE-NOTES 2010-02-06 15:00:45 UTC (rev 62069) @@ -830,6 +830,8 @@ * (bug 20809) Expose EditFormPreloadText via the API * (bug 18427) Comment (edit summary) parser option for API * (bug 5210) preload parser should parse <noinclude> (as well as <includeonly>) +* (bug 8785) Pipe trick should work with colon functions +* (bug 4099) Pipe trick doesn't work when emptiness is only provided by empty template parameter === Languages updated in 1.16 === Modified: trunk/phase3/includes/parser/Parser.php =================================================================== --- trunk/phase3/includes/parser/Parser.php 2010-02-06 14:56:54 UTC (rev 62068) +++ trunk/phase3/includes/parser/Parser.php 2010-02-06 15:00:45 UTC (rev 62069) @@ -1511,7 +1511,7 @@ if ( !$tc ) { $tc = Title::legalChars() . '#%'; # Match a link having the form [[namespace:link|alternate]]trail - $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; + $e1 = "/^([{$tc}]*)(\\|.*?)?]](.*)\$/sD"; # Match cases where there is no "]]", which might still be images $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; } @@ -1591,7 +1591,15 @@ wfProfileIn( __METHOD__."-e1" ); if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt - $text = $m[2]; + + if( $m[2] === '' ) { + $text = ''; + } elseif( $m[2] === '|' ) { + $text = $this->getPipeTrickText( $m[1] ); + } else { + $text = substr( $m[2], 1 ); + } + # If we get a ] at the beginning of $m[3] that means we have a link that's something like: # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row fucks up, # the real problem is with the $e1 regex @@ -1608,18 +1616,20 @@ $text .= ']'; # so that replaceExternalLinks($text) works later $m[3] = substr( $m[3], 1 ); } + + # Handle pipe-trick for [[|<blah>]] + $lnk = $m[1] === '' ? $this->getPipeTrickLink( $text ) : $m[1]; # fix up urlencoded title texts - if( strpos( $m[1], '%' ) !== false ) { + if( strpos( $lnk, '%' ) !== false ) { # Should anchors '#' also be rejected? - $m[1] = str_replace( array('<', '>'), array('<', '>'), urldecode($m[1]) ); + $lnk = str_replace( array('<', '>'), array('<', '>'), urldecode($lnk) ); } + $trail = $m[3]; } elseif( preg_match($e1_img, $line, $m) ) { # Invalid, but might be an image with a link in its caption $might_be_img = true; $text = $m[2]; - if ( strpos( $m[1], '%' ) !== false ) { - $m[1] = urldecode($m[1]); - } + $lnk = strpos( $m[1], '%' ) === false ? $m[1] : urldecode( $m[1] ); $trail = ""; } else { # Invalid form; output directly $s .= $prefix . '[[' . $line ; @@ -1632,7 +1642,7 @@ # Don't allow internal links to pages containing # PROTO: where PROTO is a valid URL protocol; these # should be external links. - if ( preg_match( '/^\b(?:' . wfUrlProtocols() . ')/', $m[1] ) ) { + if ( preg_match( '/^\b(?:' . wfUrlProtocols() . ')/', $lnk ) ) { $s .= $prefix . '[[' . $line ; wfProfileOut( __METHOD__."-misc" ); continue; @@ -1640,12 +1650,12 @@ # Make subpage if necessary if ( $useSubpages ) { - $link = $this->maybeDoSubpageLink( $m[1], $text ); + $link = $this->maybeDoSubpageLink( $lnk, $text ); } else { - $link = $m[1]; + $link = $lnk; } - $noforce = (substr( $m[1], 0, 1 ) !== ':'); + $noforce = (substr( $lnk, 0, 1 ) !== ':'); if (!$noforce) { # Strip off leading ':' $link = substr( $link, 1 ); @@ -1893,6 +1903,71 @@ return Linker::normalizeSubpageLink( $this->mTitle, $target, $text ); } + /** + * Returns valid title characters and namespace characters for pipe trick. + * + * FIXME: the namespace characters should not be specified like this... + */ + static function getPipeTrickCharacterClasses() { + global $wgLegalTitleChars; + return array( "[$wgLegalTitleChars]", '[ _0-9A-Za-z\x80-\xff-]' ); + } + + /** + * From the [[title|]] return link-text as though the used typed [[title|link-text]] + * + * For most links this be as though the user typed [[ns:title|title]] + * However [[ns:title (context)]], [[ns:title, context]] and [[ns:title (context), context]] + * all return the |title]] with no context or indicative punctuation. + */ + function getPipeTrickText( $link ) { + static $rexps = FALSE; + if( !$rexps ) { + list( $tc, $nc ) = Parser::getPipeTrickCharacterClasses(); + $rexps = array ( + # try this first, to turn "[[A, B (C)|]]" into "A, B" + "/^(:?$nc+:|:|)($tc+?)( \\($tc+\\)| ($tc+))$/", # [[ns:page (context)|]] + "/^(:?$nc+:|:|)($tc+?)( \\($tc+\\)|)(, $tc+|)$/" # [[ns:page (context), context|]] + ); + } + $text = urldecode( $link ); + + for( $i = 0; $i < count( $rexps ); $i++) { + if( preg_match( $rexps[$i], $text, $m ) ) + return $m[2]; + } + return $text; + } + + /** + * From the [[|link-text]] return the title as though the user typed [[title|link-text]] + * + * On most pages this will return link-text or "" if the link-text is not a valid title + * On pages like [[ns:title (context)]] and [[ns:title, context]] it will act like + * [[ns:link-text (context)|link-text]] and [[ns:link-text, context|link-text]] + */ + function getPipeTrickLink( $text ) { + static $rexps = FALSE, $tc; + if( !$rexps ) { + list( $tc, $nc ) = Parser::getPipeTrickCharacterClasses(); + $rexps = array ( + "/^($nc+:|)$tc+?( \\($tc+\\))$/", # [[ns:page (context)]] + "/^($nc+:|)$tc+?(, $tc+|)$/" # [[ns:page, context]] + ); + } + + if( !preg_match( "/^$tc+$/", $text ) ) + return ''; + + $t = $this->mTitle->getText(); + + for( $i = 0; $i < count( $rexps ); $i++) { + if( preg_match( $rexps[$i], $t, $m ) ) + return "$m[1]$text$m[2]"; + } + return $text; + } + /*...@+ * Used by doBlockLevels() * @private @@ -3986,33 +4061,11 @@ '~~~' => $sigText ) ); - # Context links: [[|name]] and [[name (context)|]] - # - global $wgLegalTitleChars; - $tc = "[$wgLegalTitleChars]"; - $nc = '[ _0-9A-Za-z\x80-\xff-]'; # Namespaces can use non-ascii! + # Links of the form [[|<blah>]] or [[<blah>|]] perform pipe tricks + list( $tc, $nc ) = Parser::getPipeTrickCharacterClasses(); + $pipeTrickRe = "/\[\[(?:(\\|)($tc+)|($tc+)\\|)\]\]/"; + $text = preg_replace_callback( $pipeTrickRe, array( $this, 'pstPipeTrickCallback' ), $text); - $p1 = "/\[\[(:?$nc+:|:|)($tc+?)( \\($tc+\\))\\|]]/"; # [[ns:page (context)|]] - $p4 = "/\[\[(:?$nc+:|:|)($tc+?)(($tc+))\\|]]/"; # [[ns:page(context)|]] - $p3 = "/\[\[(:?$nc+:|:|)($tc+?)( \\($tc+\\)|)(, $tc+|)\\|]]/"; # [[ns:page (context), context|]] - $p2 = "/\[\[\\|($tc+)]]/"; # [[|page]] - - # try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]" - $text = preg_replace( $p1, '[[\\1\\2\\3|\\2]]', $text ); - $text = preg_replace( $p4, '[[\\1\\2\\3|\\2]]', $text ); - $text = preg_replace( $p3, '[[\\1\\2\\3\\4|\\2]]', $text ); - - $t = $this->mTitle->getText(); - $m = array(); - if ( preg_match( "/^($nc+:|)$tc+?( \\($tc+\\))$/", $t, $m ) ) { - $text = preg_replace( $p2, "[[$m[1]\\1$m[2]|\\1]]", $text ); - } elseif ( preg_match( "/^($nc+:|)$tc+?(, $tc+|)$/", $t, $m ) && "$m[1]$m[2]" != '' ) { - $text = preg_replace( $p2, "[[$m[1]\\1$m[2]|\\1]]", $text ); - } else { - # if there's no context, don't bother duplicating the title - $text = preg_replace( $p2, '[[\\1]]', $text ); - } - # Trim trailing whitespace $text = rtrim( $text ); @@ -4020,6 +4073,25 @@ } /** + * Called from pstPass2 to perform the pipe trick on links. + * Original was either [[|text]] or [[link|]] + * + * @param Array ("|" or "", text, link) $m + */ + function pstPipeTrickCallback($m) + { + if( $m[1] ) { # [[|<blah>]] + $text = $m[2]; + $link = $this->getPipeTrickLink( $text ); + } else { # [[<blah>|]] + $link = $m[3]; + $text = $this->getPipeTrickText( $link ); + } + + return $link === $text ? "[[$link]]" : "[[$link|$text]]"; + } + + /** * Fetch the user's signature text, if any, and normalize to * validated, ready-to-insert wikitext. * If you have pre-fetched the nickname or the fancySig option, you can Modified: trunk/phase3/maintenance/parserTests.txt =================================================================== --- trunk/phase3/maintenance/parserTests.txt 2010-02-06 14:56:54 UTC (rev 62068) +++ trunk/phase3/maintenance/parserTests.txt 2010-02-06 15:00:45 UTC (rev 62069) @@ -3112,7 +3112,66 @@ [[Ns:Article, Context|Article]] !! end +!! test +pre-save transform: context links ("pipe trick") with url escaped page names +!! options +pst +!! input +[[Hello wo%52ld|]] +[[Hello wo%52ld (again)|]] +!! result +[[Hello wo%52ld|Hello woRld]] +[[Hello wo%52ld (again)|Hello woRld]] +!! end +!! test +pre-save transform: context links ("pipe trick") with variables are not pre-empted +!! options +pst title=[[Test (page)]] +!! input +[[{{{1|}}}|]] +[[|{{{1|}}}]] +[[{{subst:PAGENAME}}|]] +!! result +[[{{{1|}}}|]] +[[|{{{1|}}}]] +[[Test (page)|Test]] +!! end + +!! article +Template:pipetest +!! text +[[{{{1}}}|]] +!! endarticle + +!! article +Template:testpipe +!! text +[[|{{{1}}}]] +!! endarticle + +!! test +("pipe trick") should work outside PST +!!options +title=[[Help:hello (world)]] +!! input +{{pipetest|hi (world)}} +{{pipetest|hi (world), world}} +{{pipetest|Help:hi (world), world}} +{{pipetest|:Help:hi (world), world}} +{{testpipe|hi}} +[[{{PAGENAME}}|]] +!! result +<p><a href="/index.php?title=Hi_(world)&action=edit&redlink=1" class="new" title="Hi (world) (page does not exist)">hi</a> +<a href="/index.php?title=Hi_(world),_world&action=edit&redlink=1" class="new" title="Hi (world), world (page does not exist)">hi</a> +<a href="/index.php?title=Help:Hi_(world),_world&action=edit&redlink=1" class="new" title="Help:Hi (world), world (page does not exist)">hi</a> +<a href="/index.php?title=Help:Hi_(world),_world&action=edit&redlink=1" class="new" title="Help:Hi (world), world (page does not exist)">hi</a> +<a href="/index.php?title=Hi_(world)&action=edit&redlink=1" class="new" title="Hi (world) (page does not exist)">hi</a> +<a href="/index.php?title=Hello_(world)&action=edit&redlink=1" class="new" title="Hello (world) (page does not exist)">Hello</a> +</p> +!! end + + ### ### Message transform tests ### _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs