Completed
Branch master (4b8315)
by
unknown
17:52
created

includes/gallery/TraditionalImageGallery.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
class TraditionalImageGallery extends ImageGalleryBase {
24
	/**
25
	 * Return a HTML representation of the image gallery
26
	 *
27
	 * For each image in the gallery, display
28
	 * - a thumbnail
29
	 * - the image name
30
	 * - the additional text provided when adding the image
31
	 * - the size of the image
32
	 *
33
	 * @return string
34
	 */
35
	function toHTML() {
36
		if ( $this->mPerRow > 0 ) {
37
			$maxwidth = $this->mPerRow * ( $this->mWidths + $this->getAllPadding() );
38
			$oldStyle = isset( $this->mAttribs['style'] ) ? $this->mAttribs['style'] : '';
39
			# _width is ignored by any sane browser. IE6 doesn't know max-width
40
			# so it uses _width instead
41
			$this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" .
42
				$oldStyle;
43
		}
44
45
		$attribs = Sanitizer::mergeAttributes(
46
			[ 'class' => 'gallery mw-gallery-' . $this->mMode ], $this->mAttribs );
47
48
		$modules = $this->getModules();
49
50
		if ( $this->mParser ) {
51
			$this->mParser->getOutput()->addModules( $modules );
52
			$this->mParser->getOutput()->addModuleStyles( 'mediawiki.page.gallery.styles' );
53
		} else {
54
			$this->getOutput()->addModules( $modules );
55
			$this->getOutput()->addModuleStyles( 'mediawiki.page.gallery.styles' );
56
		}
57
		$output = Xml::openElement( 'ul', $attribs );
58
		if ( $this->mCaption ) {
59
			$output .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>";
60
		}
61
62
		if ( $this->mShowFilename ) {
63
			// Preload LinkCache info for when generating links
64
			// of the filename below
65
			$lb = new LinkBatch();
66
			foreach ( $this->mImages as $img ) {
67
				$lb->addObj( $img[0] );
68
			}
69
			$lb->execute();
70
		}
71
72
		$lang = $this->getRenderLang();
73
		# Output each image...
74
		foreach ( $this->mImages as $pair ) {
75
			/** @var Title $nt */
76
			$nt = $pair[0];
77
			$text = $pair[1]; # "text" means "caption" here
78
			$alt = $pair[2];
79
			$link = $pair[3];
80
81
			$descQuery = false;
82
			if ( $nt->getNamespace() === NS_FILE ) {
83
				# Get the file...
84
				if ( $this->mParser instanceof Parser ) {
85
					# Give extensions a chance to select the file revision for us
86
					$options = [];
87
					Hooks::run( 'BeforeParserFetchFileAndTitle',
88
						[ $this->mParser, $nt, &$options, &$descQuery ] );
89
					# Fetch and register the file (file title may be different via hooks)
90
					list( $img, $nt ) = $this->mParser->fetchFileAndTitle( $nt, $options );
91
				} else {
92
					$img = wfFindFile( $nt );
93
				}
94
			} else {
95
				$img = false;
96
			}
97
98
			$params = $this->getThumbParams( $img );
99
			// $pair[4] is per image handler options
100
			$transformOptions = $params + $pair[4];
101
102
			$thumb = false;
103
104
			if ( !$img ) {
105
				# We're dealing with a non-image, spit out the name and be done with it.
106
				$thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: '
107
					. ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
108
					. htmlspecialchars( $nt->getText() ) . '</div>';
109
110
				if ( $this->mParser instanceof Parser ) {
111
					$this->mParser->addTrackingCategory( 'broken-file-category' );
112
				}
113
			} elseif ( $this->mHideBadImages
114
				&& wfIsBadImage( $nt->getDBkey(), $this->getContextTitle() )
115
			) {
116
				# The image is blacklisted, just show it as a text link.
117
				$thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' .
118
					( $this->getThumbPadding() + $this->mHeights ) . 'px;">' .
119
					Linker::linkKnown(
120
						$nt,
121
						htmlspecialchars( $nt->getText() )
122
					) .
123
					'</div>';
124
			} else {
125
				$thumb = $img->transform( $transformOptions );
126
				if ( !$thumb ) {
127
					# Error generating thumbnail.
128
					$thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: '
129
						. ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
130
						. htmlspecialchars( $img->getLastError() ) . '</div>';
131
				} else {
132
					/** @var MediaTransformOutput $thumb */
133
					$vpad = $this->getVPad( $this->mHeights, $thumb->getHeight() );
134
135
					$imageParameters = [
136
						'desc-link' => true,
137
						'desc-query' => $descQuery,
138
						'alt' => $alt,
139
						'custom-url-link' => $link
140
					];
141
142
					// In the absence of both alt text and caption, fall back on
143
					// providing screen readers with the filename as alt text
144
					if ( $alt == '' && $text == '' ) {
145
						$imageParameters['alt'] = $nt->getText();
146
					}
147
148
					$this->adjustImageParameters( $thumb, $imageParameters );
149
150
					Linker::processResponsiveImages( $img, $thumb, $transformOptions );
151
152
					# Set both fixed width and min-height.
153
					$thumbhtml = "\n\t\t\t"
154
						. '<div class="thumb" style="width: '
155
						. $this->getThumbDivWidth( $thumb->getWidth() ) . 'px;">'
156
						# Auto-margin centering for block-level elements. Needed
157
						# now that we have video handlers since they may emit block-
158
						# level elements as opposed to simple <img> tags. ref
159
						# http://css-discuss.incutio.com/?page=CenteringBlockElement
160
						. '<div style="margin:' . $vpad . 'px auto;">'
161
						. $thumb->toHtml( $imageParameters ) . '</div></div>';
162
163
					// Call parser transform hook
164
					/** @var MediaHandler $handler */
165
					$handler = $img->getHandler();
166
					if ( $this->mParser && $handler ) {
167
						$handler->parserTransformHook( $this->mParser, $img );
168
					}
169
				}
170
			}
171
172
			// @todo Code is incomplete.
173
			// $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) .
174
			// ":{$ut}" );
175
			// $ul = Linker::link( $linkTarget, $ut );
176
177
			if ( $this->mShowBytes ) {
178
				if ( $img ) {
179
					$fileSize = htmlspecialchars( $lang->formatSize( $img->getSize() ) );
180
				} else {
181
					$fileSize = $this->msg( 'filemissing' )->escaped();
182
				}
183
				$fileSize = "$fileSize<br />\n";
184
			} else {
185
				$fileSize = '';
186
			}
187
188
			$textlink = $this->mShowFilename ?
189
				// Preloaded into LinkCache above
190
				Linker::linkKnown(
191
					$nt,
192
					htmlspecialchars(
193
						$this->mCaptionLength !== true ?
0 ignored issues
show
The property mCaptionLength does not seem to exist. Did you mean mCaption?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
194
							$lang->truncate( $nt->getText(), $this->mCaptionLength ) :
0 ignored issues
show
The property mCaptionLength does not seem to exist. Did you mean mCaption?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
195
							$nt->getText()
196
					),
197
					[
198
						'class' => 'galleryfilename' .
199
							( $this->mCaptionLength === true ? ' galleryfilename-truncate' : '' )
0 ignored issues
show
The property mCaptionLength does not seem to exist. Did you mean mCaption?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
200
					]
201
				) . "\n" :
202
				'';
203
204
			$galleryText = $textlink . $text . $fileSize;
205
			$galleryText = $this->wrapGalleryText( $galleryText, $thumb );
206
207
			# Weird double wrapping (the extra div inside the li) needed due to FF2 bug
208
			# Can be safely removed if FF2 falls completely out of existence
209
			$output .= "\n\t\t" . '<li class="gallerybox" style="width: '
210
				. $this->getGBWidth( $thumb ) . 'px">'
211
				. '<div style="width: ' . $this->getGBWidth( $thumb ) . 'px">'
212
				. $thumbhtml
213
				. $galleryText
214
				. "\n\t\t</div></li>";
215
		}
216
		$output .= "\n</ul>";
217
218
		return $output;
219
	}
220
221
	/**
222
	 * Add the wrapper html around the thumb's caption
223
	 *
224
	 * @param string $galleryText The caption
225
	 * @param MediaTransformOutput|bool $thumb The thumb this caption is for
226
	 *   or false for bad image.
227
	 * @return string
228
	 */
229
	protected function wrapGalleryText( $galleryText, $thumb ) {
230
		# ATTENTION: The newline after <div class="gallerytext"> is needed to
231
		# accommodate htmltidy which in version 4.8.6 generated crackpot html in
232
		# its absence, see: https://phabricator.wikimedia.org/T3765
233
		# -Ævar
234
235
		return "\n\t\t\t" . '<div class="gallerytext">' . "\n"
236
			. $galleryText
237
			. "\n\t\t\t</div>";
238
	}
239
240
	/**
241
	 * How much padding the thumb has between the image and the inner div
242
	 * that contains the border. This is for both vertical and horizontal
243
	 * padding. (However, it is cut in half in the vertical direction).
244
	 * @return int
245
	 */
246
	protected function getThumbPadding() {
247
		return 30;
248
	}
249
250
	/**
251
	 * @note GB stands for gallerybox (as in the <li class="gallerybox"> element)
252
	 *
253
	 * @return int
254
	 */
255
	protected function getGBPadding() {
256
		return 5;
257
	}
258
259
	/**
260
	 * Get how much extra space the borders around the image takes up.
261
	 *
262
	 * For this mode, it is 2px borders on each side + 2px implied padding on
263
	 * each side from the stylesheet, giving us 2*2+2*2 = 8.
264
	 * @return int
265
	 */
266
	protected function getGBBorders() {
267
		return 8;
268
	}
269
270
	/**
271
	 * Get total padding.
272
	 *
273
	 * @return int Number of pixels of whitespace surrounding the thumbnail.
274
	 */
275
	protected function getAllPadding() {
276
		return $this->getThumbPadding() + $this->getGBPadding() + $this->getGBBorders();
277
	}
278
279
	/**
280
	 * Get vertical padding for a thumbnail
281
	 *
282
	 * Generally this is the total height minus how high the thumb is.
283
	 *
284
	 * @param int $boxHeight How high we want the box to be.
285
	 * @param int $thumbHeight How high the thumbnail is.
286
	 * @return int Vertical padding to add on each side.
287
	 */
288
	protected function getVPad( $boxHeight, $thumbHeight ) {
289
		return ( $this->getThumbPadding() + $boxHeight - $thumbHeight ) / 2;
290
	}
291
292
	/**
293
	 * Get the transform parameters for a thumbnail.
294
	 *
295
	 * @param File $img The file in question. May be false for invalid image
296
	 * @return array
297
	 */
298
	protected function getThumbParams( $img ) {
299
		return [
300
			'width' => $this->mWidths,
301
			'height' => $this->mHeights
302
		];
303
	}
304
305
	/**
306
	 * Get the width of the inner div that contains the thumbnail in
307
	 * question. This is the div with the class of "thumb".
308
	 *
309
	 * @param int $thumbWidth The width of the thumbnail.
310
	 * @return int Width of inner thumb div.
311
	 */
312
	protected function getThumbDivWidth( $thumbWidth ) {
313
		return $this->mWidths + $this->getThumbPadding();
314
	}
315
316
	/**
317
	 * Width of gallerybox <li>.
318
	 *
319
	 * Generally is the width of the image, plus padding on image
320
	 * plus padding on gallerybox.
321
	 *
322
	 * @note Important: parameter will be false if no thumb used.
323
	 * @param MediaTransformOutput|bool $thumb MediaTransformObject object or false.
324
	 * @return int Width of gallerybox element
325
	 */
326
	protected function getGBWidth( $thumb ) {
327
		return $this->mWidths + $this->getThumbPadding() + $this->getGBPadding();
328
	}
329
330
	/**
331
	 * Get a list of modules to include in the page.
332
	 *
333
	 * Primarily intended for subclasses.
334
	 *
335
	 * @return array Modules to include
336
	 */
337
	protected function getModules() {
338
		return [];
339
	}
340
341
	/**
342
	 * Adjust the image parameters for a thumbnail.
343
	 *
344
	 * Used by a subclass to insert extra high resolution images.
345
	 * @param MediaTransformOutput $thumb The thumbnail
346
	 * @param array $imageParameters Array of options
347
	 */
348
	protected function adjustImageParameters( $thumb, &$imageParameters ) {
349
	}
350
}
351
352
/**
353
 * Backwards compatibility. This always uses traditional mode
354
 * if called the old way, for extensions that may expect traditional
355
 * mode.
356
 *
357
 * @deprecated since 1.22 Use ImageGalleryBase::factory instead.
358
 */
359
class ImageGallery extends TraditionalImageGallery {
360
	function __construct( $mode = 'traditional' ) {
361
		wfDeprecated( __METHOD__, '1.22' );
362
		parent::__construct( $mode );
363
	}
364
}
365