59 private $commentStore;
68 private $commentFormatter;
73 private const INDEX_FIELDS = [
74 'img_timestamp' => [
'img_timestamp',
'img_name' ],
75 'img_name' => [
'img_name' ],
76 'img_size' => [
'img_size',
'img_name' ],
109 $this->mIncluding = $including;
110 $this->mShowAll = $showAll;
113 if ( $userName !==
null && $userName !==
'' ) {
114 $nt = Title::makeTitleSafe(
NS_USER, $userName );
115 if ( $nt ===
null ) {
118 $this->mUserName = $nt->getText();
121 $this->mUser = $user;
123 if ( !$user || ( $user->isAnon() && !$userNameUtils->
isIP( $user->getName() ) ) ) {
130 if ( $this->
getRequest()->getText(
'sort',
'img_date' ) ==
'img_date' ) {
141 parent::__construct( $context, $linkRenderer );
142 $this->commentStore = $commentStore;
144 $this->userCache = $userCache;
145 $this->commentFormatter = $commentFormatter;
163 $this->
getOutput()->addHTML( Html::warningBox(
165 'mw-userpage-userdoesnotexist'
179 if ( $this->mUserName !==
null ) {
184 if ( $table ===
'oldimage' ) {
188 $conds[
'oi_deleted'] = 0;
196 if ( !$this->mFieldNames ) {
197 $this->mFieldNames = [
198 'img_timestamp' => $this->
msg(
'listfiles_date' )->text(),
199 'img_name' => $this->
msg(
'listfiles_name' )->text(),
200 'thumb' => $this->
msg(
'listfiles_thumb' )->text(),
201 'img_size' => $this->
msg(
'listfiles_size' )->text(),
203 if ( $this->mUserName ===
null ) {
205 $this->mFieldNames[
'img_actor'] = $this->
msg(
'listfiles_user' )->text();
208 $this->mFieldNames[
'img_description'] = $this->
msg(
'listfiles_description' )->text();
210 if ( !$this->
getConfig()->
get( MainConfigNames::MiserMode ) && !$this->mShowAll ) {
211 $this->mFieldNames[
'count'] = $this->
msg(
'listfiles_count' )->text();
213 if ( $this->mShowAll ) {
214 $this->mFieldNames[
'top'] = $this->
msg(
'listfiles-latestversion' )->text();
222 if ( $this->mIncluding ) {
232 if ( $this->
getConfig()->
get( MainConfigNames::MiserMode ) && $this->mUserName !==
null ) {
234 return $field ===
'img_timestamp';
235 } elseif ( $this->
getConfig()->
get( MainConfigNames::MiserMode )
239 return $field ===
'img_name';
242 return isset( self::INDEX_FIELDS[$field] );
266 $prefix = $table ===
'oldimage' ?
'oi' :
'img';
268 $tables = [ $table,
'actor' ];
271 if ( $table ===
'oldimage' ) {
273 'img_timestamp' =>
'oi_timestamp',
274 'img_name' =>
'oi_name',
275 'img_size' =>
'oi_size',
276 'top' =>
$dbr->addQuotes(
'no' )
278 $join_conds[
'actor'] = [
'JOIN',
'actor_id=oi_actor' ];
284 'top' =>
$dbr->addQuotes(
'yes' )
286 $join_conds[
'actor'] = [
'JOIN',
'actor_id=img_actor' ];
292 $commentQuery = $this->commentStore->getJoin( $prefix .
'_description' );
293 $tables += $commentQuery[
'tables'];
294 $fields += $commentQuery[
'fields'];
295 $join_conds += $commentQuery[
'joins'];
296 $fields[
'description_field'] =
$dbr->addQuotes(
"{$prefix}_description" );
299 $fields[] =
'actor_user';
300 $fields[] =
'actor_name';
302 # Depends on $wgMiserMode
303 # Will also not happen if mShowAll is true.
305 $fields[
'count'] =
$dbr->buildSelectSubquery(
307 'COUNT(oi_archive_name)',
308 'oi_name = img_name',
317 'options' => $options,
318 'join_conds' => $join_conds
334 $this->mTableName =
'image';
335 [ $tables, $fields, $conds, $fname, $options, $join_conds ] =
337 $imageRes =
$dbr->select( $tables, $fields, $conds, $fname, $options, $join_conds );
338 $this->mTableName = $prevTableName;
340 if ( !$this->mShowAll ) {
344 $this->mTableName =
'oldimage';
348 foreach ( $this->mIndexField as &$index ) {
349 if ( !str_starts_with( $index,
'img_' ) ) {
350 throw new MWException(
"Expected to be sorting on an image table field" );
352 $index =
'oi_' . substr( $index, 4 );
355 [ $tables, $fields, $conds, $fname, $options, $join_conds ] =
357 $oldimageRes =
$dbr->select( $tables, $fields, $conds, $fname, $options, $join_conds );
359 $this->mTableName = $prevTableName;
360 $this->mIndexField = $oldIndex;
362 return $this->
combineResult( $imageRes, $oldimageRes, $limit, $order );
379 $topRes1 = $res1->fetchObject();
380 $topRes2 = $res2->fetchObject();
382 for ( $i = 0; $i < $limit && $topRes1 && $topRes2; $i++ ) {
383 if ( strcmp( $topRes1->{$this->mIndexField[0]}, $topRes2->{$this->mIndexField[0]} ) > 0 ) {
385 $resultArray[] = $topRes1;
386 $topRes1 = $res1->fetchObject();
388 $resultArray[] = $topRes2;
389 $topRes2 = $res2->fetchObject();
392 $resultArray[] = $topRes2;
393 $topRes2 = $res2->fetchObject();
395 $resultArray[] = $topRes1;
396 $topRes1 = $res1->fetchObject();
400 for ( ; $i < $limit && $topRes1; $i++ ) {
401 $resultArray[] = $topRes1;
402 $topRes1 = $res1->fetchObject();
405 for ( ; $i < $limit && $topRes2; $i++ ) {
406 $resultArray[] = $topRes2;
407 $topRes2 = $res2->fetchObject();
414 return [ self::INDEX_FIELDS[$this->mSort] ];
418 if ( $this->mShowAll && $this->getConfig()->
get( MainConfigNames::MiserMode ) &&
419 $this->mUserName ===
null ) {
423 return 'img_timestamp';
429 $this->mResult->seek( 0 );
430 foreach ( $this->mResult as $row ) {
431 if ( $row->actor_user ) {
432 $userIds[] = $row->actor_user;
435 # Do a link batch query for names and userpages
436 $this->userCache->doQuery( $userIds, [
'userpage' ], __METHOD__ );
446 $linkRenderer = $this->getLinkRenderer();
449 $opt = [
'time' =>
wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
450 $file = $this->localRepo->findFile( $this->getCurrentRow()->img_name, $opt );
453 $thumb =
$file->transform( [
'width' => 180,
'height' => 360,
'loading' =>
'lazy' ] );
455 return $thumb->toHtml( [
'desc-link' =>
true ] );
457 return $this->msg(
'thumbnail_error',
'' )->escaped();
460 return htmlspecialchars( $this->getCurrentRow()->img_name );
462 case 'img_timestamp':
464 return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->
getUser() ) );
466 static $imgfile =
null;
467 if ( $imgfile ===
null ) {
468 $imgfile = $this->msg(
'imgfile' )->text();
472 $filePage = Title::makeTitleSafe(
NS_FILE, $value );
474 $link = $linkRenderer->makeKnownLink(
480 [
'href' => $this->localRepo->newFile( $filePage )->getUrl() ],
483 $download = $this->msg(
'parentheses' )->rawParams( $download )->escaped();
487 if ( $this->
getAuthority()->probablyCan(
'delete', $filePage ) ) {
488 $deleteMsg = $this->msg(
'listfiles-delete' )->text();
490 $delete = $linkRenderer->makeKnownLink(
491 $filePage, $deleteMsg, [], [
'action' =>
'delete' ]
493 $delete = $this->msg(
'parentheses' )->rawParams( $delete )->escaped();
495 return "$link $download $delete";
498 return "$link $download";
500 return htmlspecialchars( $value );
503 if ( $this->mCurrentRow->actor_user ) {
504 $name = $this->mCurrentRow->actor_name;
505 $link = $linkRenderer->makeLink(
506 Title::makeTitle(
NS_USER, $name ),
510 $link = $value !==
null ? htmlspecialchars( $value ) :
'';
515 return htmlspecialchars( $this->getLanguage()->formatSize( (
int)$value ) );
516 case 'img_description':
517 $field = $this->mCurrentRow->description_field;
518 $value = $this->commentStore->getComment( $field, $this->mCurrentRow )->text;
519 return $this->commentFormatter->format( $value );
521 return htmlspecialchars( $this->getLanguage()->formatNum( intval( $value ) + 1 ) );
524 return $this->msg(
'listfiles-latestversion-' . $value )->escaped();
531 $formDescriptor = [];
532 $formDescriptor[
'limit'] = [
535 'label-message' =>
'table_pager_limit_label',
536 'options' => $this->getLimitSelectList(),
537 'default' => $this->mLimit,
540 $formDescriptor[
'user'] = [
543 'id' =>
'mw-listfiles-user',
544 'label-message' =>
'username',
545 'default' => $this->mUserName,
547 'maxlength' =>
'255',
550 $formDescriptor[
'ilshowall'] = [
552 'name' =>
'ilshowall',
553 'id' =>
'mw-listfiles-show-all',
554 'label-message' =>
'listfiles-show-all',
555 'default' => $this->mShowAll,
558 $query = $this->
getRequest()->getQueryValues();
559 unset( $query[
'title'] );
560 unset( $query[
'limit'] );
561 unset( $query[
'ilsearch'] );
562 unset( $query[
'ilshowall'] );
563 unset( $query[
'user'] );
567 ->setId(
'mw-listfiles-form' )
569 ->setSubmitTextMsg(
'table_pager_limit_submit' )
570 ->setWrapperLegendMsg(
'listfiles' )
571 ->addHiddenFields( $query )
577 return parent::getTableClass() .
' listfiles';
581 return parent::getNavClass() .
' listfiles_nav';
585 return parent::getSortHeaderClass() .
' listfiles_sort';
589 $queries = parent::getPagingQueries();
590 if ( $this->mUserName !==
null ) {
591 # Append the username to the query string
592 foreach ( $queries as &$query ) {
593 if ( $query !==
false ) {
594 $query[
'user'] = $this->mUserName;
603 $queries = parent::getDefaultQuery();
604 if ( !isset( $queries[
'user'] ) && $this->mUserName !==
null ) {
605 $queries[
'user'] = $this->mUserName;
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
setContext(IContextSource $context)
A class containing constants representing the names of configuration variables.
Prioritized list of file repositories.
getLocalRepo()
Get the local repository, i.e.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
static newFromName( $name, $validate='valid')
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Interface for objects which can provide a MediaWiki context on request.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.