Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 68 |
|
0.00% |
0 / 23 |
CRAP | |
0.00% |
0 / 1 |
ImageGalleryBase | |
0.00% |
0 / 68 |
|
0.00% |
0 / 23 |
1332 | |
0.00% |
0 / 1 |
factory | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
20 | |||
loadModes | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
6 | |||
__construct | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
6 | |||
setParser | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setHideBadImages | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setCaption | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setCaptionHtml | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setPerRow | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
setWidths | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
setHeights | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
setAdditionalOptions | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
add | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
insert | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getImages | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isEmpty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setShowDimensions | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setShowBytes | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setShowFilename | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setAttributes | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
toHTML | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
count | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setContextTitle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getContextTitle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRenderLang | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * Image gallery. |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | */ |
22 | |
23 | use MediaWiki\Context\ContextSource; |
24 | use MediaWiki\Context\IContextSource; |
25 | use MediaWiki\Context\RequestContext; |
26 | use MediaWiki\HookContainer\HookRunner; |
27 | use MediaWiki\MainConfigNames; |
28 | use MediaWiki\MediaWikiServices; |
29 | use MediaWiki\Parser\Parser; |
30 | use MediaWiki\Title\Title; |
31 | |
32 | /** |
33 | * Image gallery |
34 | * |
35 | * Add images to the gallery using add(), then render that list to HTML using toHTML(). |
36 | * @stable to extend |
37 | * @ingroup Media |
38 | */ |
39 | abstract class ImageGalleryBase extends ContextSource { |
40 | public const LOADING_DEFAULT = 1; |
41 | public const LOADING_LAZY = 2; |
42 | |
43 | /** |
44 | * @var array[] Gallery images |
45 | * @phan-var array<int,array{0:Title,1:string,2:string,3:string,4:array,5:int}> |
46 | */ |
47 | protected $mImages; |
48 | |
49 | /** |
50 | * @var bool Whether to show the filesize in bytes in categories |
51 | */ |
52 | protected $mShowBytes; |
53 | |
54 | /** |
55 | * @var bool Whether to show the dimensions in categories |
56 | */ |
57 | protected $mShowDimensions; |
58 | |
59 | /** |
60 | * @var bool Whether to show the filename. Default: true |
61 | */ |
62 | protected $mShowFilename; |
63 | |
64 | /** |
65 | * @var string Gallery mode. Default: traditional |
66 | */ |
67 | protected $mMode; |
68 | |
69 | /** |
70 | * @var string|false Gallery caption. Default: false |
71 | */ |
72 | protected $mCaption = false; |
73 | |
74 | /** |
75 | * Length to truncate filename to in caption when using "showfilename". |
76 | * A value of 'true' will truncate the filename to one line using CSS |
77 | * and will be the behaviour after deprecation. |
78 | * |
79 | * @var bool|int |
80 | */ |
81 | protected $mCaptionLength = true; |
82 | |
83 | /** |
84 | * @var bool Hide bad images? |
85 | */ |
86 | protected $mHideBadImages; |
87 | |
88 | /** |
89 | * @var Parser|false Registered parser object for output callbacks |
90 | */ |
91 | public $mParser; |
92 | |
93 | /** |
94 | * @var Title|null Contextual title, used when images are being screened against |
95 | * the bad image list |
96 | */ |
97 | protected $contextTitle = null; |
98 | |
99 | /** @var array */ |
100 | protected $mAttribs = []; |
101 | |
102 | /** @var int */ |
103 | protected $mPerRow; |
104 | |
105 | /** @var int */ |
106 | protected $mWidths; |
107 | |
108 | /** @var int */ |
109 | protected $mHeights; |
110 | |
111 | /** @var array */ |
112 | private static $modeMapping; |
113 | |
114 | /** |
115 | * Get a new image gallery. This is the method other callers |
116 | * should use to get a gallery. |
117 | * |
118 | * @param string|false $mode Mode to use. False to use the default |
119 | * @param IContextSource|null $context |
120 | * @return ImageGalleryBase |
121 | * @throws ImageGalleryClassNotFoundException |
122 | */ |
123 | public static function factory( $mode = false, IContextSource $context = null ) { |
124 | self::loadModes(); |
125 | if ( !$context ) { |
126 | $context = RequestContext::getMainAndWarn( __METHOD__ ); |
127 | } |
128 | if ( !$mode ) { |
129 | $galleryOptions = $context->getConfig()->get( MainConfigNames::GalleryOptions ); |
130 | $mode = $galleryOptions['mode']; |
131 | } |
132 | |
133 | $mode = MediaWikiServices::getInstance()->getContentLanguage()->lc( $mode ); |
134 | |
135 | if ( isset( self::$modeMapping[$mode] ) ) { |
136 | $class = self::$modeMapping[$mode]; |
137 | return new $class( $mode, $context ); |
138 | } else { |
139 | throw new ImageGalleryClassNotFoundException( "No gallery class registered for mode $mode" ); |
140 | } |
141 | } |
142 | |
143 | private static function loadModes() { |
144 | if ( self::$modeMapping === null ) { |
145 | self::$modeMapping = [ |
146 | 'traditional' => TraditionalImageGallery::class, |
147 | 'nolines' => NolinesImageGallery::class, |
148 | 'packed' => PackedImageGallery::class, |
149 | 'packed-hover' => PackedHoverImageGallery::class, |
150 | 'packed-overlay' => PackedOverlayImageGallery::class, |
151 | 'slideshow' => SlideshowImageGallery::class, |
152 | ]; |
153 | // Allow extensions to make a new gallery format. |
154 | ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) ) |
155 | ->onGalleryGetModes( self::$modeMapping ); |
156 | } |
157 | } |
158 | |
159 | /** |
160 | * Create a new image gallery object. |
161 | * |
162 | * You should not call this directly, but instead use |
163 | * ImageGalleryBase::factory(). |
164 | * |
165 | * @stable to call |
166 | * @note constructors of subclasses must have a compatible signature |
167 | * for use by the factory() method. |
168 | * |
169 | * @param string $mode |
170 | * @param IContextSource|null $context |
171 | */ |
172 | public function __construct( $mode = 'traditional', IContextSource $context = null ) { |
173 | if ( $context ) { |
174 | $this->setContext( $context ); |
175 | } |
176 | |
177 | $galleryOptions = $this->getConfig()->get( MainConfigNames::GalleryOptions ); |
178 | $this->mImages = []; |
179 | $this->mShowBytes = $galleryOptions['showBytes']; |
180 | $this->mShowDimensions = $galleryOptions['showDimensions']; |
181 | $this->mShowFilename = true; |
182 | $this->mParser = false; |
183 | $this->mHideBadImages = false; |
184 | $this->mPerRow = $galleryOptions['imagesPerRow']; |
185 | $this->mWidths = $galleryOptions['imageWidth']; |
186 | $this->mHeights = $galleryOptions['imageHeight']; |
187 | $this->mCaptionLength = $galleryOptions['captionLength']; |
188 | $this->mMode = $mode; |
189 | } |
190 | |
191 | /** |
192 | * Register a parser object. If you do not set this |
193 | * and the output of this gallery ends up in parser |
194 | * cache, the javascript will break! |
195 | * |
196 | * @note This also triggers using the page's target |
197 | * language instead of the user language. |
198 | * |
199 | * @param Parser $parser |
200 | */ |
201 | public function setParser( $parser ) { |
202 | $this->mParser = $parser; |
203 | } |
204 | |
205 | /** |
206 | * @param bool $flag |
207 | */ |
208 | public function setHideBadImages( $flag = true ) { |
209 | $this->mHideBadImages = $flag; |
210 | } |
211 | |
212 | /** |
213 | * Set the caption (as plain text) |
214 | * |
215 | * @param string $caption |
216 | */ |
217 | public function setCaption( $caption ) { |
218 | $this->mCaption = htmlspecialchars( $caption ); |
219 | } |
220 | |
221 | /** |
222 | * Set the caption (as HTML) |
223 | * |
224 | * @param string $caption |
225 | */ |
226 | public function setCaptionHtml( $caption ) { |
227 | $this->mCaption = $caption; |
228 | } |
229 | |
230 | /** |
231 | * Set how many images will be displayed per row. |
232 | * |
233 | * @param int $num Integer >= 0; If perrow=0 the gallery layout will adapt |
234 | * to screensize invalid numbers will be rejected |
235 | */ |
236 | public function setPerRow( $num ) { |
237 | if ( $num >= 0 ) { |
238 | $this->mPerRow = (int)$num; |
239 | } |
240 | } |
241 | |
242 | /** |
243 | * Set how wide each image will be, in pixels. |
244 | * |
245 | * @param string $num Number. Unit other than 'px is invalid. Invalid numbers |
246 | * and those below 0 are ignored. |
247 | */ |
248 | public function setWidths( $num ) { |
249 | $parsed = Parser::parseWidthParam( $num, false ); |
250 | if ( isset( $parsed['width'] ) && $parsed['width'] > 0 ) { |
251 | $this->mWidths = $parsed['width']; |
252 | } |
253 | } |
254 | |
255 | /** |
256 | * Set how high each image will be, in pixels. |
257 | * |
258 | * @param string $num Number. Unit other than 'px is invalid. Invalid numbers |
259 | * and those below 0 are ignored. |
260 | */ |
261 | public function setHeights( $num ) { |
262 | $parsed = Parser::parseWidthParam( $num, false ); |
263 | if ( isset( $parsed['width'] ) && $parsed['width'] > 0 ) { |
264 | $this->mHeights = $parsed['width']; |
265 | } |
266 | } |
267 | |
268 | /** |
269 | * Allow setting additional options. This is meant |
270 | * to allow extensions to add additional parameters to |
271 | * <gallery> parser tag. |
272 | * |
273 | * @stable to override |
274 | * |
275 | * @param array $options Attributes of gallery tag |
276 | */ |
277 | public function setAdditionalOptions( $options ) { |
278 | } |
279 | |
280 | /** |
281 | * Add an image to the gallery. |
282 | * |
283 | * @param Title $title Title object of the image that is added to the gallery |
284 | * @param string $html Additional HTML text to be shown. The name and size |
285 | * of the image are always shown. |
286 | * @param string|null $alt Alt text for the image, or null to omit |
287 | * @param string $link Override image link (optional) |
288 | * @param array $handlerOpts Array of options for image handler (aka page number) |
289 | * @param int $loading Sets loading attribute of the underlying <img> (optional) |
290 | * @param ?array $imageOptions To supercede the $link param |
291 | */ |
292 | public function add( |
293 | $title, |
294 | $html = '', |
295 | $alt = '', |
296 | $link = '', |
297 | $handlerOpts = [], |
298 | $loading = self::LOADING_DEFAULT, |
299 | ?array $imageOptions = null |
300 | ) { |
301 | if ( $title instanceof File ) { |
302 | // Old calling convention |
303 | $title = $title->getTitle(); |
304 | } |
305 | $this->mImages[] = [ $title, $html, $alt, $link, $handlerOpts, $loading, $imageOptions ]; |
306 | wfDebug( 'ImageGallery::add ' . $title->getText() ); |
307 | } |
308 | |
309 | /** |
310 | * Add an image at the beginning of the gallery. |
311 | * |
312 | * @param Title $title Title object of the image that is added to the gallery |
313 | * @param string $html Additional HTML text to be shown. The name and size |
314 | * of the image are always shown. |
315 | * @param string $alt Alt text for the image |
316 | * @param string $link Override image link (optional) |
317 | * @param array $handlerOpts Array of options for image handler (aka page number) |
318 | * @param int $loading Sets loading attribute of the underlying <img> (optional) |
319 | * @param ?array $imageOptions To supercede the $link param |
320 | */ |
321 | public function insert( |
322 | $title, |
323 | $html = '', |
324 | $alt = '', |
325 | $link = '', |
326 | $handlerOpts = [], |
327 | $loading = self::LOADING_DEFAULT, |
328 | ?array $imageOptions = null |
329 | ) { |
330 | if ( $title instanceof File ) { |
331 | // Old calling convention |
332 | $title = $title->getTitle(); |
333 | } |
334 | array_unshift( $this->mImages, [ &$title, $html, $alt, $link, $handlerOpts, $loading, $imageOptions ] ); |
335 | } |
336 | |
337 | /** |
338 | * Returns the list of images this gallery contains |
339 | * @return array[] |
340 | * @phan-return array<int,array{0:Title,1:string,2:string,3:string,4:array}> |
341 | */ |
342 | public function getImages() { |
343 | return $this->mImages; |
344 | } |
345 | |
346 | /** |
347 | * isEmpty() returns true if the gallery contains no images |
348 | * @return bool |
349 | */ |
350 | public function isEmpty() { |
351 | return $this->mImages === []; |
352 | } |
353 | |
354 | /** |
355 | * Enable/Disable showing of the dimensions of an image in the gallery. |
356 | * Enabled by default. |
357 | * |
358 | * @param bool $f Set to false to disable |
359 | */ |
360 | public function setShowDimensions( $f ) { |
361 | $this->mShowDimensions = (bool)$f; |
362 | } |
363 | |
364 | /** |
365 | * Enable/Disable showing of the file size of an image in the gallery. |
366 | * Enabled by default. |
367 | * |
368 | * @param bool $f Set to false to disable |
369 | */ |
370 | public function setShowBytes( $f ) { |
371 | $this->mShowBytes = (bool)$f; |
372 | } |
373 | |
374 | /** |
375 | * Enable/Disable showing of the filename of an image in the gallery. |
376 | * Enabled by default. |
377 | * |
378 | * @param bool $f Set to false to disable |
379 | */ |
380 | public function setShowFilename( $f ) { |
381 | $this->mShowFilename = (bool)$f; |
382 | } |
383 | |
384 | /** |
385 | * Set arbitrary attributes to go on the HTML gallery output element. |
386 | * Should be suitable for a <ul> element. |
387 | * |
388 | * Note -- if taking from user input, you should probably run through |
389 | * Sanitizer::validateAttributes() first. |
390 | * |
391 | * @param array $attribs Array of HTML attribute pairs |
392 | */ |
393 | public function setAttributes( $attribs ) { |
394 | $this->mAttribs = $attribs; |
395 | } |
396 | |
397 | /** |
398 | * Display an html representation of the gallery |
399 | * |
400 | * @return string The html |
401 | */ |
402 | abstract public function toHTML(); |
403 | |
404 | /** |
405 | * @return int Number of images in the gallery |
406 | */ |
407 | public function count() { |
408 | return count( $this->mImages ); |
409 | } |
410 | |
411 | /** |
412 | * Set the contextual title |
413 | * |
414 | * @param Title|null $title Contextual title |
415 | */ |
416 | public function setContextTitle( $title ) { |
417 | $this->contextTitle = $title; |
418 | } |
419 | |
420 | /** |
421 | * Get the contextual title, if applicable |
422 | * |
423 | * @return Title|null |
424 | */ |
425 | public function getContextTitle() { |
426 | return $this->contextTitle; |
427 | } |
428 | |
429 | /** |
430 | * Determines the correct language to be used for this image gallery |
431 | * @return Language |
432 | */ |
433 | protected function getRenderLang() { |
434 | return $this->mParser |
435 | ? $this->mParser->getTargetLanguage() |
436 | : $this->getLanguage(); |
437 | } |
438 | } |