MediaWiki master
SpecialBlockList.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Specials;
22
36use Wikimedia\IPUtils;
39
48 protected $target;
49
50 protected $options;
51
52 protected $blockType;
53
54 private LinkBatchFactory $linkBatchFactory;
55 private DatabaseBlockStore $blockStore;
56 private BlockRestrictionStore $blockRestrictionStore;
57 private IConnectionProvider $dbProvider;
58 private CommentStore $commentStore;
59 private BlockUtils $blockUtils;
60 private HideUserUtils $hideUserUtils;
61 private BlockActionInfo $blockActionInfo;
62 private RowCommentFormatter $rowCommentFormatter;
63
64 public function __construct(
65 LinkBatchFactory $linkBatchFactory,
66 DatabaseBlockStore $blockStore,
67 BlockRestrictionStore $blockRestrictionStore,
68 IConnectionProvider $dbProvider,
69 CommentStore $commentStore,
70 BlockUtils $blockUtils,
71 HideUserUtils $hideUserUtils,
72 BlockActionInfo $blockActionInfo,
73 RowCommentFormatter $rowCommentFormatter
74 ) {
75 parent::__construct( 'BlockList' );
76
77 $this->linkBatchFactory = $linkBatchFactory;
78 $this->blockStore = $blockStore;
79 $this->blockRestrictionStore = $blockRestrictionStore;
80 $this->dbProvider = $dbProvider;
81 $this->commentStore = $commentStore;
82 $this->blockUtils = $blockUtils;
83 $this->hideUserUtils = $hideUserUtils;
84 $this->blockActionInfo = $blockActionInfo;
85 $this->rowCommentFormatter = $rowCommentFormatter;
86 }
87
91 public function execute( $par ) {
92 $this->setHeaders();
93 $this->outputHeader();
94 $this->addHelpLink( 'Help:Blocking_users' );
95 $out = $this->getOutput();
96 $out->setPageTitleMsg( $this->msg( 'ipblocklist' ) );
97 $out->addModuleStyles( [ 'mediawiki.special' ] );
98
99 $request = $this->getRequest();
100 $par = $request->getVal( 'ip', $par ?? '' );
101 $this->target = trim( $request->getVal( 'wpTarget', $par ) );
102
103 $this->options = $request->getArray( 'wpOptions', [] );
104 $this->blockType = $request->getVal( 'blockType' );
105
106 $action = $request->getText( 'action' );
107
108 if ( $action == 'unblock' || ( $action == 'submit' && $request->wasPosted() ) ) {
109 // B/C @since 1.18: Unblock interface is now at Special:Unblock
110 $title = $this->getSpecialPageFactory()->getTitleForAlias( 'Unblock/' . $this->target );
111 $out->redirect( $title->getFullURL() );
112
113 return;
114 }
115
116 // Setup BlockListPager here to get the actual default Limit
117 $pager = $this->getBlockListPager();
118
119 // Just show the block list
120 $fields = [
121 'Target' => [
122 'type' => 'user',
123 'label-message' => 'ipaddressorusername',
124 'tabindex' => '1',
125 'size' => '45',
126 'default' => $this->target,
127 ],
128 'Options' => [
129 'type' => 'multiselect',
130 'options-messages' => [
131 'blocklist-tempblocks' => 'tempblocks',
132 'blocklist-indefblocks' => 'indefblocks',
133 'blocklist-autoblocks' => 'autoblocks',
134 'blocklist-userblocks' => 'userblocks',
135 'blocklist-addressblocks' => 'addressblocks',
136 'blocklist-rangeblocks' => 'rangeblocks',
137 ],
138 'flatlist' => true,
139 ],
140 ];
141
142 $fields['BlockType'] = [
143 'type' => 'select',
144 'label-message' => 'blocklist-type',
145 'options' => [
146 $this->msg( 'blocklist-type-opt-all' )->escaped() => '',
147 $this->msg( 'blocklist-type-opt-sitewide' )->escaped() => 'sitewide',
148 $this->msg( 'blocklist-type-opt-partial' )->escaped() => 'partial',
149 ],
150 'name' => 'blockType',
151 'cssclass' => 'mw-field-block-type',
152 ];
153
154 $fields['Limit'] = [
155 'type' => 'limitselect',
156 'label-message' => 'table_pager_limit_label',
157 'options' => $pager->getLimitSelectList(),
158 'name' => 'limit',
159 'default' => $pager->getLimit(),
160 'cssclass' => 'mw-field-limit mw-has-field-block-type',
161 ];
162
163 $form = HTMLForm::factory( 'ooui', $fields, $this->getContext() );
164 $form
165 ->setMethod( 'get' )
166 ->setTitle( $this->getPageTitle() ) // Remove subpage
167 ->setFormIdentifier( 'blocklist' )
168 ->setWrapperLegendMsg( 'ipblocklist-legend' )
169 ->setSubmitTextMsg( 'ipblocklist-submit' )
170 ->prepareForm()
171 ->displayForm( false );
172
173 $this->showList( $pager );
174 }
175
180 protected function getBlockListPager() {
181 $conds = [];
182 $db = $this->getDB();
183
184 if ( $this->target !== '' ) {
185 [ $target, $type ] = $this->blockUtils->parseBlockTarget( $this->target );
186
187 switch ( $type ) {
188 case DatabaseBlock::TYPE_ID:
189 case DatabaseBlock::TYPE_AUTO:
190 $conds['bl_id'] = $target;
191 break;
192
193 case DatabaseBlock::TYPE_IP:
194 case DatabaseBlock::TYPE_RANGE:
195 [ $start, $end ] = IPUtils::parseRange( $target );
196 $conds[] = $this->blockStore->getRangeCond( $start, $end );
197 $conds['bt_auto'] = 0;
198 break;
199
200 case DatabaseBlock::TYPE_USER:
201 if ( $target->getId() ) {
202 $conds['bt_user'] = $target->getId();
203 $conds['bt_auto'] = 0;
204 } else {
205 // No such user
206 $conds[] = '1=0';
207 }
208 break;
209 }
210 }
211
212 // Apply filters
213 if ( in_array( 'userblocks', $this->options ) ) {
214 $conds['bt_user'] = null;
215 }
216 if ( in_array( 'autoblocks', $this->options ) ) {
217 $conds['bl_parent_block_id'] = null;
218 }
219 if ( in_array( 'addressblocks', $this->options )
220 && in_array( 'rangeblocks', $this->options )
221 ) {
222 // Simpler conditions for only user blocks (T360864)
223 $conds[] = "bt_user IS NOT NULL";
224 } elseif ( in_array( 'addressblocks', $this->options ) ) {
225 $conds[] = "bt_user IS NOT NULL OR bt_range_start IS NOT NULL";
226 } elseif ( in_array( 'rangeblocks', $this->options ) ) {
227 $conds['bt_range_start'] = null;
228 }
229
230 $hideTemp = in_array( 'tempblocks', $this->options );
231 $hideIndef = in_array( 'indefblocks', $this->options );
232 if ( $hideTemp && $hideIndef ) {
233 // If both types are hidden, ensure query doesn't produce any results
234 $conds[] = '1=0';
235 } elseif ( $hideTemp ) {
236 $conds['bl_expiry'] = $db->getInfinity();
237 } elseif ( $hideIndef ) {
238 $conds[] = $db->expr( 'bl_expiry', '!=', $db->getInfinity() );
239 }
240
241 if ( $this->blockType === 'sitewide' ) {
242 $conds['bl_sitewide'] = 1;
243 } elseif ( $this->blockType === 'partial' ) {
244 $conds['bl_sitewide'] = 0;
245 }
246
247 return new BlockListPager(
248 $this->getContext(),
249 $this->blockActionInfo,
250 $this->blockRestrictionStore,
251 $this->blockUtils,
252 $this->hideUserUtils,
253 $this->commentStore,
254 $this->linkBatchFactory,
255 $this->getLinkRenderer(),
256 $this->dbProvider,
257 $this->rowCommentFormatter,
258 $this->getSpecialPageFactory(),
259 $conds
260 );
261 }
262
267 protected function showList( BlockListPager $pager ) {
268 $out = $this->getOutput();
269
270 // Check for other blocks, i.e. global/tor blocks
271 $otherBlockLink = [];
272 $this->getHookRunner()->onOtherBlockLogLink( $otherBlockLink, $this->target );
273
274 // Show additional header for the local block only when other blocks exists.
275 // Not necessary in a standard installation without such extensions enabled
276 if ( count( $otherBlockLink ) ) {
277 $out->addHTML(
278 Html::element( 'h2', [], $this->msg( 'ipblocklist-localblock' )->text() ) . "\n"
279 );
280 }
281
282 if ( $pager->getNumRows() ) {
283 $out->addParserOutputContent( $pager->getFullOutput() );
284 } elseif ( $this->target ) {
285 $out->addWikiMsg( 'ipblocklist-no-results' );
286 } else {
287 $out->addWikiMsg( 'ipblocklist-empty' );
288 }
289
290 if ( count( $otherBlockLink ) ) {
291 $out->addHTML(
292 Html::rawElement(
293 'h2',
294 [],
295 $this->msg( 'ipblocklist-otherblocks', count( $otherBlockLink ) )->parse()
296 ) . "\n"
297 );
298 $list = '';
299 foreach ( $otherBlockLink as $link ) {
300 $list .= Html::rawElement( 'li', [], $link ) . "\n";
301 }
302 $out->addHTML( Html::rawElement(
303 'ul',
304 [ 'class' => 'mw-ipblocklist-otherblocks' ],
305 $list
306 ) . "\n" );
307 }
308 }
309
310 protected function getGroupName() {
311 return 'users';
312 }
313
319 protected function getDB() {
320 return $this->dbProvider->getReplicaDatabase();
321 }
322}
323
325class_alias( SpecialBlockList::class, 'SpecialBlockList' );
Defines the actions that can be blocked by a partial block.
Backend class for blocking utils.
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Helpers for building queries that determine whether a user is hidden.
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.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:206
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
getNumRows()
Get the number of rows in the result set.
getFullOutput()
Get the formatted result list, with navigation bars.
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getPageTitle( $subpage=false)
Get a self-referential title object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
showList(BlockListPager $pager)
Show the list of blocked accounts matching the actual filter.
__construct(LinkBatchFactory $linkBatchFactory, DatabaseBlockStore $blockStore, BlockRestrictionStore $blockRestrictionStore, IConnectionProvider $dbProvider, CommentStore $commentStore, BlockUtils $blockUtils, HideUserUtils $hideUserUtils, BlockActionInfo $blockActionInfo, RowCommentFormatter $rowCommentFormatter)
getDB()
Return a IDatabase object for reading.
getBlockListPager()
Setup a new BlockListPager instance.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Provide primary and replica IDatabase connections.
A database connection without write operations.
element(SerializerNode $parent, SerializerNode $node, $contents)