diff options
Diffstat (limited to 'includes/Linker.php')
-rw-r--r-- | includes/Linker.php | 172 |
1 files changed, 88 insertions, 84 deletions
diff --git a/includes/Linker.php b/includes/Linker.php index be850d02..b58dabab 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -37,23 +37,10 @@ class Linker { const TOOL_LINKS_EMAIL = 2; /** - * Get the appropriate HTML attributes to add to the "a" element of an - * external link, as created by [wikisyntax]. - * - * @param string $class The contents of the class attribute; if an empty - * string is passed, which is the default value, defaults to 'external'. - * @return string - * @deprecated since 1.18 Just pass the external class directly to something - * using Html::expandAttributes. - */ - static function getExternalLinkAttributes( $class = 'external' ) { - wfDeprecated( __METHOD__, '1.18' ); - return self::getLinkAttributesInternal( '', $class ); - } - - /** * Get the appropriate HTML attributes to add to the "a" element of an interwiki link. * + * @deprecated since 1.25 + * * @param string $title The title text for the link, URL-encoded (???) but * not HTML-escaped * @param string $unused Unused @@ -64,6 +51,8 @@ class Linker { static function getInterwikiLinkAttributes( $title, $unused = null, $class = 'external' ) { global $wgContLang; + wfDeprecated( __METHOD__, '1.25' ); + # @todo FIXME: We have a whole bunch of handling here that doesn't happen in # getExternalLinkAttributes, why? $title = urldecode( $title ); @@ -76,6 +65,8 @@ class Linker { /** * Get the appropriate HTML attributes to add to the "a" element of an internal link. * + * @deprecated since 1.25 + * * @param string $title The title text for the link, URL-encoded (???) but * not HTML-escaped * @param string $unused Unused @@ -83,6 +74,8 @@ class Linker { * @return string */ static function getInternalLinkAttributes( $title, $unused = null, $class = '' ) { + wfDeprecated( __METHOD__, '1.25' ); + $title = urldecode( $title ); $title = str_replace( '_', ' ', $title ); return self::getLinkAttributesInternal( $title, $class ); @@ -92,6 +85,8 @@ 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. * + * @deprecated since 1.25 + * * @param Title $nt * @param string $unused Unused * @param string $class The contents of the class attribute, default none @@ -100,6 +95,8 @@ class Linker { * @return string */ static function getInternalLinkAttributesObj( $nt, $unused = null, $class = '', $title = false ) { + wfDeprecated( __METHOD__, '1.25' ); + if ( $title === false ) { $title = $nt->getPrefixedText(); } @@ -109,12 +106,16 @@ class Linker { /** * Common code for getLinkAttributesX functions * + * @deprecated since 1.25 + * * @param string $title * @param string $class * * @return string */ private static function getLinkAttributesInternal( $title, $class ) { + wfDeprecated( __METHOD__, '1.25' ); + $title = htmlspecialchars( $title ); $class = htmlspecialchars( $class ); $r = ''; @@ -193,10 +194,9 @@ class Linker { $target, $html = null, $customAttribs = array(), $query = array(), $options = array() ) { if ( !$target instanceof Title ) { - wfWarn( __METHOD__ . ': Requires $target to be a Title object.' ); + wfWarn( __METHOD__ . ': Requires $target to be a Title object.', 2 ); return "<!-- ERROR -->$html"; } - wfProfileIn( __METHOD__ ); if ( is_string( $query ) ) { // some functions withing core using this still hand over query strings @@ -208,9 +208,9 @@ class Linker { $dummy = new DummyLinker; // dummy linker instance for bc on the hooks $ret = null; - if ( !wfRunHooks( 'LinkBegin', array( $dummy, $target, &$html, - &$customAttribs, &$query, &$options, &$ret ) ) ) { - wfProfileOut( __METHOD__ ); + if ( !Hooks::run( 'LinkBegin', + array( $dummy, $target, &$html, &$customAttribs, &$query, &$options, &$ret ) ) + ) { return $ret; } @@ -218,15 +218,13 @@ class Linker { $target = self::normaliseSpecialPage( $target ); # If we don't know whether the page exists, let's find out. - wfProfileIn( __METHOD__ . '-checkPageExistence' ); - if ( !in_array( 'known', $options ) and !in_array( 'broken', $options ) ) { + if ( !in_array( 'known', $options ) && !in_array( 'broken', $options ) ) { if ( $target->isKnown() ) { $options[] = 'known'; } else { $options[] = 'broken'; } } - wfProfileOut( __METHOD__ . '-checkPageExistence' ); $oldquery = array(); if ( in_array( "forcearticlepath", $options ) && $query ) { @@ -249,11 +247,10 @@ class Linker { } $ret = null; - if ( wfRunHooks( 'LinkEnd', array( $dummy, $target, $options, &$html, &$attribs, &$ret ) ) ) { + if ( Hooks::run( 'LinkEnd', array( $dummy, $target, $options, &$html, &$attribs, &$ret ) ) ) { $ret = Html::rawElement( 'a', $attribs, $html ); } - wfProfileOut( __METHOD__ ); return $ret; } @@ -278,7 +275,6 @@ class Linker { * @return string */ private static function linkUrl( $target, $query, $options ) { - wfProfileIn( __METHOD__ ); # We don't want to include fragments for broken links, because they # generally make no sense. if ( in_array( 'broken', $options ) && $target->hasFragment() ) { @@ -304,7 +300,6 @@ class Linker { } $ret = $target->getLinkURL( $query, false, $proto ); - wfProfileOut( __METHOD__ ); return $ret; } @@ -318,12 +313,10 @@ class Linker { * @return array */ private static function linkAttribs( $target, $attribs, $options ) { - wfProfileIn( __METHOD__ ); global $wgUser; $defaults = array(); if ( !in_array( 'noclasses', $options ) ) { - wfProfileIn( __METHOD__ . '-getClasses' ); # Now build the classes. $classes = array(); @@ -344,7 +337,6 @@ class Linker { if ( $classes != array() ) { $defaults['class'] = implode( ' ', $classes ); } - wfProfileOut( __METHOD__ . '-getClasses' ); } # Get a default title attribute. @@ -364,11 +356,10 @@ class Linker { 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' and $val !== false ) { + if ( $key != 'href' && $val !== false ) { $ret[$key] = $val; } } - wfProfileOut( __METHOD__ ); return $ret; } @@ -409,7 +400,7 @@ class Linker { */ public static function makeSelfLinkObj( $nt, $html = '', $query = '', $trail = '', $prefix = '' ) { $ret = "<strong class=\"selflink\">{$prefix}{$html}</strong>{$trail}"; - if ( !wfRunHooks( 'SelfLinkBegin', array( $nt, &$html, &$trail, &$prefix, &$ret ) ) ) { + if ( !Hooks::run( 'SelfLinkBegin', array( $nt, &$html, &$trail, &$prefix, &$ret ) ) ) { return $ret; } @@ -495,7 +486,7 @@ class Linker { $alt = self::fnamePart( $url ); } $img = ''; - $success = wfRunHooks( 'LinkerMakeExternalImage', array( &$url, &$alt, &$img ) ); + $success = Hooks::run( 'LinkerMakeExternalImage', array( &$url, &$alt, &$img ) ); if ( !$success ) { wfDebug( "Hook LinkerMakeExternalImage changed the output of external image " . "with url {$url} and alt text {$alt} to {$img}\n", true ); @@ -549,7 +540,7 @@ class Linker { ) { $res = null; $dummy = new DummyLinker; - if ( !wfRunHooks( 'ImageBeforeProduceHTML', array( &$dummy, &$title, + if ( !Hooks::run( 'ImageBeforeProduceHTML', array( &$dummy, &$title, &$file, &$frameParams, &$handlerParams, &$time, &$res ) ) ) { return $res; } @@ -931,7 +922,6 @@ class Linker { } global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl; - wfProfileIn( __METHOD__ ); if ( $label == '' ) { $label = $title->getPrefixedText(); } @@ -944,19 +934,16 @@ class Linker { $redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title ); if ( $redir ) { - wfProfileOut( __METHOD__ ); return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) ); } $href = self::getUploadUrl( $title, $query ); - wfProfileOut( __METHOD__ ); return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' . htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' . $encLabel . '</a>'; } - wfProfileOut( __METHOD__ ); return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) ); } @@ -1029,7 +1016,7 @@ class Linker { 'title' => $alt ); - if ( !wfRunHooks( 'LinkerMakeMediaLinkFile', + if ( !Hooks::run( 'LinkerMakeMediaLinkFile', array( $title, $file, &$html, &$attribs, &$ret ) ) ) { wfDebug( "Hook LinkerMakeMediaLinkFile changed the output of link " . "with url {$url} and text {$html} to {$ret}\n", true ); @@ -1088,7 +1075,7 @@ class Linker { } $attribs['rel'] = Parser::getExternalLinkRel( $url, $title ); $link = ''; - $success = wfRunHooks( 'LinkerMakeExternalLink', + $success = Hooks::run( 'LinkerMakeExternalLink', array( &$url, &$text, &$link, &$attribs, $linktype ) ); if ( !$success ) { wfDebug( "Hook LinkerMakeExternalLink changed the output of link " @@ -1174,10 +1161,10 @@ class Linker { $items[] = self::emailLink( $userId, $userText ); } - wfRunHooks( 'UserToolLinksEdit', array( $userId, $userText, &$items ) ); + Hooks::run( 'UserToolLinksEdit', array( $userId, $userText, &$items ) ); if ( $items ) { - return wfMessage( 'word-separator' )->plain() + return wfMessage( 'word-separator' )->escaped() . '<span class="mw-usertoollinks">' . wfMessage( 'parentheses' )->rawParams( $wgLang->pipeList( $items ) )->escaped() . '</span>'; @@ -1264,7 +1251,6 @@ class Linker { $userId = $rev->getUser( Revision::FOR_THIS_USER ); $userText = $rev->getUserText( Revision::FOR_THIS_USER ); $link = self::userLink( $userId, $userText ) - . wfMessage( 'word-separator' )->plain() . self::userToolLinks( $userId, $userText ); } else { $link = wfMessage( 'rev-deleted-user' )->escaped(); @@ -1293,7 +1279,6 @@ class Linker { * @return mixed|string */ public static function formatComment( $comment, $title = null, $local = false ) { - wfProfileIn( __METHOD__ ); # Sanitize text a bit: $comment = str_replace( "\n", " ", $comment ); @@ -1304,12 +1289,12 @@ class Linker { $comment = self::formatAutocomments( $comment, $title, $local ); $comment = self::formatLinksInComment( $comment, $title, $local ); - wfProfileOut( __METHOD__ ); return $comment; } /** * Converts autogenerated comments in edit summaries into section links. + * * The pattern for autogen comments is / * foo * /, which makes for * some nasty regex. * We look for all comments, match any text before and after the comment, @@ -1322,16 +1307,30 @@ class Linker { * @return string Formatted comment */ private static function formatAutocomments( $comment, $title = null, $local = false ) { - return preg_replace_callback( - '!(.*)/\*\s*(.*?)\s*\*/(.*)!', - function ( $match ) use ( $title, $local ) { + // @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 + // wiki, both when autocomments exist and when they don't, and + // (2) what markup will make that actually happen. + $append = ''; + $comment = preg_replace_callback( + // To detect the presence of content before or after the + // auto-comment, we use capturing groups inside optional zero-width + // assertions. But older versions of PCRE can't directly make + // zero-width assertions optional, so wrap them in a non-capturing + // group. + '!(?:(?<=(.)))?/\*\s*(.*?)\s*\*/(?:(?=(.)))?!', + function ( $match ) use ( $title, $local, &$append ) { global $wgLang; - $pre = $match[1]; + // Ensure all match positions are defined + $match += array( '', '', '', '' ); + + $pre = $match[1] !== ''; $auto = $match[2]; - $post = $match[3]; + $post = $match[3] !== ''; $comment = null; - wfRunHooks( 'FormatAutocomments', array( &$comment, $pre, $auto, $post, $title, $local ) ); + Hooks::run( 'FormatAutocomments', array( &$comment, $pre, $auto, $post, $title, $local ) ); if ( $comment === null ) { $link = ''; if ( $title ) { @@ -1359,7 +1358,7 @@ class Linker { } if ( $pre ) { # written summary $presep autocomment (summary /* section */) - $pre .= wfMessage( 'autocomment-prefix' )->inContentLanguage()->escaped(); + $pre = wfMessage( 'autocomment-prefix' )->inContentLanguage()->escaped(); } if ( $post ) { # autocomment $postsep written summary (/* section */ summary) @@ -1367,12 +1366,14 @@ class Linker { } $auto = '<span class="autocomment">' . $auto . '</span>'; $comment = $pre . $link . $wgLang->getDirMark() - . '<span dir="auto">' . $auto . $post . '</span>'; + . '<span dir="auto">' . $auto; + $append .= '</span>'; } return $comment; }, $comment ); + return $comment . $append; } /** @@ -1383,9 +1384,13 @@ 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 + * * @return string */ - public static function formatLinksInComment( $comment, $title = null, $local = false ) { + public static function formatLinksInComment( + $comment, $title = null, $local = false, $wikiId = null + ) { return preg_replace_callback( '/ \[\[ @@ -1399,7 +1404,7 @@ class Linker { \]\] ([^[]*) # 3. link trail (the text up until the next link) /x', - function ( $match ) use ( $title, $local ) { + function ( $match ) use ( $title, $local, $wikiId ) { global $wgContLang; $medians = '(?:' . preg_quote( MWNamespace::getCanonicalName( NS_MEDIA ), '/' ) . '|'; @@ -1455,11 +1460,22 @@ class Linker { $newTarget = clone ( $title ); $newTarget->setFragment( '#' . $target->getFragment() ); $target = $newTarget; + } - $thelink = Linker::link( - $target, - $linkText . $inside - ) . $trail; + + if ( $wikiId !== null ) { + $thelink = Linker::makeExternalLink( + WikiMap::getForeignURL( $wikiId, $target->getFullText() ), + $linkText . $inside, + /* escape = */ false // Already escaped + ) . $trail; + } else { + $thelink = Linker::link( + $target, + $linkText . $inside + ) . $trail; + } + } } if ( $thelink ) { @@ -1489,11 +1505,13 @@ class Linker { # Foobar -- normal # :Foobar -- override special treatment of prefix (images, language links) # /Foobar -- convert to CurrentPage/Foobar - # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text + # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial and final / from text # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage - # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage + # ../Foobar -- convert to CurrentPage/Foobar, + # (from CurrentPage/CurrentSubPage) + # ../Foobar/ -- convert to CurrentPage/Foobar, use 'Foobar' as text + # (from CurrentPage/CurrentSubPage) - wfProfileIn( __METHOD__ ); $ret = $target; # default return value is no change # Some namespaces don't allow subpages, @@ -1537,7 +1555,7 @@ class Linker { $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) ); # / at the end means don't show full path if ( substr( $nodotdot, -1, 1 ) === '/' ) { - $nodotdot = substr( $nodotdot, 0, -1 ); + $nodotdot = rtrim( $nodotdot, '/' ); if ( $text === '' ) { $text = $nodotdot . $suffix; } @@ -1552,7 +1570,6 @@ class Linker { } } - wfProfileOut( __METHOD__ ); return $ret; } @@ -1589,7 +1606,7 @@ class Linker { * @return string HTML fragment */ public static function revComment( Revision $rev, $local = false, $isPublic = false ) { - if ( $rev->getRawComment() == "" ) { + if ( $rev->getComment( Revision::RAW ) == "" ) { return ""; } if ( $rev->isDeleted( Revision::DELETED_COMMENT ) && $isPublic ) { @@ -1807,7 +1824,7 @@ class Linker { $inner = self::buildRollbackLink( $rev, $context, $editCount ); if ( !in_array( 'noBrackets', $options ) ) { - $inner = $context->msg( 'brackets' )->rawParams( $inner )->plain(); + $inner = $context->msg( 'brackets' )->rawParams( $inner )->escaped(); } return '<span class="mw-rollback-link">' . $inner . '</span>'; @@ -1854,7 +1871,7 @@ class Linker { $editCount = 0; $moreRevs = false; foreach ( $res as $row ) { - if ( $rev->getRawUserText() != $row->rev_user_text ) { + if ( $rev->getUserText( Revision::RAW ) != $row->rev_user_text ) { if ( $verify && ( $row->rev_deleted & Revision::DELETED_TEXT || $row->rev_deleted & Revision::DELETED_USER @@ -1892,7 +1909,7 @@ class Linker { ) { global $wgShowRollbackEditCount, $wgMiserMode; - // To config which pages are effected by miser mode + // To config which pages are affected by miser mode $disableRollbackEditCountSpecialPage = array( 'Recentchanges', 'Watchlist' ); if ( $context === null ) { @@ -1975,7 +1992,6 @@ class Linker { $section = false, $more = null ) { global $wgLang; - wfProfileIn( __METHOD__ ); $outText = ''; if ( count( $templates ) > 0 ) { @@ -2028,14 +2044,14 @@ class Linker { if ( $titleObj->quickUserCan( 'edit' ) ) { $editLink = self::link( $titleObj, - wfMessage( 'editlink' )->text(), + wfMessage( 'editlink' )->escaped(), array(), array( 'action' => 'edit' ) ); } else { $editLink = self::link( $titleObj, - wfMessage( 'viewsourcelink' )->text(), + wfMessage( 'viewsourcelink' )->escaped(), array(), array( 'action' => 'edit' ) ); @@ -2055,7 +2071,6 @@ class Linker { $outText .= '</ul>'; } - wfProfileOut( __METHOD__ ); return $outText; } @@ -2067,7 +2082,6 @@ class Linker { * @return string HTML output */ public static function formatHiddenCategories( $hiddencats ) { - wfProfileIn( __METHOD__ ); $outText = ''; if ( count( $hiddencats ) > 0 ) { @@ -2084,7 +2098,6 @@ class Linker { } $outText .= '</ul>'; } - wfProfileOut( __METHOD__ ); return $outText; } @@ -2113,7 +2126,6 @@ class Linker { * escape), or false for no title attribute */ public static function titleAttrib( $name, $options = null ) { - wfProfileIn( __METHOD__ ); $message = wfMessage( "tooltip-$name" ); @@ -2142,7 +2154,6 @@ class Linker { } } - wfProfileOut( __METHOD__ ); return $tooltip; } @@ -2162,7 +2173,6 @@ class Linker { if ( isset( self::$accesskeycache[$name] ) ) { return self::$accesskeycache[$name]; } - wfProfileIn( __METHOD__ ); $message = wfMessage( "accesskey-$name" ); @@ -2178,7 +2188,6 @@ class Linker { } } - wfProfileOut( __METHOD__ ); self::$accesskeycache[$name] = $accesskey; return self::$accesskeycache[$name]; } @@ -2286,7 +2295,6 @@ class Linker { static function makeLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) { wfDeprecated( __METHOD__, '1.21' ); - wfProfileIn( __METHOD__ ); $query = wfCgiToArray( $query ); list( $inside, $trail ) = self::splitTrail( $trail ); if ( $text === '' ) { @@ -2295,7 +2303,6 @@ class Linker { $ret = self::link( $nt, "$prefix$text$inside", array(), $query ) . $trail; - wfProfileOut( __METHOD__ ); return $ret; } @@ -2320,8 +2327,6 @@ class Linker { ) { wfDeprecated( __METHOD__, '1.21' ); - wfProfileIn( __METHOD__ ); - if ( $text == '' ) { $text = self::linkText( $title ); } @@ -2335,7 +2340,6 @@ class Linker { $ret = self::link( $title, "$prefix$text$inside", $attribs, $query, array( 'known', 'noclasses' ) ) . $trail; - wfProfileOut( __METHOD__ ); return $ret; } |