Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 110
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiGlobalBlock
0.00% covered (danger)
0.00%
0 / 110
0.00% covered (danger)
0.00%
0 / 8
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 1
132
 addLegacyErrorsFromStatus
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
6
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 mustBePosted
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isWriteMode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 needsToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\GlobalBlocking\Api;
4
5use ApiBase;
6use ApiMain;
7use ApiResult;
8use MediaWiki\Block\BlockUserFactory;
9use MediaWiki\Extension\GlobalBlocking\GlobalBlocking;
10use MediaWiki\Status\Status;
11use StatusValue;
12use Wikimedia\ParamValidator\ParamValidator;
13
14class ApiGlobalBlock extends ApiBase {
15    /** @var BlockUserFactory */
16    private $blockUserFactory;
17
18    /**
19     * @param ApiMain $mainModule
20     * @param string $moduleName
21     * @param BlockUserFactory $blockUserFactory
22     */
23    public function __construct(
24        ApiMain $mainModule,
25        $moduleName,
26        BlockUserFactory $blockUserFactory
27    ) {
28        parent::__construct( $mainModule, $moduleName );
29
30        $this->blockUserFactory = $blockUserFactory;
31    }
32
33    public function execute() {
34        $this->checkUserRightsAny( 'globalblock' );
35
36        $this->requireOnlyOneParameter( $this->extractRequestParams(), 'expiry', 'unblock' );
37        $result = $this->getResult();
38        $block = GlobalBlocking::getGlobalBlockingBlock( $this->getParameter( 'target' ), true );
39
40        if ( $this->getParameter( 'expiry' ) ) {
41            $options = [];
42
43            if ( $this->getParameter( 'anononly' ) ) {
44                $options[] = 'anon-only';
45            }
46
47            if ( $block && $this->getParameter( 'modify' ) ) {
48                $options[] = 'modify';
49            }
50
51            $status = GlobalBlocking::block(
52                $this->getParameter( 'target' ),
53                $this->getParameter( 'reason' ),
54                $this->getParameter( 'expiry' ),
55                $this->getUser(),
56                $options
57            );
58
59            if ( $this->getParameter( 'alsolocal' ) && $status->isOK() ) {
60                $this->blockUserFactory->newBlockUser(
61                    $this->getParameter( 'target' ),
62                    $this->getUser(),
63                    $this->getParameter( 'expiry' ),
64                    $this->getParameter( 'reason' ),
65                    [
66                        'isCreateAccountBlocked' => true,
67                        'isEmailBlocked' => $this->getParameter( 'localblocksemail' ),
68                        'isUserTalkEditBlocked' => $this->getParameter( 'localblockstalk' ),
69                        'isHardBlock' => !$this->getParameter( 'localanononly' ),
70                        'isAutoblocking' => true,
71                    ]
72                )->placeBlock( $this->getParameter( 'modify' ) );
73                $result->addValue( 'globalblock', 'blockedlocally', true );
74            }
75
76            if ( !$status->isOK() ) {
77                $this->addLegacyErrorsFromStatus( $status, $result );
78            } else {
79                $result->addValue( 'globalblock', 'user', $this->getParameter( 'target' ) );
80                $result->addValue( 'globalblock', 'blocked', '' );
81                if ( $this->getParameter( 'anononly' ) ) {
82                    $result->addValue( 'globalblock', 'anononly', '' );
83                }
84                $expiry = ApiResult::formatExpiry( $this->getParameter( 'expiry' ), 'infinite' );
85                $result->addValue( 'globalblock', 'expiry', $expiry );
86            }
87        } elseif ( $this->getParameter( 'unblock' ) ) {
88            $status = GlobalBlocking::unblock(
89                $this->getParameter( 'target' ),
90                $this->getParameter( 'reason' ),
91                $this->getUser()
92            );
93
94            if ( !$status->isOK() ) {
95                $this->addLegacyErrorsFromStatus( $status, $result );
96            } else {
97                $result->addValue( 'globalblock', 'user', $this->getParameter( 'target' ) );
98                $result->addValue( 'globalblock', 'unblocked', '' );
99            }
100
101        }
102    }
103
104    /**
105     * @param StatusValue $status
106     * @param ApiResult $result
107     * @return void
108     */
109    private function addLegacyErrorsFromStatus( StatusValue $status, ApiResult $result ) {
110        // Convert a StatusValue to the legacy format used by the API.
111        // TODO deprecate and replace with ApiErrorFormatter::addMessagesFromStatus()
112        $legacyErrors = [];
113        $errors = Status::wrap( $status )->getErrorsArray();
114        foreach ( $errors as $error ) {
115            $legacyErrors[] = [
116                'code' => $error[0],
117                'message' => str_replace(
118                    "\n",
119                    " ",
120                    $this->msg( ...$error )->text()
121                )
122            ];
123        }
124        $result->setIndexedTagName( $legacyErrors, 'error' );
125        $result->addValue( 'error', 'globalblock', $legacyErrors );
126    }
127
128    public function getAllowedParams() {
129        return [
130            'target' => [
131                ParamValidator::PARAM_TYPE => 'string',
132                ParamValidator::PARAM_REQUIRED => true
133            ],
134            'expiry' => [
135                ParamValidator::PARAM_TYPE => 'expiry'
136            ],
137            'unblock' => [
138                ParamValidator::PARAM_TYPE => 'boolean'
139            ],
140            'reason' => [
141                ParamValidator::PARAM_TYPE => 'string',
142                ParamValidator::PARAM_REQUIRED => true
143            ],
144            'anononly' => [
145                ParamValidator::PARAM_TYPE => 'boolean'
146            ],
147            'modify' => [
148                ParamValidator::PARAM_TYPE => 'boolean'
149            ],
150            'alsolocal' => [
151                ParamValidator::PARAM_TYPE => 'boolean'
152            ],
153            'localblockstalk' => [
154                ParamValidator::PARAM_TYPE => 'boolean'
155            ],
156            'localblocksemail' => [
157                ParamValidator::PARAM_TYPE => 'boolean'
158            ],
159            'localanononly' => [
160                ParamValidator::PARAM_TYPE => 'boolean'
161            ],
162            'token' => [
163                ParamValidator::PARAM_TYPE => 'string',
164                ParamValidator::PARAM_REQUIRED => true
165            ]
166        ];
167    }
168
169    /**
170     * @see ApiBase::getExamplesMessages()
171     * @return array
172     */
173    protected function getExamplesMessages() {
174        return [
175            'action=globalblock&target=192.0.2.1&expiry=indefinite&reason=Cross-wiki%20abuse&token=123ABC'
176                => 'apihelp-globalblock-example-1',
177        ];
178    }
179
180    public function mustBePosted() {
181        return true;
182    }
183
184    public function isWriteMode() {
185        return true;
186    }
187
188    public function needsToken() {
189        return 'csrf';
190    }
191}