59 $this->hookRunner =
new HookRunner( $hookContainer );
60 $this->tempUserConfig = $tempUserConfig;
61 $this->specialPageFactory = $specialPageFactory;
62 $this->linkRenderer = $linkRenderer;
63 $this->tempUserDetailsLookup = $tempUserDetailsLookup;
64 $this->userIdentityLookup = $userIdentityLookup;
65 $this->userNameUtils = $userNameUtils;
87 ?
string $altUserName =
null,
88 array $attributes = []
90 $outputPage = $context->getOutput();
91 $outputPage->addModuleStyles( [
92 'mediawiki.interface.helpers.styles',
93 'mediawiki.interface.helpers.linker.styles'
96 $userName = $targetUser->
getName();
99 $html = $this->userLinkCache->getWithSetCallback(
100 $this->userLinkCache->makeKey(
104 implode(
' ', $attributes )
106 fn () => $this->renderExternalUserLink(
114 $html = $this->userLinkCache->getWithSetCallback(
115 $this->userLinkCache->makeKey(
118 implode(
' ', $attributes )
120 fn () => $this->renderUserLink(
130 $this->hookRunner->onUserLinkRendererUserLinkPostRender( $targetUser, $context, $html, $prefix, $postfix );
131 return $prefix . $html . $postfix;
144 private function renderExternalUserLink(
145 UserIdentity $targetUser,
146 MessageLocalizer $messageLocalizer,
147 ?
string $altUserName =
null,
148 array $attributes = []
150 $userName = $targetUser->getName();
153 $linkText = $altUserName ?? $userName;
154 $isDefaultCaption = $this->linkRenderer->isDefaultLinkCaption( $targetPage, $linkText );
155 $params = $this->getUserLinkParameters( $targetUser, $messageLocalizer, $isDefaultCaption );
156 $attributes += $params[
'extraAttr' ];
157 $classes = $params[
'classes' ];
158 $postfix = $params[
'postfix' ];
160 $link = $this->linkRenderer->makeExternalLink(
161 WikiMap::getForeignURL(
162 $targetUser->getWikiId(),
163 'User:' . strtr( $userName,
' ',
'_' )
170 $attributes + [
'class' => $classes ]
191 private function renderUserLink(
192 UserIdentity $targetUser,
193 MessageLocalizer $messageLocalizer,
194 ?
string $altUserName =
null,
195 array $attributes = []
197 $userName = $targetUser->
getName();
200 if ( $this->tempUserConfig->isTempName( $userName ) ) {
201 $pageName = $this->specialPageFactory->getLocalNameFor(
'Contributions', $userName );
202 $page =
new TitleValue(
NS_SPECIAL, $pageName );
203 } elseif ( !$targetUser->isRegistered() ) {
204 $page = ExternalUserNames::getUserLinkTitle( $userName );
206 if ( ExternalUserNames::isExternal( $userName ) ) {
207 $classes[] =
'mw-extuserlink';
209 $altUserName ??= IPUtils::prettifyIP( $userName );
211 $classes[] =
'mw-anonuserlink';
213 $page = TitleValue::tryNew(
NS_USER, strtr( $userName,
' ',
'_' ) );
216 $linkText = $altUserName ?? $userName;
217 $isDefaultCaption = $this->linkRenderer->isDefaultLinkCaption( $page, $linkText );
218 $params = $this->getUserLinkParameters( $targetUser, $messageLocalizer, $isDefaultCaption );
219 $attributes +=
$params[
'extraAttr' ];
220 $classes = array_merge( $params[
'classes' ], $classes );
221 $postfix =
$params[
'postfix' ];
225 '<bdi>' . htmlspecialchars( $linkText ) .
'</bdi>'
228 if ( isset( $attributes[
'class'] ) ) {
229 $classes[] = $attributes[
'class'];
232 $attributes[
'class'] = $classes;
234 if ( $page !==
null ) {
235 return $this->linkRenderer->makeLink( $page,
new HtmlArmor( $linkText ), $attributes );
238 return Html::rawElement(
'span', $attributes, $linkText );
247 private function getUserLinkParameters(
248 UserIdentity $targetUser,
249 MessageLocalizer $messageLocalizer,
250 bool $isDefaultCaption,
253 $userName = $targetUser->getName();
257 $classes = $this->getLinkClassesFromUserName( $userName, $isDefaultCaption );
258 $classes[] =
'mw-userlink';
259 if ( $this->tempUserConfig->isTempName( $userName ) ) {
260 $attributes[
'data-mw-target'] = $userName;
262 if ( $this->isFromExternalWiki( $targetUser->getWikiId() ) ) {
267 $localIdentity = $this->userIdentityLookup->getUserIdentityByName(
272 $localIdentity = $targetUser;
275 if ( $localIdentity instanceof UserIdentity ) {
276 $isExpired = $this->tempUserDetailsLookup->isExpired(
284 $classes[] =
'mw-tempuserlink-expired';
286 $description = $messageLocalizer->msg(
287 'tempuser-expired-link-tooltip'
290 $postfix = Html::element(
293 'role' =>
'presentation',
294 'class' =>
'cdx-tooltip mw-tempuserlink-expired--tooltip',
299 $attributes[
'aria-description'] = $description;
303 $attributes[
'title'] =
null;
307 'classes' => $classes,
308 'extraAttr' => $attributes,
309 'postfix' => $postfix
324 return !WikiMap::isCurrentWikiDbDomain( $wikiId );
341 private function getLinkClassesFromUserName(
string $userName,
bool $isDefaultCaption ): array {
346 if ( $isDefaultCaption && $this->tempUserConfig->isTempName( $userName ) ) {
347 $classes[] =
'mw-tempuserlink';
363 $ns = $target->getNamespace();
370 [ $name, $subpage ] = $this->specialPageFactory->resolveAlias( $target->
getDBkey() );
371 if ( $name ===
'Contributions' && $subpage !==
null ) {
372 $userName = $subpage;
375 if ( $userName !==
null ) {
376 $userName = $this->userNameUtils->getCanonical( $userName );
377 if ( $userName !==
false ) {
378 return $this->getLinkClassesFromUserName( $userName, $isDefaultCaption );