MediaWiki  master
SpecialBlock.php
Go to the documentation of this file.
1 <?php
37 use Wikimedia\IPUtils;
38 
46 
48  private $blockUtils;
49 
52 
55 
57  private $userNameUtils;
58 
61 
65  protected $target;
66 
68  protected $type;
69 
71  protected $previousTarget;
72 
74  protected $requestedHideUser;
75 
77  protected $alreadyBlocked;
78 
80  protected $preErrors = [];
81 
89  public function __construct(
95  ) {
96  parent::__construct( 'Block', 'block' );
97 
98  $this->blockUtils = $blockUtils;
99  $this->blockPermissionCheckerFactory = $blockPermissionCheckerFactory;
100  $this->blockUserFactory = $blockUserFactory;
101  $this->userNameUtils = $userNameUtils;
102  $this->userNamePrefixSearch = $userNamePrefixSearch;
103  }
104 
105  public function doesWrites() {
106  return true;
107  }
108 
115  protected function checkExecutePermissions( User $user ) {
116  parent::checkExecutePermissions( $user );
117  # T17810: blocked admins should have limited access here
118  $status = $this->blockPermissionCheckerFactory
119  ->newBlockPermissionChecker( $this->target, $user )
120  ->checkBlockPermissions();
121  if ( $status !== true ) {
122  throw new ErrorPageError( 'badaccess', $status );
123  }
124  }
125 
131  public function requiresUnblock() {
132  return false;
133  }
134 
140  protected function setParameter( $par ) {
141  # Extract variables from the request. Try not to get into a situation where we
142  # need to extract *every* variable from the form just for processing here, but
143  # there are legitimate uses for some variables
144  $request = $this->getRequest();
145  list( $this->target, $this->type ) = self::getTargetAndType( $par, $request );
146  if ( $this->target instanceof User ) {
147  # Set the 'relevant user' in the skin, so it displays links like Contributions,
148  # User logs, UserRights, etc.
149  $this->getSkin()->setRelevantUser( $this->target );
150  }
151 
152  list( $this->previousTarget, /*...*/ ) = $this->blockUtils
153  ->parseBlockTarget( $request->getVal( 'wpPreviousTarget' ) );
154  $this->requestedHideUser = $request->getBool( 'wpHideUser' );
155  }
156 
162  protected function alterForm( HTMLForm $form ) {
163  $form->setHeaderText( '' );
164  $form->setSubmitDestructive();
165 
166  $msg = $this->alreadyBlocked ? 'ipb-change-block' : 'ipbsubmit';
167  $form->setSubmitTextMsg( $msg );
168 
169  $this->addHelpLink( 'Help:Blocking users' );
170 
171  # Don't need to do anything if the form has been posted
172  if ( !$this->getRequest()->wasPosted() && $this->preErrors ) {
173  $s = $form->formatErrors( $this->preErrors );
174  if ( $s ) {
176  'div',
177  [ 'class' => 'error' ],
178  $s
179  ) );
180  }
181  }
182  }
183 
184  protected function getDisplayFormat() {
185  return 'ooui';
186  }
187 
192  protected function getFormFields() {
193  $conf = $this->getConfig();
194  $blockAllowsUTEdit = $conf->get( 'BlockAllowsUTEdit' );
195 
196  $this->getOutput()->enableOOUI();
197 
198  $user = $this->getUser();
199 
200  $suggestedDurations = self::getSuggestedDurations();
201 
202  $a = [];
203 
204  $a['Target'] = [
205  'type' => 'user',
206  'ipallowed' => true,
207  'iprange' => true,
208  'id' => 'mw-bi-target',
209  'size' => '45',
210  'autofocus' => true,
211  'required' => true,
212  'validation-callback' => function ( $value, $alldata, $form ) {
213  $status = $this->blockUtils->validateTarget( $value );
214  if ( !$status->isOK() ) {
215  $errors = $status->getErrorsArray();
216 
217  return $form->msg( ...$errors[0] );
218  }
219  return true;
220  },
221  'section' => 'target',
222  ];
223 
224  $a['Editing'] = [
225  'type' => 'check',
226  'label-message' => 'block-prevent-edit',
227  'default' => true,
228  'section' => 'actions',
229  ];
230 
231  $a['EditingRestriction'] = [
232  'type' => 'radio',
233  'cssclass' => 'mw-block-editing-restriction',
234  'default' => 'sitewide',
235  'options' => [
236  $this->msg( 'ipb-sitewide' )->escaped() .
237  new \OOUI\LabelWidget( [
238  'classes' => [ 'oo-ui-inline-help' ],
239  'label' => $this->msg( 'ipb-sitewide-help' )->text(),
240  ] ) => 'sitewide',
241  $this->msg( 'ipb-partial' )->escaped() .
242  new \OOUI\LabelWidget( [
243  'classes' => [ 'oo-ui-inline-help' ],
244  'label' => $this->msg( 'ipb-partial-help' )->text(),
245  ] ) => 'partial',
246  ],
247  'section' => 'actions',
248  ];
249 
250  $a['PageRestrictions'] = [
251  'type' => 'titlesmultiselect',
252  'label' => $this->msg( 'ipb-pages-label' )->text(),
253  'exists' => true,
254  'max' => 10,
255  'cssclass' => 'mw-block-restriction',
256  'showMissing' => false,
257  'excludeDynamicNamespaces' => true,
258  'input' => [
259  'autocomplete' => false
260  ],
261  'section' => 'actions',
262  ];
263 
264  $a['NamespaceRestrictions'] = [
265  'type' => 'namespacesmultiselect',
266  'label' => $this->msg( 'ipb-namespaces-label' )->text(),
267  'exists' => true,
268  'cssclass' => 'mw-block-restriction',
269  'input' => [
270  'autocomplete' => false
271  ],
272  'section' => 'actions',
273  ];
274 
275  $a['CreateAccount'] = [
276  'type' => 'check',
277  'label-message' => 'ipbcreateaccount',
278  'default' => true,
279  'section' => 'actions',
280  ];
281 
282  if ( $this->blockPermissionCheckerFactory
283  ->newBlockPermissionChecker( null, $user )
284  ->checkEmailPermissions()
285  ) {
286  $a['DisableEmail'] = [
287  'type' => 'check',
288  'label-message' => 'ipbemailban',
289  'section' => 'actions',
290  ];
291  }
292 
293  if ( $blockAllowsUTEdit ) {
294  $a['DisableUTEdit'] = [
295  'type' => 'check',
296  'label-message' => 'ipb-disableusertalk',
297  'default' => false,
298  'section' => 'actions',
299  ];
300  }
301 
302  $defaultExpiry = $this->msg( 'ipb-default-expiry' )->inContentLanguage();
303  if ( $this->type === DatabaseBlock::TYPE_RANGE || $this->type === DatabaseBlock::TYPE_IP ) {
304  $defaultExpiryIP = $this->msg( 'ipb-default-expiry-ip' )->inContentLanguage();
305  if ( !$defaultExpiryIP->isDisabled() ) {
306  $defaultExpiry = $defaultExpiryIP;
307  }
308  }
309 
310  $a['Expiry'] = [
311  'type' => 'expiry',
312  'required' => true,
313  'options' => $suggestedDurations,
314  'default' => $defaultExpiry->text(),
315  'section' => 'expiry',
316  ];
317 
318  $a['Reason'] = [
319  'type' => 'selectandother',
320  // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
321  // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
322  // Unicode codepoints.
324  'maxlength-unit' => 'codepoints',
325  'options-message' => 'ipbreason-dropdown',
326  'section' => 'reason',
327  ];
328 
329  $a['AutoBlock'] = [
330  'type' => 'check',
331  'label-message' => 'ipbenableautoblock',
332  'default' => true,
333  'section' => 'options',
334  ];
335 
336  # Allow some users to hide name from block log, blocklist and listusers
337  if ( $this->getAuthority()->isAllowed( 'hideuser' ) ) {
338  $a['HideUser'] = [
339  'type' => 'check',
340  'label-message' => 'ipbhidename',
341  'cssclass' => 'mw-block-hideuser',
342  'section' => 'options',
343  ];
344  }
345 
346  # Watchlist their user page? (Only if user is logged in)
347  if ( $user->isRegistered() ) {
348  $a['Watch'] = [
349  'type' => 'check',
350  'label-message' => 'ipbwatchuser',
351  'section' => 'options',
352  ];
353  }
354 
355  $a['HardBlock'] = [
356  'type' => 'check',
357  'label-message' => 'ipb-hardblock',
358  'default' => false,
359  'section' => 'options',
360  ];
361 
362  # This is basically a copy of the Target field, but the user can't change it, so we
363  # can see if the warnings we maybe showed to the user before still apply
364  $a['PreviousTarget'] = [
365  'type' => 'hidden',
366  'default' => false,
367  ];
368 
369  # We'll turn this into a checkbox if we need to
370  $a['Confirm'] = [
371  'type' => 'hidden',
372  'default' => '',
373  'label-message' => 'ipb-confirm',
374  'cssclass' => 'mw-block-confirm',
375  ];
376 
377  $this->maybeAlterFormDefaults( $a );
378 
379  // Allow extensions to add more fields
380  $this->getHookRunner()->onSpecialBlockModifyFormFields( $this, $a );
381 
382  return $a;
383  }
384 
390  protected function maybeAlterFormDefaults( &$fields ) {
391  # This will be overwritten by request data
392  $fields['Target']['default'] = (string)$this->target;
393 
394  if ( $this->target ) {
395  $status = $this->blockUtils->validateTarget( $this->target );
396  if ( !$status->isOK() ) {
397  $errors = $status->getErrorsArray();
398  $this->preErrors = array_merge( $this->preErrors, $errors );
399  }
400  }
401 
402  # This won't be
403  $fields['PreviousTarget']['default'] = (string)$this->target;
404 
405  $block = DatabaseBlock::newFromTarget( $this->target );
406 
407  // Populate fields if there is a block that is not an autoblock; if it is a range
408  // block, only populate the fields if the range is the same as $this->target
409  if ( $block instanceof DatabaseBlock && $block->getType() !== DatabaseBlock::TYPE_AUTO
410  && ( $this->type != DatabaseBlock::TYPE_RANGE
411  || $block->getTarget() == $this->target )
412  ) {
413  $fields['HardBlock']['default'] = $block->isHardblock();
414  $fields['CreateAccount']['default'] = $block->isCreateAccountBlocked();
415  $fields['AutoBlock']['default'] = $block->isAutoblocking();
416 
417  if ( isset( $fields['DisableEmail'] ) ) {
418  $fields['DisableEmail']['default'] = $block->isEmailBlocked();
419  }
420 
421  if ( isset( $fields['HideUser'] ) ) {
422  $fields['HideUser']['default'] = $block->getHideName();
423  }
424 
425  if ( isset( $fields['DisableUTEdit'] ) ) {
426  $fields['DisableUTEdit']['default'] = !$block->isUsertalkEditAllowed();
427  }
428 
429  // If the username was hidden (ipb_deleted == 1), don't show the reason
430  // unless this user also has rights to hideuser: T37839
431  if ( !$block->getHideName() || $this->getAuthority()->isAllowed( 'hideuser' ) ) {
432  $fields['Reason']['default'] = $block->getReasonComment()->text;
433  } else {
434  $fields['Reason']['default'] = '';
435  }
436 
437  if ( $this->getRequest()->wasPosted() ) {
438  # Ok, so we got a POST submission asking us to reblock a user. So show the
439  # confirm checkbox; the user will only see it if they haven't previously
440  $fields['Confirm']['type'] = 'check';
441  } else {
442  # We got a target, but it wasn't a POST request, so the user must have gone
443  # to a link like [[Special:Block/User]]. We don't need to show the checkbox
444  # as long as they go ahead and block *that* user
445  $fields['Confirm']['default'] = 1;
446  }
447 
448  if ( $block->getExpiry() == 'infinity' ) {
449  $fields['Expiry']['default'] = 'infinite';
450  } else {
451  $fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->getExpiry() );
452  }
453 
454  if ( !$block->isSitewide() ) {
455  $fields['EditingRestriction']['default'] = 'partial';
456 
457  $pageRestrictions = [];
458  $namespaceRestrictions = [];
459  foreach ( $block->getRestrictions() as $restriction ) {
460  if ( $restriction instanceof PageRestriction && $restriction->getTitle() ) {
461  $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
462  } elseif ( $restriction instanceof NamespaceRestriction ) {
463  $namespaceRestrictions[] = $restriction->getValue();
464  }
465  }
466 
467  // Sort the restrictions so they are in alphabetical order.
468  sort( $pageRestrictions );
469  $fields['PageRestrictions']['default'] = implode( "\n", $pageRestrictions );
470  sort( $namespaceRestrictions );
471  $fields['NamespaceRestrictions']['default'] = implode( "\n", $namespaceRestrictions );
472 
473  if (
474  empty( $pageRestrictions ) &&
475  empty( $namespaceRestrictions )
476  ) {
477  $fields['Editing']['default'] = false;
478  }
479  }
480 
481  $this->alreadyBlocked = true;
482  $this->preErrors[] = [ 'ipb-needreblock', wfEscapeWikiText( (string)$block->getTarget() ) ];
483  }
484 
485  if ( $this->alreadyBlocked || $this->getRequest()->wasPosted()
486  || $this->getRequest()->getCheck( 'wpCreateAccount' )
487  ) {
488  $this->getOutput()->addJsConfigVars( 'wgCreateAccountDirty', true );
489  }
490 
491  # We always need confirmation to do HideUser
492  if ( $this->requestedHideUser ) {
493  $fields['Confirm']['type'] = 'check';
494  unset( $fields['Confirm']['default'] );
495  $this->preErrors[] = [ 'ipb-confirmhideuser', 'ipb-confirmaction' ];
496  }
497 
498  # Or if the user is trying to block themselves
499  if ( (string)$this->target === $this->getUser()->getName() ) {
500  $fields['Confirm']['type'] = 'check';
501  unset( $fields['Confirm']['default'] );
502  $this->preErrors[] = [ 'ipb-blockingself', 'ipb-confirmaction' ];
503  }
504  }
505 
510  protected function preText() {
511  $this->getOutput()->addModuleStyles( [
512  'mediawiki.widgets.TagMultiselectWidget.styles',
513  'mediawiki.special',
514  ] );
515  $this->getOutput()->addModules( [ 'mediawiki.special.block' ] );
516 
517  $blockCIDRLimit = $this->getConfig()->get( 'BlockCIDRLimit' );
518  $text = $this->msg( 'blockiptext', $blockCIDRLimit['IPv4'], $blockCIDRLimit['IPv6'] )->parse();
519 
520  $otherBlockMessages = [];
521  if ( $this->target !== null ) {
522  $targetName = $this->target;
523  if ( $this->target instanceof User ) {
524  $targetName = $this->target->getName();
525  }
526  # Get other blocks, i.e. from GlobalBlocking or TorBlock extension
527  $this->getHookRunner()->onOtherBlockLogLink(
528  $otherBlockMessages, $targetName );
529 
530  if ( count( $otherBlockMessages ) ) {
532  'h2',
533  [],
534  $this->msg( 'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse()
535  ) . "\n";
536 
537  $list = '';
538 
539  foreach ( $otherBlockMessages as $link ) {
540  $list .= Html::rawElement( 'li', [], $link ) . "\n";
541  }
542 
543  $s .= Html::rawElement(
544  'ul',
545  [ 'class' => 'mw-blockip-alreadyblocked' ],
546  $list
547  ) . "\n";
548 
549  $text .= $s;
550  }
551  }
552 
553  return $text;
554  }
555 
560  protected function postText() {
561  $links = [];
562 
563  $this->getOutput()->addModuleStyles( 'mediawiki.special' );
564 
565  $linkRenderer = $this->getLinkRenderer();
566  # Link to the user's contributions, if applicable
567  if ( $this->target instanceof User ) {
568  $contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() );
569  $links[] = $linkRenderer->makeLink(
570  $contribsPage,
571  $this->msg( 'ipb-blocklist-contribs', $this->target->getName() )->text()
572  );
573  }
574 
575  # Link to unblock the specified user, or to a blank unblock form
576  if ( $this->target instanceof User ) {
577  $message = $this->msg(
578  'ipb-unblock-addr',
579  wfEscapeWikiText( $this->target->getName() )
580  )->parse();
581  $list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() );
582  } else {
583  $message = $this->msg( 'ipb-unblock' )->parse();
584  $list = SpecialPage::getTitleFor( 'Unblock' );
585  }
586  $links[] = $linkRenderer->makeKnownLink(
587  $list,
588  new HtmlArmor( $message )
589  );
590 
591  # Link to the block list
592  $links[] = $linkRenderer->makeKnownLink(
593  SpecialPage::getTitleFor( 'BlockList' ),
594  $this->msg( 'ipb-blocklist' )->text()
595  );
596 
597  # Link to edit the block dropdown reasons, if applicable
598  if ( $this->getAuthority()->isAllowed( 'editinterface' ) ) {
599  $links[] = $linkRenderer->makeKnownLink(
600  $this->msg( 'ipbreason-dropdown' )->inContentLanguage()->getTitle(),
601  $this->msg( 'ipb-edit-dropdown' )->text(),
602  [],
603  [ 'action' => 'edit' ]
604  );
605  }
606 
607  $text = Html::rawElement(
608  'p',
609  [ 'class' => 'mw-ipb-conveniencelinks' ],
610  $this->getLanguage()->pipeList( $links )
611  );
612 
613  $userTitle = self::getTargetUserTitle( $this->target );
614  if ( $userTitle ) {
615  # Get relevant extracts from the block and suppression logs, if possible
616  $out = '';
617 
619  $out,
620  'block',
621  $userTitle,
622  '',
623  [
624  'lim' => 10,
625  'msgKey' => [ 'blocklog-showlog', $userTitle->getText() ],
626  'showIfEmpty' => false
627  ]
628  );
629  $text .= $out;
630 
631  # Add suppression block entries if allowed
632  if ( $this->getAuthority()->isAllowed( 'suppressionlog' ) ) {
634  $out,
635  'suppress',
636  $userTitle,
637  '',
638  [
639  'lim' => 10,
640  'conds' => [ 'log_action' => [ 'block', 'reblock', 'unblock' ] ],
641  'msgKey' => [ 'blocklog-showsuppresslog', $userTitle->getText() ],
642  'showIfEmpty' => false
643  ]
644  );
645 
646  $text .= $out;
647  }
648  }
649 
650  return $text;
651  }
652 
659  protected static function getTargetUserTitle( $target ) {
660  if ( $target instanceof User ) {
661  return $target->getUserPage();
662  } elseif ( IPUtils::isIPAddress( $target ) ) {
664  }
665 
666  return null;
667  }
668 
682  public static function getTargetAndType( ?string $par, WebRequest $request = null ) {
683  if ( !$request instanceof WebRequest ) {
684  return MediaWikiServices::getInstance()->getBlockUtils()->parseBlockTarget( $par );
685  }
686 
687  $possibleTargets = [
688  $request->getVal( 'wpTarget', null ),
689  $par,
690  $request->getVal( 'ip', null ),
691  // B/C @since 1.18
692  $request->getVal( 'wpBlockAddress', null ),
693  ];
694  foreach ( $possibleTargets as $possibleTarget ) {
695  $targetAndType = MediaWikiServices::getInstance()
696  ->getBlockUtils()
697  ->parseBlockTarget( $possibleTarget );
698  // If type is not null then target is valid
699  if ( $targetAndType[ 1 ] !== null ) {
700  break;
701  }
702  }
703  return $targetAndType;
704  }
705 
716  public static function validateTarget( $value, User $user ) {
717  wfDeprecated( __METHOD__, '1.36' );
718 
719  $status = MediaWikiServices::getInstance()->getBlockUtils()->validateTarget( $value );
720 
721  // This is here to make validateTarget to not change its behavior
722  // BlockUtils does not check checkUnblockSelf.
723  list( $target, $type ) = self::getTargetAndType( $value );
724  if ( $type === AbstractBlock::TYPE_USER ) {
725  $unblockStatus = self::checkUnblockSelf( $target, $user );
726  if ( $unblockStatus !== true ) {
727  $status->fatal( 'badaccess', $unblockStatus );
728  }
729  }
730 
731  return $status;
732  }
733 
742  public static function processForm( array $data, IContextSource $context ) {
743  $services = MediaWikiServices::getInstance();
745  $data,
746  $context->getAuthority(),
747  $services->getBlockUserFactory(),
748  $services->getBlockUtils()
749  );
750  }
751 
762  private static function processFormInternal(
763  array $data,
764  Authority $performer,
767  ) {
768  $isPartialBlock = isset( $data['EditingRestriction'] ) &&
769  $data['EditingRestriction'] === 'partial';
770 
771  # This might have been a hidden field or a checkbox, so interesting data
772  # can come from it
773  $data['Confirm'] = !in_array( $data['Confirm'], [ '', '0', null, false ], true );
774 
775  # If the user has done the form 'properly', they won't even have been given the
776  # option to suppress-block unless they have the 'hideuser' permission
777  if ( !isset( $data['HideUser'] ) ) {
778  $data['HideUser'] = false;
779  }
780 
782  list( $target, $type ) = $blockUtils->parseBlockTarget( $data['Target'] );
783  if ( $type == DatabaseBlock::TYPE_USER ) {
784  $user = $target;
785  $target = $user->getName();
786  $userId = $user->getId();
787 
788  # Give admins a heads-up before they go and block themselves. Much messier
789  # to do this for IPs, but it's pretty unlikely they'd ever get the 'block'
790  # permission anyway, although the code does allow for it.
791  # Note: Important to use $target instead of $data['Target']
792  # since both $data['PreviousTarget'] and $target are normalized
793  # but $data['target'] gets overridden by (non-normalized) request variable
794  # from previous request.
795  if ( $target === $performer->getUser()->getName() &&
796  ( $data['PreviousTarget'] !== $target || !$data['Confirm'] )
797  ) {
798  return [ 'ipb-blockingself', 'ipb-confirmaction' ];
799  }
800 
801  if ( $data['HideUser'] && !$data['Confirm'] ) {
802  return [ 'ipb-confirmhideuser', 'ipb-confirmaction' ];
803  }
804  } elseif ( $type == DatabaseBlock::TYPE_RANGE ) {
805  $user = null;
806  $userId = 0;
807  } elseif ( $type == DatabaseBlock::TYPE_IP ) {
808  $user = null;
809  $target = $target->getName();
810  $userId = 0;
811  } else {
812  # This should have been caught in the form field validation
813  return [ 'badipaddress' ];
814  }
815 
816  // Reason, to be passed to the block object. For default values of reason, see
817  // HTMLSelectAndOtherField::getDefault
818  // @phan-suppress-next-line PhanPluginDuplicateConditionalNullCoalescing
819  $blockReason = isset( $data['Reason'][0] ) ? $data['Reason'][0] : '';
820 
821  $pageRestrictions = [];
822  $namespaceRestrictions = [];
823  if ( $isPartialBlock ) {
824  if ( isset( $data['PageRestrictions'] ) && $data['PageRestrictions'] !== '' ) {
825  $titles = explode( "\n", $data['PageRestrictions'] );
826  $pageRestrictions = [];
827  foreach ( $titles as $title ) {
828  $pageRestrictions[] = PageRestriction::newFromTitle( $title );
829  }
830  }
831  if ( isset( $data['NamespaceRestrictions'] ) && $data['NamespaceRestrictions'] !== '' ) {
832  $namespaceRestrictions = array_map( static function ( $id ) {
833  return new NamespaceRestriction( 0, $id );
834  }, explode( "\n", $data['NamespaceRestrictions'] ) );
835  }
836  }
837  $restrictions = ( array_merge( $pageRestrictions, $namespaceRestrictions ) );
838 
839  if ( !isset( $data['Tags'] ) ) {
840  $data['Tags'] = [];
841  }
842 
843  $blockOptions = [
844  'isCreateAccountBlocked' => $data['CreateAccount'],
845  'isHardBlock' => $data['HardBlock'],
846  'isAutoblocking' => $data['AutoBlock'],
847  'isHideUser' => $data['HideUser'],
848  'isPartial' => $isPartialBlock,
849  ];
850 
851  if ( isset( $data['DisableUTEdit'] ) ) {
852  $blockOptions['isUserTalkEditBlocked'] = $data['DisableUTEdit'];
853  }
854  if ( isset( $data['DisableEmail'] ) ) {
855  $blockOptions['isEmailBlocked'] = $data['DisableEmail'];
856  }
857 
858  $blockUser = $blockUserFactory->newBlockUser(
859  $target,
860  $performer,
861  $data['Expiry'],
862  $blockReason,
863  $blockOptions,
864  $restrictions,
865  $data['Tags']
866  );
867 
868  # Indicates whether the user is confirming the block and is aware of
869  # the conflict (did not change the block target in the meantime)
870  $blockNotConfirmed = !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
871  && $data['PreviousTarget'] !== $target );
872 
873  # Special case for API - T34434
874  $reblockNotAllowed = ( array_key_exists( 'Reblock', $data ) && !$data['Reblock'] );
875 
876  $doReblock = !$blockNotConfirmed && !$reblockNotAllowed;
877 
878  $status = $blockUser->placeBlock( $doReblock );
879  if ( !$status->isOK() ) {
880  return $status;
881  }
882 
883  # Can't watch a rangeblock
884  if ( $type != DatabaseBlock::TYPE_RANGE && $data['Watch'] ) {
887  $performer,
889  );
890  }
891 
892  return true;
893  }
894 
905  public static function getSuggestedDurations( Language $lang = null, $includeOther = true ) {
906  $msg = $lang === null
907  ? wfMessage( 'ipboptions' )->inContentLanguage()->text()
908  : wfMessage( 'ipboptions' )->inLanguage( $lang )->text();
909 
910  if ( $msg == '-' ) {
911  return [];
912  }
913 
914  $a = XmlSelect::parseOptionsMessage( $msg );
915 
916  if ( $a && $includeOther ) {
917  // if options exist, add other to the end instead of the begining (which
918  // is what happens by default).
919  $a[ wfMessage( 'ipbother' )->text() ] = 'other';
920  }
921 
922  return $a;
923  }
924 
934  public static function parseExpiryInput( $expiry ) {
935  return BlockUser::parseExpiryInput( $expiry );
936  }
937 
945  public static function canBlockEmail( UserIdentity $user ) {
946  return MediaWikiServices::getInstance()
947  ->getBlockPermissionCheckerFactory()
948  ->newBlockPermissionChecker( null, User::newFromIdentity( $user ) )
949  ->checkEmailPermissions();
950  }
951 
966  public static function checkUnblockSelf( $target, Authority $performer ) {
967  return MediaWikiServices::getInstance()
968  ->getBlockPermissionCheckerFactory()
969  ->newBlockPermissionChecker( $target, $performer )
970  ->checkBlockPermissions();
971  }
972 
979  public function onSubmit( array $data, HTMLForm $form = null ) {
980  // If "Editing" checkbox is unchecked, the block must be a partial block affecting
981  // actions other than editing, and there must be no restrictions.
982  if ( isset( $data['Editing'] ) && $data['Editing'] === false ) {
983  $data['EditingRestriction'] = 'partial';
984  $data['PageRestrictions'] = '';
985  $data['NamespaceRestrictions'] = '';
986  }
988  $data,
989  $this->getAuthority(),
990  $this->blockUserFactory,
991  $this->blockUtils
992  );
993  }
994 
999  public function onSuccess() {
1000  $out = $this->getOutput();
1001  $out->setPageTitle( $this->msg( 'blockipsuccesssub' ) );
1002  $out->addWikiMsg( 'blockipsuccesstext', wfEscapeWikiText( $this->target ) );
1003  }
1004 
1013  public function prefixSearchSubpages( $search, $limit, $offset ) {
1014  $search = $this->userNameUtils->getCanonical( $search );
1015  if ( !$search ) {
1016  // No prefix suggestion for invalid user
1017  return [];
1018  }
1019  // Autocomplete subpage as user list - public to allow caching
1020  return $this->userNamePrefixSearch
1021  ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1022  }
1023 
1024  protected function getGroupName() {
1025  return 'users';
1026  }
1027 }
SpecialPage\$linkRenderer
LinkRenderer null $linkRenderer
Definition: SpecialPage.php:80
SpecialBlock\checkUnblockSelf
static checkUnblockSelf( $target, Authority $performer)
T17810: Sitewide blocked admins should not be able to block/unblock others with one exception; they c...
Definition: SpecialBlock.php:966
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:911
SpecialBlock\$blockUserFactory
BlockUserFactory $blockUserFactory
Definition: SpecialBlock.php:54
MediaWiki\Block\Restriction\PageRestriction\getTitle
getTitle()
Definition: PageRestriction.php:68
MediaWiki\Block\BlockPermissionCheckerFactory
Factory class for BlockPermissionChecker.
Definition: BlockPermissionCheckerFactory.php:34
HtmlArmor
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:30
SpecialBlock\canBlockEmail
static canBlockEmail(UserIdentity $user)
Can we do an email block?
Definition: SpecialBlock.php:945
MediaWiki\Block\BlockUserFactory
Definition: BlockUserFactory.php:30
SpecialBlock\onSuccess
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
Definition: SpecialBlock.php:999
SpecialBlock\$userNamePrefixSearch
UserNamePrefixSearch $userNamePrefixSearch
Definition: SpecialBlock.php:60
SpecialBlock\$type
int $type
DatabaseBlock::TYPE_ constant.
Definition: SpecialBlock.php:68
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:789
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:173
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
SpecialBlock\$preErrors
array $preErrors
Definition: SpecialBlock.php:80
HTMLForm\addHeaderText
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition: HTMLForm.php:826
SpecialBlock\$requestedHideUser
bool $requestedHideUser
Whether the previous submission of the form asked for HideUser.
Definition: SpecialBlock.php:74
SpecialBlock\processForm
static processForm(array $data, IContextSource $context)
Given the form data, actually implement a block.
Definition: SpecialBlock.php:742
SpecialBlock\preText
preText()
Add header elements like block log entries, etc.
Definition: SpecialBlock.php:510
MediaWiki\Block\BlockUser
Handles the backend logic of blocking users.
Definition: BlockUser.php:48
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1832
MediaWiki\Block\BlockUtils
Backend class for blocking utils.
Definition: BlockUtils.php:44
HTMLForm\setHeaderText
setHeaderText( $msg, $section=null)
Set header text, inside the form.
Definition: HTMLForm.php:848
HTMLForm\formatErrors
formatErrors( $errors)
Format a stack of error messages into a single HTML string.
Definition: HTMLForm.php:1371
MediaWiki\Block\DatabaseBlock\getType
getType()
Get the type of target for this particular block.int|null AbstractBlock::TYPE_ constant,...
Definition: DatabaseBlock.php:1106
SpecialBlock\$blockPermissionCheckerFactory
BlockPermissionCheckerFactory $blockPermissionCheckerFactory
Definition: SpecialBlock.php:51
SpecialBlock\$target
User string null $target
User to be blocked, as passed either by parameter (url?wpTarget=Foo) or as subpage (Special:Block/Foo...
Definition: SpecialBlock.php:65
SpecialBlock\$previousTarget
User string $previousTarget
The previous block target.
Definition: SpecialBlock.php:71
SpecialBlock\getTargetAndType
static getTargetAndType(?string $par, WebRequest $request=null)
Get the target and type, given the request and the subpage parameter.
Definition: SpecialBlock.php:682
SpecialBlock\onSubmit
onSubmit(array $data, HTMLForm $form=null)
Process the form on POST submission.
Definition: SpecialBlock.php:979
FormSpecialPage
Special page which uses an HTMLForm to handle processing.
Definition: FormSpecialPage.php:31
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1231
User\getUserPage
getUserPage()
Get this user's personal page title.
Definition: User.php:3763
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Definition: SpecialPage.php:107
SpecialPage\getSkin
getSkin()
Shortcut to get the skin being used for this instance.
Definition: SpecialPage.php:819
User\newFromIdentity
static newFromIdentity(UserIdentity $identity)
Returns a User object corresponding to the given UserIdentity.
Definition: User.php:663
SpecialPage\getAuthority
getAuthority()
Shortcut to get the Authority executing this instance.
Definition: SpecialPage.php:809
SpecialBlock\doesWrites
doesWrites()
Indicates whether this special page may perform database writes.
Definition: SpecialBlock.php:105
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:829
SpecialBlock\checkExecutePermissions
checkExecutePermissions(User $user)
Checks that the user can unblock themselves if they are trying to do so.
Definition: SpecialBlock.php:115
IContextSource\getAuthority
getAuthority()
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:179
SpecialBlock\setParameter
setParameter( $par)
Handle some magic here.
Definition: SpecialBlock.php:140
XmlSelect\parseOptionsMessage
static parseOptionsMessage(string $msg)
Parse labels and values out of a comma- and colon-separated list of options, such as is used for expi...
Definition: XmlSelect.php:145
MediaWiki\Permissions\Authority\getUser
getUser()
Returns the performer of the actions associated with this authority.
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
SpecialBlock\__construct
__construct(BlockUtils $blockUtils, BlockPermissionCheckerFactory $blockPermissionCheckerFactory, BlockUserFactory $blockUserFactory, UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch)
Definition: SpecialBlock.php:89
SpecialBlock\postText
postText()
Add footer elements to the form.
Definition: SpecialBlock.php:560
MediaWiki\Block\DatabaseBlock
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Definition: DatabaseBlock.php:53
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:947
SpecialPage\getHookRunner
getHookRunner()
Definition: SpecialPage.php:1094
SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
Definition: SpecialPage.php:877
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1034
SpecialBlock\maybeAlterFormDefaults
maybeAlterFormDefaults(&$fields)
If the user has already been blocked with similar settings, load that block and change the defaults f...
Definition: SpecialBlock.php:390
SpecialBlock\alterForm
alterForm(HTMLForm $form)
Customizes the HTMLForm a bit.
Definition: SpecialBlock.php:162
SpecialBlock
A special page that allows users with 'block' right to block users from editing pages and other actio...
Definition: SpecialBlock.php:45
MediaWiki\User\UserNamePrefixSearch
Handles searching prefixes of user names.
Definition: UserNamePrefixSearch.php:39
SpecialBlock\$blockUtils
BlockUtils $blockUtils
Definition: SpecialBlock.php:48
SpecialBlock\getTargetUserTitle
static getTargetUserTitle( $target)
Get a user page target for things like logs.
Definition: SpecialBlock.php:659
$title
$title
Definition: testCompression.php:38
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:799
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:626
LogEventsList\showLogExtract
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Definition: LogEventsList.php:602
SpecialBlock\prefixSearchSubpages
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
Definition: SpecialBlock.php:1013
FormSpecialPage\$par
string null $par
The sub-page of the special page.
Definition: FormSpecialPage.php:36
MediaWiki\Permissions\Authority
Definition: Authority.php:30
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:652
$s
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
Definition: mergeMessageFileList.php:206
WatchAction\doWatch
static doWatch(Title $title, Authority $performer, $checkRights=User::CHECK_USER_RIGHTS, ?string $expiry=null)
Watch a page.
Definition: WatchAction.php:295
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:779
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1505
SpecialBlock\getFormFields
getFormFields()
Get the HTMLForm descriptor array for the block form.
Definition: SpecialBlock.php:192
NS_USER
const NS_USER
Definition: Defines.php:66
HTMLForm\setSubmitDestructive
setSubmitDestructive()
Identify that the submit button in the form has a destructive action.
Definition: HTMLForm.php:1406
SpecialBlock\$userNameUtils
UserNameUtils $userNameUtils
Definition: SpecialBlock.php:57
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:57
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:42
MediaWiki\Block\Restriction\NamespaceRestriction
Definition: NamespaceRestriction.php:25
CommentStore\COMMENT_CHARACTER_LIMIT
const COMMENT_CHARACTER_LIMIT
Maximum length of a comment in UTF-8 characters.
Definition: CommentStore.php:48
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1420
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:1027
MediaWiki\Block\Restriction\PageRestriction
Definition: PageRestriction.php:25
SpecialBlock\$alreadyBlocked
bool $alreadyBlocked
Definition: SpecialBlock.php:77
MediaWiki\Block\BlockUserFactory\newBlockUser
newBlockUser( $target, Authority $performer, string $expiry, string $reason='', array $blockOptions=[], array $blockRestrictions=[], $tags=[])
Create BlockUser.
MediaWiki\User\UserNameUtils
UserNameUtils service.
Definition: UserNameUtils.php:42
SpecialBlock\validateTarget
static validateTarget( $value, User $user)
Validate a block target.
Definition: SpecialBlock.php:716
SpecialBlock\processFormInternal
static processFormInternal(array $data, Authority $performer, BlockUserFactory $blockUserFactory, BlockUtils $blockUtils)
Implementation details for processForm Own function to allow sharing the deprecated code with non-dep...
Definition: SpecialBlock.php:762
SpecialBlock\getDisplayFormat
getDisplayFormat()
Get display format for the form.
Definition: SpecialBlock.php:184
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
getTitle
getTitle()
Definition: RevisionSearchResultTrait.php:81
SpecialBlock\parseExpiryInput
static parseExpiryInput( $expiry)
Convert a submitted expiry time, which may be relative ("2 weeks", etc) or absolute ("24 May 2034",...
Definition: SpecialBlock.php:934
SpecialBlock\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialBlock.php:1024
SpecialBlock\getSuggestedDurations
static getSuggestedDurations(Language $lang=null, $includeOther=true)
Get an array of suggested block durations from MediaWiki:Ipboptions.
Definition: SpecialBlock.php:905
MediaWiki\Block\AbstractBlock
Definition: AbstractBlock.php:37
User\IGNORE_USER_RIGHTS
const IGNORE_USER_RIGHTS
Definition: User.php:101
MediaWiki\Block\BlockUtils\parseBlockTarget
parseBlockTarget( $target)
From an existing block, get the target and the type of target.
Definition: BlockUtils.php:83
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:30
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:66
User\getName
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:2113
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:43
SpecialBlock\requiresUnblock
requiresUnblock()
We allow certain special cases where user is blocked.
Definition: SpecialBlock.php:131
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:140