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
784 private static function getTargetAndTypeInternal( ?
string $par, WebRequest $request =
null ) {
785 if ( !$request instanceof WebRequest ) {
790 $request->getVal(
'wpTarget',
null ),
792 $request->getVal(
'ip',
null ),
794 $request->getVal(
'wpBlockAddress',
null ),
796 foreach ( $possibleTargets as $possibleTarget ) {
799 ->parseBlockTarget( $possibleTarget );
801 if ( $targetAndType[ 1 ] !==
null ) {
805 return $targetAndType;
818 return self::processFormInternal(
821 $services->getBlockUserFactory(),
822 $services->getBlockUtils()
836 private static function processFormInternal(
846 $isPartialBlock = isset( $data[
'EditingRestriction'] ) &&
847 $data[
'EditingRestriction'] ===
'partial';
851 $data[
'Confirm'] = !in_array( $data[
'Confirm'], [
'',
'0',
null,
false ],
true );
855 if ( !isset( $data[
'HideUser'] ) ) {
856 $data[
'HideUser'] =
false;
861 if ( $type == DatabaseBlock::TYPE_USER ) {
862 $target = $target->getName();
871 if ( $target === $performer->
getUser()->getName() &&
872 ( $data[
'PreviousTarget'] !== $target || !$data[
'Confirm'] )
874 return [
'ipb-blockingself',
'ipb-confirmaction' ];
877 if ( $data[
'HideUser'] && !$data[
'Confirm'] ) {
878 return [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
880 } elseif ( $type == DatabaseBlock::TYPE_IP ) {
881 $target = $target->getName();
882 } elseif ( $type != DatabaseBlock::TYPE_RANGE ) {
884 return [
'badipaddress' ];
889 $blockReason = $data[
'Reason'][0] ??
'';
891 $pageRestrictions = [];
892 $namespaceRestrictions = [];
893 $actionRestrictions = [];
894 if ( $isPartialBlock ) {
895 if ( isset( $data[
'PageRestrictions'] ) && $data[
'PageRestrictions'] !==
'' ) {
896 $titles = explode(
"\n", $data[
'PageRestrictions'] );
897 foreach ( $titles as $title ) {
898 $pageRestrictions[] = PageRestriction::newFromTitle( $title );
901 if ( isset( $data[
'NamespaceRestrictions'] ) && $data[
'NamespaceRestrictions'] !==
'' ) {
902 $namespaceRestrictions = array_map(
static function ( $id ) {
903 return new NamespaceRestriction( 0, (
int)$id );
904 }, explode(
"\n", $data[
'NamespaceRestrictions'] ) );
907 $enablePartialActionBlocks &&
908 isset( $data[
'ActionRestrictions'] ) &&
909 $data[
'ActionRestrictions'] !==
''
911 $actionRestrictions = array_map(
static function ( $id ) {
912 return new ActionRestriction( 0, $id );
913 }, $data[
'ActionRestrictions'] );
916 $restrictions = array_merge( $pageRestrictions, $namespaceRestrictions, $actionRestrictions );
918 if ( !isset( $data[
'Tags'] ) ) {
923 'isCreateAccountBlocked' => $data[
'CreateAccount'],
924 'isHardBlock' => $data[
'HardBlock'],
925 'isAutoblocking' => $data[
'AutoBlock'],
926 'isHideUser' => $data[
'HideUser'],
927 'isPartial' => $isPartialBlock,
930 if ( isset( $data[
'DisableUTEdit'] ) ) {
931 $blockOptions[
'isUserTalkEditBlocked'] = $data[
'DisableUTEdit'];
933 if ( isset( $data[
'DisableEmail'] ) ) {
934 $blockOptions[
'isEmailBlocked'] = $data[
'DisableEmail'];
949 $blockNotConfirmed = !$data[
'Confirm'] || ( array_key_exists(
'PreviousTarget', $data )
950 && $data[
'PreviousTarget'] !== $target );
953 $reblockNotAllowed = ( array_key_exists(
'Reblock', $data ) && !$data[
'Reblock'] );
955 $doReblock = !$blockNotConfirmed && !$reblockNotAllowed;
957 $status = $blockUser->placeBlock( $doReblock );
958 if ( !$status->isOK() ) {
964 $type != DatabaseBlock::TYPE_RANGE
969 && array_key_exists(
'Watch', $data )
974 Title::makeTitle(
NS_USER, $target )
994 return $lang->getBlockDurations( $includeOther );
1019 ->getBlockPermissionCheckerFactory()
1020 ->newBlockPermissionChecker(
null, User::newFromIdentity( $user ) )
1021 ->checkEmailPermissions();
1031 return self::processFormInternal(
1034 $this->blockUserFactory,
1044 $out = $this->getOutput();
1045 $out->setPageTitleMsg( $this->msg(
'blockipsuccesssub' ) );
1046 $out->addWikiMsg(
'blockipsuccesstext',
wfEscapeWikiText( $this->target ) );
1058 $search = $this->userNameUtils->getCanonical( $search );
1064 return $this->userNamePrefixSearch
1065 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1074class_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.
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.