Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.41% covered (warning)
86.41%
89 / 103
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialGlobalBlockList
86.41% covered (warning)
86.41%
89 / 103
57.14% covered (warning)
57.14%
4 / 7
22.11
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 execute
70.59% covered (warning)
70.59%
12 / 17
0.00% covered (danger)
0.00%
0 / 1
3.23
 loadParameters
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 showForm
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
1
 showList
79.49% covered (warning)
79.49%
31 / 39
0.00% covered (danger)
0.00%
0 / 1
12.04
 noResults
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\GlobalBlocking\Special;
4
5use CentralIdLookup;
6use DerivativeContext;
7use HTMLForm;
8use MediaWiki\Block\BlockUtils;
9use MediaWiki\CommentFormatter\CommentFormatter;
10use MediaWiki\Extension\GlobalBlocking\GlobalBlocking;
11use MediaWiki\Extension\GlobalBlocking\Services\GlobalBlockingLinkBuilder;
12use MediaWiki\Extension\GlobalBlocking\Services\GlobalBlockLookup;
13use MediaWiki\Html\Html;
14use MediaWiki\SpecialPage\SpecialPage;
15use Wikimedia\IPUtils;
16
17class SpecialGlobalBlockList extends SpecialPage {
18    protected ?string $target;
19    protected array $options;
20
21    private BlockUtils $blockUtils;
22    private CommentFormatter $commentFormatter;
23    private CentralIdLookup $lookup;
24    private GlobalBlockingLinkBuilder $globalBlockingLinkBuilder;
25
26    /** @var GlobalBlockLookup */
27    private $globalBlockLookup;
28
29    /**
30     * @param BlockUtils $blockUtils
31     * @param CommentFormatter $commentFormatter
32     * @param CentralIdLookup $lookup
33     * @param GlobalBlockLookup $globalBlockLookup
34     * @param GlobalBlockingLinkBuilder $globalBlockingLinkBuilder
35     */
36    public function __construct(
37        BlockUtils $blockUtils,
38        CommentFormatter $commentFormatter,
39        CentralIdLookup $lookup,
40        GlobalBlockLookup $globalBlockLookup,
41        GlobalBlockingLinkBuilder $globalBlockingLinkBuilder
42    ) {
43        parent::__construct( 'GlobalBlockList' );
44
45        $this->blockUtils = $blockUtils;
46        $this->commentFormatter = $commentFormatter;
47        $this->lookup = $lookup;
48        $this->globalBlockLookup = $globalBlockLookup;
49        $this->globalBlockingLinkBuilder = $globalBlockingLinkBuilder;
50    }
51
52    /**
53     * @param string $par Parameters of the URL, probably the IP being actioned
54     * @return void
55     */
56    public function execute( $par ) {
57        $this->setHeaders();
58        $this->outputHeader( 'globalblocking-list-intro' );
59        $this->addHelpLink( 'Extension:GlobalBlocking' );
60
61        $out = $this->getOutput();
62        $out->setPageTitleMsg( $this->msg( 'globalblocking-list' ) );
63        $out->setSubtitle( GlobalBlocking::buildSubtitleLinks( $this ) );
64        $out->setArticleRelated( false );
65        $out->disableClientCache();
66
67        $this->loadParameters( $par );
68        $this->showForm();
69
70        // Validate search target. If it is invalid, no need to build the pager.
71        if ( $this->target && !IPUtils::isIPAddress( $this->target ) ) {
72            $out->wrapWikiMsg(
73                "<div class='error'>\n$1\n</div>",
74                [ 'globalblocking-list-ipinvalid', $this->target ]
75            );
76            return;
77        }
78
79        $this->showList();
80    }
81
82    /**
83     * @param string|null $par Parameter from the URL, may be null or a string (probably an IP)
84     * that was inserted
85     */
86    protected function loadParameters( $par ) {
87        $request = $this->getRequest();
88        $ip = trim( $request->getText( 'ip', $par ?? '' ) );
89        if ( $ip !== '' ) {
90            $ip = IPUtils::isIPAddress( $ip )
91                ? IPUtils::sanitizeRange( $ip )
92                : $ip;
93        }
94        $this->target = $ip;
95
96        $this->options = $request->getArray( 'wpOptions', [] );
97    }
98
99    protected function showForm() {
100        $fields = [
101            'ip' => [
102                'type' => 'text',
103                'name' => 'ip',
104                'id' => 'mw-globalblocking-search-ip',
105                'label-message' => 'globalblocking-search-ip',
106                'default' => $this->target,
107            ],
108            'Options' => [
109                'type' => 'multiselect',
110                'options-messages' => [
111                    'globalblocking-list-tempblocks' => 'tempblocks',
112                    'globalblocking-list-indefblocks' => 'indefblocks',
113                    'globalblocking-list-addressblocks' => 'addressblocks',
114                    'globalblocking-list-rangeblocks' => 'rangeblocks',
115                ],
116                'flatlist' => true,
117            ],
118        ];
119        $context = new DerivativeContext( $this->getContext() );
120        $context->setTitle( $this->getPageTitle() ); // remove subpage
121
122        $form = HTMLForm::factory( 'ooui', $fields, $context );
123        $form->setMethod( 'get' )
124            ->setName( 'globalblocklist-search' )
125            ->setSubmitTextMsg( 'globalblocking-search-submit' )
126            ->setWrapperLegendMsg( 'globalblocking-search-legend' )
127            ->prepareForm()
128            ->displayForm( false );
129    }
130
131    protected function showList() {
132        $out = $this->getOutput();
133        $dbr = GlobalBlocking::getReplicaGlobalBlockingDatabase();
134
135        // Build a list of blocks.
136        $conds = [];
137
138        if ( $this->target !== '' ) {
139            $conds[] = $this->globalBlockLookup->getRangeCondition( $this->target );
140        }
141
142        $hideIP = in_array( 'addressblocks', $this->options );
143        $hideRange = in_array( 'rangeblocks', $this->options );
144
145        if ( $hideIP && $hideRange ) {
146            $this->noResults();
147            return;
148        } elseif ( $hideIP ) {
149            $conds[] = "gb_range_end > gb_range_start";
150        } elseif ( $hideRange ) {
151            $conds[] = "gb_range_end = gb_range_start";
152        }
153
154        $hideTemp = in_array( 'tempblocks', $this->options );
155        $hideIndef = in_array( 'indefblocks', $this->options );
156        if ( $hideTemp && $hideIndef ) {
157            $this->noResults();
158            return;
159        } elseif ( $hideTemp ) {
160            $conds['gb_expiry'] = $dbr->getInfinity();
161        } elseif ( $hideIndef ) {
162            $conds[] = $dbr->expr( 'gb_expiry', '!=', $dbr->getInfinity() );
163        }
164
165        $pager = new GlobalBlockListPager(
166            $this->getContext(),
167            $conds,
168            $this->getLinkRenderer(),
169            $this->commentFormatter,
170            $this->lookup,
171            $this->globalBlockingLinkBuilder
172        );
173        $body = $pager->getBody();
174        if ( $body != '' ) {
175            $out->addHTML(
176                $pager->getNavigationBar() .
177                Html::rawElement( 'ul', [], $body ) .
178                $pager->getNavigationBar()
179            );
180        } else {
181            $this->noResults();
182        }
183    }
184
185    /**
186     * Display an error when no results are found for those parameters
187     * @return void
188     */
189    private function noResults() {
190        $this->getOutput()->wrapWikiMsg(
191            "<div class='mw-globalblocking-noresults'>\n$1</div>\n",
192            [ 'globalblocking-list-noresults' ]
193        );
194    }
195
196    protected function getGroupName() {
197        return 'users';
198    }
199}