MediaWiki master
NewFilesPager.php
Go to the documentation of this file.
1<?php
9
10use MediaWiki\Cache\LinkBatchFactory;
24
29
30 protected ?ImageGalleryBase $gallery = null;
31 protected FormOptions $opts;
32
33 private GroupPermissionsLookup $groupPermissionsLookup;
34 private LinkBatchFactory $linkBatchFactory;
35 private int $migrationStage;
36
37 public function __construct(
38 IContextSource $context,
39 GroupPermissionsLookup $groupPermissionsLookup,
40 LinkBatchFactory $linkBatchFactory,
41 LinkRenderer $linkRenderer,
42 IConnectionProvider $dbProvider,
44 ) {
45 // Set database before parent constructor to avoid setting it there
46 $this->mDb = $dbProvider->getReplicaDatabase();
47
48 parent::__construct( $context, $linkRenderer );
49
50 $this->opts = $opts;
51 $this->groupPermissionsLookup = $groupPermissionsLookup;
52 $this->linkBatchFactory = $linkBatchFactory;
53 $this->setLimit( $opts->getValue( 'limit' ) );
54
55 $startTimestamp = '';
56 $endTimestamp = '';
57 if ( $opts->getValue( 'start' ) ) {
58 $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00';
59 }
60 if ( $opts->getValue( 'end' ) ) {
61 $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59';
62 }
63 $this->getDateRangeCond( $startTimestamp, $endTimestamp );
64 $this->migrationStage = $context->getConfig()->get(
66 );
67 }
68
70 public function getQueryInfo() {
72 $conds = [];
73 $dbr = $this->getDatabase();
74 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
75 $tables = [ 'image' ];
76 $nameField = 'img_name';
77 $actorField = 'img_actor';
78 $timestampField = 'img_timestamp';
79 $jconds = [];
80
81 } else {
82 $tables = [ 'file', 'filerevision' ];
83 $nameField = 'file_name';
84 $actorField = 'fr_actor';
85 $timestampField = 'fr_timestamp';
86 $jconds = [ 'filerevision' => [ 'JOIN', 'file_latest=fr_id' ] ];
87 }
88 $tables[] = 'actor';
89 $fields = [ 'img_name' => $nameField, 'img_timestamp' => $timestampField, 'actor_user', 'actor_name' ];
90 $options = [];
91 $jconds['actor'] = [ 'JOIN', 'actor_id=' . $actorField ];
92
93 $user = $opts->getValue( 'user' );
94 if ( $user !== '' ) {
95 $conds['actor_name'] = $user;
96 }
97
98 if ( !$opts->getValue( 'showbots' ) ) {
99 $groupsWithBotPermission = $this->groupPermissionsLookup->getGroupsWithPermission( 'bot' );
100
101 if ( count( $groupsWithBotPermission ) ) {
102 $tables[] = 'user_groups';
103 $conds['ug_group'] = null;
104 $jconds['user_groups'] = [
105 'LEFT JOIN',
106 [
107 'ug_group' => $groupsWithBotPermission,
108 'ug_user = actor_user',
109 $dbr->expr( 'ug_expiry', '=', null )->or( 'ug_expiry', '>=', $dbr->timestamp() )
110 ]
111 ];
112 }
113 }
114
115 if ( $opts->getValue( 'hidepatrolled' ) ) {
116 $tables[] = 'recentchanges';
117 $conds['rc_source'] = RecentChange::SRC_LOG;
118 $conds['rc_log_type'] = 'upload';
119 $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED;
120 $conds['rc_namespace'] = NS_FILE;
121
122 $jconds['recentchanges'] = [
123 'JOIN',
124 [
125 'rc_title = ' . $nameField,
126 'rc_actor = ' . $actorField,
127 'rc_timestamp = ' . $timestampField,
128 ]
129 ];
130 }
131
132 if ( $opts->getValue( 'mediatype' ) ) {
133 if ( $this->migrationStage & SCHEMA_COMPAT_READ_OLD ) {
134 $conds['img_media_type'] = $opts->getValue( 'mediatype' );
135 } else {
136 $tables[] = 'filetypes';
137 $jconds['filetypes'] = [ 'JOIN', 'file_type = ft_id' ];
138 $conds['ft_media_type'] = $opts->getValue( 'mediatype' );
139 }
140 }
141
142 // We're ordering by img_timestamp, but MariaDB sometimes likes to query other tables first
143 // and filesort the result set later.
144 // See T124205 / https://mariadb.atlassian.net/browse/MDEV-8880, and T244533
145 // Twist: This would cause issues if the user is set and we need to check user existence first
146 if ( $user === '' ) {
147 $options[] = 'STRAIGHT_JOIN';
148 }
149
150 $query = [
151 'tables' => $tables,
152 'fields' => $fields,
153 'join_conds' => $jconds,
154 'conds' => $conds,
155 'options' => $options,
156 ];
157
158 return $query;
159 }
160
162 public function getIndexField() {
163 return [ [ 'img_timestamp', 'img_name' ] ];
164 }
165
167 protected function getStartBody() {
168 if ( !$this->gallery ) {
169 // Note that null for mode is taken to mean use default.
170 $mode = $this->getRequest()->getVal( 'gallerymode', null );
171 try {
172 $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
174 // User specified something invalid, fallback to default.
175 $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
176 }
177 }
178
179 return '';
180 }
181
183 protected function getEndBody() {
184 return $this->gallery->toHTML();
185 }
186
188 protected function doBatchLookups() {
189 $this->mResult->seek( 0 );
190 $lb = $this->linkBatchFactory->newLinkBatch()->setCaller( __METHOD__ );
191 foreach ( $this->mResult as $row ) {
192 if ( $row->actor_user ) {
193 $lb->add( NS_USER, $row->actor_name );
194 }
195 }
196 $lb->execute();
197 }
198
200 public function formatRow( $row ) {
201 $username = $row->actor_name;
202
203 if ( ExternalUserNames::isExternal( $username ) ) {
204 $ul = htmlspecialchars( $username );
205 } else {
206 $ul = $this->getLinkRenderer()->makeLink(
207 new TitleValue( NS_USER, $username ),
208 $username
209 );
210 }
211 $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
212
213 $this->gallery->add(
214 Title::makeTitle( NS_FILE, $row->img_name ),
215 "$ul<br />\n<i>"
216 . htmlspecialchars( $time )
217 . "</i><br />\n",
218 '',
219 '',
220 [],
221 ImageGalleryBase::LOADING_LAZY
222 );
223
224 return '';
225 }
226}
227
232class_alias( NewFilesPager::class, 'NewFilesPager' );
233
235class_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.
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.
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...
getQueryInfo()
Provides all parameters needed for the main paged query.It returns an associative array with the foll...
__construct(IContextSource $context, GroupPermissionsLookup $groupPermissionsLookup, LinkBatchFactory $linkBatchFactory, LinkRenderer $linkRenderer, IConnectionProvider $dbProvider, FormOptions $opts)
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.