MediaWiki  master
NewFilesPager.php
Go to the documentation of this file.
1 <?php
22 namespace MediaWiki\Pager;
23 
24 use IContextSource;
34 use RecentChange;
36 
41 
45  protected $gallery;
46 
50  protected $opts;
51 
52  private GroupPermissionsLookup $groupPermissionsLookup;
53  private LinkBatchFactory $linkBatchFactory;
54 
63  public function __construct(
64  IContextSource $context,
65  GroupPermissionsLookup $groupPermissionsLookup,
66  LinkBatchFactory $linkBatchFactory,
67  LinkRenderer $linkRenderer,
68  IConnectionProvider $dbProvider,
70  ) {
71  // Set database before parent constructor to avoid setting it there with wfGetDB
72  $this->mDb = $dbProvider->getReplicaDatabase();
73 
74  parent::__construct( $context, $linkRenderer );
75 
76  $this->opts = $opts;
77  $this->groupPermissionsLookup = $groupPermissionsLookup;
78  $this->linkBatchFactory = $linkBatchFactory;
79  $this->setLimit( $opts->getValue( 'limit' ) );
80 
81  $startTimestamp = '';
82  $endTimestamp = '';
83  if ( $opts->getValue( 'start' ) ) {
84  $startTimestamp = $opts->getValue( 'start' ) . ' 00:00:00';
85  }
86  if ( $opts->getValue( 'end' ) ) {
87  $endTimestamp = $opts->getValue( 'end' ) . ' 23:59:59';
88  }
89  $this->getDateRangeCond( $startTimestamp, $endTimestamp );
90  }
91 
92  public function getQueryInfo() {
94  $conds = [];
95  $dbr = $this->getDatabase();
96  $tables = [ 'image', 'actor' ];
97  $fields = [ 'img_name', 'img_timestamp', 'actor_user', 'actor_name' ];
98  $options = [];
99  $jconds = [ 'actor' => [ 'JOIN', 'actor_id=img_actor' ] ];
100 
101  $user = $opts->getValue( 'user' );
102  if ( $user !== '' ) {
103  $conds['actor_name'] = $user;
104  }
105 
106  if ( !$opts->getValue( 'showbots' ) ) {
107  $groupsWithBotPermission = $this->groupPermissionsLookup->getGroupsWithPermission( 'bot' );
108 
109  if ( count( $groupsWithBotPermission ) ) {
110  $tables[] = 'user_groups';
111  $conds['ug_group'] = null;
112  $jconds['user_groups'] = [
113  'LEFT JOIN',
114  [
115  'ug_group' => $groupsWithBotPermission,
116  'ug_user = actor_user',
117  'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() )
118  ]
119  ];
120  }
121  }
122 
123  if ( $opts->getValue( 'hidepatrolled' ) ) {
124  $tables[] = 'recentchanges';
125  $conds['rc_type'] = RC_LOG;
126  $conds['rc_log_type'] = 'upload';
127  $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED;
128  $conds['rc_namespace'] = NS_FILE;
129 
130  $jconds['recentchanges'] = [
131  'JOIN',
132  [
133  'rc_title = img_name',
134  'rc_actor = img_actor',
135  'rc_timestamp = img_timestamp'
136  ]
137  ];
138  }
139 
140  if ( $opts->getValue( 'mediatype' ) ) {
141  $conds['img_media_type'] = $opts->getValue( 'mediatype' );
142  }
143 
144  // We're ordering by img_timestamp, but MariaDB sometimes likes to query other tables first
145  // and filesort the result set later.
146  // See T124205 / https://mariadb.atlassian.net/browse/MDEV-8880, and T244533
147  // Twist: This would cause issues if the user is set and we need to check user existence first
148  if ( $user === '' ) {
149  $options[] = 'STRAIGHT_JOIN';
150  }
151 
152  $query = [
153  'tables' => $tables,
154  'fields' => $fields,
155  'join_conds' => $jconds,
156  'conds' => $conds,
157  'options' => $options,
158  ];
159 
160  return $query;
161  }
162 
163  public function getIndexField() {
164  return [ [ 'img_timestamp', 'img_name' ] ];
165  }
166 
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() );
173  } catch ( ImageGalleryClassNotFoundException $e ) {
174  // User specified something invalid, fallback to default.
175  $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
176  }
177  }
178 
179  return '';
180  }
181 
182  protected function getEndBody() {
183  return $this->gallery->toHTML();
184  }
185 
186  protected function doBatchLookups() {
187  $this->mResult->seek( 0 );
188  $lb = $this->linkBatchFactory->newLinkBatch();
189  foreach ( $this->mResult as $row ) {
190  if ( $row->actor_user ) {
191  $lb->add( NS_USER, $row->actor_name );
192  }
193  }
194  $lb->execute();
195  }
196 
197  public function formatRow( $row ) {
198  $username = $row->actor_name;
199 
200  if ( ExternalUserNames::isExternal( $username ) ) {
201  $ul = htmlspecialchars( $username );
202  } else {
203  $ul = $this->getLinkRenderer()->makeLink(
204  new TitleValue( NS_USER, $username ),
205  $username
206  );
207  }
208  $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
209 
210  $this->gallery->add(
211  Title::makeTitle( NS_FILE, $row->img_name ),
212  "$ul<br />\n<i>"
213  . htmlspecialchars( $time )
214  . "</i><br />\n",
215  '',
216  '',
217  [],
219  );
220 
221  return '';
222  }
223 }
224 
229 class_alias( NewFilesPager::class, 'NewFilesPager' );
const NS_USER
Definition: Defines.php:66
const NS_FILE
Definition: Defines.php:70
const RC_LOG
Definition: Defines.php:118
getContext()
Get the base IContextSource object.
Image gallery.
static factory( $mode=false, IContextSource $context=null)
Get a new image gallery.
Class for exceptions thrown by ImageGalleryBase::factory().
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:41
getValue( $name)
Get the value for the given option name.
Class that generates HTML for internal links.
getDatabase()
Get the Database object in use.
Definition: IndexPager.php:256
setLimit( $limit)
Set the limit from an other source than the request.
Definition: IndexPager.php:343
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.
Represents the target of a wiki link.
Definition: TitleValue.php:44
Represents a title within MediaWiki.
Definition: Title.php:76
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:624
Class to parse and build external user names.
static isExternal( $username)
Tells whether the username is external or not.
Utility class for creating new RC entries.
const PRC_UNPATROLLED
Interface for objects which can provide a MediaWiki context on request.
Provide primary and replica IDatabase connections.
getReplicaDatabase( $domain=false, $group=null)
Get connection to a replica database.