diff options
author | C. Scott Ananian <cscott@cscott.net> | 2024-02-09 15:19:38 -0500 |
---|---|---|
committer | Bartosz DziewoĆski <dziewonski@fastmail.fm> | 2024-06-10 18:47:32 +0000 |
commit | b855c62f66227820136ef99faf728ca3dd1258e0 (patch) | |
tree | 5b0ef28ebe3214089a701bf64d26c26f7c35ffc0 /includes/linker/Linker.php | |
parent | 0afc5f328051fa24019fec2e0f7f01da624a1834 (diff) | |
download | mediawikicore-b855c62f66227820136ef99faf728ca3dd1258e0.tar.gz mediawikicore-b855c62f66227820136ef99faf728ca3dd1258e0.zip |
Move Linker::makeExternalLink() to the LinkRenderer service
Move Linker::makeExternalLink to the LinkRenderer service, as has been
done with the other static methods of Linker.
In order to allow phan's SecurityCheckPlugin to perform a more accurate
analysis of taintedness, tweak the API of Linker::makeExternalLink to
clearly indicate via the type system whether the link text has already
been escaped or not: a `string` argument will always be escaped, and
if the argument is already escaped it should be passed as an HtmlArmor
object. In refactoring, `Message` arguments were also common, and accept
them as-is to avoid the caller having to think about whether to call
Message::text() or Message::escaped().
This allows us to provide a more precise taint type to the $text argument,
avoids an opaque boolean argument, and avoids spurious errors from
SecurityCheck.
We also require the caller to explicitly pass a Title context, instead
of implicitly relying on the global $wgTitle. This works cleanly
everywhere except for CommentParser, which has a $selfLinkTarget which
generally works as the title context for the external link, but which
is nullable. The original Linker::makeExternalLink() used $wgTitle as
a fallback, but $wgTitle can also be null in some circumstances. The
title context only determines how $wgNoFollowNsExceptions is handled,
so existing code basically just ignored $wgNoFollowNsExceptions when
$wgTitle was null, which isn't terrible. A future refactor could/should
clean up CommentParser to ensure that there is always a non-null title
context that can be used.
Change-Id: I9bcf4780f388ba639a9cc882dd9dd42eda5736ae
Diffstat (limited to 'includes/linker/Linker.php')
-rw-r--r-- | includes/linker/Linker.php | 46 |
1 files changed, 10 insertions, 36 deletions
diff --git a/includes/linker/Linker.php b/includes/linker/Linker.php index b632c3f72ec7..b737520dce6b 100644 --- a/includes/linker/Linker.php +++ b/includes/linker/Linker.php @@ -1137,47 +1137,21 @@ class Linker { * @param LinkTarget|null $title LinkTarget object used for title specific link attributes * @param-taint $title none * @return string + * @deprecated since 1.43; use LinkRenderer::makeExternalLink(), passing + * in an HtmlArmor instance if $escape was false. */ public static function makeExternalLink( $url, $text, $escape = true, $linktype = '', $attribs = [], $title = null ) { global $wgTitle; - $class = 'external'; - if ( $linktype ) { - $class .= " $linktype"; - } - if ( isset( $attribs['class'] ) && $attribs['class'] ) { - $class .= " {$attribs['class']}"; - } - $attribs['class'] = $class; - - if ( $escape ) { - $text = htmlspecialchars( $text, ENT_COMPAT ); - } - - if ( !$title ) { - $title = $wgTitle; - } - $newRel = Parser::getExternalLinkRel( $url, $title ); - if ( !isset( $attribs['rel'] ) || $attribs['rel'] === '' ) { - $attribs['rel'] = $newRel; - } elseif ( $newRel !== null ) { - // Merge the rel attributes. - $newRels = explode( ' ', $newRel ); - $oldRels = explode( ' ', $attribs['rel'] ); - $combined = array_unique( array_merge( $newRels, $oldRels ) ); - $attribs['rel'] = implode( ' ', $combined ); - } - $link = ''; - $success = ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )->onLinkerMakeExternalLink( - $url, $text, $link, $attribs, $linktype ); - if ( !$success ) { - wfDebug( "Hook LinkerMakeExternalLink changed the output of link " - . "with url {$url} and text {$text} to {$link}" ); - return $link; - } - $attribs['href'] = $url; - return Html::rawElement( 'a', $attribs, $text ); + $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); + return $linkRenderer->makeExternalLink( + $url, + $escape ? $text : new HtmlArmor( $text ), + $title ?? $wgTitle, + $linktype, + $attribs + ); } /** |