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