136 parent::__construct(
'Block',
'block' );
138 $this->blockUtils = $blockUtils;
139 $this->blockPermissionCheckerFactory = $blockPermissionCheckerFactory;
140 $this->blockUserFactory = $blockUserFactory;
141 $this->blockStore = $blockStore;
142 $this->userNameUtils = $userNameUtils;
143 $this->userNamePrefixSearch = $userNamePrefixSearch;
144 $this->blockActionInfo = $blockActionInfo;
145 $this->titleFormatter = $titleFormatter;
146 $this->namespaceInfo = $namespaceInfo;
150 parent::execute(
$par );
152 if ( $this->
getConfig()->
get(
'UseCodexSpecialBlock' ) ) {
153 $this->
getOutput()->addModules(
'mediawiki.special.block.codex' );
154 $this->
getOutput()->addJsConfigVars( $this->codexFormData );
169 parent::checkExecutePermissions( $user );
171 $status = $this->blockPermissionCheckerFactory
172 ->newBlockPermissionChecker( $this->target, $user )
173 ->checkBlockPermissions();
174 if ( $status !==
true ) {
202 $this->
getSkin()->setRelevantUser( $this->target );
206 ->parseBlockTarget( $request->getVal(
'wpPreviousTarget' ) );
207 $this->requestedHideUser = $request->getBool(
'wpHideUser' );
219 $msg = $this->alreadyBlocked ?
'ipb-change-block' :
'ipbsubmit';
225 if ( !$this->
getRequest()->wasPosted() && $this->preErrors ) {
231 'errors' => array_map(
function ( $errMsg ) {
233 return new HtmlSnippet( $this->
msg( ...$errMsg )->parse() );
241 return $this->
getConfig()->get(
'UseCodexSpecialBlock' ) ?
'codex' :
'ooui';
256 $suggestedDurations = $this->
getLanguage()->getBlockDurations();
264 'id' =>
'mw-bi-target',
268 'placeholder' => $this->
msg(
'block-target-placeholder' )->text(),
269 'validation-callback' =>
function ( $value, $alldata, $form ) {
270 $status = $this->blockUtils->validateTarget( $value );
271 if ( !$status->isOK() ) {
272 $errors = $status->getErrorsArray();
274 return $form->msg( ...$errors[0] );
278 'section' =>
'target',
281 $editingRestrictionOptions = $this->
getConfig()->get(
'UseCodexSpecialBlock' ) ?
284 'options-messages' => [
285 'ipb-sitewide' =>
'sitewide',
286 'ipb-partial' =>
'partial'
288 'option-descriptions-messages' => [
289 'sitewide' =>
'ipb-sitewide-help',
290 'partial' =>
'ipb-partial-help'
292 'option-descriptions-messages-parse' =>
true,
297 $this->
msg(
'ipb-sitewide' )->escaped() .
299 'classes' => [
'oo-ui-inline-help' ],
300 'label' =>
new HtmlSnippet( $this->
msg(
'ipb-sitewide-help' )->parse() ),
302 $this->
msg(
'ipb-partial' )->escaped() .
304 'classes' => [
'oo-ui-inline-help' ],
305 'label' =>
new HtmlSnippet( $this->
msg(
'ipb-partial-help' )->parse() ),
310 $a[
'EditingRestriction'] = [
312 'cssclass' =>
'mw-block-editing-restriction',
313 'default' =>
'sitewide',
314 'section' =>
'actions',
315 ] + $editingRestrictionOptions;
317 $a[
'PageRestrictions'] = [
318 'type' =>
'titlesmultiselect',
319 'label' => $this->
msg(
'ipb-pages-label' )->text(),
322 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction',
324 'showMissing' =>
false,
325 'excludeDynamicNamespaces' =>
true,
327 'autocomplete' => false
329 'section' =>
'actions',
332 $a[
'NamespaceRestrictions'] = [
333 'type' =>
'namespacesmultiselect',
334 'label' => $this->
msg(
'ipb-namespaces-label' )->text(),
336 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction',
339 'autocomplete' => false
341 'section' =>
'actions',
345 $blockActions = $this->blockActionInfo->getAllBlockActions();
346 $a[
'ActionRestrictions'] = [
347 'type' =>
'multiselect',
348 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction mw-block-action-restriction',
349 'options-messages' => array_combine(
350 array_map(
static function ( $action ) {
351 return "ipb-action-$action";
352 }, array_keys( $blockActions ) ),
355 'section' =>
'actions',
359 $a[
'CreateAccount'] = [
361 'cssclass' =>
'mw-block-restriction',
362 'label-message' =>
'ipbcreateaccount',
364 'section' =>
'details',
367 if ( $this->blockPermissionCheckerFactory
368 ->newBlockPermissionChecker(
null, $user )
369 ->checkEmailPermissions()
371 $a[
'DisableEmail'] = [
373 'cssclass' =>
'mw-block-restriction',
374 'label-message' =>
'ipbemailban',
375 'section' =>
'details',
378 $this->codexFormData[
'blockAllowsEmailBan'] =
true;
381 if ( $blockAllowsUTEdit ) {
382 $a[
'DisableUTEdit'] = [
384 'cssclass' =>
'mw-block-restriction',
385 'label-message' =>
'ipb-disableusertalk',
387 'section' =>
'details',
390 $this->codexFormData[
'blockAllowsUTEdit'] =
true;
393 $defaultExpiry = $this->
msg(
'ipb-default-expiry' )->inContentLanguage();
394 if ( $this->type === DatabaseBlock::TYPE_RANGE || $this->type === DatabaseBlock::TYPE_IP ) {
395 $defaultExpiryIP = $this->
msg(
'ipb-default-expiry-ip' )->inContentLanguage();
396 if ( !$defaultExpiryIP->isDisabled() ) {
397 $defaultExpiry = $defaultExpiryIP;
404 'options' => $suggestedDurations,
405 'default' => $defaultExpiry->text(),
406 'section' =>
'expiry',
410 'type' =>
'selectandother',
414 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
415 'maxlength-unit' =>
'codepoints',
416 'options-message' =>
'ipbreason-dropdown',
417 'section' =>
'reason',
423 'ipbenableautoblock',
427 'section' =>
'options',
434 'label-message' =>
'ipbhidename',
435 'cssclass' =>
'mw-block-hideuser',
436 'section' =>
'options',
441 if ( $user->isRegistered() ) {
444 'label-message' =>
'ipbwatchuser',
445 'section' =>
'options',
451 'label-message' =>
'ipb-hardblock',
453 'section' =>
'options',
458 $a[
'PreviousTarget'] = [
467 'label-message' =>
'ipb-confirm',
468 'cssclass' =>
'mw-block-confirm',
474 $this->
getHookRunner()->onSpecialBlockModifyFormFields( $this, $a );
486 $fields[
'Target'][
'default'] = (string)$this->target;
488 if ( $this->target ) {
489 $status = $this->blockUtils->validateTarget( $this->target );
490 if ( !$status->isOK() ) {
491 $errors = $status->getErrorsArray();
492 $this->preErrors = array_merge( $this->preErrors, $errors );
497 $fields[
'PreviousTarget'][
'default'] = (string)$this->target;
499 $block = $this->blockStore->newFromTarget( $this->target );
504 && ( $this->type != DatabaseBlock::TYPE_RANGE
505 || ( $this->target && $block->isBlocking( $this->target ) ) )
507 $fields[
'HardBlock'][
'default'] = $block->isHardblock();
508 $fields[
'CreateAccount'][
'default'] = $block->isCreateAccountBlocked();
509 $fields[
'AutoBlock'][
'default'] = $block->isAutoblocking();
511 if ( isset( $fields[
'DisableEmail'] ) ) {
512 $fields[
'DisableEmail'][
'default'] = $block->isEmailBlocked();
515 if ( isset( $fields[
'HideUser'] ) ) {
516 $fields[
'HideUser'][
'default'] = $block->getHideName();
519 if ( isset( $fields[
'DisableUTEdit'] ) ) {
520 $fields[
'DisableUTEdit'][
'default'] = !$block->isUsertalkEditAllowed();
525 if ( !$block->getHideName() || $this->
getAuthority()->isAllowed(
'hideuser' ) ) {
526 $fields[
'Reason'][
'default'] = $block->getReasonComment()->text;
528 $fields[
'Reason'][
'default'] =
'';
534 $fields[
'Confirm'][
'type'] =
'check';
539 $fields[
'Confirm'][
'default'] = 1;
542 if ( $block->getExpiry() ==
'infinity' ) {
543 $fields[
'Expiry'][
'default'] =
'infinite';
545 $fields[
'Expiry'][
'default'] =
wfTimestamp( TS_RFC2822, $block->getExpiry() );
548 if ( !$block->isSitewide() ) {
549 $fields[
'EditingRestriction'][
'default'] =
'partial';
551 $pageRestrictions = [];
552 $namespaceRestrictions = [];
553 foreach ( $block->getRestrictions() as $restriction ) {
555 $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
557 $this->namespaceInfo->exists( $restriction->getValue() )
559 $namespaceRestrictions[] = $restriction->getValue();
564 sort( $pageRestrictions );
565 $fields[
'PageRestrictions'][
'default'] = implode(
"\n", $pageRestrictions );
566 sort( $namespaceRestrictions );
567 $fields[
'NamespaceRestrictions'][
'default'] = implode(
"\n", $namespaceRestrictions );
570 $actionRestrictions = [];
571 foreach ( $block->getRestrictions() as $restriction ) {
573 $actionRestrictions[] = $restriction->getValue();
576 $fields[
'ActionRestrictions'][
'default'] = $actionRestrictions;
580 $this->alreadyBlocked =
true;
581 $this->preErrors[] = [
'ipb-needreblock',
wfEscapeWikiText( $block->getTargetName() ) ];
584 if ( $this->alreadyBlocked || $this->
getRequest()->wasPosted()
585 || $this->
getRequest()->getCheck(
'wpCreateAccount' )
587 $this->
getOutput()->addJsConfigVars(
'wgCreateAccountDirty',
true );
591 if ( $this->requestedHideUser ) {
592 $fields[
'Confirm'][
'type'] =
'check';
593 unset( $fields[
'Confirm'][
'default'] );
594 $this->preErrors[] = [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
599 $fields[
'Confirm'][
'type'] =
'check';
600 unset( $fields[
'Confirm'][
'default'] );
601 $this->preErrors[] = [
'ipb-blockingself',
'ipb-confirmaction' ];
610 $this->
getOutput()->addModuleStyles( [
'mediawiki.special' ] );
611 $this->
getOutput()->addModules( [
'mediawiki.special.block' ] );
614 $text = $this->
msg(
'blockiptext', $blockCIDRLimit[
'IPv4'], $blockCIDRLimit[
'IPv6'] )->parse();
616 $otherBlockMessages = [];
617 if ( $this->target !==
null ) {
620 $targetName = $this->target->
getName();
624 $otherBlockMessages, $targetName );
626 if ( count( $otherBlockMessages ) ) {
627 $s = Html::rawElement(
630 $this->
msg(
'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse()
635 foreach ( $otherBlockMessages as $link ) {
636 $list .= Html::rawElement(
'li', [], $link ) .
"\n";
639 $s .= Html::rawElement(
641 [
'class' =>
'mw-blockip-alreadyblocked' ],
659 $this->
getOutput()->addModuleStyles(
'mediawiki.special' );
665 $links[] = $linkRenderer->makeLink(
667 $this->
msg(
'ipb-blocklist-contribs', $this->target->getName() )->text()
673 $message = $this->
msg(
679 $message = $this->
msg(
'ipb-unblock' )->parse();
682 $links[] = $linkRenderer->makeKnownLink(
688 $links[] = $linkRenderer->makeKnownLink(
690 $this->
msg(
'ipb-blocklist' )->text()
694 if ( $this->
getAuthority()->isAllowed(
'editinterface' ) ) {
695 $links[] = $linkRenderer->makeKnownLink(
696 $this->
msg(
'ipbreason-dropdown' )->inContentLanguage()->
getTitle(),
697 $this->
msg(
'ipb-edit-dropdown' )->text(),
699 [
'action' =>
'edit' ]
703 $text = Html::rawElement(
705 [
'class' =>
'mw-ipb-conveniencelinks' ],
714 LogEventsList::showLogExtract(
723 $this->titleFormatter->getText( $userPage ),
725 'showIfEmpty' =>
false
731 if ( $this->
getAuthority()->isAllowed(
'suppressionlog' ) ) {
732 LogEventsList::showLogExtract(
739 'conds' => [
'log_action' => [
'block',
'reblock',
'unblock' ] ],
741 'blocklog-showsuppresslog',
742 $this->titleFormatter->getText( $userPage ),
744 'showIfEmpty' =>
false
789 return self::getTargetAndTypeInternal( $par, $request );
803 private static function getTargetAndTypeInternal( ?
string $par,
WebRequest $request =
null ) {
809 $request->getVal(
'wpTarget',
null ),
811 $request->getVal(
'ip',
null ),
813 $request->getVal(
'wpBlockAddress',
null ),
815 foreach ( $possibleTargets as $possibleTarget ) {
818 ->parseBlockTarget( $possibleTarget );
820 if ( $targetAndType[ 1 ] !==
null ) {
824 return $targetAndType;
837 return self::processFormInternal(
840 $services->getBlockUserFactory(),
841 $services->getBlockUtils()
855 private static function processFormInternal(
865 $isPartialBlock = isset( $data[
'EditingRestriction'] ) &&
866 $data[
'EditingRestriction'] ===
'partial';
870 $data[
'Confirm'] = !in_array( $data[
'Confirm'], [
'',
'0',
null,
false ],
true );
874 if ( !isset( $data[
'HideUser'] ) ) {
875 $data[
'HideUser'] =
false;
880 if ( $type == DatabaseBlock::TYPE_USER ) {
881 $target = $target->getName();
890 if ( $target === $performer->
getUser()->getName() &&
891 ( $data[
'PreviousTarget'] !== $target || !$data[
'Confirm'] )
893 return [
'ipb-blockingself',
'ipb-confirmaction' ];
896 if ( $data[
'HideUser'] && !$data[
'Confirm'] ) {
897 return [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
899 } elseif ( $type == DatabaseBlock::TYPE_IP ) {
900 $target = $target->getName();
901 } elseif ( $type != DatabaseBlock::TYPE_RANGE ) {
903 return [
'badipaddress' ];
908 $blockReason = $data[
'Reason'][0] ??
'';
910 $pageRestrictions = [];
911 $namespaceRestrictions = [];
912 $actionRestrictions = [];
913 if ( $isPartialBlock ) {
914 if ( isset( $data[
'PageRestrictions'] ) && $data[
'PageRestrictions'] !==
'' ) {
915 $titles = explode(
"\n", $data[
'PageRestrictions'] );
916 foreach ( $titles as $title ) {
917 $pageRestrictions[] = PageRestriction::newFromTitle( $title );
920 if ( isset( $data[
'NamespaceRestrictions'] ) && $data[
'NamespaceRestrictions'] !==
'' ) {
921 $namespaceRestrictions = array_map(
static function ( $id ) {
922 return new NamespaceRestriction( 0, (
int)$id );
923 }, explode(
"\n", $data[
'NamespaceRestrictions'] ) );
926 $enablePartialActionBlocks &&
927 isset( $data[
'ActionRestrictions'] ) &&
928 $data[
'ActionRestrictions'] !==
''
930 $actionRestrictions = array_map(
static function ( $id ) {
931 return new ActionRestriction( 0, $id );
932 }, $data[
'ActionRestrictions'] );
935 $restrictions = array_merge( $pageRestrictions, $namespaceRestrictions, $actionRestrictions );
937 if ( !isset( $data[
'Tags'] ) ) {
942 'isCreateAccountBlocked' => $data[
'CreateAccount'],
943 'isHardBlock' => $data[
'HardBlock'],
944 'isAutoblocking' => $data[
'AutoBlock'],
945 'isHideUser' => $data[
'HideUser'],
946 'isPartial' => $isPartialBlock,
949 if ( isset( $data[
'DisableUTEdit'] ) ) {
950 $blockOptions[
'isUserTalkEditBlocked'] = $data[
'DisableUTEdit'];
952 if ( isset( $data[
'DisableEmail'] ) ) {
953 $blockOptions[
'isEmailBlocked'] = $data[
'DisableEmail'];
968 $blockNotConfirmed = !$data[
'Confirm'] || ( array_key_exists(
'PreviousTarget', $data )
969 && $data[
'PreviousTarget'] !== $target );
972 $reblockNotAllowed = ( array_key_exists(
'Reblock', $data ) && !$data[
'Reblock'] );
974 $doReblock = !$blockNotConfirmed && !$reblockNotAllowed;
976 $status = $blockUser->placeBlock( $doReblock );
977 if ( !$status->isOK() ) {
983 $type != DatabaseBlock::TYPE_RANGE
988 && array_key_exists(
'Watch', $data )
993 Title::makeTitle(
NS_USER, $target )
1013 return $lang->getBlockDurations( $includeOther );
1038 ->getBlockPermissionCheckerFactory()
1039 ->newBlockPermissionChecker(
null, User::newFromIdentity( $user ) )
1040 ->checkEmailPermissions();
1050 return self::processFormInternal(
1053 $this->blockUserFactory,
1063 $out = $this->getOutput();
1064 $out->setPageTitleMsg( $this->msg(
'blockipsuccesssub' ) );
1065 $out->addWikiMsg(
'blockipsuccesstext',
wfEscapeWikiText( $this->target ) );
1077 $search = $this->userNameUtils->getCanonical( $search );
1083 return $this->userNamePrefixSearch
1084 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1093class_alias( SpecialBlock::class,
'SpecialBlock' );
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
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.
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 canonical, unlocalized name of this special page without namespace.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Interface for objects which can provide a MediaWiki context on request.