MediaWiki  master
TraditionalImageGallery.php
Go to the documentation of this file.
1 <?php
2 
11 use Wikimedia\Assert\Assert;
12 
46  public function toHTML() {
47  $resolveFilesViaParser = $this->mParser instanceof Parser;
48  if ( $resolveFilesViaParser ) {
49  $parserOutput = $this->mParser->getOutput();
50  $repoGroup = null;
51  $linkRenderer = $this->mParser->getLinkRenderer();
52  $badFileLookup = $this->mParser->getBadFileLookup();
53  } else {
54  $parserOutput = $this->getOutput();
55  $services = MediaWikiServices::getInstance();
56  $repoGroup = $services->getRepoGroup();
57  $linkRenderer = $services->getLinkRenderer();
58  $badFileLookup = $services->getBadFileLookup();
59  }
60 
61  if ( $this->mPerRow > 0 ) {
62  $maxwidth = $this->mPerRow * ( $this->mWidths + $this->getAllPadding() );
63  $oldStyle = $this->mAttribs['style'] ?? '';
64  $this->mAttribs['style'] = "max-width: {$maxwidth}px;" . $oldStyle;
65  }
66 
67  $attribs = Sanitizer::mergeAttributes(
68  [ 'class' => 'gallery mw-gallery-' . $this->mMode ], $this->mAttribs );
69 
70  $parserOutput->addModules( $this->getModules() );
71  $parserOutput->addModuleStyles( [ 'mediawiki.page.gallery.styles' ] );
72  $output = Xml::openElement( 'ul', $attribs );
73  if ( $this->mCaption ) {
74  $output .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>";
75  }
76 
77  if ( $this->mShowFilename ) {
78  // Preload LinkCache info for when generating links
79  // of the filename below
80  $linkBatchFactory = MediaWikiServices::getInstance()->getLinkBatchFactory();
81  $lb = $linkBatchFactory->newLinkBatch();
82  foreach ( $this->mImages as [ $title, /* see below */ ] ) {
83  $lb->addObj( $title );
84  }
85  $lb->execute();
86  }
87 
88  $lang = $this->getRenderLang();
89  $enableLegacyMediaDOM =
90  $this->getConfig()->get( MainConfigNames::ParserEnableLegacyMediaDOM );
91  $hookRunner = new HookRunner( MediaWikiServices::getInstance()->getHookContainer() );
92 
93  # Output each image...
94  foreach ( $this->mImages as [ $nt, $text, $alt, $link, $handlerOpts, $loading, $imageOptions ] ) {
95  // "text" means "caption" here
98  $descQuery = false;
99  if ( $nt->inNamespace( NS_FILE ) && !$nt->isExternal() ) {
100  # Get the file...
101  if ( $resolveFilesViaParser ) {
102  # Give extensions a chance to select the file revision for us
103  $options = [];
104  $hookRunner->onBeforeParserFetchFileAndTitle(
105  // @phan-suppress-next-line PhanTypeMismatchArgument Type mismatch on pass-by-ref args
106  $this->mParser, $nt, $options, $descQuery );
107  # Fetch and register the file (file title may be different via hooks)
108  [ $img, $nt ] = $this->mParser->fetchFileAndTitle( $nt, $options );
109  } else {
110  $img = $repoGroup->findFile( $nt );
111  }
112  } else {
113  $img = false;
114  }
115 
116  $transformOptions = $this->getThumbParams( $img ) + $handlerOpts;
117  $thumb = $img ? $img->transform( $transformOptions ) : false;
118 
119  $rdfaType = 'mw:File';
120 
121  $isBadFile = $img && $thumb && $this->mHideBadImages &&
122  $badFileLookup->isBadFile( $nt->getDBkey(), $this->getContextTitle() );
123 
124  if ( !$img || !$thumb || ( !$enableLegacyMediaDOM && $thumb->isError() ) || $isBadFile ) {
125  $rdfaType = 'mw:Error ' . $rdfaType;
126 
127  if ( $enableLegacyMediaDOM ) {
128  if ( $isBadFile ) {
129  $thumbhtml = $linkRenderer->makeKnownLink( $nt, $nt->getText() );
130  } else {
131  $thumbhtml = htmlspecialchars( $img ? $img->getLastError() : $nt->getText() );
132  }
133  } else {
134  $currentExists = $img && $img->exists();
135  if ( $currentExists && !$thumb ) {
136  $label = wfMessage( 'thumbnail_error', '' )->text();
137  } elseif ( $thumb && $thumb->isError() ) {
138  Assert::invariant(
139  $thumb instanceof MediaTransformError,
140  'Unknown MediaTransformOutput: ' . get_class( $thumb )
141  );
142  $label = $thumb->toText();
143  } else {
144  $label = $alt ?? '';
145  }
146  $thumbhtml = Linker::makeBrokenImageLinkObj(
147  $nt, $label, '', '', '', false, $transformOptions, $currentExists
148  );
149  $thumbhtml = Html::rawElement( 'span', [ 'typeof' => $rdfaType ], $thumbhtml );
150  }
151 
152  $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: '
153  . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
154  . $thumbhtml . '</div>';
155 
156  if ( !$img && $resolveFilesViaParser ) {
157  $this->mParser->addTrackingCategory( 'broken-file-category' );
158  }
159  } else {
161  $vpad = $this->getVPad( $this->mHeights, $thumb->getHeight() );
162 
163  // Backwards compat before the $imageOptions existed
164  if ( $imageOptions === null ) {
165  $imageParameters = [
166  'desc-link' => true,
167  'desc-query' => $descQuery,
168  'alt' => $alt ?? '',
169  'custom-url-link' => $link
170  ];
171  } else {
172  $params = [];
173  // An empty alt indicates an image is not a key part of the
174  // content and that non-visual browsers may omit it from
175  // rendering. Only set the parameter if it's explicitly
176  // requested.
177  if ( $alt !== null ) {
178  $params['alt'] = $alt;
179  }
180  $params['title'] = $imageOptions['title'];
181  if ( !$enableLegacyMediaDOM ) {
182  $params['img-class'] = 'mw-file-element';
183  }
184  $imageParameters = Linker::getImageLinkMTOParams(
185  $imageOptions, $descQuery, $this->mParser
186  ) + $params;
187  }
188 
189  if ( $loading === ImageGalleryBase::LOADING_LAZY ) {
190  $imageParameters['loading'] = 'lazy';
191  }
192 
193  $this->adjustImageParameters( $thumb, $imageParameters );
194 
195  Linker::processResponsiveImages( $img, $thumb, $transformOptions );
196 
197  $thumbhtml = $thumb->toHtml( $imageParameters );
198 
199  if ( !$enableLegacyMediaDOM ) {
200  $thumbhtml = Html::rawElement(
201  'span', [ 'typeof' => $rdfaType ], $thumbhtml
202  );
203  } else {
204  $thumbhtml = Html::rawElement( 'div', [
205  # Auto-margin centering for block-level elements. Needed
206  # now that we have video handlers since they may emit block-
207  # level elements as opposed to simple <img> tags. ref
208  # http://css-discuss.incutio.com/?page=CenteringBlockElement
209  'style' => "margin:{$vpad}px auto;",
210  ], $thumbhtml );
211  }
212 
213  # Set both fixed width and min-height.
214  $width = $this->getThumbDivWidth( $thumb->getWidth() );
215  $height = $this->getThumbPadding() + $this->mHeights;
216  $thumbhtml = "\n\t\t\t" . Html::rawElement( 'div', [
217  'class' => 'thumb',
218  'style' => "width: {$width}px;" .
219  ( !$enableLegacyMediaDOM && $this->mMode === 'traditional' ?
220  " height: {$height}px;" : '' ),
221  ], $thumbhtml );
222 
223  // Call parser transform hook
224  if ( $resolveFilesViaParser ) {
226  $handler = $img->getHandler();
227  if ( $handler ) {
228  $handler->parserTransformHook( $this->mParser, $img );
229  }
230  $this->mParser->modifyImageHtml(
231  $img, [ 'handler' => $imageParameters ], $thumbhtml );
232  }
233  }
234 
235  $meta = [];
236  if ( $img ) {
237  if ( $this->mShowDimensions ) {
238  $meta[] = htmlspecialchars( $img->getDimensionsString() );
239  }
240  if ( $this->mShowBytes ) {
241  $meta[] = htmlspecialchars( $lang->formatSize( $img->getSize() ) );
242  }
243  } elseif ( $this->mShowDimensions || $this->mShowBytes ) {
244  $meta[] = $this->msg( 'filemissing' )->escaped();
245  }
246  $meta = $lang->semicolonList( $meta );
247  if ( $meta ) {
248  $meta .= "<br />\n";
249  }
250 
251  $textlink = $this->mShowFilename ?
252  $this->getCaptionHtml( $nt, $lang, $linkRenderer ) :
253  '';
254 
255  $galleryText = $this->wrapGalleryText( $textlink . $text . $meta, $thumb );
256 
257  $gbWidth = $this->getGBWidthOverwrite( $thumb ) ?: $this->getGBWidth( $thumb ) . 'px';
258  # Weird double wrapping (the extra div inside the li) needed due to FF2 bug
259  # Can be safely removed if FF2 falls completely out of existence
260  $output .= "\n\t\t" . '<li class="gallerybox" style="width: '
261  . $gbWidth . '">'
262  . ( $enableLegacyMediaDOM ? '<div style="width: ' . $gbWidth . '">' : '' )
263  . $thumbhtml
264  . $galleryText
265  . "\n\t\t"
266  . ( $enableLegacyMediaDOM ? '</div>' : '' )
267  . "</li>";
268  }
269  $output .= "\n</ul>";
270 
271  return $output;
272  }
273 
280  protected function getCaptionHtml( Title $nt, Language $lang, LinkRenderer $linkRenderer ) {
281  // Preloaded into LinkCache in toHTML
282  return $linkRenderer->makeKnownLink(
283  $nt,
284  is_int( $this->getCaptionLength() ) ?
285  $lang->truncateForVisual( $nt->getText(), $this->getCaptionLength() ) :
286  $nt->getText(),
287  [
288  'class' => 'galleryfilename' .
289  ( $this->getCaptionLength() === true ? ' galleryfilename-truncate' : '' )
290  ]
291  ) . "\n";
292  }
293 
302  protected function wrapGalleryText( $galleryText, $thumb ) {
303  # ATTENTION: The newline after <div class="gallerytext"> is needed to
304  # accommodate htmltidy which in version 4.8.6 generated crackpot html in
305  # its absence, see: https://phabricator.wikimedia.org/T3765
306  # -Ævar
307 
308  return "\n\t\t\t" . '<div class="gallerytext">' . "\n"
309  . $galleryText
310  . "\n\t\t\t</div>";
311  }
312 
319  protected function getThumbPadding() {
320  return 30;
321  }
322 
328  protected function getGBPadding() {
329  return 5;
330  }
331 
339  protected function getGBBorders() {
340  return 8;
341  }
342 
350  protected function getCaptionLength() {
351  return $this->mCaptionLength;
352  }
353 
359  protected function getAllPadding() {
360  return $this->getThumbPadding() + $this->getGBPadding() + $this->getGBBorders();
361  }
362 
372  protected function getVPad( $boxHeight, $thumbHeight ) {
373  return ( $this->getThumbPadding() + $boxHeight - $thumbHeight ) / 2;
374  }
375 
382  protected function getThumbParams( $img ) {
383  return [
384  'width' => $this->mWidths,
385  'height' => $this->mHeights
386  ];
387  }
388 
396  protected function getThumbDivWidth( $thumbWidth ) {
397  return $this->mWidths + $this->getThumbPadding();
398  }
399 
410  protected function getGBWidth( $thumb ) {
411  return $this->mWidths + $this->getThumbPadding() + $this->getGBPadding();
412  }
413 
425  protected function getGBWidthOverwrite( $thumb ) {
426  return false;
427  }
428 
436  protected function getModules() {
437  return [];
438  }
439 
447  protected function adjustImageParameters( $thumb, &$imageParameters ) {
448  }
449 }
const NS_FILE
Definition: Defines.php:70
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Image gallery.
bool int $mCaptionLength
Length to truncate filename to in caption when using "showfilename".
getRenderLang()
Determines the correct language to be used for this image gallery.
Base class for language-specific code.
Definition: Language.php:61
truncateForVisual( $string, $length, $ellipsis='...', $adjustLength=true)
Truncate a string to a specified number of characters, appending an optional string (e....
Definition: Language.php:3354
Basic media transform error class.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:568
This class is a collection of static functions that serve two purposes:
Definition: Html.php:57
Class that generates HTML for internal links.
makeKnownLink( $target, $text=null, array $extraAttribs=[], array $query=[])
Make a link that's styled as if the target page exists (usually a "blue link", although the styling m...
Some internal bits split of from Skin.php.
Definition: Linker.php:65
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
HTML sanitizer for MediaWiki.
Definition: Sanitizer.php:46
Represents a title within MediaWiki.
Definition: Title.php:76
getText()
Get the text form (spaces not underscores) of the main part.
Definition: Title.php:1031
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition: Parser.php:115
getOutput()
Definition: Parser.php:1048
getThumbPadding()
How much padding the thumb has between the image and the inner div that contains the border.
getCaptionLength()
Length (in characters) to truncate filename to in caption when using "showfilename" (if int).
getVPad( $boxHeight, $thumbHeight)
Get vertical padding for a thumbnail.
getCaptionHtml(Title $nt, Language $lang, LinkRenderer $linkRenderer)
getThumbParams( $img)
Get the transform parameters for a thumbnail.
toHTML()
Return a HTML representation of the image gallery.
getGBWidth( $thumb)
Computed width of gallerybox .
getModules()
Get a list of modules to include in the page.
getGBBorders()
Get how much extra space the borders around the image takes up.
wrapGalleryText( $galleryText, $thumb)
Add the wrapper html around the thumb's caption.
adjustImageParameters( $thumb, &$imageParameters)
Adjust the image parameters for a thumbnail.
getGBWidthOverwrite( $thumb)
Allows overwriting the computed width of the gallerybox with a string, like '100'.
getThumbDivWidth( $thumbWidth)
Get the width of the inner div that contains the thumbnail in question.
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:115