MediaWiki  master
SpecialBlock.php
Go to the documentation of this file.
1 <?php
30 use Wikimedia\IPUtils;
31 
43 
47  protected $target;
48 
50  protected $type;
51 
53  protected $previousTarget;
54 
56  protected $requestedHideUser;
57 
59  protected $alreadyBlocked;
60 
62  protected $preErrors = [];
63 
65  parent::__construct( 'Block', 'block' );
66 
67  $this->permissionManager = $permissionManager;
68  }
69 
70  public function doesWrites() {
71  return true;
72  }
73 
80  protected function checkExecutePermissions( User $user ) {
81  parent::checkExecutePermissions( $user );
82  # T17810: blocked admins should have limited access here
83  $status = self::checkUnblockSelf( $this->target, $user );
84  if ( $status !== true ) {
85  throw new ErrorPageError( 'badaccess', $status );
86  }
87  }
88 
94  public function requiresUnblock() {
95  return false;
96  }
97 
103  protected function setParameter( $par ) {
104  # Extract variables from the request. Try not to get into a situation where we
105  # need to extract *every* variable from the form just for processing here, but
106  # there are legitimate uses for some variables
107  $request = $this->getRequest();
108  list( $this->target, $this->type ) = self::getTargetAndType( $par, $request );
109  if ( $this->target instanceof User ) {
110  # Set the 'relevant user' in the skin, so it displays links like Contributions,
111  # User logs, UserRights, etc.
112  $this->getSkin()->setRelevantUser( $this->target );
113  }
114 
115  list( $this->previousTarget, /*...*/ ) =
116  DatabaseBlock::parseTarget( $request->getVal( 'wpPreviousTarget' ) );
117  $this->requestedHideUser = $request->getBool( 'wpHideUser' );
118  }
119 
125  protected function alterForm( HTMLForm $form ) {
126  $form->setHeaderText( '' );
127  $form->setSubmitDestructive();
128 
129  $msg = $this->alreadyBlocked ? 'ipb-change-block' : 'ipbsubmit';
130  $form->setSubmitTextMsg( $msg );
131 
132  $this->addHelpLink( 'Help:Blocking users' );
133 
134  # Don't need to do anything if the form has been posted
135  if ( !$this->getRequest()->wasPosted() && $this->preErrors ) {
136  $s = $form->formatErrors( $this->preErrors );
137  if ( $s ) {
139  'div',
140  [ 'class' => 'error' ],
141  $s
142  ) );
143  }
144  }
145  }
146 
147  protected function getDisplayFormat() {
148  return 'ooui';
149  }
150 
155  protected function getFormFields() {
156  $conf = $this->getConfig();
157  $blockAllowsUTEdit = $conf->get( 'BlockAllowsUTEdit' );
158 
159  $this->getOutput()->enableOOUI();
160 
161  $user = $this->getUser();
162 
163  $suggestedDurations = self::getSuggestedDurations();
164 
165  $a = [];
166 
167  $a['Target'] = [
168  'type' => 'user',
169  'ipallowed' => true,
170  'iprange' => true,
171  'id' => 'mw-bi-target',
172  'size' => '45',
173  'autofocus' => true,
174  'required' => true,
175  'validation-callback' => [ __CLASS__, 'validateTargetField' ],
176  'section' => 'target',
177  ];
178 
179  $a['Editing'] = [
180  'type' => 'check',
181  'label-message' => 'block-prevent-edit',
182  'default' => true,
183  'section' => 'actions',
184  ];
185 
186  $a['EditingRestriction'] = [
187  'type' => 'radio',
188  'cssclass' => 'mw-block-editing-restriction',
189  'default' => 'sitewide',
190  'options' => [
191  $this->msg( 'ipb-sitewide' )->escaped() .
192  new \OOUI\LabelWidget( [
193  'classes' => [ 'oo-ui-inline-help' ],
194  'label' => $this->msg( 'ipb-sitewide-help' )->text(),
195  ] ) => 'sitewide',
196  $this->msg( 'ipb-partial' )->escaped() .
197  new \OOUI\LabelWidget( [
198  'classes' => [ 'oo-ui-inline-help' ],
199  'label' => $this->msg( 'ipb-partial-help' )->text(),
200  ] ) => 'partial',
201  ],
202  'section' => 'actions',
203  ];
204 
205  $a['PageRestrictions'] = [
206  'type' => 'titlesmultiselect',
207  'label' => $this->msg( 'ipb-pages-label' )->text(),
208  'exists' => true,
209  'max' => 10,
210  'cssclass' => 'mw-block-restriction',
211  'showMissing' => false,
212  'excludeDynamicNamespaces' => true,
213  'input' => [
214  'autocomplete' => false
215  ],
216  'section' => 'actions',
217  ];
218 
219  $a['NamespaceRestrictions'] = [
220  'type' => 'namespacesmultiselect',
221  'label' => $this->msg( 'ipb-namespaces-label' )->text(),
222  'exists' => true,
223  'cssclass' => 'mw-block-restriction',
224  'input' => [
225  'autocomplete' => false
226  ],
227  'section' => 'actions',
228  ];
229 
230  $a['CreateAccount'] = [
231  'type' => 'check',
232  'label-message' => 'ipbcreateaccount',
233  'default' => true,
234  'section' => 'actions',
235  ];
236 
237  if ( self::canBlockEmail( $user ) ) {
238  $a['DisableEmail'] = [
239  'type' => 'check',
240  'label-message' => 'ipbemailban',
241  'section' => 'actions',
242  ];
243  }
244 
245  if ( $blockAllowsUTEdit ) {
246  $a['DisableUTEdit'] = [
247  'type' => 'check',
248  'label-message' => 'ipb-disableusertalk',
249  'default' => false,
250  'section' => 'actions',
251  ];
252  }
253 
254  $defaultExpiry = $this->msg( 'ipb-default-expiry' )->inContentLanguage();
255  if ( $this->type === DatabaseBlock::TYPE_RANGE || $this->type === DatabaseBlock::TYPE_IP ) {
256  $defaultExpiryIP = $this->msg( 'ipb-default-expiry-ip' )->inContentLanguage();
257  if ( !$defaultExpiryIP->isDisabled() ) {
258  $defaultExpiry = $defaultExpiryIP;
259  }
260  }
261 
262  $a['Expiry'] = [
263  'type' => 'expiry',
264  'required' => true,
265  'options' => $suggestedDurations,
266  'default' => $defaultExpiry->text(),
267  'section' => 'expiry',
268  ];
269 
270  $a['Reason'] = [
271  'type' => 'selectandother',
272  // HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
273  // (e.g. emojis) count for two each. This limit is overridden in JS to instead count
274  // Unicode codepoints.
276  'maxlength-unit' => 'codepoints',
277  'options-message' => 'ipbreason-dropdown',
278  'section' => 'reason',
279  ];
280 
281  $a['AutoBlock'] = [
282  'type' => 'check',
283  'label-message' => 'ipbenableautoblock',
284  'default' => true,
285  'section' => 'options',
286  ];
287 
288  # Allow some users to hide name from block log, blocklist and listusers
289  if ( $this->permissionManager->userHasRight( $user, 'hideuser' ) ) {
290  $a['HideUser'] = [
291  'type' => 'check',
292  'label-message' => 'ipbhidename',
293  'cssclass' => 'mw-block-hideuser',
294  'section' => 'options',
295  ];
296  }
297 
298  # Watchlist their user page? (Only if user is logged in)
299  if ( $user->isLoggedIn() ) {
300  $a['Watch'] = [
301  'type' => 'check',
302  'label-message' => 'ipbwatchuser',
303  'section' => 'options',
304  ];
305  }
306 
307  $a['HardBlock'] = [
308  'type' => 'check',
309  'label-message' => 'ipb-hardblock',
310  'default' => false,
311  'section' => 'options',
312  ];
313 
314  # This is basically a copy of the Target field, but the user can't change it, so we
315  # can see if the warnings we maybe showed to the user before still apply
316  $a['PreviousTarget'] = [
317  'type' => 'hidden',
318  'default' => false,
319  ];
320 
321  # We'll turn this into a checkbox if we need to
322  $a['Confirm'] = [
323  'type' => 'hidden',
324  'default' => '',
325  'label-message' => 'ipb-confirm',
326  'cssclass' => 'mw-block-confirm',
327  ];
328 
329  $this->maybeAlterFormDefaults( $a );
330 
331  // Allow extensions to add more fields
332  $this->getHookRunner()->onSpecialBlockModifyFormFields( $this, $a );
333 
334  return $a;
335  }
336 
342  protected function maybeAlterFormDefaults( &$fields ) {
343  # This will be overwritten by request data
344  $fields['Target']['default'] = (string)$this->target;
345 
346  if ( $this->target ) {
347  $status = self::validateTarget( $this->target, $this->getUser() );
348  if ( !$status->isOK() ) {
349  $errors = $status->getErrorsArray();
350  $this->preErrors = array_merge( $this->preErrors, $errors );
351  }
352  }
353 
354  # This won't be
355  $fields['PreviousTarget']['default'] = (string)$this->target;
356 
357  $block = DatabaseBlock::newFromTarget( $this->target );
358 
359  // Populate fields if there is a block that is not an autoblock; if it is a range
360  // block, only populate the fields if the range is the same as $this->target
361  if ( $block instanceof DatabaseBlock && $block->getType() !== DatabaseBlock::TYPE_AUTO
362  && ( $this->type != DatabaseBlock::TYPE_RANGE
363  || $block->getTarget() == $this->target )
364  ) {
365  $fields['HardBlock']['default'] = $block->isHardblock();
366  $fields['CreateAccount']['default'] = $block->isCreateAccountBlocked();
367  $fields['AutoBlock']['default'] = $block->isAutoblocking();
368 
369  if ( isset( $fields['DisableEmail'] ) ) {
370  $fields['DisableEmail']['default'] = $block->isEmailBlocked();
371  }
372 
373  if ( isset( $fields['HideUser'] ) ) {
374  $fields['HideUser']['default'] = $block->getHideName();
375  }
376 
377  if ( isset( $fields['DisableUTEdit'] ) ) {
378  $fields['DisableUTEdit']['default'] = !$block->isUsertalkEditAllowed();
379  }
380 
381  // If the username was hidden (ipb_deleted == 1), don't show the reason
382  // unless this user also has rights to hideuser: T37839
383  if ( !$block->getHideName() || $this->permissionManager
384  ->userHasRight( $this->getUser(), 'hideuser' )
385  ) {
386  $fields['Reason']['default'] = $block->getReasonComment()->text;
387  } else {
388  $fields['Reason']['default'] = '';
389  }
390 
391  if ( $this->getRequest()->wasPosted() ) {
392  # Ok, so we got a POST submission asking us to reblock a user. So show the
393  # confirm checkbox; the user will only see it if they haven't previously
394  $fields['Confirm']['type'] = 'check';
395  } else {
396  # We got a target, but it wasn't a POST request, so the user must have gone
397  # to a link like [[Special:Block/User]]. We don't need to show the checkbox
398  # as long as they go ahead and block *that* user
399  $fields['Confirm']['default'] = 1;
400  }
401 
402  if ( $block->getExpiry() == 'infinity' ) {
403  $fields['Expiry']['default'] = 'infinite';
404  } else {
405  $fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->getExpiry() );
406  }
407 
408  if ( !$block->isSitewide() ) {
409  $fields['EditingRestriction']['default'] = 'partial';
410 
411  $pageRestrictions = [];
412  $namespaceRestrictions = [];
413  foreach ( $block->getRestrictions() as $restriction ) {
414  if ( $restriction instanceof PageRestriction && $restriction->getTitle() ) {
415  $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
416  } elseif ( $restriction instanceof NamespaceRestriction ) {
417  $namespaceRestrictions[] = $restriction->getValue();
418  }
419  }
420 
421  // Sort the restrictions so they are in alphabetical order.
422  sort( $pageRestrictions );
423  $fields['PageRestrictions']['default'] = implode( "\n", $pageRestrictions );
424  sort( $namespaceRestrictions );
425  $fields['NamespaceRestrictions']['default'] = implode( "\n", $namespaceRestrictions );
426 
427  if (
428  empty( $pageRestrictions ) &&
429  empty( $namespaceRestrictions )
430  ) {
431  $fields['Editing']['default'] = false;
432  }
433  }
434 
435  $this->alreadyBlocked = true;
436  $this->preErrors[] = [ 'ipb-needreblock', wfEscapeWikiText( (string)$block->getTarget() ) ];
437  }
438 
439  if ( $this->alreadyBlocked || $this->getRequest()->wasPosted()
440  || $this->getRequest()->getCheck( 'wpCreateAccount' )
441  ) {
442  $this->getOutput()->addJsConfigVars( 'wgCreateAccountDirty', true );
443  }
444 
445  # We always need confirmation to do HideUser
446  if ( $this->requestedHideUser ) {
447  $fields['Confirm']['type'] = 'check';
448  unset( $fields['Confirm']['default'] );
449  $this->preErrors[] = [ 'ipb-confirmhideuser', 'ipb-confirmaction' ];
450  }
451 
452  # Or if the user is trying to block themselves
453  if ( (string)$this->target === $this->getUser()->getName() ) {
454  $fields['Confirm']['type'] = 'check';
455  unset( $fields['Confirm']['default'] );
456  $this->preErrors[] = [ 'ipb-blockingself', 'ipb-confirmaction' ];
457  }
458  }
459 
464  protected function preText() {
465  $this->getOutput()->addModuleStyles( [
466  'mediawiki.widgets.TagMultiselectWidget.styles',
467  'mediawiki.special',
468  ] );
469  $this->getOutput()->addModules( [ 'mediawiki.special.block' ] );
470 
471  $blockCIDRLimit = $this->getConfig()->get( 'BlockCIDRLimit' );
472  $text = $this->msg( 'blockiptext', $blockCIDRLimit['IPv4'], $blockCIDRLimit['IPv6'] )->parse();
473 
474  $otherBlockMessages = [];
475  if ( $this->target !== null ) {
476  $targetName = $this->target;
477  if ( $this->target instanceof User ) {
478  $targetName = $this->target->getName();
479  }
480  # Get other blocks, i.e. from GlobalBlocking or TorBlock extension
481  $this->getHookRunner()->onOtherBlockLogLink(
482  $otherBlockMessages, $targetName );
483 
484  if ( count( $otherBlockMessages ) ) {
486  'h2',
487  [],
488  $this->msg( 'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse()
489  ) . "\n";
490 
491  $list = '';
492 
493  foreach ( $otherBlockMessages as $link ) {
494  $list .= Html::rawElement( 'li', [], $link ) . "\n";
495  }
496 
497  $s .= Html::rawElement(
498  'ul',
499  [ 'class' => 'mw-blockip-alreadyblocked' ],
500  $list
501  ) . "\n";
502 
503  $text .= $s;
504  }
505  }
506 
507  return $text;
508  }
509 
514  protected function postText() {
515  $links = [];
516 
517  $this->getOutput()->addModuleStyles( 'mediawiki.special' );
518 
519  $linkRenderer = $this->getLinkRenderer();
520  # Link to the user's contributions, if applicable
521  if ( $this->target instanceof User ) {
522  $contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() );
523  $links[] = $linkRenderer->makeLink(
524  $contribsPage,
525  $this->msg( 'ipb-blocklist-contribs', $this->target->getName() )->text()
526  );
527  }
528 
529  # Link to unblock the specified user, or to a blank unblock form
530  if ( $this->target instanceof User ) {
531  $message = $this->msg(
532  'ipb-unblock-addr',
533  wfEscapeWikiText( $this->target->getName() )
534  )->parse();
535  $list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() );
536  } else {
537  $message = $this->msg( 'ipb-unblock' )->parse();
538  $list = SpecialPage::getTitleFor( 'Unblock' );
539  }
540  $links[] = $linkRenderer->makeKnownLink(
541  $list,
542  new HtmlArmor( $message )
543  );
544 
545  # Link to the block list
546  $links[] = $linkRenderer->makeKnownLink(
547  SpecialPage::getTitleFor( 'BlockList' ),
548  $this->msg( 'ipb-blocklist' )->text()
549  );
550 
551  $user = $this->getUser();
552 
553  # Link to edit the block dropdown reasons, if applicable
554  if ( $this->permissionManager->userHasRight( $user, 'editinterface' ) ) {
555  $links[] = $linkRenderer->makeKnownLink(
556  $this->msg( 'ipbreason-dropdown' )->inContentLanguage()->getTitle(),
557  $this->msg( 'ipb-edit-dropdown' )->text(),
558  [],
559  [ 'action' => 'edit' ]
560  );
561  }
562 
563  $text = Html::rawElement(
564  'p',
565  [ 'class' => 'mw-ipb-conveniencelinks' ],
566  $this->getLanguage()->pipeList( $links )
567  );
568 
569  $userTitle = self::getTargetUserTitle( $this->target );
570  if ( $userTitle ) {
571  # Get relevant extracts from the block and suppression logs, if possible
572  $out = '';
573 
575  $out,
576  'block',
577  $userTitle,
578  '',
579  [
580  'lim' => 10,
581  'msgKey' => [ 'blocklog-showlog', $userTitle->getText() ],
582  'showIfEmpty' => false
583  ]
584  );
585  $text .= $out;
586 
587  # Add suppression block entries if allowed
588  if ( $this->permissionManager->userHasRight( $user, 'suppressionlog' ) ) {
590  $out,
591  'suppress',
592  $userTitle,
593  '',
594  [
595  'lim' => 10,
596  'conds' => [ 'log_action' => [ 'block', 'reblock', 'unblock' ] ],
597  'msgKey' => [ 'blocklog-showsuppresslog', $userTitle->getText() ],
598  'showIfEmpty' => false
599  ]
600  );
601 
602  $text .= $out;
603  }
604  }
605 
606  return $text;
607  }
608 
615  protected static function getTargetUserTitle( $target ) {
616  if ( $target instanceof User ) {
617  return $target->getUserPage();
618  } elseif ( IPUtils::isIPAddress( $target ) ) {
620  }
621 
622  return null;
623  }
624 
634  public static function getTargetAndType( $par, WebRequest $request = null ) {
635  $i = 0;
636  $target = null;
637 
638  while ( true ) {
639  switch ( $i++ ) {
640  case 0:
641  # The HTMLForm will check wpTarget first and only if it doesn't get
642  # a value use the default, which will be generated from the options
643  # below; so this has to have a higher precedence here than $par, or
644  # we could end up with different values in $this->target and the HTMLForm!
645  if ( $request instanceof WebRequest ) {
646  $target = $request->getText( 'wpTarget', null );
647  }
648  break;
649  case 1:
650  $target = $par;
651  break;
652  case 2:
653  if ( $request instanceof WebRequest ) {
654  $target = $request->getText( 'ip', null );
655  }
656  break;
657  case 3:
658  # B/C @since 1.18
659  if ( $request instanceof WebRequest ) {
660  $target = $request->getText( 'wpBlockAddress', null );
661  }
662  break;
663  case 4:
664  break 2;
665  }
666 
667  list( $target, $type ) = DatabaseBlock::parseTarget( $target );
668 
669  if ( $type !== null ) {
670  return [ $target, $type ];
671  }
672  }
673 
674  return [ null, null ];
675  }
676 
685  public static function validateTargetField( $value, $alldata, $form ) {
686  $status = self::validateTarget( $value, $form->getUser() );
687  if ( !$status->isOK() ) {
688  $errors = $status->getErrorsArray();
689 
690  return $form->msg( ...$errors[0] );
691  } else {
692  return true;
693  }
694  }
695 
704  public static function validateTarget( $value, User $user ) {
705  global $wgBlockCIDRLimit;
706 
708  list( $target, $type ) = self::getTargetAndType( $value );
709  $status = Status::newGood( $target );
710 
711  if ( $type == DatabaseBlock::TYPE_USER ) {
712  if ( $target->isAnon() ) {
713  $status->fatal(
714  'nosuchusershort',
716  );
717  }
718 
719  $unblockStatus = self::checkUnblockSelf( $target, $user );
720  if ( $unblockStatus !== true ) {
721  $status->fatal( 'badaccess', $unblockStatus );
722  }
723  } elseif ( $type == DatabaseBlock::TYPE_RANGE ) {
724  list( $ip, $range ) = explode( '/', $target, 2 );
725 
726  if (
727  ( IPUtils::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 ) ||
728  ( IPUtils::isIPv6( $ip ) && $wgBlockCIDRLimit['IPv6'] == 128 )
729  ) {
730  // Range block effectively disabled
731  $status->fatal( 'range_block_disabled' );
732  }
733 
734  if (
735  ( IPUtils::isIPv4( $ip ) && $range > 32 ) ||
736  ( IPUtils::isIPv6( $ip ) && $range > 128 )
737  ) {
738  // Dodgy range
739  $status->fatal( 'ip_range_invalid' );
740  }
741 
742  if ( IPUtils::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) {
743  $status->fatal( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv4'] );
744  }
745 
746  if ( IPUtils::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) {
747  $status->fatal( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv6'] );
748  }
749  } elseif ( $type == DatabaseBlock::TYPE_IP ) {
750  # All is well
751  } else {
752  $status->fatal( 'badipaddress' );
753  }
754 
755  return $status;
756  }
757 
765  public static function processForm( array $data, IContextSource $context ) {
766  $performer = $context->getUser();
767  $isPartialBlock = isset( $data['EditingRestriction'] ) &&
768  $data['EditingRestriction'] === 'partial';
769 
770  # This might have been a hidden field or a checkbox, so interesting data
771  # can come from it
772  $data['Confirm'] = !in_array( $data['Confirm'], [ '', '0', null, false ], true );
773 
775  list( $target, $type ) = self::getTargetAndType( $data['Target'] );
776  if ( $type == DatabaseBlock::TYPE_USER ) {
777  $user = $target;
778  $target = $user->getName();
779  $userId = $user->getId();
780 
781  # Give admins a heads-up before they go and block themselves. Much messier
782  # to do this for IPs, but it's pretty unlikely they'd ever get the 'block'
783  # permission anyway, although the code does allow for it.
784  # Note: Important to use $target instead of $data['Target']
785  # since both $data['PreviousTarget'] and $target are normalized
786  # but $data['target'] gets overridden by (non-normalized) request variable
787  # from previous request.
788  if ( $target === $performer->getName() &&
789  ( $data['PreviousTarget'] !== $target || !$data['Confirm'] )
790  ) {
791  return [ 'ipb-blockingself', 'ipb-confirmaction' ];
792  }
793  } elseif ( $type == DatabaseBlock::TYPE_RANGE ) {
794  $user = null;
795  $userId = 0;
796  } elseif ( $type == DatabaseBlock::TYPE_IP ) {
797  $user = null;
798  $target = $target->getName();
799  $userId = 0;
800  } else {
801  # This should have been caught in the form field validation
802  return [ 'badipaddress' ];
803  }
804 
805  // Reason, to be passed to the block object. For default values of reason, see
806  // HTMLSelectAndOtherField::getDefault
807  // @phan-suppress-next-line PhanPluginDuplicateConditionalNullCoalescing
808  $blockReason = isset( $data['Reason'][0] ) ? $data['Reason'][0] : '';
809 
810  $expiryTime = self::parseExpiryInput( $data['Expiry'] );
811 
812  if (
813  // an expiry time is needed
814  ( strlen( $data['Expiry'] ) == 0 ) ||
815  // can't be a larger string as 50 (it should be a time format in any way)
816  ( strlen( $data['Expiry'] ) > 50 ) ||
817  // check, if the time could be parsed
818  !$expiryTime
819  ) {
820  return [ 'ipb_expiry_invalid' ];
821  }
822 
823  // an expiry time should be in the future, not in the
824  // past (wouldn't make any sense) - bug T123069
825  if ( $expiryTime < wfTimestampNow() ) {
826  return [ 'ipb_expiry_old' ];
827  }
828 
829  if ( !isset( $data['DisableEmail'] ) ) {
830  $data['DisableEmail'] = false;
831  }
832 
833  # If the user has done the form 'properly', they won't even have been given the
834  # option to suppress-block unless they have the 'hideuser' permission
835  if ( !isset( $data['HideUser'] ) ) {
836  $data['HideUser'] = false;
837  }
838 
839  if ( $data['HideUser'] ) {
840  if ( !MediaWikiServices::getInstance()
842  ->userHasRight( $performer, 'hideuser' )
843  ) {
844  # this codepath is unreachable except by a malicious user spoofing forms,
845  # or by race conditions (user has hideuser and block rights, loads block form,
846  # and loses hideuser rights before submission); so need to fail completely
847  # rather than just silently disable hiding
848  return [ 'badaccess-group0' ];
849  }
850 
851  if ( $isPartialBlock ) {
852  return [ 'ipb_hide_partial' ];
853  }
854 
855  # Recheck params here...
856  $hideUserContribLimit = $context->getConfig()->get( 'HideUserContribLimit' );
857  if ( $type != DatabaseBlock::TYPE_USER ) {
858  $data['HideUser'] = false; # IP users should not be hidden
859  } elseif ( !wfIsInfinity( $data['Expiry'] ) ) {
860  # Bad expiry.
861  return [ 'ipb_expiry_temp' ];
862  } elseif ( $hideUserContribLimit !== false
863  && $user->getEditCount() > $hideUserContribLimit
864  ) {
865  # Typically, the user should have a handful of edits.
866  # Disallow hiding users with many edits for performance.
867  return [ [ 'ipb_hide_invalid',
868  Message::numParam( $hideUserContribLimit ) ] ];
869  } elseif ( !$data['Confirm'] ) {
870  return [ 'ipb-confirmhideuser', 'ipb-confirmaction' ];
871  }
872  }
873 
874  // Check whether the user can edit their own user talk page.
875  $blockAllowsUTEdit = $context->getConfig()->get( 'BlockAllowsUTEdit' );
876  $isUserTalkNamespaceBlock = !$isPartialBlock ||
877  in_array( NS_USER_TALK, explode( "\n", $data['NamespaceRestrictions'] ) );
878  if ( $isUserTalkNamespaceBlock ) {
879  // If the block blocks the user talk namespace, disallow own user talk edit if
880  // the global config disallows it; otherwise use the form field value.
881  $userTalkEditAllowed = $blockAllowsUTEdit ? !$data['DisableUTEdit'] : false;
882  } else {
883  // If the block doesn't block the user talk namespace, then it can't block own
884  // user talk edit, regardless of the config or field (T210475). Return error
885  // message if the field tries to disallow own user talk edit.
886  if ( isset( $data['DisableUTEdit'] ) && $data['DisableUTEdit'] ) {
887  return [ 'ipb-prevent-user-talk-edit' ];
888  }
889  $userTalkEditAllowed = true;
890  }
891 
892  // A block is empty if it is a partial block, the page restrictions are empty, the
893  // namespace restrictions are empty, and none of the actions are enabled
894  if ( $isPartialBlock &&
895  !( isset( $data['PageRestrictions'] ) && $data['PageRestrictions'] !== '' ) &&
896  !( isset( $data['NamespaceRestrictions'] ) && $data['NamespaceRestrictions'] !== '' ) &&
897  $data['DisableEmail'] === false &&
898  ( $userTalkEditAllowed || !$blockAllowsUTEdit ) &&
899  !$data['CreateAccount']
900  ) {
901  return [ 'ipb-empty-block' ];
902  }
903 
904  # Create block object.
905  $block = new DatabaseBlock();
906  $block->setTarget( $target );
907  $block->setBlocker( $performer );
908  $block->setReason( $blockReason );
909  $block->setExpiry( $expiryTime );
910  $block->isCreateAccountBlocked( $data['CreateAccount'] );
911  $block->isUsertalkEditAllowed( $userTalkEditAllowed );
912  $block->isEmailBlocked( $data['DisableEmail'] );
913  $block->isHardblock( $data['HardBlock'] );
914  $block->isAutoblocking( $data['AutoBlock'] );
915  $block->setHideName( $data['HideUser'] );
916 
917  if ( $isPartialBlock ) {
918  $block->isSitewide( false );
919  }
920 
921  $reason = [ 'hookaborted' ];
922  if ( !Hooks::runner()->onBlockIp( $block, $performer, $reason ) ) {
923  return $reason;
924  }
925 
926  $pageRestrictions = [];
927  $namespaceRestrictions = [];
928  if ( isset( $data['PageRestrictions'] ) && $data['PageRestrictions'] !== '' ) {
929  $pageRestrictions = array_map( function ( $text ) {
930  $title = Title::newFromText( $text );
931  // Use the link cache since the title has already been loaded when
932  // the field was validated.
933  $restriction = new PageRestriction( 0, $title->getArticleID() );
934  $restriction->setTitle( $title );
935  return $restriction;
936  }, explode( "\n", $data['PageRestrictions'] ) );
937  }
938  if ( isset( $data['NamespaceRestrictions'] ) && $data['NamespaceRestrictions'] !== '' ) {
939  $namespaceRestrictions = array_map( function ( $id ) {
940  return new NamespaceRestriction( 0, $id );
941  }, explode( "\n", $data['NamespaceRestrictions'] ) );
942  }
943 
944  $restrictions = ( array_merge( $pageRestrictions, $namespaceRestrictions ) );
945  $block->setRestrictions( $restrictions );
946 
947  $priorBlock = null;
948  # Try to insert block. Is there a conflicting block?
949  $status = $block->insert();
950  if ( !$status ) {
951  # Indicates whether the user is confirming the block and is aware of
952  # the conflict (did not change the block target in the meantime)
953  $blockNotConfirmed = !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
954  && $data['PreviousTarget'] !== $target );
955 
956  # Special case for API - T34434
957  $reblockNotAllowed = ( array_key_exists( 'Reblock', $data ) && !$data['Reblock'] );
958 
959  # Show form unless the user is already aware of this...
960  if ( $blockNotConfirmed || $reblockNotAllowed ) {
961  return [ [ 'ipb_already_blocked', $block->getTarget() ] ];
962  # Otherwise, try to update the block...
963  } else {
964  # This returns direct blocks before autoblocks/rangeblocks, since we should
965  # be sure the user is blocked by now it should work for our purposes
966  $currentBlock = DatabaseBlock::newFromTarget( $target );
967  if ( $block->equals( $currentBlock ) ) {
968  return [ [ 'ipb_already_blocked', $block->getTarget() ] ];
969  }
970  # If the name was hidden and the blocking user cannot hide
971  # names, then don't allow any block changes...
972  if ( $currentBlock->getHideName() && !MediaWikiServices::getInstance()
973  ->getPermissionManager()
974  ->userHasRight( $performer, 'hideuser' )
975  ) {
976  return [ 'cant-see-hidden-user' ];
977  }
978 
979  $priorBlock = clone $currentBlock;
980  $currentBlock->setBlocker( $performer );
981  $currentBlock->isHardblock( $block->isHardblock() );
982  $currentBlock->isCreateAccountBlocked( $block->isCreateAccountBlocked() );
983  $currentBlock->setExpiry( $block->getExpiry() );
984  $currentBlock->isAutoblocking( $block->isAutoblocking() );
985  $currentBlock->setHideName( $block->getHideName() );
986  $currentBlock->isEmailBlocked( $block->isEmailBlocked() );
987  $currentBlock->isUsertalkEditAllowed( $block->isUsertalkEditAllowed() );
988  $currentBlock->setReason( $block->getReasonComment() );
989 
990  // Maintain the sitewide status. If partial blocks is not enabled,
991  // saving the block will result in a sitewide block.
992  $currentBlock->isSitewide( $block->isSitewide() );
993 
994  // Set the block id of the restrictions.
995  $blockRestrictionStore = MediaWikiServices::getInstance()->getBlockRestrictionStore();
996  $currentBlock->setRestrictions(
997  $blockRestrictionStore->setBlockId( $currentBlock->getId(), $restrictions )
998  );
999 
1000  $status = $currentBlock->update();
1001  // TODO handle failure
1002 
1003  $logaction = 'reblock';
1004 
1005  # Unset _deleted fields if requested
1006  if ( $currentBlock->getHideName() && !$data['HideUser'] ) {
1008  }
1009 
1010  # If hiding/unhiding a name, this should go in the private logs
1011  if ( (bool)$currentBlock->getHideName() ) {
1012  $data['HideUser'] = true;
1013  }
1014 
1015  $block = $currentBlock;
1016  }
1017  } else {
1018  $logaction = 'block';
1019  }
1020 
1021  Hooks::runner()->onBlockIpComplete( $block, $performer, $priorBlock );
1022 
1023  # Set *_deleted fields if requested
1024  if ( $data['HideUser'] ) {
1026  }
1027 
1028  # Can't watch a rangeblock
1029  if ( $type != DatabaseBlock::TYPE_RANGE && $data['Watch'] ) {
1032  $performer,
1034  );
1035  }
1036 
1037  # DatabaseBlock constructor sanitizes certain block options on insert
1038  $data['BlockEmail'] = $block->isEmailBlocked();
1039  $data['AutoBlock'] = $block->isAutoblocking();
1040 
1041  # Prepare log parameters
1042  $logParams = [];
1043 
1044  $rawExpiry = $data['Expiry'];
1045  $logExpiry = wfIsInfinity( $rawExpiry ) ? 'infinity' : $rawExpiry;
1046 
1047  $logParams['5::duration'] = $logExpiry;
1048  $logParams['6::flags'] = self::blockLogFlags( $data, $type );
1049  $logParams['sitewide'] = $block->isSitewide();
1050 
1051  if ( !$block->isSitewide() ) {
1052  if ( $data['PageRestrictions'] !== '' ) {
1053  $logParams['7::restrictions']['pages'] = explode( "\n", $data['PageRestrictions'] );
1054  }
1055 
1056  if ( $data['NamespaceRestrictions'] !== '' ) {
1057  $logParams['7::restrictions']['namespaces'] = explode( "\n", $data['NamespaceRestrictions'] );
1058  }
1059  }
1060 
1061  # Make log entry, if the name is hidden, put it in the suppression log
1062  $log_type = $data['HideUser'] ? 'suppress' : 'block';
1063  $logEntry = new ManualLogEntry( $log_type, $logaction );
1064  $logEntry->setTarget( Title::makeTitle( NS_USER, $target ) );
1065  $logEntry->setComment( $blockReason );
1066  $logEntry->setPerformer( $performer );
1067  $logEntry->setParameters( $logParams );
1068  # Relate log ID to block ID (T27763)
1069  $logEntry->setRelations( [ 'ipb_id' => $block->getId() ] );
1070  $logId = $logEntry->insert();
1071 
1072  if ( !empty( $data['Tags'] ) ) {
1073  $logEntry->addTags( $data['Tags'] );
1074  }
1075 
1076  $logEntry->publish( $logId );
1077 
1078  return true;
1079  }
1080 
1091  public static function getSuggestedDurations( Language $lang = null, $includeOther = true ) {
1092  $msg = $lang === null
1093  ? wfMessage( 'ipboptions' )->inContentLanguage()->text()
1094  : wfMessage( 'ipboptions' )->inLanguage( $lang )->text();
1095 
1096  if ( $msg == '-' ) {
1097  return [];
1098  }
1099 
1100  $a = XmlSelect::parseOptionsMessage( $msg );
1101 
1102  if ( $a && $includeOther ) {
1103  // if options exist, add other to the end instead of the begining (which
1104  // is what happens by default).
1105  $a[ wfMessage( 'ipbother' )->text() ] = 'other';
1106  }
1107 
1108  return $a;
1109  }
1110 
1122  public static function parseExpiryInput( $expiry ) {
1123  if ( wfIsInfinity( $expiry ) ) {
1124  return 'infinity';
1125  }
1126 
1127  $expiry = strtotime( $expiry );
1128 
1129  if ( $expiry < 0 || $expiry === false ) {
1130  return false;
1131  }
1132 
1133  return wfTimestamp( TS_MW, $expiry );
1134  }
1135 
1141  public static function canBlockEmail( UserIdentity $user ) {
1142  global $wgEnableUserEmail;
1143 
1144  return ( $wgEnableUserEmail && MediaWikiServices::getInstance()
1146  ->userHasRight( $user, 'blockemail' ) );
1147  }
1148 
1162  public static function checkUnblockSelf( $target, User $performer ) {
1163  if ( is_int( $target ) ) {
1165  } elseif ( is_string( $target ) ) {
1167  }
1168  if ( $performer->getBlock() ) {
1169  if ( !$performer->getBlock()->isSitewide() ) {
1170  # Allow user to block other users while they are subject to partial block
1171  return true;
1172  }
1173 
1174  if ( $target instanceof User && $target->getId() == $performer->getId() ) {
1175  # User is trying to unblock themselves
1176  if ( MediaWikiServices::getInstance()
1178  ->userHasRight( $performer, 'unblockself' )
1179  ) {
1180  return true;
1181  # User blocked themselves and is now trying to reverse it
1182  } elseif ( $performer->blockedBy() === $performer->getName() ) {
1183  return true;
1184  } else {
1185  return 'ipbnounblockself';
1186  }
1187  } elseif (
1188  $target instanceof User &&
1189  $performer->getBlock() instanceof DatabaseBlock &&
1190  $performer->getBlock()->getBy() &&
1191  $performer->getBlock()->getBy() === $target->getId()
1192  ) {
1193  // Allow users to block the user that blocked them.
1194  // This is to prevent a situation where a malicious user
1195  // blocks all other users. This way, the non-malicious
1196  // user can block the malicious user back, resulting
1197  // in a stalemate.
1198  return true;
1199  } else {
1200  // User is trying to block/unblock someone else while
1201  // they have sitewide block on themselves.
1202  return 'ipbblocked';
1203  }
1204  } else {
1205  return true;
1206  }
1207  }
1208 
1216  protected static function blockLogFlags( array $data, $type ) {
1217  $config = RequestContext::getMain()->getConfig();
1218 
1219  $blockAllowsUTEdit = $config->get( 'BlockAllowsUTEdit' );
1220 
1221  $flags = [];
1222 
1223  # when blocking a user the option 'anononly' is not available/has no effect
1224  # -> do not write this into log
1225  if ( !$data['HardBlock'] && $type != DatabaseBlock::TYPE_USER ) {
1226  // For grepping: message block-log-flags-anononly
1227  $flags[] = 'anononly';
1228  }
1229 
1230  if ( $data['CreateAccount'] ) {
1231  // For grepping: message block-log-flags-nocreate
1232  $flags[] = 'nocreate';
1233  }
1234 
1235  # Same as anononly, this is not displayed when blocking an IP address
1236  if ( !$data['AutoBlock'] && $type == DatabaseBlock::TYPE_USER ) {
1237  // For grepping: message block-log-flags-noautoblock
1238  $flags[] = 'noautoblock';
1239  }
1240 
1241  if ( $data['DisableEmail'] ) {
1242  // For grepping: message block-log-flags-noemail
1243  $flags[] = 'noemail';
1244  }
1245 
1246  if ( $blockAllowsUTEdit && $data['DisableUTEdit'] ) {
1247  // For grepping: message block-log-flags-nousertalk
1248  $flags[] = 'nousertalk';
1249  }
1250 
1251  if ( $data['HideUser'] ) {
1252  // For grepping: message block-log-flags-hiddenname
1253  $flags[] = 'hiddenname';
1254  }
1255 
1256  return implode( ',', $flags );
1257  }
1258 
1265  public function onSubmit( array $data, HTMLForm $form = null ) {
1266  // If "Editing" checkbox is unchecked, the block must be a partial block affecting
1267  // actions other than editing, and there must be no restrictions.
1268  if ( isset( $data['Editing'] ) && $data['Editing'] === false ) {
1269  $data['EditingRestriction'] = 'partial';
1270  $data['PageRestrictions'] = '';
1271  $data['NamespaceRestrictions'] = '';
1272  }
1273  return self::processForm( $data, $form->getContext() );
1274  }
1275 
1280  public function onSuccess() {
1281  $out = $this->getOutput();
1282  $out->setPageTitle( $this->msg( 'blockipsuccesssub' ) );
1283  $out->addWikiMsg( 'blockipsuccesstext', wfEscapeWikiText( $this->target ) );
1284  }
1285 
1294  public function prefixSearchSubpages( $search, $limit, $offset ) {
1295  $user = User::newFromName( $search );
1296  if ( !$user ) {
1297  // No prefix suggestion for invalid user
1298  return [];
1299  }
1300  // Autocomplete subpage as user list - public to allow caching
1301  return UserNamePrefixSearch::search( 'public', $search, $limit, $offset );
1302  }
1303 
1304  protected function getGroupName() {
1305  return 'users';
1306  }
1307 }
Message\numParam
static numParam( $num)
Definition: Message.php:1046
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:800
MediaWiki\Block\Restriction\PageRestriction\getTitle
getTitle()
Get Title.
Definition: PageRestriction.php:72
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:559
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:332
HtmlArmor
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:28
SpecialBlock\canBlockEmail
static canBlockEmail(UserIdentity $user)
Can we do an email block?
Definition: SpecialBlock.php:1141
SpecialBlock\$permissionManager
PermissionManager $permissionManager
Definition: SpecialBlock.php:42
SpecialBlock\onSuccess
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
Definition: SpecialBlock.php:1280
User\getId
getId()
Get the user's ID.
Definition: User.php:2108
WatchAction\doWatch
static doWatch(Title $title, User $user, $checkRights=User::CHECK_USER_RIGHTS, ?string $expiry=null)
Watch a page.
Definition: WatchAction.php:201
User\isAnon
isAnon()
Get whether the user is anonymous.
Definition: User.php:3225
SpecialBlock\$type
int $type
DatabaseBlock::TYPE_ constant.
Definition: SpecialBlock.php:50
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:716
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:146
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
SpecialBlock\checkUnblockSelf
static checkUnblockSelf( $target, User $performer)
T17810: Sitewide blocked admins should not be able to block/unblock others with one exception; they c...
Definition: SpecialBlock.php:1162
SpecialBlock\$preErrors
array $preErrors
Definition: SpecialBlock.php:62
HTMLForm\addHeaderText
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition: HTMLForm.php:810
SpecialBlock\$requestedHideUser
bool $requestedHideUser
Whether the previous submission of the form asked for HideUser.
Definition: SpecialBlock.php:56
SpecialBlock\processForm
static processForm(array $data, IContextSource $context)
Given the form data, actually implement a block.
Definition: SpecialBlock.php:765
SpecialBlock\preText
preText()
Add header elements like block log entries, etc.
Definition: SpecialBlock.php:464
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1806
HTMLForm\setHeaderText
setHeaderText( $msg, $section=null)
Set header text, inside the form.
Definition: HTMLForm.php:832
HTMLForm\formatErrors
formatErrors( $errors)
Format a stack of error messages into a single HTML string.
Definition: HTMLForm.php:1339
MediaWiki\Block\DatabaseBlock\getType
getType()
Get the type of target for this particular block.int|null AbstractBlock::TYPE_ constant,...
Definition: DatabaseBlock.php:1384
UserNamePrefixSearch\search
static search( $audience, $search, $limit, $offset=0)
Do a prefix search of user names and return a list of matching user names.
Definition: UserNamePrefixSearch.php:41
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:47
SpecialBlock\$previousTarget
User string $previousTarget
The previous block target.
Definition: SpecialBlock.php:53
$wgEnableUserEmail
$wgEnableUserEmail
Set to true to enable user-to-user e-mail.
Definition: DefaultSettings.php:1770
IP
Pre-librarized class name for IPUtils.
Definition: IP.php:80
SpecialBlock\onSubmit
onSubmit(array $data, HTMLForm $form=null)
Process the form on POST submission.
Definition: SpecialBlock.php:1265
FormSpecialPage
Special page which uses an HTMLForm to handle processing.
Definition: FormSpecialPage.php:31
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:535
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1198
User\getUserPage
getUserPage()
Get this user's personal page title.
Definition: User.php:4015
$s
$s
Definition: mergeMessageFileList.php:185
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:90
SpecialPage\getSkin
getSkin()
Shortcut to get the skin being used for this instance.
Definition: SpecialPage.php:736
RevisionDeleteUser\unsuppressUserName
static unsuppressUserName( $name, $userId, IDatabase $dbw=null)
Definition: RevisionDeleteUser.php:168
SpecialBlock\doesWrites
doesWrites()
Indicates whether this special page may perform database writes.
Definition: SpecialBlock.php:70
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:746
SpecialBlock\checkExecutePermissions
checkExecutePermissions(User $user)
Checks that the user can unblock themselves if they are trying to do so.
Definition: SpecialBlock.php:80
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:160
SpecialBlock\setParameter
setParameter( $par)
Handle some magic here.
Definition: SpecialBlock.php:103
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\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:32
SpecialBlock\__construct
__construct(PermissionManager $permissionManager)
Definition: SpecialBlock.php:64
SpecialBlock\postText
postText()
Add footer elements to the form.
Definition: SpecialBlock.php:514
MediaWiki\Block\DatabaseBlock
A DatabaseBlock (unlike a SystemBlock) is stored in the database, may give rise to autoblocks and may...
Definition: DatabaseBlock.php:54
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:836
SpecialPage\getHookRunner
getHookRunner()
Definition: SpecialPage.php:974
SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
Definition: SpecialPage.php:766
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:342
SpecialBlock\alterForm
alterForm(HTMLForm $form)
Customizes the HTMLForm a bit.
Definition: SpecialBlock.php:125
getPermissionManager
getPermissionManager()
SpecialBlock
A special page that allows users with 'block' right to block users from editing pages and other actio...
Definition: SpecialBlock.php:38
SpecialBlock\getTargetUserTitle
static getTargetUserTitle( $target)
Get a user page target for things like logs.
Definition: SpecialBlock.php:615
$title
$title
Definition: testCompression.php:38
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:726
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:595
LogEventsList\showLogExtract
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Definition: LogEventsList.php:639
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1835
User\getBlock
getBlock( $fromReplica=true)
Get the block affecting the user, or null if the user is not blocked.
Definition: User.php:1978
SpecialBlock\prefixSearchSubpages
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
Definition: SpecialBlock.php:1294
FormSpecialPage\$par
string null $par
The sub-page of the special page.
Definition: FormSpecialPage.php:36
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:621
MediaWiki\Permissions\PermissionManager
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Definition: PermissionManager.php:49
NS_USER_TALK
const NS_USER_TALK
Definition: Defines.php:72
$expiryTime
$expiryTime
Definition: opensearch_desc.php:49
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:171
wfIsInfinity
wfIsInfinity( $str)
Determine input string is represents as infinity.
Definition: GlobalFunctions.php:2842
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:706
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1485
SpecialBlock\getFormFields
getFormFields()
Get the HTMLForm descriptor array for the block form.
Definition: SpecialBlock.php:155
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:451
User\blockedBy
blockedBy()
If user is blocked, return the name of the user who placed the block.
Definition: User.php:2003
HTMLForm\setSubmitDestructive
setSubmitDestructive()
Identify that the submit button in the form has a destructive action.
Definition: HTMLForm.php:1374
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:43
$context
$context
Definition: load.php:43
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:37
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1388
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:912
$wgBlockCIDRLimit
$wgBlockCIDRLimit
Limits on the possible sizes of range blocks.
Definition: DefaultSettings.php:5376
SpecialBlock\validateTargetField
static validateTargetField( $value, $alldata, $form)
HTMLForm field validation-callback for Target field.
Definition: SpecialBlock.php:685
MediaWiki\Block\Restriction\PageRestriction
Definition: PageRestriction.php:25
SpecialBlock\$alreadyBlocked
bool $alreadyBlocked
Definition: SpecialBlock.php:59
SpecialBlock\validateTarget
static validateTarget( $value, User $user)
Validate a block target.
Definition: SpecialBlock.php:704
SpecialBlock\getDisplayFormat
getDisplayFormat()
Get display format for the form.
Definition: SpecialBlock.php:147
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
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:1122
SpecialBlock\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialBlock.php:1304
NS_USER
const NS_USER
Definition: Defines.php:71
SpecialBlock\getSuggestedDurations
static getSuggestedDurations(Language $lang=null, $includeOther=true)
Get an array of suggested block durations from MediaWiki:Ipboptions.
Definition: SpecialBlock.php:1091
ManualLogEntry
Class for creating new log entries and inserting them into the database.
Definition: ManualLogEntry.php:38
SpecialBlock\getTargetAndType
static getTargetAndType( $par, WebRequest $request=null)
Determine the target of the block, and the type of target.
Definition: SpecialBlock.php:634
RevisionDeleteUser\suppressUserName
static suppressUserName( $name, $userId, IDatabase $dbw=null)
Definition: RevisionDeleteUser.php:158
User\IGNORE_USER_RIGHTS
const IGNORE_USER_RIGHTS
Definition: User.php:89
SpecialPage\$linkRenderer
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:69
SpecialBlock\blockLogFlags
static blockLogFlags(array $data, $type)
Return a comma-delimited list of "flags" to be passed to the log reader for this block,...
Definition: SpecialBlock.php:1216
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:27
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55
User\getName
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:2137
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:41
SpecialBlock\requiresUnblock
requiresUnblock()
We allow certain special cases where user is blocked.
Definition: SpecialBlock.php:94
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:133