Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 121 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
SpecialNotifyTranslators | |
0.00% |
0 / 121 |
|
0.00% |
0 / 11 |
420 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
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 | |||
getMessagePrefix | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDisplayFormat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
alterForm | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getFormFields | |
0.00% |
0 / 62 |
|
0.00% |
0 / 1 |
12 | |||
getTranslatablePages | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
20 | |||
getSourceLanguage | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
onSubmit | |
0.00% |
0 / 29 |
|
0.00% |
0 / 1 |
30 | |||
onSuccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Form for translation managers to send a notification |
4 | * to registered translators. |
5 | * |
6 | * @file |
7 | * @author Amir E. Aharoni |
8 | * @author Santhosh Thottingal |
9 | * @author Niklas Laxström |
10 | * @author Siebrand Mazeland |
11 | * @copyright Copyright © 2012, Amir E. Aharoni, Santhosh Thottingal |
12 | * @license GPL-2.0-or-later |
13 | */ |
14 | |
15 | namespace MediaWiki\Extension\TranslationNotifications; |
16 | |
17 | use ErrorPageError; |
18 | use HTMLForm; |
19 | use JobQueueGroup; |
20 | use MediaWiki\Cache\LinkBatchFactory; |
21 | use MediaWiki\Extension\Translate\MessageGroupProcessing\MessageGroups; |
22 | use MediaWiki\Extension\Translate\PageTranslation\TranslatablePage; |
23 | use MediaWiki\Extension\TranslationNotifications\Jobs\TranslationNotificationsSubmitJob; |
24 | use MediaWiki\Extension\TranslationNotifications\Utilities\LanguageSet; |
25 | use MediaWiki\Extension\TranslationNotifications\Utilities\NotificationMessageBuilder; |
26 | use MediaWiki\Languages\LanguageNameUtils; |
27 | use MediaWiki\SpecialPage\FormSpecialPage; |
28 | use MediaWiki\Status\Status; |
29 | use MediaWiki\Title\Title; |
30 | use WikiPageMessageGroup; |
31 | |
32 | /** |
33 | * Form for translation managers to send a notification |
34 | * to registered translators. |
35 | * |
36 | * @ingroup SpecialPage TranslateSpecialPage |
37 | */ |
38 | class SpecialNotifyTranslators extends FormSpecialPage { |
39 | public static string $right = 'translate-manage'; |
40 | |
41 | /** @var LanguageNameUtils */ |
42 | private $languageNameUtils; |
43 | /** @var JobQueueGroup */ |
44 | private $jobQueueGroup; |
45 | /** @var LinkBatchFactory */ |
46 | private $linkBatchFactory; |
47 | |
48 | public function __construct( |
49 | LanguageNameUtils $languageNameUtils, |
50 | JobQueueGroup $jobQueueGroup, |
51 | LinkBatchFactory $linkBatchFactory |
52 | ) { |
53 | parent::__construct( 'NotifyTranslators', self::$right ); |
54 | $this->languageNameUtils = $languageNameUtils; |
55 | $this->jobQueueGroup = $jobQueueGroup; |
56 | $this->linkBatchFactory = $linkBatchFactory; |
57 | } |
58 | |
59 | public function doesWrites() { |
60 | return true; |
61 | } |
62 | |
63 | protected function getGroupName(): string { |
64 | return 'translation'; |
65 | } |
66 | |
67 | protected function getMessagePrefix(): string { |
68 | return 'translationnotifications'; |
69 | } |
70 | |
71 | protected function getDisplayFormat(): string { |
72 | return 'ooui'; |
73 | } |
74 | |
75 | protected function alterForm( HTMLForm $form ): void { |
76 | $form->setId( 'notifytranslators-form' ); |
77 | $form->setSubmitID( 'translationnotifications-send-notification-button' ); |
78 | $form->setSubmitTextMsg( 'translationnotifications-send-notification-button' ); |
79 | } |
80 | |
81 | /** |
82 | * Get the form fields for use by the HTMLForm. |
83 | * We also set up the JavaScript needed on the form here. |
84 | * |
85 | * @return array |
86 | * @throws ErrorPageError if there is no translatable page on this wiki |
87 | */ |
88 | protected function getFormFields(): array { |
89 | $this->getOutput()->addModules( 'ext.translationnotifications.notifytranslators' ); |
90 | |
91 | $formFields = []; |
92 | |
93 | $pages = $this->getTranslatablePages(); |
94 | if ( count( $pages ) === 0 ) { |
95 | throw new ErrorPageError( 'notifytranslators', |
96 | 'translationnotifications-error-no-translatable-pages' ); |
97 | } |
98 | |
99 | $formFields['TranslatablePage'] = [ |
100 | 'name' => 'tpage', |
101 | 'type' => 'select', |
102 | 'label-message' => [ 'translationnotifications-translatablepage-title' ], |
103 | 'options' => $pages, |
104 | ]; |
105 | |
106 | $languages = array_flip( |
107 | $this->languageNameUtils->getLanguageNames( $this->getLanguage()->getCode() ) |
108 | ); |
109 | |
110 | $formFields['LanguageSet'] = [ |
111 | 'name' => 'notifiable-languages-options', |
112 | 'type' => 'radio', |
113 | 'default' => LanguageSet::ALL, |
114 | 'label-message' => 'translationnotifications-requested-languages-label', |
115 | 'options-messages' => [ |
116 | 'translationnotifications-languages-to-notify-all-label' |
117 | => LanguageSet::ALL, |
118 | 'translationnotifications-languages-to-notify-only-selected-label' |
119 | => LanguageSet::SOME, |
120 | 'translationnotifications-languages-to-notify-all-except-label' |
121 | => LanguageSet::ALL_EXCEPT_SOME |
122 | ] |
123 | ]; |
124 | |
125 | // Selected languages input box |
126 | $formFields['SelectedLanguages'] = [ |
127 | 'type' => 'multiselect', |
128 | 'dropdown' => true, |
129 | 'label-message' => 'translationnotifications-languages-to-notify-label', |
130 | 'help-message' => 'translationnotifications-languages-to-notify-label-help-message', |
131 | 'options' => $languages, |
132 | 'hide-if' => [ '===', 'LanguageSet', (string)LanguageSet::ALL ] |
133 | ]; |
134 | |
135 | // Priority dropdown |
136 | $priorityOptions = []; |
137 | $priorities = [ 'unset', 'high', 'medium', 'low' ]; |
138 | |
139 | foreach ( $priorities as $priority ) { |
140 | $priorityMessage = |
141 | NotificationMessageBuilder::getPriorityMessage( $priority ) |
142 | ->setContext( $this->getContext() )->text(); |
143 | $priorityOptions[$priorityMessage] = $priority; |
144 | } |
145 | |
146 | $formFields['Priority'] = [ |
147 | 'type' => 'select', |
148 | 'label-message' => [ 'translationnotifications-priority' ], |
149 | 'options' => $priorityOptions, |
150 | 'default' => 'unset', |
151 | ]; |
152 | |
153 | // Deadline date input box with datepicker |
154 | $formFields['DeadlineDate'] = [ |
155 | 'type' => 'date', |
156 | 'min' => date( 'Y-m-d' ), |
157 | 'label-message' => 'translationnotifications-deadline-label', |
158 | 'help-message' => 'translationnotifications-deadline-help-message', |
159 | ]; |
160 | |
161 | // Custom text |
162 | $formFields['NotificationText'] = [ |
163 | 'type' => 'textarea', |
164 | 'rows' => 20, |
165 | 'label-message' => 'emailmessage', |
166 | ]; |
167 | |
168 | return $formFields; |
169 | } |
170 | |
171 | protected function getTranslatablePages(): array { |
172 | $translatablePages = MessageGroups::getGroupsByType( WikiPageMessageGroup::class ); |
173 | usort( $translatablePages, [ MessageGroups::class, 'groupLabelSort' ] ); |
174 | |
175 | $titles = []; |
176 | // Retrieving article id requires doing DB queries. |
177 | // Make it more efficient by batching into one query. |
178 | $lb = $this->linkBatchFactory->newLinkBatch(); |
179 | /** |
180 | * @var WikiPageMessageGroup $page |
181 | */ |
182 | foreach ( $translatablePages as $page ) { |
183 | if ( MessageGroups::getPriority( $page ) === 'discouraged' ) { |
184 | continue; |
185 | } |
186 | '@phan-var WikiPageMessageGroup $page'; |
187 | $title = $page->getTitle(); |
188 | $lb->addObj( $title ); |
189 | $titles[] = $title; |
190 | } |
191 | $lb->execute(); |
192 | |
193 | $translatablePagesOptions = []; |
194 | foreach ( $titles as $title ) { |
195 | $translatablePagesOptions[$title->getPrefixedText()] = $title->getArticleID(); |
196 | } |
197 | |
198 | return $translatablePagesOptions; |
199 | } |
200 | |
201 | private function getSourceLanguage( Title $title ): string { |
202 | $translatablePage = TranslatablePage::newFromTitle( $title ); |
203 | return $translatablePage->getMessageGroup()->getSourceLanguage(); |
204 | } |
205 | |
206 | public function onSubmit( array $formData ): Status { |
207 | $translatablePageTitle = Title::newFromID( $formData['TranslatablePage'] ); |
208 | $notificationText = $formData['NotificationText']; |
209 | $priority = $formData['Priority']; |
210 | $deadlineDate = $formData['DeadlineDate']; |
211 | $selectedLanguages = $formData['SelectedLanguages']; |
212 | $pageSourceLangCode = $this->getSourceLanguage( $translatablePageTitle ); |
213 | $notificationLanguages = []; |
214 | |
215 | // The default is not to specify any languages and to send the notification to speakers of |
216 | // all the languages except the source language. When no languages are specified, |
217 | // an empty string will be sent here and an appropriate message will be shown in the log. |
218 | if ( count( $selectedLanguages ) ) { |
219 | // Filter out the source language |
220 | foreach ( $selectedLanguages as $langCode ) { |
221 | if ( $langCode !== $pageSourceLangCode ) { |
222 | $notificationLanguages[] = $langCode; |
223 | } |
224 | } |
225 | |
226 | if ( $notificationLanguages === [] ) { |
227 | return Status::newFatal( 'translationnotifications-sourcelang-only' ); |
228 | } |
229 | } |
230 | $languageSet = new LanguageSet( $formData['LanguageSet'] ); |
231 | |
232 | $requestData = [ |
233 | 'notificationText' => $notificationText, |
234 | 'priority' => $priority, |
235 | 'deadlineDate' => $deadlineDate, |
236 | 'selectedLanguages' => $selectedLanguages, |
237 | 'languageSet' => $languageSet->jsonSerialize(), |
238 | ]; |
239 | |
240 | $job = TranslationNotificationsSubmitJob::newJob( |
241 | $translatablePageTitle, |
242 | $requestData, |
243 | $this->getUser()->getId(), |
244 | $this->getLanguage()->getCode() |
245 | ); |
246 | |
247 | $this->jobQueueGroup->push( $job ); |
248 | return Status::newGood(); |
249 | } |
250 | |
251 | public function onSuccess() { |
252 | $this->getOutput()->addWikiMsg( 'translationnotifications-submit-ok' ); |
253 | } |
254 | } |