--- /dev/null
+<?php
+
+namespace wcf\system\comment\command;
+
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentAction;
+use wcf\data\comment\CommentEditor;
+use wcf\data\object\type\ObjectType;
+use wcf\data\user\User;
+use wcf\event\comment\CommentCreated;
+use wcf\system\event\EventHandler;
+use wcf\system\html\input\HtmlInputProcessor;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\moderation\queue\ModerationQueueActivationManager;
+
+/**
+ * Creates a new comment.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class CreateComment
+{
+ public function __construct(
+ private readonly ObjectType $objectType,
+ private readonly int $objectID,
+ private readonly HtmlInputProcessor $htmlInputProcessor,
+ private readonly ?User $user = null,
+ private readonly string $username = '',
+ private readonly bool $isDisabled = false,
+ ) {
+ }
+
+ public function __invoke(): Comment
+ {
+ $action = new CommentAction([], 'create', [
+ 'data' => [
+ 'objectTypeID' => $this->objectType->objectTypeID,
+ 'objectID' => $this->objectID,
+ 'time' => TIME_NOW,
+ 'userID' => $this->user ? $this->user->userID : null,
+ 'username' => $this->user ? $this->user->username : $this->username,
+ 'message' => $this->htmlInputProcessor->getHtml(),
+ 'responses' => 0,
+ 'responseIDs' => \serialize([]),
+ 'enableHtml' => 1,
+ 'isDisabled' => $this->isDisabled ? 1 : 0,
+ ]
+ ]);
+ /** @var Comment $comment */
+ $comment = $action->executeAction()['returnValues'];
+
+ if (!$comment->isDisabled) {
+ (new PublishComment($comment))();
+ } else {
+ ModerationQueueActivationManager::getInstance()->addModeratedContent(
+ 'com.woltlab.wcf.comment.comment',
+ $comment->commentID
+ );
+ }
+
+ $this->htmlInputProcessor->setObjectID($comment->getObjectID());
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->htmlInputProcessor)) {
+ (new CommentEditor($comment))->update([
+ 'hasEmbeddedObjects' => 1,
+ ]);
+ $comment = new Comment($comment->getObjectID());
+ }
+
+ $event = new CommentCreated($comment);
+ EventHandler::getInstance()->fire($event);
+
+ return $comment;
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\command;
+
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentAction;
+use wcf\data\comment\response\CommentResponseList;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\event\comment\CommentsDeleted;
+use wcf\system\comment\response\command\DeleteResponses;
+use wcf\system\event\EventHandler;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\moderation\queue\ModerationQueueManager;
+use wcf\system\reaction\ReactionHandler;
+use wcf\system\user\activity\event\UserActivityEventHandler;
+use wcf\system\user\notification\UserNotificationHandler;
+
+/**
+ * Deletes a bunch of comments that belong to the same object type.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ *
+ * @property-read int[] $commentIDs
+ * @property-read Comment[] $comments
+ */
+final class DeleteComments
+{
+ private readonly ObjectType $objectType;
+ private readonly array $commentIDs;
+
+ public function __construct(
+ private readonly array $comments,
+ private readonly bool $updateCounters = true,
+ ) {
+ $this->commentIDs = \array_map(fn (Comment $comment): int => $comment->commentID, $this->comments);
+ foreach ($this->comments as $comment) {
+ if (!isset($this->objectType)) {
+ $this->objectType = ObjectTypeCache::getInstance()->getObjectType($comment->objectTypeID);
+ } else if ($this->objectType->objectTypeID !== $comment->objectTypeID) {
+ throw new \InvalidArgumentException('Given comments do not belong to the same object type.');
+ }
+ }
+ }
+
+ public function __invoke(): void
+ {
+ $this->deleteActivityEvents();
+ $this->deleteNotifications();
+ $this->deleteReactions();
+ $this->deleteModerationQueues();
+ $this->deleteMessageEmbeddedObjects();
+ $this->deleteResponses();
+
+ $action = new CommentAction($this->commentIDs, 'delete');
+ $action->executeAction();
+
+ $this->updateCounters();
+
+ $event = new CommentsDeleted($this->comments);
+ EventHandler::getInstance()->fire($event);
+ }
+
+ private function deleteActivityEvents(): void
+ {
+ if (UserActivityEventHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.recentActivityEvent')) {
+ UserActivityEventHandler::getInstance()->removeEvents(
+ $this->objectType->objectType . '.recentActivityEvent',
+ $this->commentIDs
+ );
+ }
+ }
+
+ private function deleteNotifications(): void
+ {
+ if (UserNotificationHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.notification')) {
+ UserNotificationHandler::getInstance()->removeNotifications(
+ $this->objectType->objectType . '.notification',
+ $this->commentIDs
+ );
+ }
+ }
+
+ private function deleteReactions(): void
+ {
+ ReactionHandler::getInstance()->removeReactions(
+ 'com.woltlab.wcf.comment',
+ $this->commentIDs,
+ UserNotificationHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.like.notification')
+ ? [$this->objectType->objectType . '.like.notification']
+ : []
+ );
+ }
+
+ private function deleteResponses(): void
+ {
+ $responseList = new CommentResponseList();
+ $responseList->getConditionBuilder()->add('comment_response.commentID IN (?)', [$this->commentIDs]);
+ $responseList->readObjectIDs();
+ if (!\count($responseList->getObjectIDs())) {
+ return;
+ }
+
+ (new DeleteResponses($responseList->getObjects(), $this->updateCounters))();
+ }
+
+ private function deleteModerationQueues(): void
+ {
+ ModerationQueueManager::getInstance()->removeQueues(
+ 'com.woltlab.wcf.comment.comment',
+ $this->commentIDs
+ );
+ }
+
+ private function deleteMessageEmbeddedObjects(): void
+ {
+ MessageEmbeddedObjectManager::getInstance()->removeObjects(
+ 'com.woltlab.wcf.comment',
+ $this->commentIDs
+ );
+ }
+
+ private function updateCounters(): void
+ {
+ if (!$this->updateCounters) {
+ return;
+ }
+
+ foreach ($this->comments as $comment) {
+ if (!$comment->isDisabled) {
+ $this->objectType->getProcessor()->updateCounter($comment->objectID, -1);
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\command;
+
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentEditor;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\event\comment\CommentPublished;
+use wcf\system\event\EventHandler;
+use wcf\system\user\activity\event\UserActivityEventHandler;
+use wcf\system\user\notification\object\CommentUserNotificationObject;
+use wcf\system\user\notification\object\type\ICommentUserNotificationObjectType;
+use wcf\system\user\notification\object\type\IMultiRecipientCommentUserNotificationObjectType;
+use wcf\system\user\notification\UserNotificationHandler;
+
+/**
+ * Publishes a comment.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class PublishComment
+{
+ private readonly ObjectType $objectType;
+
+ public function __construct(
+ private readonly Comment $comment,
+ ) {
+ $this->objectType = ObjectTypeCache::getInstance()->getObjectType($this->comment->objectTypeID);
+ }
+
+ public function __invoke(): void
+ {
+ if ($this->comment->isDisabled) {
+ (new CommentEditor($this->comment))->update([
+ 'isDisabled' => 0
+ ]);
+ }
+ $this->objectType->getProcessor()->updateCounter($this->comment->objectID, 1);
+
+ $this->fireActivityEvent();
+ $this->fireNotificationEvent();
+
+ $event = new CommentPublished($this->comment);
+ EventHandler::getInstance()->fire($event);
+ }
+
+ private function fireActivityEvent(): void
+ {
+ if (
+ $this->comment->userID
+ && UserActivityEventHandler::getInstance()->getObjectTypeID(
+ $this->objectType->objectType . '.recentActivityEvent'
+ )
+ ) {
+ UserActivityEventHandler::getInstance()->fireEvent(
+ $this->objectType->objectType . '.recentActivityEvent',
+ $this->comment->commentID,
+ null,
+ $this->comment->userID,
+ $this->comment->time
+ );
+ }
+ }
+
+ private function fireNotificationEvent(): void
+ {
+ if (!UserNotificationHandler::getInstance()->getEvent($this->objectType->objectType . '.notification', 'comment')) {
+ return;
+ }
+
+ $notificationObject = new CommentUserNotificationObject($this->comment);
+ $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor(
+ $this->objectType->objectType . '.notification'
+ );
+
+ if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType) {
+ $recipientIDs = $notificationObjectType->getRecipientIDs($this->comment);
+ } else {
+ $recipientIDs = [];
+ }
+
+ if ($notificationObjectType instanceof ICommentUserNotificationObjectType) {
+ $recipientIDs[] = $notificationObjectType->getOwnerID($this->comment->commentID);
+ }
+
+ // make sure that the comment's author gets no notification
+ $recipientIDs = \array_diff($recipientIDs, [$this->comment->getUserID()]);
+
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'comment',
+ $this->objectType->objectType . '.notification',
+ $notificationObject,
+ $recipientIDs
+ );
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\command;
+
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentAction;
+use wcf\event\comment\CommentUpdated;
+use wcf\system\event\EventHandler;
+use wcf\system\html\input\HtmlInputProcessor;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+
+/**
+ * Updates a comment.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class UpdateComment
+{
+ public function __construct(
+ private readonly Comment $comment,
+ private readonly HtmlInputProcessor $htmlInputProcessor,
+ ) {
+ }
+
+ public function __invoke(): void
+ {
+ $data = [
+ 'message' => $this->htmlInputProcessor->getHtml(),
+ ];
+
+ $this->htmlInputProcessor->setObjectID($this->comment->getObjectID());
+ $hasEmbeddedObjects = MessageEmbeddedObjectManager::getInstance()->registerObjects($this->htmlInputProcessor);
+ if ($this->comment->hasEmbeddedObjects != $hasEmbeddedObjects) {
+ $data['hasEmbeddedObjects'] = $this->comment->hasEmbeddedObjects ? 0 : 1;
+ }
+
+ $action = new CommentAction([$this->comment], 'update', [
+ 'data' => $data,
+ ]);
+ $action->executeAction();
+
+ $event = new CommentUpdated(new Comment($this->comment->commentID));
+ EventHandler::getInstance()->fire($event);
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\response\command;
+
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentEditor;
+use wcf\data\comment\response\CommentResponse;
+use wcf\data\comment\response\CommentResponseAction;
+use wcf\data\comment\response\CommentResponseEditor;
+use wcf\data\user\User;
+use wcf\event\comment\response\ResponseCreated;
+use wcf\system\event\EventHandler;
+use wcf\system\html\input\HtmlInputProcessor;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\moderation\queue\ModerationQueueActivationManager;
+
+/**
+ * Creates a new comment response.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class CreateResponse
+{
+ public function __construct(
+ private readonly Comment $comment,
+ private readonly HtmlInputProcessor $htmlInputProcessor,
+ private readonly ?User $user = null,
+ private readonly string $username = '',
+ private readonly bool $isDisabled = false,
+ ) {
+ }
+
+ public function __invoke(): CommentResponse
+ {
+ $action = new CommentResponseAction([], 'create', [
+ 'data' => [
+ 'commentID' => $this->comment->commentID,
+ 'time' => TIME_NOW,
+ 'userID' => $this->user ? $this->user->userID : null,
+ 'username' => $this->user ? $this->user->username : $this->username,
+ 'message' => $this->htmlInputProcessor->getHtml(),
+ 'enableHtml' => 1,
+ 'isDisabled' => $this->isDisabled ? 1 : 0,
+ ]
+ ]);
+ /** @var CommentResponse $response */
+ $response = $action->executeAction()['returnValues'];
+
+ $this->updateResponseData($response);
+
+ if (!$response->isDisabled) {
+ (new PublishResponse($response))();
+ } else {
+ ModerationQueueActivationManager::getInstance()->addModeratedContent(
+ 'com.woltlab.wcf.comment.response',
+ $response->responseID
+ );
+ }
+
+ $this->htmlInputProcessor->setObjectID($response->getObjectID());
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->htmlInputProcessor)) {
+ (new CommentResponseEditor($response))->update([
+ 'hasEmbeddedObjects' => 1,
+ ]);
+ $response = new CommentResponse($response->getObjectID());
+ }
+
+ $event = new ResponseCreated($response);
+ EventHandler::getInstance()->fire($event);
+
+ return $response;
+ }
+
+ private function updateResponseData(CommentResponse $response): void
+ {
+ $unfilteredResponseIDs = $this->comment->getUnfilteredResponseIDs();
+ if (\count($unfilteredResponseIDs) < 5) {
+ $unfilteredResponseIDs[] = $response->responseID;
+ }
+ $unfilteredResponses = $this->comment->unfilteredResponses + 1;
+
+ (new CommentEditor($this->comment))->update([
+ 'unfilteredResponseIDs' => \serialize($unfilteredResponseIDs),
+ 'unfilteredResponses' => $unfilteredResponses,
+ ]);
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\response\command;
+
+use wcf\data\comment\CommentEditor;
+use wcf\data\comment\CommentList;
+use wcf\data\comment\response\CommentResponse;
+use wcf\data\comment\response\CommentResponseAction;
+use wcf\data\object\type\ObjectType;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\event\comment\response\ResponsesDeleted;
+use wcf\system\event\EventHandler;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\moderation\queue\ModerationQueueManager;
+use wcf\system\reaction\ReactionHandler;
+use wcf\system\user\activity\event\UserActivityEventHandler;
+use wcf\system\user\notification\UserNotificationHandler;
+
+/**
+ * Deletes a bunch of comment responses that belong to the same object type.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ *
+ * @property-read int[] $responseIDs
+ * @property-read CommentResponse[] $responses
+ */
+final class DeleteResponses
+{
+ private readonly ObjectType $objectType;
+ private readonly array $responseIDs;
+
+ public function __construct(
+ private readonly array $responses,
+ private readonly bool $updateCounters = true,
+ ) {
+ $this->responseIDs = \array_map(fn (CommentResponse $response): int => $response->responseID, $this->responses);
+ foreach ($this->responses as $response) {
+ if (!isset($this->objectType)) {
+ $this->objectType = ObjectTypeCache::getInstance()->getObjectType($response->getComment()->objectTypeID);
+ }
+ }
+ }
+
+ public function __invoke(): void
+ {
+ $this->deleteActivityEvents();
+ $this->deleteNotifications();
+ $this->deleteReactions();
+ $this->deleteModerationQueues();
+ $this->deleteMessageEmbeddedObjects();
+
+ $action = new CommentResponseAction($this->responseIDs, 'delete');
+ $action->executeAction();
+
+ $this->updateCounters();
+
+ $event = new ResponsesDeleted($this->responses);
+ EventHandler::getInstance()->fire($event);
+ }
+
+ private function deleteActivityEvents(): void
+ {
+ if (UserActivityEventHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.response.recentActivityEvent')) {
+ UserActivityEventHandler::getInstance()->removeEvents(
+ $this->objectType->objectType . '.response.recentActivityEvent',
+ $this->responseIDs
+ );
+ }
+ }
+
+ private function deleteNotifications(): void
+ {
+ if (UserNotificationHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.response.notification')) {
+ UserNotificationHandler::getInstance()->removeNotifications(
+ $this->objectType->objectType . '.response.notification',
+ $this->responseIDs
+ );
+ }
+ }
+
+ private function deleteReactions(): void
+ {
+ ReactionHandler::getInstance()->removeReactions(
+ 'com.woltlab.wcf.comment.response',
+ $this->responseIDs,
+ UserNotificationHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.response.like.notification')
+ ? [$this->objectType->objectType . '.response.like.notification']
+ : []
+ );
+ }
+
+ private function deleteModerationQueues(): void
+ {
+ ModerationQueueManager::getInstance()->removeQueues(
+ 'com.woltlab.wcf.comment.response',
+ $this->responseIDs
+ );
+ }
+
+ private function deleteMessageEmbeddedObjects(): void
+ {
+ MessageEmbeddedObjectManager::getInstance()->removeObjects(
+ 'com.woltlab.wcf.comment.response',
+ $this->responseIDs
+ );
+ }
+
+ private function updateCounters(): void
+ {
+ if (!$this->updateCounters) {
+ return;
+ }
+
+ foreach ($this->responses as $response) {
+ $commentIDs[] = $response->commentID;
+ }
+
+ $commentList = new CommentList();
+ $commentList->setObjectIDs(\array_unique($commentIDs));
+ $commentList->readObjects();
+ $comments = $commentList->getObjects();
+
+ foreach ($comments as $comment) {
+ $commentEditor = new CommentEditor($comment);
+ $commentEditor->updateResponseIDs();
+ $commentEditor->updateUnfilteredResponseIDs();
+ $commentEditor->updateResponses();
+ $commentEditor->updateUnfilteredResponses();
+ }
+
+ foreach ($this->responses as $response) {
+ if (!$response->isDisabled) {
+ $this->objectType->getProcessor()->updateCounter($comments[$response->commentID]->objectID, -1);
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\response\command;
+
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentEditor;
+use wcf\data\comment\response\CommentResponse;
+use wcf\data\comment\response\CommentResponseEditor;
+use wcf\data\object\type\ObjectType;
+use wcf\event\comment\response\ResponsePublished;
+use wcf\system\comment\CommentHandler;
+use wcf\system\event\EventHandler;
+use wcf\system\user\activity\event\UserActivityEventHandler;
+use wcf\system\user\notification\object\CommentResponseUserNotificationObject;
+use wcf\system\user\notification\object\type\ICommentUserNotificationObjectType;
+use wcf\system\user\notification\object\type\IMultiRecipientCommentUserNotificationObjectType;
+use wcf\system\user\notification\UserNotificationHandler;
+
+/**
+ * Publishes a comment response.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class PublishResponse
+{
+ private readonly ObjectType $objectType;
+ private readonly Comment $comment;
+
+ public function __construct(
+ private readonly CommentResponse $response,
+ ) {
+ $this->comment = $response->getComment();
+ $this->objectType = CommentHandler::getInstance()->getObjectType($this->comment->objectTypeID);
+ }
+
+ public function __invoke(): void
+ {
+ if ($this->response->isDisabled) {
+ (new CommentResponseEditor($this->response))->update([
+ 'isDisabled' => 0,
+ ]);
+ }
+
+ $commentEditor = new CommentEditor($this->comment);
+ $commentEditor->updateCounters(['responses' => 1]);
+ // do not prepend the response id as the approved response can appear anywhere
+ $commentEditor->updateResponseIDs();
+
+ $this->objectType->getProcessor()->updateCounter($this->comment->objectID, 1);
+
+ $this->fireActivityEvent();
+ $this->fireNotificationEvent();
+
+ $event = new ResponsePublished($this->response);
+ EventHandler::getInstance()->fire($event);
+ }
+
+ private function fireActivityEvent(): void
+ {
+ if (
+ $this->response->userID
+ && UserActivityEventHandler::getInstance()->getObjectTypeID(
+ $this->objectType->objectType . '.response.recentActivityEvent'
+ )
+ ) {
+ UserActivityEventHandler::getInstance()->fireEvent(
+ $this->objectType->objectType . '.response.recentActivityEvent',
+ $this->response->responseID,
+ null,
+ $this->response->userID,
+ $this->response->time
+ );
+ }
+ }
+
+ private function fireNotificationEvent(): void
+ {
+ if (
+ !UserNotificationHandler::getInstance()->getObjectTypeID($this->objectType->objectType . '.notification')
+ || (
+ !UserNotificationHandler::getInstance()->getEvent($this->objectType->objectType . '.response.notification', 'commentResponse')
+ && !UserNotificationHandler::getInstance()->getEvent($this->objectType->objectType . '.response.notification', 'commentResponseOwner')
+ )
+ ) {
+ return;
+ }
+
+ $notificationObject = new CommentResponseUserNotificationObject($this->response);
+ $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor($this->objectType->objectType . '.notification');
+
+ if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType) {
+ $recipientIDs = $notificationObjectType->getRecipientIDs($this->comment);
+ } else {
+ $recipientIDs = [];
+ }
+
+ $recipientIDs[] = $this->comment->userID;
+
+ $userID = 0;
+ if ($notificationObjectType instanceof ICommentUserNotificationObjectType) {
+ $userID = $notificationObjectType->getOwnerID($this->comment->commentID);
+ }
+
+ // make sure that the response's author gets no notification
+ $recipientIDs = \array_diff($recipientIDs, [$this->response->getUserID()]);
+
+ if (UserNotificationHandler::getInstance()->getEvent($this->objectType->objectType . '.response.notification', 'commentResponse')) {
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'commentResponse',
+ $this->objectType->objectType . '.response.notification',
+ $notificationObject,
+ $recipientIDs,
+ [
+ 'commentID' => $this->comment->commentID,
+ 'objectID' => $this->comment->objectID,
+ 'userID' => $this->comment->userID,
+ ]
+ );
+ }
+
+ // notify the container owner
+ if (UserNotificationHandler::getInstance()->getEvent($this->objectType->objectType . '.response.notification', 'commentResponseOwner')) {
+ if ($userID && $userID != $this->comment->userID && $userID != $this->response->getUserID()) {
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'commentResponseOwner',
+ $this->objectType->objectType . '.response.notification',
+ $notificationObject,
+ [$userID],
+ [
+ 'commentID' => $this->comment->commentID,
+ 'objectID' => $this->comment->objectID,
+ 'objectUserID' => $userID,
+ 'userID' => $this->comment->userID,
+ ]
+ );
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\system\comment\response\command;
+
+use wcf\data\comment\response\CommentResponse;
+use wcf\data\comment\response\CommentResponseAction;
+use wcf\event\comment\response\ResponseUpdated;
+use wcf\system\event\EventHandler;
+use wcf\system\html\input\HtmlInputProcessor;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+
+/**
+ * Updates a comment response.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class UpdateResponse
+{
+ public function __construct(
+ private readonly CommentResponse $response,
+ private readonly HtmlInputProcessor $htmlInputProcessor,
+ ) {
+ }
+
+ public function __invoke(): void
+ {
+ $data = [
+ 'message' => $this->htmlInputProcessor->getHtml(),
+ ];
+
+ $this->htmlInputProcessor->setObjectID($this->response->getObjectID());
+ $hasEmbeddedObjects = MessageEmbeddedObjectManager::getInstance()->registerObjects($this->htmlInputProcessor);
+ if ($this->response->hasEmbeddedObjects != $hasEmbeddedObjects) {
+ $data['hasEmbeddedObjects'] = $this->response->hasEmbeddedObjects ? 0 : 1;
+ }
+
+ $action = new CommentResponseAction([$this->response], 'update', [
+ 'data' => $data,
+ ]);
+ $action->executeAction();
+
+ $event = new ResponseUpdated(new CommentResponse($this->response->commentID));
+ EventHandler::getInstance()->fire($event);
+ }
+}