Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 165 |
|
0.00% |
0 / 13 |
CRAP | |
0.00% |
0 / 1 |
SpecialTranslatorSignup | |
0.00% |
0 / 165 |
|
0.00% |
0 / 13 |
1260 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
doesWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getMessagePrefix | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
alterForm | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
postHtml | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getFormFields | |
0.00% |
0 / 101 |
|
0.00% |
0 / 1 |
156 | |||
onSubmit | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
onSuccess | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
getOtherWikis | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
56 | |||
getDisplayFormat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isUserUnsubscribed | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | /** |
3 | * Form for translators to register contact methods |
4 | * |
5 | * @file |
6 | * @author Niklas Laxström |
7 | * @author Amir E. Aharoni |
8 | * @author Santhosh Thottingal |
9 | * @author Siebrand Mazeland |
10 | * @copyright Copyright © 2012, Niklas Laxström |
11 | * @license GPL-2.0-or-later |
12 | */ |
13 | |
14 | namespace MediaWiki\Extension\TranslationNotifications; |
15 | |
16 | use ExtensionRegistry; |
17 | use HTMLForm; |
18 | use LanguageCode; |
19 | use MediaWiki\Extension\CentralAuth\User\CentralAuthUser; |
20 | use MediaWiki\Extension\SiteMatrix\SiteMatrix; |
21 | use MediaWiki\Html\Html; |
22 | use MediaWiki\Languages\LanguageNameUtils; |
23 | use MediaWiki\SpecialPage\FormSpecialPage; |
24 | use MediaWiki\SpecialPage\SpecialPage; |
25 | use MediaWiki\User\Options\UserOptionsManager; |
26 | use MediaWiki\WikiMap\WikiMap; |
27 | |
28 | /** |
29 | * Form for translators to register contact methods |
30 | * |
31 | * @ingroup SpecialPage TranslateSpecialPage |
32 | */ |
33 | |
34 | class SpecialTranslatorSignup extends FormSpecialPage { |
35 | /** @var UserOptionsManager */ |
36 | private $userOptionsManager; |
37 | |
38 | /** @var LanguageNameUtils */ |
39 | private $languageNameUtils; |
40 | |
41 | public function __construct( |
42 | UserOptionsManager $userOptionsManager, |
43 | LanguageNameUtils $languageNameUtils |
44 | ) { |
45 | parent::__construct( 'TranslatorSignup' ); |
46 | $this->userOptionsManager = $userOptionsManager; |
47 | $this->languageNameUtils = $languageNameUtils; |
48 | } |
49 | |
50 | public function doesWrites() { |
51 | return true; |
52 | } |
53 | |
54 | protected function getGroupName(): string { |
55 | return 'translation'; |
56 | } |
57 | |
58 | /** @inheritDoc */ |
59 | public function execute( $par ) { |
60 | $this->requireNamedUser(); |
61 | parent::execute( $par ); |
62 | } |
63 | |
64 | protected function getMessagePrefix(): string { |
65 | return 'translationnotifications'; |
66 | } |
67 | |
68 | protected function alterForm( HTMLForm $form ): void { |
69 | $form->setWrapperLegend( false ); |
70 | $form->setId( 'translationnotifications-form' ); |
71 | $form->setSubmitID( 'translationnotifications-submit' ); |
72 | $form->setSubmitTextMsg( 'translationnotifications-submit' ); |
73 | |
74 | $form->addButton( [ |
75 | 'name' => 'translationnotifications-unsubscribe', |
76 | 'value' => 'unsubscribe', |
77 | 'label-message' => 'translationnotifications-unsubscribe', |
78 | 'attribs' => [ 'disabled' => $this->isUserUnsubscribed() ], |
79 | 'flags' => 'destructive', |
80 | ] ); |
81 | // Without the following code the translationnotifications-text appears on this page. See: T334371 |
82 | $form->setHeaderHtml( '' ); |
83 | } |
84 | |
85 | protected function postHtml() { |
86 | $legalMsg = $this->getConfig()->get( 'TranslationNotificationsSignupLegalMessage' ); |
87 | if ( $legalMsg ) { |
88 | // Show the legal text regarding the notifications. |
89 | // Do not show if value is empty or false. |
90 | return Html::warningBox( $this->msg( $legalMsg )->parseAsBlock() ); |
91 | } |
92 | return ''; |
93 | } |
94 | |
95 | protected function getFormFields(): array { |
96 | $this->getOutput()->addModules( 'ext.translationnotifications.translatorsignup' ); |
97 | $user = $this->getUser(); |
98 | |
99 | $m = [ |
100 | 'username' => [ |
101 | 'type' => 'info', |
102 | 'label-message' => 'translationnotifications-username', |
103 | 'default' => $user->getName(), |
104 | 'section' => 'info', |
105 | ], |
106 | ]; |
107 | |
108 | if ( $user->isEmailConfirmed() ) { |
109 | if ( $this->userOptionsManager->getOption( $user, 'disablemail' ) ) { |
110 | $status = $this->msg( 'translationnotifications-email-disablemail' )->parse(); |
111 | } else { |
112 | $status = $this->msg( 'translationnotifications-email-confirmed' )->parse(); |
113 | } |
114 | } elseif ( trim( $user->getEmail() ) !== '' ) { |
115 | $confirmMail = $this->getLinkRenderer()->makeKnownLink( |
116 | SpecialPage::getTitleFor( 'Confirmemail' ), |
117 | $this->msg( 'emailconfirmlink' )->text() |
118 | ); |
119 | $status = $this->msg( 'translationnotifications-email-unconfirmed' ) |
120 | ->rawParams( $confirmMail )->parse(); |
121 | |
122 | } else { |
123 | $status = $this->msg( 'translationnotifications-email-notset' )->parse(); |
124 | } |
125 | |
126 | $m['emailstatus'] = [ |
127 | 'type' => 'info', |
128 | 'label-message' => 'translationnotifications-emailstatus', |
129 | 'default' => $status, |
130 | 'section' => 'info', |
131 | 'raw' => true, |
132 | ]; |
133 | |
134 | $languages = $this->languageNameUtils->getLanguageNames(); |
135 | ksort( $languages ); |
136 | |
137 | $options = []; |
138 | foreach ( $languages as $code => $name ) { |
139 | $display = LanguageCode::bcp47( $code ) . ' - ' . $name; |
140 | $options[$display] = $code; |
141 | } |
142 | |
143 | $options = |
144 | [ $this->msg( 'translationnotifications-nolang' )->plain() => '' ] + $options; |
145 | |
146 | for ( $i = 1; $i < 4; $i++ ) { |
147 | $formatted = $this->getLanguage()->formatNum( $i ); |
148 | $m["lang-$i"] = [ |
149 | 'type' => 'select', |
150 | 'label-message' => [ 'translationnotifications-lang', $formatted ], |
151 | 'section' => 'languages', |
152 | 'options' => $options, |
153 | 'default' => $this->userOptionsManager->getOption( |
154 | $user, |
155 | "translationnotifications-lang-$i" |
156 | ), |
157 | ]; |
158 | |
159 | if ( $i === 1 ) { |
160 | $m["lang-$i"]['default'] = $this->userOptionsManager->getOption( |
161 | $user, |
162 | "translationnotifications-lang-$i", |
163 | $this->getLanguage()->getCode() |
164 | ); |
165 | $m["lang-$i"]['required'] = true; |
166 | } |
167 | } |
168 | |
169 | $config = $this->getConfig(); |
170 | $contactMethods = $config->get( 'TranslationNotificationsContactMethods' ); |
171 | foreach ( $contactMethods as $method => $value ) { |
172 | if ( $value === false ) { |
173 | continue; |
174 | } |
175 | |
176 | // Give grep a chance to find the usages: |
177 | // translationnotifications-cmethod-email, translationnotifications-cmethod-talkpage, |
178 | // translationnotifications-cmethod-talkpage-elsewhere, |
179 | // translationnotifications-cmethod-feed |
180 | $m["cmethod-$method"] = [ |
181 | 'type' => 'check', |
182 | 'label-message' => "translationnotifications-cmethod-$method", |
183 | 'default' => $this->userOptionsManager->getOption( |
184 | $user, |
185 | "translationnotifications-cmethod-$method" |
186 | ), |
187 | 'section' => 'contact', |
188 | ]; |
189 | |
190 | if ( $method === 'email' ) { |
191 | $m["cmethod-$method"]['disabled'] = !$user->canReceiveEmail(); |
192 | } |
193 | |
194 | $localInterwikis = $config->get( 'LocalInterwikis' ); |
195 | if ( $method === 'talkpage-elsewhere' && count( $localInterwikis ) ) { |
196 | $m['cmethod-talkpage-elsewhere-loc'] = [ |
197 | 'type' => 'select', |
198 | 'default' => $this->userOptionsManager->getOption( |
199 | $user, |
200 | 'translationnotifications-cmethod-talkpage-elsewhere-loc' |
201 | ), |
202 | 'section' => 'contact', |
203 | 'options' => $this->getOtherWikis(), |
204 | ]; |
205 | } |
206 | } |
207 | |
208 | $m['freq'] = [ |
209 | 'type' => 'radio', |
210 | 'default' => $this->userOptionsManager->getOption( |
211 | $user, |
212 | 'translationnotifications-freq', |
213 | 'always' |
214 | ), |
215 | 'section' => 'frequency', |
216 | 'options' => [ |
217 | $this->msg( 'translationnotifications-freq-always' )->escaped() => 'always', |
218 | $this->msg( 'translationnotifications-freq-week' )->escaped() => 'week', |
219 | $this->msg( 'translationnotifications-freq-month' )->escaped() => 'month', |
220 | $this->msg( 'translationnotifications-freq-weekly' )->escaped() => 'weekly', |
221 | $this->msg( 'translationnotifications-freq-monthly' )->escaped() => 'monthly', |
222 | $this->msg( 'translationnotifications-freq-none' )->escaped() => 'none', |
223 | ], |
224 | ]; |
225 | |
226 | return $m; |
227 | } |
228 | |
229 | /** |
230 | * @param array $formData |
231 | * @return true |
232 | */ |
233 | public function onSubmit( array $formData ) { |
234 | $user = $this->getUser()->getInstanceForUpdate(); |
235 | |
236 | if ( $this->getRequest()->getVal( 'translationnotifications-unsubscribe' ) !== null ) { |
237 | $this->userOptionsManager->setOption( $user, 'translationnotifications-freq', 'none' ); |
238 | |
239 | $user->saveSettings(); |
240 | return true; |
241 | } |
242 | |
243 | $this->userOptionsManager->setOption( $user, 'translationnotifications-lastactivity', wfTimestampNow() ); |
244 | // @todo Needs input validation |
245 | foreach ( $formData as $key => $value ) { |
246 | $this->userOptionsManager->setOption( $user, "translationnotifications-$key", $value ); |
247 | } |
248 | $user->saveSettings(); |
249 | return true; |
250 | } |
251 | |
252 | public function onSuccess() { |
253 | $out = $this->getOutput(); |
254 | $out->addHTML( |
255 | Html::successBox( |
256 | $out->msg( 'translationnotifications-signup-success' )->plain() |
257 | ) |
258 | ); |
259 | } |
260 | |
261 | /** @return array<string,string> */ |
262 | protected function getOtherWikis(): array { |
263 | global $wgConf; |
264 | if ( !ExtensionRegistry::getInstance()->isLoaded( 'CentralAuth' ) ) { |
265 | return []; |
266 | } |
267 | $globalUser = CentralAuthUser::getInstance( $this->getUser() ); |
268 | if ( !$globalUser->exists() ) { |
269 | return []; |
270 | } |
271 | |
272 | $matrix = new SiteMatrix(); |
273 | $wikis = []; |
274 | foreach ( $globalUser->listAttached() as $dbname ) { |
275 | // Skip inactive and special wikis |
276 | [ $site, $lang ] = $wgConf->siteFromDB( $dbname ); |
277 | if ( $matrix->isClosed( $lang, $site ) |
278 | || $matrix->isPrivate( $dbname ) |
279 | || $matrix->isFishbowl( $dbname ) |
280 | ) { |
281 | continue; |
282 | } |
283 | |
284 | $wikis[WikiMap::getWikiName( $dbname )] = $dbname; |
285 | } |
286 | |
287 | return $wikis; |
288 | } |
289 | |
290 | protected function getDisplayFormat(): string { |
291 | return 'ooui'; |
292 | } |
293 | |
294 | private function isUserUnsubscribed(): bool { |
295 | $contactMethods = $this->getConfig()->get( 'TranslationNotificationsContactMethods' ); |
296 | foreach ( $contactMethods as $method => $value ) { |
297 | if ( |
298 | $this->userOptionsManager->getOption( |
299 | $this->getUser(), |
300 | "translationnotifications-cmethod-$method" ) |
301 | ) { |
302 | return false; |
303 | } |
304 | } |
305 | |
306 | return true; |
307 | } |
308 | } |