Migrate ignore/unignore to modern code
authorMarcel Werk <burntime@woltlab.com>
Thu, 25 Jan 2024 14:41:03 +0000 (15:41 +0100)
committerMarcel Werk <burntime@woltlab.com>
Thu, 25 Jan 2024 14:41:03 +0000 (15:41 +0100)
com.woltlab.wcf/templates/userCard.tpl
ts/WoltLabSuite/Core/BootstrapFrontend.ts
ts/WoltLabSuite/Core/Component/User/Ignore.ts [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/BootstrapFrontend.js
wcfsetup/install/files/js/WoltLabSuite/Core/Component/User/Ignore.js [new file with mode: 0644]
wcfsetup/install/files/lib/action/UserIgnoreAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/event/listener/PreloadPhrasesCollectingListener.class.php

index cb644bea467d8c9602c038204929a66203a5d320..8ec056e990d406eb22dd3f472c63007006b2938a 100644 (file)
                                                                >{icon name='circle-plus' size=24}</button>
                                                        {/if}
                                                {/if}
+
+                                               {if $__wcf->getUserProfileHandler()->isIgnoredUser($user->userID)}
+                                                       <button
+                                                               type="button"
+                                                               data-ignored="1"
+                                                               data-ignore-user="{link controller='UserIgnore' id=$user->userID}{/link}"
+                                                               class="userCard__button jsTooltip"
+                                                               title="{lang}wcf.user.button.unignore{/lang}"
+                                                       >{icon name='eye' size=24 type='solid'}</button>
+                                               {else}
+                                                       <button
+                                                               type="button"
+                                                               data-ignored="0"
+                                                               data-ignore-user="{link controller='UserIgnore' id=$user->userID}{/link}"
+                                                               class="userCard__button jsTooltip"
+                                                               title="{lang}wcf.user.button.ignore{/lang}"
+                                                       >{icon name='eye-slash' size=24 type='solid'}</button>
+                                               {/if}
                                        {/if}
                                        {event name='buttons'}
                                {/content}
index 8b8b5fac8ca72f18cba722dfef5e5a9d2f1d25ab..f1709ee6d99a3d58f0b121906190690a8aed6388 100644 (file)
@@ -120,4 +120,7 @@ export function setup(options: BootstrapOptions): void {
   whenFirstSeen("[data-follow-user]", () => {
     void import("./Component/User/Follow").then(({ setup }) => setup());
   });
+  whenFirstSeen("[data-ignore-user]", () => {
+    void import("./Component/User/Ignore").then(({ setup }) => setup());
+  });
 }
diff --git a/ts/WoltLabSuite/Core/Component/User/Ignore.ts b/ts/WoltLabSuite/Core/Component/User/Ignore.ts
new file mode 100644 (file)
index 0000000..4bbc840
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Handles the user ignore buttons.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+
+import { promiseMutex } from "WoltLabSuite/Core/Helper/PromiseMutex";
+import { wheneverFirstSeen } from "WoltLabSuite/Core/Helper/Selector";
+import { getPhrase } from "WoltLabSuite/Core/Language";
+import { show as showNotification } from "WoltLabSuite/Core/Ui/Notification";
+import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";
+
+type Response = {
+  type: number;
+};
+
+async function toggleIgnore(button: HTMLElement): Promise<void> {
+  const { ok, result } = await dialogFactory().usingFormBuilder().fromEndpoint<Response>(button.dataset.ignoreUser!);
+
+  if (ok) {
+    if (result.type) {
+      button.dataset.ignored = "1";
+      button.dataset.tooltip = getPhrase("wcf.user.button.unignore");
+      button.querySelector("fa-icon")?.setIcon("eye", true);
+    } else {
+      button.dataset.ignored = "0";
+      button.dataset.tooltip = getPhrase("wcf.user.button.ignore");
+      button.querySelector("fa-icon")?.setIcon("eye-slash", true);
+    }
+
+    showNotification();
+  }
+}
+
+export function setup(): void {
+  wheneverFirstSeen("[data-ignore-user]", (button) => {
+    button.addEventListener(
+      "click",
+      promiseMutex(() => toggleIgnore(button)),
+    );
+  });
+}
index a24fdbdd4e2d41d24f5f428f0be809f9b28b86d2..25abf088832a33ab38baf1dd8484788929ea2265 100644 (file)
@@ -93,6 +93,9 @@ define(["require", "exports", "tslib", "./BackgroundQueue", "./Bootstrap", "./Co
         (0, LazyLoader_1.whenFirstSeen)("[data-follow-user]", () => {
             void new Promise((resolve_5, reject_5) => { require(["./Component/User/Follow"], resolve_5, reject_5); }).then(tslib_1.__importStar).then(({ setup }) => setup());
         });
+        (0, LazyLoader_1.whenFirstSeen)("[data-ignore-user]", () => {
+            void new Promise((resolve_6, reject_6) => { require(["./Component/User/Ignore"], resolve_6, reject_6); }).then(tslib_1.__importStar).then(({ setup }) => setup());
+        });
     }
     exports.setup = setup;
 });
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/User/Ignore.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/User/Ignore.js
new file mode 100644 (file)
index 0000000..d3b5068
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * Handles the user ignore buttons.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+define(["require", "exports", "WoltLabSuite/Core/Helper/PromiseMutex", "WoltLabSuite/Core/Helper/Selector", "WoltLabSuite/Core/Language", "WoltLabSuite/Core/Ui/Notification", "WoltLabSuite/Core/Component/Dialog"], function (require, exports, PromiseMutex_1, Selector_1, Language_1, Notification_1, Dialog_1) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.setup = void 0;
+    async function toggleIgnore(button) {
+        const { ok, result } = await (0, Dialog_1.dialogFactory)().usingFormBuilder().fromEndpoint(button.dataset.ignoreUser);
+        if (ok) {
+            if (result.type) {
+                button.dataset.ignored = "1";
+                button.dataset.tooltip = (0, Language_1.getPhrase)("wcf.user.button.unignore");
+                button.querySelector("fa-icon")?.setIcon("eye", true);
+            }
+            else {
+                button.dataset.ignored = "0";
+                button.dataset.tooltip = (0, Language_1.getPhrase)("wcf.user.button.ignore");
+                button.querySelector("fa-icon")?.setIcon("eye-slash", true);
+            }
+            (0, Notification_1.show)();
+        }
+    }
+    function setup() {
+        (0, Selector_1.wheneverFirstSeen)("[data-ignore-user]", (button) => {
+            button.addEventListener("click", (0, PromiseMutex_1.promiseMutex)(() => toggleIgnore(button)));
+        });
+    }
+    exports.setup = setup;
+});
diff --git a/wcfsetup/install/files/lib/action/UserIgnoreAction.class.php b/wcfsetup/install/files/lib/action/UserIgnoreAction.class.php
new file mode 100644 (file)
index 0000000..3cdb223
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+
+namespace wcf\action;
+
+use Laminas\Diactoros\Response\JsonResponse;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use wcf\data\user\ignore\UserIgnore;
+use wcf\data\user\ignore\UserIgnoreAction as IgnoreUserIgnoreAction;
+use wcf\data\user\UserProfile;
+use wcf\http\Helper;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\PermissionDeniedException;
+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\Psr15DialogForm;
+use wcf\system\WCF;
+
+/**
+ * Handles user ignores.
+ *
+ * @author      Marcel Werk
+ * @copyright   2001-2023 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since       6.1
+ */
+final class UserIgnoreAction implements RequestHandlerInterface
+{
+    /**
+     * @inheritDoc
+     */
+    public function handle(ServerRequestInterface $request): ResponseInterface
+    {
+        $parameters = Helper::mapQueryParameters(
+            $request->getQueryParams(),
+            <<<'EOT'
+                array {
+                    id: positive-int
+                }
+                EOT
+        );
+
+        $this->assertUserIsLoggedIn();
+
+        $user = UserProfileRuntimeCache::getInstance()->getObject($parameters['id']);
+        $ignore = UserIgnore::getIgnore($parameters['id']);
+        $this->assertTargetCanBeIgnored($user, $ignore);
+
+        $form = $this->getForm($user, $ignore);
+
+        if ($request->getMethod() === 'GET') {
+            return $form->toResponse();
+        } elseif ($request->getMethod() === 'POST') {
+            $response = $form->validateRequest($request);
+            if ($response !== null) {
+                return $response;
+            }
+
+            $type = \intval($form->getData()['data']['type']);
+
+            if ($type === UserIgnore::TYPE_NO_IGNORE) {
+                (new IgnoreUserIgnoreAction([], 'unignore', [
+                    'data' => [
+                        'userID' => $parameters['id'],
+                    ],
+                ]))->executeAction();
+            } else {
+                (new IgnoreUserIgnoreAction([], 'ignore', [
+                    'data' => [
+                        'userID' => $parameters['id'],
+                        'type' => $type,
+                    ],
+                ]))->executeAction();
+            }
+
+            return new JsonResponse([
+                'result' => [
+                    'type' => $type,
+                ],
+            ]);
+        } else {
+            throw new \LogicException('Unreachable');
+        }
+    }
+
+    private function assertUserIsLoggedIn(): void
+    {
+        if (!WCF::getUser()->userID) {
+            throw new PermissionDeniedException();
+        }
+    }
+
+    private function assertTargetCanBeIgnored(?UserProfile $target, UserIgnore $ignore): void
+    {
+        if (!$target) {
+            throw new IllegalLinkException();
+        }
+
+        if ($target->userID === WCF::getUser()->userID) {
+            throw new IllegalLinkException();
+        }
+
+        // Check if the user is not yet ignored and cannot be ignored.
+        if ($ignore->type == UserIgnore::TYPE_NO_IGNORE && $target->getPermission('user.profile.cannotBeIgnored')) {
+            throw new PermissionDeniedException();
+        }
+    }
+
+    private function getForm(UserProfile $user, UserIgnore $ignore): Psr15DialogForm
+    {
+        $form = new Psr15DialogForm(
+            static::class,
+            WCF::getLanguage()->get('wcf.user.ignore.type')
+        );
+        $form->appendChildren([
+            RadioButtonFormField::create('type')
+                ->required()
+                ->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) use ($user) {
+                    if ($user->getPermission('user.profile.cannotBeIgnored')) {
+                        if ($formField->getValue() != UserIgnore::TYPE_NO_IGNORE) {
+                            $formField->addValidationError(
+                                new FormFieldValidationError(
+                                    'cannotBeIgnored',
+                                    'wcf.user.ignore.error.cannotBeIgnored'
+                                )
+                            );
+                        }
+                    }
+                })),
+        ]);
+
+        $form->markRequiredFields(false);
+        $form->build();
+
+        return $form;
+    }
+}
index 9691c1fc48a65738af3687e6c46ae394e050920d..6f0da89f61b2db6a3e6ea20b31e1e8e2cf806d85 100644 (file)
@@ -153,5 +153,7 @@ final class PreloadPhrasesCollectingListener
         $event->preload('wcf.user.panel.showAll');
         $event->preload('wcf.user.button.follow');
         $event->preload('wcf.user.button.unfollow');
+        $event->preload('wcf.user.button.ignore');
+        $event->preload('wcf.user.button.unignore');
     }
 }