3 namespace wcf\data\comment
;
5 use wcf\data\AbstractDatabaseObjectAction
;
6 use wcf\data\comment\response\CommentResponse
;
7 use wcf\data\comment\response\CommentResponseAction
;
8 use wcf\data\comment\response\CommentResponseEditor
;
9 use wcf\data\comment\response\StructuredCommentResponse
;
10 use wcf\data\IMessageInlineEditorAction
;
11 use wcf\data\
object\type\ObjectType
;
12 use wcf\data\
object\type\ObjectTypeCache
;
13 use wcf\data\user\User
;
14 use wcf\event\message\MessageSpamChecking
;
15 use wcf\system\bbcode\BBCodeHandler
;
16 use wcf\system\captcha\CaptchaHandler
;
17 use wcf\system\comment\CommentHandler
;
18 use wcf\system\comment\manager\ICommentManager
;
19 use wcf\system\event\EventHandler
;
20 use wcf\system\exception\NamedUserException
;
21 use wcf\system\exception\PermissionDeniedException
;
22 use wcf\system\exception\SystemException
;
23 use wcf\system\exception\UserInputException
;
24 use wcf\system\flood\FloodControl
;
25 use wcf\system\html\input\HtmlInputProcessor
;
26 use wcf\system\html\upcast\HtmlUpcastProcessor
;
27 use wcf\system\message\embedded\
object\MessageEmbeddedObjectManager
;
28 use wcf\system\moderation\queue\ModerationQueueActivationManager
;
29 use wcf\system\reaction\ReactionHandler
;
30 use wcf\system\user\activity\event\UserActivityEventHandler
;
31 use wcf\system\user\notification\
object\CommentResponseUserNotificationObject
;
32 use wcf\system\user\notification\
object\CommentUserNotificationObject
;
33 use wcf\system\user\notification\
object\type\ICommentUserNotificationObjectType
;
34 use wcf\system\user\notification\
object\type\IMultiRecipientCommentUserNotificationObjectType
;
35 use wcf\system\user\notification\UserNotificationHandler
;
37 use wcf\util\MessageUtil
;
38 use wcf\util\UserRegistrationUtil
;
39 use wcf\util\UserUtil
;
42 * Executes comment-related actions.
44 * @author Alexander Ebert
45 * @copyright 2001-2020 WoltLab GmbH
46 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
48 * @method Comment create()
49 * @method CommentEditor[] getObjects()
50 * @method CommentEditor getSingleObject()
52 class CommentAction
extends AbstractDatabaseObjectAction
implements IMessageInlineEditorAction
57 protected $allowGuestAccess = [
66 * captcha object type used for comments
70 public $captchaObjectType;
75 protected $className = CommentEditor
::class;
86 * @var ICommentManager
89 protected $commentProcessor;
92 * @var HtmlInputProcessor
95 protected $htmlInputProcessor;
99 * @var CommentResponse
105 * comment object created by addComment()
109 public $createdComment;
112 * response object created by addResponse()
113 * @var CommentResponse
116 public $createdResponse;
119 * errors occurring through the validation of addComment or addResponse
123 public $validationErrors = [];
126 * Validates parameters to load comments.
128 * @throws PermissionDeniedException
129 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
131 public function validateLoadComments()
133 $this->readInteger('lastCommentTime', false, 'data');
134 $this->readInteger('objectID', false, 'data');
136 $objectType = $this->validateObjectType();
137 $this->commentProcessor
= $objectType->getProcessor();
138 if (!$this->commentProcessor
->isAccessible($this->parameters
['data']['objectID'])) {
139 throw new PermissionDeniedException();
144 * Returns parsed comments.
147 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
149 public function loadComments()
151 $commentList = CommentHandler
::getInstance()->getCommentList(
152 $this->commentProcessor
,
153 $this->parameters
['data']['objectTypeID'],
154 $this->parameters
['data']['objectID'],
157 $commentList->getConditionBuilder()->add("comment.time < ?", [$this->parameters
['data']['lastCommentTime']]);
158 $commentList->readObjects();
160 // mark notifications for loaded comments as read
161 CommentHandler
::getInstance()->markNotificationsAsConfirmedForComments(
162 CommentHandler
::getInstance()->getObjectType($this->parameters
['data']['objectTypeID'])->objectType
,
163 $commentList->getObjects()
166 WCF
::getTPL()->assign([
167 'commentList' => $commentList,
168 'likeData' => MODULE_LIKE ?
$commentList->getLikeData() : [],
172 'lastCommentTime' => $commentList->getMinCommentTime(),
173 'template' => WCF
::getTPL()->fetch('commentList'),
178 * Validates the `loadComment` action.
180 * @throws PermissionDeniedException
182 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
184 public function validateLoadComment()
186 $this->readInteger('responseID', true);
187 $this->readInteger('objectTypeID', true);
188 $this->comment
= $this->getSingleObject()->getDecoratedObject();
189 if (!empty($this->parameters
['objectTypeID']) && $this->parameters
['objectTypeID'] !== $this->comment
->objectTypeID
) {
190 throw new UserInputException('objectTypeID');
193 $objectType = ObjectTypeCache
::getInstance()->getObjectType($this->comment
->objectTypeID
);
194 $this->commentProcessor
= $objectType->getProcessor();
195 if (!$this->commentProcessor
->isAccessible($this->comment
->objectID
)) {
196 throw new PermissionDeniedException();
198 if ($this->comment
->isDisabled
&& !$this->commentProcessor
->canModerate($this->comment
->objectTypeID
, $this->comment
->objectID
)) {
199 throw new PermissionDeniedException();
202 if (!empty($this->parameters
['responseID'])) {
203 $this->response
= new CommentResponse($this->parameters
['responseID']);
204 if (!$this->response
->responseID
) {
205 throw new UserInputException('responseID');
207 if ($this->response
->commentID
!= $this->comment
->commentID
) {
208 throw new PermissionDeniedException();
210 if ($this->response
->isDisabled
&& !$this->commentProcessor
->canModerate($this->comment
->objectTypeID
, $this->comment
->objectID
)) {
211 throw new PermissionDeniedException();
217 * Returns a rendered comment.
221 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
223 public function loadComment()
225 // mark notifications for loaded comment/response as read
226 $objectType = CommentHandler
::getInstance()->getObjectType($this->comment
->objectTypeID
)->objectType
;
227 if ($this->response
=== null) {
228 CommentHandler
::getInstance()->markNotificationsAsConfirmedForComments(
230 [new StructuredComment($this->comment
)]
233 CommentHandler
::getInstance()->markNotificationsAsConfirmedForResponses(
239 $returnValues = $this->renderComment($this->comment
, $this->response
);
241 return (\
is_array($returnValues)) ?
$returnValues : ['template' => $returnValues];
245 * Validates the `loadResponse` action.
248 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
250 public function validateLoadResponse()
252 $this->readInteger('responseID');
253 $this->readInteger('objectTypeID', true);
254 $this->response
= new CommentResponse($this->parameters
['responseID']);
255 if (!$this->response
->responseID
) {
256 throw new UserInputException('responseID');
259 $this->comment
= $this->response
->getComment();
260 if (!empty($this->parameters
['objectTypeID']) && $this->parameters
['objectTypeID'] !== $this->comment
->objectTypeID
) {
261 throw new UserInputException('objectTypeID');
264 $objectType = ObjectTypeCache
::getInstance()->getObjectType($this->comment
->objectTypeID
);
265 $this->commentProcessor
= $objectType->getProcessor();
266 if (!$this->commentProcessor
->isAccessible($this->comment
->objectID
)) {
267 throw new PermissionDeniedException();
272 * Returns a rendered response.
276 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
278 public function loadResponse()
281 'template' => $this->renderResponse($this->response
),
286 * Validates parameters to add a comment.
288 * @throws PermissionDeniedException
289 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
291 public function validateAddComment()
294 CommentHandler
::enforceFloodControl();
295 } catch (NamedUserException
$e) {
296 throw new UserInputException('message', $e->getMessage());
299 $this->readInteger('objectID', false, 'data');
300 $this->validateGetGuestDialog();
302 $this->validateMessage();
303 $objectType = $this->validateObjectType();
305 // validate object id and permissions
306 $this->commentProcessor
= $objectType->getProcessor();
307 if (!$this->commentProcessor
->canAdd($this->parameters
['data']['objectID'])) {
308 throw new PermissionDeniedException();
311 $event = new MessageSpamChecking(
312 $this->parameters
['htmlInputProcessor'],
313 WCF
::getUser()->userID ? WCF
::getUser() : null,
314 UserUtil
::getIpAddress(),
316 EventHandler
::getInstance()->fire($event);
317 if ($event->defaultPrevented()) {
318 throw new PermissionDeniedException();
326 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
328 public function addComment()
330 $guestDialog = $this->getGuestDialog();
333 'guestDialog' => $guestDialog,
337 /** @var HtmlInputProcessor $htmlInputProcessor */
338 $htmlInputProcessor = $this->parameters
['htmlInputProcessor'];
341 $this->createdComment
= CommentEditor
::create([
342 'objectTypeID' => $this->parameters
['data']['objectTypeID'],
343 'objectID' => $this->parameters
['data']['objectID'],
345 'userID' => WCF
::getUser()->userID ?
: null,
346 'username' => WCF
::getUser()->userID ? WCF
::getUser()->username
: $this->parameters
['data']['username'],
347 'message' => $htmlInputProcessor->getHtml(),
349 'responseIDs' => \
serialize([]),
351 'isDisabled' => $this->commentProcessor
->canAddWithoutApproval($this->parameters
['data']['objectID']) ?
0 : 1,
354 if (!$this->createdComment
->isDisabled
) {
355 $action = new self([$this->createdComment
], 'triggerPublication', [
356 'commentProcessor' => $this->commentProcessor
,
358 $action->executeAction();
360 // mark comment for moderated content
361 ModerationQueueActivationManager
::getInstance()->addModeratedContent(
362 'com.woltlab.wcf.comment.comment',
363 $this->createdComment
->commentID
367 $htmlInputProcessor->setObjectID($this->createdComment
->getObjectID());
368 if (MessageEmbeddedObjectManager
::getInstance()->registerObjects($htmlInputProcessor)) {
369 (new CommentEditor($this->createdComment
))->update([
370 'hasEmbeddedObjects' => 1,
372 $this->createdComment
= new Comment($this->createdComment
->getObjectID());
375 FloodControl
::getInstance()->registerContent('com.woltlab.wcf.comment');
377 if (!$this->createdComment
->userID
) {
378 // save user name is session
379 WCF
::getSession()->register('username', $this->createdComment
->username
);
381 // save last comment time for flood control
382 WCF
::getSession()->register('lastCommentTime', $this->createdComment
->time
);
384 // reset captcha for future requests
385 if ($this->captchaObjectType
) {
386 $this->captchaObjectType
->getProcessor()->reset();
391 'template' => $this->renderComment($this->createdComment
),
396 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
398 public function triggerPublication()
400 if (!empty($this->parameters
['commentProcessor'])) {
402 if (!empty($this->objects
)) {
403 /** @var Comment $comment */
404 $comment = \reset
($this->objects
);
405 $objectType = $this->validateObjectType($comment->objectTypeID
);
408 $this->commentProcessor
= $this->parameters
['commentProcessor'];
410 $objectType = $this->validateObjectType($this->parameters
['objectTypeID']);
411 $this->commentProcessor
= $objectType->getProcessor();
414 /** @var CommentEditor $comment */
415 foreach ($this->objects
as $comment) {
417 $comment->update(['isDisabled' => 0]);
418 $this->commentProcessor
->updateCounter($comment->objectID
, 1);
420 // fire activity event
421 if ($comment->userID
&& UserActivityEventHandler
::getInstance()->getObjectTypeID($objectType->objectType
. '.recentActivityEvent')) {
422 UserActivityEventHandler
::getInstance()->fireEvent(
423 $objectType->objectType
. '.recentActivityEvent',
431 // fire notification event
432 if (UserNotificationHandler
::getInstance()->getEvent($objectType->objectType
. '.notification', 'comment')) {
433 $notificationObject = new CommentUserNotificationObject($comment->getDecoratedObject());
434 $notificationObjectType = UserNotificationHandler
::getInstance()->getObjectTypeProcessor($objectType->objectType
. '.notification');
436 if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType
) {
437 $recipientIDs = $notificationObjectType->getRecipientIDs($comment->getDecoratedObject());
442 if ($notificationObjectType instanceof ICommentUserNotificationObjectType
) {
443 $recipientIDs[] = $notificationObjectType->getOwnerID($comment->commentID
);
446 // make sure that the comment's author gets no notification
447 $recipientIDs = \array_diff
($recipientIDs, [$comment->getUserID()]);
449 UserNotificationHandler
::getInstance()->fireEvent(
451 $objectType->objectType
. '.notification',
460 * Validates parameters to add a response.
462 * @throws PermissionDeniedException
463 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
465 public function validateAddResponse()
468 CommentHandler
::enforceFloodControl();
469 } catch (NamedUserException
$e) {
470 throw new UserInputException('message', $e->getMessage());
473 $comment = $this->getSingleObject();
474 $objectType = ObjectTypeCache
::getInstance()->getObjectType($comment->objectTypeID
);
475 $this->commentProcessor
= $objectType->getProcessor();
476 if (!$this->commentProcessor
->canAdd($comment->objectID
)) {
477 throw new PermissionDeniedException();
480 if ($comment->isDisabled
&& !$this->commentProcessor
->canModerate($comment->objectTypeID
, $comment->objectID
)) {
481 throw new PermissionDeniedException();
484 $this->validateGetGuestDialog();
485 $this->validateMessage(true);
487 $event = new MessageSpamChecking(
488 $this->parameters
['htmlInputProcessor'],
489 WCF
::getUser()->userID ? WCF
::getUser() : null,
490 UserUtil
::getIpAddress(),
492 EventHandler
::getInstance()->fire($event);
493 if ($event->defaultPrevented()) {
494 throw new PermissionDeniedException();
502 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
504 public function addResponse()
506 $guestDialog = $this->getGuestDialog();
509 'guestDialog' => $guestDialog,
513 $comment = $this->getSingleObject();
515 /** @var HtmlInputProcessor $htmlInputProcessor */
516 $htmlInputProcessor = $this->parameters
['htmlInputProcessor'];
519 $this->createdResponse
= CommentResponseEditor
::create([
520 'commentID' => $comment->commentID
,
522 'userID' => WCF
::getUser()->userID ?
: null,
523 'username' => WCF
::getUser()->userID ? WCF
::getUser()->username
: $this->parameters
['data']['username'],
524 'message' => $htmlInputProcessor->getHtml(),
526 'isDisabled' => $this->commentProcessor
->canAddWithoutApproval($comment->objectID
) ?
0 : 1,
528 $this->createdResponse
->setComment($comment->getDecoratedObject());
530 $htmlInputProcessor->setObjectID($this->createdResponse
->getObjectID());
531 if (MessageEmbeddedObjectManager
::getInstance()->registerObjects($htmlInputProcessor)) {
532 (new CommentResponseEditor($this->createdResponse
))->update([
533 'hasEmbeddedObjects' => 1,
535 $this->createdResponse
= new CommentResponse($this->createdResponse
->getObjectID());
538 // update response data
539 $unfilteredResponseIDs = $comment->getUnfilteredResponseIDs();
540 if (\
count($unfilteredResponseIDs) < 5) {
541 $unfilteredResponseIDs[] = $this->createdResponse
->responseID
;
543 $unfilteredResponses = $comment->unfilteredResponses +
1;
547 'unfilteredResponseIDs' => \
serialize($unfilteredResponseIDs),
548 'unfilteredResponses' => $unfilteredResponses,
551 if (!$this->createdResponse
->isDisabled
) {
552 $action = new self([], 'triggerPublicationResponse', [
553 'commentProcessor' => $this->commentProcessor
,
554 'responses' => [$this->createdResponse
],
556 $action->executeAction();
558 // mark response for moderated content
559 ModerationQueueActivationManager
::getInstance()->addModeratedContent(
560 'com.woltlab.wcf.comment.response',
561 $this->createdResponse
->responseID
565 FloodControl
::getInstance()->registerContent('com.woltlab.wcf.comment');
567 if (!$this->createdResponse
->userID
) {
568 // save user name is session
569 WCF
::getSession()->register('username', $this->createdResponse
->username
);
571 // save last comment time for flood control
572 WCF
::getSession()->register('lastCommentTime', $this->createdResponse
->time
);
574 // reset captcha for future requests
575 if ($this->captchaObjectType
) {
576 $this->captchaObjectType
->getProcessor()->reset();
580 $responses = $comment->responses
;
582 $this->commentProcessor
->canModerate(
583 $comment->objectTypeID
,
587 $responses = $comment->unfilteredResponses
;
591 'commentID' => $comment->commentID
,
592 'template' => $this->renderResponse($this->createdResponse
),
593 'responses' => $responses +
1,
598 * Publishes a response.
599 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
601 public function triggerPublicationResponse()
603 if (!empty($this->parameters
['commentProcessor'])) {
605 if (!empty($this->parameters
['responses'])) {
606 /** @var CommentResponse $response */
607 $response = \reset
($this->parameters
['responses']);
608 $objectType = $this->validateObjectType($response->getComment()->objectTypeID
);
611 $this->commentProcessor
= $this->parameters
['commentProcessor'];
613 $objectType = $this->validateObjectType($this->parameters
['objectTypeID']);
614 $this->commentProcessor
= $objectType->getProcessor();
617 /** @var CommentResponse $response */
618 foreach ($this->parameters
['responses'] as $response) {
619 (new CommentResponseEditor($response))->update(['isDisabled' => 0]);
621 $comment = $response->getComment();
623 // update response count
624 $commentEditor = new CommentEditor($comment);
625 $commentEditor->updateCounters(['responses' => 1]);
627 // do not prepend the response id as the approved response can appear anywhere
628 $commentEditor->updateResponseIDs();
631 $this->commentProcessor
->updateCounter($comment->objectID
, 1);
633 // fire activity event
634 if ($response->userID
&& UserActivityEventHandler
::getInstance()->getObjectTypeID($objectType->objectType
. '.response.recentActivityEvent')) {
635 UserActivityEventHandler
::getInstance()->fireEvent(
636 $objectType->objectType
. '.response.recentActivityEvent',
637 $response->responseID
,
644 // fire notification event
646 UserNotificationHandler
::getInstance()->getObjectTypeID($objectType->objectType
. '.notification')
648 UserNotificationHandler
::getInstance()->getEvent($objectType->objectType
. '.response.notification', 'commentResponse')
649 || UserNotificationHandler
::getInstance()->getEvent($objectType->objectType
. '.response.notification', 'commentResponseOwner')
652 $notificationObject = new CommentResponseUserNotificationObject($response);
653 $notificationObjectType = UserNotificationHandler
::getInstance()->getObjectTypeProcessor($objectType->objectType
. '.notification');
655 if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType
) {
656 $recipientIDs = $notificationObjectType->getRecipientIDs($comment);
661 $recipientIDs[] = $comment->userID
;
664 if ($notificationObjectType instanceof ICommentUserNotificationObjectType
) {
665 $userID = $notificationObjectType->getOwnerID($comment->commentID
);
668 // make sure that the response's author gets no notification
669 $recipientIDs = \array_diff
($recipientIDs, [$response->getUserID()]);
671 if (UserNotificationHandler
::getInstance()->getEvent($objectType->objectType
. '.response.notification', 'commentResponse')) {
672 UserNotificationHandler
::getInstance()->fireEvent(
674 $objectType->objectType
. '.response.notification',
678 'commentID' => $comment->commentID
,
679 'objectID' => $comment->objectID
,
680 'userID' => $comment->userID
,
685 // notify the container owner
686 if (UserNotificationHandler
::getInstance()->getEvent($objectType->objectType
. '.response.notification', 'commentResponseOwner')) {
687 if ($userID && $userID != $comment->userID
&& $userID != $response->getUserID()) {
688 UserNotificationHandler
::getInstance()->fireEvent(
689 'commentResponseOwner',
690 $objectType->objectType
. '.response.notification',
694 'commentID' => $comment->commentID
,
695 'objectID' => $comment->objectID
,
696 'objectUserID' => $userID,
697 'userID' => $comment->userID
,
707 * Validates the `enable` action.
709 * @throws PermissionDeniedException
710 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
712 public function validateEnable()
714 $this->comment
= $this->getSingleObject()->getDecoratedObject();
716 $objectType = $this->validateObjectType($this->comment
->objectTypeID
);
717 $this->commentProcessor
= $objectType->getProcessor();
718 if (!$this->commentProcessor
->canModerate($this->comment
->objectTypeID
, $this->comment
->objectID
)) {
719 throw new PermissionDeniedException();
727 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
729 public function enable()
731 if ($this->comment
=== null) {
732 $this->comment
= \reset
($this->objects
);
735 if ($this->comment
->isDisabled
) {
736 $action = new self([$this->comment
], 'triggerPublication', [
737 'commentProcessor' => $this->commentProcessor
,
738 'objectTypeID' => $this->comment
->objectTypeID
,
740 $action->executeAction();
743 ModerationQueueActivationManager
::getInstance()->removeModeratedContent(
744 'com.woltlab.wcf.comment.comment',
745 [$this->comment
->commentID
]
748 return ['commentID' => $this->comment
->commentID
];
752 * Validates the `enableResponse` action.
754 * @throws PermissionDeniedException
755 * @throws UserInputException
756 * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
758 public function validateEnableResponse()
760 $this->readInteger('responseID', false, 'data');
761 $this->response
= new CommentResponse($this->parameters
['data']['responseID']);
762 if (!$this->response
->responseID
) {
763 throw new UserInputException('responseID');
766 $this->comment
= $this->response
->getComment();
768 $objectType = $this->validateObjectType($this->comment
->objectTypeID
);
769 $this->commentProcessor
= $objectType->getProcessor();
770 if (!$this->commentProcessor
->canModerate($this->comment
->objectTypeID
, $this->comment
->objectID
)) {
771 throw new PermissionDeniedException();
776 * Enables a response.
779 * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
781 public function enableResponse()
783 if ($this->comment
=== null) {
784 $this->comment
= \reset
($this->objects
);
786 if ($this->response
=== null) {
787 $this->response
= \reset
($this->parameters
['responses']);
790 if ($this->response
->isDisabled
) {
791 $action = new self([], 'triggerPublicationResponse', [
792 'commentProcessor' => $this->commentProcessor
,
793 'objectTypeID' => $this->comment
->objectTypeID
,
794 'responses' => [$this->response
],
796 $action->executeAction();
799 ModerationQueueActivationManager
::getInstance()->removeModeratedContent(
800 'com.woltlab.wcf.comment.response',
801 [$this->response
->responseID
]
804 return ['responseID' => $this->response
->responseID
];
809 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
811 public function validateBeginEdit()
813 $this->comment
= $this->getSingleObject()->getDecoratedObject();
815 $objectType = ObjectTypeCache
::getInstance()->getObjectType($this->comment
->objectTypeID
);
816 $processor = $objectType->getProcessor();
817 if (!$processor->canEditComment($this->comment
)) {
818 throw new PermissionDeniedException();
821 $this->setDisallowedBBCodes();
826 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
828 public function beginEdit()
830 $upcastProcessor = new HtmlUpcastProcessor();
831 $upcastProcessor->process($this->comment
->message
, 'com.woltlab.wcf.comment');
832 WCF
::getTPL()->assign([
833 'comment' => $this->comment
,
834 'text' => $upcastProcessor->getHtml(),
835 'wysiwygSelector' => 'commentEditor' . $this->comment
->commentID
,
839 'actionName' => 'beginEdit',
840 'template' => WCF
::getTPL()->fetch('commentEditor', 'wcf'),
846 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
848 public function validateSave()
850 $this->validateBeginEdit();
852 $this->validateMessage();
857 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
859 public function save()
861 /** @var HtmlInputProcessor $htmlInputProcessor */
862 $htmlInputProcessor = $this->parameters
['htmlInputProcessor'];
865 'message' => $htmlInputProcessor->getHtml(),
868 $htmlInputProcessor->setObjectID($this->comment
->getObjectID());
869 $hasEmbeddedObjects = MessageEmbeddedObjectManager
::getInstance()->registerObjects($htmlInputProcessor);
870 if ($this->comment
->hasEmbeddedObjects
!= $hasEmbeddedObjects) {
871 $data['hasEmbeddedObjects'] = $this->comment
->hasEmbeddedObjects ?
0 : 1;
874 $action = new self([$this->comment
], 'update', [
877 $action->executeAction();
879 $comment = new Comment($this->comment
->getObjectID());
881 if ($comment->hasEmbeddedObjects
) {
882 MessageEmbeddedObjectManager
::getInstance()->loadObjects(
883 'com.woltlab.wcf.comment',
884 [$comment->getObjectID()]
889 'actionName' => 'save',
890 'message' => $comment->getFormattedMessage(),
895 * Validates parameters to remove a comment or response.
897 * @throws PermissionDeniedException
898 * @throws UserInputException
899 * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
901 public function validateRemove()
903 // validate comment id or response id
905 $this->validateCommentID();
906 } catch (UserInputException
$e) {
908 $this->validateResponseID();
909 } catch (UserInputException
$e) {
910 throw new UserInputException('objectIDs');
914 // validate object type id
915 $objectType = $this->validateObjectType();
917 // validate object id and permissions
918 $this->commentProcessor
= $objectType->getProcessor();
919 if ($this->comment
!== null) {
920 if (!$this->commentProcessor
->canDeleteComment($this->comment
)) {
921 throw new PermissionDeniedException();
924 if (!$this->commentProcessor
->canDeleteResponse($this->response
)) {
925 throw new PermissionDeniedException();
931 * Removes a comment or response.
934 * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
936 public function remove()
938 if ($this->comment
!== null) {
939 $objectAction = new self([$this->comment
], 'delete');
940 $objectAction->executeAction();
942 return ['commentID' => $this->comment
->commentID
];
944 $objectAction = new CommentResponseAction([$this->response
], 'delete');
945 $objectAction->executeAction();
947 return ['responseID' => $this->response
->responseID
];
953 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
955 private function validateGetGuestDialog(): void
957 if (!WCF
::getUser()->userID
) {
958 if (isset($this->parameters
['data']['username'])) {
959 $this->validateUsername();
960 $this->validateCaptcha();
966 * Returns the dialog for guests when they try to write a comment letting
967 * them enter a username and solving a captcha.
969 * @throws SystemException
970 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
972 private function getGuestDialog(): ?
string
974 if (WCF
::getUser()->userID
) {
978 if (isset($this->parameters
['data']['username']) && empty($this->validationErrors
)) {
982 if (!empty($this->validationErrors
)) {
983 if (!empty($this->parameters
['data']['username'])) {
984 WCF
::getSession()->register('username', $this->parameters
['data']['username']);
986 WCF
::getTPL()->assign('errorType', $this->validationErrors
);
989 $captchaObjectType = null;
992 $captchaObjectType = CaptchaHandler
::getInstance()->getObjectTypeByName(CAPTCHA_TYPE
);
993 if ($captchaObjectType === null) {
994 throw new SystemException("Unknown captcha object type with name '" . CAPTCHA_TYPE
. "'");
997 if (!$captchaObjectType->getProcessor()->isAvailable()) {
998 $captchaObjectType = null;
1002 return WCF
::getTPL()->fetch('commentAddGuestDialog', 'wcf', [
1003 'ajaxCaptcha' => true,
1004 'captchaID' => 'commentAdd',
1005 'captchaObjectType' => $captchaObjectType,
1006 'supportsAsyncCaptcha' => true,
1007 'username' => WCF
::getSession()->getVar('username'),
1012 * Renders a comment.
1014 * @param Comment $comment
1015 * @param CommentResponse $response
1016 * @return string|string[]
1017 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1019 protected function renderComment(Comment
$comment, ?CommentResponse
$response = null)
1021 $comment = new StructuredComment($comment);
1022 $comment->setIsDeletable($this->commentProcessor
->canDeleteComment($comment->getDecoratedObject()));
1023 $comment->setIsEditable($this->commentProcessor
->canEditComment($comment->getDecoratedObject()));
1025 if ($comment->hasEmbeddedObjects
) {
1026 MessageEmbeddedObjectManager
::getInstance()->loadObjects(
1027 'com.woltlab.wcf.comment',
1028 [$comment->getObjectID()]
1031 if ($response && $response->hasEmbeddedObjects
) {
1032 MessageEmbeddedObjectManager
::getInstance()->loadObjects(
1033 'com.woltlab.wcf.comment.response',
1034 [$response->getObjectID()]
1038 if ($response !== null) {
1039 // check if response is not visible
1040 /** @var CommentResponse $visibleResponse */
1041 foreach ($comment as $visibleResponse) {
1042 if ($visibleResponse->responseID
== $response->responseID
) {
1049 // This functions renders a single comment without rendering its responses.
1050 // We need to prevent the setting of the data attribute for the last response time
1051 // so that the loading of the responses by the user works correctly.
1052 if ($comment->getDecoratedObject()->responses
) {
1053 WCF
::getTPL()->assign('ignoreLastResponseTime', true);
1056 WCF
::getTPL()->assign([
1057 'commentCanAdd' => $this->commentProcessor
->canAdd(
1058 $comment->getDecoratedObject()->objectID
1060 'commentCanModerate' => $this->commentProcessor
->canModerate(
1061 $comment->getDecoratedObject()->objectTypeID
,
1062 $comment->getDecoratedObject()->objectID
1064 'commentList' => [$comment],
1065 'commentManager' => $this->commentProcessor
,
1071 $commentObjectType = ReactionHandler
::getInstance()->getObjectType('com.woltlab.wcf.comment');
1072 ReactionHandler
::getInstance()->loadLikeObjects($commentObjectType, [$comment->commentID
]);
1073 $likeData['comment'] = ReactionHandler
::getInstance()->getLikeObjects($commentObjectType);
1076 foreach ($comment as $visibleResponse) {
1077 $responseIDs[] = $visibleResponse->responseID
;
1080 if ($response !== null) {
1081 $responseIDs[] = $response->responseID
;
1084 if (!empty($responseIDs)) {
1085 $responseObjectType = ReactionHandler
::getInstance()->getObjectType('com.woltlab.wcf.comment.response');
1086 ReactionHandler
::getInstance()->loadLikeObjects($responseObjectType, $responseIDs);
1087 $likeData['response'] = ReactionHandler
::getInstance()->getLikeObjects($responseObjectType);
1090 WCF
::getTPL()->assign('likeData', $likeData);
1093 $template = WCF
::getTPL()->fetch('commentList');
1094 if ($response === null) {
1099 'template' => $template,
1100 'response' => $this->renderResponse($response),
1105 * Renders a response.
1107 * @param CommentResponse $response
1109 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1111 protected function renderResponse(CommentResponse
$response)
1113 $response = new StructuredCommentResponse($response);
1114 $response->setIsDeletable($this->commentProcessor
->canDeleteResponse($response->getDecoratedObject()));
1115 $response->setIsEditable($this->commentProcessor
->canEditResponse($response->getDecoratedObject()));
1117 if ($response->hasEmbeddedObjects
) {
1118 MessageEmbeddedObjectManager
::getInstance()->loadObjects(
1119 'com.woltlab.wcf.comment.response',
1120 [$response->getObjectID()]
1125 WCF
::getTPL()->assign([
1126 'responseList' => [$response],
1127 'commentCanModerate' => $this->commentProcessor
->canModerate(
1128 $response->getComment()->objectTypeID
,
1129 $response->getComment()->objectID
1131 'commentManager' => $this->commentProcessor
,
1134 return WCF
::getTPL()->fetch('commentResponseList');
1138 * Validates message parameters.
1140 * @throws UserInputException
1141 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1143 protected function validateMessage(bool $isResponse = false)
1145 $this->readString('message', false, 'data');
1146 $this->parameters
['data']['message'] = MessageUtil
::stripCrap($this->parameters
['data']['message']);
1148 if (empty($this->parameters
['data']['message'])) {
1149 throw new UserInputException('message');
1152 CommentHandler
::enforceCensorship($this->parameters
['data']['message']);
1154 $this->setDisallowedBBCodes();
1156 $htmlInputProcessor = new HtmlInputProcessor();
1158 $htmlInputProcessor->process(
1159 $this->parameters
['data']['message'],
1160 'com.woltlab.wcf.comment.response'
1163 $htmlInputProcessor->process(
1164 $this->parameters
['data']['message'],
1165 'com.woltlab.wcf.comment',
1166 $this->comment
!== null ?
$this->comment
->getObjectID() : 0
1170 // search for disallowed bbcodes
1171 $disallowedBBCodes = $htmlInputProcessor->validate();
1172 if (!empty($disallowedBBCodes)) {
1173 throw new UserInputException(
1175 WCF
::getLanguage()->getDynamicVariable(
1176 'wcf.message.error.disallowedBBCodes',
1177 ['disallowedBBCodes' => $disallowedBBCodes]
1182 if ($htmlInputProcessor->appearsToBeEmpty()) {
1183 throw new UserInputException('message');
1186 $commentTextContent = $htmlInputProcessor->getTextContent();
1187 if (\
mb_strlen($commentTextContent) > WCF
::getSession()->getPermission('user.comment.maxLength')) {
1188 throw new UserInputException(
1190 WCF
::getLanguage()->getDynamicVariable(
1191 'wcf.message.error.tooLong',
1192 ['maxTextLength' => WCF
::getSession()->getPermission('user.comment.maxLength')]
1197 $this->parameters
['htmlInputProcessor'] = $htmlInputProcessor;
1201 * Validates object type id parameter.
1203 * @param int $objectTypeID
1204 * @return ObjectType
1205 * @throws UserInputException
1206 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1208 protected function validateObjectType($objectTypeID = null)
1210 if ($objectTypeID === null) {
1211 $this->readInteger('objectTypeID', false, 'data');
1212 $objectTypeID = $this->parameters
['data']['objectTypeID'];
1215 $objectType = ObjectTypeCache
::getInstance()->getObjectType($objectTypeID);
1216 if ($objectType === null) {
1217 throw new UserInputException('objectTypeID');
1219 if ($objectType->getDefinition()->definitionName
!== 'com.woltlab.wcf.comment.commentableContent') {
1220 throw new UserInputException('objectTypeID');
1227 * Validates comment id parameter.
1229 * @throws UserInputException
1230 * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1232 protected function validateCommentID()
1234 $this->readInteger('commentID', false, 'data');
1236 $this->comment
= new Comment($this->parameters
['data']['commentID']);
1237 if ($this->comment
=== null ||
!$this->comment
->commentID
) {
1238 throw new UserInputException('commentID');
1243 * Validates response id parameter.
1245 * @throws UserInputException
1246 * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1248 protected function validateResponseID()
1250 if (isset($this->parameters
['data']['responseID'])) {
1251 $this->response
= new CommentResponse($this->parameters
['data']['responseID']);
1253 if ($this->response
=== null ||
!$this->response
->responseID
) {
1254 throw new UserInputException('responseID');
1259 * Validates the username parameter.
1260 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1262 protected function validateUsername()
1264 if (WCF
::getUser()->userID
) {
1269 $this->readString('username', false, 'data');
1271 if (!UserRegistrationUtil
::isValidUsername($this->parameters
['data']['username'])) {
1272 throw new UserInputException('username', 'invalid');
1274 if (User
::getUserByUsername($this->parameters
['data']['username'])->userID
) {
1275 throw new UserInputException('username', 'notUnique');
1277 } catch (UserInputException
$e) {
1278 $this->validationErrors
['username'] = $e->getType();
1283 * Validates the captcha challenge.
1285 * @throws SystemException
1286 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1288 protected function validateCaptcha()
1290 if (WCF
::getUser()->userID
) {
1295 $this->captchaObjectType
= CaptchaHandler
::getInstance()->getObjectTypeByName(CAPTCHA_TYPE
);
1296 if ($this->captchaObjectType
=== null) {
1297 throw new SystemException("Unknown captcha object type with name '" . CAPTCHA_TYPE
. "'");
1300 if (!$this->captchaObjectType
->getProcessor()->isAvailable()) {
1301 $this->captchaObjectType
= null;
1305 if ($this->captchaObjectType
=== null) {
1310 $this->captchaObjectType
->getProcessor()->readFormParameters();
1311 $this->captchaObjectType
->getProcessor()->validate();
1312 } catch (UserInputException
$e) {
1313 $this->validationErrors
= \array_merge
($this->validationErrors
, [$e->getField() => $e->getType()]);
1318 * Sets the list of disallowed bbcodes for comments.
1319 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1321 protected function setDisallowedBBCodes()
1323 BBCodeHandler
::getInstance()->setDisallowedBBCodes(\
explode(
1325 WCF
::getSession()->getPermission('user.comment.disallowedBBCodes')
1330 * Returns the current html input processor or a new one if `$message` is not null.
1332 * @param string|null $message source message
1333 * @param int $objectID object id
1334 * @return HtmlInputProcessor
1335 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1337 public function getHtmlInputProcessor($message = null, $objectID = 0)
1339 if ($message === null) {
1340 return $this->htmlInputProcessor
;
1343 $this->htmlInputProcessor
= new HtmlInputProcessor();
1344 $this->htmlInputProcessor
->process($message, 'com.woltlab.wcf.comment', $objectID);
1346 return $this->htmlInputProcessor
;
1350 * Returns the comment object.
1353 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1355 public function getComment()
1357 return $this->comment
;
1361 * Returns the comment response object.
1363 * @return CommentResponse
1364 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1366 public function getResponse()
1368 return $this->response
;
1372 * Returns the comment manager.
1374 * @return ICommentManager
1375 * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend
1377 public function getCommentManager()
1379 return $this->commentProcessor
;