2011-03-12 21:54:35 +00:00
|
|
|
<?php
|
|
|
|
|
/**
|
2011-03-12 22:53:15 +00:00
|
|
|
* Implements Special:Block
|
2011-03-12 21:54:35 +00:00
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
|
|
|
*
|
|
|
|
|
* @file
|
|
|
|
|
* @ingroup SpecialPage
|
|
|
|
|
*/
|
|
|
|
|
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
use MediaWiki\Block\BlockActionInfo;
|
2020-10-05 16:08:10 +00:00
|
|
|
use MediaWiki\Block\BlockPermissionCheckerFactory;
|
2020-04-23 19:33:56 +00:00
|
|
|
use MediaWiki\Block\BlockUser;
|
2020-10-05 16:08:10 +00:00
|
|
|
use MediaWiki\Block\BlockUserFactory;
|
|
|
|
|
use MediaWiki\Block\BlockUtils;
|
2019-05-13 14:18:07 +00:00
|
|
|
use MediaWiki\Block\DatabaseBlock;
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
use MediaWiki\Block\Restriction\ActionRestriction;
|
2018-12-14 21:08:40 +00:00
|
|
|
use MediaWiki\Block\Restriction\NamespaceRestriction;
|
2020-01-10 00:00:51 +00:00
|
|
|
use MediaWiki\Block\Restriction\PageRestriction;
|
2022-04-13 15:28:26 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
2019-04-11 19:54:10 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2021-05-30 16:18:26 +00:00
|
|
|
use MediaWiki\Page\PageReference;
|
|
|
|
|
use MediaWiki\Page\PageReferenceValue;
|
2021-03-17 02:58:43 +00:00
|
|
|
use MediaWiki\Permissions\Authority;
|
2019-08-21 02:01:06 +00:00
|
|
|
use MediaWiki\User\UserIdentity;
|
2020-10-05 16:08:10 +00:00
|
|
|
use MediaWiki\User\UserNamePrefixSearch;
|
|
|
|
|
use MediaWiki\User\UserNameUtils;
|
2019-06-25 18:53:15 +00:00
|
|
|
use Wikimedia\IPUtils;
|
2018-08-27 22:19:37 +00:00
|
|
|
|
2011-03-12 21:54:35 +00:00
|
|
|
/**
|
|
|
|
|
* A special page that allows users with 'block' right to block users from
|
|
|
|
|
* editing pages and other actions
|
|
|
|
|
*
|
|
|
|
|
* @ingroup SpecialPage
|
|
|
|
|
*/
|
2011-11-15 02:25:36 +00:00
|
|
|
class SpecialBlock extends FormSpecialPage {
|
2020-05-08 22:31:17 +00:00
|
|
|
|
2020-10-05 16:08:10 +00:00
|
|
|
/** @var BlockUtils */
|
|
|
|
|
private $blockUtils;
|
|
|
|
|
|
|
|
|
|
/** @var BlockPermissionCheckerFactory */
|
|
|
|
|
private $blockPermissionCheckerFactory;
|
|
|
|
|
|
|
|
|
|
/** @var BlockUserFactory */
|
|
|
|
|
private $blockUserFactory;
|
|
|
|
|
|
|
|
|
|
/** @var UserNameUtils */
|
|
|
|
|
private $userNameUtils;
|
|
|
|
|
|
|
|
|
|
/** @var UserNamePrefixSearch */
|
|
|
|
|
private $userNamePrefixSearch;
|
|
|
|
|
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
/** @var BlockActionInfo */
|
|
|
|
|
private $blockActionInfo;
|
|
|
|
|
|
2021-05-30 16:18:26 +00:00
|
|
|
/** @var TitleFormatter */
|
|
|
|
|
private $titleFormatter;
|
|
|
|
|
|
2021-07-15 21:57:52 +00:00
|
|
|
/** @var UserIdentity|string|null User to be blocked, as passed either by parameter
|
|
|
|
|
* (url?wpTarget=Foo) or as subpage (Special:Block/Foo)
|
2019-08-05 17:00:00 +00:00
|
|
|
*/
|
2011-03-12 22:53:15 +00:00
|
|
|
protected $target;
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
/** @var int DatabaseBlock::TYPE_ constant */
|
2011-03-12 22:53:15 +00:00
|
|
|
protected $type;
|
|
|
|
|
|
2014-04-19 08:16:52 +00:00
|
|
|
/** @var User|string The previous block target */
|
2011-04-01 23:13:15 +00:00
|
|
|
protected $previousTarget;
|
|
|
|
|
|
2014-04-19 08:16:52 +00:00
|
|
|
/** @var bool Whether the previous submission of the form asked for HideUser */
|
2011-04-01 23:13:15 +00:00
|
|
|
protected $requestedHideUser;
|
|
|
|
|
|
2014-04-19 08:16:52 +00:00
|
|
|
/** @var bool */
|
2011-03-12 22:53:15 +00:00
|
|
|
protected $alreadyBlocked;
|
2011-06-02 19:32:45 +00:00
|
|
|
|
2014-04-19 08:16:52 +00:00
|
|
|
/** @var array */
|
2016-02-17 09:09:32 +00:00
|
|
|
protected $preErrors = [];
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2021-08-16 16:50:55 +00:00
|
|
|
/** @var NamespaceInfo */
|
|
|
|
|
private $namespaceInfo;
|
|
|
|
|
|
2020-10-05 16:08:10 +00:00
|
|
|
/**
|
|
|
|
|
* @param BlockUtils $blockUtils
|
|
|
|
|
* @param BlockPermissionCheckerFactory $blockPermissionCheckerFactory
|
|
|
|
|
* @param BlockUserFactory $blockUserFactory
|
|
|
|
|
* @param UserNameUtils $userNameUtils
|
|
|
|
|
* @param UserNamePrefixSearch $userNamePrefixSearch
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
* @param BlockActionInfo $blockActionInfo
|
2021-05-30 16:18:26 +00:00
|
|
|
* @param TitleFormatter $titleFormatter
|
2021-08-16 16:50:55 +00:00
|
|
|
* @param NamespaceInfo $namespaceInfo
|
2020-10-05 16:08:10 +00:00
|
|
|
*/
|
|
|
|
|
public function __construct(
|
|
|
|
|
BlockUtils $blockUtils,
|
|
|
|
|
BlockPermissionCheckerFactory $blockPermissionCheckerFactory,
|
|
|
|
|
BlockUserFactory $blockUserFactory,
|
|
|
|
|
UserNameUtils $userNameUtils,
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
UserNamePrefixSearch $userNamePrefixSearch,
|
2021-05-30 16:18:26 +00:00
|
|
|
BlockActionInfo $blockActionInfo,
|
2021-08-16 16:50:55 +00:00
|
|
|
TitleFormatter $titleFormatter,
|
|
|
|
|
NamespaceInfo $namespaceInfo
|
2020-10-05 16:08:10 +00:00
|
|
|
) {
|
2011-03-12 22:53:15 +00:00
|
|
|
parent::__construct( 'Block', 'block' );
|
2020-05-08 22:31:17 +00:00
|
|
|
|
2020-10-05 16:08:10 +00:00
|
|
|
$this->blockUtils = $blockUtils;
|
|
|
|
|
$this->blockPermissionCheckerFactory = $blockPermissionCheckerFactory;
|
|
|
|
|
$this->blockUserFactory = $blockUserFactory;
|
|
|
|
|
$this->userNameUtils = $userNameUtils;
|
|
|
|
|
$this->userNamePrefixSearch = $userNamePrefixSearch;
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
$this->blockActionInfo = $blockActionInfo;
|
2021-05-30 16:18:26 +00:00
|
|
|
$this->titleFormatter = $titleFormatter;
|
2021-08-16 16:50:55 +00:00
|
|
|
$this->namespaceInfo = $namespaceInfo;
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-14 22:35:31 +00:00
|
|
|
public function doesWrites() {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
/**
|
|
|
|
|
* Checks that the user can unblock themselves if they are trying to do so
|
|
|
|
|
*
|
|
|
|
|
* @param User $user
|
|
|
|
|
* @throws ErrorPageError
|
|
|
|
|
*/
|
|
|
|
|
protected function checkExecutePermissions( User $user ) {
|
2013-02-03 19:28:43 +00:00
|
|
|
parent::checkExecutePermissions( $user );
|
2017-02-20 22:31:04 +00:00
|
|
|
# T17810: blocked admins should have limited access here
|
2020-10-05 16:08:10 +00:00
|
|
|
$status = $this->blockPermissionCheckerFactory
|
|
|
|
|
->newBlockPermissionChecker( $this->target, $user )
|
|
|
|
|
->checkBlockPermissions();
|
2011-11-15 02:25:36 +00:00
|
|
|
if ( $status !== true ) {
|
|
|
|
|
throw new ErrorPageError( 'badaccess', $status );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-27 18:38:14 +00:00
|
|
|
/**
|
|
|
|
|
* We allow certain special cases where user is blocked
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function requiresUnblock() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
/**
|
|
|
|
|
* Handle some magic here
|
|
|
|
|
*
|
2014-04-19 08:16:52 +00:00
|
|
|
* @param string $par
|
2011-11-15 02:25:36 +00:00
|
|
|
*/
|
|
|
|
|
protected function setParameter( $par ) {
|
2011-03-12 22:53:15 +00:00
|
|
|
# Extract variables from the request. Try not to get into a situation where we
|
|
|
|
|
# need to extract *every* variable from the form just for processing here, but
|
|
|
|
|
# there are legitimate uses for some variables
|
2011-09-12 08:49:14 +00:00
|
|
|
$request = $this->getRequest();
|
|
|
|
|
list( $this->target, $this->type ) = self::getTargetAndType( $par, $request );
|
2021-07-15 21:57:52 +00:00
|
|
|
if ( $this->target instanceof UserIdentity ) {
|
2011-03-12 22:53:15 +00:00
|
|
|
# Set the 'relevant user' in the skin, so it displays links like Contributions,
|
|
|
|
|
# User logs, UserRights, etc.
|
2011-07-01 02:25:19 +00:00
|
|
|
$this->getSkin()->setRelevantUser( $this->target );
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-03-18 20:37:11 +00:00
|
|
|
|
2021-03-17 17:48:43 +00:00
|
|
|
list( $this->previousTarget, /*...*/ ) = $this->blockUtils
|
|
|
|
|
->parseBlockTarget( $request->getVal( 'wpPreviousTarget' ) );
|
2011-09-12 08:49:14 +00:00
|
|
|
$this->requestedHideUser = $request->getBool( 'wpHideUser' );
|
2011-11-15 02:25:36 +00:00
|
|
|
}
|
2011-04-01 23:13:15 +00:00
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
/**
|
|
|
|
|
* Customizes the HTMLForm a bit
|
|
|
|
|
*
|
2014-04-19 08:16:52 +00:00
|
|
|
* @param HTMLForm $form
|
2011-11-15 02:25:36 +00:00
|
|
|
*/
|
|
|
|
|
protected function alterForm( HTMLForm $form ) {
|
|
|
|
|
$form->setHeaderText( '' );
|
2014-10-07 23:07:58 +00:00
|
|
|
$form->setSubmitDestructive();
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
$msg = $this->alreadyBlocked ? 'ipb-change-block' : 'ipbsubmit';
|
|
|
|
|
$form->setSubmitTextMsg( $msg );
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2015-05-02 11:37:19 +00:00
|
|
|
$this->addHelpLink( 'Help:Blocking users' );
|
2014-08-31 10:25:18 +00:00
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
# Don't need to do anything if the form has been posted
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( !$this->getRequest()->wasPosted() && $this->preErrors ) {
|
2022-06-07 22:43:37 +00:00
|
|
|
if ( $this->preErrors ) {
|
|
|
|
|
# Mimic error messages normally generated by the form
|
|
|
|
|
$form->addHeaderText( (string)new OOUI\FieldLayout(
|
|
|
|
|
new OOUI\Widget( [] ),
|
|
|
|
|
[
|
|
|
|
|
'align' => 'top',
|
|
|
|
|
'errors' => array_map( function ( $errMsg ) {
|
|
|
|
|
return new OOUI\HtmlSnippet( $this->msg( ...$errMsg )->parse() );
|
|
|
|
|
}, $this->preErrors ),
|
|
|
|
|
]
|
2013-03-25 22:52:41 +00:00
|
|
|
) );
|
2011-11-15 02:25:36 +00:00
|
|
|
}
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2015-07-26 23:44:25 +00:00
|
|
|
protected function getDisplayFormat() {
|
|
|
|
|
return 'ooui';
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
/**
|
|
|
|
|
* Get the HTMLForm descriptor array for the block form
|
2014-04-19 08:16:52 +00:00
|
|
|
* @return array
|
2011-03-12 22:53:15 +00:00
|
|
|
*/
|
2012-08-29 02:34:00 +00:00
|
|
|
protected function getFormFields() {
|
2019-04-02 10:43:37 +00:00
|
|
|
$conf = $this->getConfig();
|
2022-04-26 15:48:03 +00:00
|
|
|
$blockAllowsUTEdit = $conf->get( MainConfigNames::BlockAllowsUTEdit );
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
$this->getOutput()->addJsConfigVars(
|
|
|
|
|
'wgEnablePartialActionBlocks',
|
2022-04-26 15:48:03 +00:00
|
|
|
$conf->get( MainConfigNames::EnablePartialActionBlocks )
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
);
|
2017-01-21 18:54:21 +00:00
|
|
|
|
2019-02-27 22:11:40 +00:00
|
|
|
$this->getOutput()->enableOOUI();
|
|
|
|
|
|
2011-09-12 08:49:14 +00:00
|
|
|
$user = $this->getUser();
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2013-04-29 13:48:57 +00:00
|
|
|
$suggestedDurations = self::getSuggestedDurations();
|
|
|
|
|
|
2018-08-27 22:19:37 +00:00
|
|
|
$a = [];
|
|
|
|
|
|
|
|
|
|
$a['Target'] = [
|
|
|
|
|
'type' => 'user',
|
|
|
|
|
'ipallowed' => true,
|
|
|
|
|
'iprange' => true,
|
|
|
|
|
'id' => 'mw-bi-target',
|
|
|
|
|
'size' => '45',
|
|
|
|
|
'autofocus' => true,
|
|
|
|
|
'required' => true,
|
2021-04-01 06:15:36 +00:00
|
|
|
'placeholder' => $this->msg( 'block-target-placeholder' )->text(),
|
2020-10-05 16:08:10 +00:00
|
|
|
'validation-callback' => function ( $value, $alldata, $form ) {
|
|
|
|
|
$status = $this->blockUtils->validateTarget( $value );
|
|
|
|
|
if ( !$status->isOK() ) {
|
|
|
|
|
$errors = $status->getErrorsArray();
|
|
|
|
|
|
|
|
|
|
return $form->msg( ...$errors[0] );
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
2019-01-07 14:04:54 +00:00
|
|
|
'section' => 'target',
|
|
|
|
|
];
|
|
|
|
|
|
2020-03-02 16:18:23 +00:00
|
|
|
$a['EditingRestriction'] = [
|
|
|
|
|
'type' => 'radio',
|
|
|
|
|
'cssclass' => 'mw-block-editing-restriction',
|
2020-04-17 13:57:26 +00:00
|
|
|
'default' => 'sitewide',
|
2020-03-02 16:18:23 +00:00
|
|
|
'options' => [
|
|
|
|
|
$this->msg( 'ipb-sitewide' )->escaped() .
|
|
|
|
|
new \OOUI\LabelWidget( [
|
|
|
|
|
'classes' => [ 'oo-ui-inline-help' ],
|
2021-05-04 10:21:03 +00:00
|
|
|
'label' => new \OOUI\HtmlSnippet( $this->msg( 'ipb-sitewide-help' )->parse() ),
|
2020-03-02 16:18:23 +00:00
|
|
|
] ) => 'sitewide',
|
|
|
|
|
$this->msg( 'ipb-partial' )->escaped() .
|
|
|
|
|
new \OOUI\LabelWidget( [
|
|
|
|
|
'classes' => [ 'oo-ui-inline-help' ],
|
|
|
|
|
'label' => $this->msg( 'ipb-partial-help' )->text(),
|
|
|
|
|
] ) => 'partial',
|
|
|
|
|
],
|
|
|
|
|
'section' => 'actions',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$a['PageRestrictions'] = [
|
|
|
|
|
'type' => 'titlesmultiselect',
|
|
|
|
|
'label' => $this->msg( 'ipb-pages-label' )->text(),
|
|
|
|
|
'exists' => true,
|
|
|
|
|
'max' => 10,
|
2022-06-06 16:58:11 +00:00
|
|
|
'cssclass' => 'mw-htmlform-checkradio-indent mw-block-partial-restriction',
|
2020-03-02 16:18:23 +00:00
|
|
|
'showMissing' => false,
|
|
|
|
|
'excludeDynamicNamespaces' => true,
|
|
|
|
|
'input' => [
|
|
|
|
|
'autocomplete' => false
|
|
|
|
|
],
|
|
|
|
|
'section' => 'actions',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$a['NamespaceRestrictions'] = [
|
|
|
|
|
'type' => 'namespacesmultiselect',
|
|
|
|
|
'label' => $this->msg( 'ipb-namespaces-label' )->text(),
|
|
|
|
|
'exists' => true,
|
2022-06-06 16:58:11 +00:00
|
|
|
'cssclass' => 'mw-htmlform-checkradio-indent mw-block-partial-restriction',
|
2020-03-02 16:18:23 +00:00
|
|
|
'input' => [
|
|
|
|
|
'autocomplete' => false
|
|
|
|
|
],
|
|
|
|
|
'section' => 'actions',
|
|
|
|
|
];
|
2018-08-27 22:19:37 +00:00
|
|
|
|
2022-04-26 15:48:03 +00:00
|
|
|
if ( $conf->get( MainConfigNames::EnablePartialActionBlocks ) ) {
|
2021-05-04 10:21:03 +00:00
|
|
|
$blockActions = $this->blockActionInfo->getAllBlockActions();
|
|
|
|
|
$a['ActionRestrictions'] = [
|
|
|
|
|
'type' => 'multiselect',
|
2022-06-06 16:58:11 +00:00
|
|
|
'cssclass' => 'mw-htmlform-checkradio-indent mw-block-partial-restriction mw-block-action-restriction',
|
2021-05-04 10:21:03 +00:00
|
|
|
'options-messages' => array_combine(
|
|
|
|
|
array_map( static function ( $action ) {
|
|
|
|
|
return "ipb-action-$action";
|
|
|
|
|
}, array_keys( $blockActions ) ),
|
|
|
|
|
$blockActions
|
|
|
|
|
),
|
|
|
|
|
'section' => 'actions',
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-27 22:19:37 +00:00
|
|
|
$a['CreateAccount'] = [
|
|
|
|
|
'type' => 'check',
|
2021-05-04 10:21:03 +00:00
|
|
|
'cssclass' => 'mw-block-restriction',
|
2018-08-27 22:19:37 +00:00
|
|
|
'label-message' => 'ipbcreateaccount',
|
|
|
|
|
'default' => true,
|
2021-05-04 10:21:03 +00:00
|
|
|
'section' => 'details',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2020-10-05 16:08:10 +00:00
|
|
|
if ( $this->blockPermissionCheckerFactory
|
|
|
|
|
->newBlockPermissionChecker( null, $user )
|
|
|
|
|
->checkEmailPermissions()
|
|
|
|
|
) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['DisableEmail'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'check',
|
2021-05-04 10:21:03 +00:00
|
|
|
'cssclass' => 'mw-block-restriction',
|
2011-03-12 22:53:15 +00:00
|
|
|
'label-message' => 'ipbemailban',
|
2021-05-04 10:21:03 +00:00
|
|
|
'section' => 'details',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-02 10:43:37 +00:00
|
|
|
if ( $blockAllowsUTEdit ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['DisableUTEdit'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'check',
|
2021-05-04 10:21:03 +00:00
|
|
|
'cssclass' => 'mw-block-restriction',
|
2011-03-12 22:53:15 +00:00
|
|
|
'label-message' => 'ipb-disableusertalk',
|
|
|
|
|
'default' => false,
|
2021-05-04 10:21:03 +00:00
|
|
|
'section' => 'details',
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-05 04:34:46 +00:00
|
|
|
$defaultExpiry = $this->msg( 'ipb-default-expiry' )->inContentLanguage();
|
|
|
|
|
if ( $this->type === DatabaseBlock::TYPE_RANGE || $this->type === DatabaseBlock::TYPE_IP ) {
|
|
|
|
|
$defaultExpiryIP = $this->msg( 'ipb-default-expiry-ip' )->inContentLanguage();
|
|
|
|
|
if ( !$defaultExpiryIP->isDisabled() ) {
|
|
|
|
|
$defaultExpiry = $defaultExpiryIP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-07 14:04:54 +00:00
|
|
|
$a['Expiry'] = [
|
|
|
|
|
'type' => 'expiry',
|
|
|
|
|
'required' => true,
|
|
|
|
|
'options' => $suggestedDurations,
|
2019-08-05 04:34:46 +00:00
|
|
|
'default' => $defaultExpiry->text(),
|
2019-01-07 14:04:54 +00:00
|
|
|
'section' => 'expiry',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$a['Reason'] = [
|
|
|
|
|
'type' => 'selectandother',
|
|
|
|
|
// HTML maxlength uses "UTF-16 code units", which means that characters outside BMP
|
|
|
|
|
// (e.g. emojis) count for two each. This limit is overridden in JS to instead count
|
2019-01-04 18:55:11 +00:00
|
|
|
// Unicode codepoints.
|
|
|
|
|
'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
|
2019-01-07 14:04:54 +00:00
|
|
|
'maxlength-unit' => 'codepoints',
|
|
|
|
|
'options-message' => 'ipbreason-dropdown',
|
|
|
|
|
'section' => 'reason',
|
|
|
|
|
];
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['AutoBlock'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'check',
|
2021-09-09 15:57:27 +00:00
|
|
|
'label-message' => [
|
|
|
|
|
'ipbenableautoblock',
|
2022-04-26 15:48:03 +00:00
|
|
|
Message::durationParam( $conf->get( MainConfigNames::AutoblockExpiry ) )
|
2021-09-09 15:57:27 +00:00
|
|
|
],
|
2011-03-12 22:53:15 +00:00
|
|
|
'default' => true,
|
2019-01-07 14:04:54 +00:00
|
|
|
'section' => 'options',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
# Allow some users to hide name from block log, blocklist and listusers
|
2021-03-02 23:59:56 +00:00
|
|
|
if ( $this->getAuthority()->isAllowed( 'hideuser' ) ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['HideUser'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'check',
|
|
|
|
|
'label-message' => 'ipbhidename',
|
|
|
|
|
'cssclass' => 'mw-block-hideuser',
|
2019-01-07 14:04:54 +00:00
|
|
|
'section' => 'options',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Watchlist their user page? (Only if user is logged in)
|
2020-12-17 23:10:11 +00:00
|
|
|
if ( $user->isRegistered() ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['Watch'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'check',
|
|
|
|
|
'label-message' => 'ipbwatchuser',
|
2019-01-07 14:04:54 +00:00
|
|
|
'section' => 'options',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['HardBlock'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'check',
|
|
|
|
|
'label-message' => 'ipb-hardblock',
|
|
|
|
|
'default' => false,
|
2019-01-07 14:04:54 +00:00
|
|
|
'section' => 'options',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2011-04-01 23:13:15 +00:00
|
|
|
# This is basically a copy of the Target field, but the user can't change it, so we
|
|
|
|
|
# can see if the warnings we maybe showed to the user before still apply
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['PreviousTarget'] = [
|
2011-03-12 22:53:15 +00:00
|
|
|
'type' => 'hidden',
|
|
|
|
|
'default' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2011-04-01 23:13:15 +00:00
|
|
|
# We'll turn this into a checkbox if we need to
|
2016-02-17 09:09:32 +00:00
|
|
|
$a['Confirm'] = [
|
2011-04-01 23:13:15 +00:00
|
|
|
'type' => 'hidden',
|
|
|
|
|
'default' => '',
|
|
|
|
|
'label-message' => 'ipb-confirm',
|
2017-10-03 13:44:30 +00:00
|
|
|
'cssclass' => 'mw-block-confirm',
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2011-04-01 23:13:15 +00:00
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
$this->maybeAlterFormDefaults( $a );
|
|
|
|
|
|
2013-12-12 20:18:05 +00:00
|
|
|
// Allow extensions to add more fields
|
Hooks::run() call site migration
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
2020-03-19 02:42:09 +00:00
|
|
|
$this->getHookRunner()->onSpecialBlockModifyFormFields( $this, $a );
|
2013-12-12 20:18:05 +00:00
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
return $a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If the user has already been blocked with similar settings, load that block
|
|
|
|
|
* and change the defaults for the form fields to match the existing settings.
|
2017-08-11 00:23:16 +00:00
|
|
|
* @param array &$fields HTMLForm descriptor array
|
2011-03-12 22:53:15 +00:00
|
|
|
*/
|
2012-08-29 02:34:00 +00:00
|
|
|
protected function maybeAlterFormDefaults( &$fields ) {
|
2011-04-01 23:13:15 +00:00
|
|
|
# This will be overwritten by request data
|
2011-03-13 14:41:57 +00:00
|
|
|
$fields['Target']['default'] = (string)$this->target;
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2014-05-30 09:14:54 +00:00
|
|
|
if ( $this->target ) {
|
2020-10-05 16:08:10 +00:00
|
|
|
$status = $this->blockUtils->validateTarget( $this->target );
|
2014-05-30 09:14:54 +00:00
|
|
|
if ( !$status->isOK() ) {
|
|
|
|
|
$errors = $status->getErrorsArray();
|
|
|
|
|
$this->preErrors = array_merge( $this->preErrors, $errors );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-01 23:13:15 +00:00
|
|
|
# This won't be
|
|
|
|
|
$fields['PreviousTarget']['default'] = (string)$this->target;
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = DatabaseBlock::newFromTarget( $this->target );
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2019-03-22 15:16:40 +00:00
|
|
|
// Populate fields if there is a block that is not an autoblock; if it is a range
|
|
|
|
|
// block, only populate the fields if the range is the same as $this->target
|
2019-05-13 14:18:07 +00:00
|
|
|
if ( $block instanceof DatabaseBlock && $block->getType() !== DatabaseBlock::TYPE_AUTO
|
|
|
|
|
&& ( $this->type != DatabaseBlock::TYPE_RANGE
|
2021-04-16 12:55:24 +00:00
|
|
|
|| ( $this->target && $block->isBlocking( $this->target ) ) )
|
2013-03-25 22:52:41 +00:00
|
|
|
) {
|
2011-03-19 23:47:08 +00:00
|
|
|
$fields['HardBlock']['default'] = $block->isHardblock();
|
Separate out different functionalities of Block::prevents
Block::prevents plays several different roles:
* acts as get/setter for Boolean properties that correspond to
ipb_create_account, ipb_block_email and ipb_allow_usertalk
* calculates whether a block blocks a given right, based on Block
properties, global configs, white/blacklists and anonymous user
rights
* decides whether a block prevents editing of the target's own
user talk page (listed separately because 'editownusertalk' is
not a right)
This patch:
* renames mDisableUsertalk to allowEditUsertalk (and reverses the
value), to match the field ipb_allow_usertalk and make this logic
easier to follow
* renames mCreateAccount to blockCreateAccount, to make it clear
that the flag blocks account creation when true, and make this
logic easier to follow
* decouples the block that is stored in the database (which now
reflects the form that the admin submitted) and the behaviour of
the block on enforcement (since the properties set by the admin
can be overridden by global configs) - so if the global configs
change, the block behaviour could too
* creates get/setters for blockCreateAccount, mBlockEmail and
allowEditUsertalk properties
* creates appliesToRight, exclusively for checking whether the
block blocks a given right, taking into account the block
properties, global configs and anonymous user rights
* creates appliesToUsertalk, for checking whether the block
blocks a user from editing their own talk page. The block is
unaware of the user trying to make the edit, and this user is not
always the same as the block target, e.g. if the block target is
an IP range. Therefore the user's talk page is passed in to this
method. appliesToUsertalk can be called from anywhere where the
user is known
* uses the get/setters wherever Block::prevents was being used as
such
* uses appliesToRight whenever Block::prevents was being used to
determine if the block blocks a given right
* uses appliesToUsertalk in User::isBlockedFrom
Bug: T211578
Bug: T214508
Change-Id: I0e131696419211319082cb454f4f05297e55d22e
2019-02-09 12:17:54 +00:00
|
|
|
$fields['CreateAccount']['default'] = $block->isCreateAccountBlocked();
|
2011-03-21 19:12:41 +00:00
|
|
|
$fields['AutoBlock']['default'] = $block->isAutoblocking();
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( isset( $fields['DisableEmail'] ) ) {
|
Separate out different functionalities of Block::prevents
Block::prevents plays several different roles:
* acts as get/setter for Boolean properties that correspond to
ipb_create_account, ipb_block_email and ipb_allow_usertalk
* calculates whether a block blocks a given right, based on Block
properties, global configs, white/blacklists and anonymous user
rights
* decides whether a block prevents editing of the target's own
user talk page (listed separately because 'editownusertalk' is
not a right)
This patch:
* renames mDisableUsertalk to allowEditUsertalk (and reverses the
value), to match the field ipb_allow_usertalk and make this logic
easier to follow
* renames mCreateAccount to blockCreateAccount, to make it clear
that the flag blocks account creation when true, and make this
logic easier to follow
* decouples the block that is stored in the database (which now
reflects the form that the admin submitted) and the behaviour of
the block on enforcement (since the properties set by the admin
can be overridden by global configs) - so if the global configs
change, the block behaviour could too
* creates get/setters for blockCreateAccount, mBlockEmail and
allowEditUsertalk properties
* creates appliesToRight, exclusively for checking whether the
block blocks a given right, taking into account the block
properties, global configs and anonymous user rights
* creates appliesToUsertalk, for checking whether the block
blocks a user from editing their own talk page. The block is
unaware of the user trying to make the edit, and this user is not
always the same as the block target, e.g. if the block target is
an IP range. Therefore the user's talk page is passed in to this
method. appliesToUsertalk can be called from anywhere where the
user is known
* uses the get/setters wherever Block::prevents was being used as
such
* uses appliesToRight whenever Block::prevents was being used to
determine if the block blocks a given right
* uses appliesToUsertalk in User::isBlockedFrom
Bug: T211578
Bug: T214508
Change-Id: I0e131696419211319082cb454f4f05297e55d22e
2019-02-09 12:17:54 +00:00
|
|
|
$fields['DisableEmail']['default'] = $block->isEmailBlocked();
|
2011-03-15 11:20:15 +00:00
|
|
|
}
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( isset( $fields['HideUser'] ) ) {
|
2019-03-22 15:16:40 +00:00
|
|
|
$fields['HideUser']['default'] = $block->getHideName();
|
2011-03-15 11:20:15 +00:00
|
|
|
}
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( isset( $fields['DisableUTEdit'] ) ) {
|
Separate out different functionalities of Block::prevents
Block::prevents plays several different roles:
* acts as get/setter for Boolean properties that correspond to
ipb_create_account, ipb_block_email and ipb_allow_usertalk
* calculates whether a block blocks a given right, based on Block
properties, global configs, white/blacklists and anonymous user
rights
* decides whether a block prevents editing of the target's own
user talk page (listed separately because 'editownusertalk' is
not a right)
This patch:
* renames mDisableUsertalk to allowEditUsertalk (and reverses the
value), to match the field ipb_allow_usertalk and make this logic
easier to follow
* renames mCreateAccount to blockCreateAccount, to make it clear
that the flag blocks account creation when true, and make this
logic easier to follow
* decouples the block that is stored in the database (which now
reflects the form that the admin submitted) and the behaviour of
the block on enforcement (since the properties set by the admin
can be overridden by global configs) - so if the global configs
change, the block behaviour could too
* creates get/setters for blockCreateAccount, mBlockEmail and
allowEditUsertalk properties
* creates appliesToRight, exclusively for checking whether the
block blocks a given right, taking into account the block
properties, global configs and anonymous user rights
* creates appliesToUsertalk, for checking whether the block
blocks a user from editing their own talk page. The block is
unaware of the user trying to make the edit, and this user is not
always the same as the block target, e.g. if the block target is
an IP range. Therefore the user's talk page is passed in to this
method. appliesToUsertalk can be called from anywhere where the
user is known
* uses the get/setters wherever Block::prevents was being used as
such
* uses appliesToRight whenever Block::prevents was being used to
determine if the block blocks a given right
* uses appliesToUsertalk in User::isBlockedFrom
Bug: T211578
Bug: T214508
Change-Id: I0e131696419211319082cb454f4f05297e55d22e
2019-02-09 12:17:54 +00:00
|
|
|
$fields['DisableUTEdit']['default'] = !$block->isUsertalkEditAllowed();
|
2011-03-15 11:20:15 +00:00
|
|
|
}
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2012-08-08 17:04:10 +00:00
|
|
|
// If the username was hidden (ipb_deleted == 1), don't show the reason
|
2017-02-20 22:31:04 +00:00
|
|
|
// unless this user also has rights to hideuser: T37839
|
2021-03-02 23:59:56 +00:00
|
|
|
if ( !$block->getHideName() || $this->getAuthority()->isAllowed( 'hideuser' ) ) {
|
2019-10-20 00:04:00 +00:00
|
|
|
$fields['Reason']['default'] = $block->getReasonComment()->text;
|
2012-08-08 17:04:10 +00:00
|
|
|
} else {
|
|
|
|
|
$fields['Reason']['default'] = '';
|
|
|
|
|
}
|
2011-04-01 23:13:15 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( $this->getRequest()->wasPosted() ) {
|
2011-04-01 23:13:15 +00:00
|
|
|
# Ok, so we got a POST submission asking us to reblock a user. So show the
|
|
|
|
|
# confirm checkbox; the user will only see it if they haven't previously
|
|
|
|
|
$fields['Confirm']['type'] = 'check';
|
|
|
|
|
} else {
|
|
|
|
|
# We got a target, but it wasn't a POST request, so the user must have gone
|
|
|
|
|
# to a link like [[Special:Block/User]]. We don't need to show the checkbox
|
|
|
|
|
# as long as they go ahead and block *that* user
|
|
|
|
|
$fields['Confirm']['default'] = 1;
|
|
|
|
|
}
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2019-03-22 15:16:40 +00:00
|
|
|
if ( $block->getExpiry() == 'infinity' ) {
|
2012-06-06 19:50:19 +00:00
|
|
|
$fields['Expiry']['default'] = 'infinite';
|
2011-03-12 22:53:15 +00:00
|
|
|
} else {
|
2019-03-22 15:16:40 +00:00
|
|
|
$fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->getExpiry() );
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-17 13:57:26 +00:00
|
|
|
if ( !$block->isSitewide() ) {
|
|
|
|
|
$fields['EditingRestriction']['default'] = 'partial';
|
|
|
|
|
|
|
|
|
|
$pageRestrictions = [];
|
|
|
|
|
$namespaceRestrictions = [];
|
|
|
|
|
foreach ( $block->getRestrictions() as $restriction ) {
|
|
|
|
|
if ( $restriction instanceof PageRestriction && $restriction->getTitle() ) {
|
|
|
|
|
$pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
|
2021-05-07 11:20:58 +00:00
|
|
|
} elseif ( $restriction instanceof NamespaceRestriction &&
|
2021-08-16 16:50:55 +00:00
|
|
|
$this->namespaceInfo->exists( $restriction->getValue() )
|
2021-05-07 11:20:58 +00:00
|
|
|
) {
|
2020-04-17 13:57:26 +00:00
|
|
|
$namespaceRestrictions[] = $restriction->getValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort the restrictions so they are in alphabetical order.
|
|
|
|
|
sort( $pageRestrictions );
|
|
|
|
|
$fields['PageRestrictions']['default'] = implode( "\n", $pageRestrictions );
|
|
|
|
|
sort( $namespaceRestrictions );
|
|
|
|
|
$fields['NamespaceRestrictions']['default'] = implode( "\n", $namespaceRestrictions );
|
|
|
|
|
|
2022-04-13 15:28:26 +00:00
|
|
|
if ( $this->getConfig()->get( MainConfigNames::EnablePartialActionBlocks ) ) {
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
$actionRestrictions = [];
|
|
|
|
|
foreach ( $block->getRestrictions() as $restriction ) {
|
|
|
|
|
if ( $restriction instanceof ActionRestriction ) {
|
|
|
|
|
$actionRestrictions[] = $restriction->getValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$fields['ActionRestrictions']['default'] = $actionRestrictions;
|
|
|
|
|
}
|
2020-04-17 13:57:26 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-01 23:13:15 +00:00
|
|
|
$this->alreadyBlocked = true;
|
2021-04-16 12:55:24 +00:00
|
|
|
$this->preErrors[] = [ 'ipb-needreblock', wfEscapeWikiText( $block->getTargetName() ) ];
|
2011-04-01 23:13:15 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-02 16:33:11 +00:00
|
|
|
if ( $this->alreadyBlocked || $this->getRequest()->wasPosted()
|
|
|
|
|
|| $this->getRequest()->getCheck( 'wpCreateAccount' )
|
|
|
|
|
) {
|
|
|
|
|
$this->getOutput()->addJsConfigVars( 'wgCreateAccountDirty', true );
|
2019-03-12 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-01 23:13:15 +00:00
|
|
|
# We always need confirmation to do HideUser
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( $this->requestedHideUser ) {
|
2011-04-01 23:13:15 +00:00
|
|
|
$fields['Confirm']['type'] = 'check';
|
|
|
|
|
unset( $fields['Confirm']['default'] );
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->preErrors[] = [ 'ipb-confirmhideuser', 'ipb-confirmaction' ];
|
2011-04-01 23:13:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Or if the user is trying to block themselves
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( (string)$this->target === $this->getUser()->getName() ) {
|
2011-04-01 23:13:15 +00:00
|
|
|
$fields['Confirm']['type'] = 'check';
|
|
|
|
|
unset( $fields['Confirm']['default'] );
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->preErrors[] = [ 'ipb-blockingself', 'ipb-confirmaction' ];
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-03-12 22:53:15 +00:00
|
|
|
* Add header elements like block log entries, etc.
|
2014-04-19 08:16:52 +00:00
|
|
|
* @return string
|
2011-03-12 21:54:35 +00:00
|
|
|
*/
|
2022-07-07 18:40:11 +00:00
|
|
|
protected function preHtml() {
|
2019-01-03 19:04:48 +00:00
|
|
|
$this->getOutput()->addModuleStyles( [
|
|
|
|
|
'mediawiki.widgets.TagMultiselectWidget.styles',
|
|
|
|
|
'mediawiki.special',
|
|
|
|
|
] );
|
2015-07-26 23:44:25 +00:00
|
|
|
$this->getOutput()->addModules( [ 'mediawiki.special.block' ] );
|
2012-07-24 20:59:42 +00:00
|
|
|
|
2022-04-13 15:28:26 +00:00
|
|
|
$blockCIDRLimit = $this->getConfig()->get( MainConfigNames::BlockCIDRLimit );
|
2015-12-31 20:24:39 +00:00
|
|
|
$text = $this->msg( 'blockiptext', $blockCIDRLimit['IPv4'], $blockCIDRLimit['IPv6'] )->parse();
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$otherBlockMessages = [];
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( $this->target !== null ) {
|
2016-04-29 17:38:35 +00:00
|
|
|
$targetName = $this->target;
|
2021-07-15 21:57:52 +00:00
|
|
|
if ( $this->target instanceof UserIdentity ) {
|
2016-04-29 17:38:35 +00:00
|
|
|
$targetName = $this->target->getName();
|
|
|
|
|
}
|
2011-03-12 22:53:15 +00:00
|
|
|
# Get other blocks, i.e. from GlobalBlocking or TorBlock extension
|
Hooks::run() call site migration
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
2020-03-19 02:42:09 +00:00
|
|
|
$this->getHookRunner()->onOtherBlockLogLink(
|
|
|
|
|
$otherBlockMessages, $targetName );
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( count( $otherBlockMessages ) ) {
|
2011-03-12 22:53:15 +00:00
|
|
|
$s = Html::rawElement(
|
|
|
|
|
'h2',
|
2016-02-17 09:09:32 +00:00
|
|
|
[],
|
2011-12-28 19:15:10 +00:00
|
|
|
$this->msg( 'ipb-otherblocks-header', count( $otherBlockMessages ) )->parse()
|
2011-03-12 22:53:15 +00:00
|
|
|
) . "\n";
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
$list = '';
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
foreach ( $otherBlockMessages as $link ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$list .= Html::rawElement( 'li', [], $link ) . "\n";
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
$s .= Html::rawElement(
|
|
|
|
|
'ul',
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'class' => 'mw-blockip-alreadyblocked' ],
|
2011-03-12 22:53:15 +00:00
|
|
|
$list
|
|
|
|
|
) . "\n";
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
$text .= $s;
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
return $text;
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2011-03-12 21:54:35 +00:00
|
|
|
/**
|
2011-03-12 22:53:15 +00:00
|
|
|
* Add footer elements to the form
|
2012-01-03 15:36:46 +00:00
|
|
|
* @return string
|
2011-03-12 21:54:35 +00:00
|
|
|
*/
|
2022-07-07 18:40:11 +00:00
|
|
|
protected function postHtml() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$links = [];
|
2012-06-26 09:09:53 +00:00
|
|
|
|
2015-10-10 06:41:43 +00:00
|
|
|
$this->getOutput()->addModuleStyles( 'mediawiki.special' );
|
|
|
|
|
|
2016-11-30 00:05:22 +00:00
|
|
|
$linkRenderer = $this->getLinkRenderer();
|
2011-03-12 22:53:15 +00:00
|
|
|
# Link to the user's contributions, if applicable
|
2021-07-15 21:57:52 +00:00
|
|
|
if ( $this->target instanceof UserIdentity ) {
|
2011-03-12 22:53:15 +00:00
|
|
|
$contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() );
|
2016-11-30 00:05:22 +00:00
|
|
|
$links[] = $linkRenderer->makeLink(
|
2011-03-12 22:53:15 +00:00
|
|
|
$contribsPage,
|
2016-11-30 00:05:22 +00:00
|
|
|
$this->msg( 'ipb-blocklist-contribs', $this->target->getName() )->text()
|
2011-03-12 22:53:15 +00:00
|
|
|
);
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
2011-03-12 22:53:15 +00:00
|
|
|
|
|
|
|
|
# Link to unblock the specified user, or to a blank unblock form
|
2021-07-15 21:57:52 +00:00
|
|
|
if ( $this->target instanceof UserIdentity ) {
|
2014-05-09 19:33:58 +00:00
|
|
|
$message = $this->msg(
|
|
|
|
|
'ipb-unblock-addr',
|
|
|
|
|
wfEscapeWikiText( $this->target->getName() )
|
|
|
|
|
)->parse();
|
2011-03-13 21:33:52 +00:00
|
|
|
$list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() );
|
2011-03-12 21:54:35 +00:00
|
|
|
} else {
|
2011-12-28 19:15:10 +00:00
|
|
|
$message = $this->msg( 'ipb-unblock' )->parse();
|
2011-03-13 21:33:52 +00:00
|
|
|
$list = SpecialPage::getTitleFor( 'Unblock' );
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2016-11-30 00:05:22 +00:00
|
|
|
$links[] = $linkRenderer->makeKnownLink(
|
|
|
|
|
$list,
|
|
|
|
|
new HtmlArmor( $message )
|
|
|
|
|
);
|
2011-03-12 22:53:15 +00:00
|
|
|
|
|
|
|
|
# Link to the block list
|
2016-11-30 00:05:22 +00:00
|
|
|
$links[] = $linkRenderer->makeKnownLink(
|
2011-03-14 16:09:44 +00:00
|
|
|
SpecialPage::getTitleFor( 'BlockList' ),
|
2016-11-30 00:05:22 +00:00
|
|
|
$this->msg( 'ipb-blocklist' )->text()
|
2011-03-12 22:53:15 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
# Link to edit the block dropdown reasons, if applicable
|
2021-03-02 23:59:56 +00:00
|
|
|
if ( $this->getAuthority()->isAllowed( 'editinterface' ) ) {
|
2016-11-30 00:05:22 +00:00
|
|
|
$links[] = $linkRenderer->makeKnownLink(
|
2014-12-13 19:55:13 +00:00
|
|
|
$this->msg( 'ipbreason-dropdown' )->inContentLanguage()->getTitle(),
|
2016-11-30 00:05:22 +00:00
|
|
|
$this->msg( 'ipb-edit-dropdown' )->text(),
|
2016-02-17 09:09:32 +00:00
|
|
|
[],
|
|
|
|
|
[ 'action' => 'edit' ]
|
2011-03-12 22:53:15 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-28 21:11:10 +00:00
|
|
|
$text = Html::rawElement(
|
2011-03-12 22:53:15 +00:00
|
|
|
'p',
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'class' => 'mw-ipb-conveniencelinks' ],
|
2011-11-21 16:13:21 +00:00
|
|
|
$this->getLanguage()->pipeList( $links )
|
2011-11-15 02:25:36 +00:00
|
|
|
);
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2021-05-30 16:18:26 +00:00
|
|
|
$userPage = self::getTargetUserTitle( $this->target );
|
|
|
|
|
if ( $userPage ) {
|
2011-03-12 22:53:15 +00:00
|
|
|
# Get relevant extracts from the block and suppression logs, if possible
|
|
|
|
|
$out = '';
|
|
|
|
|
|
|
|
|
|
LogEventsList::showLogExtract(
|
|
|
|
|
$out,
|
|
|
|
|
'block',
|
2021-05-30 16:18:26 +00:00
|
|
|
$userPage,
|
2011-03-12 22:53:15 +00:00
|
|
|
'',
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2011-03-12 22:53:15 +00:00
|
|
|
'lim' => 10,
|
2021-05-30 16:18:26 +00:00
|
|
|
'msgKey' => [
|
|
|
|
|
'blocklog-showlog',
|
|
|
|
|
$this->titleFormatter->getText( $userPage ),
|
|
|
|
|
],
|
2011-03-12 22:53:15 +00:00
|
|
|
'showIfEmpty' => false
|
2016-02-17 09:09:32 +00:00
|
|
|
]
|
2011-03-12 22:53:15 +00:00
|
|
|
);
|
2011-11-15 02:25:36 +00:00
|
|
|
$text .= $out;
|
2011-03-12 22:53:15 +00:00
|
|
|
|
|
|
|
|
# Add suppression block entries if allowed
|
2021-03-02 23:59:56 +00:00
|
|
|
if ( $this->getAuthority()->isAllowed( 'suppressionlog' ) ) {
|
2011-03-12 22:53:15 +00:00
|
|
|
LogEventsList::showLogExtract(
|
|
|
|
|
$out,
|
|
|
|
|
'suppress',
|
2021-05-30 16:18:26 +00:00
|
|
|
$userPage,
|
2011-03-12 22:53:15 +00:00
|
|
|
'',
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2011-03-12 22:53:15 +00:00
|
|
|
'lim' => 10,
|
2016-02-17 09:09:32 +00:00
|
|
|
'conds' => [ 'log_action' => [ 'block', 'reblock', 'unblock' ] ],
|
2021-05-30 16:18:26 +00:00
|
|
|
'msgKey' => [
|
|
|
|
|
'blocklog-showsuppresslog',
|
|
|
|
|
$this->titleFormatter->getText( $userPage ),
|
|
|
|
|
],
|
2011-03-12 22:53:15 +00:00
|
|
|
'showIfEmpty' => false
|
2016-02-17 09:09:32 +00:00
|
|
|
]
|
2011-03-12 22:53:15 +00:00
|
|
|
);
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
$text .= $out;
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
2011-11-15 02:25:36 +00:00
|
|
|
|
|
|
|
|
return $text;
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-14 01:42:14 +00:00
|
|
|
/**
|
|
|
|
|
* Get a user page target for things like logs.
|
|
|
|
|
* This handles account and IP range targets.
|
2022-08-02 15:26:58 +00:00
|
|
|
* @param UserIdentity|string|null $target
|
2021-05-30 16:18:26 +00:00
|
|
|
* @return PageReference|null
|
2012-03-14 01:42:14 +00:00
|
|
|
*/
|
2021-05-30 16:18:26 +00:00
|
|
|
protected static function getTargetUserTitle( $target ): ?PageReference {
|
|
|
|
|
if ( $target instanceof UserIdentity ) {
|
|
|
|
|
return PageReferenceValue::localReference( NS_USER, $target->getName() );
|
2022-08-02 15:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( is_string( $target ) && IPUtils::isIPAddress( $target ) ) {
|
2021-05-30 16:18:26 +00:00
|
|
|
return PageReferenceValue::localReference( NS_USER, $target );
|
2012-03-14 01:42:14 +00:00
|
|
|
}
|
2022-08-02 15:26:58 +00:00
|
|
|
|
2012-03-14 01:42:14 +00:00
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-12 21:54:35 +00:00
|
|
|
/**
|
2020-04-22 19:45:13 +00:00
|
|
|
* Get the target and type, given the request and the subpage parameter.
|
|
|
|
|
* Several parameters are handled for backwards compatability. 'wpTarget' is
|
|
|
|
|
* prioritized, since it matches the HTML form.
|
|
|
|
|
*
|
2020-10-05 16:08:10 +00:00
|
|
|
* @deprecated since 1.36. Use BlockUtils::parseBlockTarget directly instead.
|
2020-04-23 07:49:22 +00:00
|
|
|
*
|
2020-09-23 14:00:34 +00:00
|
|
|
* @param string|null $par Subpage parameter passed to setup, or data value from
|
2020-04-22 19:45:13 +00:00
|
|
|
* the HTMLForm
|
2018-06-26 21:14:43 +00:00
|
|
|
* @param WebRequest|null $request Optionally try and get data from a request too
|
2021-07-15 21:57:52 +00:00
|
|
|
* @return array [ UserIdentity|string|null, DatabaseBlock::TYPE_ constant|null ]
|
|
|
|
|
* @phan-return array{0:UserIdentity|string|null,1:int|null}
|
2011-03-12 21:54:35 +00:00
|
|
|
*/
|
2020-09-23 14:00:34 +00:00
|
|
|
public static function getTargetAndType( ?string $par, WebRequest $request = null ) {
|
2020-04-22 19:45:13 +00:00
|
|
|
if ( !$request instanceof WebRequest ) {
|
2021-03-17 17:48:43 +00:00
|
|
|
return MediaWikiServices::getInstance()->getBlockUtils()->parseBlockTarget( $par );
|
2020-04-22 19:45:13 +00:00
|
|
|
}
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2020-04-22 19:45:13 +00:00
|
|
|
$possibleTargets = [
|
|
|
|
|
$request->getVal( 'wpTarget', null ),
|
|
|
|
|
$par,
|
|
|
|
|
$request->getVal( 'ip', null ),
|
|
|
|
|
// B/C @since 1.18
|
|
|
|
|
$request->getVal( 'wpBlockAddress', null ),
|
|
|
|
|
];
|
|
|
|
|
foreach ( $possibleTargets as $possibleTarget ) {
|
2021-03-17 17:48:43 +00:00
|
|
|
$targetAndType = MediaWikiServices::getInstance()
|
|
|
|
|
->getBlockUtils()
|
|
|
|
|
->parseBlockTarget( $possibleTarget );
|
2020-04-22 19:45:13 +00:00
|
|
|
// If type is not null then target is valid
|
|
|
|
|
if ( $targetAndType[ 1 ] !== null ) {
|
|
|
|
|
break;
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
2020-04-22 19:45:13 +00:00
|
|
|
return $targetAndType;
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2011-11-13 07:25:56 +00:00
|
|
|
/**
|
2020-04-23 19:33:56 +00:00
|
|
|
* Given the form data, actually implement a block.
|
2015-07-27 14:23:24 +00:00
|
|
|
*
|
2020-04-23 19:33:56 +00:00
|
|
|
* @deprecated since 1.36, use BlockUserFactory service instead
|
2014-04-19 08:16:52 +00:00
|
|
|
* @param array $data
|
|
|
|
|
* @param IContextSource $context
|
2021-08-26 21:49:26 +00:00
|
|
|
* @return bool|string|array|Status
|
2011-03-13 09:57:02 +00:00
|
|
|
*/
|
2012-08-29 02:34:00 +00:00
|
|
|
public static function processForm( array $data, IContextSource $context ) {
|
2020-10-05 16:08:10 +00:00
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
|
return self::processFormInternal(
|
|
|
|
|
$data,
|
2021-03-16 01:37:57 +00:00
|
|
|
$context->getAuthority(),
|
2020-10-05 16:08:10 +00:00
|
|
|
$services->getBlockUserFactory(),
|
|
|
|
|
$services->getBlockUtils()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Implementation details for processForm
|
|
|
|
|
* Own function to allow sharing the deprecated code with non-deprecated and service code
|
|
|
|
|
*
|
|
|
|
|
* @param array $data
|
2021-03-16 01:37:57 +00:00
|
|
|
* @param Authority $performer
|
2020-10-05 16:08:10 +00:00
|
|
|
* @param BlockUserFactory $blockUserFactory
|
|
|
|
|
* @param BlockUtils $blockUtils
|
2021-08-26 21:49:26 +00:00
|
|
|
* @return bool|string|array|Status
|
2020-10-05 16:08:10 +00:00
|
|
|
*/
|
|
|
|
|
private static function processFormInternal(
|
|
|
|
|
array $data,
|
2021-03-16 01:37:57 +00:00
|
|
|
Authority $performer,
|
2020-10-05 16:08:10 +00:00
|
|
|
BlockUserFactory $blockUserFactory,
|
|
|
|
|
BlockUtils $blockUtils
|
|
|
|
|
) {
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
// Temporarily access service container until the feature flag is removed: T280532
|
|
|
|
|
$enablePartialActionBlocks = MediaWikiServices::getInstance()
|
2022-04-13 15:28:26 +00:00
|
|
|
->getMainConfig()->get( MainConfigNames::EnablePartialActionBlocks );
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
|
2020-03-02 16:18:23 +00:00
|
|
|
$isPartialBlock = isset( $data['EditingRestriction'] ) &&
|
2019-01-14 14:21:50 +00:00
|
|
|
$data['EditingRestriction'] === 'partial';
|
2011-03-13 09:57:02 +00:00
|
|
|
|
2011-04-01 23:13:15 +00:00
|
|
|
# This might have been a hidden field or a checkbox, so interesting data
|
|
|
|
|
# can come from it
|
2016-02-17 09:09:32 +00:00
|
|
|
$data['Confirm'] = !in_array( $data['Confirm'], [ '', '0', null, false ], true );
|
2011-04-01 23:13:15 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
# If the user has done the form 'properly', they won't even have been given the
|
|
|
|
|
# option to suppress-block unless they have the 'hideuser' permission
|
|
|
|
|
if ( !isset( $data['HideUser'] ) ) {
|
|
|
|
|
$data['HideUser'] = false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-14 19:18:38 +00:00
|
|
|
/** @var User $target */
|
2020-10-05 16:08:10 +00:00
|
|
|
list( $target, $type ) = $blockUtils->parseBlockTarget( $data['Target'] );
|
2019-05-13 14:18:07 +00:00
|
|
|
if ( $type == DatabaseBlock::TYPE_USER ) {
|
2011-03-13 14:41:57 +00:00
|
|
|
$user = $target;
|
|
|
|
|
$target = $user->getName();
|
|
|
|
|
$userId = $user->getId();
|
2011-03-30 18:00:11 +00:00
|
|
|
|
|
|
|
|
# Give admins a heads-up before they go and block themselves. Much messier
|
|
|
|
|
# to do this for IPs, but it's pretty unlikely they'd ever get the 'block'
|
2011-12-20 10:15:18 +00:00
|
|
|
# permission anyway, although the code does allow for it.
|
|
|
|
|
# Note: Important to use $target instead of $data['Target']
|
|
|
|
|
# since both $data['PreviousTarget'] and $target are normalized
|
2014-12-12 08:41:27 +00:00
|
|
|
# but $data['target'] gets overridden by (non-normalized) request variable
|
2011-12-20 10:15:18 +00:00
|
|
|
# from previous request.
|
2021-03-16 01:37:57 +00:00
|
|
|
if ( $target === $performer->getUser()->getName() &&
|
2013-03-25 22:52:41 +00:00
|
|
|
( $data['PreviousTarget'] !== $target || !$data['Confirm'] )
|
|
|
|
|
) {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [ 'ipb-blockingself', 'ipb-confirmaction' ];
|
2011-03-30 18:00:11 +00:00
|
|
|
}
|
2020-04-23 19:33:56 +00:00
|
|
|
|
|
|
|
|
if ( $data['HideUser'] && !$data['Confirm'] ) {
|
|
|
|
|
return [ 'ipb-confirmhideuser', 'ipb-confirmaction' ];
|
|
|
|
|
}
|
2019-05-13 14:18:07 +00:00
|
|
|
} elseif ( $type == DatabaseBlock::TYPE_RANGE ) {
|
2016-06-09 21:53:47 +00:00
|
|
|
$user = null;
|
2011-03-13 14:41:57 +00:00
|
|
|
$userId = 0;
|
2019-05-13 14:18:07 +00:00
|
|
|
} elseif ( $type == DatabaseBlock::TYPE_IP ) {
|
2016-06-09 21:53:47 +00:00
|
|
|
$user = null;
|
2011-03-13 14:41:57 +00:00
|
|
|
$target = $target->getName();
|
|
|
|
|
$userId = 0;
|
|
|
|
|
} else {
|
|
|
|
|
# This should have been caught in the form field validation
|
2016-02-17 09:09:32 +00:00
|
|
|
return [ 'badipaddress' ];
|
2011-03-13 14:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-03 19:10:46 +00:00
|
|
|
// Reason, to be passed to the block object. For default values of reason, see
|
|
|
|
|
// HTMLSelectAndOtherField::getDefault
|
2021-06-04 04:12:21 +00:00
|
|
|
$blockReason = $data['Reason'][0] ?? '';
|
2020-03-03 19:10:46 +00:00
|
|
|
|
2018-12-14 21:08:40 +00:00
|
|
|
$pageRestrictions = [];
|
|
|
|
|
$namespaceRestrictions = [];
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
$actionRestrictions = [];
|
2020-09-28 16:23:43 +00:00
|
|
|
if ( $isPartialBlock ) {
|
|
|
|
|
if ( isset( $data['PageRestrictions'] ) && $data['PageRestrictions'] !== '' ) {
|
2020-12-04 07:30:22 +00:00
|
|
|
$titles = explode( "\n", $data['PageRestrictions'] );
|
|
|
|
|
foreach ( $titles as $title ) {
|
|
|
|
|
$pageRestrictions[] = PageRestriction::newFromTitle( $title );
|
|
|
|
|
}
|
2020-09-28 16:23:43 +00:00
|
|
|
}
|
|
|
|
|
if ( isset( $data['NamespaceRestrictions'] ) && $data['NamespaceRestrictions'] !== '' ) {
|
2021-02-10 22:31:02 +00:00
|
|
|
$namespaceRestrictions = array_map( static function ( $id ) {
|
2022-02-26 16:28:48 +00:00
|
|
|
return new NamespaceRestriction( 0, (int)$id );
|
2020-09-28 16:23:43 +00:00
|
|
|
}, explode( "\n", $data['NamespaceRestrictions'] ) );
|
|
|
|
|
}
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
if (
|
|
|
|
|
$enablePartialActionBlocks &&
|
|
|
|
|
isset( $data['ActionRestrictions'] ) &&
|
|
|
|
|
$data['ActionRestrictions'] !== ''
|
|
|
|
|
) {
|
2021-04-29 16:24:12 +00:00
|
|
|
$actionRestrictions = array_map( static function ( $id ) {
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
return new ActionRestriction( 0, $id );
|
|
|
|
|
}, $data['ActionRestrictions'] );
|
|
|
|
|
}
|
2020-03-02 16:18:23 +00:00
|
|
|
}
|
Introduce infrastructure for partial blocks for actions
This adds a new type of block restriction for actions, which extends
AbstractRestriction. Like page and namespace restrictions, action
restrictions are stored in the ipblocks_restrictions table.
Blockable actions are defined in a BlockActionInfo service, with a
method for getting all the blockable actions, getAllBlockActions.
Action blocks are checked for in PermissionManager::checkUserBlock
using DatabaseBlock::appliesToRight. To make this work, this patch
also removes the 'edit' case from AbstractBlock::appliesToRight,
which always returned true. This was incorrect, as blocks do not
always apply to edit, so cases that called appliesToRight('edit')
were fixed before this commit. appliesToRight('edit') now returns
null (i.e. unsure), which is correct because it is not possible to
determine whether a block applies to editing a particular page
without knowing what that page is, and appliesToRight doesn't know
that page.
There are some flags on sitewide blocks that predate partial blocks,
which block particular actions: 'createaccount' and 'sendemail'.
These are still handled in AbstractBlock::appliesToRight, and are
still checked for separately in the peripheral components.
The feature flag $wgEnablePartialActionBlocks must set to true to
enable partial action blocks.
Bug: T279556
Bug: T6995
Change-Id: I17962bb7c4247a12c722e7bc6bcaf8c36efd8600
2021-04-26 23:07:17 +00:00
|
|
|
$restrictions = array_merge( $pageRestrictions, $namespaceRestrictions, $actionRestrictions );
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
if ( !isset( $data['Tags'] ) ) {
|
|
|
|
|
$data['Tags'] = [];
|
|
|
|
|
}
|
2013-06-02 17:36:30 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
$blockOptions = [
|
|
|
|
|
'isCreateAccountBlocked' => $data['CreateAccount'],
|
|
|
|
|
'isHardBlock' => $data['HardBlock'],
|
|
|
|
|
'isAutoblocking' => $data['AutoBlock'],
|
|
|
|
|
'isHideUser' => $data['HideUser'],
|
|
|
|
|
'isPartial' => $isPartialBlock,
|
|
|
|
|
];
|
2013-06-02 17:36:30 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
if ( isset( $data['DisableUTEdit'] ) ) {
|
|
|
|
|
$blockOptions['isUserTalkEditBlocked'] = $data['DisableUTEdit'];
|
|
|
|
|
}
|
|
|
|
|
if ( isset( $data['DisableEmail'] ) ) {
|
|
|
|
|
$blockOptions['isEmailBlocked'] = $data['DisableEmail'];
|
|
|
|
|
}
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2020-10-05 16:08:10 +00:00
|
|
|
$blockUser = $blockUserFactory->newBlockUser(
|
2020-04-23 19:33:56 +00:00
|
|
|
$target,
|
2020-10-05 16:08:10 +00:00
|
|
|
$performer,
|
2020-04-23 19:33:56 +00:00
|
|
|
$data['Expiry'],
|
|
|
|
|
$blockReason,
|
|
|
|
|
$blockOptions,
|
|
|
|
|
$restrictions,
|
|
|
|
|
$data['Tags']
|
|
|
|
|
);
|
2011-03-12 22:53:15 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
# Indicates whether the user is confirming the block and is aware of
|
|
|
|
|
# the conflict (did not change the block target in the meantime)
|
|
|
|
|
$blockNotConfirmed = !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
|
|
|
|
|
&& $data['PreviousTarget'] !== $target );
|
2018-12-18 07:50:05 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
# Special case for API - T34434
|
|
|
|
|
$reblockNotAllowed = ( array_key_exists( 'Reblock', $data ) && !$data['Reblock'] );
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
$doReblock = !$blockNotConfirmed && !$reblockNotAllowed;
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2020-04-23 19:33:56 +00:00
|
|
|
$status = $blockUser->placeBlock( $doReblock );
|
|
|
|
|
if ( !$status->isOK() ) {
|
|
|
|
|
return $status;
|
2011-03-12 22:53:15 +00:00
|
|
|
}
|
2011-03-12 21:54:35 +00:00
|
|
|
|
2021-08-05 02:01:15 +00:00
|
|
|
if (
|
|
|
|
|
// Can't watch a rangeblock
|
|
|
|
|
$type != DatabaseBlock::TYPE_RANGE
|
|
|
|
|
|
|
|
|
|
// Technically a wiki can be configured to allow anonymous users to place blocks,
|
|
|
|
|
// in which case the 'Watch' field isn't included in the form shown, and we should
|
|
|
|
|
// not try to access it.
|
|
|
|
|
&& array_key_exists( 'Watch', $data )
|
|
|
|
|
&& $data['Watch']
|
|
|
|
|
) {
|
2021-04-13 01:47:07 +00:00
|
|
|
MediaWikiServices::getInstance()->getWatchlistManager()->addWatchIgnoringRights(
|
|
|
|
|
$performer->getUser(),
|
|
|
|
|
Title::makeTitle( NS_USER, $target )
|
2014-05-09 19:33:58 +00:00
|
|
|
);
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
return true;
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-03-12 22:53:15 +00:00
|
|
|
* Get an array of suggested block durations from MediaWiki:Ipboptions
|
2011-05-17 22:03:20 +00:00
|
|
|
* @todo FIXME: This uses a rather odd syntax for the options, should it be converted
|
2011-03-12 22:53:15 +00:00
|
|
|
* to the standard "**<duration>|<displayname>" format?
|
2014-04-19 08:16:52 +00:00
|
|
|
* @param Language|null $lang The language to get the durations in, or null to use
|
2011-07-26 19:04:48 +00:00
|
|
|
* the wiki's content language
|
2018-04-30 01:38:42 +00:00
|
|
|
* @param bool $includeOther Whether to include the 'other' option in the list of
|
|
|
|
|
* suggestions
|
2020-03-24 08:59:02 +00:00
|
|
|
* @return string[]
|
2011-03-12 21:54:35 +00:00
|
|
|
*/
|
2017-10-04 19:02:29 +00:00
|
|
|
public static function getSuggestedDurations( Language $lang = null, $includeOther = true ) {
|
2011-03-18 16:35:22 +00:00
|
|
|
$msg = $lang === null
|
2011-03-21 19:12:41 +00:00
|
|
|
? wfMessage( 'ipboptions' )->inContentLanguage()->text()
|
|
|
|
|
: wfMessage( 'ipboptions' )->inLanguage( $lang )->text();
|
2011-03-18 16:35:22 +00:00
|
|
|
|
2012-08-29 02:34:00 +00:00
|
|
|
if ( $msg == '-' ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [];
|
2011-03-18 16:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-13 03:37:14 +00:00
|
|
|
$a = XmlSelect::parseOptionsMessage( $msg );
|
2011-09-01 13:59:38 +00:00
|
|
|
|
2018-04-30 01:38:42 +00:00
|
|
|
if ( $a && $includeOther ) {
|
2022-01-09 17:58:53 +00:00
|
|
|
// if options exist, add other to the end instead of the beginning (which
|
2018-03-22 05:15:16 +00:00
|
|
|
// is what happens by default).
|
|
|
|
|
$a[ wfMessage( 'ipbother' )->text() ] = 'other';
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
return $a;
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2011-03-18 16:35:22 +00:00
|
|
|
/**
|
|
|
|
|
* Convert a submitted expiry time, which may be relative ("2 weeks", etc) or absolute
|
|
|
|
|
* ("24 May 2034", etc), into an absolute timestamp we can put into the database.
|
2018-03-22 05:15:16 +00:00
|
|
|
*
|
2020-04-23 19:33:56 +00:00
|
|
|
* @deprecated since 1.36, use BlockUser::parseExpiryInput instead
|
2018-03-22 05:15:16 +00:00
|
|
|
*
|
2014-04-19 08:16:52 +00:00
|
|
|
* @param string $expiry Whatever was typed into the form
|
2018-03-22 05:15:16 +00:00
|
|
|
* @return string|bool Timestamp or 'infinity' or false on error.
|
2011-03-18 16:35:22 +00:00
|
|
|
*/
|
|
|
|
|
public static function parseExpiryInput( $expiry ) {
|
2020-04-23 19:33:56 +00:00
|
|
|
return BlockUser::parseExpiryInput( $expiry );
|
2011-03-18 16:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
/**
|
|
|
|
|
* Can we do an email block?
|
2020-09-18 19:40:19 +00:00
|
|
|
*
|
|
|
|
|
* @deprecated since 1.36, use BlockPermissionChecker service instead
|
2019-08-21 02:01:06 +00:00
|
|
|
* @param UserIdentity $user The sysop wanting to make a block
|
2014-04-19 08:16:52 +00:00
|
|
|
* @return bool
|
2011-03-12 22:53:15 +00:00
|
|
|
*/
|
2019-08-21 02:01:06 +00:00
|
|
|
public static function canBlockEmail( UserIdentity $user ) {
|
2020-09-18 19:40:19 +00:00
|
|
|
return MediaWikiServices::getInstance()
|
|
|
|
|
->getBlockPermissionCheckerFactory()
|
|
|
|
|
->newBlockPermissionChecker( null, User::newFromIdentity( $user ) )
|
|
|
|
|
->checkEmailPermissions();
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2011-03-12 22:53:15 +00:00
|
|
|
/**
|
2020-03-31 10:55:57 +00:00
|
|
|
* T17810: Sitewide blocked admins should not be able to block/unblock
|
|
|
|
|
* others with one exception; they can block the user who blocked them,
|
|
|
|
|
* to reduce advantage of a malicious account blocking all admins (T150826).
|
2018-11-27 18:38:14 +00:00
|
|
|
*
|
2020-03-31 10:55:57 +00:00
|
|
|
* T208965: Partially blocked admins can block and unblock others as normal.
|
2018-11-27 18:38:14 +00:00
|
|
|
*
|
2021-06-02 06:49:01 +00:00
|
|
|
* @deprecated since 1.36, hard deprecated since 1.37, use BlockPermissionChecker instead
|
2021-05-30 16:18:26 +00:00
|
|
|
* @param UserIdentity|string|null $target Target to block or unblock; could be a
|
|
|
|
|
* UserIdentity object, or username/IP address, or null when the target is not
|
|
|
|
|
* known yet (e.g. when displaying Special:Block)
|
2021-03-17 02:58:43 +00:00
|
|
|
* @param Authority $performer User doing the request
|
2014-04-19 08:16:52 +00:00
|
|
|
* @return bool|string True or error message key
|
2011-03-12 22:53:15 +00:00
|
|
|
*/
|
2021-03-17 02:58:43 +00:00
|
|
|
public static function checkUnblockSelf( $target, Authority $performer ) {
|
2021-06-02 06:49:01 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.36' );
|
2020-05-07 18:50:24 +00:00
|
|
|
return MediaWikiServices::getInstance()
|
|
|
|
|
->getBlockPermissionCheckerFactory()
|
|
|
|
|
->newBlockPermissionChecker( $target, $performer )
|
|
|
|
|
->checkBlockPermissions();
|
2011-03-12 21:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-15 02:25:36 +00:00
|
|
|
/**
|
|
|
|
|
* Process the form on POST submission.
|
2014-04-19 08:16:52 +00:00
|
|
|
* @param array $data
|
2018-06-26 21:14:43 +00:00
|
|
|
* @param HTMLForm|null $form
|
2021-08-26 21:49:26 +00:00
|
|
|
* @return bool|string|array|Status As documented for HTMLForm::trySubmit.
|
2011-11-15 02:25:36 +00:00
|
|
|
*/
|
2015-07-27 14:23:24 +00:00
|
|
|
public function onSubmit( array $data, HTMLForm $form = null ) {
|
2020-10-05 16:08:10 +00:00
|
|
|
return self::processFormInternal(
|
|
|
|
|
$data,
|
2021-03-16 01:37:57 +00:00
|
|
|
$this->getAuthority(),
|
2020-10-05 16:08:10 +00:00
|
|
|
$this->blockUserFactory,
|
|
|
|
|
$this->blockUtils
|
|
|
|
|
);
|
2011-11-15 02:25:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Do something exciting on successful processing of the form, most likely to show a
|
|
|
|
|
* confirmation message
|
|
|
|
|
*/
|
|
|
|
|
public function onSuccess() {
|
|
|
|
|
$out = $this->getOutput();
|
|
|
|
|
$out->setPageTitle( $this->msg( 'blockipsuccesssub' ) );
|
2012-04-21 13:12:08 +00:00
|
|
|
$out->addWikiMsg( 'blockipsuccesstext', wfEscapeWikiText( $this->target ) );
|
2011-11-15 02:25:36 +00:00
|
|
|
}
|
2013-03-07 20:15:54 +00:00
|
|
|
|
2015-12-03 20:08:31 +00:00
|
|
|
/**
|
|
|
|
|
* Return an array of subpages beginning with $search that this special page will accept.
|
|
|
|
|
*
|
|
|
|
|
* @param string $search Prefix to search for
|
|
|
|
|
* @param int $limit Maximum number of results to return (usually 10)
|
|
|
|
|
* @param int $offset Number of results to skip (usually 0)
|
|
|
|
|
* @return string[] Matching subpages
|
|
|
|
|
*/
|
|
|
|
|
public function prefixSearchSubpages( $search, $limit, $offset ) {
|
2020-10-05 16:08:10 +00:00
|
|
|
$search = $this->userNameUtils->getCanonical( $search );
|
|
|
|
|
if ( !$search ) {
|
2015-12-03 20:08:31 +00:00
|
|
|
// No prefix suggestion for invalid user
|
2016-02-17 09:09:32 +00:00
|
|
|
return [];
|
2015-12-03 20:08:31 +00:00
|
|
|
}
|
|
|
|
|
// Autocomplete subpage as user list - public to allow caching
|
2020-10-05 16:08:10 +00:00
|
|
|
return $this->userNamePrefixSearch
|
|
|
|
|
->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
|
2015-12-03 20:08:31 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-07 20:15:54 +00:00
|
|
|
protected function getGroupName() {
|
|
|
|
|
return 'users';
|
|
|
|
|
}
|
2011-03-12 22:51:48 +00:00
|
|
|
}
|