[JsonCodec] Use wikimedia/json-codec to implement JsonCodec
[mediawiki.git] / includes / specials / SpecialMute.php
blob0e5f17debb5774450c975eccf3e21e4136d3f047
1 <?php
2 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
18 * @file
21 namespace MediaWiki\Specials;
23 use ErrorPageError;
24 use MediaWiki\HTMLForm\HTMLForm;
25 use MediaWiki\MainConfigNames;
26 use MediaWiki\Preferences\MultiUsernameFilter;
27 use MediaWiki\SpecialPage\FormSpecialPage;
28 use MediaWiki\User\CentralId\CentralIdLookup;
29 use MediaWiki\User\Options\UserOptionsManager;
30 use MediaWiki\User\User;
31 use MediaWiki\User\UserIdentity;
32 use MediaWiki\User\UserIdentityLookup;
33 use MediaWiki\User\UserIdentityUtils;
35 /**
36 * Modify your own notification preferences
38 * @ingroup SpecialPage
40 class SpecialMute extends FormSpecialPage {
42 private const PAGE_NAME = 'Mute';
44 /** @var UserIdentity|null */
45 private $target;
47 /** @var int */
48 private $targetCentralId;
50 private CentralIdLookup $centralIdLookup;
51 private UserOptionsManager $userOptionsManager;
52 private UserIdentityLookup $userIdentityLookup;
53 private UserIdentityUtils $userIdentityUtils;
55 /**
56 * @param CentralIdLookup $centralIdLookup
57 * @param UserOptionsManager $userOptionsManager
58 * @param UserIdentityLookup $userIdentityLookup
59 * @param UserIdentityUtils $userIdentityUtils
61 public function __construct(
62 CentralIdLookup $centralIdLookup,
63 UserOptionsManager $userOptionsManager,
64 UserIdentityLookup $userIdentityLookup,
65 UserIdentityUtils $userIdentityUtils
66 ) {
67 parent::__construct( self::PAGE_NAME, '', false );
68 $this->centralIdLookup = $centralIdLookup;
69 $this->userOptionsManager = $userOptionsManager;
70 $this->userIdentityLookup = $userIdentityLookup;
71 $this->userIdentityUtils = $userIdentityUtils;
74 /**
75 * Entry point for special pages
77 * @param string|null $par
79 public function execute( $par ) {
80 $this->addHelpLink(
81 'https://meta.wikimedia.org/wiki/Community_health_initiative/User_Mute_features',
82 true
84 $this->requireNamedUser( 'specialmute-login-required' );
85 $this->loadTarget( $par );
87 parent::execute( $par );
89 $out = $this->getOutput();
90 $out->addModules( 'mediawiki.misc-authed-ooui' );
93 /**
94 * @inheritDoc
96 public function requiresUnblock() {
97 return false;
101 * @inheritDoc
103 protected function getDisplayFormat() {
104 return 'ooui';
108 * @inheritDoc
110 public function onSuccess() {
111 $out = $this->getOutput();
112 $out->addWikiMsg( 'specialmute-success' );
116 * @param array $data
117 * @param HTMLForm|null $form
118 * @return bool
120 public function onSubmit( array $data, HTMLForm $form = null ) {
121 foreach ( $data as $userOption => $value ) {
122 if ( $value ) {
123 $this->muteTarget( $userOption );
124 } else {
125 $this->unmuteTarget( $userOption );
129 return true;
133 * @inheritDoc
135 public function getDescription() {
136 return $this->msg( 'specialmute' );
140 * @return UserIdentity|null
142 private function getTarget(): ?UserIdentity {
143 return $this->target;
147 * Un-mute target
149 * @param string $userOption up_property key that holds the list of muted users
151 private function unmuteTarget( $userOption ) {
152 $muteList = $this->getMuteList( $userOption );
154 $key = array_search( $this->targetCentralId, $muteList );
155 if ( $key !== false ) {
156 unset( $muteList[$key] );
157 $muteList = implode( "\n", $muteList );
159 $user = $this->getUser();
160 $this->userOptionsManager->setOption( $user, $userOption, $muteList );
161 $user->saveSettings();
166 * Mute target
167 * @param string $userOption up_property key that holds the blacklist
169 private function muteTarget( $userOption ) {
170 // avoid duplicates just in case
171 if ( !$this->isTargetMuted( $userOption ) ) {
172 $muteList = $this->getMuteList( $userOption );
174 $muteList[] = $this->targetCentralId;
175 $muteList = implode( "\n", $muteList );
177 $user = $this->getUser();
178 $this->userOptionsManager->setOption( $user, $userOption, $muteList );
179 $user->saveSettings();
184 * @inheritDoc
186 protected function getForm() {
187 $target = $this->getTarget();
188 $form = parent::getForm();
189 $form->setId( 'mw-specialmute-form' );
190 $form->setHeaderHtml( $this->msg( 'specialmute-header', $target ? $target->getName() : '' )->parse() );
191 $form->setSubmitTextMsg( 'specialmute-submit' );
192 $form->setSubmitID( 'save' );
194 return $form;
198 * @inheritDoc
200 protected function getFormFields() {
201 $config = $this->getConfig();
202 $fields = [];
204 if ( !$config->get( MainConfigNames::EnableUserEmail ) ) {
205 throw new ErrorPageError( 'specialmute', 'specialmute-error-email-disabled' );
208 if ( !$config->get( MainConfigNames::EnableUserEmailMuteList ) ) {
209 throw new ErrorPageError( 'specialmute', 'specialmute-error-mutelist-disabled' );
212 if ( !$this->getUser()->isEmailConfirmed() ) {
213 throw new ErrorPageError( 'specialmute', 'specialmute-error-no-email-set' );
216 $target = $this->getTarget();
218 if ( $target && $this->userIdentityUtils->isNamed( $target ) ) {
219 $fields['email-blacklist'] = [
220 'type' => 'check',
221 'label-message' => [
222 'specialmute-label-mute-email',
223 $target->getName()
225 'default' => $this->isTargetMuted( 'email-blacklist' ),
229 $legacyUser = $target ? User::newFromIdentity( $target ) : null;
230 $this->getHookRunner()->onSpecialMuteModifyFormFields( $legacyUser, $this->getUser(), $fields );
232 if ( count( $fields ) == 0 ) {
233 throw new ErrorPageError( 'specialmute', 'specialmute-error-no-options' );
236 return $fields;
240 * @param string|null $username
242 private function loadTarget( $username ) {
243 $target = null;
244 if ( $username !== null ) {
245 $target = $this->userIdentityLookup->getUserIdentityByName( $username );
247 if ( !$target || !$target->isRegistered() ) {
248 throw new ErrorPageError( 'specialmute', 'specialmute-error-invalid-user' );
249 } else {
250 $this->target = $target;
251 $this->targetCentralId = $this->centralIdLookup->centralIdFromLocalUser( $target );
256 * @param string $userOption
257 * @return bool
259 public function isTargetMuted( $userOption ) {
260 $muteList = $this->getMuteList( $userOption );
261 return in_array( $this->targetCentralId, $muteList, true );
265 * @param string $userOption
266 * @return array
268 private function getMuteList( $userOption ) {
269 $muteList = $this->userOptionsManager->getOption( $this->getUser(), $userOption );
270 if ( !$muteList ) {
271 return [];
274 return MultiUsernameFilter::splitIds( $muteList );
279 * Retain the old class name for backwards compatibility.
280 * @deprecated since 1.41
282 class_alias( SpecialMute::class, 'SpecialMute' );