Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 289 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
SpecialCreateCollaborationHub | |
0.00% |
0 / 289 |
|
0.00% |
0 / 8 |
1056 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
doesWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
42 | |||
showForm | |
0.00% |
0 / 41 |
|
0.00% |
0 / 1 |
2 | |||
getFormFields | |
0.00% |
0 / 119 |
|
0.00% |
0 / 1 |
90 | |||
getOptions | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
doSubmit | |
0.00% |
0 / 93 |
|
0.00% |
0 / 1 |
132 | |||
onSuccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Form to create Collaboration Hubs + migrations/imports/clones |
5 | * Based on code from MassMessage/SpecialMovePage |
6 | * |
7 | * @file |
8 | */ |
9 | |
10 | class SpecialCreateCollaborationHub extends SpecialPage { |
11 | /** @var int */ |
12 | protected $titleNs; |
13 | |
14 | /** @var string */ |
15 | protected $titleText; |
16 | |
17 | /** @var string */ |
18 | protected $displayName; |
19 | |
20 | /** @var string */ |
21 | protected $icon; |
22 | |
23 | /** @var string */ |
24 | protected $colour; |
25 | |
26 | /** @var string */ |
27 | protected $introduction; |
28 | |
29 | /** @var bool */ |
30 | protected $overwrite; |
31 | |
32 | /** |
33 | * @param string $name |
34 | * @param string $right |
35 | */ |
36 | public function __construct( $name = 'CreateCollaborationHub', |
37 | $right = 'createpage' |
38 | ) { |
39 | // Note: The right check is primarily for UI. There are |
40 | // additional checks later on. |
41 | parent::__construct( $name, $right ); |
42 | } |
43 | |
44 | public function doesWrites() { |
45 | return true; |
46 | } |
47 | |
48 | /** |
49 | * @param string $par |
50 | */ |
51 | public function execute( $par ) { |
52 | $user = $this->getUser(); |
53 | |
54 | // More thorough permissions checks in doSubmit, but for now... |
55 | if ( !$user->isAllowed( 'createpage' ) ) { |
56 | throw new PermissionsError( 'createpage' ); |
57 | } |
58 | if ( !$user->isAllowed( 'editcontentmodel' ) ) { |
59 | throw new PermissionsError( 'editcontentmodel' ); |
60 | } |
61 | |
62 | $this->useTransactionalTimeLimit(); |
63 | |
64 | $this->checkReadOnly(); |
65 | $this->setHeaders(); |
66 | $this->outputHeader(); |
67 | |
68 | $request = $this->getRequest(); |
69 | $out = $this->getContext()->getOutput(); |
70 | |
71 | if ( $request->getVal( 'confirm' ) ) { |
72 | $out->wrapWikiMsg( |
73 | "<div class=\"warningbox\">\n$1\n</div>", |
74 | 'collaborationkit-createhub-confirmheader' |
75 | ); |
76 | } |
77 | |
78 | $this->titleText = $request->getText( 'titletext' ); |
79 | $this->titleNs = $request->getInt( 'titlens', 0 ); |
80 | $this->displayName = $request->getText( 'displayname' ); |
81 | $this->icon = $request->getText( 'icon' ); |
82 | $this->colour = $request->getText( 'colour' ); |
83 | $this->introduction = $request->getText( 'introduction' ); |
84 | $this->overwrite = $request->getBool( 'overwrite' ); |
85 | |
86 | if ( $request->getVal( 'action' ) == 'submit' && $request->wasPosted() ) { |
87 | $this->doSubmit(); |
88 | } else { |
89 | $this->showForm(); |
90 | } |
91 | } |
92 | |
93 | /** |
94 | * Show the form |
95 | */ |
96 | private function showForm() { |
97 | $out = $this->getOutput(); |
98 | |
99 | $out->addModules( [ |
100 | 'ext.CollaborationKit.hubtheme' |
101 | ] ); |
102 | $out->addModuleStyles( [ |
103 | 'mediawiki.special', |
104 | 'ext.CollaborationKit.edit.styles', |
105 | 'ext.CollaborationKit.createhub.styles' |
106 | ] ); |
107 | $out->addJsConfigVars( |
108 | 'wgCollaborationKitColourList', |
109 | CollaborationHubContent::getThemeColours() |
110 | ); |
111 | // For some reason we're not using the standard special page intro |
112 | // (formspecialpage didn't use it), so we gotta manually add our own... |
113 | $out->addWikiMsg( 'createcollaborationhub-text' ); |
114 | $out->enableOOUI(); |
115 | |
116 | // Not actually correct for FormSpecialPage anymore, but still nice structure... |
117 | $fields = $this->getFormFields(); |
118 | |
119 | $fieldset1 = new OOUI\FieldsetLayout( [ |
120 | 'classes' => [ |
121 | 'mw-ck-hub-topform', |
122 | 'ck-createcollaborationhub-setup' |
123 | ], |
124 | 'items' => $fields[0], |
125 | ] ); |
126 | $fieldset2 = new OOUI\FieldsetLayout( [ |
127 | 'classes' => [ 'ck-createcollaborationhub-block' ], |
128 | 'items' => $fields[1], |
129 | ] ); |
130 | |
131 | $form = new OOUI\FormLayout( [ |
132 | 'method' => 'post', |
133 | 'action' => $this->getPageTitle()->getLocalURL( 'action=submit' ), |
134 | 'classes' => [ 'ck-createcollaborationhub' ], |
135 | ] ); |
136 | $form->appendContent( $fieldset1, $fieldset2 ); |
137 | |
138 | $out->addHTML( |
139 | new OOUI\PanelLayout( [ |
140 | 'expanded' => false, |
141 | 'padded' => false, |
142 | 'framed' => false, |
143 | 'content' => $form, |
144 | ] ) |
145 | ); |
146 | } |
147 | |
148 | /** |
149 | * @return array |
150 | */ |
151 | protected function getFormFields() { |
152 | $allowedNamespaces = $this->getConfig() |
153 | ->get( 'CollaborationListAllowedNamespaces' ); |
154 | $excludeNamespaces = []; |
155 | foreach ( array_keys( $this->getLanguage()->getNamespaces() ) as $option ) { |
156 | if ( !isset( $allowedNamespaces[$option] ) || !$allowedNamespaces[$option] ) { |
157 | $excludeNamespaces[] = $option; |
158 | } |
159 | } |
160 | |
161 | $titleInput = [ |
162 | 'namespace' => [ |
163 | 'classes' => [ 'mw-ck-namespace-input' ], |
164 | 'name' => 'titlens', |
165 | 'exclude' => $excludeNamespaces, |
166 | 'required' => true |
167 | ], |
168 | 'title' => [ |
169 | 'classes' => [ 'mw-ck-title-input' ], |
170 | 'placeholder' => $this->msg( 'collaborationkit-createhub-title-placeholder' )->text(), |
171 | 'name' => 'titletext', |
172 | 'suggestions' => false, |
173 | 'required' => true, |
174 | 'value' => $this->titleText |
175 | ], |
176 | 'infusable' => true |
177 | ]; |
178 | |
179 | // Our preference is the Project namespace |
180 | if ( $this->titleNs !== null && array_key_exists( $this->titleNs, $allowedNamespaces ) ) { |
181 | $titleInput['namespace']['value'] = $this->titleNs; |
182 | } elseif ( array_key_exists( NS_PROJECT, $allowedNamespaces ) ) { |
183 | $titleInput['namespace']['value'] = NS_PROJECT; |
184 | } |
185 | |
186 | $fields = [ [], [] ]; |
187 | |
188 | $fields[0][] = new OOUI\FieldLayout( |
189 | new MediaWiki\Widget\ComplexTitleInputWidget( $titleInput ), |
190 | [ |
191 | 'label' => $this->msg( 'collaborationkit-createhub-title' )->text(), |
192 | 'align' => 'top', |
193 | 'classes' => [ 'mw-ck-title-input' ], |
194 | 'helpInline' => true, |
195 | 'help' => $this->msg( 'collaborationkit-createhub-title-help' )->text(), |
196 | ] |
197 | ); |
198 | |
199 | $fields[0][] = new OOUI\FieldLayout( |
200 | new OOUI\TextInputWidget( [ |
201 | // Display name can be different from page title |
202 | 'name' => 'displayname', |
203 | 'value' => $this->displayName |
204 | ] ), |
205 | [ |
206 | 'classes' => [ 'mw-ck-display-input' ], |
207 | 'label' => $this->msg( 'collaborationkit-hubedit-displayname' )->text(), |
208 | 'helpInline' => true, |
209 | 'help' => new OOUI\HtmlSnippet( |
210 | $this->msg( 'collaborationkit-hubedit-displayname-help' )->parse() |
211 | ), |
212 | 'align' => 'top', |
213 | ] |
214 | ); |
215 | $fields[0][] = new OOUI\FieldLayout( |
216 | new OOUI\TextInputWidget( [ |
217 | // Display name can be different from page title |
218 | 'name' => 'icon', |
219 | 'value' => $this->icon |
220 | ] ), |
221 | [ |
222 | 'classes' => [ 'mw-ck-hub-image-input' ], |
223 | 'label' => $this->msg( 'collaborationkit-hubedit-image' )->text(), |
224 | 'helpInline' => true, |
225 | 'help' => new OOUI\HtmlSnippet( $this->msg( 'collaborationkit-hubedit-image-help' )->parse() ), |
226 | 'align' => 'top', |
227 | ] |
228 | ); |
229 | |
230 | // Colours for the hub styles |
231 | $colours = []; |
232 | foreach ( CollaborationHubContent::getThemeColours() as $colour ) { |
233 | $colours['collaborationkit-' . $colour] = $colour; |
234 | } |
235 | |
236 | $fields[0][] = new OOUI\FieldLayout( |
237 | new OOUI\DropdownInputWidget( [ |
238 | // Display name can be different from page title |
239 | 'name' => 'colour', |
240 | 'options' => $this->getOptions( $colours ), |
241 | 'value' => $this->colour |
242 | ] ), |
243 | [ |
244 | 'label' => $this->msg( 'collaborationkit-hubedit-colour' )->text(), |
245 | 'align' => 'top', |
246 | 'classes' => [ 'mw-ck-colour-input' ], |
247 | ] |
248 | ); |
249 | |
250 | $fields[1][] = new OOUI\FieldLayout( |
251 | new OOUI\MultilineTextInputWidget( [ |
252 | 'name' => 'introduction', |
253 | 'rows' => 5, |
254 | 'placeholder' => $this->msg( 'collaborationkit-hubedit-introduction-placeholder' )->text(), |
255 | 'value' => $this->introduction |
256 | ] ), |
257 | [ |
258 | 'label' => $this->msg( 'collaborationkit-hubedit-introduction' )->text(), |
259 | 'align' => 'top', |
260 | 'classes' => [ 'mw-ck-introduction-input' ] |
261 | ] |
262 | ); |
263 | |
264 | // This form can be used to overwrite existing pages, but the user must |
265 | // confirm first. |
266 | if ( $this->getRequest()->getVal( 'confirm' ) ) { |
267 | $fields[1][] = new OOUI\FieldLayout( |
268 | new OOUI\CheckboxInputWidget( [ |
269 | 'name' => 'overwrite', |
270 | 'value' => '1' |
271 | ] ), |
272 | [ |
273 | 'label' => $this->msg( 'collaborationkit-createhub-confirm' )->text(), |
274 | 'classes' => [ 'mw-ck-confirm-input' ], |
275 | 'align' => 'inline', |
276 | ] |
277 | ); |
278 | } |
279 | |
280 | $fields[1][] = new OOUI\FieldLayout( |
281 | new OOUI\ButtonInputWidget( [ |
282 | 'name' => 'submit', |
283 | 'value' => 'submit', |
284 | 'label' => $this->msg( 'collaborationkit-createhub-submit' )->text(), |
285 | 'flags' => [ 'primary', 'progressive' ], |
286 | 'type' => 'submit', |
287 | ] ), |
288 | [ |
289 | 'align' => 'top', |
290 | ] |
291 | ); |
292 | |
293 | return $fields; |
294 | } |
295 | |
296 | /** |
297 | * Build and return the associative array for the content source field. |
298 | * @param array $mapping |
299 | * @return array |
300 | */ |
301 | protected function getOptions( $mapping ) { |
302 | $options = []; |
303 | foreach ( $mapping as $msgKey => $option ) { |
304 | $options[] = [ |
305 | 'data' => $option, |
306 | 'label' => $this->msg( $msgKey )->text() |
307 | ]; |
308 | } |
309 | return $options; |
310 | } |
311 | |
312 | /** |
313 | * @return Status |
314 | */ |
315 | public function doSubmit() { |
316 | $title = Title::makeTitleSafe( $this->titleNs, $this->titleText ); |
317 | $user = $this->getUser(); |
318 | $permissionManager = MediaWiki\MediaWikiServices::getInstance()->getPermissionManager(); |
319 | |
320 | if ( !$title ) { |
321 | return Status::newFatal( 'collaborationkit-createhub-invalidtitle' ); |
322 | } |
323 | |
324 | // TODO: Consider changing to getUserPermissionsErrors for |
325 | // better error message. Possibly as a first step in constructor |
326 | // as the non-title specific error. |
327 | if ( |
328 | !$permissionManager->userCan( 'editcontentmodel', $user, $title ) || |
329 | !$permissionManager->userCan( 'edit', $user, $title ) |
330 | ) { |
331 | return Status::newFatal( 'collaborationkit-createhub-nopermission' ); |
332 | } |
333 | |
334 | $context = $this->getContext(); |
335 | // If a page already exists at the title, ask the user before over- |
336 | // writing the page. |
337 | if ( $title->exists() && !$this->overwrite ) { |
338 | $this->getOutput()->redirect( |
339 | SpecialPage::getTitleFor( 'CreateCollaborationHub' )->getFullURL( [ |
340 | 'titletext' => $this->titleText, |
341 | 'titlens' => $this->titleNs, |
342 | 'displayname' => $this->displayName, |
343 | 'icon' => $this->icon, |
344 | 'colour' => $this->colour, |
345 | 'introduction' => $this->introduction, |
346 | 'confirm' => 1 |
347 | ] ) |
348 | ); |
349 | |
350 | return Status::newGood(); |
351 | } |
352 | |
353 | // Create member list |
354 | $memberListTitle = Title::newFromText( |
355 | $title->getFullText() |
356 | . '/' |
357 | . $this->msg( 'collaborationkit-hub-pagetitle-members' ) |
358 | ->inContentLanguage() |
359 | ->plain() |
360 | ); |
361 | if ( !$memberListTitle ) { |
362 | return Status::newFatal( 'collaborationkit-createhub-invalidtitle' ); |
363 | } |
364 | $memberResult = CollaborationListContentHandler::postMemberList( |
365 | $memberListTitle, |
366 | $this->msg( 'collaborationkit-createhub-editsummary' ) |
367 | ->inContentLanguage() |
368 | ->plain(), |
369 | $context |
370 | ); |
371 | |
372 | if ( !$memberResult->isGood() ) { |
373 | return $memberResult; |
374 | } |
375 | |
376 | // Create announcements page |
377 | $announcementsTitle = Title::newFromText( $title->getFullText() |
378 | . '/' |
379 | . $this->msg( 'collaborationkit-hub-pagetitle-announcements' ) |
380 | ->inContentLanguage() |
381 | ->plain() |
382 | ); |
383 | if ( !$announcementsTitle ) { |
384 | return Status::newFatal( 'collaborationkit-createhub-invalidtitle' ); |
385 | } |
386 | |
387 | $der = new DerivativeContext( $context ); |
388 | $request = new DerivativeRequest( |
389 | $context->getRequest(), |
390 | [ |
391 | 'action' => 'edit', |
392 | 'title' => $announcementsTitle->getFullText(), |
393 | 'text' => "* " . $context |
394 | ->msg( 'collaborationkit-hub-announcements-initial' ) |
395 | ->inContentLanguage() |
396 | ->plain() |
397 | . " ~~~~~", |
398 | 'summary' => $context |
399 | ->msg( 'collaborationkit-createhub-editsummary' ) |
400 | ->inContentLanguage() |
401 | ->plain(), |
402 | 'token' => $context->getUser()->getEditToken(), |
403 | ], |
404 | true // Treat data as POSTed |
405 | ); |
406 | $der->setRequest( $request ); |
407 | try { |
408 | $api = new ApiMain( $der, true ); |
409 | $api->execute(); |
410 | } catch ( ApiUsageException $e ) { |
411 | return Status::newFatal( |
412 | $context->msg( 'collaborationkit-hub-edit-apierror', |
413 | $e->getMessageObject() ) |
414 | ); |
415 | } |
416 | |
417 | // Now, to create the hub itself |
418 | $result = CollaborationHubContentHandler::edit( |
419 | $title, |
420 | $this->displayName, |
421 | $this->icon, |
422 | $this->colour, |
423 | $this->introduction, |
424 | '', |
425 | [], |
426 | $this |
427 | ->msg( 'collaborationkit-createhub-editsummary' ) |
428 | ->inContentLanguage() |
429 | ->plain(), |
430 | $context |
431 | ); |
432 | |
433 | if ( !$result->isGood() ) { |
434 | return $result; |
435 | } |
436 | |
437 | // Once all the pages we want to create are created, we send them to |
438 | // the first one |
439 | $this->getOutput()->redirect( $title->getFullURL() ); |
440 | return Status::newGood(); |
441 | } |
442 | |
443 | public function onSuccess() { |
444 | // No-op: We have already redirected. |
445 | } |
446 | } |