131 parent::__construct(
'Block',
'block' );
133 $this->blockUtils = $blockUtils;
134 $this->blockPermissionCheckerFactory = $blockPermissionCheckerFactory;
135 $this->blockUserFactory = $blockUserFactory;
136 $this->blockStore = $blockStore;
137 $this->userNameUtils = $userNameUtils;
138 $this->userNamePrefixSearch = $userNamePrefixSearch;
139 $this->blockActionInfo = $blockActionInfo;
140 $this->titleFormatter = $titleFormatter;
141 $this->namespaceInfo = $namespaceInfo;
155 parent::checkExecutePermissions( $user );
157 $status = $this->blockPermissionCheckerFactory
158 ->newBlockPermissionChecker( $this->target, $user )
159 ->checkBlockPermissions();
160 if ( $status !==
true ) {
188 $this->
getSkin()->setRelevantUser( $this->target );
192 ->parseBlockTarget( $request->getVal(
'wpPreviousTarget' ) );
193 $this->requestedHideUser = $request->getBool(
'wpHideUser' );
205 $msg = $this->alreadyBlocked ?
'ipb-change-block' :
'ipbsubmit';
211 if ( !$this->
getRequest()->wasPosted() && $this->preErrors ) {
217 'errors' => array_map(
function ( $errMsg ) {
219 return new HtmlSnippet( $this->
msg( ...$errMsg )->parse() );
242 $suggestedDurations = $this->
getLanguage()->getBlockDurations();
250 'id' =>
'mw-bi-target',
254 'placeholder' => $this->
msg(
'block-target-placeholder' )->text(),
255 'validation-callback' =>
function ( $value, $alldata, $form ) {
256 $status = $this->blockUtils->validateTarget( $value );
257 if ( !$status->isOK() ) {
258 $errors = $status->getErrorsArray();
260 return $form->msg( ...$errors[0] );
264 'section' =>
'target',
267 $a[
'EditingRestriction'] = [
269 'cssclass' =>
'mw-block-editing-restriction',
270 'default' =>
'sitewide',
272 $this->
msg(
'ipb-sitewide' )->escaped() .
274 'classes' => [
'oo-ui-inline-help' ],
275 'label' =>
new HtmlSnippet( $this->
msg(
'ipb-sitewide-help' )->parse() ),
277 $this->
msg(
'ipb-partial' )->escaped() .
279 'classes' => [
'oo-ui-inline-help' ],
280 'label' =>
new HtmlSnippet( $this->
msg(
'ipb-partial-help' )->parse() ),
283 'section' =>
'actions',
286 $a[
'PageRestrictions'] = [
287 'type' =>
'titlesmultiselect',
288 'label' => $this->
msg(
'ipb-pages-label' )->text(),
291 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction',
293 'showMissing' =>
false,
294 'excludeDynamicNamespaces' =>
true,
296 'autocomplete' => false
298 'section' =>
'actions',
301 $a[
'NamespaceRestrictions'] = [
302 'type' =>
'namespacesmultiselect',
303 'label' => $this->
msg(
'ipb-namespaces-label' )->text(),
305 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction',
308 'autocomplete' => false
310 'section' =>
'actions',
314 $blockActions = $this->blockActionInfo->getAllBlockActions();
315 $a[
'ActionRestrictions'] = [
316 'type' =>
'multiselect',
317 'cssclass' =>
'mw-htmlform-checkradio-indent mw-block-partial-restriction mw-block-action-restriction',
318 'options-messages' => array_combine(
319 array_map(
static function ( $action ) {
320 return "ipb-action-$action";
321 }, array_keys( $blockActions ) ),
324 'section' =>
'actions',
328 $a[
'CreateAccount'] = [
330 'cssclass' =>
'mw-block-restriction',
331 'label-message' =>
'ipbcreateaccount',
333 'section' =>
'details',
336 if ( $this->blockPermissionCheckerFactory
337 ->newBlockPermissionChecker(
null, $user )
338 ->checkEmailPermissions()
340 $a[
'DisableEmail'] = [
342 'cssclass' =>
'mw-block-restriction',
343 'label-message' =>
'ipbemailban',
344 'section' =>
'details',
348 if ( $blockAllowsUTEdit ) {
349 $a[
'DisableUTEdit'] = [
351 'cssclass' =>
'mw-block-restriction',
352 'label-message' =>
'ipb-disableusertalk',
354 'section' =>
'details',
358 $defaultExpiry = $this->
msg(
'ipb-default-expiry' )->inContentLanguage();
359 if ( $this->type === DatabaseBlock::TYPE_RANGE || $this->type === DatabaseBlock::TYPE_IP ) {
360 $defaultExpiryIP = $this->
msg(
'ipb-default-expiry-ip' )->inContentLanguage();
361 if ( !$defaultExpiryIP->isDisabled() ) {
362 $defaultExpiry = $defaultExpiryIP;
369 'options' => $suggestedDurations,
370 'default' => $defaultExpiry->text(),
371 'section' =>
'expiry',
375 'type' =>
'selectandother',
379 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
380 'maxlength-unit' =>
'codepoints',
381 'options-message' =>
'ipbreason-dropdown',
382 'section' =>
'reason',
388 'ipbenableautoblock',
392 'section' =>
'options',
399 'label-message' =>
'ipbhidename',
400 'cssclass' =>
'mw-block-hideuser',
401 'section' =>
'options',
406 if ( $user->isRegistered() ) {
409 'label-message' =>
'ipbwatchuser',
410 'section' =>
'options',
416 'label-message' =>
'ipb-hardblock',
418 'section' =>
'options',
423 $a[
'PreviousTarget'] = [
432 'label-message' =>
'ipb-confirm',
433 'cssclass' =>
'mw-block-confirm',
439 $this->
getHookRunner()->onSpecialBlockModifyFormFields( $this, $a );
451 $fields[
'Target'][
'default'] = (string)$this->target;
453 if ( $this->target ) {
454 $status = $this->blockUtils->validateTarget( $this->target );
455 if ( !$status->isOK() ) {
456 $errors = $status->getErrorsArray();
457 $this->preErrors = array_merge( $this->preErrors, $errors );
462 $fields[
'PreviousTarget'][
'default'] = (string)$this->target;
464 $block = $this->blockStore->newFromTarget( $this->target );
469 && ( $this->type != DatabaseBlock::TYPE_RANGE
470 || ( $this->target && $block->isBlocking( $this->target ) ) )
472 $fields[
'HardBlock'][
'default'] = $block->isHardblock();
473 $fields[
'CreateAccount'][
'default'] = $block->isCreateAccountBlocked();
474 $fields[
'AutoBlock'][
'default'] = $block->isAutoblocking();
476 if ( isset( $fields[
'DisableEmail'] ) ) {
477 $fields[
'DisableEmail'][
'default'] = $block->isEmailBlocked();
480 if ( isset( $fields[
'HideUser'] ) ) {
481 $fields[
'HideUser'][
'default'] = $block->getHideName();
484 if ( isset( $fields[
'DisableUTEdit'] ) ) {
485 $fields[
'DisableUTEdit'][
'default'] = !$block->isUsertalkEditAllowed();
490 if ( !$block->getHideName() || $this->
getAuthority()->isAllowed(
'hideuser' ) ) {
491 $fields[
'Reason'][
'default'] = $block->getReasonComment()->text;
493 $fields[
'Reason'][
'default'] =
'';
499 $fields[
'Confirm'][
'type'] =
'check';
504 $fields[
'Confirm'][
'default'] = 1;
507 if ( $block->getExpiry() ==
'infinity' ) {
508 $fields[
'Expiry'][
'default'] =
'infinite';
510 $fields[
'Expiry'][
'default'] =
wfTimestamp( TS_RFC2822, $block->getExpiry() );
513 if ( !$block->isSitewide() ) {
514 $fields[
'EditingRestriction'][
'default'] =
'partial';
516 $pageRestrictions = [];
517 $namespaceRestrictions = [];
518 foreach ( $block->getRestrictions() as $restriction ) {
520 $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
522 $this->namespaceInfo->exists( $restriction->getValue() )
524 $namespaceRestrictions[] = $restriction->getValue();
529 sort( $pageRestrictions );
530 $fields[
'PageRestrictions'][
'default'] = implode(
"\n", $pageRestrictions );
531 sort( $namespaceRestrictions );
532 $fields[
'NamespaceRestrictions'][
'default'] = implode(
"\n", $namespaceRestrictions );
535 $actionRestrictions = [];
536 foreach ( $block->getRestrictions() as $restriction ) {
538 $actionRestrictions[] = $restriction->getValue();
541 $fields[
'ActionRestrictions'][
'default'] = $actionRestrictions;
545 $this->alreadyBlocked =
true;
546 $this->preErrors[] = [
'ipb-needreblock',
wfEscapeWikiText( $block->getTargetName() ) ];
549 if ( $this->alreadyBlocked || $this->
getRequest()->wasPosted()
550 || $this->
getRequest()->getCheck(
'wpCreateAccount' )
552 $this->
getOutput()->addJsConfigVars(
'wgCreateAccountDirty',
true );
556 if ( $this->requestedHideUser ) {
557 $fields[
'Confirm'][
'type'] =
'check';
558 unset( $fields[
'Confirm'][
'default'] );
559 $this->preErrors[] = [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
564 $fields[
'Confirm'][
'type'] =
'check';
565 unset( $fields[
'Confirm'][
'default'] );
566 $this->preErrors[] = [
'ipb-blockingself',
'ipb-confirmaction' ];
575 $this->
getOutput()->addModuleStyles( [
'mediawiki.special' ] );
576 $this->
getOutput()->addModules( [
'mediawiki.special.block' ] );
579 $text = $this->
msg(
'blockiptext', $blockCIDRLimit[
'IPv4'], $blockCIDRLimit[
'IPv6'] )->parse();
581 $otherBlockMessages = [];
582 if ( $this->target !==
null ) {
585 $targetName = $this->target->
getName();
589 $otherBlockMessages, $targetName );
591 if ( count( $otherBlockMessages ) ) {
592 $s = Html::rawElement(
595 $this->
msg(
'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse()
600 foreach ( $otherBlockMessages as $link ) {
601 $list .= Html::rawElement(
'li', [], $link ) .
"\n";
604 $s .= Html::rawElement(
606 [
'class' =>
'mw-blockip-alreadyblocked' ],
624 $this->
getOutput()->addModuleStyles(
'mediawiki.special' );
630 $links[] = $linkRenderer->makeLink(
632 $this->
msg(
'ipb-blocklist-contribs', $this->target->getName() )->text()
638 $message = $this->
msg(
644 $message = $this->
msg(
'ipb-unblock' )->parse();
647 $links[] = $linkRenderer->makeKnownLink(
653 $links[] = $linkRenderer->makeKnownLink(
655 $this->
msg(
'ipb-blocklist' )->text()
659 if ( $this->
getAuthority()->isAllowed(
'editinterface' ) ) {
660 $links[] = $linkRenderer->makeKnownLink(
661 $this->
msg(
'ipbreason-dropdown' )->inContentLanguage()->
getTitle(),
662 $this->
msg(
'ipb-edit-dropdown' )->text(),
664 [
'action' =>
'edit' ]
668 $text = Html::rawElement(
670 [
'class' =>
'mw-ipb-conveniencelinks' ],
679 LogEventsList::showLogExtract(
688 $this->titleFormatter->getText( $userPage ),
690 'showIfEmpty' =>
false
696 if ( $this->
getAuthority()->isAllowed(
'suppressionlog' ) ) {
697 LogEventsList::showLogExtract(
704 'conds' => [
'log_action' => [
'block',
'reblock',
'unblock' ] ],
706 'blocklog-showsuppresslog',
707 $this->titleFormatter->getText( $userPage ),
709 'showIfEmpty' =>
false
754 return self::getTargetAndTypeInternal( $par, $request );
768 private static function getTargetAndTypeInternal( ?
string $par,
WebRequest $request =
null ) {
774 $request->getVal(
'wpTarget',
null ),
776 $request->getVal(
'ip',
null ),
778 $request->getVal(
'wpBlockAddress',
null ),
780 foreach ( $possibleTargets as $possibleTarget ) {
783 ->parseBlockTarget( $possibleTarget );
785 if ( $targetAndType[ 1 ] !==
null ) {
789 return $targetAndType;
802 return self::processFormInternal(
805 $services->getBlockUserFactory(),
806 $services->getBlockUtils()
820 private static function processFormInternal(
830 $isPartialBlock = isset( $data[
'EditingRestriction'] ) &&
831 $data[
'EditingRestriction'] ===
'partial';
835 $data[
'Confirm'] = !in_array( $data[
'Confirm'], [
'',
'0',
null,
false ],
true );
839 if ( !isset( $data[
'HideUser'] ) ) {
840 $data[
'HideUser'] =
false;
845 if ( $type == DatabaseBlock::TYPE_USER ) {
846 $target = $target->getName();
855 if ( $target === $performer->
getUser()->getName() &&
856 ( $data[
'PreviousTarget'] !== $target || !$data[
'Confirm'] )
858 return [
'ipb-blockingself',
'ipb-confirmaction' ];
861 if ( $data[
'HideUser'] && !$data[
'Confirm'] ) {
862 return [
'ipb-confirmhideuser',
'ipb-confirmaction' ];
864 } elseif ( $type == DatabaseBlock::TYPE_IP ) {
865 $target = $target->getName();
866 } elseif ( $type != DatabaseBlock::TYPE_RANGE ) {
868 return [
'badipaddress' ];
873 $blockReason = $data[
'Reason'][0] ??
'';
875 $pageRestrictions = [];
876 $namespaceRestrictions = [];
877 $actionRestrictions = [];
878 if ( $isPartialBlock ) {
879 if ( isset( $data[
'PageRestrictions'] ) && $data[
'PageRestrictions'] !==
'' ) {
880 $titles = explode(
"\n", $data[
'PageRestrictions'] );
881 foreach ( $titles as $title ) {
882 $pageRestrictions[] = PageRestriction::newFromTitle( $title );
885 if ( isset( $data[
'NamespaceRestrictions'] ) && $data[
'NamespaceRestrictions'] !==
'' ) {
886 $namespaceRestrictions = array_map(
static function ( $id ) {
887 return new NamespaceRestriction( 0, (
int)$id );
888 }, explode(
"\n", $data[
'NamespaceRestrictions'] ) );
891 $enablePartialActionBlocks &&
892 isset( $data[
'ActionRestrictions'] ) &&
893 $data[
'ActionRestrictions'] !==
''
895 $actionRestrictions = array_map(
static function ( $id ) {
896 return new ActionRestriction( 0, $id );
897 }, $data[
'ActionRestrictions'] );
900 $restrictions = array_merge( $pageRestrictions, $namespaceRestrictions, $actionRestrictions );
902 if ( !isset( $data[
'Tags'] ) ) {
907 'isCreateAccountBlocked' => $data[
'CreateAccount'],
908 'isHardBlock' => $data[
'HardBlock'],
909 'isAutoblocking' => $data[
'AutoBlock'],
910 'isHideUser' => $data[
'HideUser'],
911 'isPartial' => $isPartialBlock,
914 if ( isset( $data[
'DisableUTEdit'] ) ) {
915 $blockOptions[
'isUserTalkEditBlocked'] = $data[
'DisableUTEdit'];
917 if ( isset( $data[
'DisableEmail'] ) ) {
918 $blockOptions[
'isEmailBlocked'] = $data[
'DisableEmail'];
933 $blockNotConfirmed = !$data[
'Confirm'] || ( array_key_exists(
'PreviousTarget', $data )
934 && $data[
'PreviousTarget'] !== $target );
937 $reblockNotAllowed = ( array_key_exists(
'Reblock', $data ) && !$data[
'Reblock'] );
939 $doReblock = !$blockNotConfirmed && !$reblockNotAllowed;
941 $status = $blockUser->placeBlock( $doReblock );
942 if ( !$status->isOK() ) {
948 $type != DatabaseBlock::TYPE_RANGE
953 && array_key_exists(
'Watch', $data )
958 Title::makeTitle(
NS_USER, $target )
978 return $lang->getBlockDurations( $includeOther );
1003 ->getBlockPermissionCheckerFactory()
1004 ->newBlockPermissionChecker(
null, User::newFromIdentity( $user ) )
1005 ->checkEmailPermissions();
1015 return self::processFormInternal(
1018 $this->blockUserFactory,
1028 $out = $this->getOutput();
1029 $out->setPageTitleMsg( $this->msg(
'blockipsuccesssub' ) );
1030 $out->addWikiMsg(
'blockipsuccesstext',
wfEscapeWikiText( $this->target ) );
1042 $search = $this->userNameUtils->getCanonical( $search );
1048 return $this->userNamePrefixSearch
1049 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
1060class_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.