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