MediaWiki master
NewFilesPager.php
Go to the documentation of this file.
1<?php
22namespace MediaWiki\Pager;
23
37
42
43 protected ?ImageGalleryBase $gallery = null;
44 protected FormOptions $opts;
45
46 private GroupPermissionsLookup $groupPermissionsLookup;
47 private LinkBatchFactory $linkBatchFactory;
48 private int $migrationStage;
49
50 public function __construct(
51 IContextSource $context,
52 GroupPermissionsLookup $groupPermissionsLookup,
53 LinkBatchFactory $linkBatchFactory,
54 LinkRenderer $linkRenderer,
55 IConnectionProvider $dbProvider,
57 ) {
58 // Set database before parent constructor to avoid setting it there
59 $this->mDb = $dbProvider->getReplicaDatabase();
60
61 parent::__construct( $context, $linkRenderer );
62
63 $this->opts = $opts;
64 $this->groupPermissionsLookup = $groupPermissionsLookup;
65 $this->linkBatchFactory = $linkBatchFactory;
66 $this->setLimit( $opts->getValue( 'limit' ) );
67
68 $startTimestamp = '';
69 $endTimestamp = '';
70 if ( $opts->getValue( 'start' ) ) {
71 $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00';
72 }
73 if ( $opts->getValue( 'end' ) ) {
74 $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59';
75 }
76 $this->getDateRangeCond( $startTimestamp, $endTimestamp );
77 $this->migrationStage = $context->getConfig()->get(
79 );
80 }
81
82 public function getQueryInfo() {
84 $conds = [];
85 $dbr = $this->getDatabase();
86 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
87 $tables = [ 'image' ];
88 $nameField = 'img_name';
89 $actorField = 'img_actor';
90 $timestampField = 'img_timestamp';
91 $jconds = [];
92
93 } else {
94 $tables = [ 'file', 'filerevision' ];
95 $nameField = 'file_name';
96 $actorField = 'fr_actor';
97 $timestampField = 'fr_timestamp';
98 $jconds = [ 'filerevision' => [ 'JOIN', 'file_latest=fr_id' ] ];
99 }
100 $tables[] = 'actor';
101 $fields = [ 'img_name' => $nameField, 'img_timestamp' => $timestampField, 'actor_user', 'actor_name' ];
102 $options = [];
103 $jconds['actor'] = [ 'JOIN', 'actor_id=' . $actorField ];
104
105 $user = $opts->getValue( 'user' );
106 if ( $user !== '' ) {
107 $conds['actor_name'] = $user;
108 }
109
110 if ( !$opts->getValue( 'showbots' ) ) {
111 $groupsWithBotPermission = $this->groupPermissionsLookup->getGroupsWithPermission( 'bot' );
112
113 if ( count( $groupsWithBotPermission ) ) {
114 $tables[] = 'user_groups';
115 $conds['ug_group'] = null;
116 $jconds['user_groups'] = [
117 'LEFT JOIN',
118 [
119 'ug_group' => $groupsWithBotPermission,
120 'ug_user = actor_user',
121 $dbr->expr( 'ug_expiry', '=', null )->or( 'ug_expiry', '>=', $dbr->timestamp() )
122 ]
123 ];
124 }
125 }
126
127 if ( $opts->getValue( 'hidepatrolled' ) ) {
128 $tables[] = 'recentchanges';
129 $conds['rc_type'] = RC_LOG;
130 $conds['rc_log_type'] = 'upload';
131 $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED;
132 $conds['rc_namespace'] = NS_FILE;
133
134 $jconds['recentchanges'] = [
135 'JOIN',
136 [
137 'rc_title = ' . $nameField,
138 'rc_actor = ' . $actorField,
139 'rc_timestamp = ' . $timestampField,
140 ]
141 ];
142 }
143
144 if ( $opts->getValue( 'mediatype' ) ) {
145 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
146 $conds['img_media_type'] = $opts->getValue( 'mediatype' );
147 } else {
148 $tables[] = 'filetypes';
149 $jconds['filetypes'] = [ 'JOIN', 'file_type = ft_id' ];
150 $conds['ft_media_type'] = $opts->getValue( 'mediatype' );
151 }
152 }
153
154 // We're ordering by img_timestamp, but MariaDB sometimes likes to query other tables first
155 // and filesort the result set later.
156 // See T124205 / https://mariadb.atlassian.net/browse/MDEV-8880, and T244533
157 // Twist: This would cause issues if the user is set and we need to check user existence first
158 if ( $user === '' ) {
159 $options[] = 'STRAIGHT_JOIN';
160 }
161
162 $query = [
163 'tables' => $tables,
164 'fields' => $fields,
165 'join_conds' => $jconds,
166 'conds' => $conds,
167 'options' => $options,
168 ];
169
170 return $query;
171 }
172
173 public function getIndexField() {
174 return [ [ 'img_timestamp', 'img_name' ] ];
175 }
176
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
192 protected function getEndBody() {
193 return $this->gallery->toHTML();
194 }
195
196 protected function doBatchLookups() {
197 $this->mResult->seek( 0 );
198 $lb = $this->linkBatchFactory->newLinkBatch();
199 foreach ( $this->mResult as $row ) {
200 if ( $row->actor_user ) {
201 $lb->add( NS_USER, $row->actor_name );
202 }
203 }
204 $lb->execute();
205 }
206
207 public function formatRow( $row ) {
208 $username = $row->actor_name;
209
210 if ( ExternalUserNames::isExternal( $username ) ) {
211 $ul = htmlspecialchars( $username );
212 } else {
213 $ul = $this->getLinkRenderer()->makeLink(
214 new TitleValue( NS_USER, $username ),
215 $username
216 );
217 }
218 $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
219
220 $this->gallery->add(
221 Title::makeTitle( NS_FILE, $row->img_name ),
222 "$ul<br />\n<i>"
223 . htmlspecialchars( $time )
224 . "</i><br />\n",
225 '',
226 '',
227 [],
228 ImageGalleryBase::LOADING_LAZY
229 );
230
231 return '';
232 }
233}
234
239class_alias( NewFilesPager::class, 'NewFilesPager' );
const NS_USER
Definition Defines.php:67
const NS_FILE
Definition Defines.php:71
const SCHEMA_COMPAT_READ_OLD
Definition Defines.php:304
const RC_LOG
Definition Defines.php:119
Class for exceptions thrown by ImageGalleryBase::factory().
getContext()
Get the base IContextSource object.
Helper class to keep track of options when mixing links and form elements.
getValue( $name)
Get the value for the given option name.
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()
getDatabase()
Get the Database object in use.
setLimit( $limit)
Set the limit from an other source than the request.
getEndBody()
Hook into getBody() for the end of the list.
__construct(IContextSource $context, GroupPermissionsLookup $groupPermissionsLookup, LinkBatchFactory $linkBatchFactory, LinkRenderer $linkRenderer, IConnectionProvider $dbProvider, FormOptions $opts)
getIndexField()
Returns the name of the index field.
doBatchLookups()
Called from getBody(), before getStartBody() is called and after doQuery() was called.
getStartBody()
Hook into getBody(), allows text to be inserted at the start.
getQueryInfo()
Provides all parameters needed for the main paged query.
formatRow( $row)
Returns an HTML string representing the result row $row.
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.
Represents the target of a wiki link.
Represents a title within MediaWiki.
Definition Title.php:78
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( $domain=false, $group=null)
Get connection to a replica database.