MediaWiki  master
ProtectedPagesPager.php
Go to the documentation of this file.
1 <?php
25 
27 
28  public $mConds;
30 
33 
35  private $commentStore;
36 
38  private $actorMigration;
39 
41  private $userCache;
42 
61  public function __construct(
62  $form,
63  $conds,
64  $type,
65  $level,
66  $namespace,
67  $sizetype,
68  $size,
69  $indefonly,
74  ILoadBalancer $loadBalancer,
78  ) {
79  // Set database before parent constructor to avoid setting it there with wfGetDB
80  $this->mDb = $loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
81  parent::__construct( $form->getContext(), $linkRenderer );
82  $this->mConds = $conds;
83  $this->type = $type ?: 'edit';
84  $this->level = $level;
85  $this->namespace = $namespace;
86  $this->sizetype = $sizetype;
87  $this->size = intval( $size );
88  $this->indefonly = (bool)$indefonly;
89  $this->cascadeonly = (bool)$cascadeonly;
90  $this->noredirect = (bool)$noredirect;
91  $this->linkBatchFactory = $linkBatchFactory;
92  $this->commentStore = $commentStore;
93  $this->actorMigration = $actorMigration;
94  $this->userCache = $userCache;
95  }
96 
97  public function preprocessResults( $result ) {
98  # Do a link batch query
99  $lb = $this->linkBatchFactory->newLinkBatch();
100  $userids = [];
101 
102  foreach ( $result as $row ) {
103  $lb->add( $row->page_namespace, $row->page_title );
104  // field is nullable, maybe null on old protections
105  if ( $row->log_user !== null ) {
106  $userids[] = $row->log_user;
107  }
108  }
109 
110  // fill LinkBatch with user page and user talk
111  if ( count( $userids ) ) {
112  $this->userCache->doQuery( $userids, [], __METHOD__ );
113  foreach ( $userids as $userid ) {
114  $name = $this->userCache->getProp( $userid, 'name' );
115  if ( $name !== false ) {
116  $lb->add( NS_USER, $name );
117  $lb->add( NS_USER_TALK, $name );
118  }
119  }
120  }
121 
122  $lb->execute();
123  }
124 
125  protected function getFieldNames() {
126  static $headers = null;
127 
128  if ( $headers == [] ) {
129  $headers = [
130  'log_timestamp' => 'protectedpages-timestamp',
131  'pr_page' => 'protectedpages-page',
132  'pr_expiry' => 'protectedpages-expiry',
133  'log_user' => 'protectedpages-performer',
134  'pr_params' => 'protectedpages-params',
135  'log_comment' => 'protectedpages-reason',
136  ];
137  foreach ( $headers as $key => $val ) {
138  $headers[$key] = $this->msg( $val )->text();
139  }
140  }
141 
142  return $headers;
143  }
144 
151  public function formatValue( $field, $value ) {
153  $row = $this->mCurrentRow;
154  $linkRenderer = $this->getLinkRenderer();
155 
156  switch ( $field ) {
157  case 'log_timestamp':
158  // when timestamp is null, this is a old protection row
159  if ( $value === null ) {
160  $formatted = Html::rawElement(
161  'span',
162  [ 'class' => 'mw-protectedpages-unknown' ],
163  $this->msg( 'protectedpages-unknown-timestamp' )->escaped()
164  );
165  } else {
166  $formatted = htmlspecialchars( $this->getLanguage()->userTimeAndDate(
167  $value, $this->getUser() ) );
168  }
169  break;
170 
171  case 'pr_page':
172  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
173  if ( !$title ) {
174  $formatted = Html::element(
175  'span',
176  [ 'class' => 'mw-invalidtitle' ],
178  $this->getContext(),
179  $row->page_namespace,
180  $row->page_title
181  )
182  );
183  } else {
184  $formatted = $linkRenderer->makeLink( $title );
185  }
186  if ( $row->page_len !== null ) {
187  $formatted .= $this->getLanguage()->getDirMark() .
188  ' ' . Html::rawElement(
189  'span',
190  [ 'class' => 'mw-protectedpages-length' ],
191  Linker::formatRevisionSize( $row->page_len )
192  );
193  }
194  break;
195 
196  case 'pr_expiry':
197  $formatted = htmlspecialchars( $this->getLanguage()->formatExpiry(
198  $value, /* User preference timezone */true ) );
199  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
200  if ( $title && $this->getAuthority()->isAllowed( 'protect' ) ) {
201  $changeProtection = $linkRenderer->makeKnownLink(
202  $title,
203  $this->msg( 'protect_change' )->text(),
204  [],
205  [ 'action' => 'unprotect' ]
206  );
207  $formatted .= ' ' . Html::rawElement(
208  'span',
209  [ 'class' => 'mw-protectedpages-actions' ],
210  $this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped()
211  );
212  }
213  break;
214 
215  case 'log_user':
216  // when timestamp is null, this is a old protection row
217  if ( $row->log_timestamp === null ) {
218  $formatted = Html::rawElement(
219  'span',
220  [ 'class' => 'mw-protectedpages-unknown' ],
221  $this->msg( 'protectedpages-unknown-performer' )->escaped()
222  );
223  } else {
224  $username = $this->userCache->getProp( $value, 'name' );
226  $row->log_deleted,
228  $this->getUser()
229  ) ) {
230  if ( $username === false ) {
231  $formatted = htmlspecialchars( $value );
232  } else {
233  $formatted = Linker::userLink( $value, $username )
234  . Linker::userToolLinks( $value, $username );
235  }
236  } else {
237  $formatted = $this->msg( 'rev-deleted-user' )->escaped();
238  }
240  $formatted = '<span class="history-deleted">' . $formatted . '</span>';
241  }
242  }
243  break;
244 
245  case 'pr_params':
246  $params = [];
247  // Messages: restriction-level-sysop, restriction-level-autoconfirmed
248  $params[] = $this->msg( 'restriction-level-' . $row->pr_level )->escaped();
249  if ( $row->pr_cascade ) {
250  $params[] = $this->msg( 'protect-summary-cascade' )->escaped();
251  }
252  $formatted = $this->getLanguage()->commaList( $params );
253  break;
254 
255  case 'log_comment':
256  // when timestamp is null, this is an old protection row
257  if ( $row->log_timestamp === null ) {
258  $formatted = Html::rawElement(
259  'span',
260  [ 'class' => 'mw-protectedpages-unknown' ],
261  $this->msg( 'protectedpages-unknown-reason' )->escaped()
262  );
263  } else {
265  $row->log_deleted,
267  $this->getUser()
268  ) ) {
269  $value = $this->commentStore->getComment( 'log_comment', $row )->text;
270  $formatted = Linker::formatComment( $value ?? '' );
271  } else {
272  $formatted = $this->msg( 'rev-deleted-comment' )->escaped();
273  }
275  $formatted = '<span class="history-deleted">' . $formatted . '</span>';
276  }
277  }
278  break;
279 
280  default:
281  throw new MWException( "Unknown field '$field'" );
282  }
283 
284  return $formatted;
285  }
286 
287  public function getQueryInfo() {
288  $dbr = $this->getDatabase();
289  $conds = $this->mConds;
290  $conds[] = 'pr_expiry > ' . $dbr->addQuotes( $dbr->timestamp() ) .
291  ' OR pr_expiry IS NULL';
292  $conds[] = 'page_id=pr_page';
293  $conds[] = 'pr_type=' . $dbr->addQuotes( $this->type );
294 
295  if ( $this->sizetype == 'min' ) {
296  $conds[] = 'page_len>=' . $this->size;
297  } elseif ( $this->sizetype == 'max' ) {
298  $conds[] = 'page_len<=' . $this->size;
299  }
300 
301  if ( $this->indefonly ) {
302  $infinity = $dbr->addQuotes( $dbr->getInfinity() );
303  $conds[] = "pr_expiry = $infinity OR pr_expiry IS NULL";
304  }
305  if ( $this->cascadeonly ) {
306  $conds[] = 'pr_cascade = 1';
307  }
308  if ( $this->noredirect ) {
309  $conds[] = 'page_is_redirect = 0';
310  }
311 
312  if ( $this->level ) {
313  $conds[] = 'pr_level=' . $dbr->addQuotes( $this->level );
314  }
315  if ( $this->namespace !== null ) {
316  $conds[] = 'page_namespace=' . $dbr->addQuotes( $this->namespace );
317  }
318 
319  $commentQuery = $this->commentStore->getJoin( 'log_comment' );
320  $actorQuery = $this->actorMigration->getJoin( 'log_user' );
321 
322  return [
323  'tables' => [
324  'page', 'page_restrictions', 'log_search',
325  'logparen' => [ 'logging' ] + $commentQuery['tables'] + $actorQuery['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  ] + $commentQuery['fields'] + $actorQuery['fields'],
339  'conds' => $conds,
340  'join_conds' => [
341  'log_search' => [
342  'LEFT JOIN', [
343  'ls_field' => 'pr_id', 'ls_value = ' . $dbr->buildStringCast( 'pr_id' )
344  ]
345  ],
346  'logparen' => [
347  'LEFT JOIN', [
348  'ls_log_id = log_id'
349  ]
350  ]
351  ] + $commentQuery['joins'] + $actorQuery['joins']
352  ];
353  }
354 
355  protected function getTableClass() {
356  return parent::getTableClass() . ' mw-protectedpages';
357  }
358 
359  public function getIndexField() {
360  return 'pr_id';
361  }
362 
363  public function getDefaultSort() {
364  return 'pr_id';
365  }
366 
367  protected function isFieldSortable( $field ) {
368  // no index for sorting exists
369  return false;
370  }
371 }
ProtectedPagesPager\$level
$level
Definition: ProtectedPagesPager.php:29
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:46
UserCache
Definition: UserCache.php:32
Linker\userLink
static userLink( $userId, $userName, $altUserName=false)
Make user link (or user contributions for unregistered users)
Definition: Linker.php:897
ProtectedPagesPager\isFieldSortable
isFieldSortable( $field)
Return true if the named field should be sortable by the UI, false otherwise.
Definition: ProtectedPagesPager.php:367
ProtectedPagesPager\formatValue
formatValue( $field, $value)
Definition: ProtectedPagesPager.php:151
ProtectedPagesPager\getIndexField
getIndexField()
Returns the name of the index field.If the pager supports multiple orders, it may return an array of ...
Definition: ProtectedPagesPager.php:359
MediaWiki\Linker\LinkRenderer
Class that generates HTML links for pages.
Definition: LinkRenderer.php:41
Linker\userToolLinks
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:942
LogEventsList\userCanBitfield
static userCanBitfield( $bitfield, $field, Authority $performer)
Determine if the current user is allowed to view a particular field of this log row,...
Definition: LogEventsList.php:540
IndexPager\getDatabase
getDatabase()
Get the Database object in use.
Definition: IndexPager.php:244
ProtectedPagesPager\$userCache
UserCache $userCache
Definition: ProtectedPagesPager.php:41
CommentStore
Handle database storage of comments such as edit summaries and log reasons.
Definition: CommentStore.php:42
ProtectedPagesPager\getQueryInfo
getQueryInfo()
Provides all parameters needed for the main paged query.
Definition: ProtectedPagesPager.php:287
ProtectedPagesPager\getDefaultSort
getDefaultSort()
The database field name used as a default sort order.
Definition: ProtectedPagesPager.php:363
ProtectedPagesPager\$type
$type
Definition: ProtectedPagesPager.php:29
ProtectedPagesPager\getTableClass
getTableClass()
TablePager relies on mw-datatable for styling, see T214208.
Definition: ProtectedPagesPager.php:355
IndexPager\$linkRenderer
LinkRenderer $linkRenderer
Definition: IndexPager.php:167
ActorMigration
This class handles the logic for the actor table migration and should always be used in lieu of direc...
Definition: ActorMigration.php:41
Linker\getInvalidTitleDescription
static getInvalidTitleDescription(IContextSource $context, $namespace, $title)
Get a message saying that an invalid title was encountered.
Definition: Linker.php:189
ContextSource\getUser
getUser()
Definition: ContextSource.php:135
ProtectedPagesPager\$namespace
$namespace
Definition: ProtectedPagesPager.php:29
Wikimedia\Rdbms\ILoadBalancer\getConnectionRef
getConnectionRef( $i, $groups=[], $domain=false, $flags=0)
Get a live database handle reference for a server index.
ProtectedPagesPager\preprocessResults
preprocessResults( $result)
Pre-process results; useful for performing batch existence checks, etc.
Definition: ProtectedPagesPager.php:97
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:151
ProtectedPagesPager\__construct
__construct( $form, $conds, $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect, LinkRenderer $linkRenderer, LinkBatchFactory $linkBatchFactory, ILoadBalancer $loadBalancer, CommentStore $commentStore, ActorMigration $actorMigration, UserCache $userCache)
Definition: ProtectedPagesPager.php:61
MWException
MediaWiki exception.
Definition: MWException.php:29
ProtectedPagesPager\$size
$size
Definition: ProtectedPagesPager.php:29
LogPage\DELETED_COMMENT
const DELETED_COMMENT
Definition: LogPage.php:39
ProtectedPagesPager\$cascadeonly
$cascadeonly
Definition: ProtectedPagesPager.php:29
LogPage\DELETED_USER
const DELETED_USER
Definition: LogPage.php:40
MediaWiki\Cache\LinkBatchFactory
Definition: LinkBatchFactory.php:38
TablePager
Table-based display with a user-selectable sort order.
Definition: TablePager.php:31
TablePager\$mCurrentRow
stdClass $mCurrentRow
Definition: TablePager.php:36
ProtectedPagesPager\$commentStore
CommentStore $commentStore
Definition: ProtectedPagesPager.php:35
ProtectedPagesPager\$linkBatchFactory
LinkBatchFactory $linkBatchFactory
Definition: ProtectedPagesPager.php:32
$title
$title
Definition: testCompression.php:38
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
ProtectedPagesPager\$actorMigration
ActorMigration $actorMigration
Definition: ProtectedPagesPager.php:38
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:195
ProtectedPagesPager\$indefonly
$indefonly
Definition: ProtectedPagesPager.php:29
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:652
ContextSource\getAuthority
getAuthority()
Definition: ContextSource.php:142
Linker\formatRevisionSize
static formatRevisionSize( $size)
Definition: Linker.php:1638
IndexPager\getLinkRenderer
getLinkRenderer()
Definition: IndexPager.php:980
NS_USER
const NS_USER
Definition: Defines.php:66
Linker\formatComment
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Definition: Linker.php:1191
ProtectedPagesPager\getFieldNames
getFieldNames()
An array mapping database field names to a textual description of the field name, for use in the tabl...
Definition: ProtectedPagesPager.php:125
ProtectedPagesPager\$noredirect
$noredirect
Definition: ProtectedPagesPager.php:29
MediaWiki\Linker\LinkRenderer\makeKnownLink
makeKnownLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:225
LogEventsList\isDeleted
static isDeleted( $row, $field)
Definition: LogEventsList.php:573
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
NS_USER_TALK
const NS_USER_TALK
Definition: Defines.php:67
ProtectedPagesPager\$mConds
$mConds
Definition: ProtectedPagesPager.php:28
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:234
MediaWiki\Linker\LinkRenderer\makeLink
makeLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:160
ProtectedPagesPager
Definition: ProtectedPagesPager.php:26
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
ProtectedPagesPager\$sizetype
$sizetype
Definition: ProtectedPagesPager.php:29