MediaWiki  master
ProtectedPagesPager.php
Go to the documentation of this file.
1 <?php
30 
32 
33  public $mConds;
35 
37  private $commentStore;
38 
40  private $linkBatchFactory;
41 
43  private $userCache;
44 
46  private $rowCommentFormatter;
47 
49  private $formattedComments = [];
50 
69  public function __construct(
70  IContextSource $context,
71  CommentStore $commentStore,
72  LinkBatchFactory $linkBatchFactory,
73  LinkRenderer $linkRenderer,
74  IConnectionProvider $dbProvider,
75  RowCommentFormatter $rowCommentFormatter,
76  UserCache $userCache,
77  $conds,
78  $type,
79  $level,
80  $namespace,
81  $sizetype,
82  $size,
83  $indefonly,
86  ) {
87  // Set database before parent constructor to avoid setting it there with wfGetDB
88  $this->mDb = $dbProvider->getReplicaDatabase();
89  parent::__construct( $context, $linkRenderer );
90  $this->commentStore = $commentStore;
91  $this->linkBatchFactory = $linkBatchFactory;
92  $this->rowCommentFormatter = $rowCommentFormatter;
93  $this->userCache = $userCache;
94  $this->mConds = $conds;
95  $this->type = $type ?: 'edit';
96  $this->level = $level;
97  $this->namespace = $namespace;
98  $this->sizetype = $sizetype;
99  $this->size = intval( $size );
100  $this->indefonly = (bool)$indefonly;
101  $this->cascadeonly = (bool)$cascadeonly;
102  $this->noredirect = (bool)$noredirect;
103  }
104 
105  public function preprocessResults( $result ) {
106  # Do a link batch query
107  $lb = $this->linkBatchFactory->newLinkBatch();
108  $userids = [];
109 
110  foreach ( $result as $row ) {
111  $lb->add( $row->page_namespace, $row->page_title );
112  if ( $row->actor_user !== null ) {
113  $userids[] = $row->actor_user;
114  }
115  }
116 
117  // fill LinkBatch with user page and user talk
118  if ( count( $userids ) ) {
119  $this->userCache->doQuery( $userids, [], __METHOD__ );
120  foreach ( $userids as $userid ) {
121  $name = $this->userCache->getProp( $userid, 'name' );
122  if ( $name !== false ) {
123  $lb->add( NS_USER, $name );
124  $lb->add( NS_USER_TALK, $name );
125  }
126  }
127  }
128 
129  $lb->execute();
130 
131  // Format the comments
132  $this->formattedComments = $this->rowCommentFormatter->formatRows( $result, 'log_comment' );
133  }
134 
135  protected function getFieldNames() {
136  static $headers = null;
137 
138  if ( $headers == [] ) {
139  $headers = [
140  'log_timestamp' => 'protectedpages-timestamp',
141  'pr_page' => 'protectedpages-page',
142  'pr_expiry' => 'protectedpages-expiry',
143  'actor_user' => 'protectedpages-performer',
144  'pr_params' => 'protectedpages-params',
145  'log_comment' => 'protectedpages-reason',
146  ];
147  foreach ( $headers as $key => $val ) {
148  $headers[$key] = $this->msg( $val )->text();
149  }
150  }
151 
152  return $headers;
153  }
154 
161  public function formatValue( $field, $value ) {
163  $row = $this->mCurrentRow;
164  $linkRenderer = $this->getLinkRenderer();
165 
166  switch ( $field ) {
167  case 'log_timestamp':
168  // when timestamp is null, this is a old protection row
169  if ( $value === null ) {
170  $formatted = Html::rawElement(
171  'span',
172  [ 'class' => 'mw-protectedpages-unknown' ],
173  $this->msg( 'protectedpages-unknown-timestamp' )->escaped()
174  );
175  } else {
176  $formatted = htmlspecialchars( $this->getLanguage()->userTimeAndDate(
177  $value, $this->getUser() ) );
178  }
179  break;
180 
181  case 'pr_page':
182  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
183  if ( !$title ) {
184  $formatted = Html::element(
185  'span',
186  [ 'class' => 'mw-invalidtitle' ],
187  Linker::getInvalidTitleDescription(
188  $this->getContext(),
189  $row->page_namespace,
190  $row->page_title
191  )
192  );
193  } else {
194  $formatted = $linkRenderer->makeLink( $title );
195  }
196  if ( $row->page_len !== null ) {
197  $formatted .= $this->getLanguage()->getDirMark() .
198  ' ' . Html::rawElement(
199  'span',
200  [ 'class' => 'mw-protectedpages-length' ],
201  Linker::formatRevisionSize( $row->page_len )
202  );
203  }
204  break;
205 
206  case 'pr_expiry':
207  $formatted = htmlspecialchars( $this->getLanguage()->formatExpiry(
208  $value, /* User preference timezone */true, 'infinity', $this->getUser() ) );
209  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
210  if ( $title && $this->getAuthority()->isAllowed( 'protect' ) ) {
211  $changeProtection = $linkRenderer->makeKnownLink(
212  $title,
213  $this->msg( 'protect_change' )->text(),
214  [],
215  [ 'action' => 'unprotect' ]
216  );
217  $formatted .= ' ' . Html::rawElement(
218  'span',
219  [ 'class' => 'mw-protectedpages-actions' ],
220  $this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped()
221  );
222  }
223  break;
224 
225  case 'actor_user':
226  // when timestamp is null, this is a old protection row
227  if ( $row->log_timestamp === null ) {
228  $formatted = Html::rawElement(
229  'span',
230  [ 'class' => 'mw-protectedpages-unknown' ],
231  $this->msg( 'protectedpages-unknown-performer' )->escaped()
232  );
233  } else {
234  $username = $row->actor_name;
236  $row->log_deleted,
238  $this->getAuthority()
239  ) ) {
240  $formatted = Linker::userLink( (int)$value, $username )
241  . Linker::userToolLinks( (int)$value, $username );
242  } else {
243  $formatted = $this->msg( 'rev-deleted-user' )->escaped();
244  }
246  $formatted = '<span class="history-deleted">' . $formatted . '</span>';
247  }
248  }
249  break;
250 
251  case 'pr_params':
252  $params = [];
253  // Messages: restriction-level-sysop, restriction-level-autoconfirmed
254  $params[] = $this->msg( 'restriction-level-' . $row->pr_level )->escaped();
255  if ( $row->pr_cascade ) {
256  $params[] = $this->msg( 'protect-summary-cascade' )->escaped();
257  }
258  $formatted = $this->getLanguage()->commaList( $params );
259  break;
260 
261  case 'log_comment':
262  // when timestamp is null, this is an old protection row
263  if ( $row->log_timestamp === null ) {
264  $formatted = Html::rawElement(
265  'span',
266  [ 'class' => 'mw-protectedpages-unknown' ],
267  $this->msg( 'protectedpages-unknown-reason' )->escaped()
268  );
269  } else {
271  $row->log_deleted,
273  $this->getAuthority()
274  ) ) {
275  $formatted = $this->formattedComments[$this->getResultOffset()];
276  } else {
277  $formatted = $this->msg( 'rev-deleted-comment' )->escaped();
278  }
280  $formatted = '<span class="history-deleted">' . $formatted . '</span>';
281  }
282  }
283  break;
284 
285  default:
286  throw new MWException( "Unknown field '$field'" );
287  }
288 
289  return $formatted;
290  }
291 
292  public function getQueryInfo() {
293  $dbr = $this->getDatabase();
294  $conds = $this->mConds;
295  $conds[] = 'pr_expiry > ' . $dbr->addQuotes( $dbr->timestamp() ) .
296  ' OR pr_expiry IS NULL';
297  $conds[] = 'page_id=pr_page';
298  $conds[] = 'pr_type=' . $dbr->addQuotes( $this->type );
299 
300  if ( $this->sizetype == 'min' ) {
301  $conds[] = 'page_len>=' . $this->size;
302  } elseif ( $this->sizetype == 'max' ) {
303  $conds[] = 'page_len<=' . $this->size;
304  }
305 
306  if ( $this->indefonly ) {
307  $infinity = $dbr->addQuotes( $dbr->getInfinity() );
308  $conds[] = "pr_expiry = $infinity OR pr_expiry IS NULL";
309  }
310  if ( $this->cascadeonly ) {
311  $conds[] = 'pr_cascade = 1';
312  }
313  if ( $this->noredirect ) {
314  $conds[] = 'page_is_redirect = 0';
315  }
316 
317  if ( $this->level ) {
318  $conds[] = 'pr_level=' . $dbr->addQuotes( $this->level );
319  }
320  if ( $this->namespace !== null ) {
321  $conds[] = 'page_namespace=' . $dbr->addQuotes( $this->namespace );
322  }
323 
324  $commentQuery = $this->commentStore->getJoin( 'log_comment' );
325 
326  return [
327  'tables' => [
328  'page', 'page_restrictions', 'log_search',
329  'logparen' => [ 'logging', 'actor' ] + $commentQuery['tables'],
330  ],
331  'fields' => [
332  'pr_id',
333  'page_namespace',
334  'page_title',
335  'page_len',
336  'pr_type',
337  'pr_level',
338  'pr_expiry',
339  'pr_cascade',
340  'log_timestamp',
341  'log_deleted',
342  'actor_name',
343  'actor_user'
344  ] + $commentQuery['fields'],
345  'conds' => $conds,
346  'join_conds' => [
347  'log_search' => [
348  'LEFT JOIN', [
349  'ls_field' => 'pr_id', 'ls_value = ' . $dbr->buildStringCast( 'pr_id' )
350  ]
351  ],
352  'logparen' => [
353  'LEFT JOIN', [
354  'ls_log_id = log_id'
355  ]
356  ],
357  'actor' => [
358  'JOIN', [
359  'actor_id=log_actor'
360  ]
361  ]
362  ] + $commentQuery['joins']
363  ];
364  }
365 
366  protected function getTableClass() {
367  return parent::getTableClass() . ' mw-protectedpages';
368  }
369 
370  public function getIndexField() {
371  return 'pr_id';
372  }
373 
374  public function getDefaultSort() {
375  return 'pr_id';
376  }
377 
378  protected function isFieldSortable( $field ) {
379  // no index for sorting exists
380  return false;
381  }
382 }
const NS_USER
Definition: Defines.php:66
const NS_USER_TALK
Definition: Defines.php:67
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.
Definition: IndexPager.php:248
static userCanBitfield( $bitfield, $field, Authority $performer)
Determine if the current user is allowed to view a particular field of this log row,...
static isDeleted( $row, $field)
const DELETED_USER
Definition: LogPage.php:44
const DELETED_COMMENT
Definition: LogPage.php:43
MediaWiki exception.
Definition: MWException.php:32
This is basically a CommentFormatter with a CommentStore dependency, allowing it to retrieve comment ...
Handle database storage of comments such as edit summaries and log reasons.
This class is a collection of static functions that serve two purposes:
Definition: Html.php:55
Class that generates HTML for internal links.
Some internal bits split of from Skin.php.
Definition: Linker.php:67
Represents a title within MediaWiki.
Definition: Title.php:82
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, IConnectionProvider $dbProvider, 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.
Definition: TablePager.php:30
stdClass $mCurrentRow
Definition: TablePager.php:35
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.