Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 36 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
UserLinker | |
0.00% |
0 / 36 |
|
0.00% |
0 / 5 |
72 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
generateUserLink | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
generateUserLinkWithFallback | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
12 | |||
getUserPagePath | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
preloadUserLinks | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | declare( strict_types=1 ); |
4 | |
5 | namespace MediaWiki\Extension\CampaignEvents\MWEntity; |
6 | |
7 | use MediaWiki\Cache\LinkBatchFactory; |
8 | use MediaWiki\Html\Html; |
9 | use MediaWiki\Linker\Linker; |
10 | use MediaWiki\Parser\Sanitizer; |
11 | use Wikimedia\Message\IMessageFormatterFactory; |
12 | use Wikimedia\Message\MessageValue; |
13 | |
14 | /** |
15 | * This class generates links to (global) user accounts. |
16 | */ |
17 | class UserLinker { |
18 | public const SERVICE_NAME = 'CampaignEventsUserLinker'; |
19 | |
20 | public const MODULE_STYLES = [ |
21 | // Needed by Linker::userLink |
22 | 'mediawiki.interface.helpers.styles', |
23 | ]; |
24 | |
25 | private CampaignsCentralUserLookup $centralUserLookup; |
26 | private IMessageFormatterFactory $messageFormatterFactory; |
27 | private LinkBatchFactory $linkBatchFactory; |
28 | |
29 | /** |
30 | * @param CampaignsCentralUserLookup $centralUserLookup |
31 | * @param IMessageFormatterFactory $messageFormatterFactory |
32 | * @param LinkBatchFactory $linkBatchFactory |
33 | */ |
34 | public function __construct( |
35 | CampaignsCentralUserLookup $centralUserLookup, |
36 | IMessageFormatterFactory $messageFormatterFactory, |
37 | LinkBatchFactory $linkBatchFactory |
38 | ) { |
39 | $this->centralUserLookup = $centralUserLookup; |
40 | $this->messageFormatterFactory = $messageFormatterFactory; |
41 | $this->linkBatchFactory = $linkBatchFactory; |
42 | } |
43 | |
44 | /** |
45 | * Generates a link to the given user, if it can be found and is visible, throwing an exception otherwise. |
46 | * |
47 | * @param CentralUser $user |
48 | * @return string HTML |
49 | * @throws CentralUserNotFoundException |
50 | * @throws HiddenCentralUserException |
51 | * @note When using this method, make sure to add self::MODULE_STYLES to the output. |
52 | */ |
53 | public function generateUserLink( CentralUser $user ): string { |
54 | $name = $this->centralUserLookup->getUserName( $user ); |
55 | // HACK: Linker::userLink does not really need the user ID (T308000), so don't bother looking it up, which |
56 | // would be too slow (T345250). |
57 | // TODO: Here we'll generate a red link if the account does not exist locally. Is that OK? Could we maybe |
58 | // link to Special:CentralAuth (if CA is installed)? |
59 | return Linker::userLink( 1, $name ); |
60 | } |
61 | |
62 | /** |
63 | * Like ::generateUserLink, but returns placeholders instead of throwing an exception for users that |
64 | * cannot be found or are not visible. |
65 | * |
66 | * @param CentralUser $user |
67 | * @param string $langCode Used for localizing placeholders. |
68 | * @return string HTML |
69 | * |
70 | * @note When using this method, make sure to add self::MODULE_STYLES to the output, and to include the |
71 | * ext.campaignEvents.userlinks.styles.less file as well. |
72 | * @note This assumes that the given central user exists, or existed in the past. As such, if the account |
73 | * cannot be found it will consider it as being deleted. |
74 | * @fixme This must be kept in sync with ParticipantsManager.getDeletedOrNotFoundParticipantElement in JS |
75 | */ |
76 | public function generateUserLinkWithFallback( CentralUser $user, string $langCode ): string { |
77 | try { |
78 | return $this->generateUserLink( $user ); |
79 | } catch ( CentralUserNotFoundException $_ ) { |
80 | $msgFormatter = $this->messageFormatterFactory->getTextFormatter( $langCode ); |
81 | return Html::element( |
82 | 'span', |
83 | [ 'class' => 'ext-campaignevents-userlink-deleted' ], |
84 | $msgFormatter->format( |
85 | MessageValue::new( 'campaignevents-userlink-deleted-user' ) |
86 | ) |
87 | ); |
88 | } catch ( HiddenCentralUserException $_ ) { |
89 | $msgFormatter = $this->messageFormatterFactory->getTextFormatter( $langCode ); |
90 | return Html::element( |
91 | 'span', |
92 | [ 'class' => 'ext-campaignevents-userlink-hidden' ], |
93 | $msgFormatter->format( |
94 | MessageValue::new( 'campaignevents-userlink-suppressed-user' ) |
95 | ) |
96 | ); |
97 | } |
98 | } |
99 | |
100 | /** |
101 | * @param CentralUser $centralUser |
102 | * @return string[] |
103 | * NOTE: Make sure that the user is not hidden before calling this method, or it will throw an exception. |
104 | * TODO: Remove this hack and replace with a proper javascript implementation of Linker::userLink |
105 | */ |
106 | public function getUserPagePath( CentralUser $centralUser ): array { |
107 | $html = $this->generateUserLink( $centralUser ); |
108 | $attribs = Sanitizer::decodeTagAttributes( $html ); |
109 | return [ |
110 | 'path' => $attribs['href'] ?? '', |
111 | 'title' => $attribs['title'] ?? '', |
112 | 'classes' => $attribs['class'] ?? '', |
113 | ]; |
114 | } |
115 | |
116 | /** |
117 | * Preloads link data for linking to the user pages of the given users. |
118 | * |
119 | * @param string[] $usernames |
120 | */ |
121 | public function preloadUserLinks( array $usernames ): void { |
122 | $lb = $this->linkBatchFactory->newLinkBatch(); |
123 | foreach ( $usernames as $username ) { |
124 | $lb->add( NS_USER, $username ); |
125 | } |
126 | $lb->setCaller( wfGetCaller() ); |
127 | $lb->execute(); |
128 | } |
129 | } |