Merge "Add LinkRenderer (rewrite of Linker::link())"
[lhc/web/wiklou.git] / includes / Linker.php
index 977d71e..990ad15 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  */
 use MediaWiki\Linker\LinkTarget;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Some internal bits split of from Skin.php. These functions are used
@@ -40,6 +41,7 @@ class Linker {
        /**
         * Get the appropriate HTML attributes to add to the "a" element of an interwiki link.
         *
+        * @since 1.16.3
         * @deprecated since 1.25
         *
         * @param string $title The title text for the link, URL-encoded (???) but
@@ -66,6 +68,7 @@ class Linker {
        /**
         * Get the appropriate HTML attributes to add to the "a" element of an internal link.
         *
+        * @since 1.16.3
         * @deprecated since 1.25
         *
         * @param string $title The title text for the link, URL-encoded (???) but
@@ -86,6 +89,7 @@ class Linker {
         * Get the appropriate HTML attributes to add to the "a" element of an internal
         * link, given the Title object for the page we want to link to.
         *
+        * @since 1.16.3
         * @deprecated since 1.25
         *
         * @param Title $nt
@@ -107,6 +111,7 @@ class Linker {
        /**
         * Common code for getLinkAttributesX functions
         *
+        * @since 1.16.3
         * @deprecated since 1.25
         *
         * @param string $title
@@ -132,6 +137,7 @@ class Linker {
        /**
         * Return the CSS colour of a known link
         *
+        * @since 1.16.3
         * @param Title $t
         * @param int $threshold User defined threshold
         * @return string CSS class
@@ -205,199 +211,55 @@ class Linker {
                        wfDeprecated( __METHOD__ . ' with parameter $query as string (should be array)', '1.20' );
                        $query = wfCgiToArray( $query );
                }
-               $options = (array)$options;
-
-               $dummy = new DummyLinker; // dummy linker instance for bc on the hooks
-
-               $ret = null;
-               if ( !Hooks::run( 'LinkBegin',
-                       [ $dummy, $target, &$html, &$customAttribs, &$query, &$options, &$ret ] )
-               ) {
-                       return $ret;
-               }
 
-               # Normalize the Title if it's a special page
-               $target = self::normaliseSpecialPage( $target );
-
-               # If we don't know whether the page exists, let's find out.
-               if ( !in_array( 'known', $options, true ) && !in_array( 'broken', $options, true ) ) {
-                       if ( $target->isKnown() ) {
-                               $options[] = 'known';
-                       } else {
-                               $options[] = 'broken';
+               $services = MediaWikiServices::getInstance();
+               $options = (array)$options;
+               if ( $options ) {
+                       // Custom options, create new LinkRenderer
+                       if ( !isset( $options['stubThreshold'] ) ) {
+                               global $wgUser;
+                               $options['stubThreshold'] = $wgUser->getStubThreshold();
                        }
+                       $linkRenderer = $services->getLinkRendererFactory()
+                               ->createFromLegacyOptions( $options );
+               } else {
+                       $linkRenderer = $services->getLinkRenderer();
                }
 
-               $oldquery = [];
-               if ( in_array( "forcearticlepath", $options, true ) && $query ) {
-                       $oldquery = $query;
-                       $query = [];
-               }
-
-               # Note: we want the href attribute first, for prettiness.
-               $attribs = [ 'href' => self::linkUrl( $target, $query, $options ) ];
-               if ( in_array( 'forcearticlepath', $options, true ) && $oldquery ) {
-                       $attribs['href'] = wfAppendQuery( $attribs['href'], $oldquery );
-               }
-
-               $attribs = array_merge(
-                       $attribs,
-                       self::linkAttribs( $target, $customAttribs, $options )
-               );
-               if ( is_null( $html ) ) {
-                       $html = self::linkText( $target );
+               if ( $html !== null ) {
+                       $text = new HtmlArmor( $html );
+               } else {
+                       $text = $html; // null
                }
-
-               $ret = null;
-               if ( Hooks::run( 'LinkEnd', [ $dummy, $target, $options, &$html, &$attribs, &$ret ] ) ) {
-                       $ret = Html::rawElement( 'a', $attribs, $html );
+               if ( in_array( 'known', $options, true ) ) {
+                       return $linkRenderer->makeKnownLink( $target, $text, $customAttribs, $query );
+               } elseif ( in_array( 'broken', $options, true ) ) {
+                       return $linkRenderer->makeBrokenLink( $target, $text, $customAttribs, $query );
+               } else {
+                       return $linkRenderer->makeLink( $target, $text, $customAttribs, $query );
                }
-
-               return $ret;
        }
 
        /**
         * Identical to link(), except $options defaults to 'known'.
+        * @since 1.16.3
         * @see Linker::link
         * @return string
         */
        public static function linkKnown(
                $target, $html = null, $customAttribs = [],
-               $query = [], $options = [ 'known', 'noclasses' ]
+               $query = [], $options = [ 'known' ]
        ) {
                return self::link( $target, $html, $customAttribs, $query, $options );
        }
 
-       /**
-        * Returns the Url used to link to a Title
-        *
-        * @param LinkTarget $target
-        * @param array $query Query parameters
-        * @param array $options
-        * @return string
-        */
-       private static function linkUrl( LinkTarget $target, $query, $options ) {
-               # We don't want to include fragments for broken links, because they
-               # generally make no sense.
-               if ( in_array( 'broken', $options, true ) && $target->hasFragment() ) {
-                       $target = $target->createFragmentTarget( '' );
-               }
-
-               # If it's a broken link, add the appropriate query pieces, unless
-               # there's already an action specified, or unless 'edit' makes no sense
-               # (i.e., for a nonexistent special page).
-               if ( in_array( 'broken', $options, true ) && empty( $query['action'] )
-                       && $target->getNamespace() !== NS_SPECIAL ) {
-                       $query['action'] = 'edit';
-                       $query['redlink'] = '1';
-               }
-
-               if ( in_array( 'http', $options, true ) ) {
-                       $proto = PROTO_HTTP;
-               } elseif ( in_array( 'https', $options, true ) ) {
-                       $proto = PROTO_HTTPS;
-               } else {
-                       $proto = PROTO_RELATIVE;
-               }
-
-               $title = Title::newFromLinkTarget( $target );
-               $ret = $title->getLinkURL( $query, false, $proto );
-               return $ret;
-       }
-
-       /**
-        * Returns the array of attributes used when linking to the Title $target
-        *
-        * @param Title $target
-        * @param array $attribs
-        * @param array $options
-        *
-        * @return array
-        */
-       private static function linkAttribs( $target, $attribs, $options ) {
-               global $wgUser;
-               $defaults = [];
-
-               if ( !in_array( 'noclasses', $options, true ) ) {
-                       # Now build the classes.
-                       $classes = [];
-
-                       if ( in_array( 'broken', $options, true ) ) {
-                               $classes[] = 'new';
-                       }
-
-                       if ( $target->isExternal() ) {
-                               $classes[] = 'extiw';
-                       }
-
-                       if ( !in_array( 'broken', $options, true ) ) { # Avoid useless calls to LinkCache (see r50387)
-                               $colour = self::getLinkColour(
-                                       $target,
-                                       isset( $options['stubThreshold'] ) ? $options['stubThreshold'] : $wgUser->getStubThreshold()
-                               );
-                               if ( $colour !== '' ) {
-                                       $classes[] = $colour; # mw-redirect or stub
-                               }
-                       }
-                       if ( $classes != [] ) {
-                               $defaults['class'] = implode( ' ', $classes );
-                       }
-               }
-
-               # Get a default title attribute.
-               if ( $target->getPrefixedText() == '' ) {
-                       # A link like [[#Foo]].  This used to mean an empty title
-                       # attribute, but that's silly.  Just don't output a title.
-               } elseif ( in_array( 'known', $options, true ) ) {
-                       $defaults['title'] = $target->getPrefixedText();
-               } else {
-                       // This ends up in parser cache!
-                       $defaults['title'] = wfMessage( 'red-link-title', $target->getPrefixedText() )
-                               ->inContentLanguage()
-                               ->text();
-               }
-
-               # Finally, merge the custom attribs with the default ones, and iterate
-               # over that, deleting all "false" attributes.
-               $ret = [];
-               $merged = Sanitizer::mergeAttributes( $defaults, $attribs );
-               foreach ( $merged as $key => $val ) {
-                       # A false value suppresses the attribute, and we don't want the
-                       # href attribute to be overridden.
-                       if ( $key != 'href' && $val !== false ) {
-                               $ret[$key] = $val;
-                       }
-               }
-               return $ret;
-       }
-
-       /**
-        * Default text of the links to the Title $target
-        *
-        * @param Title $target
-        *
-        * @return string
-        */
-       private static function linkText( $target ) {
-               if ( !$target instanceof Title ) {
-                       wfWarn( __METHOD__ . ': Requires $target to be a Title object.' );
-                       return '';
-               }
-               // If the target is just a fragment, with no title, we return the fragment
-               // text.  Otherwise, we return the title text itself.
-               if ( $target->getPrefixedText() === '' && $target->hasFragment() ) {
-                       return htmlspecialchars( $target->getFragment() );
-               }
-
-               return htmlspecialchars( $target->getPrefixedText() );
-       }
-
        /**
         * Make appropriate markup for a link to the current article. This is
         * currently rendered as the bold link text. The calling sequence is the
         * same as the other make*LinkObj static functions, despite $query not
         * being used.
         *
+        * @since 1.16.3
         * @param Title $nt
         * @param string $html [optional]
         * @param string $query [optional]
@@ -446,19 +308,20 @@ class Linker {
        }
 
        /**
-        * @param Title $title
-        * @return Title
+        * @since 1.16.3
+        * @param LinkTarget $target
+        * @return LinkTarget|Title You will get back the same type you passed in, or a Title object
         */
-       static function normaliseSpecialPage( Title $title ) {
-               if ( $title->isSpecialPage() ) {
-                       list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+       public static function normaliseSpecialPage( LinkTarget $target ) {
+               if ( $target->getNamespace() == NS_SPECIAL ) {
+                       list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $target->getDBkey() );
                        if ( !$name ) {
-                               return $title;
+                               return $target;
                        }
-                       $ret = SpecialPage::getTitleFor( $name, $subpage, $title->getFragment() );
+                       $ret = SpecialPage::getTitleFor( $name, $subpage, $target->getFragment() );
                        return $ret;
                } else {
-                       return $title;
+                       return $target;
                }
        }
 
@@ -484,6 +347,7 @@ class Linker {
         * Return the code for images which were added via external links,
         * via Parser::maybeMakeExternalImage().
         *
+        * @since 1.16.3
         * @param string $url
         * @param string $alt
         *
@@ -901,6 +765,7 @@ class Linker {
        /**
         * Make a "broken" link to an image
         *
+        * @since 1.16.3
         * @param Title $title
         * @param string $label Link label (plain text)
         * @param string $query Query string
@@ -930,7 +795,15 @@ class Linker {
                        $redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title );
 
                        if ( $redir ) {
-                               return self::linkKnown( $title, $encLabel, [], wfCgiToArray( $query ) );
+                               // We already know it's a redirect, so mark it
+                               // accordingly
+                               return self::link(
+                                       $title,
+                                       $encLabel,
+                                       [ 'class' => 'mw-redirect' ],
+                                       wfCgiToArray( $query ),
+                                       [ 'known', 'noclasses' ]
+                               );
                        }
 
                        $href = self::getUploadUrl( $title, $query );
@@ -940,12 +813,13 @@ class Linker {
                                $encLabel . '</a>';
                }
 
-               return self::linkKnown( $title, $encLabel, [], wfCgiToArray( $query ) );
+               return self::link( $title, $encLabel, [], wfCgiToArray( $query ), [ 'known', 'noclasses' ] );
        }
 
        /**
         * Get the URL to upload a certain file
         *
+        * @since 1.16.3
         * @param Title $destFile Title object of the file to upload
         * @param string $query Urlencoded query string to prepend
         * @return string Urlencoded URL
@@ -970,6 +844,7 @@ class Linker {
        /**
         * Create a direct link to a given uploaded file.
         *
+        * @since 1.16.3
         * @param Title $title
         * @param string $html Pre-sanitized HTML
         * @param string $time MW timestamp of file creation time
@@ -984,6 +859,7 @@ class Linker {
         * Create a direct link to a given uploaded file.
         * This will make a broken link if $file is false.
         *
+        * @since 1.16.3
         * @param Title $title
         * @param File|bool $file File object or false
         * @param string $html Pre-sanitized HTML
@@ -1027,6 +903,7 @@ class Linker {
         * a message key from the link text.
         * Usage example: Linker::specialLink( 'Recentchanges' )
         *
+        * @since 1.16.3
         * @param string $name
         * @param string $key
         * @return string
@@ -1041,6 +918,7 @@ class Linker {
 
        /**
         * Make an external link
+        * @since 1.16.3. $title added in 1.21
         * @param string $url URL to link to
         * @param string $text Text of link
         * @param bool $escape Do we escape the link text?
@@ -1069,7 +947,16 @@ class Linker {
                if ( !$title ) {
                        $title = $wgTitle;
                }
-               $attribs['rel'] = Parser::getExternalLinkRel( $url, $title );
+               $newRel = Parser::getExternalLinkRel( $url, $title );
+               if ( !isset( $attribs['rel'] ) || $attribs['rel'] === '' ) {
+                       $attribs['rel'] = $newRel;
+               } elseif ( $newRel !== '' ) {
+                       // Merge the rel attributes.
+                       $newRels = explode( ' ', $newRel );
+                       $oldRels = explode( ' ', $attribs['rel'] );
+                       $combined = array_unique( array_merge( $newRels, $oldRels ) );
+                       $attribs['rel'] = implode( ' ', $combined );
+               }
                $link = '';
                $success = Hooks::run( 'LinkerMakeExternalLink',
                        [ &$url, &$text, &$link, &$attribs, $linktype ] );
@@ -1088,7 +975,7 @@ class Linker {
         * @param string $userName User name in database.
         * @param string $altUserName Text to display instead of the user name (optional)
         * @return string HTML fragment
-        * @since 1.19 Method exists for a long time. $altUserName was added in 1.19.
+        * @since 1.16.3. $altUserName was added in 1.19.
         */
        public static function userLink( $userId, $userName, $altUserName = false ) {
                $classes = 'mw-userlink';
@@ -1112,6 +999,7 @@ class Linker {
        /**
         * Generate standard user tool links (talk, contributions, block link, etc.)
         *
+        * @since 1.16.3
         * @param int $userId User identifier
         * @param string $userText User name or IP address
         * @param bool $redContribsWhenNoEdits Should the contributions link be
@@ -1171,6 +1059,7 @@ class Linker {
 
        /**
         * Alias for userToolLinks( $userId, $userText, true );
+        * @since 1.16.3
         * @param int $userId User identifier
         * @param string $userText User name or IP address
         * @param int $edits User edit count (optional, for performance)
@@ -1181,6 +1070,7 @@ class Linker {
        }
 
        /**
+        * @since 1.16.3
         * @param int $userId User id in database.
         * @param string $userText User name in database.
         * @return string HTML fragment with user talk link
@@ -1192,6 +1082,7 @@ class Linker {
        }
 
        /**
+        * @since 1.16.3
         * @param int $userId Userid
         * @param string $userText User name in database.
         * @return string HTML fragment with block link
@@ -1215,6 +1106,7 @@ class Linker {
 
        /**
         * Generate a user link if the current user is allowed to view it
+        * @since 1.16.3
         * @param Revision $rev
         * @param bool $isPublic Show only if all users can see it
         * @return string HTML fragment
@@ -1236,6 +1128,7 @@ class Linker {
 
        /**
         * Generate a user tool link cluster if the current user is allowed to view it
+        * @since 1.16.3
         * @param Revision $rev
         * @param bool $isPublic Show only if all users can see it
         * @return string HTML
@@ -1264,6 +1157,7 @@ class Linker {
         * auto-generated comments (from section editing) and formats [[wikilinks]].
         *
         * @author Erik Moeller <moeller@scireview.de>
+        * @since 1.16.3. $wikiId added in 1.26
         *
         * Note: there's not always a title to pass to this function.
         * Since you can't set a default parameter for a reference, I've turned it
@@ -1389,7 +1283,9 @@ class Linker {
         * Formats wiki links and media links in text; all other wiki formatting
         * is ignored
         *
+        * @since 1.16.3. $wikiId added in 1.26
         * @todo FIXME: Doesn't handle sub-links as in image thumb texts like the main parser
+        *
         * @param string $comment Text to format links in. WARNING! Since the output of this
         *      function is html, $comment must be sanitized for use as html. You probably want
         *      to pass $comment through Sanitizer::escapeHtmlAllowEntities() before calling
@@ -1612,6 +1508,7 @@ class Linker {
         * Wrap a comment in standard punctuation and formatting if
         * it's non-empty, otherwise return empty string.
         *
+        * @since 1.16.3. $wikiId added in 1.26
         * @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
@@ -1639,6 +1536,7 @@ class Linker {
         * Wrap and format the given revision's comment block, if the current
         * user is allowed to view it.
         *
+        * @since 1.16.3
         * @param Revision $rev
         * @param bool $local Whether section links should refer to local page
         * @param bool $isPublic Show only if all users can see it
@@ -1663,6 +1561,7 @@ class Linker {
        }
 
        /**
+        * @since 1.16.3
         * @param int $size
         * @return string
         */
@@ -1679,6 +1578,7 @@ class Linker {
        /**
         * Add another level to the Table of Contents
         *
+        * @since 1.16.3
         * @return string
         */
        public static function tocIndent() {
@@ -1688,6 +1588,7 @@ class Linker {
        /**
         * Finish one or more sublevels on the Table of Contents
         *
+        * @since 1.16.3
         * @param int $level
         * @return string
         */
@@ -1698,6 +1599,7 @@ class Linker {
        /**
         * parameter level defines if we are on an indentation level
         *
+        * @since 1.16.3
         * @param string $anchor
         * @param string $tocline
         * @param string $tocnumber
@@ -1720,6 +1622,7 @@ class Linker {
         * End a Table Of Contents line.
         * tocUnindent() will be used instead if we're ending a line below
         * the new level.
+        * @since 1.16.3
         * @return string
         */
        public static function tocLineEnd() {
@@ -1729,6 +1632,7 @@ class Linker {
        /**
         * Wraps the TOC in a table and provides the hide/collapse javascript.
         *
+        * @since 1.16.3
         * @param string $toc Html of the Table Of Contents
         * @param string|Language|bool $lang Language for the toc title, defaults to user language
         * @return string Full html of the TOC
@@ -1746,6 +1650,7 @@ class Linker {
        /**
         * Generate a table of contents from a section tree.
         *
+        * @since 1.16.3. $lang added in 1.17
         * @param array $tree Return value of ParserOutput::getSections()
         * @param string|Language|bool $lang Language for the toc title, defaults to user language
         * @return string HTML fragment
@@ -1775,6 +1680,7 @@ class Linker {
        /**
         * Create a headline for content
         *
+        * @since 1.16.3
         * @param int $level The level of the headline (1-6)
         * @param string $attribs Any attributes for the headline, starting with
         *   a space and ending with '>'
@@ -1838,7 +1744,11 @@ class Linker {
         * work if $wgShowRollbackEditCount is disabled, so this can only function
         * as an additional check.
         *
-        * If the option noBrackets is set the rollback link wont be enclosed in []
+        * If the option noBrackets is set the rollback link wont be enclosed in "[]".
+        *
+        * See the "mediawiki.page.rollback" module for the client-side handling of this link.
+        *
+        * @since 1.16.3. $context added in 1.20. $options added in 1.21
         *
         * @param Revision $rev
         * @param IContextSource $context Context to use or null for the main context.
@@ -1866,6 +1776,8 @@ class Linker {
                        $inner = $context->msg( 'brackets' )->rawParams( $inner )->escaped();
                }
 
+               $context->getOutput()->addModules( 'mediawiki.page.rollback' );
+
                return '<span class="mw-rollback-link">' . $inner . '</span>';
        }
 
@@ -1938,6 +1850,7 @@ class Linker {
        /**
         * Build a raw rollback link, useful for collections of "tool" links
         *
+        * @since 1.16.3. $context added in 1.20. $editCount added in 1.21
         * @param Revision $rev
         * @param IContextSource|null $context Context to use or null for the main context.
         * @param int $editCount Number of edits that would be reverted
@@ -1959,11 +1872,13 @@ class Linker {
                $query = [
                        'action' => 'rollback',
                        'from' => $rev->getUserText(),
-                       'token' => $context->getUser()->getEditToken( [
-                               $title->getPrefixedText(),
-                               $rev->getUserText()
-                       ] ),
                ];
+               $attrs = [
+                       'data-mw' => 'interface',
+                       'title' => $context->msg( 'tooltip-rollback' )->text(),
+               ];
+               $options = [ 'known', 'noclasses' ];
+
                if ( $context->getRequest()->getBool( 'bot' ) ) {
                        $query['bot'] = '1';
                        $query['hidediff'] = '1'; // bug 15999
@@ -1988,27 +1903,16 @@ class Linker {
                        }
 
                        if ( $editCount > $wgShowRollbackEditCount ) {
-                               $editCount_output = $context->msg( 'rollbacklinkcount-morethan' )
+                               $html = $context->msg( 'rollbacklinkcount-morethan' )
                                        ->numParams( $wgShowRollbackEditCount )->parse();
                        } else {
-                               $editCount_output = $context->msg( 'rollbacklinkcount' )->numParams( $editCount )->parse();
+                               $html = $context->msg( 'rollbacklinkcount' )->numParams( $editCount )->parse();
                        }
 
-                       return self::link(
-                               $title,
-                               $editCount_output,
-                               [ 'title' => $context->msg( 'tooltip-rollback' )->text() ],
-                               $query,
-                               [ 'known', 'noclasses' ]
-                       );
+                       return self::link( $title, $html, $attrs, $query, $options );
                } else {
-                       return self::link(
-                               $title,
-                               $context->msg( 'rollbacklink' )->escaped(),
-                               [ 'title' => $context->msg( 'tooltip-rollback' )->text() ],
-                               $query,
-                               [ 'known', 'noclasses' ]
-                       );
+                       $html = $context->msg( 'rollbacklink' )->escaped();
+                       return self::link( $title, $html, $attrs, $query, $options );
                }
        }
 
@@ -2021,6 +1925,7 @@ class Linker {
         * directly paste it in as the link (escaping needs to be done manually).
         * Finally, if $more is a Message, call toString().
         *
+        * @since 1.16.3. $more added in 1.21
         * @param Title[] $templates Array of templates
         * @param bool $preview Whether this is for a preview
         * @param bool $section Whether this is for a section edit
@@ -2116,6 +2021,7 @@ class Linker {
        /**
         * Returns HTML for the "hidden categories on this page" list.
         *
+        * @since 1.16.3
         * @param array $hiddencats Array of hidden categories from Article::getHiddenCategories
         *   or similar
         * @return string HTML output
@@ -2144,6 +2050,7 @@ class Linker {
         * Format a size in bytes for output, using an appropriate
         * unit (B, KB, MB or GB) according to the magnitude in question
         *
+        * @since 1.16.3
         * @param int $size Size to format
         * @return string
         */
@@ -2158,6 +2065,7 @@ class Linker {
         * isn't always, because sometimes the accesskey needs to go on a different
         * element than the id, for reverse-compatibility, etc.)
         *
+        * @since 1.16.3 $msgParams added in 1.27
         * @param string $name Id of the element, minus prefixes.
         * @param string|null $options Null or the string 'withaccess' to add an access-
         *   key hint
@@ -2204,6 +2112,7 @@ class Linker {
         * the id but isn't always, because sometimes the accesskey needs to go on
         * a different element than the id, for reverse-compatibility, etc.)
         *
+        * @since 1.16.3
         * @param string $name Id of the element, minus prefixes.
         * @return string Contents of the accesskey attribute (which you must HTML-
         *   escape), or false for no accesskey attribute
@@ -2301,6 +2210,7 @@ class Linker {
        /**
         * Creates a dead (show/hide) link for deleting revisions/log entries
         *
+        * @since 1.16.3
         * @param bool $delete Set to true to use (show/hide) rather than (show)
         *
         * @return string HTML text wrapped in a span to allow for customization
@@ -2318,6 +2228,7 @@ class Linker {
        /**
         * Returns the attributes for the tooltip and access key.
         *
+        * @since 1.16.3. $msgParams introduced in 1.27
         * @param string $name
         * @param array $msgParams Params for constructing the message
         *
@@ -2342,6 +2253,7 @@ class Linker {
 
        /**
         * Returns raw bits of HTML, use titleAttrib()
+        * @since 1.16.3
         * @param string $name
         * @param array|null $options
         * @return null|string
@@ -2361,20 +2273,3 @@ class Linker {
 
 }
 
-/**
- * @since 1.18
- */
-class DummyLinker {
-
-       /**
-        * Use PHP's magic __call handler to transform instance calls to a dummy instance
-        * into static calls to the new Linker for backwards compatibility.
-        *
-        * @param string $fname Name of called method
-        * @param array $args Arguments to the method
-        * @return mixed
-        */
-       public function __call( $fname, $args ) {
-               return call_user_func_array( [ 'Linker', $fname ], $args );
-       }
-}