58 $this->hookRunner =
new HookRunner( $hookContainer );
59 $this->tempUserConfig = $tempUserConfig;
60 $this->specialPageFactory = $specialPageFactory;
61 $this->linkRenderer = $linkRenderer;
62 $this->tempUserDetailsLookup = $tempUserDetailsLookup;
63 $this->userIdentityLookup = $userIdentityLookup;
64 $this->userNameUtils = $userNameUtils;
86 ?
string $altUserName =
null,
87 array $attributes = []
89 $outputPage = $context->getOutput();
90 $outputPage->addModuleStyles( [
91 'mediawiki.interface.helpers.styles',
92 'mediawiki.interface.helpers.linker.styles'
95 $userName = $targetUser->
getName();
98 $html = $this->userLinkCache->getWithSetCallback(
99 $this->userLinkCache->makeKey(
103 implode(
' ', $attributes )
105 fn () => $this->renderExternalUserLink(
113 $html = $this->userLinkCache->getWithSetCallback(
114 $this->userLinkCache->makeKey(
117 implode(
' ', $attributes )
119 fn () => $this->renderUserLink(
129 $this->hookRunner->onUserLinkRendererUserLinkPostRender( $targetUser, $context, $html, $prefix, $postfix );
130 return $prefix . $html . $postfix;
143 private function renderExternalUserLink(
144 UserIdentity $targetUser,
145 MessageLocalizer $messageLocalizer,
146 ?
string $altUserName =
null,
147 array $attributes = []
149 $userName = $targetUser->getName();
152 $linkText = $altUserName ?? $userName;
153 $isDefaultCaption = $this->linkRenderer->isDefaultLinkCaption( $targetPage, $linkText );
154 $params = $this->getUserLinkParameters( $targetUser, $messageLocalizer, $isDefaultCaption );
155 $attributes += $params[
'extraAttr' ];
156 $classes = $params[
'classes' ];
157 $postfix = $params[
'postfix' ];
159 $link = $this->linkRenderer->makeExternalLink(
160 WikiMap::getForeignURL(
161 $targetUser->getWikiId(),
162 'User:' . strtr( $userName,
' ',
'_' )
169 $attributes + [
'class' => $classes ]
190 private function renderUserLink(
191 UserIdentity $targetUser,
192 MessageLocalizer $messageLocalizer,
193 ?
string $altUserName =
null,
194 array $attributes = []
196 $userName = $targetUser->
getName();
199 if ( $this->tempUserConfig->isTempName( $userName ) ) {
200 $pageName = $this->specialPageFactory->getLocalNameFor(
'Contributions', $userName );
201 $page =
new TitleValue(
NS_SPECIAL, $pageName );
202 } elseif ( !$targetUser->isRegistered() ) {
203 $page = ExternalUserNames::getUserLinkTitle( $userName );
205 if ( ExternalUserNames::isExternal( $userName ) ) {
206 $classes[] =
'mw-extuserlink';
208 $altUserName ??= IPUtils::prettifyIP( $userName );
210 $classes[] =
'mw-anonuserlink';
212 $page = TitleValue::tryNew(
NS_USER, strtr( $userName,
' ',
'_' ) );
215 $linkText = $altUserName ?? $userName;
216 $isDefaultCaption = $this->linkRenderer->isDefaultLinkCaption( $page, $linkText );
217 $params = $this->getUserLinkParameters( $targetUser, $messageLocalizer, $isDefaultCaption );
218 $attributes +=
$params[
'extraAttr' ];
219 $classes = array_merge( $params[
'classes' ], $classes );
220 $postfix =
$params[
'postfix' ];
224 '<bdi>' . htmlspecialchars( $linkText ) .
'</bdi>'
227 if ( isset( $attributes[
'class'] ) ) {
228 $classes[] = $attributes[
'class'];
231 $attributes[
'class'] = $classes;
233 if ( $page !==
null ) {
234 return $this->linkRenderer->makeLink( $page,
new HtmlArmor( $linkText ), $attributes );
237 return Html::rawElement(
'span', $attributes, $linkText );
246 private function getUserLinkParameters(
247 UserIdentity $targetUser,
248 MessageLocalizer $messageLocalizer,
249 bool $isDefaultCaption,
252 $userName = $targetUser->getName();
256 $classes = $this->getLinkClassesFromUserName( $userName, $isDefaultCaption );
257 $classes[] =
'mw-userlink';
258 if ( $this->tempUserConfig->isTempName( $userName ) ) {
259 $attributes[
'data-mw-target'] = $userName;
261 if ( $this->isFromExternalWiki( $targetUser->getWikiId() ) ) {
266 $localIdentity = $this->userIdentityLookup->getUserIdentityByName(
271 $localIdentity = $targetUser;
274 if ( $localIdentity instanceof UserIdentity ) {
275 $isExpired = $this->tempUserDetailsLookup->isExpired(
283 $classes[] =
'mw-tempuserlink-expired';
285 $description = $messageLocalizer->msg(
286 'tempuser-expired-link-tooltip'
289 $postfix = Html::element(
292 'role' =>
'presentation',
293 'class' =>
'cdx-tooltip mw-tempuserlink-expired--tooltip',
298 $attributes[
'aria-description'] = $description;
302 $attributes[
'title'] =
null;
306 'classes' => $classes,
307 'extraAttr' => $attributes,
308 'postfix' => $postfix
323 return !WikiMap::isCurrentWikiDbDomain( $wikiId );
340 private function getLinkClassesFromUserName(
string $userName,
bool $isDefaultCaption ): array {
345 if ( $isDefaultCaption && $this->tempUserConfig->isTempName( $userName ) ) {
346 $classes[] =
'mw-tempuserlink';
362 $ns = $target->getNamespace();
366 $userName = $target->
getText();
369 [ $name, $subpage ] = $this->specialPageFactory->resolveAlias( $target->
getText() );
370 if ( $name ===
'Contributions' && $subpage !==
null ) {
371 $userName = $subpage;
374 if ( $userName !==
null ) {
375 $userName = $this->userNameUtils->getCanonical( $userName );
376 if ( $userName !==
false ) {
377 return $this->getLinkClassesFromUserName( $userName, $isDefaultCaption );