MediaWiki master
NewFilesPager.php
Go to the documentation of this file.
1<?php
9
24
29
30 protected ?ImageGalleryBase $gallery = null;
31
32 private int $migrationStage;
33
34 public function __construct(
35 IContextSource $context,
36 private readonly GroupPermissionsLookup $groupPermissionsLookup,
37 private readonly LinkBatchFactory $linkBatchFactory,
38 LinkRenderer $linkRenderer,
39 IConnectionProvider $dbProvider,
40 protected readonly FormOptions $opts,
41 ) {
42 // Set database before parent constructor to avoid setting it there
43 $this->mDb = $dbProvider->getReplicaDatabase();
44 $this->migrationStage = $context->getConfig()->get(
46 );
47
48 parent::__construct( $context, $linkRenderer );
49
50 $this->setLimit( $opts->getValue( 'limit' ) );
51
52 $startTimestamp = '';
53 $endTimestamp = '';
54 if ( $opts->getValue( 'start' ) ) {
55 $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00';
56 }
57 if ( $opts->getValue( 'end' ) ) {
58 $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59';
59 }
60 $this->getDateRangeCond( $startTimestamp, $endTimestamp );
61 }
62
64 public function getQueryInfo() {
65 $opts = $this->opts;
66 $conds = [];
67 $dbr = $this->getDatabase();
68 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
69 $tables = [ 'image' ];
70 $nameField = 'img_name';
71 $actorField = 'img_actor';
72 $timestampField = 'img_timestamp';
73 $fields = [
74 $nameField,
75 $timestampField,
76 'actor_user',
77 'actor_name'
78 ];
79 $jconds = [];
80
81 } else {
82 $tables = [ 'filerevision', 'file' ];
83 $nameField = 'file_name';
84 $actorField = 'fr_actor';
85 $timestampField = 'fr_timestamp';
86 $fields = [
87 $nameField,
88 $timestampField,
89 'fr_id',
90 'actor_user',
91 'actor_name'
92 ];
93 $jconds = [ 'file' => [ 'JOIN', 'file_latest=fr_id' ] ];
94 }
95 $tables[] = 'actor';
96 $options = [];
97 $jconds['actor'] = [ 'JOIN', 'actor_id=' . $actorField ];
98
99 $user = $opts->getValue( 'user' );
100 if ( $user !== '' ) {
101 $conds['actor_name'] = $user;
102 }
103
104 if ( !$opts->getValue( 'showbots' ) ) {
105 $groupsWithBotPermission = $this->groupPermissionsLookup->getGroupsWithPermission( 'bot' );
106
107 if ( count( $groupsWithBotPermission ) ) {
108 $tables[] = 'user_groups';
109 $conds['ug_group'] = null;
110 $jconds['user_groups'] = [
111 'LEFT JOIN',
112 [
113 'ug_group' => $groupsWithBotPermission,
114 'ug_user = actor_user',
115 $dbr->expr( 'ug_expiry', '=', null )->or( 'ug_expiry', '>=', $dbr->timestamp() )
116 ]
117 ];
118 }
119 }
120
121 if ( $opts->getValue( 'hidepatrolled' ) ) {
122 $tables[] = 'recentchanges';
123 $conds['rc_source'] = RecentChange::SRC_LOG;
124 $conds['rc_log_type'] = 'upload';
125 $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED;
126 $conds['rc_namespace'] = NS_FILE;
127
128 $jconds['recentchanges'] = [
129 'JOIN',
130 [
131 'rc_title = ' . $nameField,
132 'rc_actor = ' . $actorField,
133 'rc_timestamp = ' . $timestampField,
134 ]
135 ];
136 }
137
138 if ( $opts->getValue( 'mediatype' ) ) {
139 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
140 $conds['img_media_type'] = $opts->getValue( 'mediatype' );
141 } else {
142 $tables[] = 'filetypes';
143 $jconds['filetypes'] = [ 'JOIN', 'file_type = ft_id' ];
144 $conds['ft_media_type'] = $opts->getValue( 'mediatype' );
145 }
146 }
147
148 // We're ordering by img_timestamp, but MariaDB sometimes likes to query other tables first
149 // and filesort the result set later.
150 // See T124205 / https://mariadb.atlassian.net/browse/MDEV-8880, and T244533
151 // Twist: This would cause issues if the user is set and we need to check user existence first
152 if ( $user === '' ) {
153 $options[] = 'STRAIGHT_JOIN';
154 }
155
156 $query = [
157 'tables' => $tables,
158 'fields' => $fields,
159 'join_conds' => $jconds,
160 'conds' => $conds,
161 'options' => $options,
162 ];
163
164 return $query;
165 }
166
168 public function getIndexField() {
169 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
170 return [ [ 'img_timestamp', 'img_name' ] ];
171 } else {
172 return [ [ 'fr_timestamp', 'fr_id' ] ];
173 }
174 }
175
177 protected function getStartBody() {
178 if ( !$this->gallery ) {
179 // Note that null for mode is taken to mean use default.
180 $mode = $this->getRequest()->getVal( 'gallerymode', null );
181 try {
182 $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
184 // User specified something invalid, fallback to default.
185 $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
186 }
187 }
188
189 return '';
190 }
191
193 protected function getEndBody() {
194 return $this->gallery->toHTML();
195 }
196
198 protected function doBatchLookups() {
199 $this->mResult->seek( 0 );
200 $lb = $this->linkBatchFactory->newLinkBatch()->setCaller( __METHOD__ );
201 foreach ( $this->mResult as $row ) {
202 if ( $row->actor_user ) {
203 $lb->add( NS_USER, $row->actor_name );
204 }
205 }
206 $lb->execute();
207 }
208
210 public function formatRow( $row ) {
211 $username = $row->actor_name;
212
213 if ( ExternalUserNames::isExternal( $username ) ) {
214 $ul = htmlspecialchars( $username );
215 } else {
216 $ul = $this->getLinkRenderer()->makeLink(
217 new TitleValue( NS_USER, $username ),
218 $username
219 );
220 }
221
222 $timestamp = $this->migrationStage & SCHEMA_COMPAT_READ_OLD ? $row->img_timestamp : $row->fr_timestamp;
223 $time = $this->getLanguage()->userTimeAndDate( $timestamp, $this->getUser() );
224
225 $fileName = $this->migrationStage & SCHEMA_COMPAT_READ_OLD ? $row->img_name : $row->file_name;
226 $this->gallery->add(
227 Title::makeTitle( NS_FILE, $fileName ),
228 "$ul<br />\n<i>"
229 . htmlspecialchars( $time )
230 . "</i><br />\n",
231 '',
232 '',
233 [],
234 ImageGalleryBase::LOADING_LAZY
235 );
236
237 return '';
238 }
239}
240
245class_alias( NewFilesPager::class, 'NewFilesPager' );
246
248class_alias( NewFilesPager::class, 'MediaWiki\\Pager\\NewFilesPager' );
const NS_USER
Definition Defines.php:53
const NS_FILE
Definition Defines.php:57
const SCHEMA_COMPAT_READ_OLD
Definition Defines.php:294
getContext()
Get the base IContextSource object.
makeTitle( $linkId)
Convert a link ID to a Title.to override Title
Class for exceptions thrown by ImageGalleryBase::factory().
Helper class to keep track of options when mixing links and form elements.
Class that generates HTML for internal links.
A class containing constants representing the names of configuration variables.
const FileSchemaMigrationStage
Name constant for the FileSchemaMigrationStage setting, for use with Config::get()
Factory for LinkBatch objects to batch query page metadata.
getDatabase()
Get the Database object in use.
setLimit( $limit)
Set the limit from an other source than the request.
Pager for filtering by a range of dates.
getDateRangeCond( $startTime, $endTime)
Set and return a date range condition using timestamps provided by the user.
Utility class for creating and reading rows in the recentchanges table.
formatRow( $row)
Returns an HTML string representing the result row $row.Rows will be concatenated and returned by get...
doBatchLookups()
Called from getBody(), before getStartBody() is called and after doQuery() was called....
getIndexField()
Returns the name of the index field.If the pager supports multiple orders, it may return an array of ...
getEndBody()
Hook into getBody() for the end of the list.to overridestring
getStartBody()
Hook into getBody(), allows text to be inserted at the start.This will be called even if there are no...
__construct(IContextSource $context, private readonly GroupPermissionsLookup $groupPermissionsLookup, private readonly LinkBatchFactory $linkBatchFactory, LinkRenderer $linkRenderer, IConnectionProvider $dbProvider, protected readonly FormOptions $opts,)
getQueryInfo()
Provides all parameters needed for the main paged query.It returns an associative array with the foll...
Represents the target of a wiki link.
Represents a title within MediaWiki.
Definition Title.php:69
Class to parse and build external user names.
Interface for objects which can provide a MediaWiki context on request.
getConfig()
Get the site configuration.
Provide primary and replica IDatabase connections.
getReplicaDatabase(string|false $domain=false, $group=null)
Get connection to a replica database.