From b5f384f943fc67c6601d4959dcfb9774766e1156 Mon Sep 17 00:00:00 2001 From: Dayllan Maza Date: Mon, 1 Jul 2019 10:14:42 -0400 Subject: [PATCH] Add support for extentions to change Special:Mute form The hook (SpecialMuteModifyFormFields) is used to append the option to mute/unmute notifications from a specified user. Special:Mute handles posting and saving the fields, the only requirement is that the field name is the same as the property that wants to be modified. Currently there are only two notifications "blacklists": * `email-blacklist` is directly handled in this page 'cause it is part of core. * `echo-notifications-blacklist` is part of Echo, so this change is required to support it. See I77b3ccfdce9b501e Bug: T220163 Change-Id: I2b3eee0802cb086091f35ecce13ae77a8e7d518d --- RELEASE-NOTES-1.34 | 2 + docs/hooks.txt | 4 + includes/specials/SpecialMute.php | 79 +++++++++++-------- languages/i18n/en.json | 5 +- languages/i18n/qqq.json | 3 +- .../includes/specials/SpecialMuteTest.php | 11 ++- 6 files changed, 65 insertions(+), 39 deletions(-) diff --git a/RELEASE-NOTES-1.34 b/RELEASE-NOTES-1.34 index a92b5c206e..99ede17f6c 100644 --- a/RELEASE-NOTES-1.34 +++ b/RELEASE-NOTES-1.34 @@ -77,6 +77,8 @@ For notes on 1.33.x and older releases, see HISTORY. of headers in private wikis. * Language::formatTimePeriod now supports the new 'avoidhours' option to output strings like "5 days ago" instead of "5 days 13 hours ago". +* (T220163) Added SpecialMuteModifyFormFields hook to allow extensions + to add fields to Special:Mute. === External library changes in 1.34 === diff --git a/docs/hooks.txt b/docs/hooks.txt index 36e0891750..756ba4e8d0 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -3200,6 +3200,10 @@ $request: WebRequest object for getting the value provided by the current user &$oldTitle: old title (object) &$newTitle: new title (object) +'SpecialMuteModifyFormFields': Add more fields to Special:Mute +$sp: SpecialPage object, for context +&$fields: Current HTMLForm fields descriptors + 'SpecialNewpagesConditions': Called when building sql query for Special:NewPages. &$special: NewPagesPager object (subclass of ReverseChronologicalPager) diff --git a/includes/specials/SpecialMute.php b/includes/specials/SpecialMute.php index 4f34785115..f3ae31a731 100644 --- a/includes/specials/SpecialMute.php +++ b/includes/specials/SpecialMute.php @@ -28,6 +28,8 @@ use MediaWiki\Preferences\MultiUsernameFilter; */ class SpecialMute extends FormSpecialPage { + const PAGE_NAME = 'Mute'; + /** @var User */ private $target; @@ -51,7 +53,7 @@ class SpecialMute extends FormSpecialPage { $this->centralIdLookup = CentralIdLookup::factory(); - parent::__construct( 'Mute', '', false ); + parent::__construct( self::PAGE_NAME, '', false ); } /** @@ -66,7 +68,7 @@ class SpecialMute extends FormSpecialPage { parent::execute( $par ); $out = $this->getOutput(); - $out->addModules( 'mediawiki.special.pageLanguage' ); + $out->addModules( 'mediawiki.misc-authed-ooui' ); } /** @@ -97,10 +99,12 @@ class SpecialMute extends FormSpecialPage { * @return bool */ public function onSubmit( array $data, HTMLForm $form = null ) { - if ( !empty( $data['MuteEmail'] ) ) { - $this->muteEmailsFromTarget(); - } else { - $this->unmuteEmailsFromTarget(); + foreach ( $data as $userOption => $value ) { + if ( $value ) { + $this->muteTarget( $userOption ); + } else { + $this->unmuteTarget( $userOption ); + } } return true; @@ -114,10 +118,12 @@ class SpecialMute extends FormSpecialPage { } /** - * Un-mute emails from target + * Un-mute target + * + * @param string $userOption up_property key that holds the blacklist */ - private function unmuteEmailsFromTarget() { - $blacklist = $this->getBlacklist(); + private function unmuteTarget( $userOption ) { + $blacklist = $this->getBlacklist( $userOption ); $key = array_search( $this->targetCentralId, $blacklist ); if ( $key !== false ) { @@ -125,24 +131,25 @@ class SpecialMute extends FormSpecialPage { $blacklist = implode( "\n", $blacklist ); $user = $this->getUser(); - $user->setOption( 'email-blacklist', $blacklist ); + $user->setOption( $userOption, $blacklist ); $user->saveSettings(); } } /** - * Mute emails from target + * Mute target + * @param string $userOption up_property key that holds the blacklist */ - private function muteEmailsFromTarget() { + private function muteTarget( $userOption ) { // avoid duplicates just in case - if ( !$this->isTargetBlacklisted() ) { - $blacklist = $this->getBlacklist(); + if ( !$this->isTargetBlacklisted( $userOption ) ) { + $blacklist = $this->getBlacklist( $userOption ); $blacklist[] = $this->targetCentralId; $blacklist = implode( "\n", $blacklist ); $user = $this->getUser(); - $user->setOption( 'email-blacklist', $blacklist ); + $user->setOption( $userOption, $blacklist ); $user->saveSettings(); } } @@ -150,30 +157,38 @@ class SpecialMute extends FormSpecialPage { /** * @inheritDoc */ - protected function alterForm( HTMLForm $form ) { + protected function getForm() { + $form = parent::getForm(); $form->setId( 'mw-specialmute-form' ); $form->setHeaderText( $this->msg( 'specialmute-header', $this->target )->parse() ); $form->setSubmitTextMsg( 'specialmute-submit' ); $form->setSubmitID( 'save' ); + + return $form; } /** * @inheritDoc */ protected function getFormFields() { - if ( !$this->enableUserEmailBlacklist || !$this->enableUserEmail ) { - throw new ErrorPageError( 'specialmute', 'specialmute-error-email-blacklist-disabled' ); + $fields = []; + if ( + $this->enableUserEmailBlacklist && + $this->enableUserEmail && + $this->getUser()->getEmailAuthenticationTimestamp() + ) { + $fields['email-blacklist'] = [ + 'type' => 'check', + 'label-message' => 'specialmute-label-mute-email', + 'default' => $this->isTargetBlacklisted( 'email-blacklist' ), + ]; } - if ( !$this->getUser()->getEmailAuthenticationTimestamp() ) { - throw new ErrorPageError( 'specialmute', 'specialmute-error-email-preferences' ); - } + Hooks::run( 'SpecialMuteModifyFormFields', [ $this, &$fields ] ); - $fields['MuteEmail'] = [ - 'type' => 'check', - 'label-message' => 'specialmute-label-mute-email', - 'default' => $this->isTargetBlacklisted(), - ]; + if ( count( $fields ) == 0 ) { + throw new ErrorPageError( 'specialmute', 'specialmute-error-no-options' ); + } return $fields; } @@ -192,18 +207,20 @@ class SpecialMute extends FormSpecialPage { } /** + * @param string $userOption * @return bool */ - private function isTargetBlacklisted() { - $blacklist = $this->getBlacklist(); - return in_array( $this->targetCentralId, $blacklist ); + public function isTargetBlacklisted( $userOption ) { + $blacklist = $this->getBlacklist( $userOption ); + return in_array( $this->targetCentralId, $blacklist, true ); } /** + * @param string $userOption * @return array */ - private function getBlacklist() { - $blacklist = $this->getUser()->getOption( 'email-blacklist' ); + private function getBlacklist( $userOption ) { + $blacklist = $this->getUser()->getOption( $userOption ); if ( !$blacklist ) { return []; } diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 7e40594e6d..fb265d31a1 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -4202,10 +4202,9 @@ "specialmute-success": "Your mute preferences have been updated. See all muted users in [[Special:Preferences|your preferences]].", "specialmute-submit": "Confirm", "specialmute-label-mute-email": "Mute emails from this user", - "specialmute-header": "Please select your mute preferences for {{BIDI:[[User:$1]]}}.", + "specialmute-header": "Please select your mute preferences for {{BIDI:[[User:$1]]}}.", "specialmute-error-invalid-user": "The username requested could not be found.", - "specialmute-error-email-blacklist-disabled": "Muting users from sending you emails is not enabled.", - "specialmute-error-email-preferences": "You must confirm your email address before you can mute a user. You may do so from [[Special:Preferences]].", + "specialmute-error-no-options": "Mute features are unavailable. This might be because: you haven't confirmed your email address or the wiki administrator has disabled email features and/or email blacklist for this wiki.", "specialmute-email-footer": "To manage email preferences for {{BIDI:$2}} please visit <$1>.", "specialmute-login-required": "Please log in to change your mute preferences.", "mute-preferences": "Mute preferences", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index a58010e089..a348031fed 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -4413,8 +4413,7 @@ "specialmute-label-mute-email": "Label for the checkbox that mutes/unmutes emails from the specified user.", "specialmute-header": "Used as header text on [[Special:Mute]]. Shown before the form with the muting options.\n* $1 - User selected for muting", "specialmute-error-invalid-user": "Error displayed when the username cannot be found.", - "specialmute-error-email-blacklist-disabled": "Error displayed when email blacklist is not enabled.", - "specialmute-error-email-preferences": "Error displayed when the user has not confirmed their email address.", + "specialmute-error-no-options": "Error displayed when there are no options available to mute on [[Special:Mute]].", "specialmute-email-footer": "Email footer in plain text linking to [[Special:Mute]] preselecting the sender to manage muting options.\n* $1 - Url linking to [[Special:Mute]].\n* $2 - The user sending the email.", "specialmute-login-required": "Error displayed when a user tries to access [[Special:Mute]] before logging in.", "mute-preferences": "Link in the sidebar to manage muting preferences for a user. It links to [[Special:Mute]] with the user in context as the subpage.", diff --git a/tests/phpunit/includes/specials/SpecialMuteTest.php b/tests/phpunit/includes/specials/SpecialMuteTest.php index e31357cb33..a57745be53 100644 --- a/tests/phpunit/includes/specials/SpecialMuteTest.php +++ b/tests/phpunit/includes/specials/SpecialMuteTest.php @@ -35,10 +35,15 @@ class SpecialMuteTest extends SpecialPageTestBase { /** * @covers SpecialMute::execute - * @expectedExceptionMessage Muting users from sending you emails is not enabled + * @expectedExceptionMessage Mute features are unavailable * @expectedException ErrorPageError */ public function testEmailBlacklistNotEnabled() { + $this->setTemporaryHook( + 'SpecialMuteModifyFormFields', + null + ); + $this->setMwGlobals( [ 'wgEnableUserEmailBlacklist' => false ] ); @@ -72,7 +77,7 @@ class SpecialMuteTest extends SpecialPageTestBase { $loggedInUser->confirmEmail(); $loggedInUser->saveSettings(); - $fauxRequest = new FauxRequest( [ 'wpMuteEmail' => 1 ], true ); + $fauxRequest = new FauxRequest( [ 'wpemail-blacklist' => true ], true ); list( $html, ) = $this->executeSpecialPage( $targetUser->getName(), $fauxRequest, 'qqx', $loggedInUser ); @@ -99,7 +104,7 @@ class SpecialMuteTest extends SpecialPageTestBase { $loggedInUser->confirmEmail(); $loggedInUser->saveSettings(); - $fauxRequest = new FauxRequest( [ 'wpMuteEmail' => false ], true ); + $fauxRequest = new FauxRequest( [ 'wpemail-blacklist' => false ], true ); list( $html, ) = $this->executeSpecialPage( $targetUser->getName(), $fauxRequest, 'qqx', $loggedInUser ); -- 2.20.1