MediaWiki  master
ImageHistoryList.php
Go to the documentation of this file.
1 <?php
22 
29 
33  protected $title;
34 
38  protected $img;
39 
43  protected $imagePage;
44 
48  protected $current;
49 
50  protected $repo, $showThumb;
51  protected $preventClickjacking = false;
52 
56  public function __construct( $imagePage ) {
58  $this->current = $imagePage->getPage()->getFile();
59  $this->img = $imagePage->getDisplayedFile();
60  $this->title = $imagePage->getTitle();
61  $this->imagePage = $imagePage;
62  $this->showThumb = $context->getConfig()->get( 'ShowArchiveThumbnails' ) &&
63  $this->img->canRender();
64  $this->setContext( $context );
65  }
66 
70  public function getImagePage() {
71  return $this->imagePage;
72  }
73 
77  public function getFile() {
78  return $this->img;
79  }
80 
85  public function beginImageHistoryList( $navLinks = '' ) {
86  return Xml::element( 'h2', [ 'id' => 'filehistory' ], $this->msg( 'filehist' )->text() )
87  . "\n"
88  . "<div id=\"mw-imagepage-section-filehistory\">\n"
89  . $this->msg( 'filehist-help' )->parseAsBlock()
90  . $navLinks . "\n"
91  . Xml::openElement( 'table', [ 'class' => 'wikitable filehistory' ] ) . "\n"
92  . '<tr><th></th>'
93  . ( $this->current->isLocal()
94  && ( MediaWikiServices::getInstance()
95  ->getPermissionManager()
96  ->userHasAnyRight( $this->getUser(), 'delete', 'deletedhistory' ) ) ? '<th></th>' : '' )
97  . '<th>' . $this->msg( 'filehist-datetime' )->escaped() . '</th>'
98  . ( $this->showThumb ? '<th>' . $this->msg( 'filehist-thumb' )->escaped() . '</th>' : '' )
99  . '<th>' . $this->msg( 'filehist-dimensions' )->escaped() . '</th>'
100  . '<th>' . $this->msg( 'filehist-user' )->escaped() . '</th>'
101  . '<th>' . $this->msg( 'filehist-comment' )->escaped() . '</th>'
102  . "</tr>\n";
103  }
104 
109  public function endImageHistoryList( $navLinks = '' ) {
110  return "</table>\n$navLinks\n</div>\n";
111  }
112 
118  public function imageHistoryLine( $iscur, $file ) {
119  $user = $this->getUser();
120  $lang = $this->getLanguage();
121  $pm = MediaWikiServices::getInstance()->getPermissionManager();
122  $timestamp = wfTimestamp( TS_MW, $file->getTimestamp() );
123  // @phan-suppress-next-line PhanUndeclaredMethod
124  $img = $iscur ? $file->getName() : $file->getArchiveName();
125  $userId = $file->getUser( 'id' );
126  $userText = $file->getUser( 'text' );
127  $description = $file->getDescription( File::FOR_THIS_USER, $user );
128 
129  $local = $this->current->isLocal();
130  $row = $selected = '';
131 
132  // Deletion link
133  if ( $local && ( $pm->userHasAnyRight( $user, 'delete', 'deletedhistory' ) ) ) {
134  $row .= '<td>';
135  # Link to remove from history
136  if ( $pm->userHasRight( $user, 'delete' ) ) {
137  $q = [ 'action' => 'delete' ];
138  if ( !$iscur ) {
139  $q['oldimage'] = $img;
140  }
141  $row .= Linker::linkKnown(
142  $this->title,
143  $this->msg( $iscur ? 'filehist-deleteall' : 'filehist-deleteone' )->escaped(),
144  [], $q
145  );
146  }
147  # Link to hide content. Don't show useless link to people who cannot hide revisions.
148  $canHide = $pm->userHasRight( $user, 'deleterevision' );
149  if ( $canHide || ( $pm->userHasRight( $user, 'deletedhistory' )
150  && $file->getVisibility() ) ) {
151  if ( $pm->userHasRight( $user, 'delete' ) ) {
152  $row .= '<br />';
153  }
154  // If file is top revision or locked from this user, don't link
155  if ( $iscur || !$file->userCan( File::DELETED_RESTRICTED, $user ) ) {
156  $del = Linker::revDeleteLinkDisabled( $canHide );
157  } else {
158  list( $ts, ) = explode( '!', $img, 2 );
159  $query = [
160  'type' => 'oldimage',
161  'target' => $this->title->getPrefixedText(),
162  'ids' => $ts,
163  ];
164  $del = Linker::revDeleteLink( $query,
165  $file->isDeleted( File::DELETED_RESTRICTED ), $canHide );
166  }
167  $row .= $del;
168  }
169  $row .= '</td>';
170  }
171 
172  // Reversion link/current indicator
173  $row .= '<td>';
174  if ( $iscur ) {
175  $row .= $this->msg( 'filehist-current' )->escaped();
176  } elseif ( $local && $pm->quickUserCan( 'edit', $user, $this->title )
177  && $pm->quickUserCan( 'upload', $user, $this->title )
178  ) {
179  if ( $file->isDeleted( File::DELETED_FILE ) ) {
180  $row .= $this->msg( 'filehist-revert' )->escaped();
181  } else {
182  $row .= Linker::linkKnown(
183  $this->title,
184  $this->msg( 'filehist-revert' )->escaped(),
185  [],
186  [
187  'action' => 'revert',
188  'oldimage' => $img,
189  ]
190  );
191  }
192  }
193  $row .= '</td>';
194 
195  // Date/time and image link
196  if ( $file->getTimestamp() === $this->img->getTimestamp() ) {
197  $selected = "class='filehistory-selected'";
198  }
199  $row .= "<td $selected style='white-space: nowrap;'>";
200  if ( !$file->userCan( File::DELETED_FILE, $user ) ) {
201  # Don't link to unviewable files
202  $row .= Html::element( 'span', [ 'class' => 'history-deleted' ],
203  $lang->userTimeAndDate( $timestamp, $user )
204  );
205  } elseif ( $file->isDeleted( File::DELETED_FILE ) ) {
206  $timeAndDate = htmlspecialchars( $lang->userTimeAndDate( $timestamp, $user ) );
207  if ( $local ) {
208  $this->preventClickjacking();
209  $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
210  # Make a link to review the image
211  $url = Linker::linkKnown(
212  $revdel,
213  $timeAndDate,
214  [],
215  [
216  'target' => $this->title->getPrefixedText(),
217  'file' => $img,
218  'token' => $user->getEditToken( $img )
219  ]
220  );
221  } else {
222  $url = $timeAndDate;
223  }
224  $row .= '<span class="history-deleted">' . $url . '</span>';
225  } elseif ( !$file->exists() ) {
226  $row .= Html::element( 'span', [ 'class' => 'mw-file-missing' ],
227  $lang->userTimeAndDate( $timestamp, $user )
228  );
229  } else {
230  $url = $iscur ? $this->current->getUrl() : $this->current->getArchiveUrl( $img );
231  $row .= Xml::element(
232  'a',
233  [ 'href' => $url ],
234  $lang->userTimeAndDate( $timestamp, $user )
235  );
236  }
237  $row .= "</td>";
238 
239  // Thumbnail
240  if ( $this->showThumb ) {
241  $row .= '<td>' . $this->getThumbForLine( $file ) . '</td>';
242  }
243 
244  // Image dimensions + size
245  $row .= '<td>';
246  $row .= htmlspecialchars( $file->getDimensionsString() );
247  $row .= $this->msg( 'word-separator' )->escaped();
248  $row .= '<span style="white-space: nowrap;">';
249  $row .= $this->msg( 'parentheses' )->sizeParams( $file->getSize() )->escaped();
250  $row .= '</span>';
251  $row .= '</td>';
252 
253  // Uploading user
254  $row .= '<td>';
255  // Hide deleted usernames
256  if ( $file->isDeleted( File::DELETED_USER ) ) {
257  $row .= '<span class="history-deleted">'
258  . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
259  } else {
260  if ( $local ) {
261  $row .= Linker::userLink( $userId, $userText );
262  $row .= '<span style="white-space: nowrap;">';
263  $row .= Linker::userToolLinks( $userId, $userText );
264  $row .= '</span>';
265  } else {
266  $row .= htmlspecialchars( $userText );
267  }
268  }
269  $row .= '</td>';
270 
271  // Don't show deleted descriptions
272  if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
273  $row .= '<td><span class="history-deleted">' .
274  $this->msg( 'rev-deleted-comment' )->escaped() . '</span></td>';
275  } else {
276  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
277  $row .= Html::rawElement(
278  'td',
279  [ 'dir' => $contLang->getDir() ],
280  Linker::formatComment( $description, $this->title )
281  );
282  }
283 
284  $rowClass = null;
285  Hooks::run( 'ImagePageFileHistoryLine', [ $this, $file, &$row, &$rowClass ] );
286  $classAttr = $rowClass ? " class='$rowClass'" : '';
287 
288  return "<tr{$classAttr}>{$row}</tr>\n";
289  }
290 
295  protected function getThumbForLine( $file ) {
296  $lang = $this->getLanguage();
297  $user = $this->getUser();
298  if ( $file->allowInlineDisplay() && $file->userCan( File::DELETED_FILE, $user )
299  && !$file->isDeleted( File::DELETED_FILE )
300  ) {
301  $params = [
302  'width' => '120',
303  'height' => '120',
304  ];
305  $timestamp = wfTimestamp( TS_MW, $file->getTimestamp() );
306 
307  $thumbnail = $file->transform( $params );
308  $options = [
309  'alt' => $this->msg( 'filehist-thumbtext',
310  $lang->userTimeAndDate( $timestamp, $user ),
311  $lang->userDate( $timestamp, $user ),
312  $lang->userTime( $timestamp, $user ) )->text(),
313  'file-link' => true,
314  ];
315 
316  if ( !$thumbnail ) {
317  return $this->msg( 'filehist-nothumb' )->escaped();
318  }
319 
320  return $thumbnail->toHtml( $options );
321  } else {
322  return $this->msg( 'filehist-nothumb' )->escaped();
323  }
324  }
325 
329  protected function preventClickjacking( $enable = true ) {
330  $this->preventClickjacking = $enable;
331  }
332 
336  public function getPreventClickjacking() {
338  }
339 }
setContext(IContextSource $context)
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
const DELETED_COMMENT
Definition: File.php:64
const FOR_THIS_USER
Definition: File.php:80
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
beginImageHistoryList( $navLinks='')
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
getPage()
Get the WikiPage object of this instance.
Definition: Article.php:234
if(!isset( $args[0])) $lang
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
endImageHistoryList( $navLinks='')
IContextSource $context
Builds the image revision log shown on image pages.
const DELETED_FILE
Definition: File.php:63
getContext()
Gets the context this Article is executed in.
Definition: Article.php:2270
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
getConfig()
Get the site configuration.
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Definition: Linker.php:1165
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:108
static userToolLinks( $userId, $userText, $redContribsWhenNoEdits=false, $flags=0, $edits=null, $useParentheses=true)
Generate standard user tool links (talk, contributions, block link, etc.)
Definition: Linker.php:943
getTitle()
Get the title object of the article.
Definition: Article.php:224
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don&#39;t need a full Title object...
Definition: SpecialPage.php:83
const DELETED_USER
Definition: File.php:65
static userLink( $userId, $userName, $altUserName=false)
Make user link (or user contributions for unregistered users)
Definition: Linker.php:898
const DELETED_RESTRICTED
Definition: File.php:66
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
static linkKnown( $target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to &#39;known&#39;.
Definition: Linker.php:141
static revDeleteLink( $query=[], $restricted=false, $delete=true)
Creates a (show/hide) link for deleting revisions/log entries.
Definition: Linker.php:2150
__construct( $imagePage)
imageHistoryLine( $iscur, $file)
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:41
getDisplayedFile()
Definition: ImagePage.php:214
preventClickjacking( $enable=true)
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
static revDeleteLinkDisabled( $delete=true)
Creates a dead (show/hide) link for deleting revisions/log entries.
Definition: Linker.php:2172