MediaWiki REL1_40
ApiBlock.php
Go to the documentation of this file.
1<?php
43
50class ApiBlock extends ApiBase {
51
54
56 private $blockPermissionCheckerFactory;
57
59 private $blockUserFactory;
60
62 private $titleFactory;
63
65 private $userIdentityLookup;
66
68 private $watchedItemStore;
69
71 private $blockUtils;
72
74 private $blockActionInfo;
75
89 public function __construct(
90 ApiMain $main,
91 $action,
92 BlockPermissionCheckerFactory $blockPermissionCheckerFactory,
93 BlockUserFactory $blockUserFactory,
94 TitleFactory $titleFactory,
95 UserIdentityLookup $userIdentityLookup,
96 WatchedItemStoreInterface $watchedItemStore,
97 BlockUtils $blockUtils,
98 BlockActionInfo $blockActionInfo,
99 WatchlistManager $watchlistManager,
100 UserOptionsLookup $userOptionsLookup
101 ) {
102 parent::__construct( $main, $action );
103
104 $this->blockPermissionCheckerFactory = $blockPermissionCheckerFactory;
105 $this->blockUserFactory = $blockUserFactory;
106 $this->titleFactory = $titleFactory;
107 $this->userIdentityLookup = $userIdentityLookup;
108 $this->watchedItemStore = $watchedItemStore;
109 $this->blockUtils = $blockUtils;
110 $this->blockActionInfo = $blockActionInfo;
111
112 // Variables needed in ApiWatchlistTrait trait
113 $this->watchlistExpiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
114 $this->watchlistMaxDuration =
115 $this->getConfig()->get( MainConfigNames::WatchlistExpiryMaxDuration );
116 $this->watchlistManager = $watchlistManager;
117 $this->userOptionsLookup = $userOptionsLookup;
118 }
119
126 public function execute() {
127 $this->checkUserRightsAny( 'block' );
128 $params = $this->extractRequestParams();
129 $this->requireOnlyOneParameter( $params, 'user', 'userid' );
130
131 // Make sure $target contains a parsed target
132 if ( $params['user'] !== null ) {
133 $target = $params['user'];
134 } else {
135 $target = $this->userIdentityLookup->getUserIdentityByUserId( $params['userid'] );
136 if ( !$target ) {
137 $this->dieWithError( [ 'apierror-nosuchuserid', $params['userid'] ], 'nosuchuserid' );
138 }
139 }
140 [ $target, $targetType ] = $this->blockUtils->parseBlockTarget( $target );
141
142 if (
143 $params['noemail'] &&
144 !$this->blockPermissionCheckerFactory
145 ->newBlockPermissionChecker(
146 $target,
147 $this->getAuthority()
148 )
149 ->checkEmailPermissions()
150 ) {
151 $this->dieWithError( 'apierror-cantblock-email' );
152 }
153
154 $restrictions = [];
155 if ( $params['partial'] ) {
156 $pageRestrictions = array_map(
157 [ PageRestriction::class, 'newFromTitle' ],
158 (array)$params['pagerestrictions']
159 );
160
161 $namespaceRestrictions = array_map( static function ( $id ) {
162 return new NamespaceRestriction( 0, $id );
163 }, (array)$params['namespacerestrictions'] );
164 $restrictions = array_merge( $pageRestrictions, $namespaceRestrictions );
165
166 if ( $this->getConfig()->get( MainConfigNames::EnablePartialActionBlocks ) ) {
167 $actionRestrictions = array_map( function ( $action ) {
168 return new ActionRestriction( 0, $this->blockActionInfo->getIdFromAction( $action ) );
169 }, (array)$params['actionrestrictions'] );
170 $restrictions = array_merge( $restrictions, $actionRestrictions );
171 }
172 }
173
174 $status = $this->blockUserFactory->newBlockUser(
175 $target,
176 $this->getAuthority(),
177 $params['expiry'],
178 $params['reason'],
179 [
180 'isCreateAccountBlocked' => $params['nocreate'],
181 'isEmailBlocked' => $params['noemail'],
182 'isHardBlock' => !$params['anononly'],
183 'isAutoblocking' => $params['autoblock'],
184 'isUserTalkEditBlocked' => !$params['allowusertalk'],
185 'isHideUser' => $params['hidename'],
186 'isPartial' => $params['partial'],
187 ],
188 $restrictions,
189 $params['tags']
190 )->placeBlock( $params['reblock'] );
191
192 if ( !$status->isOK() ) {
193 $this->dieStatus( $status );
194 }
195
196 $block = $status->value;
197
198 $watchlistExpiry = $this->getExpiryFromParams( $params );
199 $userPage = Title::makeTitle( NS_USER, $block->getTargetName() );
200
201 if ( $params['watchuser'] && $targetType !== AbstractBlock::TYPE_RANGE ) {
202 $this->setWatch( 'watch', $userPage, $this->getUser(), null, $watchlistExpiry );
203 }
204
205 $res = [];
206
207 $res['user'] = $block->getTargetName();
208 $res['userID'] = $target instanceof UserIdentity ? $target->getId() : 0;
209
210 if ( $block instanceof DatabaseBlock ) {
211 $res['expiry'] = ApiResult::formatExpiry( $block->getExpiry(), 'infinite' );
212 $res['id'] = $block->getId();
213 } else {
214 # should be unreachable
215 $res['expiry'] = ''; // @codeCoverageIgnore
216 $res['id'] = ''; // @codeCoverageIgnore
217 }
218
219 $res['reason'] = $params['reason'];
220 $res['anononly'] = $params['anononly'];
221 $res['nocreate'] = $params['nocreate'];
222 $res['autoblock'] = $params['autoblock'];
223 $res['noemail'] = $params['noemail'];
224 $res['hidename'] = $params['hidename'];
225 $res['allowusertalk'] = $params['allowusertalk'];
226 $res['watchuser'] = $params['watchuser'];
227 if ( $watchlistExpiry ) {
228 $expiry = $this->getWatchlistExpiry(
229 $this->watchedItemStore,
230 $userPage,
231 $this->getUser()
232 );
233 $res['watchlistexpiry'] = $expiry;
234 }
235 $res['partial'] = $params['partial'];
236 $res['pagerestrictions'] = $params['pagerestrictions'];
237 $res['namespacerestrictions'] = $params['namespacerestrictions'];
238 if ( $this->getConfig()->get( MainConfigNames::EnablePartialActionBlocks ) ) {
239 $res['actionrestrictions'] = $params['actionrestrictions'];
240 }
241
242 $this->getResult()->addValue( null, $this->getModuleName(), $res );
243 }
244
245 public function mustBePosted() {
246 return true;
247 }
248
249 public function isWriteMode() {
250 return true;
251 }
252
253 public function getAllowedParams() {
254 $params = [
255 'user' => [
256 ParamValidator::PARAM_TYPE => 'user',
257 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'cidr', 'id' ],
258 ],
259 'userid' => [
260 ParamValidator::PARAM_TYPE => 'integer',
261 ParamValidator::PARAM_DEPRECATED => true,
262 ],
263 'expiry' => 'never',
264 'reason' => '',
265 'anononly' => false,
266 'nocreate' => false,
267 'autoblock' => false,
268 'noemail' => false,
269 'hidename' => false,
270 'allowusertalk' => false,
271 'reblock' => false,
272 'watchuser' => false,
273 ];
274
275 // Params appear in the docs in the order they are defined,
276 // which is why this is here and not at the bottom.
277 // @todo Find better way to support insertion at arbitrary position
278 if ( $this->watchlistExpiryEnabled ) {
279 $params += [
280 'watchlistexpiry' => [
281 ParamValidator::PARAM_TYPE => 'expiry',
282 ExpiryDef::PARAM_MAX => $this->watchlistMaxDuration,
283 ExpiryDef::PARAM_USE_MAX => true,
284 ]
285 ];
286 }
287
288 $params += [
289 'tags' => [
290 ParamValidator::PARAM_TYPE => 'tags',
291 ParamValidator::PARAM_ISMULTI => true,
292 ],
293 'partial' => false,
294 'pagerestrictions' => [
295 ParamValidator::PARAM_TYPE => 'title',
296 TitleDef::PARAM_MUST_EXIST => true,
297
298 // TODO: TitleDef returns instances of TitleValue when PARAM_RETURN_OBJECT is
299 // truthy. At the time of writing,
300 // MediaWiki\Block\Restriction\PageRestriction::newFromTitle accepts either
301 // string or instance of Title.
302 //TitleDef::PARAM_RETURN_OBJECT => true,
303
304 ParamValidator::PARAM_ISMULTI => true,
305 ParamValidator::PARAM_ISMULTI_LIMIT1 => 10,
306 ParamValidator::PARAM_ISMULTI_LIMIT2 => 10,
307 ],
308 'namespacerestrictions' => [
309 ParamValidator::PARAM_ISMULTI => true,
310 ParamValidator::PARAM_TYPE => 'namespace',
311 ],
312 ];
313
314 if ( $this->getConfig()->get( MainConfigNames::EnablePartialActionBlocks ) ) {
315 $params += [
316 'actionrestrictions' => [
317 ParamValidator::PARAM_ISMULTI => true,
318 ParamValidator::PARAM_TYPE => array_keys(
319 $this->blockActionInfo->getAllBlockActions()
320 ),
321 ],
322 ];
323 }
324
325 return $params;
326 }
327
328 public function needsToken() {
329 return 'csrf';
330 }
331
332 protected function getExamplesMessages() {
333 // phpcs:disable Generic.Files.LineLength
334 return [
335 'action=block&user=192.0.2.5&expiry=3%20days&reason=First%20strike&token=123ABC'
336 => 'apihelp-block-example-ip-simple',
337 'action=block&user=Vandal&expiry=never&reason=Vandalism&nocreate=&autoblock=&noemail=&token=123ABC'
338 => 'apihelp-block-example-user-complex',
339 ];
340 // phpcs:enable
341 }
342
343 public function getHelpUrls() {
344 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Block';
345 }
346}
getExpiryFromParams(array $params)
Get formatted expiry from the given parameters, or null if no expiry was provided.
setWatch(string $watch, Title $title, User $user, ?string $userOption=null, ?string $expiry=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
getWatchlistExpiry(WatchedItemStoreInterface $store, Title $title, UserIdentity $user)
Get existing expiry from the database.
const NS_USER
Definition Defines.php:66
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:59
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1460
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition ApiBase.php:1566
requireOnlyOneParameter( $params,... $required)
Die if none or more than one of a certain set of parameters is set and not false.
Definition ApiBase.php:911
getResult()
Get the result object.
Definition ApiBase.php:637
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:773
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:506
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition ApiBase.php:1521
API module that facilitates the blocking of users.
Definition ApiBlock.php:50
needsToken()
Returns the token type this module requires in order to execute.
Definition ApiBlock.php:328
getExamplesMessages()
Returns usage examples for this module.
Definition ApiBlock.php:332
isWriteMode()
Indicates whether this module requires write mode.
Definition ApiBlock.php:249
__construct(ApiMain $main, $action, BlockPermissionCheckerFactory $blockPermissionCheckerFactory, BlockUserFactory $blockUserFactory, TitleFactory $titleFactory, UserIdentityLookup $userIdentityLookup, WatchedItemStoreInterface $watchedItemStore, BlockUtils $blockUtils, BlockActionInfo $blockActionInfo, WatchlistManager $watchlistManager, UserOptionsLookup $userOptionsLookup)
Definition ApiBlock.php:89
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition ApiBlock.php:245
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition ApiBlock.php:253
execute()
Blocks the user specified in the parameters for the given expiry, with the given reason,...
Definition ApiBlock.php:126
getHelpUrls()
Return links to more detailed help pages about the module.
Definition ApiBlock.php:343
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:58
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...
Restriction for partial blocks of actions.
A class containing constants representing the names of configuration variables.
Type definition for page titles.
Definition TitleDef.php:22
Type definition for user types.
Definition UserDef.php:27
Creates Title objects.
Represents a title within MediaWiki.
Definition Title.php:82
Provides access to user options.
Service for formatting and validating API parameters.
Type definition for expiry timestamps.
Definition ExpiryDef.php:17
trait ApiBlockInfoTrait
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...
Interface for objects representing user identity.
getId( $wikiId=self::LOCAL)