MediaWiki REL1_35
BlockListPager.php
Go to the documentation of this file.
1<?php
31use Wikimedia\IPUtils;
33
35
36 protected $conds;
37
43 protected $restrictions = [];
44
49 public function __construct( $page, $conds ) {
50 parent::__construct( $page->getContext(), $page->getLinkRenderer() );
51 $this->conds = $conds;
52 $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
53 }
54
55 protected function getFieldNames() {
56 static $headers = null;
57
58 if ( $headers === null ) {
59 $headers = [
60 'ipb_timestamp' => 'blocklist-timestamp',
61 'ipb_target' => 'blocklist-target',
62 'ipb_expiry' => 'blocklist-expiry',
63 'ipb_by' => 'blocklist-by',
64 'ipb_params' => 'blocklist-params',
65 'ipb_reason' => 'blocklist-reason',
66 ];
67 foreach ( $headers as $key => $val ) {
68 $headers[$key] = $this->msg( $val )->text();
69 }
70 }
71
72 return $headers;
73 }
74
81 public function formatValue( $name, $value ) {
82 static $msg = null;
83 if ( $msg === null ) {
84 $keys = [
85 'anononlyblock',
86 'createaccountblock',
87 'noautoblockblock',
88 'emailblock',
89 'blocklist-nousertalk',
90 'unblocklink',
91 'change-blocklink',
92 'blocklist-editing',
93 'blocklist-editing-sitewide',
94 ];
95
96 foreach ( $keys as $key ) {
97 $msg[$key] = $this->msg( $key )->text();
98 }
99 }
100 '@phan-var string[] $msg';
101
103 $row = $this->mCurrentRow;
104
105 $language = $this->getLanguage();
106
107 $formatted = '';
108
110
111 switch ( $name ) {
112 case 'ipb_timestamp':
113 $formatted = htmlspecialchars( $language->userTimeAndDate( $value, $this->getUser() ) );
114 break;
115
116 case 'ipb_target':
117 if ( $row->ipb_auto ) {
118 $formatted = $this->msg( 'autoblockid', $row->ipb_id )->parse();
119 } else {
120 list( $target, $type ) = DatabaseBlock::parseTarget( $row->ipb_address );
121
122 if ( is_string( $target ) ) {
123 if ( IPUtils::isValidRange( $target ) ) {
124 $target = User::newFromName( $target, false );
125 } else {
126 $formatted = $target;
127 }
128 }
129
130 if ( $target instanceof UserIdentity ) {
131 $formatted = Linker::userLink( $target->getId(), $target->getName() );
132 $formatted .= Linker::userToolLinks(
133 $target->getId(),
134 $target->getName(),
135 false,
137 );
138 }
139 }
140 break;
141
142 case 'ipb_expiry':
143 $formatted = htmlspecialchars( $language->formatExpiry(
144 $value,
145 /* User preference timezone */true
146 ) );
147 if ( MediaWikiServices::getInstance()
149 ->userHasRight( $this->getUser(), 'block' )
150 ) {
151 $links = [];
152 if ( $row->ipb_auto ) {
153 $links[] = $linkRenderer->makeKnownLink(
154 SpecialPage::getTitleFor( 'Unblock' ),
155 $msg['unblocklink'],
156 [],
157 [ 'wpTarget' => "#{$row->ipb_id}" ]
158 );
159 } else {
160 $links[] = $linkRenderer->makeKnownLink(
161 SpecialPage::getTitleFor( 'Unblock', $row->ipb_address ),
162 $msg['unblocklink']
163 );
164 $links[] = $linkRenderer->makeKnownLink(
165 SpecialPage::getTitleFor( 'Block', $row->ipb_address ),
166 $msg['change-blocklink']
167 );
168 }
169 $formatted .= ' ' . Html::rawElement(
170 'span',
171 [ 'class' => 'mw-blocklist-actions' ],
172 $this->msg( 'parentheses' )->rawParams(
173 $language->pipeList( $links ) )->escaped()
174 );
175 }
176 if ( $value !== 'infinity' ) {
177 $timestamp = new MWTimestamp( $value );
178 $formatted .= '<br />' . $this->msg(
179 'ipb-blocklist-duration-left',
180 $language->formatDuration(
181 $timestamp->getTimestamp() - MWTimestamp::time(),
182 // reasonable output
183 [
184 'minutes',
185 'hours',
186 'days',
187 'years',
188 ]
189 )
190 )->escaped();
191 }
192 break;
193
194 case 'ipb_by':
195 if ( isset( $row->by_user_name ) ) {
196 $formatted = Linker::userLink( $value, $row->by_user_name );
197 $formatted .= Linker::userToolLinks( $value, $row->by_user_name );
198 } else {
199 $formatted = htmlspecialchars( $row->ipb_by_text ); // foreign user?
200 }
201 break;
202
203 case 'ipb_reason':
204 $value = CommentStore::getStore()->getComment( 'ipb_reason', $row )->text;
205 $formatted = Linker::formatComment( $value );
206 break;
207
208 case 'ipb_params':
209 $properties = [];
210
211 if ( $row->ipb_sitewide ) {
212 $properties[] = htmlspecialchars( $msg['blocklist-editing-sitewide'] );
213 }
214
215 if ( !$row->ipb_sitewide && $this->restrictions ) {
216 $list = $this->getRestrictionListHTML( $row );
217 if ( $list ) {
218 $properties[] = htmlspecialchars( $msg['blocklist-editing'] ) . $list;
219 }
220 }
221
222 if ( $row->ipb_anon_only ) {
223 $properties[] = htmlspecialchars( $msg['anononlyblock'] );
224 }
225 if ( $row->ipb_create_account ) {
226 $properties[] = htmlspecialchars( $msg['createaccountblock'] );
227 }
228 if ( $row->ipb_user && !$row->ipb_enable_autoblock ) {
229 $properties[] = htmlspecialchars( $msg['noautoblockblock'] );
230 }
231
232 if ( $row->ipb_block_email ) {
233 $properties[] = htmlspecialchars( $msg['emailblock'] );
234 }
235
236 if ( !$row->ipb_allow_usertalk ) {
237 $properties[] = htmlspecialchars( $msg['blocklist-nousertalk'] );
238 }
239
240 $formatted = Html::rawElement(
241 'ul',
242 [],
243 implode( '', array_map( function ( $prop ) {
244 return Html::rawElement(
245 'li',
246 [],
247 $prop
248 );
249 }, $properties ) )
250 );
251 break;
252
253 default:
254 $formatted = "Unable to format $name";
255 break;
256 }
257
258 return $formatted;
259 }
260
268 private function getRestrictionListHTML( stdClass $row ) {
269 $items = [];
271
272 foreach ( $this->restrictions as $restriction ) {
273 if ( $restriction->getBlockId() !== (int)$row->ipb_id ) {
274 continue;
275 }
276
277 switch ( $restriction->getType() ) {
278 case PageRestriction::TYPE:
279 '@phan-var PageRestriction $restriction';
280 if ( $restriction->getTitle() ) {
281 $items[$restriction->getType()][] = Html::rawElement(
282 'li',
283 [],
284 $linkRenderer->makeLink( $restriction->getTitle() )
285 );
286 }
287 break;
288 case NamespaceRestriction::TYPE:
289 $text = $restriction->getValue() === NS_MAIN
290 ? $this->msg( 'blanknamespace' )->text()
291 : $this->getLanguage()->getFormattedNsText(
292 $restriction->getValue()
293 );
294 $items[$restriction->getType()][] = Html::rawElement(
295 'li',
296 [],
298 SpecialPage::getTitleValueFor( 'Allpages' ),
299 $text,
300 [],
301 [
302 'namespace' => $restriction->getValue()
303 ]
304 )
305 );
306 break;
307 }
308 }
309
310 if ( empty( $items ) ) {
311 return '';
312 }
313
314 $sets = [];
315 foreach ( $items as $key => $value ) {
316 $sets[] = Html::rawElement(
317 'li',
318 [],
319 $this->msg( 'blocklist-editing-' . $key ) . Html::rawElement(
320 'ul',
321 [],
322 implode( '', $value )
323 )
324 );
325 }
326
327 return Html::rawElement(
328 'ul',
329 [],
330 implode( '', $sets )
331 );
332 }
333
334 public function getQueryInfo() {
335 $commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
336 $actorQuery = ActorMigration::newMigration()->getJoin( 'ipb_by' );
337
338 $info = [
339 'tables' => array_merge(
340 [ 'ipblocks' ], $commentQuery['tables'], $actorQuery['tables'], [ 'user' ]
341 ),
342 'fields' => [
343 'ipb_id',
344 'ipb_address',
345 'ipb_user',
346 'by_user_name' => 'user_name',
347 'ipb_timestamp',
348 'ipb_auto',
349 'ipb_anon_only',
350 'ipb_create_account',
351 'ipb_enable_autoblock',
352 'ipb_expiry',
353 'ipb_range_start',
354 'ipb_range_end',
355 'ipb_deleted',
356 'ipb_block_email',
357 'ipb_allow_usertalk',
358 'ipb_sitewide',
359 ] + $commentQuery['fields'] + $actorQuery['fields'],
360 'conds' => $this->conds,
361 'join_conds' => [
362 'user' => [ 'LEFT JOIN', 'user_id = ' . $actorQuery['fields']['ipb_by'] ]
363 ] + $commentQuery['joins'] + $actorQuery['joins']
364 ];
365
366 # Filter out any expired blocks
367 $db = $this->getDatabase();
368 $info['conds'][] = 'ipb_expiry > ' . $db->addQuotes( $db->timestamp() );
369
370 # Is the user allowed to see hidden blocks?
371 if ( !MediaWikiServices::getInstance()
373 ->userHasRight( $this->getUser(), 'hideuser' )
374 ) {
375 $info['conds']['ipb_deleted'] = 0;
376 }
377
378 return $info;
379 }
380
386 public function getTotalAutoblocks() {
387 $dbr = $this->getDatabase();
388 $res = $dbr->selectField( 'ipblocks',
389 'COUNT(*)',
390 [
391 'ipb_auto' => '1',
392 'ipb_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() ),
393 ],
394 __METHOD__
395 );
396 if ( $res ) {
397 return $res;
398 }
399 return 0; // We found nothing
400 }
401
402 protected function getTableClass() {
403 return parent::getTableClass() . ' mw-blocklist';
404 }
405
406 public function getIndexField() {
407 return [ [ 'ipb_timestamp', 'ipb_id' ] ];
408 }
409
410 public function getDefaultSort() {
411 return '';
412 }
413
414 protected function isFieldSortable( $name ) {
415 return false;
416 }
417
422 public function preprocessResults( $result ) {
423 # Do a link batch query
424 $lb = new LinkBatch;
425 $lb->setCaller( __METHOD__ );
426
427 $partialBlocks = [];
428 foreach ( $result as $row ) {
429 $lb->add( NS_USER, $row->ipb_address );
430 $lb->add( NS_USER_TALK, $row->ipb_address );
431
432 if ( isset( $row->by_user_name ) ) {
433 $lb->add( NS_USER, $row->by_user_name );
434 $lb->add( NS_USER_TALK, $row->by_user_name );
435 }
436
437 if ( !$row->ipb_sitewide ) {
438 $partialBlocks[] = $row->ipb_id;
439 }
440 }
441
442 if ( $partialBlocks ) {
443 // Mutations to the $row object are not persisted. The restrictions will
444 // need be stored in a separate store.
445 $blockRestrictionStore = MediaWikiServices::getInstance()->getBlockRestrictionStore();
446 $this->restrictions = $blockRestrictionStore->loadByBlockId( $partialBlocks );
447
448 foreach ( $this->restrictions as $restriction ) {
449 if ( $restriction->getType() === PageRestriction::TYPE ) {
450 '@phan-var PageRestriction $restriction';
451 $title = $restriction->getTitle();
452 if ( $title !== null ) {
453 $lb->addObj( $title );
454 }
455 }
456 }
457 }
458
459 $lb->execute();
460 }
461
462}
getPermissionManager()
getQueryInfo()
Provides all parameters needed for the main paged query.
isFieldSortable( $name)
Return true if the named field should be sortable by the UI, false otherwise.
__construct( $page, $conds)
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...
getIndexField()
Returns the name of the index field.If the pager supports multiple orders, it may return an array of ...
preprocessResults( $result)
Do a LinkBatch query to minimise database load when generating all these links.
getRestrictionListHTML(stdClass $row)
Get Restriction List HTML.
formatValue( $name, $value)
Restriction[] $restrictions
Array of restrictions.
getTotalAutoblocks()
Get total number of autoblocks at any given time.
getDefaultSort()
The database field name used as a default sort order.
getUser()
Stable to override.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getDatabase()
Get the Database object in use.
LinkRenderer $linkRenderer
const DIR_DESCENDING
Backwards-compatible constant for $mDefaultDirection field (do not change)
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:35
setCaller( $caller)
Use ->setCaller( METHOD ) to indicate which code is using this class.
static userLink( $userId, $userName, $altUserName=false)
Make user link (or user contributions for unregistered users)
Definition Linker.php:906
const TOOL_LINKS_NOBLOCK
Flags for userToolLinks()
Definition Linker.php:40
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:951
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:1209
Library for creating and parsing MW-style timestamps.
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
makeKnownLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
makeLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
MediaWikiServices is the service locator for the application scope of MediaWiki.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
static getTitleValueFor( $name, $subpage=false, $fragment='')
Get a localised TitleValue object for a specified special page name.
Table-based display with a user-selectable sort order Stable to extend.
stdClass $mCurrentRow
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition User.php:541
const NS_USER
Definition Defines.php:72
const NS_MAIN
Definition Defines.php:70
const NS_USER_TALK
Definition Defines.php:73
Interface for objects representing user identity.
Result wrapper for grabbing data queried from an IDatabase object.