Merge "Allow Linker::formatComment to link to another wiki per default."
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 15 Sep 2015 18:49:08 +0000 (18:49 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 15 Sep 2015 18:49:08 +0000 (18:49 +0000)
RELEASE-NOTES-1.26
docs/hooks.txt
includes/Linker.php
tests/phpunit/includes/LinkerTest.php

index 8f5db0e..4463c78 100644 (file)
@@ -139,6 +139,7 @@ changes to languages because of Phabricator reports.
 * ChangeTags::tagDescription() will return false if the interface message
   for the tag is disabled.
 * Added PageHistoryPager::doBatchLookups hook.
+* Added $wikiId parameter to FormatAutocomments hook.
 * Added ParserCacheSaveComplete to ParserCache
 * supportsDirectEditing and supportsDirectApiEditing methods added to
   ContentHandler, to provide a way for ApiEditPage and EditPage to check
index 5e2269a..54ab46c 100644 (file)
@@ -1376,6 +1376,9 @@ $auto: The extracted part of the parsed comment before the call to the hook.
 $post: Boolean, true if there is text after this autocomment
 $title: An optional title object used to links to sections. Can be null.
 $local: Boolean indicating whether section links should refer to local page.
+$wikiId: String containing the ID (as used by WikiMap) of the wiki from which the
+  autocomment originated; null for the local wiki. Added in 1.26, should default
+  to null in handler functions, for backwards compatibility.
 
 'GalleryGetModes': Get list of classes that can render different modes of a
 gallery.
index db6f379..9b5ff27 100644 (file)
@@ -1276,9 +1276,11 @@ class Linker {
         * @param string $comment
         * @param Title|null $title Title object (to generate link to the section in autocomment) or null
         * @param bool $local Whether section links should refer to local page
+        * @param string|null $wikiId Id (as used by WikiMap) of the wiki to generate links to. For use with external changes.
+        *
         * @return mixed|string
         */
-       public static function formatComment( $comment, $title = null, $local = false ) {
+       public static function formatComment( $comment, $title = null, $local = false, $wikiId = null ) {
 
                # Sanitize text a bit:
                $comment = str_replace( "\n", " ", $comment );
@@ -1286,8 +1288,8 @@ class Linker {
                $comment = Sanitizer::escapeHtmlAllowEntities( $comment );
 
                # Render autocomments and make links:
-               $comment = self::formatAutocomments( $comment, $title, $local );
-               $comment = self::formatLinksInComment( $comment, $title, $local );
+               $comment = self::formatAutocomments( $comment, $title, $local, $wikiId );
+               $comment = self::formatLinksInComment( $comment, $title, $local, $wikiId );
 
                return $comment;
        }
@@ -1304,9 +1306,11 @@ class Linker {
         * @param string $comment Comment text
         * @param Title|null $title An optional title object used to links to sections
         * @param bool $local Whether section links should refer to local page
-        * @return string Formatted comment
+        * @param string|null $wikiId Id of the wiki to link to (if not the local wiki), as used by WikiMap.
+        *
+        * @return string Formatted comment (wikitext)
         */
-       private static function formatAutocomments( $comment, $title = null, $local = false ) {
+       private static function formatAutocomments( $comment, $title = null, $local = false, $wikiId = null ) {
                // @todo $append here is something of a hack to preserve the status
                // quo. Someone who knows more about bidi and such should decide
                // (1) what sane rendering even *is* for an LTR edit summary on an RTL
@@ -1320,7 +1324,7 @@ class Linker {
                        // zero-width assertions optional, so wrap them in a non-capturing
                        // group.
                        '!(?:(?<=(.)))?/\*\s*(.*?)\s*\*/(?:(?=(.)))?!',
-                       function ( $match ) use ( $title, $local, &$append ) {
+                       function ( $match ) use ( $title, $local, $wikiId, &$append ) {
                                global $wgLang;
 
                                // Ensure all match positions are defined
@@ -1330,7 +1334,7 @@ class Linker {
                                $auto = $match[2];
                                $post = $match[3] !== '';
                                $comment = null;
-                               Hooks::run( 'FormatAutocomments', array( &$comment, $pre, $auto, $post, $title, $local ) );
+                               Hooks::run( 'FormatAutocomments', array( &$comment, $pre, $auto, $post, $title, $local, $wikiId ) );
                                if ( $comment === null ) {
                                        $link = '';
                                        if ( $title ) {
@@ -1349,9 +1353,7 @@ class Linker {
                                                                $title->getDBkey(), $section );
                                                }
                                                if ( $sectionTitle ) {
-                                                       $link = Linker::link( $sectionTitle,
-                                                               $wgLang->getArrow(), array(), array(),
-                                                               'noclasses' );
+                                                       $link = Linker::makeCommentLink( $sectionTitle, $wgLang->getArrow(), $wikiId, 'noclasses' );
                                                } else {
                                                        $link = '';
                                                }
@@ -1384,7 +1386,7 @@ class Linker {
         * @param string $comment Text to format links in
         * @param Title|null $title An optional title object used to links to sections
         * @param bool $local Whether section links should refer to local page
-        * @param string|null $wikiId Id of the wiki to link to (if not the local wiki), as used by WikiMap
+        * @param string|null $wikiId Id of the wiki to link to (if not the local wiki), as used by WikiMap.
         *
         * @return string
         */
@@ -1459,22 +1461,9 @@ class Linker {
                                                        $newTarget = clone ( $title );
                                                        $newTarget->setFragment( '#' . $target->getFragment() );
                                                        $target = $newTarget;
-
-                                               }
-
-                                               if ( $wikiId !== null ) {
-                                                       $thelink = Linker::makeExternalLink(
-                                                               WikiMap::getForeignURL( $wikiId, $target->getPrefixedText(), $target->getFragment() ),
-                                                               $linkText . $inside,
-                                                               /* escape = */ false // Already escaped
-                                                       ) . $trail;
-                                               } else {
-                                                       $thelink = Linker::link(
-                                                               $target,
-                                                               $linkText . $inside
-                                                       ) . $trail;
                                                }
 
+                                               $thelink = Linker::makeCommentLink( $target, $linkText . $inside, $wikiId ) . $trail;
                                        }
                                }
                                if ( $thelink ) {
@@ -1493,6 +1482,32 @@ class Linker {
                );
        }
 
+       /**
+        * Generates a link to the given Title
+        *
+        * @note This is only public for technical reasons. It's not intended for use outside Linker.
+        *
+        * @param Title $title
+        * @param string $text
+        * @param string|null $wikiId Id of the wiki to link to (if not the local wiki), as used by WikiMap.
+        * @param string|string[] $options See the $options parameter in Linker::link.
+        *
+        * @return string HTML link
+        */
+       public static function makeCommentLink( Title $title, $text, $wikiId = null, $options = array() ) {
+               if ( $wikiId !== null && !$title->isExternal() ) {
+                       $link = Linker::makeExternalLink(
+                                       WikiMap::getForeignURL( $wikiId, $title->getPrefixedText(), $title->getFragment() ),
+                                       $text,
+                                       /* escape = */ false // Already escaped
+                               );
+               } else {
+                       $link = Linker::link( $title, $text, array(), array(), $options );
+               }
+
+               return $link;
+       }
+
        /**
         * @param Title $contextTitle
         * @param string $target
@@ -1579,17 +1594,18 @@ class Linker {
         * @param string $comment
         * @param Title|null $title Title object (to generate link to section in autocomment) or null
         * @param bool $local Whether section links should refer to local page
+        * @param string|null $wikiId Id (as used by WikiMap) of the wiki to generate links to. For use with external changes.
         *
         * @return string
         */
-       public static function commentBlock( $comment, $title = null, $local = false ) {
+       public static function commentBlock( $comment, $title = null, $local = false, $wikiId = null ) {
                // '*' used to be the comment inserted by the software way back
                // in antiquity in case none was provided, here for backwards
                // compatibility, acc. to brion -ævar
                if ( $comment == '' || $comment == '*' ) {
                        return '';
                } else {
-                       $formatted = self::formatComment( $comment, $title, $local );
+                       $formatted = self::formatComment( $comment, $title, $local, $wikiId );
                        $formatted = wfMessage( 'parentheses' )->rawParams( $formatted )->escaped();
                        return " <span class=\"comment\">$formatted</span>";
                }
@@ -2382,6 +2398,7 @@ class Linker {
                        'title' => $tooltip
                ) );
        }
+
 }
 
 /**
index 823c933..a3efbb8 100644 (file)
@@ -93,12 +93,26 @@ class LinkerTest extends MediaWikiLangTestCase {
         * @covers Linker::formatAutocomments
         * @covers Linker::formatLinksInComment
         */
-       public function testFormatComment( $expected, $comment, $title = false, $local = false ) {
+       public function testFormatComment( $expected, $comment, $title = false, $local = false, $wikiId = null ) {
+               $conf = new SiteConfiguration();
+               $conf->settings = array(
+                       'wgServer' => array(
+                               'enwiki' => '//en.example.org',
+                               'dewiki' => '//de.example.org',
+                       ),
+                       'wgArticlePath' => array(
+                               'enwiki' => '/w/$1',
+                               'dewiki' => '/w/$1',
+                       ),
+               );
+               $conf->suffixes = array( 'wiki' );
+
                $this->setMwGlobals( array(
                        'wgScript' => '/wiki/index.php',
                        'wgArticlePath' => '/wiki/$1',
                        'wgWellFormedXml' => true,
                        'wgCapitalLinks' => true,
+                       'wgConf' => $conf,
                ) );
 
                if ( $title === false ) {
@@ -108,11 +122,13 @@ class LinkerTest extends MediaWikiLangTestCase {
 
                $this->assertEquals(
                        $expected,
-                       Linker::formatComment( $comment, $title, $local )
+                       Linker::formatComment( $comment, $title, $local, $wikiId )
                );
        }
 
-       public static function provideCasesForFormatComment() {
+       public function provideCasesForFormatComment() {
+               $wikiId = 'enwiki'; // $wgConf has a fake entry for this
+
                return array(
                        // Linker::formatComment
                        array(
@@ -127,6 +143,10 @@ class LinkerTest extends MediaWikiLangTestCase {
                                "&#039;&#039;&#039;not bolded&#039;&#039;&#039;",
                                "'''not bolded'''",
                        ),
+                       array(
+                               "try &lt;script&gt;evil&lt;/scipt&gt; things",
+                               "try <script>evil</scipt> things",
+                       ),
                        // Linker::formatAutocomments
                        array(
                                '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
@@ -156,6 +176,14 @@ class LinkerTest extends MediaWikiLangTestCase {
                                '<a href="/wiki/Special:BlankPage#autocomment_containing_.2F.2A" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing /*: </span> T70361</span>',
                                "/* autocomment containing /* */ T70361"
                        ),
+                       array(
+                               '<a href="/wiki/Special:BlankPage#autocomment_containing_.22quotes.22" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing &quot;quotes&quot;</span></span>',
+                               "/* autocomment containing \"quotes\" */"
+                       ),
+                       array(
+                               '<a href="/wiki/Special:BlankPage#autocomment_containing_.3Cscript.3Etags.3C.2Fscript.3E" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing &lt;script&gt;tags&lt;/script&gt;</span></span>',
+                               "/* autocomment containing <script>tags</script> */"
+                       ),
                        array(
                                '<a href="#autocomment">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "/* autocomment */",
@@ -166,6 +194,16 @@ class LinkerTest extends MediaWikiLangTestCase {
                                "/* autocomment */",
                                null
                        ),
+                       array(
+                               '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
+                               "/* autocomment */",
+                               false, false
+                       ),
+                       array(
+                               '<a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage#autocomment">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
+                               "/* autocomment */",
+                               false, false, $wikiId
+                       ),
                        // Linker::formatLinksInComment
                        array(
                                'abc <a href="/wiki/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">link</a> def',
@@ -191,6 +229,28 @@ class LinkerTest extends MediaWikiLangTestCase {
                                'abc <a href="/wiki/index.php?title=/subpage&amp;action=edit&amp;redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a> def',
                                "abc [[/subpage]] def",
                        ),
+                       array(
+                               'abc <a href="/wiki/index.php?title=%22evil!%22&amp;action=edit&amp;redlink=1" class="new" title="&quot;evil!&quot; (page does not exist)">&quot;evil!&quot;</a> def',
+                               "abc [[\"evil!\"]] def",
+                       ),
+                       array(
+                               'abc [[&lt;script&gt;very evil&lt;/script&gt;]] def',
+                               "abc [[<script>very evil</script>]] def",
+                       ),
+                       array(
+                               'abc [[|]] def',
+                               "abc [[|]] def",
+                       ),
+                       array(
+                               'abc <a href="/wiki/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">link</a> def',
+                               "abc [[link]] def",
+                               false, false
+                       ),
+                       array(
+                               'abc <a class="external" rel="nofollow" href="//en.example.org/w/Link">link</a> def',
+                               "abc [[link]] def",
+                               false, false, $wikiId
+                       )
                );
        }