Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 251 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 1 |
Hooks | |
0.00% |
0 / 251 |
|
0.00% |
0 / 9 |
2550 | |
0.00% |
0 / 1 |
onSidebarBeforeOutput | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
20 | |||
getPortlet | |
0.00% |
0 / 54 |
|
0.00% |
0 / 1 |
210 | |||
onSiteNoticeAfter | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
182 | |||
renderBookCreatorBox | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
12 | |||
getBookCreatorBoxContent | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getBookCreatorBoxAddRemoveLink | |
0.00% |
0 / 59 |
|
0.00% |
0 / 1 |
72 | |||
getBookCreatorBoxShowBookLink | |
0.00% |
0 / 35 |
|
0.00% |
0 / 1 |
6 | |||
getBookCreatorBoxSuggestLink | |
0.00% |
0 / 37 |
|
0.00% |
0 / 1 |
12 | |||
onOutputPageCheckLastModified | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * Collection Extension for MediaWiki |
4 | * |
5 | * Copyright (C) PediaPress GmbH |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; if not, write to the Free Software Foundation, Inc., |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | * http://www.gnu.org/copyleft/gpl.html |
21 | */ |
22 | |
23 | namespace MediaWiki\Extension\Collection; |
24 | |
25 | use MediaWiki\Hook\OutputPageCheckLastModifiedHook; |
26 | use MediaWiki\Hook\SidebarBeforeOutputHook; |
27 | use MediaWiki\Hook\SiteNoticeAfterHook; |
28 | use MediaWiki\Html\Html; |
29 | use MediaWiki\Html\TemplateParser; |
30 | use MediaWiki\Linker\Linker; |
31 | use MediaWiki\MainConfigNames; |
32 | use MediaWiki\Output\OutputPage; |
33 | use MediaWiki\Session\SessionManager; |
34 | use MediaWiki\SpecialPage\SpecialPage; |
35 | use MediaWiki\Title\Title; |
36 | use RequestContext; |
37 | use Skin; |
38 | |
39 | class Hooks implements |
40 | SidebarBeforeOutputHook, |
41 | SiteNoticeAfterHook, |
42 | OutputPageCheckLastModifiedHook |
43 | { |
44 | /** |
45 | * Callback for SidebarBeforeOutput hook |
46 | * |
47 | * @param Skin $skin |
48 | * @param array &$sidebar |
49 | */ |
50 | public function onSidebarBeforeOutput( $skin, &$sidebar ): void { |
51 | global $wgCollectionPortletForLoggedInUsersOnly; |
52 | |
53 | if ( !$wgCollectionPortletForLoggedInUsersOnly || $skin->getUser()->isRegistered() ) { |
54 | |
55 | $portlet = self::getPortlet( $skin ); |
56 | |
57 | if ( $portlet ) { |
58 | // Unset 'print' item. We have moved it to our own section. |
59 | unset( $sidebar['TOOLBOX']['print'] ); |
60 | |
61 | // Add our section |
62 | $sidebar[ 'coll-print_export' ] = $portlet; |
63 | } |
64 | } |
65 | } |
66 | |
67 | /** |
68 | * Return HTML-code to be inserted as portlet |
69 | * |
70 | * @param Skin $sk |
71 | * |
72 | * @return array[]|false |
73 | */ |
74 | public static function getPortlet( $sk ) { |
75 | global $wgCollectionArticleNamespaces; |
76 | global $wgCollectionFormats; |
77 | global $wgCollectionPortletFormats; |
78 | |
79 | $title = $sk->getTitle(); |
80 | |
81 | if ( $title === null || !$title->exists() ) { |
82 | return false; |
83 | } |
84 | |
85 | $namespace = $title->getNamespace(); |
86 | |
87 | if ( !in_array( $namespace, $wgCollectionArticleNamespaces ) |
88 | && $namespace != NS_CATEGORY ) { |
89 | return false; |
90 | } |
91 | |
92 | $action = $sk->getRequest()->getVal( 'action', 'view' ); |
93 | if ( $action != 'view' && $action != 'purge' ) { |
94 | return false; |
95 | } |
96 | |
97 | $out = []; |
98 | |
99 | $booktitle = SpecialPage::getTitleFor( 'Book' ); |
100 | if ( !Session::isEnabled() ) { |
101 | if ( !$sk->getConfig()->get( 'CollectionDisableSidebarLink' ) ) { |
102 | $out[] = [ |
103 | 'text' => $sk->msg( 'coll-create_a_book' )->escaped(), |
104 | 'id' => 'coll-create_a_book', |
105 | 'href' => $booktitle->getLocalURL( |
106 | [ 'bookcmd' => 'book_creator', 'referer' => $title->getPrefixedText() ] |
107 | ), |
108 | ]; |
109 | } |
110 | } else { |
111 | $out[] = [ |
112 | 'text' => $sk->msg( 'coll-book_creator_disable' )->escaped(), |
113 | 'id' => 'coll-book_creator_disable', |
114 | 'href' => $booktitle->getLocalURL( |
115 | [ |
116 | 'bookcmd' => 'stop_book_creator', |
117 | 'referer' => $title->getPrefixedText(), |
118 | ] |
119 | ), |
120 | ]; |
121 | } |
122 | |
123 | $params = [ |
124 | 'bookcmd' => 'render_article', |
125 | 'arttitle' => $title->getPrefixedText(), |
126 | 'returnto' => $title->getPrefixedText(), |
127 | ]; |
128 | |
129 | $oldid = $sk->getRequest()->getVal( 'oldid' ); |
130 | if ( $oldid ) { |
131 | $params['oldid'] = $oldid; |
132 | } else { |
133 | $params['oldid'] = $title->getLatestRevID(); |
134 | } |
135 | |
136 | foreach ( $wgCollectionPortletFormats as $writer ) { |
137 | $params['writer'] = $writer; |
138 | $out[] = [ |
139 | 'text' => $sk->msg( 'coll-download_as', $wgCollectionFormats[$writer] )->escaped(), |
140 | 'id' => 'coll-download-as-' . $writer, |
141 | 'href' => $booktitle->getLocalURL( $params ), |
142 | ]; |
143 | } |
144 | |
145 | // Move the 'printable' link into our section for consistency |
146 | if ( $action == 'view' || $action == 'purge' ) { |
147 | if ( !$sk->getOutput()->isPrintable() ) { |
148 | $out[] = [ 'text' => $sk->msg( 'printableversion' )->text(), |
149 | 'id' => 't-print', |
150 | 'href' => $title->getLocalURL( [ 'printable' => 'yes' ] ) |
151 | ]; |
152 | } |
153 | } |
154 | |
155 | return $out; |
156 | } |
157 | |
158 | /** |
159 | * Callback for hook SiteNoticeAfter |
160 | * @param string &$siteNotice |
161 | * @param Skin $skin |
162 | */ |
163 | public function onSiteNoticeAfter( &$siteNotice, $skin ) { |
164 | global $wgCollectionArticleNamespaces; |
165 | |
166 | $request = $skin->getRequest(); |
167 | $title = $skin->getTitle(); |
168 | |
169 | $action = $request->getVal( 'action' ); |
170 | if ( $action != '' && $action != 'view' && $action != 'purge' ) { |
171 | return; |
172 | } |
173 | |
174 | $session = SessionManager::getGlobalSession(); |
175 | |
176 | if ( |
177 | !isset( $session['wsCollection'] ) || |
178 | !isset( $session['wsCollection']['enabled'] ) || |
179 | !$session['wsCollection']['enabled'] |
180 | ) { |
181 | return; |
182 | } |
183 | |
184 | if ( $title->isSpecial( 'Book' ) ) { |
185 | $cmd = $request->getVal( 'bookcmd', '' ); |
186 | if ( $cmd == 'suggest' ) { |
187 | $siteNotice .= self::renderBookCreatorBox( $title, 'suggest' ); |
188 | } elseif ( $cmd == '' ) { |
189 | $siteNotice .= self::renderBookCreatorBox( $title, 'showbook' ); |
190 | } |
191 | return; |
192 | } |
193 | |
194 | if ( !$title->exists() ) { |
195 | return; |
196 | } |
197 | |
198 | $namespace = $title->getNamespace(); |
199 | if ( !in_array( $namespace, $wgCollectionArticleNamespaces ) |
200 | && $namespace != NS_CATEGORY ) { |
201 | return; |
202 | } |
203 | |
204 | $siteNotice .= self::renderBookCreatorBox( $title ); |
205 | } |
206 | |
207 | /** |
208 | * @param Title $title |
209 | * @param string $mode |
210 | * @return string |
211 | */ |
212 | public static function renderBookCreatorBox( Title $title, $mode = '' ) { |
213 | $templateParser = new TemplateParser( dirname( __DIR__ ) . '/templates' ); |
214 | $context = RequestContext::getMain(); |
215 | |
216 | $imagePath = $context->getConfig()->get( MainConfigNames::ExtensionAssetsPath ) . '/Collection/images'; |
217 | $ptext = $title->getPrefixedText(); |
218 | $oldid = $context->getRequest()->getInt( 'oldid', 0 ); |
219 | if ( $oldid == $title->getLatestRevID() ) { |
220 | $oldid = 0; |
221 | } |
222 | |
223 | $out = $context->getOutput(); |
224 | $out->addModules( 'ext.collection.bookcreator' ); |
225 | $out->addModuleStyles( 'ext.collection.bookcreator.styles' ); |
226 | |
227 | $addRemoveState = $mode; |
228 | $helpPage = Title::newFromText( $context->msg( 'coll-helppage' )->text() ); |
229 | |
230 | return $templateParser->processTemplate( 'create-book', [ |
231 | "actionsHtml" => self::getBookCreatorBoxContent( $title, $addRemoveState, $oldid ), |
232 | "imagePath" => $imagePath, |
233 | "title" => $context->msg( 'coll-book_creator' )->text(), |
234 | "disable" => [ |
235 | "url" => SpecialPage::getTitleFor( 'Book' )->getLocalUrl( |
236 | [ 'bookcmd' => 'stop_book_creator', 'referer' => $ptext ] |
237 | ), |
238 | "title" => $context->msg( 'coll-book_creator_disable_tooltip' )->text(), |
239 | "label" => $context->msg( 'coll-disable' )->escaped(), |
240 | ], |
241 | "help" => [ |
242 | "url" => $helpPage ? $helpPage->getLocalUrl() : '', |
243 | "label" => $context->msg( 'coll-help' )->escaped(), |
244 | "title" => $context->msg( 'coll-help_tooltip' )->text(), |
245 | "icon" => $imagePath . '/silk-help.png', |
246 | ] |
247 | ] ); |
248 | } |
249 | |
250 | /** |
251 | * @param Title $title |
252 | * @param string|null $hint Defaults to null |
253 | * @param null|int $oldid |
254 | * @return string |
255 | */ |
256 | public static function getBookCreatorBoxContent( Title $title, $hint = null, $oldid = null ) { |
257 | global $wgExtensionAssetsPath; |
258 | |
259 | $imagePath = "$wgExtensionAssetsPath/Collection/images"; |
260 | |
261 | return self::getBookCreatorBoxAddRemoveLink( $imagePath, $hint, $title, $oldid ) |
262 | . self::getBookCreatorBoxShowBookLink( $imagePath, $hint ) |
263 | . self::getBookCreatorBoxSuggestLink( $imagePath, $hint ); |
264 | } |
265 | |
266 | /** |
267 | * @param string $imagePath |
268 | * @param string $hint |
269 | * @param Title $title |
270 | * @param int $oldid |
271 | * @return string |
272 | */ |
273 | public static function getBookCreatorBoxAddRemoveLink( |
274 | $imagePath, |
275 | $hint, |
276 | Title $title, |
277 | $oldid |
278 | ) { |
279 | $namespace = $title->getNamespace(); |
280 | $ptext = $title->getPrefixedText(); |
281 | |
282 | if ( $hint == 'suggest' || $hint == 'showbook' ) { |
283 | return Html::rawElement( 'span', |
284 | [ 'style' => 'color: #777;' ], |
285 | Html::element( 'img', |
286 | [ |
287 | 'src' => "$imagePath/disabled.png", |
288 | 'alt' => '', |
289 | 'width' => '16', |
290 | 'height' => '16', |
291 | 'style' => 'vertical-align: text-bottom', |
292 | ] |
293 | ) |
294 | . ' ' . wfMessage( 'coll-not_addable' )->escaped() |
295 | ); |
296 | } |
297 | |
298 | if ( $hint == 'addcategory' || $namespace == NS_CATEGORY ) { |
299 | $id = 'coll-add_category'; |
300 | $icon = 'silk-add.png'; |
301 | $captionMsg = 'coll-add_category'; |
302 | $tooltipMsg = 'coll-add_category_tooltip'; |
303 | $query = [ 'bookcmd' => 'add_category', 'cattitle' => $title->getText() ]; |
304 | $onclick = "collectionCall('addcategory', mw.config.get('wgNamespaceNumber')," . |
305 | "mw.config.get('wgTitle')]); return false;"; |
306 | } else { |
307 | $collectionArgsJs = "mw.config.get('wgNamespaceNumber'), mw.config.get('wgTitle'), " . |
308 | Html::encodeJsVar( $oldid ); |
309 | if ( $hint == 'addarticle' |
310 | || ( $hint == '' && Session::findArticle( $ptext, $oldid ) == -1 ) ) { |
311 | $id = 'coll-add_article'; |
312 | $icon = 'silk-add.png'; |
313 | $captionMsg = 'coll-add_this_page'; |
314 | $tooltipMsg = 'coll-add_page_tooltip'; |
315 | $query = [ 'bookcmd' => 'add_article', 'arttitle' => $ptext, 'oldid' => $oldid ]; |
316 | $onclick = "collectionCall('addarticle', " . $collectionArgsJs . "); return false;"; |
317 | } else { |
318 | $id = 'coll-remove_article'; |
319 | $icon = 'silk-remove.png'; |
320 | $captionMsg = 'coll-remove_this_page'; |
321 | $tooltipMsg = 'coll-remove_page_tooltip'; |
322 | $query = [ 'bookcmd' => 'remove_article', 'arttitle' => $ptext, 'oldid' => $oldid ]; |
323 | $onclick = "collectionCall('removearticle', " . $collectionArgsJs . "); return false;"; |
324 | } |
325 | } |
326 | |
327 | return Linker::linkKnown( |
328 | SpecialPage::getTitleFor( 'Book' ), |
329 | Html::element( 'img', |
330 | [ |
331 | 'src' => "$imagePath/$icon", |
332 | 'alt' => '', |
333 | 'width' => '16', |
334 | 'height' => '16', |
335 | ] |
336 | ) |
337 | . ' ' . wfMessage( $captionMsg )->escaped(), |
338 | [ |
339 | 'id' => $id, |
340 | 'rel' => 'nofollow', |
341 | 'title' => wfMessage( $tooltipMsg )->text(), |
342 | 'onclick' => $onclick, |
343 | ], |
344 | $query |
345 | ); |
346 | } |
347 | |
348 | /** |
349 | * @param string $imagePath |
350 | * @param string $hint |
351 | * @return string |
352 | */ |
353 | public static function getBookCreatorBoxShowBookLink( $imagePath, $hint ) { |
354 | $numArticles = Session::countArticles(); |
355 | |
356 | if ( $hint == 'showbook' ) { |
357 | return Html::rawElement( 'strong', |
358 | [ |
359 | 'class' => 'collection-creatorbox-iconlink', |
360 | ], |
361 | Html::element( 'img', |
362 | [ |
363 | 'src' => "$imagePath/silk-book_open.png", |
364 | 'alt' => '', |
365 | 'width' => '16', |
366 | 'height' => '16', |
367 | ] |
368 | ) |
369 | . ' ' . wfMessage( 'coll-show_collection' )->escaped() |
370 | . ' (' . wfMessage( 'coll-n_pages' )->numParams( $numArticles )->escaped() . ')' |
371 | ); // @todo FIXME: Hard coded parentheses. |
372 | } else { |
373 | return Linker::linkKnown( |
374 | SpecialPage::getTitleFor( 'Book' ), |
375 | Html::element( 'img', |
376 | [ |
377 | 'src' => "$imagePath/silk-book_open.png", |
378 | 'alt' => '', |
379 | 'width' => '16', |
380 | 'height' => '16', |
381 | ] |
382 | ) |
383 | . ' ' . wfMessage( 'coll-show_collection' )->escaped() |
384 | . ' (' . wfMessage( 'coll-n_pages' )->numParams( $numArticles )->escaped() . ')', |
385 | [ |
386 | 'rel' => 'nofollow', |
387 | 'title' => wfMessage( 'coll-show_collection_tooltip' )->text(), |
388 | 'class' => 'collection-creatorbox-iconlink', |
389 | ] |
390 | ); // @todo FIXME: Hard coded parentheses. |
391 | } |
392 | } |
393 | |
394 | /** |
395 | * @param string $imagePath |
396 | * @param string $hint |
397 | * @return string |
398 | */ |
399 | public static function getBookCreatorBoxSuggestLink( $imagePath, $hint ) { |
400 | if ( wfMessage( 'coll-suggest_enabled' )->escaped() != '1' ) { |
401 | return ''; |
402 | } |
403 | |
404 | if ( $hint == 'suggest' ) { |
405 | return Html::rawElement( 'strong', |
406 | [ |
407 | 'class' => 'collection-creatorbox-iconlink', |
408 | ], |
409 | Html::element( 'img', |
410 | [ |
411 | 'src' => "$imagePath/silk-wand.png", |
412 | 'alt' => '', |
413 | 'width' => '16', |
414 | 'height' => '16', |
415 | 'style' => 'vertical-align: text-bottom', |
416 | ] |
417 | ) |
418 | . ' ' . wfMessage( 'coll-make_suggestions' )->escaped() |
419 | ); |
420 | } else { |
421 | return Linker::linkKnown( |
422 | SpecialPage::getTitleFor( 'Book' ), |
423 | Html::element( 'img', |
424 | [ |
425 | 'src' => "$imagePath/silk-wand.png", |
426 | 'alt' => '', |
427 | 'width' => '16', |
428 | 'height' => '16', |
429 | 'style' => 'vertical-align: text-bottom', |
430 | ] |
431 | ) |
432 | . ' ' . wfMessage( 'coll-make_suggestions' )->escaped(), |
433 | [ |
434 | 'rel' => 'nofollow', |
435 | 'title' => wfMessage( 'coll-make_suggestions_tooltip' )->text(), |
436 | 'class' => 'collection-creatorbox-iconlink', |
437 | ], |
438 | [ 'bookcmd' => 'suggest' ] |
439 | ); |
440 | } |
441 | } |
442 | |
443 | /** |
444 | * OutputPageCheckLastModified hook |
445 | * @param array &$modifiedTimes |
446 | * @param OutputPage $out |
447 | */ |
448 | public function onOutputPageCheckLastModified( &$modifiedTimes, $out ) { |
449 | $session = SessionManager::getGlobalSession(); |
450 | if ( isset( $session['wsCollection']['timestamp'] ) ) { |
451 | $modifiedTimes['collection'] = $session['wsCollection']['timestamp']; |
452 | } |
453 | } |
454 | } |