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