100 $this->mIncluding = $including;
101 $this->mShowAll = $showAll;
103 if ( $userName !==
null && $userName !==
'' ) {
104 $nt = Title::makeTitleSafe(
NS_USER, $userName );
105 if ( $nt ===
null ) {
108 $this->mUserName = $nt->getText();
109 $user = User::newFromName( $this->mUserName,
false );
111 $this->mUser = $user;
113 if ( !$user || ( $user->isAnon() && !$userNameUtils->
isIP( $user->getName() ) ) ) {
120 $this->
getRequest()->getText(
'sort',
'img_date' ) ===
'img_date'
129 parent::__construct( $context, $linkRenderer );
130 $this->commentStore = $commentStore;
132 $this->rowCommentFormatter = $rowCommentFormatter;
133 $this->linkBatchFactory = $linkBatchFactory;
134 $this->migrationStage = $this->
getConfig()->get(
263 return $this->getQueryInfoReal( $this->mTableName );
265 $dbr = $this->getDatabase();
266 $tables = [
'filerevision',
'file',
'actor' ];
268 'img_timestamp' =>
'fr_timestamp',
269 'img_name' =>
'file_name',
270 'img_size' =>
'fr_size',
271 'top' =>
'CASE WHEN file_latest = fr_id THEN \'yes\' ELSE \'no\' END',
274 'filerevision' => [
'JOIN',
'fr_file=file_id' ],
275 'actor' => [
'JOIN',
'actor_id=fr_actor' ]
279 $commentQuery = $this->commentStore->getJoin(
'fr_description' );
280 $tables += $commentQuery[
'tables'];
281 $fields += $commentQuery[
'fields'];
282 $join_conds += $commentQuery[
'joins'];
283 $fields[
'description_field'] = $dbr->addQuotes(
"fr_description" );
286 $fields[] =
'actor_user';
287 $fields[] =
'actor_name';
289 # Depends on $wgMiserMode
290 # Will also not happen if mShowAll is true.
291 if ( array_key_exists(
'count', $this->getFieldNames() ) ) {
292 $fields[
'count'] =
new Subquery( $dbr->newSelectQueryBuilder()
293 ->select(
'COUNT(fr_archive_name)' )
294 ->from(
'filerevision' )
295 ->where(
'fr_file = file_id' )
296 ->caller( __METHOD__ )
304 'conds' => $this->buildQueryConds(),
306 'join_conds' => $join_conds
321 $dbr = $this->getDatabase();
322 $prefix = $table ===
'oldimage' ?
'oi' :
'img';
324 $tables = [ $table,
'actor' ];
327 if ( $table ===
'oldimage' ) {
329 'img_timestamp' =>
'oi_timestamp',
330 'img_name' =>
'oi_name',
331 'img_size' =>
'oi_size',
332 'top' => $dbr->addQuotes(
'no' )
334 $join_conds[
'actor'] = [
'JOIN',
'actor_id=oi_actor' ];
340 'top' => $dbr->addQuotes(
'yes' )
342 $join_conds[
'actor'] = [
'JOIN',
'actor_id=img_actor' ];
346 $commentQuery = $this->commentStore->getJoin( $prefix .
'_description' );
347 $tables += $commentQuery[
'tables'];
348 $fields += $commentQuery[
'fields'];
349 $join_conds += $commentQuery[
'joins'];
350 $fields[
'description_field'] = $dbr->addQuotes(
"{$prefix}_description" );
353 $fields[] =
'actor_user';
354 $fields[] =
'actor_name';
356 # Depends on $wgMiserMode
357 # Will also not happen if mShowAll is true.
358 if ( array_key_exists(
'count', $this->getFieldNames() ) ) {
359 $fields[
'count'] =
new Subquery( $dbr->newSelectQueryBuilder()
360 ->select(
'COUNT(oi_archive_name)' )
362 ->where(
'oi_name = img_name' )
363 ->caller( __METHOD__ )
371 'conds' => $this->buildQueryCondsOld( $table ),
373 'join_conds' => $join_conds
379 return $this->reallyDoQueryOld( $offset, $limit, $order );
381 return parent::reallyDoQuery( $offset, $limit, $order );
394 $dbr = $this->getDatabase();
395 $prevTableName = $this->mTableName;
396 $this->mTableName =
'image';
397 [ $tables, $fields, $conds, $fname, $options, $join_conds ] =
398 $this->buildQueryInfo( $offset, $limit, $order );
399 $imageRes = $dbr->newSelectQueryBuilder()
400 ->tables( is_array( $tables ) ? $tables : [ $tables ] )
404 ->options( $options )
405 ->joinConds( $join_conds )
407 $this->mTableName = $prevTableName;
409 if ( !$this->mShowAll ) {
413 $this->mTableName =
'oldimage';
416 $oldIndex = $this->mIndexField;
417 foreach ( $this->mIndexField as &$index ) {
418 if ( !str_starts_with( $index,
'img_' ) ) {
419 throw new UnexpectedValueException(
"Expected to be sorting on an image table field" );
421 $index =
'oi_' . substr( $index, 4 );
425 [ $tables, $fields, $conds, $fname, $options, $join_conds ] =
426 $this->buildQueryInfo( $offset, $limit, $order );
427 $oldimageRes = $dbr->newSelectQueryBuilder()
428 ->tables( is_array( $tables ) ? $tables : [ $tables ] )
432 ->options( $options )
433 ->joinConds( $join_conds )
436 $this->mTableName = $prevTableName;
437 $this->mIndexField = $oldIndex;
439 return $this->combineResult( $imageRes, $oldimageRes, $limit, $order );
456 $topRes1 = $res1->fetchObject();
457 $topRes2 = $res2->fetchObject();
459 for ( $i = 0; $i < $limit && $topRes1 && $topRes2; $i++ ) {
460 if ( strcmp( $topRes1->{$this->mIndexField[0]}, $topRes2->{$this->mIndexField[0]} ) > 0 ) {
462 $resultArray[] = $topRes1;
463 $topRes1 = $res1->fetchObject();
465 $resultArray[] = $topRes2;
466 $topRes2 = $res2->fetchObject();
469 $resultArray[] = $topRes2;
470 $topRes2 = $res2->fetchObject();
472 $resultArray[] = $topRes1;
473 $topRes1 = $res1->fetchObject();
477 for ( ; $i < $limit && $topRes1; $i++ ) {
478 $resultArray[] = $topRes1;
479 $topRes1 = $res1->fetchObject();
482 for ( ; $i < $limit && $topRes2; $i++ ) {
483 $resultArray[] = $topRes2;
484 $topRes2 = $res2->fetchObject();
487 return new FakeResultWrapper( $resultArray );
507 $this->mResult->seek( 0 );
508 $batch = $this->linkBatchFactory->newLinkBatch()->setCaller( __METHOD__ );
509 $rowsWithComments = [
'img_description' => [],
'oi_description' => [],
'fr_description' => [] ];
510 foreach ( $this->mResult as $i => $row ) {
511 $batch->addUser(
new UserIdentityValue( $row->actor_user ?? 0, $row->actor_name ) );
512 $batch->add(
NS_FILE, $row->img_name );
513 $rowsWithComments[$row->description_field][$i] = $row;
518 if ( $rowsWithComments[
'img_description'] ) {
519 $this->formattedComments += $this->rowCommentFormatter->formatRows(
520 $rowsWithComments[
'img_description'],
524 if ( $rowsWithComments[
'oi_description'] ) {
525 $this->formattedComments += $this->rowCommentFormatter->formatRows(
526 $rowsWithComments[
'oi_description'],
530 if ( $rowsWithComments[
'fr_description'] ) {
531 $this->formattedComments += $this->rowCommentFormatter->formatRows(
532 $rowsWithComments[
'fr_description'],
544 $linkRenderer = $this->getLinkRenderer();
547 $opt = [
'time' =>
wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
548 $file = $this->localRepo->findFile( $this->getCurrentRow()->img_name, $opt );
551 $thumb = $file->transform( [
'width' => 180,
'height' => 360 ] );
553 return $thumb->toHtml( [
'desc-link' =>
true,
'loading' =>
'lazy' ] );
555 return $this->msg(
'thumbnail_error',
'' )->escaped();
557 return htmlspecialchars( $this->getCurrentRow()->img_name );
559 case 'img_timestamp':
561 return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ) );
563 static $imgfile =
null;
564 $imgfile ??= $this->msg(
'imgfile' )->text();
567 $filePage = Title::makeTitleSafe(
NS_FILE, $value );
569 $html = $linkRenderer->makeKnownLink(
573 $opt = [
'time' =>
wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
574 $file = $this->localRepo->findFile( $value, $opt );
576 $download = Html::element(
578 [
'href' => $file->getUrl() ],
581 $html .=
' ' . $this->msg(
'parentheses' )->rawParams( $download )->escaped();
586 if ( $this->getAuthority()->probablyCan(
'delete', $filePage ) ) {
587 $deleteMsg = $this->msg(
'listfiles-delete' )->text();
589 $delete = $linkRenderer->makeKnownLink(
590 $filePage, $deleteMsg, [], [
'action' =>
'delete' ]
592 $html .=
' ' . $this->msg(
'parentheses' )->rawParams( $delete )->escaped();
597 return htmlspecialchars( $value );
600 $userId = (int)$this->mCurrentRow->actor_user;
601 $userName = $this->mCurrentRow->actor_name;
602 return Linker::userLink( $userId, $userName )
603 . Linker::userToolLinks( $userId, $userName );
605 return htmlspecialchars( $this->getLanguage()->formatSize( (
int)$value ) );
606 case 'img_description':
607 return $this->formattedComments[$this->getResultOffset()];
610 return htmlspecialchars( $this->getLanguage()->formatNum( intval( $value ) + 1 ) );
612 return htmlspecialchars( $this->getLanguage()->formatNum( intval( $value ) ) );
616 return $this->msg(
'listfiles-latestversion-' . $value )->escaped();
618 throw new UnexpectedValueException(
"Unknown field '$field'" );
635 $formDescriptor = [];
636 $formDescriptor[
'limit'] = [
639 'label-message' =>
'table_pager_limit_label',
640 'options' => $this->getEscapedLimitSelectList(),
642 'default' => $this->mLimit
645 $formDescriptor[
'user'] = [
648 'id' =>
'mw-listfiles-user',
649 'label-message' =>
'username',
650 'default' => $this->mUserName,
652 'maxlength' =>
'255',
655 $formDescriptor[
'ilshowall'] = [
657 'name' =>
'ilshowall',
658 'id' =>
'mw-listfiles-show-all',
659 'label-message' =>
'listfiles-show-all',
660 'default' => $this->mShowAll,
663 $query = $this->getRequest()->getQueryValues();
664 unset( $query[
'title'] );
665 unset( $query[
'limit'] );
666 unset( $query[
'ilsearch'] );
667 unset( $query[
'ilshowall'] );
668 unset( $query[
'user'] );
670 HTMLForm::factory(
'ooui', $formDescriptor, $this->getContext() )
672 ->setId(
'mw-listfiles-form' )
674 ->setSubmitTextMsg(
'listfiles-pager-submit' )
675 ->setWrapperLegendMsg(
'listfiles' )
676 ->addHiddenFields( $query )