From 10bc76ece73ceccf77869ee6d0d1c54c07467792 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 10 Mar 2021 12:21:51 +0100 Subject: [PATCH] Add `type` to `wcf1_user_ignore` --- .../Core/Ui/User/Profile/Menu/Item/Ignore.ts | 38 ++-- .../database/update_com.woltlab.wcf_5.4.php | 9 + .../Core/Ui/User/Profile/Menu/Item/Ignore.js | 28 +-- .../lib/data/user/ignore/UserIgnore.class.php | 7 + .../user/ignore/UserIgnoreAction.class.php | 163 +++++++++++++++++- wcfsetup/install/lang/de.xml | 5 + wcfsetup/install/lang/en.xml | 5 + wcfsetup/setup/db/install.sql | 1 + 8 files changed, 223 insertions(+), 33 deletions(-) diff --git a/ts/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.ts b/ts/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.ts index debe11bb59..5e89335cf2 100644 --- a/ts/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.ts +++ b/ts/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.ts @@ -1,41 +1,47 @@ import * as Core from "../../../../../Core"; import * as Language from "../../../../../Language"; -import { AjaxCallbackSetup, ResponseData } from "../../../../../Ajax/Data"; import * as UiNotification from "../../../../Notification"; import UiUserProfileMenuItemAbstract from "./Abstract"; +import FormBuilderDialog from "../../../../../Form/Builder/Dialog"; -interface AjaxResponse extends ResponseData { - returnValues: { - isIgnoredUser: 1 | 0; - }; +interface AjaxResponse { + isIgnoredUser: 1 | 0; } class UiUserProfileMenuItemIgnore extends UiUserProfileMenuItemAbstract { + private readonly dialog: FormBuilderDialog; + constructor(userId: number, isActive: boolean) { super(userId, isActive); + + this.dialog = new FormBuilderDialog("ignoreDialog", "wcf\\data\\user\\ignore\\UserIgnoreAction", "getDialog", { + dialog: { + title: Language.get("wcf.user.button.ignore"), + }, + actionParameters: { + userID: this._userId, + }, + submitActionName: "submitDialog", + successCallback: (r: AjaxResponse) => this._ajaxSuccess(r), + destroyOnClose: true, + }); } _getLabel(): string { return Language.get("wcf.user.button." + (this._isActive ? "un" : "") + "ignore"); } - _getAjaxActionName(): string { - return this._isActive ? "unignore" : "ignore"; - } - _ajaxSuccess(data: AjaxResponse): void { - this._isActive = !!data.returnValues.isIgnoredUser; + this._isActive = !!data.isIgnoredUser; this._updateButton(); UiNotification.show(); } - _ajaxSetup(): ReturnType { - return { - data: { - className: "wcf\\data\\user\\ignore\\UserIgnoreAction", - }, - }; + protected _toggle(event: MouseEvent): void { + event.preventDefault(); + + this.dialog.open(); } } diff --git a/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_5.4.php b/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_5.4.php index ed946e355a..dbad31b28e 100644 --- a/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_5.4.php +++ b/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_5.4.php @@ -19,6 +19,7 @@ use wcf\system\database\table\column\NotNullInt10DatabaseTableColumn; use wcf\system\database\table\column\NotNullVarchar255DatabaseTableColumn; use wcf\system\database\table\column\ObjectIdDatabaseTableColumn; use wcf\system\database\table\column\TextDatabaseTableColumn; +use wcf\system\database\table\column\TinyintDatabaseTableColumn; use wcf\system\database\table\column\VarbinaryDatabaseTableColumn; use wcf\system\database\table\column\VarcharDatabaseTableColumn; use wcf\system\database\table\DatabaseTable; @@ -115,6 +116,14 @@ return [ DefaultFalseBooleanDatabaseTableColumn::create('requireMultifactor'), ]), + PartialDatabaseTable::create('wcf1_user_ignore') + ->columns([ + TinyintDatabaseTableColumn::create('type') + ->length(1) + ->notNull() + ->defaultValue(1), + ]), + DatabaseTable::create('wcf1_user_multifactor') ->columns([ ObjectIdDatabaseTableColumn::create('setupID'), diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.js index 63c5cfda39..5854d6efd3 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Profile/Menu/Item/Ignore.js @@ -1,30 +1,36 @@ -define(["require", "exports", "tslib", "../../../../../Core", "../../../../../Language", "../../../../Notification", "./Abstract"], function (require, exports, tslib_1, Core, Language, UiNotification, Abstract_1) { +define(["require", "exports", "tslib", "../../../../../Core", "../../../../../Language", "../../../../Notification", "./Abstract", "../../../../../Form/Builder/Dialog"], function (require, exports, tslib_1, Core, Language, UiNotification, Abstract_1, Dialog_1) { "use strict"; Core = tslib_1.__importStar(Core); Language = tslib_1.__importStar(Language); UiNotification = tslib_1.__importStar(UiNotification); Abstract_1 = tslib_1.__importDefault(Abstract_1); + Dialog_1 = tslib_1.__importDefault(Dialog_1); class UiUserProfileMenuItemIgnore extends Abstract_1.default { constructor(userId, isActive) { super(userId, isActive); + this.dialog = new Dialog_1.default("ignoreDialog", "wcf\\data\\user\\ignore\\UserIgnoreAction", "getDialog", { + dialog: { + title: Language.get("wcf.user.button.ignore"), + }, + actionParameters: { + userID: this._userId, + }, + submitActionName: "submitDialog", + successCallback: (r) => this._ajaxSuccess(r), + destroyOnClose: true, + }); } _getLabel() { return Language.get("wcf.user.button." + (this._isActive ? "un" : "") + "ignore"); } - _getAjaxActionName() { - return this._isActive ? "unignore" : "ignore"; - } _ajaxSuccess(data) { - this._isActive = !!data.returnValues.isIgnoredUser; + this._isActive = !!data.isIgnoredUser; this._updateButton(); UiNotification.show(); } - _ajaxSetup() { - return { - data: { - className: "wcf\\data\\user\\ignore\\UserIgnoreAction", - }, - }; + _toggle(event) { + event.preventDefault(); + this.dialog.open(); } } Core.enableLegacyInheritance(UiUserProfileMenuItemIgnore); diff --git a/wcfsetup/install/files/lib/data/user/ignore/UserIgnore.class.php b/wcfsetup/install/files/lib/data/user/ignore/UserIgnore.class.php index 089b654820..2b5c3bf3a5 100644 --- a/wcfsetup/install/files/lib/data/user/ignore/UserIgnore.class.php +++ b/wcfsetup/install/files/lib/data/user/ignore/UserIgnore.class.php @@ -17,9 +17,16 @@ use wcf\system\WCF; * @property-read int $userID id of the ignoring user * @property-read int $ignoreUserID id of the ignored user * @property-read int $time time at which ignore relation has been established + * @property-read int $type one of the TYPE_* class constants */ class UserIgnore extends DatabaseObject { + public const TYPE_NO_IGNORE = 0; + + public const TYPE_BLOCK_DIRECT_CONTACT = 1; + + public const TYPE_HIDE_MESSAGES = 2; + /** * Returns a UserIgnore object for given ignored user id. * diff --git a/wcfsetup/install/files/lib/data/user/ignore/UserIgnoreAction.class.php b/wcfsetup/install/files/lib/data/user/ignore/UserIgnoreAction.class.php index e98d4bcce6..32fe88f96c 100644 --- a/wcfsetup/install/files/lib/data/user/ignore/UserIgnoreAction.class.php +++ b/wcfsetup/install/files/lib/data/user/ignore/UserIgnoreAction.class.php @@ -5,10 +5,17 @@ namespace wcf\data\user\ignore; use wcf\data\AbstractDatabaseObjectAction; use wcf\data\user\follow\UserFollow; use wcf\data\user\follow\UserFollowEditor; +use wcf\data\user\User; use wcf\system\cache\runtime\UserProfileRuntimeCache; use wcf\system\exception\IllegalLinkException; use wcf\system\exception\PermissionDeniedException; use wcf\system\exception\UserInputException; +use wcf\system\form\builder\data\processor\CustomFormDataProcessor; +use wcf\system\form\builder\DialogFormDocument; +use wcf\system\form\builder\field\RadioButtonFormField; +use wcf\system\form\builder\field\validation\FormFieldValidationError; +use wcf\system\form\builder\field\validation\FormFieldValidator; +use wcf\system\form\builder\IFormDocument; use wcf\system\user\storage\UserStorageHandler; use wcf\system\WCF; @@ -26,6 +33,8 @@ use wcf\system\WCF; */ class UserIgnoreAction extends AbstractDatabaseObjectAction { + protected $form; + /** * Validates the 'ignore' action. */ @@ -42,6 +51,18 @@ class UserIgnoreAction extends AbstractDatabaseObjectAction if ($userProfile->getPermission('user.profile.cannotBeIgnored')) { throw new PermissionDeniedException(); } + + $this->readInteger('type', true, 'data'); + + if ( + $this->parameters['data']['type'] + && !\in_array($this->parameters['data']['type'], [ + UserIgnore::TYPE_BLOCK_DIRECT_CONTACT, + UserIgnore::TYPE_HIDE_MESSAGES, + ]) + ) { + throw new UserInputException('type', 'invalid'); + } } /** @@ -51,12 +72,22 @@ class UserIgnoreAction extends AbstractDatabaseObjectAction */ public function ignore() { - /** @var UserIgnore $ignore */ - $ignore = UserIgnoreEditor::createOrIgnore([ - 'ignoreUserID' => $this->parameters['data']['userID'], - 'time' => TIME_NOW, - 'userID' => WCF::getUser()->userID, - ]); + $ignore = new UserIgnoreEditor(UserIgnore::getIgnore($this->parameters['data']['userID'])); + $type = $this->parameters['data']['type'] ?? UserIgnore::TYPE_BLOCK_DIRECT_CONTACT; + + if ($ignore->ignoreID) { + $ignore->update([ + 'type' => $type, + 'time' => TIME_NOW, + ]); + } else { + $ignore = UserIgnoreEditor::createOrIgnore([ + 'ignoreUserID' => $this->parameters['data']['userID'], + 'type' => $type, + 'time' => TIME_NOW, + 'userID' => WCF::getUser()->userID, + ]); + } if ($ignore !== null) { UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'ignoredUserIDs'); @@ -121,6 +152,126 @@ class UserIgnoreAction extends AbstractDatabaseObjectAction return ['isIgnoredUser' => 0]; } + public function validateGetDialog() + { + $this->readInteger('userID'); + + $userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->parameters['userID']); + if ($userProfile === null || $userProfile->userID == WCF::getUser()->userID) { + throw new IllegalLinkException(); + } + + $ignore = UserIgnore::getIgnore($this->parameters['userID']); + + // Check if the user is not yet ignored and cannot be ignored. + if (!$ignore && $userProfile->getPermission('user.profile.cannotBeIgnored')) { + throw new PermissionDeniedException(); + } + } + + public function getDialog() + { + $form = $this->getForm(); + + return [ + 'dialog' => $form->getHtml(), + 'formId' => $form->getId(), + ]; + } + + public function validateSubmitDialog() + { + $this->validateGetDialog(); + + $this->readString('formId'); + + $this->getForm()->requestData($this->parameters['data'] ?? []); + $this->getForm()->readValues(); + } + + public function submitDialog() + { + $this->getForm()->validate(); + + if ($this->getForm()->hasValidationErrors()) { + return [ + 'dialog' => $this->getForm()->getHtml(), + 'formId' => $this->getForm()->getId(), + ]; + } + + $formData = $this->getForm()->getData(); + + if ($formData['data']['type'] === UserIgnore::TYPE_NO_IGNORE) { + return (new self([], 'unignore', [ + 'data' => [ + 'userID' => $this->parameters['userID'], + ], + ]))->executeAction()['returnValues']; + } else { + return (new self([], 'ignore', [ + 'data' => [ + 'userID' => $this->parameters['userID'], + 'type' => $formData['data']['type'], + ], + ]))->executeAction()['returnValues']; + } + } + + protected function getForm(): IFormDocument + { + if ($this->form === null) { + $id = 'userIgnore'; + $this->form = DialogFormDocument::create($id) + ->ajax() + ->prefix($id); + + $ignore = UserIgnore::getIgnore($this->parameters['userID']); + + $this->form->appendChildren([ + RadioButtonFormField::create('type') + ->label(WCF::getLanguage()->get('wcf.user.ignore.type')) + ->options([ + UserIgnore::TYPE_NO_IGNORE => WCF::getLanguage() + ->get('wcf.user.ignore.type.noIgnore'), + UserIgnore::TYPE_BLOCK_DIRECT_CONTACT => WCF::getLanguage() + ->get('wcf.user.ignore.type.blockDirectContact'), + UserIgnore::TYPE_HIDE_MESSAGES => WCF::getLanguage() + ->get('wcf.user.ignore.type.hideMessages'), + ]) + ->value($ignore->type ?: 0) + ->addValidator(new FormFieldValidator('type', function (RadioButtonFormField $formField) { + $userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->parameters['userID']); + if ($userProfile->getPermission('user.profile.cannotBeIgnored')) { + if ($formField->getValue() != UserIgnore::TYPE_NO_IGNORE) { + $formField->addValidationError( + new FormFieldValidationError( + 'cannotBeIgnored', + 'wcf.user.ignore.error.cannotBeIgnored' + ) + ); + } + } + })), + ]); + + $this->form->getDataHandler()->addProcessor( + new CustomFormDataProcessor( + 'type', + static function (IFormDocument $document, array $parameters) { + $parameters['data']['type'] = \intval($parameters['data']['type']); + + return $parameters; + } + ) + ); + + $this->form->build(); + } + + return $this->form; + } + /** * @inheritDoc */ diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index d570edb199..6247b20154 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -4800,6 +4800,11 @@ sich{/if} nicht bei uns registriert {if LANGUAGE_USE_INFORMAL_VARIANT}hast{else} user->username}? Abmelden und Benutzer wechseln.]]> + + + + + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index b3caad7bd1..f845c08de1 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -4798,6 +4798,11 @@ not register with us.]]> user->username}? Logout and change user.]]> + + + + + diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index a09f77ed39..6f6bc13d9f 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -1672,6 +1672,7 @@ CREATE TABLE wcf1_user_ignore ( userID INT(10) NOT NULL, ignoreUserID INT(10) NOT NULL, time INT(10) NOT NULL DEFAULT 0, + type TINYINT(1) NOT NULL DEFAULT 1, UNIQUE KEY (userID, ignoreUserID) ); -- 2.20.1