MediaWiki REL1_39
ProtectedPagesPager.php
Go to the documentation of this file.
1<?php
26
28
29 public $mConds;
30 private $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect;
31
33 private $commentStore;
34
36 private $linkBatchFactory;
37
39 private $userCache;
40
42 private $rowCommentFormatter;
43
45 private $formattedComments = [];
46
65 public function __construct(
66 IContextSource $context,
67 CommentStore $commentStore,
68 LinkBatchFactory $linkBatchFactory,
69 LinkRenderer $linkRenderer,
70 ILoadBalancer $loadBalancer,
71 RowCommentFormatter $rowCommentFormatter,
72 UserCache $userCache,
73 $conds,
74 $type,
75 $level,
76 $namespace,
77 $sizetype,
78 $size,
79 $indefonly,
80 $cascadeonly,
81 $noredirect
82 ) {
83 // Set database before parent constructor to avoid setting it there with wfGetDB
84 $this->mDb = $loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
85 parent::__construct( $context, $linkRenderer );
86 $this->commentStore = $commentStore;
87 $this->linkBatchFactory = $linkBatchFactory;
88 $this->rowCommentFormatter = $rowCommentFormatter;
89 $this->userCache = $userCache;
90 $this->mConds = $conds;
91 $this->type = $type ?: 'edit';
92 $this->level = $level;
93 $this->namespace = $namespace;
94 $this->sizetype = $sizetype;
95 $this->size = intval( $size );
96 $this->indefonly = (bool)$indefonly;
97 $this->cascadeonly = (bool)$cascadeonly;
98 $this->noredirect = (bool)$noredirect;
99 }
100
101 public function preprocessResults( $result ) {
102 # Do a link batch query
103 $lb = $this->linkBatchFactory->newLinkBatch();
104 $userids = [];
105
106 foreach ( $result as $row ) {
107 $lb->add( $row->page_namespace, $row->page_title );
108 if ( $row->actor_user !== null ) {
109 $userids[] = $row->actor_user;
110 }
111 }
112
113 // fill LinkBatch with user page and user talk
114 if ( count( $userids ) ) {
115 $this->userCache->doQuery( $userids, [], __METHOD__ );
116 foreach ( $userids as $userid ) {
117 $name = $this->userCache->getProp( $userid, 'name' );
118 if ( $name !== false ) {
119 $lb->add( NS_USER, $name );
120 $lb->add( NS_USER_TALK, $name );
121 }
122 }
123 }
124
125 $lb->execute();
126
127 // Format the comments
128 $this->formattedComments = $this->rowCommentFormatter->formatRows( $result, 'log_comment' );
129 }
130
131 protected function getFieldNames() {
132 static $headers = null;
133
134 if ( $headers == [] ) {
135 $headers = [
136 'log_timestamp' => 'protectedpages-timestamp',
137 'pr_page' => 'protectedpages-page',
138 'pr_expiry' => 'protectedpages-expiry',
139 'actor_user' => 'protectedpages-performer',
140 'pr_params' => 'protectedpages-params',
141 'log_comment' => 'protectedpages-reason',
142 ];
143 foreach ( $headers as $key => $val ) {
144 $headers[$key] = $this->msg( $val )->text();
145 }
146 }
147
148 return $headers;
149 }
150
157 public function formatValue( $field, $value ) {
159 $row = $this->mCurrentRow;
160 $linkRenderer = $this->getLinkRenderer();
161
162 switch ( $field ) {
163 case 'log_timestamp':
164 // when timestamp is null, this is a old protection row
165 if ( $value === null ) {
166 $formatted = Html::rawElement(
167 'span',
168 [ 'class' => 'mw-protectedpages-unknown' ],
169 $this->msg( 'protectedpages-unknown-timestamp' )->escaped()
170 );
171 } else {
172 $formatted = htmlspecialchars( $this->getLanguage()->userTimeAndDate(
173 $value, $this->getUser() ) );
174 }
175 break;
176
177 case 'pr_page':
178 $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
179 if ( !$title ) {
180 $formatted = Html::element(
181 'span',
182 [ 'class' => 'mw-invalidtitle' ],
184 $this->getContext(),
185 $row->page_namespace,
186 $row->page_title
187 )
188 );
189 } else {
190 $formatted = $linkRenderer->makeLink( $title );
191 }
192 if ( $row->page_len !== null ) {
193 $formatted .= $this->getLanguage()->getDirMark() .
194 ' ' . Html::rawElement(
195 'span',
196 [ 'class' => 'mw-protectedpages-length' ],
197 Linker::formatRevisionSize( $row->page_len )
198 );
199 }
200 break;
201
202 case 'pr_expiry':
203 $formatted = htmlspecialchars( $this->getLanguage()->formatExpiry(
204 $value, /* User preference timezone */true, 'infinity', $this->getUser() ) );
205 $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
206 if ( $title && $this->getAuthority()->isAllowed( 'protect' ) ) {
207 $changeProtection = $linkRenderer->makeKnownLink(
208 $title,
209 $this->msg( 'protect_change' )->text(),
210 [],
211 [ 'action' => 'unprotect' ]
212 );
213 $formatted .= ' ' . Html::rawElement(
214 'span',
215 [ 'class' => 'mw-protectedpages-actions' ],
216 $this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped()
217 );
218 }
219 break;
220
221 case 'actor_user':
222 // when timestamp is null, this is a old protection row
223 if ( $row->log_timestamp === null ) {
224 $formatted = Html::rawElement(
225 'span',
226 [ 'class' => 'mw-protectedpages-unknown' ],
227 $this->msg( 'protectedpages-unknown-performer' )->escaped()
228 );
229 } else {
230 $username = $row->actor_name;
231 if ( LogEventsList::userCanBitfield(
232 $row->log_deleted,
234 $this->getAuthority()
235 ) ) {
236 $formatted = Linker::userLink( (int)$value, $username )
237 . Linker::userToolLinks( (int)$value, $username );
238 } else {
239 $formatted = $this->msg( 'rev-deleted-user' )->escaped();
240 }
241 if ( LogEventsList::isDeleted( $row, LogPage::DELETED_USER ) ) {
242 $formatted = '<span class="history-deleted">' . $formatted . '</span>';
243 }
244 }
245 break;
246
247 case 'pr_params':
248 $params = [];
249 // Messages: restriction-level-sysop, restriction-level-autoconfirmed
250 $params[] = $this->msg( 'restriction-level-' . $row->pr_level )->escaped();
251 if ( $row->pr_cascade ) {
252 $params[] = $this->msg( 'protect-summary-cascade' )->escaped();
253 }
254 $formatted = $this->getLanguage()->commaList( $params );
255 break;
256
257 case 'log_comment':
258 // when timestamp is null, this is an old protection row
259 if ( $row->log_timestamp === null ) {
260 $formatted = Html::rawElement(
261 'span',
262 [ 'class' => 'mw-protectedpages-unknown' ],
263 $this->msg( 'protectedpages-unknown-reason' )->escaped()
264 );
265 } else {
266 if ( LogEventsList::userCanBitfield(
267 $row->log_deleted,
269 $this->getAuthority()
270 ) ) {
271 $formatted = $this->formattedComments[$this->getResultOffset()];
272 } else {
273 $formatted = $this->msg( 'rev-deleted-comment' )->escaped();
274 }
275 if ( LogEventsList::isDeleted( $row, LogPage::DELETED_COMMENT ) ) {
276 $formatted = '<span class="history-deleted">' . $formatted . '</span>';
277 }
278 }
279 break;
280
281 default:
282 throw new MWException( "Unknown field '$field'" );
283 }
284
285 return $formatted;
286 }
287
288 public function getQueryInfo() {
289 $dbr = $this->getDatabase();
290 $conds = $this->mConds;
291 $conds[] = 'pr_expiry > ' . $dbr->addQuotes( $dbr->timestamp() ) .
292 ' OR pr_expiry IS NULL';
293 $conds[] = 'page_id=pr_page';
294 $conds[] = 'pr_type=' . $dbr->addQuotes( $this->type );
295
296 if ( $this->sizetype == 'min' ) {
297 $conds[] = 'page_len>=' . $this->size;
298 } elseif ( $this->sizetype == 'max' ) {
299 $conds[] = 'page_len<=' . $this->size;
300 }
301
302 if ( $this->indefonly ) {
303 $infinity = $dbr->addQuotes( $dbr->getInfinity() );
304 $conds[] = "pr_expiry = $infinity OR pr_expiry IS NULL";
305 }
306 if ( $this->cascadeonly ) {
307 $conds[] = 'pr_cascade = 1';
308 }
309 if ( $this->noredirect ) {
310 $conds[] = 'page_is_redirect = 0';
311 }
312
313 if ( $this->level ) {
314 $conds[] = 'pr_level=' . $dbr->addQuotes( $this->level );
315 }
316 if ( $this->namespace !== null ) {
317 $conds[] = 'page_namespace=' . $dbr->addQuotes( $this->namespace );
318 }
319
320 $commentQuery = $this->commentStore->getJoin( 'log_comment' );
321
322 return [
323 'tables' => [
324 'page', 'page_restrictions', 'log_search',
325 'logparen' => [ 'logging', 'actor' ] + $commentQuery['tables'],
326 ],
327 'fields' => [
328 'pr_id',
329 'page_namespace',
330 'page_title',
331 'page_len',
332 'pr_type',
333 'pr_level',
334 'pr_expiry',
335 'pr_cascade',
336 'log_timestamp',
337 'log_deleted',
338 'actor_name',
339 'actor_user'
340 ] + $commentQuery['fields'],
341 'conds' => $conds,
342 'join_conds' => [
343 'log_search' => [
344 'LEFT JOIN', [
345 'ls_field' => 'pr_id', 'ls_value = ' . $dbr->buildStringCast( 'pr_id' )
346 ]
347 ],
348 'logparen' => [
349 'LEFT JOIN', [
350 'ls_log_id = log_id'
351 ]
352 ],
353 'actor' => [
354 'JOIN', [
355 'actor_id=log_actor'
356 ]
357 ]
358 ] + $commentQuery['joins']
359 ];
360 }
361
362 protected function getTableClass() {
363 return parent::getTableClass() . ' mw-protectedpages';
364 }
365
366 public function getIndexField() {
367 return 'pr_id';
368 }
369
370 public function getDefaultSort() {
371 return 'pr_id';
372 }
373
374 protected function isFieldSortable( $field ) {
375 // no index for sorting exists
376 return false;
377 }
378}
const NS_USER
Definition Defines.php:66
const NS_USER_TALK
Definition Defines.php:67
Handle database storage of comments such as edit summaries and log reasons.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getContext()
Get the base IContextSource object.
getDatabase()
Get the Database object in use.
static userLink( $userId, $userName, $altUserName=false)
Make user link (or user contributions for unregistered users)
Definition Linker.php:1114
static getInvalidTitleDescription(IContextSource $context, $namespace, $title)
Get a message saying that an invalid title was encountered.
Definition Linker.php:189
static formatRevisionSize( $size)
Definition Linker.php:1623
static userToolLinks( $userId, $userText, $redContribsWhenNoEdits=false, $flags=0, $edits=null, $useParentheses=true)
Generate standard user tool links (talk, contributions, block link, etc.)
Definition Linker.php:1159
const DELETED_USER
Definition LogPage.php:42
const DELETED_COMMENT
Definition LogPage.php:41
MediaWiki exception.
This is basically a CommentFormatter with a CommentStore dependency, allowing it to retrieve comment ...
Class that generates HTML anchor link elements for pages.
getTableClass()
TablePager relies on mw-datatable for styling, see T214208.
getFieldNames()
An array mapping database field names to a textual description of the field name, for use in the tabl...
preprocessResults( $result)
Pre-process results; useful for performing batch existence checks, etc.
getQueryInfo()
Provides all parameters needed for the main paged query.
formatValue( $field, $value)
getDefaultSort()
The database field name used as a default sort order.
__construct(IContextSource $context, CommentStore $commentStore, LinkBatchFactory $linkBatchFactory, LinkRenderer $linkRenderer, ILoadBalancer $loadBalancer, RowCommentFormatter $rowCommentFormatter, UserCache $userCache, $conds, $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect)
getIndexField()
Returns the name of the index field.If the pager supports multiple orders, it may return an array of ...
isFieldSortable( $field)
Return true if the named field should be sortable by the UI, false otherwise.
Table-based display with a user-selectable sort order.
stdClass $mCurrentRow
Interface for objects which can provide a MediaWiki context on request.
Create and track the database connections and transactions for a given database cluster.
getConnectionRef( $i, $groups=[], $domain=false, $flags=0)