Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
61.36% |
27 / 44 |
|
80.00% |
4 / 5 |
CRAP | |
0.00% |
0 / 1 |
CentralAuthUIService | |
61.36% |
27 / 44 |
|
80.00% |
4 / 5 |
22.75 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
formatHiddenLevel | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
4 | |||
prettyTimespan | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
showRenameLogExtract | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
2 | |||
processAntiSpoofConflicts | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
4 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\CentralAuth; |
4 | |
5 | use HTMLForm; |
6 | use IContextSource; |
7 | use LogEventsList; |
8 | use MediaWiki\Extension\CentralAuth\User\CentralAuthUser; |
9 | use MediaWiki\Title\TitleFactory; |
10 | use MessageLocalizer; |
11 | |
12 | /** |
13 | * Shared utilities for building UIs in CentralAuth |
14 | * |
15 | * @author Taavi "Majavah" Väänänen <hi@taavi.wtf> |
16 | */ |
17 | class CentralAuthUIService { |
18 | /** @var TitleFactory */ |
19 | private $titleFactory; |
20 | |
21 | /** |
22 | * @param TitleFactory $titleFactory |
23 | */ |
24 | public function __construct( TitleFactory $titleFactory ) { |
25 | $this->titleFactory = $titleFactory; |
26 | } |
27 | |
28 | /** |
29 | * Format a given CentralAuthUser::HIDDEN_* constant to a string. |
30 | * @param MessageLocalizer $localizer |
31 | * @param int $level one of the CentralAuthUser::HIDDEN_LEVEL_* constants |
32 | * @return string Already html escaped |
33 | */ |
34 | public function formatHiddenLevel( MessageLocalizer $localizer, int $level ): string { |
35 | switch ( $level ) { |
36 | case CentralAuthUser::HIDDEN_LEVEL_NONE: |
37 | return $localizer->msg( 'centralauth-admin-no' )->escaped(); |
38 | case CentralAuthUser::HIDDEN_LEVEL_LISTS: |
39 | return $localizer->msg( 'centralauth-admin-hidden-list' )->escaped(); |
40 | case CentralAuthUser::HIDDEN_LEVEL_SUPPRESSED: |
41 | return $localizer->msg( 'centralauth-admin-hidden-oversight' )->escaped(); |
42 | } |
43 | |
44 | return ''; |
45 | } |
46 | |
47 | /** |
48 | * Format a number of seconds into a human-readable timespan ("XX hours ago"). |
49 | * @param MessageLocalizer $localizer |
50 | * @param int $time in seconds |
51 | * @return string |
52 | */ |
53 | public function prettyTimespan( MessageLocalizer $localizer, int $time ): string { |
54 | // map all units for how many times they fit in the next unit |
55 | $units = [ |
56 | 'seconds' => 60, |
57 | 'minutes' => 60, |
58 | 'hours' => 24, |
59 | 'days' => 30.417, |
60 | 'months' => 12, |
61 | 'years' => 1 |
62 | ]; |
63 | |
64 | // Used messaged (to make sure that grep finds them): |
65 | // 'centralauth-seconds-ago', 'centralauth-minutes-ago', 'centralauth-hours-ago' |
66 | // 'centralauth-days-ago', 'centralauth-months-ago', 'centralauth-years-ago' |
67 | |
68 | // check each unit individually, to find a suitable unit to display |
69 | foreach ( $units as $unit => $chunk ) { |
70 | // if it's less than two times the size of the next unit, use this unit |
71 | // for example: 6 seconds uses seconds, 61 seconds uses seconds, 119 seconds uses seconds, |
72 | // but 121 seconds is detected that seconds isn't a useful unit anymore, and it goes to |
73 | // the next unit (minutes), and then it outputs 2 minutes (2 is under 2*60, it won't go to hours) |
74 | if ( $time < 2 * $chunk ) { |
75 | return $localizer->msg( "centralauth-$unit-ago" )->numParams( $time )->text(); |
76 | } |
77 | |
78 | // convert to the next unit, eg. seconds into minutes, minutes into hours, ... |
79 | $time = intval( $time / $chunk ); |
80 | } |
81 | |
82 | // if the timespan is so long that it's more than two times the size of the last unit, |
83 | // use the last unit (years) anyways |
84 | return $localizer->msg( "centralauth-years-ago" )->numParams( $time )->text(); |
85 | } |
86 | |
87 | /** |
88 | * Append an extract of the global rename log for the specific username. |
89 | * @param IContextSource $context |
90 | * @param string $name |
91 | */ |
92 | public function showRenameLogExtract( IContextSource $context, string $name ): void { |
93 | $caTitle = $this->titleFactory->makeTitle( NS_SPECIAL, 'CentralAuth/' . $name ); |
94 | |
95 | $logs = ''; |
96 | LogEventsList::showLogExtract( $logs, 'gblrename', $caTitle, '', [ |
97 | 'showIfEmpty' => true, |
98 | ] ); |
99 | |
100 | $formDescriptor = [ |
101 | 'logs' => [ |
102 | 'type' => 'info', |
103 | 'raw' => true, |
104 | 'default' => $logs, |
105 | ], |
106 | ]; |
107 | |
108 | $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $context ); |
109 | $htmlForm->suppressDefaultSubmit() |
110 | ->setWrapperLegendMsg( 'centralauth-rename-progress-logs-fieldset' ) |
111 | ->prepareForm() |
112 | ->displayForm( false ); |
113 | } |
114 | |
115 | /** |
116 | * Format antispoof conflicts, change hidden ones to a generic text and link others to Special:CentralAuth. |
117 | * @param MessageLocalizer $localizer |
118 | * @param string $oldName User's old (current) name |
119 | * @param string[] $conflicts Conflicting usernames |
120 | * @return string[] Usernames formatted as wikitext, either saying that it's hidden or |
121 | * linking to Special:CentralAuth |
122 | */ |
123 | public function processAntiSpoofConflicts( |
124 | MessageLocalizer $localizer, |
125 | string $oldName, |
126 | array $conflicts |
127 | ): array { |
128 | $display = []; |
129 | |
130 | foreach ( $conflicts as $name ) { |
131 | if ( $name === $oldName ) { |
132 | // Not a conflict since the old usage will go away |
133 | continue; |
134 | } |
135 | $ca = CentralAuthUser::getInstanceByName( $name ); |
136 | if ( $ca->isHidden() ) { |
137 | $display[] = $localizer->msg( 'centralauth-rename-conflict-hidden' )->text(); |
138 | } else { |
139 | $display[] = "[[Special:CentralAuth/$name|$name]]"; |
140 | } |
141 | } |
142 | |
143 | return $display; |
144 | } |
145 | } |