101 $this->mIncluding = $including;
102 $this->mShowAll = $showAll;
104 if ( $userName !==
null && $userName !==
'' ) {
105 $nt = Title::makeTitleSafe(
NS_USER, $userName );
106 if ( $nt ===
null ) {
109 $this->mUserName = $nt->getText();
110 $user = User::newFromName( $this->mUserName,
false );
112 $this->mUser = $user;
114 if ( !$user || ( $user->isAnon() && !$userNameUtils->
isIP( $user->getName() ) ) ) {
121 $this->
getRequest()->getText(
'sort',
'img_date' ) ===
'img_date'
130 parent::__construct( $context, $linkRenderer );
131 $this->commentStore = $commentStore;
133 $this->rowCommentFormatter = $rowCommentFormatter;
134 $this->linkBatchFactory = $linkBatchFactory;
135 $this->migrationStage = $this->
getConfig()->get(
267 $tables = [
'filerevision',
'file',
'actor' ];
269 'img_timestamp' =>
'fr_timestamp',
270 'img_name' =>
'file_name',
271 'img_size' =>
'fr_size',
272 'top' =>
'CASE WHEN file_latest = fr_id THEN \'yes\' ELSE \'no\' END',
275 'filerevision' => [
'JOIN',
'fr_file=file_id' ],
276 'actor' => [
'JOIN',
'actor_id=fr_actor' ]
280 $commentQuery = $this->commentStore->getJoin(
'fr_description' );
281 $tables += $commentQuery[
'tables'];
282 $fields += $commentQuery[
'fields'];
283 $join_conds += $commentQuery[
'joins'];
284 $fields[
'description_field'] = $dbr->addQuotes(
"fr_description" );
287 $fields[] =
'actor_user';
288 $fields[] =
'actor_name';
290 # Depends on $wgMiserMode
291 # Will also not happen if mShowAll is true.
293 $fields[
'count'] =
new Subquery( $dbr->newSelectQueryBuilder()
294 ->select(
'COUNT(fr_archive_name)' )
295 ->from(
'filerevision' )
296 ->where(
'fr_file = file_id' )
297 ->caller( __METHOD__ )
305 'conds' => $this->buildQueryConds(),
307 'join_conds' => $join_conds
323 $prefix = $table ===
'oldimage' ?
'oi' :
'img';
325 $tables = [ $table,
'actor' ];
328 if ( $table ===
'oldimage' ) {
330 'img_timestamp' =>
'oi_timestamp',
331 'img_name' =>
'oi_name',
332 'img_size' =>
'oi_size',
333 'top' => $dbr->addQuotes(
'no' )
335 $join_conds[
'actor'] = [
'JOIN',
'actor_id=oi_actor' ];
341 'top' => $dbr->addQuotes(
'yes' )
343 $join_conds[
'actor'] = [
'JOIN',
'actor_id=img_actor' ];
347 $commentQuery = $this->commentStore->getJoin( $prefix .
'_description' );
348 $tables += $commentQuery[
'tables'];
349 $fields += $commentQuery[
'fields'];
350 $join_conds += $commentQuery[
'joins'];
351 $fields[
'description_field'] = $dbr->addQuotes(
"{$prefix}_description" );
354 $fields[] =
'actor_user';
355 $fields[] =
'actor_name';
357 # Depends on $wgMiserMode
358 # Will also not happen if mShowAll is true.
360 $fields[
'count'] =
new Subquery( $dbr->newSelectQueryBuilder()
361 ->select(
'COUNT(oi_archive_name)' )
363 ->where(
'oi_name = img_name' )
364 ->caller( __METHOD__ )
374 'join_conds' => $join_conds
382 return parent::reallyDoQuery( $offset, $limit, $order );
397 $this->mTableName =
'image';
398 [ $tables, $fields, $conds, $fname, $options, $join_conds ] =
400 $imageRes = $dbr->newSelectQueryBuilder()
401 ->tables( is_array( $tables ) ? $tables : [ $tables ] )
405 ->options( $options )
406 ->joinConds( $join_conds )
408 $this->mTableName = $prevTableName;
410 if ( !$this->mShowAll ) {
414 $this->mTableName =
'oldimage';
418 foreach ( $this->mIndexField as &$index ) {
419 if ( !str_starts_with( $index,
'img_' ) ) {
420 throw new UnexpectedValueException(
"Expected to be sorting on an image table field" );
422 $index =
'oi_' . substr( $index, 4 );
426 [ $tables, $fields, $conds, $fname, $options, $join_conds ] =
428 $oldimageRes = $dbr->newSelectQueryBuilder()
429 ->tables( is_array( $tables ) ? $tables : [ $tables ] )
433 ->options( $options )
434 ->joinConds( $join_conds )
437 $this->mTableName = $prevTableName;
438 $this->mIndexField = $oldIndex;
440 return $this->
combineResult( $imageRes, $oldimageRes, $limit, $order );
457 $topRes1 = $res1->fetchObject();
458 $topRes2 = $res2->fetchObject();
460 for ( $i = 0; $i < $limit && $topRes1 && $topRes2; $i++ ) {
461 if ( strcmp( $topRes1->{$this->mIndexField[0]}, $topRes2->{$this->mIndexField[0]} ) > 0 ) {
463 $resultArray[] = $topRes1;
464 $topRes1 = $res1->fetchObject();
466 $resultArray[] = $topRes2;
467 $topRes2 = $res2->fetchObject();
470 $resultArray[] = $topRes2;
471 $topRes2 = $res2->fetchObject();
473 $resultArray[] = $topRes1;
474 $topRes1 = $res1->fetchObject();
478 for ( ; $i < $limit && $topRes1; $i++ ) {
479 $resultArray[] = $topRes1;
480 $topRes1 = $res1->fetchObject();
483 for ( ; $i < $limit && $topRes2; $i++ ) {
484 $resultArray[] = $topRes2;
485 $topRes2 = $res2->fetchObject();
488 return new FakeResultWrapper( $resultArray );
508 $this->mResult->seek( 0 );
509 $batch = $this->linkBatchFactory->newLinkBatch();
510 $rowsWithComments = [
'img_description' => [],
'oi_description' => [],
'fr_description' => [] ];
511 foreach ( $this->mResult as $i => $row ) {
512 $batch->addUser(
new UserIdentityValue( $row->actor_user ?? 0, $row->actor_name ) );
513 $batch->add(
NS_FILE, $row->img_name );
514 $rowsWithComments[$row->description_field][$i] = $row;
519 if ( $rowsWithComments[
'img_description'] ) {
520 $this->formattedComments += $this->rowCommentFormatter->formatRows(
521 $rowsWithComments[
'img_description'],
525 if ( $rowsWithComments[
'oi_description'] ) {
526 $this->formattedComments += $this->rowCommentFormatter->formatRows(
527 $rowsWithComments[
'oi_description'],
531 if ( $rowsWithComments[
'fr_description'] ) {
532 $this->formattedComments += $this->rowCommentFormatter->formatRows(
533 $rowsWithComments[
'fr_description'],
545 $linkRenderer = $this->getLinkRenderer();
548 $opt = [
'time' =>
wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
549 $file = $this->localRepo->findFile( $this->getCurrentRow()->img_name, $opt );
552 $thumb = $file->transform( [
'width' => 180,
'height' => 360 ] );
554 return $thumb->toHtml( [
'desc-link' =>
true,
'loading' =>
'lazy' ] );
556 return $this->msg(
'thumbnail_error',
'' )->escaped();
558 return htmlspecialchars( $this->getCurrentRow()->img_name );
560 case 'img_timestamp':
562 return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ) );
564 static $imgfile =
null;
565 $imgfile ??= $this->msg(
'imgfile' )->text();
568 $filePage = Title::makeTitleSafe(
NS_FILE, $value );
570 $html = $linkRenderer->makeKnownLink(
574 $opt = [
'time' =>
wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
575 $file = $this->localRepo->findFile( $value, $opt );
577 $download = Xml::element(
579 [
'href' => $file->getUrl() ],
582 $html .=
' ' . $this->msg(
'parentheses' )->rawParams( $download )->escaped();
587 if ( $this->getAuthority()->probablyCan(
'delete', $filePage ) ) {
588 $deleteMsg = $this->msg(
'listfiles-delete' )->text();
590 $delete = $linkRenderer->makeKnownLink(
591 $filePage, $deleteMsg, [], [
'action' =>
'delete' ]
593 $html .=
' ' . $this->msg(
'parentheses' )->rawParams( $delete )->escaped();
598 return htmlspecialchars( $value );
601 $userId = (int)$this->mCurrentRow->actor_user;
602 $userName = $this->mCurrentRow->actor_name;
603 return Linker::userLink( $userId, $userName )
604 . Linker::userToolLinks( $userId, $userName );
606 return htmlspecialchars( $this->getLanguage()->formatSize( (
int)$value ) );
607 case 'img_description':
608 return $this->formattedComments[$this->getResultOffset()];
611 return htmlspecialchars( $this->getLanguage()->formatNum( intval( $value ) + 1 ) );
613 return htmlspecialchars( $this->getLanguage()->formatNum( intval( $value ) ) );
617 return $this->msg(
'listfiles-latestversion-' . $value )->escaped();
619 throw new UnexpectedValueException(
"Unknown field '$field'" );
636 $formDescriptor = [];
637 $formDescriptor[
'limit'] = [
640 'label-message' =>
'table_pager_limit_label',
641 'options' => $this->getEscapedLimitSelectList(),
643 'default' => $this->mLimit
646 $formDescriptor[
'user'] = [
649 'id' =>
'mw-listfiles-user',
650 'label-message' =>
'username',
651 'default' => $this->mUserName,
653 'maxlength' =>
'255',
656 $formDescriptor[
'ilshowall'] = [
658 'name' =>
'ilshowall',
659 'id' =>
'mw-listfiles-show-all',
660 'label-message' =>
'listfiles-show-all',
661 'default' => $this->mShowAll,
664 $query = $this->getRequest()->getQueryValues();
665 unset( $query[
'title'] );
666 unset( $query[
'limit'] );
667 unset( $query[
'ilsearch'] );
668 unset( $query[
'ilshowall'] );
669 unset( $query[
'user'] );
671 HTMLForm::factory(
'ooui', $formDescriptor, $this->getContext() )
673 ->setId(
'mw-listfiles-form' )
675 ->setSubmitTextMsg(
'listfiles-pager-submit' )
676 ->setWrapperLegendMsg(
'listfiles' )
677 ->addHiddenFields( $query )