MediaWiki  master
ImagePage.php
Go to the documentation of this file.
1 <?php
28 class ImagePage extends Article {
30  private $displayImg;
31 
33  private $repo;
34 
36  private $fileLoaded;
37 
39  protected $mExtraDescription = false;
40 
44  protected $mPage;
45 
50  protected function newPage( Title $title ) {
51  // Overload mPage with a file-specific page
52  return new WikiFilePage( $title );
53  }
54 
60  public static function newFromID( $id ) {
61  $t = Title::newFromID( $id );
62  # @todo FIXME: Doesn't inherit right
63  return $t == null ? null : new self( $t );
64  # return $t == null ? null : new static( $t ); // PHP 5.3
65  }
66 
71  public function setFile( $file ) {
72  $this->mPage->setFile( $file );
73  $this->displayImg = $file;
74  $this->fileLoaded = true;
75  }
76 
77  protected function loadFile() {
78  if ( $this->fileLoaded ) {
79  return;
80  }
81  $this->fileLoaded = true;
82 
83  $this->displayImg = $img = false;
84  Hooks::run( 'ImagePageFindFile', [ $this, &$img, &$this->displayImg ] );
85  if ( !$img ) { // not set by hook?
86  $img = wfFindFile( $this->getTitle() );
87  if ( !$img ) {
88  $img = wfLocalFile( $this->getTitle() );
89  }
90  }
91  $this->mPage->setFile( $img );
92  if ( !$this->displayImg ) { // not set by hook?
93  $this->displayImg = $img;
94  }
95  $this->repo = $img->getRepo();
96  }
97 
102  public function render() {
103  $this->getContext()->getOutput()->setArticleBodyOnly( true );
104  parent::view();
105  }
106 
107  public function view() {
109 
110  $out = $this->getContext()->getOutput();
111  $request = $this->getContext()->getRequest();
112  $diff = $request->getVal( 'diff' );
113  $diffOnly = $request->getBool(
114  'diffonly',
115  $this->getContext()->getUser()->getOption( 'diffonly' )
116  );
117 
118  if ( $this->getTitle()->getNamespace() != NS_FILE || ( $diff !== null && $diffOnly ) ) {
119  parent::view();
120  return;
121  }
122 
123  $this->loadFile();
124 
125  if ( $this->getTitle()->getNamespace() == NS_FILE && $this->mPage->getFile()->getRedirected() ) {
126  if ( $this->getTitle()->getDBkey() == $this->mPage->getFile()->getName() || $diff !== null ) {
127  // mTitle is the same as the redirect target so ask Article
128  // to perform the redirect for us.
129  $request->setVal( 'diffonly', 'true' );
130  parent::view();
131  return;
132  } else {
133  // mTitle is not the same as the redirect target so it is
134  // probably the redirect page itself. Fake the redirect symbol
135  $out->setPageTitle( $this->getTitle()->getPrefixedText() );
136  $out->addHTML( $this->viewRedirect(
137  Title::makeTitle( NS_FILE, $this->mPage->getFile()->getName() ),
138  /* $appendSubtitle */ true,
139  /* $forceKnown */ true )
140  );
141  $this->mPage->doViewUpdates( $this->getContext()->getUser(), $this->getOldID() );
142  return;
143  }
144  }
145 
146  if ( $wgShowEXIF && $this->displayImg->exists() ) {
147  // @todo FIXME: Bad interface, see note on MediaHandler::formatMetadata().
148  $formattedMetadata = $this->displayImg->formatMetadata( $this->getContext() );
149  $showmeta = $formattedMetadata !== false;
150  } else {
151  $showmeta = false;
152  }
153 
154  if ( !$diff && $this->displayImg->exists() ) {
155  $out->addHTML( $this->showTOC( $showmeta ) );
156  }
157 
158  if ( !$diff ) {
159  $this->openShowImage();
160  }
161 
162  # No need to display noarticletext, we use our own message, output in openShowImage()
163  if ( $this->mPage->getId() ) {
164  # NS_FILE is in the user language, but this section (the actual wikitext)
165  # should be in page content language
166  $pageLang = $this->getTitle()->getPageViewLanguage();
167  $out->addHTML( Xml::openElement( 'div', [ 'id' => 'mw-imagepage-content',
168  'lang' => $pageLang->getHtmlCode(), 'dir' => $pageLang->getDir(),
169  'class' => 'mw-content-' . $pageLang->getDir() ] ) );
170 
171  parent::view();
172 
173  $out->addHTML( Xml::closeElement( 'div' ) );
174  } else {
175  # Just need to set the right headers
176  $out->setArticleFlag( true );
177  $out->setPageTitle( $this->getTitle()->getPrefixedText() );
178  $this->mPage->doViewUpdates( $this->getContext()->getUser(), $this->getOldID() );
179  }
180 
181  # Show shared description, if needed
182  if ( $this->mExtraDescription ) {
183  $fol = $this->getContext()->msg( 'shareddescriptionfollows' );
184  if ( !$fol->isDisabled() ) {
185  $out->addWikiText( $fol->plain() );
186  }
187  $out->addHTML( '<div id="shared-image-desc">' . $this->mExtraDescription . "</div>\n" );
188  }
189 
190  $this->closeShowImage();
191  $this->imageHistory();
192  // TODO: Cleanup the following
193 
194  $out->addHTML( Xml::element( 'h2',
195  [ 'id' => 'filelinks' ],
196  $this->getContext()->msg( 'imagelinks' )->text() ) . "\n" );
197  $this->imageDupes();
198  # @todo FIXME: For some freaky reason, we can't redirect to foreign images.
199  # Yet we return metadata about the target. Definitely an issue in the FileRepo
200  $this->imageLinks();
201 
202  # Allow extensions to add something after the image links
203  $html = '';
204  Hooks::run( 'ImagePageAfterImageLinks', [ $this, &$html ] );
205  if ( $html ) {
206  $out->addHTML( $html );
207  }
208 
209  if ( $showmeta ) {
210  $out->addHTML( Xml::element(
211  'h2',
212  [ 'id' => 'metadata' ],
213  $this->getContext()->msg( 'metadata' )->text() ) . "\n" );
214  $out->addWikiText( $this->makeMetadataTable( $formattedMetadata ) );
215  $out->addModules( [ 'mediawiki.action.view.metadata' ] );
216  }
217 
218  // Add remote Filepage.css
219  if ( !$this->repo->isLocal() ) {
220  $css = $this->repo->getDescriptionStylesheetUrl();
221  if ( $css ) {
222  $out->addStyle( $css );
223  }
224  }
225 
226  $out->addModuleStyles( [
227  'filepage', // always show the local local Filepage.css, bug 29277
228  'mediawiki.action.view.filepage', // Add MediaWiki styles for a file page
229  ] );
230 
231  }
232 
236  public function getDisplayedFile() {
237  $this->loadFile();
238  return $this->displayImg;
239  }
240 
247  protected function showTOC( $metadata ) {
248  $r = [
249  '<li><a href="#file">' . $this->getContext()->msg( 'file-anchor-link' )->escaped() . '</a></li>',
250  '<li><a href="#filehistory">' . $this->getContext()->msg( 'filehist' )->escaped() . '</a></li>',
251  '<li><a href="#filelinks">' . $this->getContext()->msg( 'imagelinks' )->escaped() . '</a></li>',
252  ];
253 
254  Hooks::run( 'ImagePageShowTOC', [ $this, &$r ] );
255 
256  if ( $metadata ) {
257  $r[] = '<li><a href="#metadata">' .
258  $this->getContext()->msg( 'metadata' )->escaped() .
259  '</a></li>';
260  }
261 
262  return '<ul id="filetoc">' . implode( "\n", $r ) . '</ul>';
263  }
264 
273  protected function makeMetadataTable( $metadata ) {
274  $r = "<div class=\"mw-imagepage-section-metadata\">";
275  $r .= $this->getContext()->msg( 'metadata-help' )->plain();
276  $r .= "<table id=\"mw_metadata\" class=\"mw_metadata\">\n";
277  foreach ( $metadata as $type => $stuff ) {
278  foreach ( $stuff as $v ) {
279  # @todo FIXME: Why is this using escapeId for a class?!
280  $class = Sanitizer::escapeId( $v['id'] );
281  if ( $type == 'collapsed' ) {
282  // Handled by mediawiki.action.view.metadata module.
283  $class .= ' collapsable';
284  }
285  $r .= "<tr class=\"$class\">\n";
286  $r .= "<th>{$v['name']}</th>\n";
287  $r .= "<td>{$v['value']}</td>\n</tr>";
288  }
289  }
290  $r .= "</table>\n</div>\n";
291  return $r;
292  }
293 
301  public function getContentObject() {
302  $this->loadFile();
303  if ( $this->mPage->getFile() && !$this->mPage->getFile()->isLocal() && 0 == $this->getId() ) {
304  return null;
305  }
306  return parent::getContentObject();
307  }
308 
309  protected function openShowImage() {
311 
312  $this->loadFile();
313  $out = $this->getContext()->getOutput();
314  $user = $this->getContext()->getUser();
315  $lang = $this->getContext()->getLanguage();
316  $dirmark = $lang->getDirMarkEntity();
317  $request = $this->getContext()->getRequest();
318 
319  $max = $this->getImageLimitsFromOption( $user, 'imagesize' );
320  $maxWidth = $max[0];
321  $maxHeight = $max[1];
322 
323  if ( $this->displayImg->exists() ) {
324  # image
325  $page = $request->getIntOrNull( 'page' );
326  if ( is_null( $page ) ) {
327  $params = [];
328  $page = 1;
329  } else {
330  $params = [ 'page' => $page ];
331  }
332 
333  $renderLang = $request->getVal( 'lang' );
334  if ( !is_null( $renderLang ) ) {
335  $handler = $this->displayImg->getHandler();
336  if ( $handler && $handler->validateParam( 'lang', $renderLang ) ) {
337  $params['lang'] = $renderLang;
338  } else {
339  $renderLang = null;
340  }
341  }
342 
343  $width_orig = $this->displayImg->getWidth( $page );
344  $width = $width_orig;
345  $height_orig = $this->displayImg->getHeight( $page );
346  $height = $height_orig;
347 
348  $filename = wfEscapeWikiText( $this->displayImg->getName() );
349  $linktext = $filename;
350 
351  Hooks::run( 'ImageOpenShowImageInlineBefore', [ &$this, &$out ] );
352 
353  if ( $this->displayImg->allowInlineDisplay() ) {
354  # image
355  # "Download high res version" link below the image
356  # $msgsize = $this->getContext()->msg( 'file-info-size', $width_orig, $height_orig,
357  # Linker::formatSize( $this->displayImg->getSize() ), $mime )->escaped();
358  # We'll show a thumbnail of this image
359  if ( $width > $maxWidth || $height > $maxHeight || $this->displayImg->isVectorized() ) {
360  list( $width, $height ) = $this->getDisplayWidthHeight(
361  $maxWidth, $maxHeight, $width, $height
362  );
363  $linktext = $this->getContext()->msg( 'show-big-image' )->escaped();
364 
365  $thumbSizes = $this->getThumbSizes( $width_orig, $height_orig );
366  # Generate thumbnails or thumbnail links as needed...
367  $otherSizes = [];
368  foreach ( $thumbSizes as $size ) {
369  // We include a thumbnail size in the list, if it is
370  // less than or equal to the original size of the image
371  // asset ($width_orig/$height_orig). We also exclude
372  // the current thumbnail's size ($width/$height)
373  // since that is added to the message separately, so
374  // it can be denoted as the current size being shown.
375  // Vectorized images are limited by $wgSVGMaxSize big,
376  // so all thumbs less than or equal that are shown.
377  if ( ( ( $size[0] <= $width_orig && $size[1] <= $height_orig )
378  || ( $this->displayImg->isVectorized()
379  && max( $size[0], $size[1] ) <= $wgSVGMaxSize )
380  )
381  && $size[0] != $width && $size[1] != $height
382  ) {
383  $sizeLink = $this->makeSizeLink( $params, $size[0], $size[1] );
384  if ( $sizeLink ) {
385  $otherSizes[] = $sizeLink;
386  }
387  }
388  }
389  $otherSizes = array_unique( $otherSizes );
390 
391  $sizeLinkBigImagePreview = $this->makeSizeLink( $params, $width, $height );
392  $msgsmall = $this->getThumbPrevText( $params, $sizeLinkBigImagePreview );
393  if ( count( $otherSizes ) ) {
394  $msgsmall .= ' ' .
396  'span',
397  [ 'class' => 'mw-filepage-other-resolutions' ],
398  $this->getContext()->msg( 'show-big-image-other' )
399  ->rawParams( $lang->pipeList( $otherSizes ) )
400  ->params( count( $otherSizes ) )
401  ->parse()
402  );
403  }
404  } elseif ( $width == 0 && $height == 0 ) {
405  # Some sort of audio file that doesn't have dimensions
406  # Don't output a no hi res message for such a file
407  $msgsmall = '';
408  } else {
409  # Image is small enough to show full size on image page
410  $msgsmall = $this->getContext()->msg( 'file-nohires' )->parse();
411  }
412 
413  $params['width'] = $width;
414  $params['height'] = $height;
415  $thumbnail = $this->displayImg->transform( $params );
416  Linker::processResponsiveImages( $this->displayImg, $thumbnail, $params );
417 
418  $anchorclose = Html::rawElement(
419  'div',
420  [ 'class' => 'mw-filepage-resolutioninfo' ],
421  $msgsmall
422  );
423 
424  $isMulti = $this->displayImg->isMultipage() && $this->displayImg->pageCount() > 1;
425  if ( $isMulti ) {
426  $out->addModules( 'mediawiki.page.image.pagination' );
427  $out->addHTML( '<table class="multipageimage"><tr><td>' );
428  }
429 
430  if ( $thumbnail ) {
431  $options = [
432  'alt' => $this->displayImg->getTitle()->getPrefixedText(),
433  'file-link' => true,
434  ];
435  $out->addHTML( '<div class="fullImageLink" id="file">' .
436  $thumbnail->toHtml( $options ) .
437  $anchorclose . "</div>\n" );
438  }
439 
440  if ( $isMulti ) {
441  $count = $this->displayImg->pageCount();
442 
443  if ( $page > 1 ) {
444  $label = $out->parse( $this->getContext()->msg( 'imgmultipageprev' )->text(), false );
445  // on the client side, this link is generated in ajaxifyPageNavigation()
446  // in the mediawiki.page.image.pagination module
448  $this->getTitle(),
449  $label,
450  [],
451  [ 'page' => $page - 1 ]
452  );
453  $thumb1 = Linker::makeThumbLinkObj(
454  $this->getTitle(),
455  $this->displayImg,
456  $link,
457  $label,
458  'none',
459  [ 'page' => $page - 1 ]
460  );
461  } else {
462  $thumb1 = '';
463  }
464 
465  if ( $page < $count ) {
466  $label = $this->getContext()->msg( 'imgmultipagenext' )->text();
468  $this->getTitle(),
469  $label,
470  [],
471  [ 'page' => $page + 1 ]
472  );
473  $thumb2 = Linker::makeThumbLinkObj(
474  $this->getTitle(),
475  $this->displayImg,
476  $link,
477  $label,
478  'none',
479  [ 'page' => $page + 1 ]
480  );
481  } else {
482  $thumb2 = '';
483  }
484 
486 
487  $formParams = [
488  'name' => 'pageselector',
489  'action' => $wgScript,
490  ];
491  $options = [];
492  for ( $i = 1; $i <= $count; $i++ ) {
493  $options[] = Xml::option( $lang->formatNum( $i ), $i, $i == $page );
494  }
495  $select = Xml::tags( 'select',
496  [ 'id' => 'pageselector', 'name' => 'page' ],
497  implode( "\n", $options ) );
498 
499  $out->addHTML(
500  '</td><td><div class="multipageimagenavbox">' .
501  Xml::openElement( 'form', $formParams ) .
502  Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
503  $this->getContext()->msg( 'imgmultigoto' )->rawParams( $select )->parse() .
504  Xml::submitButton( $this->getContext()->msg( 'imgmultigo' )->text() ) .
505  Xml::closeElement( 'form' ) .
506  "<hr />$thumb1\n$thumb2<br style=\"clear: both\" /></div></td></tr></table>"
507  );
508  }
509  } elseif ( $this->displayImg->isSafeFile() ) {
510  # if direct link is allowed but it's not a renderable image, show an icon.
511  $icon = $this->displayImg->iconThumb();
512 
513  $out->addHTML( '<div class="fullImageLink" id="file">' .
514  $icon->toHtml( [ 'file-link' => true ] ) .
515  "</div>\n" );
516  }
517 
518  $longDesc = $this->getContext()->msg( 'parentheses', $this->displayImg->getLongDesc() )->text();
519 
520  $handler = $this->displayImg->getHandler();
521 
522  // If this is a filetype with potential issues, warn the user.
523  if ( $handler ) {
524  $warningConfig = $handler->getWarningConfig( $this->displayImg );
525 
526  if ( $warningConfig !== null ) {
527  // The warning will be displayed via CSS and JavaScript.
528  // We just need to tell the client side what message to use.
529  $output = $this->getContext()->getOutput();
530  $output->addJsConfigVars( 'wgFileWarning', $warningConfig );
531  $output->addModules( $warningConfig['module'] );
532  $output->addModules( 'mediawiki.filewarning' );
533  }
534  }
535 
536  $medialink = "[[Media:$filename|$linktext]]";
537 
538  if ( !$this->displayImg->isSafeFile() ) {
539  $warning = $this->getContext()->msg( 'mediawarning' )->plain();
540  // dirmark is needed here to separate the file name, which
541  // most likely ends in Latin characters, from the description,
542  // which may begin with the file type. In RTL environment
543  // this will get messy.
544  // The dirmark, however, must not be immediately adjacent
545  // to the filename, because it can get copied with it.
546  // See bug 25277.
547  // @codingStandardsIgnoreStart Ignore long line
548  $out->addWikiText( <<<EOT
549 <div class="fullMedia"><span class="dangerousLink">{$medialink}</span> $dirmark<span class="fileInfo">$longDesc</span></div>
550 <div class="mediaWarning">$warning</div>
551 EOT
552  );
553  // @codingStandardsIgnoreEnd
554  } else {
555  $out->addWikiText( <<<EOT
556 <div class="fullMedia">{$medialink} {$dirmark}<span class="fileInfo">$longDesc</span>
557 </div>
558 EOT
559  );
560  }
561 
562  $renderLangOptions = $this->displayImg->getAvailableLanguages();
563  if ( count( $renderLangOptions ) >= 1 ) {
564  $currentLanguage = $renderLang;
565  $defaultLang = $this->displayImg->getDefaultRenderLanguage();
566  if ( is_null( $currentLanguage ) ) {
567  $currentLanguage = $defaultLang;
568  }
569  $out->addHTML( $this->doRenderLangOpt( $renderLangOptions, $currentLanguage, $defaultLang ) );
570  }
571 
572  // Add cannot animate thumbnail warning
573  if ( !$this->displayImg->canAnimateThumbIfAppropriate() ) {
574  // Include the extension so wiki admins can
575  // customize it on a per file-type basis
576  // (aka say things like use format X instead).
577  // additionally have a specific message for
578  // file-no-thumb-animation-gif
579  $ext = $this->displayImg->getExtension();
580  $noAnimMesg = wfMessageFallback(
581  'file-no-thumb-animation-' . $ext,
582  'file-no-thumb-animation'
583  )->plain();
584 
585  $out->addWikiText( <<<EOT
586 <div class="mw-noanimatethumb">{$noAnimMesg}</div>
587 EOT
588  );
589  }
590 
591  if ( !$this->displayImg->isLocal() ) {
592  $this->printSharedImageText();
593  }
594  } else {
595  # Image does not exist
596  if ( !$this->getId() ) {
597  # No article exists either
598  # Show deletion log to be consistent with normal articles
600  $out,
601  [ 'delete', 'move' ],
602  $this->getTitle()->getPrefixedText(),
603  '',
604  [ 'lim' => 10,
605  'conds' => [ "log_action != 'revision'" ],
606  'showIfEmpty' => false,
607  'msgKey' => [ 'moveddeleted-notice' ]
608  ]
609  );
610  }
611 
612  if ( $wgEnableUploads && $user->isAllowed( 'upload' ) ) {
613  // Only show an upload link if the user can upload
614  $uploadTitle = SpecialPage::getTitleFor( 'Upload' );
615  $nofile = [
616  'filepage-nofile-link',
617  $uploadTitle->getFullURL( [ 'wpDestFile' => $this->mPage->getFile()->getName() ] )
618  ];
619  } else {
620  $nofile = 'filepage-nofile';
621  }
622  // Note, if there is an image description page, but
623  // no image, then this setRobotPolicy is overridden
624  // by Article::View().
625  $out->setRobotPolicy( 'noindex,nofollow' );
626  $out->wrapWikiMsg( "<div id='mw-imagepage-nofile' class='plainlinks'>\n$1\n</div>", $nofile );
627  if ( !$this->getId() && $wgSend404Code ) {
628  // If there is no image, no shared image, and no description page,
629  // output a 404, to be consistent with Article::showMissingArticle.
630  $request->response()->statusHeader( 404 );
631  }
632  }
633  $out->setFileVersion( $this->displayImg );
634  }
635 
643  private function getThumbPrevText( $params, $sizeLinkBigImagePreview ) {
644  if ( $sizeLinkBigImagePreview ) {
645  // Show a different message of preview is different format from original.
646  $previewTypeDiffers = false;
647  $origExt = $thumbExt = $this->displayImg->getExtension();
648  if ( $this->displayImg->getHandler() ) {
649  $origMime = $this->displayImg->getMimeType();
650  $typeParams = $params;
651  $this->displayImg->getHandler()->normaliseParams( $this->displayImg, $typeParams );
652  list( $thumbExt, $thumbMime ) = $this->displayImg->getHandler()->getThumbType(
653  $origExt, $origMime, $typeParams );
654  if ( $thumbMime !== $origMime ) {
655  $previewTypeDiffers = true;
656  }
657  }
658  if ( $previewTypeDiffers ) {
659  return $this->getContext()->msg( 'show-big-image-preview-differ' )->
660  rawParams( $sizeLinkBigImagePreview )->
661  params( strtoupper( $origExt ) )->
662  params( strtoupper( $thumbExt ) )->
663  parse();
664  } else {
665  return $this->getContext()->msg( 'show-big-image-preview' )->
666  rawParams( $sizeLinkBigImagePreview )->
667  parse();
668  }
669  } else {
670  return '';
671  }
672  }
673 
681  private function makeSizeLink( $params, $width, $height ) {
682  $params['width'] = $width;
683  $params['height'] = $height;
684  $thumbnail = $this->displayImg->transform( $params );
685  if ( $thumbnail && !$thumbnail->isError() ) {
686  return Html::rawElement( 'a', [
687  'href' => $thumbnail->getUrl(),
688  'class' => 'mw-thumbnail-link'
689  ], $this->getContext()->msg( 'show-big-image-size' )->numParams(
690  $thumbnail->getWidth(), $thumbnail->getHeight()
691  )->parse() );
692  } else {
693  return '';
694  }
695  }
696 
700  protected function printSharedImageText() {
701  $out = $this->getContext()->getOutput();
702  $this->loadFile();
703 
704  $descUrl = $this->mPage->getFile()->getDescriptionUrl();
705  $descText = $this->mPage->getFile()->getDescriptionText( $this->getContext()->getLanguage() );
706 
707  /* Add canonical to head if there is no local page for this shared file */
708  if ( $descUrl && $this->mPage->getId() == 0 ) {
709  $out->setCanonicalUrl( $descUrl );
710  }
711 
712  $wrap = "<div class=\"sharedUploadNotice\">\n$1\n</div>\n";
713  $repo = $this->mPage->getFile()->getRepo()->getDisplayName();
714 
715  if ( $descUrl &&
716  $descText &&
717  $this->getContext()->msg( 'sharedupload-desc-here' )->plain() !== '-'
718  ) {
719  $out->wrapWikiMsg( $wrap, [ 'sharedupload-desc-here', $repo, $descUrl ] );
720  } elseif ( $descUrl &&
721  $this->getContext()->msg( 'sharedupload-desc-there' )->plain() !== '-'
722  ) {
723  $out->wrapWikiMsg( $wrap, [ 'sharedupload-desc-there', $repo, $descUrl ] );
724  } else {
725  $out->wrapWikiMsg( $wrap, [ 'sharedupload', $repo ], ''/*BACKCOMPAT*/ );
726  }
727 
728  if ( $descText ) {
729  $this->mExtraDescription = $descText;
730  }
731  }
732 
733  public function getUploadUrl() {
734  $this->loadFile();
735  $uploadTitle = SpecialPage::getTitleFor( 'Upload' );
736  return $uploadTitle->getFullURL( [
737  'wpDestFile' => $this->mPage->getFile()->getName(),
738  'wpForReUpload' => 1
739  ] );
740  }
741 
746  protected function uploadLinksBox() {
748 
749  if ( !$wgEnableUploads ) {
750  return;
751  }
752 
753  $this->loadFile();
754  if ( !$this->mPage->getFile()->isLocal() ) {
755  return;
756  }
757 
758  $out = $this->getContext()->getOutput();
759  $out->addHTML( "<ul>\n" );
760 
761  # "Upload a new version of this file" link
762  $canUpload = $this->getTitle()->quickUserCan( 'upload', $this->getContext()->getUser() );
763  if ( $canUpload && UploadBase::userCanReUpload(
764  $this->getContext()->getUser(),
765  $this->mPage->getFile() )
766  ) {
767  $ulink = Linker::makeExternalLink(
768  $this->getUploadUrl(),
769  $this->getContext()->msg( 'uploadnewversion-linktext' )->text()
770  );
771  $out->addHTML( "<li id=\"mw-imagepage-reupload-link\">"
772  . "<div class=\"plainlinks\">{$ulink}</div></li>\n" );
773  } else {
774  $out->addHTML( "<li id=\"mw-imagepage-upload-disallowed\">"
775  . $this->getContext()->msg( 'upload-disallowed-here' )->escaped() . "</li>\n" );
776  }
777 
778  $out->addHTML( "</ul>\n" );
779  }
780 
784  protected function closeShowImage() {
785  }
786 
791  protected function imageHistory() {
792  $this->loadFile();
793  $out = $this->getContext()->getOutput();
794  $pager = new ImageHistoryPseudoPager( $this );
795  $out->addHTML( $pager->getBody() );
796  $out->preventClickjacking( $pager->getPreventClickjacking() );
797 
798  $this->mPage->getFile()->resetHistory(); // free db resources
799 
800  # Exist check because we don't want to show this on pages where an image
801  # doesn't exist along with the noimage message, that would suck. -ævar
802  if ( $this->mPage->getFile()->exists() ) {
803  $this->uploadLinksBox();
804  }
805  }
806 
812  protected function queryImageLinks( $target, $limit ) {
813  $dbr = wfGetDB( DB_SLAVE );
814 
815  return $dbr->select(
816  [ 'imagelinks', 'page' ],
817  [ 'page_namespace', 'page_title', 'il_to' ],
818  [ 'il_to' => $target, 'il_from = page_id' ],
819  __METHOD__,
820  [ 'LIMIT' => $limit + 1, 'ORDER BY' => 'il_from', ]
821  );
822  }
823 
824  protected function imageLinks() {
825  $limit = 100;
826 
827  $out = $this->getContext()->getOutput();
828 
829  $rows = [];
830  $redirects = [];
831  foreach ( $this->getTitle()->getRedirectsHere( NS_FILE ) as $redir ) {
832  $redirects[$redir->getDBkey()] = [];
833  $rows[] = (object)[
834  'page_namespace' => NS_FILE,
835  'page_title' => $redir->getDBkey(),
836  ];
837  }
838 
839  $res = $this->queryImageLinks( $this->getTitle()->getDBkey(), $limit + 1 );
840  foreach ( $res as $row ) {
841  $rows[] = $row;
842  }
843  $count = count( $rows );
844 
845  $hasMore = $count > $limit;
846  if ( !$hasMore && count( $redirects ) ) {
847  $res = $this->queryImageLinks( array_keys( $redirects ),
848  $limit - count( $rows ) + 1 );
849  foreach ( $res as $row ) {
850  $redirects[$row->il_to][] = $row;
851  $count++;
852  }
853  $hasMore = ( $res->numRows() + count( $rows ) ) > $limit;
854  }
855 
856  if ( $count == 0 ) {
857  $out->wrapWikiMsg(
858  Html::rawElement( 'div',
859  [ 'id' => 'mw-imagepage-nolinkstoimage' ], "\n$1\n" ),
860  'nolinkstoimage'
861  );
862  return;
863  }
864 
865  $out->addHTML( "<div id='mw-imagepage-section-linkstoimage'>\n" );
866  if ( !$hasMore ) {
867  $out->addWikiMsg( 'linkstoimage', $count );
868  } else {
869  // More links than the limit. Add a link to [[Special:Whatlinkshere]]
870  $out->addWikiMsg( 'linkstoimage-more',
871  $this->getContext()->getLanguage()->formatNum( $limit ),
872  $this->getTitle()->getPrefixedDBkey()
873  );
874  }
875 
876  $out->addHTML(
877  Html::openElement( 'ul',
878  [ 'class' => 'mw-imagepage-linkstoimage' ] ) . "\n"
879  );
880  $count = 0;
881 
882  // Sort the list by namespace:title
883  usort( $rows, [ $this, 'compare' ] );
884 
885  // Create links for every element
886  $currentCount = 0;
887  foreach ( $rows as $element ) {
888  $currentCount++;
889  if ( $currentCount > $limit ) {
890  break;
891  }
892 
893  $query = [];
894  # Add a redirect=no to make redirect pages reachable
895  if ( isset( $redirects[$element->page_title] ) ) {
896  $query['redirect'] = 'no';
897  }
899  Title::makeTitle( $element->page_namespace, $element->page_title ),
900  null, [], $query
901  );
902  if ( !isset( $redirects[$element->page_title] ) ) {
903  # No redirects
904  $liContents = $link;
905  } elseif ( count( $redirects[$element->page_title] ) === 0 ) {
906  # Redirect without usages
907  $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )
908  ->rawParams( $link, '' )
909  ->parse();
910  } else {
911  # Redirect with usages
912  $li = '';
913  foreach ( $redirects[$element->page_title] as $row ) {
914  $currentCount++;
915  if ( $currentCount > $limit ) {
916  break;
917  }
918 
919  $link2 = Linker::linkKnown( Title::makeTitle( $row->page_namespace, $row->page_title ) );
920  $li .= Html::rawElement(
921  'li',
922  [ 'class' => 'mw-imagepage-linkstoimage-ns' . $element->page_namespace ],
923  $link2
924  ) . "\n";
925  }
926 
928  'ul',
929  [ 'class' => 'mw-imagepage-redirectstofile' ],
930  $li
931  ) . "\n";
932  $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )->rawParams(
933  $link, $ul )->parse();
934  }
935  $out->addHTML( Html::rawElement(
936  'li',
937  [ 'class' => 'mw-imagepage-linkstoimage-ns' . $element->page_namespace ],
938  $liContents
939  ) . "\n"
940  );
941 
942  };
943  $out->addHTML( Html::closeElement( 'ul' ) . "\n" );
944  $res->free();
945 
946  // Add a links to [[Special:Whatlinkshere]]
947  if ( $count > $limit ) {
948  $out->addWikiMsg( 'morelinkstoimage', $this->getTitle()->getPrefixedDBkey() );
949  }
950  $out->addHTML( Html::closeElement( 'div' ) . "\n" );
951  }
952 
953  protected function imageDupes() {
954  $this->loadFile();
955  $out = $this->getContext()->getOutput();
956 
957  $dupes = $this->mPage->getDuplicates();
958  if ( count( $dupes ) == 0 ) {
959  return;
960  }
961 
962  $out->addHTML( "<div id='mw-imagepage-section-duplicates'>\n" );
963  $out->addWikiMsg( 'duplicatesoffile',
964  $this->getContext()->getLanguage()->formatNum( count( $dupes ) ), $this->getTitle()->getDBkey()
965  );
966  $out->addHTML( "<ul class='mw-imagepage-duplicates'>\n" );
967 
971  foreach ( $dupes as $file ) {
972  $fromSrc = '';
973  if ( $file->isLocal() ) {
974  $link = Linker::linkKnown( $file->getTitle() );
975  } else {
976  $link = Linker::makeExternalLink( $file->getDescriptionUrl(),
977  $file->getTitle()->getPrefixedText() );
978  $fromSrc = $this->getContext()->msg(
979  'shared-repo-from',
980  $file->getRepo()->getDisplayName()
981  )->text();
982  }
983  $out->addHTML( "<li>{$link} {$fromSrc}</li>\n" );
984  }
985  $out->addHTML( "</ul></div>\n" );
986  }
987 
991  public function delete() {
992  $file = $this->mPage->getFile();
993  if ( !$file->exists() || !$file->isLocal() || $file->getRedirected() ) {
994  // Standard article deletion
995  parent::delete();
996  return;
997  }
998 
999  $deleter = new FileDeleteForm( $file );
1000  $deleter->execute();
1001  }
1002 
1008  function showError( $description ) {
1009  $out = $this->getContext()->getOutput();
1010  $out->setPageTitle( $this->getContext()->msg( 'internalerror' ) );
1011  $out->setRobotPolicy( 'noindex,nofollow' );
1012  $out->setArticleRelated( false );
1013  $out->enableClientCache( false );
1014  $out->addWikiText( $description );
1015  }
1016 
1025  protected function compare( $a, $b ) {
1026  if ( $a->page_namespace == $b->page_namespace ) {
1027  return strcmp( $a->page_title, $b->page_title );
1028  } else {
1029  return $a->page_namespace - $b->page_namespace;
1030  }
1031  }
1032 
1041  public function getImageLimitsFromOption( $user, $optionName ) {
1043 
1044  $option = $user->getIntOption( $optionName );
1045  if ( !isset( $wgImageLimits[$option] ) ) {
1046  $option = User::getDefaultOption( $optionName );
1047  }
1048 
1049  // The user offset might still be incorrect, specially if
1050  // $wgImageLimits got changed (see bug #8858).
1051  if ( !isset( $wgImageLimits[$option] ) ) {
1052  // Default to the first offset in $wgImageLimits
1053  $option = 0;
1054  }
1055 
1056  return isset( $wgImageLimits[$option] )
1057  ? $wgImageLimits[$option]
1058  : [ 800, 600 ]; // if nothing is set, fallback to a hardcoded default
1059  }
1060 
1069  protected function doRenderLangOpt( array $langChoices, $curLang, $defaultLang ) {
1070  global $wgScript;
1071  sort( $langChoices );
1072  $curLang = wfBCP47( $curLang );
1073  $defaultLang = wfBCP47( $defaultLang );
1074  $opts = '';
1075  $haveCurrentLang = false;
1076  $haveDefaultLang = false;
1077 
1078  // We make a list of all the language choices in the file.
1079  // Additionally if the default language to render this file
1080  // is not included as being in this file (for example, in svgs
1081  // usually the fallback content is the english content) also
1082  // include a choice for that. Last of all, if we're viewing
1083  // the file in a language not on the list, add it as a choice.
1084  foreach ( $langChoices as $lang ) {
1085  $code = wfBCP47( $lang );
1086  $name = Language::fetchLanguageName( $code, $this->getContext()->getLanguage()->getCode() );
1087  if ( $name !== '' ) {
1088  $display = $this->getContext()->msg( 'img-lang-opt', $code, $name )->text();
1089  } else {
1090  $display = $code;
1091  }
1092  $opts .= "\n" . Xml::option( $display, $code, $curLang === $code );
1093  if ( $curLang === $code ) {
1094  $haveCurrentLang = true;
1095  }
1096  if ( $defaultLang === $code ) {
1097  $haveDefaultLang = true;
1098  }
1099  }
1100  if ( !$haveDefaultLang ) {
1101  // Its hard to know if the content is really in the default language, or
1102  // if its just unmarked content that could be in any language.
1103  $opts = Xml::option(
1104  $this->getContext()->msg( 'img-lang-default' )->text(),
1105  $defaultLang,
1106  $defaultLang === $curLang
1107  ) . $opts;
1108  }
1109  if ( !$haveCurrentLang && $defaultLang !== $curLang ) {
1110  $name = Language::fetchLanguageName( $curLang, $this->getContext()->getLanguage()->getCode() );
1111  if ( $name !== '' ) {
1112  $display = $this->getContext()->msg( 'img-lang-opt', $curLang, $name )->text();
1113  } else {
1114  $display = $curLang;
1115  }
1116  $opts = Xml::option( $display, $curLang, true ) . $opts;
1117  }
1118 
1119  $select = Html::rawElement(
1120  'select',
1121  [ 'id' => 'mw-imglangselector', 'name' => 'lang' ],
1122  $opts
1123  );
1124  $submit = Xml::submitButton( $this->getContext()->msg( 'img-lang-go' )->text() );
1125 
1126  $formContents = $this->getContext()->msg( 'img-lang-info' )
1127  ->rawParams( $select, $submit )
1128  ->parse();
1129  $formContents .= Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() );
1130 
1131  $langSelectLine = Html::rawElement( 'div', [ 'id' => 'mw-imglangselector-line' ],
1132  Html::rawElement( 'form', [ 'action' => $wgScript ], $formContents )
1133  );
1134  return $langSelectLine;
1135  }
1136 
1151  protected function getDisplayWidthHeight( $maxWidth, $maxHeight, $width, $height ) {
1152  if ( !$maxWidth || !$maxHeight ) {
1153  // should never happen
1154  throw new MWException( 'Using a choice from $wgImageLimits that is 0x0' );
1155  }
1156 
1157  if ( !$width || !$height ) {
1158  return [ 0, 0 ];
1159  }
1160 
1161  # Calculate the thumbnail size.
1162  if ( $width <= $maxWidth && $height <= $maxHeight ) {
1163  // Vectorized image, do nothing.
1164  } elseif ( $width / $height >= $maxWidth / $maxHeight ) {
1165  # The limiting factor is the width, not the height.
1166  $height = round( $height * $maxWidth / $width );
1167  $width = $maxWidth;
1168  # Note that $height <= $maxHeight now.
1169  } else {
1170  $newwidth = floor( $width * $maxHeight / $height );
1171  $height = round( $height * $newwidth / $width );
1172  $width = $newwidth;
1173  # Note that $height <= $maxHeight now, but might not be identical
1174  # because of rounding.
1175  }
1176  return [ $width, $height ];
1177  }
1178 
1187  protected function getThumbSizes( $origWidth, $origHeight ) {
1189  if ( $this->displayImg->getRepo()->canTransformVia404() ) {
1190  $thumbSizes = $wgImageLimits;
1191  // Also include the full sized resolution in the list, so
1192  // that users know they can get it. This will link to the
1193  // original file asset if mustRender() === false. In the case
1194  // that we mustRender, some users have indicated that they would
1195  // find it useful to have the full size image in the rendered
1196  // image format.
1197  $thumbSizes[] = [ $origWidth, $origHeight ];
1198  } else {
1199  # Creating thumb links triggers thumbnail generation.
1200  # Just generate the thumb for the current users prefs.
1201  $thumbSizes = [
1202  $this->getImageLimitsFromOption( $this->getContext()->getUser(), 'thumbsize' )
1203  ];
1204  if ( !$this->displayImg->mustRender() ) {
1205  // We can safely include a link to the "full-size" preview,
1206  // without actually rendering.
1207  $thumbSizes[] = [ $origWidth, $origHeight ];
1208  }
1209  }
1210  return $thumbSizes;
1211  }
1212 
1217  public function getFile() {
1218  return $this->mPage->getFile();
1219  }
1220 
1225  public function isLocal() {
1226  return $this->mPage->isLocal();
1227  }
1228 
1233  public function getDuplicates() {
1234  return $this->mPage->getDuplicates();
1235  }
1236 
1241  public function getForeignCategories() {
1242  $this->mPage->getForeignCategories();
1243  }
1244 
1245 }
viewRedirect($target, $appendSubtitle=true, $forceKnown=false)
Return the HTML for the top of a redirect page.
Definition: Article.php:1537
static newFromID($id, $flags=0)
Create a new Title from an article ID.
Definition: Title.php:396
static closeElement($element)
Returns "</$element>".
Definition: Html.php:306
$article view()
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition: hooks.txt:1816
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
wfGetDB($db, $groups=[], $wiki=false)
Get a Database object.
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
Definition: hooks.txt:776
static processResponsiveImages($file, $thumb, $hp)
Process responsive images: add 1.5x and 2x subimages to the thumbnail, where applicable.
Definition: Linker.php:748
bool $fileLoaded
Definition: ImagePage.php:36
the array() calling protocol came about after MediaWiki 1.4rc1.
null for the local wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1435
$wgScript
The URL path to index.php.
static element($element, $attribs=null, $contents= '', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:39
queryImageLinks($target, $limit)
Definition: ImagePage.php:812
static getTitleFor($name, $subpage=false, $fragment= '')
Get a localised Title object for a specified special page name.
Definition: SpecialPage.php:80
showTOC($metadata)
Create the TOC.
Definition: ImagePage.php:247
static rawElement($element, $attribs=[], $contents= '')
Returns an HTML element in a string.
Definition: Html.php:210
if(!isset($args[0])) $lang
static hidden($name, $value, array $attribs=[])
Convenience function to produce an input element with type=hidden.
Definition: Html.php:749
getUploadUrl()
Definition: ImagePage.php:733
Class for viewing MediaWiki article and history.
Definition: Article.php:34
Class for viewing MediaWiki file description pages.
Definition: ImagePage.php:28
FileRepo $repo
Definition: ImagePage.php:33
wfMessageFallback()
This function accepts multiple message keys and returns a message instance for the first message whic...
Represents a title within MediaWiki.
Definition: Title.php:36
when a variable name is used in a it is silently declared as a new local masking the global
Definition: design.txt:93
printSharedImageText()
Show a notice that the file is from a shared repository.
Definition: ImagePage.php:700
wfLocalFile($title)
Get an object referring to a locally registered file.
imageHistory()
If the page we've just displayed is in the "Image" namespace, we follow it with an upload history of ...
Definition: ImagePage.php:791
uploadLinksBox()
Print out the various links at the bottom of the image page, e.g.
Definition: ImagePage.php:746
globals will be eliminated from MediaWiki replaced by an application object which would be passed to constructors Whether that would be an convenient solution remains to be but certainly PHP makes such object oriented programming models easier than they were in previous versions For the time being MediaWiki programmers will have to work in an environment with some global context At the time of globals were initialised on startup by MediaWiki of these were configuration which are documented in DefaultSettings php There is no comprehensive documentation for the remaining however some of the most important ones are listed below They are typically initialised either in index php or in Setup php For a description of the see design txt $wgTitle Title object created from the request URL $wgOut OutputPage object for HTTP response $wgUser User object for the user associated with the current request $wgLang Language object selected by user preferences $wgContLang Language object associated with the wiki being viewed $wgParser Parser object Parser extensions register their hooks here $wgRequest WebRequest object
Definition: globals.txt:25
static submitButton($value, $attribs=[])
Convenience function to build an HTML submit button When $wgUseMediaWikiUIEverywhere is true it will ...
Definition: Xml.php:460
static userCanReUpload(User $user, File $img)
Check if a user is the last uploader.
static showLogExtract(&$out, $types=[], $page= '', $user= '', $param=[])
Show log extract.
getForeignCategories()
Definition: ImagePage.php:1241
the value to return A Title object or null for latest to be modified or replaced by the hook handler or if authentication is not possible after cache objects are set for highlighting & $link
Definition: hooks.txt:2621
getThumbSizes($origWidth, $origHeight)
Get alternative thumbnail sizes.
Definition: ImagePage.php:1187
$wgEnableUploads
Uploads have to be specially set up to be secure.
getContext()
Gets the context this Article is executed in.
Definition: Article.php:2040
static closeElement($element)
Shortcut to close an XML element.
Definition: Xml.php:118
showError($description)
Display an error with a wikitext description.
Definition: ImagePage.php:1008
static openElement($element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:248
$wgShowEXIF
Show Exif data, on by default if available.
wfEscapeWikiText($text)
Escapes the given text so that it may be output using addWikiText() without any linking, formatting, etc.
static newFromID($id)
Constructor from a page id.
Definition: ImagePage.php:60
$css
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1020
$res
Definition: database.txt:21
static option($text, $value=null, $selected=false, $attribs=[])
Convenience function to build an HTML drop-down list item.
Definition: Xml.php:485
MediaWiki exception.
Definition: MWException.php:26
static openElement($element, $attribs=null)
This opens an XML element.
Definition: Xml.php:109
$wgImageLimits
Limit images on image description pages to a user-selectable limit.
getTitle()
Get the title object of the article.
Definition: Article.php:166
$params
File $displayImg
Definition: ImagePage.php:30
const DB_SLAVE
Definition: Defines.php:46
wfBCP47($code)
Get the normalised IETF language tag See unit test for examples.
Allows to change the fields on the form that will be generated are created Can be used to omit specific feeds from being outputted You must not use this hook to add use OutputPage::addFeedLink() instead.&$feedLinks conditions will AND in the final query as a Content object as a Content object $title
Definition: hooks.txt:312
static linkKnown($target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to 'known'.
Definition: Linker.php:255
static run($event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition: design.txt:12
const NS_FILE
Definition: Defines.php:75
addModules($modules)
render()
Handler for action=render Include body text only; none of the image extras.
Definition: ImagePage.php:102
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
Special handling for file pages.
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code
Definition: hooks.txt:776
compare($a, $b)
Callback for usort() to do link sorts by (namespace, title) Function copied from Title::compare() ...
Definition: ImagePage.php:1025
static fetchLanguageName($code, $inLanguage=null, $include= 'all')
Definition: Language.php:886
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user
Definition: hooks.txt:242
$wgSVGMaxSize
Don't scale a SVG larger than this.
static escapeId($id, $options=[])
Given a value, escape it so that it can be used in an id attribute and return it. ...
Definition: Sanitizer.php:1169
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object & $output
Definition: hooks.txt:1020
static makeExternalLink($url, $text, $escape=true, $linktype= '', $attribs=[], $title=null)
Make an external link.
Definition: Linker.php:936
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
static tags($element, $attribs=null, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:131
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2458
getId()
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2285
getDisplayWidthHeight($maxWidth, $maxHeight, $width, $height)
Get the width and height to display image at.
Definition: ImagePage.php:1151
getOldID()
Definition: Article.php:253
setFile($file)
Definition: ImagePage.php:71
getDisplayName()
Get the human-readable name of the repo.
Definition: FileRepo.php:1753
newPage(Title $title)
Definition: ImagePage.php:50
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object to manipulate or replace but no entry for that model exists in $wgContentHandlers if desired whether it is OK to use $contentModel on $title Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok inclusive $limit
Definition: hooks.txt:1020
bool $mExtraDescription
Definition: ImagePage.php:39
getDisplayedFile()
Definition: ImagePage.php:236
makeSizeLink($params, $width, $height)
Creates an thumbnail of specified size and returns an HTML link to it.
Definition: ImagePage.php:681
$count
addJsConfigVars($keys, $value=null)
Add one or more variables to be set in mw.config in JavaScript.
doRenderLangOpt(array $langChoices, $curLang, $defaultLang)
Output a drop-down box for language options for the file.
Definition: ImagePage.php:1069
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable modifiable after all normalizations have been except for the $wgMaxImageArea check set to true or false to override the $wgMaxImageArea check result gives extension the possibility to transform it themselves $handler
Definition: hooks.txt:776
getThumbPrevText($params, $sizeLinkBigImagePreview)
Make the text under the image to say what size preview.
Definition: ImagePage.php:643
getUser($audience=Revision::FOR_PUBLIC, User $user=null)
Call to WikiPage function for backwards compatibility.
Definition: Article.php:2382
WikiFilePage $mPage
Definition: ImagePage.php:44
static makeThumbLinkObj(Title $title, $file, $label= '', $alt, $align= 'right', $params=[], $framed=false, $manualthumb="")
Make HTML for a thumbnail including image, border and caption.
Definition: Linker.php:596
static getDefaultOption($opt)
Get a given default option value.
Definition: User.php:1598
$wgSend404Code
Some web hosts attempt to rewrite all responses with a 404 (not found) status code, mangling or hiding MediaWiki's output.
getImageLimitsFromOption($user, $optionName)
Returns the corresponding $wgImageLimits entry for the selected user option.
Definition: ImagePage.php:1041
File deletion user interface.
wfFindFile($title, $options=[])
Find a file.
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached one of or reset my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
Definition: hooks.txt:2376
static makeTitle($ns, $title, $fragment= '', $interwiki= '')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:503
makeMetadataTable($metadata)
Make a table with metadata to be shown in the output page.
Definition: ImagePage.php:273
getContentObject()
Overloading Article's getContentObject method.
Definition: ImagePage.php:301
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached $page
Definition: hooks.txt:2376
closeShowImage()
For overloading.
Definition: ImagePage.php:784
openShowImage()
Definition: ImagePage.php:309
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:310