24 namespace MediaWiki\Specials;
64 use Wikimedia\IPUtils;
128 parent::__construct(
'Block',
'block' );
130 $this->blockUtils = $blockUtils;
131 $this->blockPermissionCheckerFactory = $blockPermissionCheckerFactory;
132 $this->blockUserFactory = $blockUserFactory;
133 $this->userNameUtils = $userNameUtils;
134 $this->userNamePrefixSearch = $userNamePrefixSearch;
135 $this->blockActionInfo = $blockActionInfo;
136 $this->titleFormatter = $titleFormatter;
137 $this->namespaceInfo = $namespaceInfo;
151 parent::checkExecutePermissions( $user );
153 $status = $this->blockPermissionCheckerFactory
154 ->newBlockPermissionChecker( $this->target, $user )
155 ->checkBlockPermissions();
156 if ( $status !==
true ) {
184 $this->
getSkin()->setRelevantUser( $this->target );
188 ->parseBlockTarget( $request->getVal(
'wpPreviousTarget' ) );
189 $this->requestedHideUser = $request->getBool(
'wpHideUser' );
201 $msg = $this->alreadyBlocked ?
'ipb-change-block' :
'ipbsubmit';
207 if ( !$this->
getRequest()->wasPosted() && $this->preErrors ) {
213 'errors' => array_map(
function ( $errMsg ) {
215 return new HtmlSnippet( $this->
msg( ...$errMsg )->parse() );
246 'id' =>
'mw-bi-target',
250 'placeholder' => $this->
msg(
'block-target-placeholder' )->text(),
251 'validation-callback' =>
function ( $value, $alldata, $form ) {
252 $status = $this->blockUtils->validateTarget( $value );
253 if ( !$status->isOK() ) {
254 $errors = $status->getErrorsArray();
256 return $form->msg( ...$errors[0] );
260 'section' =>
'target',
263 $a[
'EditingRestriction'] = [
265 'cssclass' =>
'mw-block-editing-restriction',
266 'default' =>
'sitewide',
268 $this->
msg(
'ipb-sitewide' )->escaped() .
270 'classes' => [
'oo-ui-inline-help' ],
271 'label' =>
new HtmlSnippet( $this->
msg(
'ipb-sitewide-help' )->parse() ),
273 $this->
msg(
'ipb-partial' )->escaped() .
275 'classes' => [
'oo-ui-inline-help' ],
276 'label' => $this->
msg(
'ipb-partial-help' )->text(),
279 'section' =>
'actions',
282 $a[
'PageRestrictions'] = [
283 'type' =>
'titlesmultiselect',
284 'label' => $this->
msg(
'ipb-pages-label' )->text(),
287 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction',
289 'showMissing' =>
false,
290 'excludeDynamicNamespaces' =>
true,
292 'autocomplete' => false
294 'section' =>
'actions',
297 $a[
'NamespaceRestrictions'] = [
298 'type' =>
'namespacesmultiselect',
299 'label' => $this->
msg(
'ipb-namespaces-label' )->text(),
301 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction',
304 'autocomplete' => false
306 'section' =>
'actions',
310 $blockActions = $this->blockActionInfo->getAllBlockActions();
311 $a[
'ActionRestrictions'] = [
312 'type' =>
'multiselect',
313 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction mw-block-action-restriction',
314 'options-messages' => array_combine(
315 array_map(
static function ( $action ) {
316 return "ipb-action-$action";
317 }, array_keys( $blockActions ) ),
320 'section' =>
'actions',
324 $a[
'CreateAccount'] = [
326 'cssclass' =>
'mw-block-restriction',
327 'label-message' =>
'ipbcreateaccount',
329 'section' =>
'details',
332 if ( $this->blockPermissionCheckerFactory
333 ->newBlockPermissionChecker(
null, $user )
334 ->checkEmailPermissions()
336 $a[
'DisableEmail'] = [
338 'cssclass' =>
'mw-block-restriction',
339 'label-message' =>
'ipbemailban',
340 'section' =>
'details',
344 if ( $blockAllowsUTEdit ) {
345 $a[
'DisableUTEdit'] = [
347 'cssclass' =>
'mw-block-restriction',
348 'label-message' =>
'ipb-disableusertalk',
350 'section' =>
'details',
354 $defaultExpiry = $this->
msg(
'ipb-default-expiry' )->inContentLanguage();
356 $defaultExpiryIP = $this->
msg(
'ipb-default-expiry-ip' )->inContentLanguage();
357 if ( !$defaultExpiryIP->isDisabled() ) {
358 $defaultExpiry = $defaultExpiryIP;
365 'options' => $suggestedDurations,
366 'default' => $defaultExpiry->text(),
367 'section' =>
'expiry',
371 'type' =>
'selectandother',
376 'maxlength-unit' =>
'codepoints',
377 'options-message' =>
'ipbreason-dropdown',
378 'section' =>
'reason',
384 'ipbenableautoblock',
388 'section' =>
'options',
395 'label-message' =>
'ipbhidename',
396 'cssclass' =>
'mw-block-hideuser',
397 'section' =>
'options',
402 if ( $user->isRegistered() ) {
405 'label-message' =>
'ipbwatchuser',
406 'section' =>
'options',
412 'label-message' =>
'ipb-hardblock',
414 'section' =>
'options',
419 $a[
'PreviousTarget'] = [
428 'label-message' =>
'ipb-confirm',
429 'cssclass' =>
'mw-block-confirm',
435 $this->
getHookRunner()->onSpecialBlockModifyFormFields( $this, $a );
447 $fields[
'Target'][
'default'] = (string)$this->target;
449 if ( $this->target ) {
450 $status = $this->blockUtils->validateTarget( $this->target );
451 if ( !$status->isOK() ) {
452 $errors = $status->getErrorsArray();
453 $this->preErrors = array_merge( $this->preErrors, $errors );
458 $fields[
'PreviousTarget'][
'default'] = (string)$this->target;
466 || ( $this->target && $block->isBlocking( $this->target ) ) )
468 $fields[
'HardBlock'][
'default'] = $block->isHardblock();
469 $fields[
'CreateAccount'][
'default'] = $block->isCreateAccountBlocked();
470 $fields[
'AutoBlock'][
'default'] = $block->isAutoblocking();
472 if ( isset( $fields[
'DisableEmail'] ) ) {
473 $fields[
'DisableEmail'][
'default'] = $block->isEmailBlocked();
476 if ( isset( $fields[
'HideUser'] ) ) {
477 $fields[
'HideUser'][
'default'] = $block->getHideName();
480 if ( isset( $fields[
'DisableUTEdit'] ) ) {
481 $fields[
'DisableUTEdit'][
'default'] = !$block->isUsertalkEditAllowed();
486 if ( !$block->getHideName() || $this->getAuthority()->isAllowed(
'hideuser' ) ) {
487 $fields[
'Reason'][
'default'] = $block->getReasonComment()->text;
489 $fields[
'Reason'][
'default'] =
'';
495 $fields[
'Confirm'][
'type'] =
'check';
500 $fields[
'Confirm'][
'default'] = 1;
503 if ( $block->getExpiry() ==
'infinity' ) {
504 $fields[
'Expiry'][
'default'] =
'infinite';
506 $fields[
'Expiry'][
'default'] =
wfTimestamp( TS_RFC2822, $block->getExpiry() );
509 if ( !$block->isSitewide() ) {
510 $fields[
'EditingRestriction'][
'default'] =
'partial';
512 $pageRestrictions = [];
513 $namespaceRestrictions = [];
514 foreach ( $block->getRestrictions() as $restriction ) {
516 $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
518 $this->namespaceInfo->exists( $restriction->getValue() )
520 $namespaceRestrictions[] = $restriction->getValue();
525 sort( $pageRestrictions );
526 $fields[
'PageRestrictions'][
'default'] = implode(
"\n", $pageRestrictions );
527 sort( $namespaceRestrictions );
528 $fields[
'NamespaceRestrictions'][
'default'] = implode(
"\n", $namespaceRestrictions );
531 $actionRestrictions = [];
532 foreach ( $block->getRestrictions() as $restriction ) {
534 $actionRestrictions[] = $restriction->getValue();
537 $fields[
'ActionRestrictions'][
'default'] = $actionRestrictions;
541 $this->alreadyBlocked =
true;
542 $this->preErrors[] = [
'ipb-needreblock',
wfEscapeWikiText( $block->getTargetName() ) ];
545 if ( $this->alreadyBlocked || $this->
getRequest()->wasPosted()
546 || $this->
getRequest()->getCheck(
'wpCreateAccount' )
548 $this->
getOutput()->addJsConfigVars(
'wgCreateAccountDirty',
true );
552 if ( $this->requestedHideUser ) {
553 $fields[
'Confirm'][
'type'] =
'check';
554 unset( $fields[
'Confirm'][
'default'] );
555 $this->preErrors[] = [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
560 $fields[
'Confirm'][
'type'] =
'check';
561 unset( $fields[
'Confirm'][
'default'] );
562 $this->preErrors[] = [
'ipb-blockingself',
'ipb-confirmaction' ];
571 $this->
getOutput()->addModuleStyles( [
'mediawiki.special' ] );
572 $this->
getOutput()->addModules( [
'mediawiki.special.block' ] );
575 $text = $this->
msg(
'blockiptext', $blockCIDRLimit[
'IPv4'], $blockCIDRLimit[
'IPv6'] )->parse();
577 $otherBlockMessages = [];
578 if ( $this->target !==
null ) {
581 $targetName = $this->target->
getName();
585 $otherBlockMessages, $targetName );
587 if ( count( $otherBlockMessages ) ) {
591 $this->
msg(
'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse()
596 foreach ( $otherBlockMessages as $link ) {
602 [
'class' =>
'mw-blockip-alreadyblocked' ],
620 $this->
getOutput()->addModuleStyles(
'mediawiki.special' );
626 $links[] = $linkRenderer->makeLink(
628 $this->
msg(
'ipb-blocklist-contribs', $this->target->getName() )->text()
634 $message = $this->
msg(
640 $message = $this->
msg(
'ipb-unblock' )->parse();
643 $links[] = $linkRenderer->makeKnownLink(
649 $links[] = $linkRenderer->makeKnownLink(
651 $this->
msg(
'ipb-blocklist' )->text()
655 if ( $this->
getAuthority()->isAllowed(
'editinterface' ) ) {
656 $links[] = $linkRenderer->makeKnownLink(
657 $this->
msg(
'ipbreason-dropdown' )->inContentLanguage()->
getTitle(),
658 $this->
msg(
'ipb-edit-dropdown' )->text(),
660 [
'action' =>
'edit' ]
666 [
'class' =>
'mw-ipb-conveniencelinks' ],
684 $this->titleFormatter->getText( $userPage ),
686 'showIfEmpty' =>
false
692 if ( $this->
getAuthority()->isAllowed(
'suppressionlog' ) ) {
700 'conds' => [
'log_action' => [
'block',
'reblock',
'unblock' ] ],
702 'blocklog-showsuppresslog',
703 $this->titleFormatter->getText( $userPage ),
705 'showIfEmpty' =>
false
750 return self::getTargetAndTypeInternal( $par, $request );
764 private static function getTargetAndTypeInternal( ?
string $par,
WebRequest $request =
null ) {
770 $request->getVal(
'wpTarget',
null ),
772 $request->getVal(
'ip',
null ),
774 $request->getVal(
'wpBlockAddress',
null ),
776 foreach ( $possibleTargets as $possibleTarget ) {
779 ->parseBlockTarget( $possibleTarget );
781 if ( $targetAndType[ 1 ] !==
null ) {
785 return $targetAndType;
798 return self::processFormInternal(
801 $services->getBlockUserFactory(),
802 $services->getBlockUtils()
816 private static function processFormInternal(
826 $isPartialBlock = isset( $data[
'EditingRestriction'] ) &&
827 $data[
'EditingRestriction'] ===
'partial';
831 $data[
'Confirm'] = !in_array( $data[
'Confirm'], [
'',
'0',
null,
false ],
true );
835 if ( !isset( $data[
'HideUser'] ) ) {
836 $data[
'HideUser'] =
false;
842 $target = $target->getName();
851 if ( $target === $performer->
getUser()->getName() &&
852 ( $data[
'PreviousTarget'] !== $target || !$data[
'Confirm'] )
854 return [
'ipb-blockingself',
'ipb-confirmaction' ];
857 if ( $data[
'HideUser'] && !$data[
'Confirm'] ) {
858 return [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
861 $target = $target->getName();
864 return [
'badipaddress' ];
869 $blockReason = $data[
'Reason'][0] ??
'';
871 $pageRestrictions = [];
872 $namespaceRestrictions = [];
873 $actionRestrictions = [];
874 if ( $isPartialBlock ) {
875 if ( isset( $data[
'PageRestrictions'] ) && $data[
'PageRestrictions'] !==
'' ) {
876 $titles = explode(
"\n", $data[
'PageRestrictions'] );
877 foreach ( $titles as $title ) {
881 if ( isset( $data[
'NamespaceRestrictions'] ) && $data[
'NamespaceRestrictions'] !==
'' ) {
882 $namespaceRestrictions = array_map(
static function ( $id ) {
883 return new NamespaceRestriction( 0, (
int)$id );
884 }, explode(
"\n", $data[
'NamespaceRestrictions'] ) );
887 $enablePartialActionBlocks &&
888 isset( $data[
'ActionRestrictions'] ) &&
889 $data[
'ActionRestrictions'] !==
''
891 $actionRestrictions = array_map(
static function ( $id ) {
892 return new ActionRestriction( 0, $id );
893 }, $data[
'ActionRestrictions'] );
896 $restrictions = array_merge( $pageRestrictions, $namespaceRestrictions, $actionRestrictions );
898 if ( !isset( $data[
'Tags'] ) ) {
903 'isCreateAccountBlocked' => $data[
'CreateAccount'],
904 'isHardBlock' => $data[
'HardBlock'],
905 'isAutoblocking' => $data[
'AutoBlock'],
906 'isHideUser' => $data[
'HideUser'],
907 'isPartial' => $isPartialBlock,
910 if ( isset( $data[
'DisableUTEdit'] ) ) {
911 $blockOptions[
'isUserTalkEditBlocked'] = $data[
'DisableUTEdit'];
913 if ( isset( $data[
'DisableEmail'] ) ) {
914 $blockOptions[
'isEmailBlocked'] = $data[
'DisableEmail'];
929 $blockNotConfirmed = !$data[
'Confirm'] || ( array_key_exists(
'PreviousTarget', $data )
930 && $data[
'PreviousTarget'] !== $target );
933 $reblockNotAllowed = ( array_key_exists(
'Reblock', $data ) && !$data[
'Reblock'] );
935 $doReblock = !$blockNotConfirmed && !$reblockNotAllowed;
937 $status = $blockUser->placeBlock( $doReblock );
938 if ( !$status->isOK() ) {
949 && array_key_exists(
'Watch', $data )
972 $msg = $lang ===
null
973 ?
wfMessage(
'ipboptions' )->inContentLanguage()->text()
974 :
wfMessage(
'ipboptions' )->inLanguage( $lang )->text();
982 if ( $a && $includeOther ) {
985 $a[
wfMessage(
'ipbother' )->text() ] =
'other';
1013 ->getBlockPermissionCheckerFactory()
1015 ->checkEmailPermissions();
1035 ->getBlockPermissionCheckerFactory()
1036 ->newBlockPermissionChecker( $target, $performer )
1037 ->checkBlockPermissions();
1047 return self::processFormInternal(
1050 $this->blockUserFactory,
1060 $out = $this->getOutput();
1061 $out->setPageTitleMsg( $this->msg(
'blockipsuccesssub' ) );
1062 $out->addWikiMsg(
'blockipsuccesstext',
wfEscapeWikiText( $this->target ) );
1074 $search = $this->userNameUtils->getCanonical( $search );
1080 return $this->userNamePrefixSearch
1081 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1092 class_alias( SpecialBlock::class,
'SpecialBlock' );
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined('MW_SETUP_CALLBACK'))
An error page which can definitely be safely rendered using the OutputPage.
Marks HTML that shouldn't be escaped.
Base class for language-specific code.
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
A class containing constants representing the names of configuration variables.
const AutoblockExpiry
Name constant for the AutoblockExpiry setting, for use with Config::get()
const BlockAllowsUTEdit
Name constant for the BlockAllowsUTEdit setting, for use with Config::get()
const BlockCIDRLimit
Name constant for the BlockCIDRLimit setting, for use with Config::get()
const EnablePartialActionBlocks
Name constant for the EnablePartialActionBlocks setting, for use with Config::get()
Special page which uses an HTMLForm to handle processing.
string null $par
The sub-page of the special page.
Parent class for all special pages.
getSkin()
Shortcut to get the skin being used for this instance.
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,...
getUser()
Shortcut to get the User executing this instance.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
getLanguage()
Shortcut to get user's language.
getName()
Get the name of this Special Page.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
The Message class deals with fetching and processing of interface message into a variety of formats.
static durationParam( $duration)
Class for generating HTML <select> or <datalist> elements.
static parseOptionsMessage(string $msg)
Parse labels and values out of a comma- and colon-separated list of options, such as is used for expi...
Interface for objects which can provide a MediaWiki context on request.