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