* @file
*/
+use MediaWiki\MediaWikiServices;
+use Wikimedia\WrappedString;
+use Wikimedia\WrappedStringList;
+
/**
* @defgroup Skins Skins
*/
* @ingroup Skins
*/
abstract class Skin extends ContextSource {
+ /**
+ * @var string|null
+ */
protected $skinname = null;
+
protected $mRelevantTitle = null;
protected $mRelevantUser = null;
static function normalizeKey( $key ) {
global $wgDefaultSkin, $wgFallbackSkin;
- $skinNames = Skin::getSkinNames();
+ $skinNames = self::getSkinNames();
// Make keys lowercase for case-insensitive matching.
$skinNames = array_change_key_case( $skinNames, CASE_LOWER );
}
/**
- * @return string Skin name
+ * @since 1.31
+ * @param string|null $skinname
+ */
+ public function __construct( $skinname = null ) {
+ if ( is_string( $skinname ) ) {
+ $this->skinname = $skinname;
+ }
+ }
+
+ /**
+ * @return string|null Skin name
*/
public function getSkinName() {
return $this->skinname;
/**
* @param OutputPage $out
*/
- function initPage( OutputPage $out ) {
-
+ public function initPage( OutputPage $out ) {
$this->preloadExistence();
-
}
/**
* Defines the ResourceLoader modules that should be added to the skin
* It is recommended that skins wishing to override call parent::getDefaultModules()
* and substitute out any modules they wish to change by using a key to look them up
+ *
+ * Any modules defined with the 'styles' key will be added as render blocking CSS via
+ * Output::addModuleStyles. Similarly, each key should refer to a list of modules
+ *
* @return array Array of modules with helper keys for easy overriding
*/
public function getDefaultModules() {
- global $wgUseAjax, $wgEnableAPI, $wgEnableWriteAPI;
-
$out = $this->getOutput();
- $user = $out->getUser();
+ $config = $this->getConfig();
+ $user = $this->getUser();
+
+ // Modules declared in the $modules literal are loaded
+ // for ALL users, on ALL pages, in ALL skins.
+ // Keep this list as small as possible!
$modules = [
- // modules that enhance the page content in some way
+ 'styles' => [
+ // The 'styles' key sets render-blocking style modules
+ // Unlike other keys in $modules, this is an associative array
+ // where each key is its own group pointing to a list of modules
+ 'core' => [
+ 'mediawiki.legacy.shared',
+ 'mediawiki.legacy.commonPrint',
+ ],
+ 'content' => [],
+ 'syndicate' => [],
+ ],
+ 'core' => [
+ 'site',
+ 'mediawiki.page.startup',
+ 'mediawiki.user',
+ ],
+ // modules that enhance the content in some way
'content' => [
'mediawiki.page.ready',
],
- // modules that exist for legacy reasons
- 'legacy' => ResourceLoaderStartUpModule::getLegacyModules(),
// modules relating to search functionality
'search' => [],
// modules relating to functionality relating to watching an article
'watch' => [],
// modules which relate to the current users preferences
'user' => [],
+ // modules relating to RSS/Atom Feeds
+ 'syndicate' => [],
];
- // Add various resources if required
- if ( $wgUseAjax && $wgEnableAPI ) {
- if ( $wgEnableWriteAPI && $user->isLoggedIn()
- && $user->isAllowedAll( 'writeapi', 'viewmywatchlist', 'editmywatchlist' )
- && $this->getRelevantTitle()->canExist()
- ) {
- $modules['watch'][] = 'mediawiki.page.watch.ajax';
- }
+ // Preload jquery.tablesorter for mediawiki.page.ready
+ if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
+ $modules['content'][] = 'jquery.tablesorter';
+ }
+
+ // Preload jquery.makeCollapsible for mediawiki.page.ready
+ if ( strpos( $out->getHTML(), 'mw-collapsible' ) !== false ) {
+ $modules['content'][] = 'jquery.makeCollapsible';
+ $modules['styles']['content'][] = 'jquery.makeCollapsible.styles';
+ }
+
+ // Deprecated since 1.26: Unconditional loading of mediawiki.ui.button
+ // on every page is deprecated. Express a dependency instead.
+ if ( strpos( $out->getHTML(), 'mw-ui-button' ) !== false ) {
+ $modules['styles']['content'][] = 'mediawiki.ui.button';
+ }
- $modules['search'][] = 'mediawiki.searchSuggest';
+ if ( $out->isTOCEnabled() ) {
+ $modules['content'][] = 'mediawiki.toc';
+ $modules['styles']['content'][] = 'mediawiki.toc.styles';
}
+ // Add various resources if required
+ if ( $user->isLoggedIn()
+ && $user->isAllowedAll( 'writeapi', 'viewmywatchlist', 'editmywatchlist' )
+ && $this->getRelevantTitle()->canExist()
+ ) {
+ $modules['watch'][] = 'mediawiki.page.watch.ajax';
+ }
+
+ $modules['search'][] = 'mediawiki.searchSuggest';
+
if ( $user->getBoolOption( 'editsectiononrightclick' ) ) {
$modules['user'][] = 'mediawiki.action.view.rightClickEdit';
}
if ( $out->isArticle() && $user->getOption( 'editondblclick' ) ) {
$modules['user'][] = 'mediawiki.action.view.dblClickEdit';
}
+
+ if ( $out->isSyndicated() ) {
+ $modules['styles']['syndicate'][] = 'mediawiki.feedlink';
+ }
+
return $modules;
}
/**
* Preload the existence of three commonly-requested pages in a single query
*/
- function preloadExistence() {
+ protected function preloadExistence() {
$titles = [];
- $user = $this->getUser();
- $title = $this->getRelevantTitle();
-
// User/talk link
+ $user = $this->getUser();
if ( $user->isLoggedIn() ) {
$titles[] = $user->getUserPage();
$titles[] = $user->getTalkPage();
}
// Check, if the page can hold some kind of content, otherwise do nothing
- if ( !$title->canExist() ) {
- // nothing
- } elseif ( $title->isTalkPage() ) {
- $titles[] = $title->getSubjectPage();
- } else {
- $titles[] = $title->getTalkPage();
+ $title = $this->getRelevantTitle();
+ if ( $title->canExist() ) {
+ if ( $title->isTalkPage() ) {
+ $titles[] = $title->getSubjectPage();
+ } else {
+ $titles[] = $title->getTalkPage();
+ }
+ }
+
+ // Footer links (used by SkinTemplate::prepareQuickTemplate)
+ foreach ( [
+ $this->footerLinkTitle( 'privacy', 'privacypage' ),
+ $this->footerLinkTitle( 'aboutsite', 'aboutpage' ),
+ $this->footerLinkTitle( 'disclaimers', 'disclaimerpage' ),
+ ] as $title ) {
+ if ( $title ) {
+ $titles[] = $title;
+ }
}
Hooks::run( 'SkinPreloadExistence', [ &$titles, $this ] );
- if ( count( $titles ) ) {
+ if ( $titles ) {
$lb = new LinkBatch( $titles );
$lb->setCaller( __METHOD__ );
$lb->execute();
/**
* Outputs the HTML generated by other functions.
- * @param OutputPage $out
+ * @param OutputPage|null $out
*/
abstract function outputPage( OutputPage $out = null );
/**
* @param array $data
- * @return string
+ * @param string|null $nonce OutputPage::getCSPNonce()
+ * @return string|WrappedString HTML
*/
- static function makeVariablesScript( $data ) {
+ public static function makeVariablesScript( $data, $nonce = null ) {
if ( $data ) {
return ResourceLoader::makeInlineScript(
- ResourceLoader::makeConfigSetScript( $data )
+ ResourceLoader::makeConfigSetScript( $data ),
+ $nonce
);
- } else {
- return '';
}
+ return '';
}
/**
}
/**
- * Add skin specific stylesheets
- * Calling this method with an $out of anything but the same OutputPage
- * inside ->getOutput() is deprecated. The $out arg is kept
- * for compatibility purposes with skins.
- * @param OutputPage $out
- * @todo delete
+ * Hook point for adding style modules to OutputPage.
+ *
+ * @deprecated since 1.32 Use getDefaultModules() instead.
+ * @param OutputPage $out Legacy parameter, identical to $this->getOutput()
*/
- abstract function setupSkinUserCss( OutputPage $out );
+ public function setupSkinUserCss( OutputPage $out ) {
+ // Stub.
+ }
/**
* TODO: document
if ( $title->isSpecialPage() ) {
$type = 'ns-special';
- // bug 23315: provide a class based on the canonical special page name without subpages
- list( $canonicalName ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+ // T25315: provide a class based on the canonical special page name without subpages
+ list( $canonicalName ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
+ resolveAlias( $title->getDBkey() );
if ( $canonicalName ) {
$type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
} else {
* "<body>" tag, skins can override it if they have a need to add in any
* body attributes or classes of their own.
* @param OutputPage $out
- * @param array $bodyAttrs
+ * @param array &$bodyAttrs
*/
function addToBodyAttributes( $out, &$bodyAttrs ) {
// does nothing by default
return $wgLogo;
}
+ /**
+ * Whether the logo should be preloaded with an HTTP link header or not
+ * @since 1.29
+ * @return bool
+ */
+ public function shouldPreloadLogo() {
+ return false;
+ }
+
/**
* @return string HTML
*/
/**
* This gets called shortly before the "</body>" tag.
*
- * @return string HTML-wrapped JS code to be put before "</body>"
+ * @return string|WrappedStringList HTML containing scripts to put before `</body>`
*/
function bottomScripts() {
// TODO and the suckage continues. This function is really just a wrapper around
// OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
// up at some point
- $bottomScriptText = $this->getOutput()->getBottomScripts();
- Hooks::run( 'SkinAfterBottomScripts', [ $this, &$bottomScriptText ] );
-
- return $bottomScriptText;
+ $chunks = [ $this->getOutput()->getBottomScripts() ];
+
+ // Keep the hook appendage separate to preserve WrappedString objects.
+ // This enables BaseTemplate::getTrail() to merge them where possible.
+ $extraHtml = '';
+ Hooks::run( 'SkinAfterBottomScripts', [ $this, &$extraHtml ] );
+ if ( $extraHtml !== '' ) {
+ $chunks[] = $extraHtml;
+ }
+ return WrappedString::join( "\n", $chunks );
}
/**
}
/**
+ * @param OutputPage|null $out Defaults to $this->getOutput() if left as null
* @return string
*/
- function subPageSubtitle() {
- $out = $this->getOutput();
+ function subPageSubtitle( $out = null ) {
+ if ( $out === null ) {
+ $out = $this->getOutput();
+ }
+ $title = $out->getTitle();
$subpages = '';
if ( !Hooks::run( 'SkinSubPageSubtitle', [ &$subpages, $this, $out ] ) ) {
return $subpages;
}
- if ( $out->isArticle() && MWNamespace::hasSubpages( $out->getTitle()->getNamespace() ) ) {
- $ptext = $this->getTitle()->getPrefixedText();
- if ( preg_match( '/\//', $ptext ) ) {
+ if ( $out->isArticle() && MWNamespace::hasSubpages( $title->getNamespace() ) ) {
+ $ptext = $title->getPrefixedText();
+ if ( strpos( $ptext, '/' ) !== false ) {
$links = explode( '/', $ptext );
array_pop( $links );
$c = 0;
return $subpages;
}
- /**
- * @deprecated since 1.27, feature removed
- * @return bool Always false
- */
- function showIPinHeader() {
- wfDeprecated( __METHOD__, '1.27' );
- return false;
- }
-
/**
* @return string
*/
$s = '';
}
- if ( wfGetLB()->getLaggedSlaveMode() ) {
+ if ( MediaWikiServices::getInstance()->getDBLoadBalancer()->getLaggedReplicaMode() ) {
$s .= ' <strong>' . $this->msg( 'laggedslavemode' )->parse() . '</strong>';
}
if ( is_string( $icon ) ) {
$html = $icon;
} else { // Assuming array
- $url = isset( $icon["url"] ) ? $icon["url"] : null;
+ $url = $icon["url"] ?? null;
unset( $icon["url"] );
if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
// do this the lazy way, just pass icon data as an attribute array
$html = htmlspecialchars( $icon["alt"] );
}
if ( $url ) {
- $html = Html::rawElement( 'a', [ "href" => $url ], $html );
+ global $wgExternalLinkTarget;
+ $html = Html::rawElement( 'a',
+ [ "href" => $url, "target" => $wgExternalLinkTarget ],
+ $html );
}
}
return $html;
* @return string HTML anchor
*/
public function footerLink( $desc, $page ) {
- // if the link description has been set to "-" in the default language,
- if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
- // then it is disabled, for all languages.
+ $title = $this->footerLinkTitle( $desc, $page );
+ if ( !$title ) {
return '';
- } else {
- // Otherwise, we display the link for the user, described in their
- // language (which may or may not be the same as the default language),
- // but we make the link target be the one site-wide page.
- $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
+ }
- if ( !$title ) {
- return '';
- }
+ return Linker::linkKnown(
+ $title,
+ $this->msg( $desc )->escaped()
+ );
+ }
- return Linker::linkKnown(
- $title,
- $this->msg( $desc )->escaped()
- );
+ /**
+ * @param string $desc
+ * @param string $page
+ * @return Title|null
+ */
+ private function footerLinkTitle( $desc, $page ) {
+ // If the link description has been set to "-" in the default language,
+ if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
+ // then it is disabled, for all languages.
+ return null;
}
+ // Otherwise, we display the link for the user, described in their
+ // language (which may or may not be the same as the default language),
+ // but we make the link target be the one site-wide page.
+ $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
+
+ return $title ?: null;
}
/**
$targetUser = User::newFromId( $id );
}
- # The sending user must have a confirmed email address and the target
- # user must have a confirmed email address and allow emails from users.
- return $this->getUser()->canSendEmail() &&
- $targetUser->canReceiveEmail();
+ # The sending user must have a confirmed email address and the receiving
+ # user must accept emails from the sender.
+ return $this->getUser()->canSendEmail()
+ && SpecialEmailUser::validateTarget( $targetUser, $this->getUser() ) === '';
}
/**
- * Return a fully resolved style path url to images or styles stored in the current skins's folder.
- * This method returns a url resolved using the configured skin style path
- * and includes the style version inside of the url.
+ * Return a fully resolved style path URL to images or styles stored in the
+ * current skin's folder. This method returns a URL resolved using the
+ * configured skin style path.
*
* Requires $stylename to be set, otherwise throws MWException.
*
* @param string $name The name or path of a skin resource file
- * @return string The fully resolved style path url including styleversion
+ * @return string The fully resolved style path URL
* @throws MWException
*/
function getSkinStylePath( $name ) {
- global $wgStylePath, $wgStyleVersion;
+ global $wgStylePath;
if ( $this->stylename === null ) {
- $class = get_class( $this );
+ $class = static::class;
throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
}
- return "$wgStylePath/{$this->stylename}/$name?$wgStyleVersion";
+ return "$wgStylePath/{$this->stylename}/$name";
}
/* these are used extensively in SkinTemplate, but also some other places */
/**
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @return string
*/
static function makeMainPageUrl( $urlaction = '' ) {
$title = Title::newMainPage();
self::checkTitle( $title, '' );
- return $title->getLocalURL( $urlaction );
+ return $title->getLinkURL( $urlaction );
}
/**
* URL with the protocol specified.
*
* @param string $name Name of the Special page
- * @param string $urlaction Query to append
+ * @param string|string[] $urlaction Query to append
* @param string|null $proto Protocol to use or null for a local URL
* @return string
*/
/**
* @param string $name
* @param string $subpage
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @return string
*/
static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
/**
* @param string $name
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @return string
*/
static function makeI18nUrl( $name, $urlaction = '' ) {
/**
* @param string $name
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @return string
*/
static function makeUrl( $name, $urlaction = '' ) {
/**
* this can be passed the NS number as defined in Language.php
* @param string $name
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @param int $namespace
* @return string
*/
/**
* these return an array with the 'href' and boolean 'exists'
* @param string $name
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @return array
*/
static function makeUrlDetails( $name, $urlaction = '' ) {
/**
* Make URL details where the article exists (or at least it's convenient to think so)
* @param string $name Article name
- * @param string $urlaction
+ * @param string|string[] $urlaction
* @return array
*/
static function makeKnownUrlDetails( $name, $urlaction = '' ) {
/**
* make sure we have some title to operate on
*
- * @param Title $title
+ * @param Title &$title
* @param string $name
*/
static function checkTitle( &$title, $name ) {
*
* BaseTemplate::getSidebar can be used to simplify the format and id generation in new skins.
*
- * The format of the returned array is array( heading => content, ... ), where:
+ * The format of the returned array is [ heading => content, ... ], where:
* - heading is the heading of a navigation portlet. It is either:
* - magic string to be handled by the skins ('SEARCH' / 'LANGUAGES' / 'TOOLBOX' / ...)
* - a message name (e.g. 'navigation'), the message should be HTML-escaped by the skin
*
* @return array
*/
- function buildSidebar() {
+ public function buildSidebar() {
global $wgEnableSidebarCache, $wgSidebarCacheExpiry;
- $that = $this;
- $callback = function () use ( $that ) {
+ $callback = function ( $old = null, &$ttl = null ) {
$bar = [];
- $that->addToSidebar( $bar, 'sidebar' );
- Hooks::run( 'SkinBuildSidebar', [ $that, &$bar ] );
+ $this->addToSidebar( $bar, 'sidebar' );
+ Hooks::run( 'SkinBuildSidebar', [ $this, &$bar ] );
+ if ( MessageCache::singleton()->isDisabled() ) {
+ $ttl = WANObjectCache::TTL_UNCACHEABLE; // bug T133069
+ }
return $bar;
};
- if ( $wgEnableSidebarCache ) {
- $cache = ObjectCache::getMainWANInstance();
- $sidebar = $cache->getWithSetCallback(
- $cache->makeKey( 'sidebar', $this->getLanguage()->getCode() ),
- MessageCache::singleton()->isDisabled()
- ? $cache::TTL_UNCACHEABLE // bug T133069
- : $wgSidebarCacheExpiry,
+ $msgCache = MessageCache::singleton();
+ $wanCache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+
+ $sidebar = $wgEnableSidebarCache
+ ? $wanCache->getWithSetCallback(
+ $wanCache->makeKey( 'sidebar', $this->getLanguage()->getCode() ),
+ $wgSidebarCacheExpiry,
$callback,
- [ 'lockTSE' => 30 ]
- );
- } else {
- $sidebar = $callback();
- }
+ [
+ 'checkKeys' => [
+ // Unless there is both no exact $code override nor an i18n definition
+ // in the software, the only MediaWiki page to check is for $code.
+ $msgCache->getCheckKey( $this->getLanguage()->getCode() )
+ ],
+ 'lockTSE' => 30
+ ]
+ )
+ : $callback();
// Apply post-processing to the cached value
Hooks::run( 'SidebarBeforeOutput', [ $this, &$sidebar ] );
*
* This is just a wrapper around addToSidebarPlain() for backwards compatibility
*
- * @param array $bar
+ * @param array &$bar
* @param string $message
*/
public function addToSidebar( &$bar, $message ) {
/**
* Add content from plain text
* @since 1.17
- * @param array $bar
+ * @param array &$bar
* @param string $text
* @return array
*/
$lines = explode( "\n", $text );
$heading = '';
+ $messageTitle = $this->getConfig()->get( 'EnableSidebarCache' )
+ ? Title::newMainPage() : $this->getTitle();
foreach ( $lines as $line ) {
if ( strpos( $line, '*' ) !== 0 ) {
$line = trim( $line, '* ' );
if ( strpos( $line, '|' ) !== false ) { // sanity check
- $line = MessageCache::singleton()->transform( $line, false, null, $this->getTitle() );
+ $line = MessageCache::singleton()->transform( $line, false, null, $messageTitle );
$line = array_map( 'trim', explode( '|', $line, 2 ) );
if ( count( $line ) !== 2 ) {
// Second sanity check, could be hit by people doing
- // funky stuff with parserfuncs... (bug 33321)
+ // funky stuff with parserfuncs... (T35321)
continue;
}
$extraAttribs = [];
- $msgLink = $this->msg( $line[0] )->inContentLanguage();
+ $msgLink = $this->msg( $line[0] )->title( $messageTitle )->inContentLanguage();
if ( $msgLink->exists() ) {
$link = $msgLink->text();
if ( $link == '-' ) {
} else {
$link = $line[0];
}
- $msgText = $this->msg( $line[1] );
+ $msgText = $this->msg( $line[1] )->title( $messageTitle );
if ( $msgText->exists() ) {
$text = $msgText->text();
} else {
$bar[$heading][] = array_merge( [
'text' => $text,
'href' => $href,
- 'id' => 'n-' . Sanitizer::escapeId( strtr( $line[1], ' ', '-' ), 'noninitial' ),
- 'active' => false
+ 'id' => Sanitizer::escapeIdForAttribute( 'n-' . strtr( $line[1], ' ', '-' ) ),
+ 'active' => false,
], $extraAttribs );
} else {
continue;
* @return string
*/
function getNewtalks() {
-
$newMessagesAlert = '';
$user = $this->getUser();
$newtalks = $user->getNewMessageLinks();
if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
$uTalkTitle = $user->getTalkPage();
- $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
+ $lastSeenRev = $newtalks[0]['rev'] ?? null;
$nofAuthors = 0;
if ( $lastSeenRev !== null ) {
$plural = true; // Default if we have a last seen revision: if unknown, use plural
$uTalkTitle,
$this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
[],
- [ 'redirect' => 'no' ]
+ $uTalkTitle->isRedirect() ? [ 'redirect' => 'no' ] : []
);
$newMessagesDiffLink = Linker::linkKnown(
* should fall back to the next notice in its sequence
*/
private function getCachedNotice( $name ) {
- global $wgRenderHashAppend, $parserMemc, $wgContLang;
+ global $wgRenderHashAppend;
$needParse = false;
$notice = $msg->plain();
}
- // Use the extra hash appender to let eg SSL variants separately cache.
- $key = wfMemcKey( $name . $wgRenderHashAppend );
- $cachedNotice = $parserMemc->get( $key );
- if ( is_array( $cachedNotice ) ) {
- if ( md5( $notice ) == $cachedNotice['hash'] ) {
- $notice = $cachedNotice['html'];
- } else {
- $needParse = true;
+ $services = MediaWikiServices::getInstance();
+ $cache = $services->getMainWANObjectCache();
+ $parsed = $cache->getWithSetCallback(
+ // Use the extra hash appender to let eg SSL variants separately cache
+ // Key is verified with md5 hash of unparsed wikitext
+ $cache->makeKey( $name, $wgRenderHashAppend, md5( $notice ) ),
+ // TTL in seconds
+ 600,
+ function () use ( $notice ) {
+ return $this->getOutput()->parse( $notice );
}
- } else {
- $needParse = true;
- }
-
- if ( $needParse ) {
- $parsed = $this->getOutput()->parse( $notice );
- $parserMemc->set( $key, [ 'html' => $parsed, 'hash' => md5( $notice ) ], 600 );
- $notice = $parsed;
- }
+ );
- $notice = Html::rawElement( 'div', [ 'id' => 'localNotice',
- 'lang' => $wgContLang->getHtmlCode(), 'dir' => $wgContLang->getDir() ], $notice );
- return $notice;
+ $contLang = $services->getContentLanguage();
+ return Html::rawElement(
+ 'div',
+ [
+ 'id' => 'localNotice',
+ 'lang' => $contLang->getHtmlCode(),
+ 'dir' => $contLang->getDir()
+ ],
+ $parsed
+ );
}
/**
}
/**
- * Create a section edit link. This supersedes editSectionLink() and
- * editSectionLinkForOther().
+ * Create a section edit link.
*
* @param Title $nt The title being linked to (may not be the same as
* the current page, if the section is included from a template)
* @param string $section The designation of the section being pointed to,
* to be included in the link, like "§ion=$section"
- * @param string $tooltip The tooltip to use for the link: will be escaped
+ * @param string|null $tooltip The tooltip to use for the link: will be escaped
* and wrapped in the 'editsectionhint' message
* @param string $lang Language code
* @return string HTML to use for edit link
$attribs = [];
if ( !is_null( $tooltip ) ) {
- # Bug 25462: undo double-escaping.
- $tooltip = Sanitizer::decodeCharReferences( $tooltip );
$attribs['title'] = wfMessage( 'editsectionhint' )->rawParams( $tooltip )
->inLanguage( $lang )->text();
}
$result .= implode(
'<span class="mw-editsection-divider">'
- . wfMessage( 'pipe-separator' )->inLanguage( $lang )->text()
+ . wfMessage( 'pipe-separator' )->inLanguage( $lang )->escaped()
. '</span>',
$linksHtml
);
return $result;
}
- /** @deprecated in 1.21 */
- public function commentBlock( $comment, $title = null, $local = false, $wikiId = null ) {
- wfDeprecated( __METHOD__, '1.21' );
- return Linker::commentBlock( $comment, $title, $local, $wikiId );
- }
-
- /** @deprecated in 1.21 */
- public function generateRollback(
- $rev,
- IContextSource $context = null,
- $options = [ 'verify' ]
- ) {
- wfDeprecated( __METHOD__, '1.21' );
- return Linker::generateRollback( $rev, $context, $options );
- }
-
- /** @deprecated in 1.21 */
- public function link( $target, $html = null, $customAttribs = [], $query = [], $options = [] ) {
- wfDeprecated( __METHOD__, '1.21' );
- return Linker::link( $target, $html, $customAttribs, $query, $options );
- }
-
- /** @deprecated in 1.21 */
- public function linkKnown(
- $target,
- $html = null,
- $customAttribs = [],
- $query = [],
- $options = [ 'known', 'noclasses' ]
- ) {
- wfDeprecated( __METHOD__, '1.21' );
- return Linker::linkKnown( $target, $html, $customAttribs, $query, $options );
- }
-
- /** @deprecated in 1.21 */
- public function userLink( $userId, $userName, $altUserName = false ) {
- wfDeprecated( __METHOD__, '1.21' );
- return Linker::userLink( $userId, $userName, $altUserName );
- }
-
- /** @deprecated in 1.21 */
- public function userToolLinks(
- $userId,
- $userText,
- $redContribsWhenNoEdits = false,
- $flags = 0,
- $edits = null
- ) {
- wfDeprecated( __METHOD__, '1.21' );
- return Linker::userToolLinks( $userId, $userText, $redContribsWhenNoEdits, $flags, $edits );
- }
-
}