Commit | Line | Data |
---|---|---|
285b1d92 | 1 | <?php |
a9229942 | 2 | |
285b1d92 | 3 | namespace wcf\data\comment; |
a9229942 TD |
4 | |
5 | use wcf\data\AbstractDatabaseObjectAction; | |
285b1d92 MW |
6 | use wcf\data\comment\response\CommentResponse; |
7 | use wcf\data\comment\response\CommentResponseAction; | |
8 | use wcf\data\comment\response\CommentResponseEditor; | |
285b1d92 | 9 | use wcf\data\comment\response\StructuredCommentResponse; |
a9229942 | 10 | use wcf\data\IMessageInlineEditorAction; |
ce207cd8 | 11 | use wcf\data\object\type\ObjectType; |
285b1d92 | 12 | use wcf\data\object\type\ObjectTypeCache; |
3552067d | 13 | use wcf\data\user\User; |
38cc47a0 | 14 | use wcf\event\message\MessageSpamChecking; |
3e712fe3 | 15 | use wcf\system\bbcode\BBCodeHandler; |
96714cab | 16 | use wcf\system\captcha\CaptchaHandler; |
371ae274 | 17 | use wcf\system\comment\CommentHandler; |
a9229942 | 18 | use wcf\system\comment\manager\ICommentManager; |
38cc47a0 | 19 | use wcf\system\event\EventHandler; |
7c81eb93 | 20 | use wcf\system\exception\NamedUserException; |
285b1d92 | 21 | use wcf\system\exception\PermissionDeniedException; |
7295e995 | 22 | use wcf\system\exception\SystemException; |
285b1d92 | 23 | use wcf\system\exception\UserInputException; |
aba69968 | 24 | use wcf\system\flood\FloodControl; |
3e712fe3 | 25 | use wcf\system\html\input\HtmlInputProcessor; |
6abbfb9b | 26 | use wcf\system\html\upcast\HtmlUpcastProcessor; |
aa950db3 | 27 | use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; |
6f351423 | 28 | use wcf\system\moderation\queue\ModerationQueueActivationManager; |
0add3703 | 29 | use wcf\system\reaction\ReactionHandler; |
285b1d92 | 30 | use wcf\system\user\activity\event\UserActivityEventHandler; |
a9229942 TD |
31 | use wcf\system\user\notification\object\CommentResponseUserNotificationObject; |
32 | use wcf\system\user\notification\object\CommentUserNotificationObject; | |
8e38b649 | 33 | use wcf\system\user\notification\object\type\ICommentUserNotificationObjectType; |
371ae274 | 34 | use wcf\system\user\notification\object\type\IMultiRecipientCommentUserNotificationObjectType; |
285b1d92 MW |
35 | use wcf\system\user\notification\UserNotificationHandler; |
36 | use wcf\system\WCF; | |
81c3ee0e | 37 | use wcf\util\MessageUtil; |
dd07c150 | 38 | use wcf\util\UserRegistrationUtil; |
38cc47a0 | 39 | use wcf\util\UserUtil; |
285b1d92 MW |
40 | |
41 | /** | |
42 | * Executes comment-related actions. | |
a9229942 TD |
43 | * |
44 | * @author Alexander Ebert | |
45 | * @copyright 2001-2020 WoltLab GmbH | |
46 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> | |
a9229942 TD |
47 | * |
48 | * @method Comment create() | |
49 | * @method CommentEditor[] getObjects() | |
50 | * @method CommentEditor getSingleObject() | |
285b1d92 | 51 | */ |
a9229942 TD |
52 | class CommentAction extends AbstractDatabaseObjectAction implements IMessageInlineEditorAction |
53 | { | |
54 | /** | |
55 | * @inheritDoc | |
56 | */ | |
57 | protected $allowGuestAccess = [ | |
58 | 'addComment', | |
59 | 'addResponse', | |
60 | 'loadComment', | |
61 | 'loadComments', | |
62 | 'loadResponse', | |
a9229942 TD |
63 | ]; |
64 | ||
65 | /** | |
66 | * captcha object type used for comments | |
67 | * @var ObjectType | |
64c94219 | 68 | * @deprecated 6.1 |
a9229942 TD |
69 | */ |
70 | public $captchaObjectType; | |
71 | ||
72 | /** | |
73 | * @inheritDoc | |
74 | */ | |
75 | protected $className = CommentEditor::class; | |
76 | ||
77 | /** | |
78 | * comment object | |
79 | * @var Comment | |
64c94219 | 80 | * @deprecated 6.1 |
a9229942 TD |
81 | */ |
82 | protected $comment; | |
83 | ||
84 | /** | |
85 | * comment processor | |
86 | * @var ICommentManager | |
64c94219 | 87 | * @deprecated 6.1 |
a9229942 TD |
88 | */ |
89 | protected $commentProcessor; | |
90 | ||
91 | /** | |
92 | * @var HtmlInputProcessor | |
64c94219 | 93 | * @deprecated 6.1 |
a9229942 TD |
94 | */ |
95 | protected $htmlInputProcessor; | |
96 | ||
97 | /** | |
98 | * response object | |
99 | * @var CommentResponse | |
64c94219 | 100 | * @deprecated 6.1 |
a9229942 TD |
101 | */ |
102 | protected $response; | |
103 | ||
104 | /** | |
105 | * comment object created by addComment() | |
106 | * @var Comment | |
64c94219 | 107 | * @deprecated 6.1 |
a9229942 TD |
108 | */ |
109 | public $createdComment; | |
110 | ||
111 | /** | |
112 | * response object created by addResponse() | |
113 | * @var CommentResponse | |
64c94219 | 114 | * @deprecated 6.1 |
a9229942 TD |
115 | */ |
116 | public $createdResponse; | |
117 | ||
118 | /** | |
119 | * errors occurring through the validation of addComment or addResponse | |
120 | * @var array | |
64c94219 | 121 | * @deprecated 6.1 |
a9229942 TD |
122 | */ |
123 | public $validationErrors = []; | |
124 | ||
a9229942 TD |
125 | /** |
126 | * Validates parameters to load comments. | |
127 | * | |
128 | * @throws PermissionDeniedException | |
1b1ee406 | 129 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
130 | */ |
131 | public function validateLoadComments() | |
132 | { | |
133 | $this->readInteger('lastCommentTime', false, 'data'); | |
134 | $this->readInteger('objectID', false, 'data'); | |
135 | ||
136 | $objectType = $this->validateObjectType(); | |
137 | $this->commentProcessor = $objectType->getProcessor(); | |
138 | if (!$this->commentProcessor->isAccessible($this->parameters['data']['objectID'])) { | |
139 | throw new PermissionDeniedException(); | |
140 | } | |
141 | } | |
142 | ||
143 | /** | |
144 | * Returns parsed comments. | |
145 | * | |
146 | * @return array | |
1b1ee406 | 147 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
148 | */ |
149 | public function loadComments() | |
150 | { | |
151 | $commentList = CommentHandler::getInstance()->getCommentList( | |
152 | $this->commentProcessor, | |
153 | $this->parameters['data']['objectTypeID'], | |
154 | $this->parameters['data']['objectID'], | |
155 | false | |
156 | ); | |
157 | $commentList->getConditionBuilder()->add("comment.time < ?", [$this->parameters['data']['lastCommentTime']]); | |
158 | $commentList->readObjects(); | |
159 | ||
160 | // mark notifications for loaded comments as read | |
161 | CommentHandler::getInstance()->markNotificationsAsConfirmedForComments( | |
162 | CommentHandler::getInstance()->getObjectType($this->parameters['data']['objectTypeID'])->objectType, | |
163 | $commentList->getObjects() | |
164 | ); | |
165 | ||
166 | WCF::getTPL()->assign([ | |
167 | 'commentList' => $commentList, | |
168 | 'likeData' => MODULE_LIKE ? $commentList->getLikeData() : [], | |
169 | ]); | |
170 | ||
171 | return [ | |
172 | 'lastCommentTime' => $commentList->getMinCommentTime(), | |
173 | 'template' => WCF::getTPL()->fetch('commentList'), | |
174 | ]; | |
175 | } | |
176 | ||
177 | /** | |
178 | * Validates the `loadComment` action. | |
179 | * | |
180 | * @throws PermissionDeniedException | |
181 | * @since 3.1 | |
1b1ee406 | 182 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
183 | */ |
184 | public function validateLoadComment() | |
185 | { | |
66ce0f8c | 186 | $this->readInteger('responseID', true); |
27c1494a | 187 | $this->readInteger('objectTypeID', true); |
66ce0f8c | 188 | $this->comment = $this->getSingleObject()->getDecoratedObject(); |
27c1494a MW |
189 | if (!empty($this->parameters['objectTypeID']) && $this->parameters['objectTypeID'] !== $this->comment->objectTypeID) { |
190 | throw new UserInputException('objectTypeID'); | |
191 | } | |
192 | ||
66ce0f8c | 193 | $objectType = ObjectTypeCache::getInstance()->getObjectType($this->comment->objectTypeID); |
a9229942 | 194 | $this->commentProcessor = $objectType->getProcessor(); |
66ce0f8c MW |
195 | if (!$this->commentProcessor->isAccessible($this->comment->objectID)) { |
196 | throw new PermissionDeniedException(); | |
197 | } | |
198 | if ($this->comment->isDisabled && !$this->commentProcessor->canModerate($this->comment->objectTypeID, $this->comment->objectID)) { | |
a9229942 TD |
199 | throw new PermissionDeniedException(); |
200 | } | |
201 | ||
66ce0f8c MW |
202 | if (!empty($this->parameters['responseID'])) { |
203 | $this->response = new CommentResponse($this->parameters['responseID']); | |
a9229942 | 204 | if (!$this->response->responseID) { |
66ce0f8c MW |
205 | throw new UserInputException('responseID'); |
206 | } | |
207 | if ($this->response->commentID != $this->comment->commentID) { | |
208 | throw new PermissionDeniedException(); | |
209 | } | |
210 | if ($this->response->isDisabled && !$this->commentProcessor->canModerate($this->comment->objectTypeID, $this->comment->objectID)) { | |
211 | throw new PermissionDeniedException(); | |
a9229942 TD |
212 | } |
213 | } | |
214 | } | |
215 | ||
216 | /** | |
217 | * Returns a rendered comment. | |
218 | * | |
219 | * @return string[] | |
220 | * @since 3.1 | |
1b1ee406 | 221 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
222 | */ |
223 | public function loadComment() | |
224 | { | |
a9229942 | 225 | // mark notifications for loaded comment/response as read |
66ce0f8c | 226 | $objectType = CommentHandler::getInstance()->getObjectType($this->comment->objectTypeID)->objectType; |
a9229942 TD |
227 | if ($this->response === null) { |
228 | CommentHandler::getInstance()->markNotificationsAsConfirmedForComments( | |
229 | $objectType, | |
230 | [new StructuredComment($this->comment)] | |
231 | ); | |
232 | } else { | |
233 | CommentHandler::getInstance()->markNotificationsAsConfirmedForResponses( | |
234 | $objectType, | |
235 | [$this->response] | |
236 | ); | |
237 | } | |
238 | ||
239 | $returnValues = $this->renderComment($this->comment, $this->response); | |
240 | ||
241 | return (\is_array($returnValues)) ? $returnValues : ['template' => $returnValues]; | |
242 | } | |
243 | ||
244 | /** | |
245 | * Validates the `loadResponse` action. | |
246 | * | |
247 | * @since 3.1 | |
1b1ee406 | 248 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
249 | */ |
250 | public function validateLoadResponse() | |
251 | { | |
d281434b | 252 | $this->readInteger('responseID'); |
27c1494a | 253 | $this->readInteger('objectTypeID', true); |
66ce0f8c | 254 | $this->response = new CommentResponse($this->parameters['responseID']); |
d281434b MW |
255 | if (!$this->response->responseID) { |
256 | throw new UserInputException('responseID'); | |
257 | } | |
258 | ||
66ce0f8c | 259 | $this->comment = $this->response->getComment(); |
27c1494a MW |
260 | if (!empty($this->parameters['objectTypeID']) && $this->parameters['objectTypeID'] !== $this->comment->objectTypeID) { |
261 | throw new UserInputException('objectTypeID'); | |
262 | } | |
263 | ||
66ce0f8c MW |
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(); | |
268 | } | |
a9229942 TD |
269 | } |
270 | ||
271 | /** | |
66ce0f8c | 272 | * Returns a rendered response. |
a9229942 TD |
273 | * |
274 | * @return string[] | |
275 | * @since 3.1 | |
1b1ee406 | 276 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
277 | */ |
278 | public function loadResponse() | |
279 | { | |
a9229942 TD |
280 | return [ |
281 | 'template' => $this->renderResponse($this->response), | |
282 | ]; | |
283 | } | |
284 | ||
285 | /** | |
286 | * Validates parameters to add a comment. | |
287 | * | |
288 | * @throws PermissionDeniedException | |
1b1ee406 | 289 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
290 | */ |
291 | public function validateAddComment() | |
292 | { | |
293 | try { | |
294 | CommentHandler::enforceFloodControl(); | |
295 | } catch (NamedUserException $e) { | |
296 | throw new UserInputException('message', $e->getMessage()); | |
297 | } | |
298 | ||
299 | $this->readInteger('objectID', false, 'data'); | |
199a6b01 | 300 | $this->validateGetGuestDialog(); |
a9229942 TD |
301 | |
302 | $this->validateMessage(); | |
303 | $objectType = $this->validateObjectType(); | |
304 | ||
305 | // validate object id and permissions | |
306 | $this->commentProcessor = $objectType->getProcessor(); | |
307 | if (!$this->commentProcessor->canAdd($this->parameters['data']['objectID'])) { | |
308 | throw new PermissionDeniedException(); | |
309 | } | |
38cc47a0 MW |
310 | |
311 | $event = new MessageSpamChecking( | |
312 | $this->parameters['htmlInputProcessor'], | |
313 | WCF::getUser()->userID ? WCF::getUser() : null, | |
314 | UserUtil::getIpAddress(), | |
315 | ); | |
316 | EventHandler::getInstance()->fire($event); | |
317 | if ($event->defaultPrevented()) { | |
318 | throw new PermissionDeniedException(); | |
319 | } | |
a9229942 TD |
320 | } |
321 | ||
322 | /** | |
323 | * Adds a comment. | |
324 | * | |
325 | * @return string[] | |
1b1ee406 | 326 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
327 | */ |
328 | public function addComment() | |
329 | { | |
199a6b01 MW |
330 | $guestDialog = $this->getGuestDialog(); |
331 | if ($guestDialog) { | |
a9229942 | 332 | return [ |
199a6b01 | 333 | 'guestDialog' => $guestDialog, |
a9229942 TD |
334 | ]; |
335 | } | |
336 | ||
337 | /** @var HtmlInputProcessor $htmlInputProcessor */ | |
338 | $htmlInputProcessor = $this->parameters['htmlInputProcessor']; | |
339 | ||
340 | // create comment | |
341 | $this->createdComment = CommentEditor::create([ | |
342 | 'objectTypeID' => $this->parameters['data']['objectTypeID'], | |
343 | 'objectID' => $this->parameters['data']['objectID'], | |
344 | 'time' => TIME_NOW, | |
345 | 'userID' => WCF::getUser()->userID ?: null, | |
346 | 'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'], | |
347 | 'message' => $htmlInputProcessor->getHtml(), | |
348 | 'responses' => 0, | |
349 | 'responseIDs' => \serialize([]), | |
350 | 'enableHtml' => 1, | |
351 | 'isDisabled' => $this->commentProcessor->canAddWithoutApproval($this->parameters['data']['objectID']) ? 0 : 1, | |
352 | ]); | |
353 | ||
354 | if (!$this->createdComment->isDisabled) { | |
355 | $action = new self([$this->createdComment], 'triggerPublication', [ | |
356 | 'commentProcessor' => $this->commentProcessor, | |
357 | ]); | |
358 | $action->executeAction(); | |
359 | } else { | |
360 | // mark comment for moderated content | |
361 | ModerationQueueActivationManager::getInstance()->addModeratedContent( | |
362 | 'com.woltlab.wcf.comment.comment', | |
363 | $this->createdComment->commentID | |
364 | ); | |
365 | } | |
366 | ||
aa950db3 MS |
367 | $htmlInputProcessor->setObjectID($this->createdComment->getObjectID()); |
368 | if (MessageEmbeddedObjectManager::getInstance()->registerObjects($htmlInputProcessor)) { | |
369 | (new CommentEditor($this->createdComment))->update([ | |
370 | 'hasEmbeddedObjects' => 1, | |
371 | ]); | |
372 | $this->createdComment = new Comment($this->createdComment->getObjectID()); | |
373 | } | |
374 | ||
a9229942 TD |
375 | FloodControl::getInstance()->registerContent('com.woltlab.wcf.comment'); |
376 | ||
377 | if (!$this->createdComment->userID) { | |
378 | // save user name is session | |
379 | WCF::getSession()->register('username', $this->createdComment->username); | |
380 | ||
381 | // save last comment time for flood control | |
382 | WCF::getSession()->register('lastCommentTime', $this->createdComment->time); | |
383 | ||
384 | // reset captcha for future requests | |
385 | if ($this->captchaObjectType) { | |
386 | $this->captchaObjectType->getProcessor()->reset(); | |
387 | } | |
388 | } | |
389 | ||
390 | return [ | |
391 | 'template' => $this->renderComment($this->createdComment), | |
392 | ]; | |
393 | } | |
394 | ||
64c94219 | 395 | /** |
1b1ee406 | 396 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
64c94219 | 397 | */ |
a9229942 TD |
398 | public function triggerPublication() |
399 | { | |
400 | if (!empty($this->parameters['commentProcessor'])) { | |
401 | $objectType = null; | |
402 | if (!empty($this->objects)) { | |
403 | /** @var Comment $comment */ | |
404 | $comment = \reset($this->objects); | |
405 | $objectType = $this->validateObjectType($comment->objectTypeID); | |
406 | } | |
407 | ||
408 | $this->commentProcessor = $this->parameters['commentProcessor']; | |
409 | } else { | |
410 | $objectType = $this->validateObjectType($this->parameters['objectTypeID']); | |
411 | $this->commentProcessor = $objectType->getProcessor(); | |
412 | } | |
413 | ||
414 | /** @var CommentEditor $comment */ | |
415 | foreach ($this->objects as $comment) { | |
416 | // update counter | |
417 | $comment->update(['isDisabled' => 0]); | |
418 | $this->commentProcessor->updateCounter($comment->objectID, 1); | |
419 | ||
420 | // fire activity event | |
421 | if ($comment->userID && UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType . '.recentActivityEvent')) { | |
422 | UserActivityEventHandler::getInstance()->fireEvent( | |
423 | $objectType->objectType . '.recentActivityEvent', | |
424 | $comment->commentID, | |
425 | null, | |
426 | $comment->userID, | |
427 | $comment->time | |
428 | ); | |
429 | } | |
430 | ||
431 | // fire notification event | |
3725f84b | 432 | if (UserNotificationHandler::getInstance()->getEvent($objectType->objectType . '.notification', 'comment')) { |
a9229942 TD |
433 | $notificationObject = new CommentUserNotificationObject($comment->getDecoratedObject()); |
434 | $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor($objectType->objectType . '.notification'); | |
435 | ||
436 | if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType) { | |
437 | $recipientIDs = $notificationObjectType->getRecipientIDs($comment->getDecoratedObject()); | |
a9229942 | 438 | } else { |
a77b39d0 | 439 | $recipientIDs = []; |
a9229942 | 440 | } |
c069a1b0 | 441 | |
bb329797 MW |
442 | if ($notificationObjectType instanceof ICommentUserNotificationObjectType) { |
443 | $recipientIDs[] = $notificationObjectType->getOwnerID($comment->commentID); | |
444 | } | |
a77b39d0 | 445 | |
59cb802b TD |
446 | // make sure that the comment's author gets no notification |
447 | $recipientIDs = \array_diff($recipientIDs, [$comment->getUserID()]); | |
448 | ||
c069a1b0 TD |
449 | UserNotificationHandler::getInstance()->fireEvent( |
450 | 'comment', | |
451 | $objectType->objectType . '.notification', | |
452 | $notificationObject, | |
453 | $recipientIDs | |
454 | ); | |
a9229942 TD |
455 | } |
456 | } | |
457 | } | |
458 | ||
459 | /** | |
460 | * Validates parameters to add a response. | |
461 | * | |
462 | * @throws PermissionDeniedException | |
1b1ee406 | 463 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
464 | */ |
465 | public function validateAddResponse() | |
466 | { | |
467 | try { | |
468 | CommentHandler::enforceFloodControl(); | |
469 | } catch (NamedUserException $e) { | |
470 | throw new UserInputException('message', $e->getMessage()); | |
471 | } | |
472 | ||
bc83b316 | 473 | $comment = $this->getSingleObject(); |
bc83b316 | 474 | $objectType = ObjectTypeCache::getInstance()->getObjectType($comment->objectTypeID); |
a9229942 | 475 | $this->commentProcessor = $objectType->getProcessor(); |
bc83b316 | 476 | if (!$this->commentProcessor->canAdd($comment->objectID)) { |
a9229942 TD |
477 | throw new PermissionDeniedException(); |
478 | } | |
479 | ||
3334053d | 480 | if ($comment->isDisabled && !$this->commentProcessor->canModerate($comment->objectTypeID, $comment->objectID)) { |
a9229942 TD |
481 | throw new PermissionDeniedException(); |
482 | } | |
3334053d | 483 | |
bc83b316 MW |
484 | $this->validateGetGuestDialog(); |
485 | $this->validateMessage(true); | |
38cc47a0 MW |
486 | |
487 | $event = new MessageSpamChecking( | |
488 | $this->parameters['htmlInputProcessor'], | |
489 | WCF::getUser()->userID ? WCF::getUser() : null, | |
490 | UserUtil::getIpAddress(), | |
491 | ); | |
492 | EventHandler::getInstance()->fire($event); | |
493 | if ($event->defaultPrevented()) { | |
494 | throw new PermissionDeniedException(); | |
495 | } | |
a9229942 TD |
496 | } |
497 | ||
498 | /** | |
499 | * Adds a response. | |
500 | * | |
501 | * @return array | |
1b1ee406 | 502 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
503 | */ |
504 | public function addResponse() | |
505 | { | |
bc83b316 MW |
506 | $guestDialog = $this->getGuestDialog(); |
507 | if ($guestDialog) { | |
a9229942 | 508 | return [ |
bc83b316 | 509 | 'guestDialog' => $guestDialog, |
a9229942 TD |
510 | ]; |
511 | } | |
512 | ||
bc83b316 MW |
513 | $comment = $this->getSingleObject(); |
514 | ||
a9229942 TD |
515 | /** @var HtmlInputProcessor $htmlInputProcessor */ |
516 | $htmlInputProcessor = $this->parameters['htmlInputProcessor']; | |
517 | ||
518 | // create response | |
519 | $this->createdResponse = CommentResponseEditor::create([ | |
bc83b316 | 520 | 'commentID' => $comment->commentID, |
a9229942 TD |
521 | 'time' => TIME_NOW, |
522 | 'userID' => WCF::getUser()->userID ?: null, | |
523 | 'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'], | |
524 | 'message' => $htmlInputProcessor->getHtml(), | |
525 | 'enableHtml' => 1, | |
bc83b316 | 526 | 'isDisabled' => $this->commentProcessor->canAddWithoutApproval($comment->objectID) ? 0 : 1, |
a9229942 | 527 | ]); |
bc83b316 | 528 | $this->createdResponse->setComment($comment->getDecoratedObject()); |
a9229942 | 529 | |
aa950db3 MS |
530 | $htmlInputProcessor->setObjectID($this->createdResponse->getObjectID()); |
531 | if (MessageEmbeddedObjectManager::getInstance()->registerObjects($htmlInputProcessor)) { | |
532 | (new CommentResponseEditor($this->createdResponse))->update([ | |
533 | 'hasEmbeddedObjects' => 1, | |
534 | ]); | |
535 | $this->createdResponse = new CommentResponse($this->createdResponse->getObjectID()); | |
536 | } | |
537 | ||
a9229942 | 538 | // update response data |
bc83b316 | 539 | $unfilteredResponseIDs = $comment->getUnfilteredResponseIDs(); |
a9229942 TD |
540 | if (\count($unfilteredResponseIDs) < 5) { |
541 | $unfilteredResponseIDs[] = $this->createdResponse->responseID; | |
542 | } | |
bc83b316 | 543 | $unfilteredResponses = $comment->unfilteredResponses + 1; |
a9229942 TD |
544 | |
545 | // update comment | |
bc83b316 | 546 | $comment->update([ |
a9229942 TD |
547 | 'unfilteredResponseIDs' => \serialize($unfilteredResponseIDs), |
548 | 'unfilteredResponses' => $unfilteredResponses, | |
549 | ]); | |
550 | ||
551 | if (!$this->createdResponse->isDisabled) { | |
552 | $action = new self([], 'triggerPublicationResponse', [ | |
553 | 'commentProcessor' => $this->commentProcessor, | |
554 | 'responses' => [$this->createdResponse], | |
555 | ]); | |
556 | $action->executeAction(); | |
557 | } else { | |
558 | // mark response for moderated content | |
559 | ModerationQueueActivationManager::getInstance()->addModeratedContent( | |
560 | 'com.woltlab.wcf.comment.response', | |
561 | $this->createdResponse->responseID | |
562 | ); | |
563 | } | |
564 | ||
565 | FloodControl::getInstance()->registerContent('com.woltlab.wcf.comment'); | |
566 | ||
567 | if (!$this->createdResponse->userID) { | |
568 | // save user name is session | |
569 | WCF::getSession()->register('username', $this->createdResponse->username); | |
570 | ||
571 | // save last comment time for flood control | |
572 | WCF::getSession()->register('lastCommentTime', $this->createdResponse->time); | |
573 | ||
574 | // reset captcha for future requests | |
575 | if ($this->captchaObjectType) { | |
576 | $this->captchaObjectType->getProcessor()->reset(); | |
577 | } | |
578 | } | |
579 | ||
bc83b316 | 580 | $responses = $comment->responses; |
a9229942 TD |
581 | if ( |
582 | $this->commentProcessor->canModerate( | |
bc83b316 MW |
583 | $comment->objectTypeID, |
584 | $comment->objectID | |
a9229942 TD |
585 | ) |
586 | ) { | |
bc83b316 | 587 | $responses = $comment->unfilteredResponses; |
a9229942 TD |
588 | } |
589 | ||
590 | return [ | |
bc83b316 | 591 | 'commentID' => $comment->commentID, |
a9229942 TD |
592 | 'template' => $this->renderResponse($this->createdResponse), |
593 | 'responses' => $responses + 1, | |
594 | ]; | |
595 | } | |
596 | ||
597 | /** | |
598 | * Publishes a response. | |
1b1ee406 | 599 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
600 | */ |
601 | public function triggerPublicationResponse() | |
602 | { | |
603 | if (!empty($this->parameters['commentProcessor'])) { | |
604 | $objectType = null; | |
605 | if (!empty($this->parameters['responses'])) { | |
606 | /** @var CommentResponse $response */ | |
607 | $response = \reset($this->parameters['responses']); | |
608 | $objectType = $this->validateObjectType($response->getComment()->objectTypeID); | |
609 | } | |
610 | ||
611 | $this->commentProcessor = $this->parameters['commentProcessor']; | |
612 | } else { | |
613 | $objectType = $this->validateObjectType($this->parameters['objectTypeID']); | |
614 | $this->commentProcessor = $objectType->getProcessor(); | |
615 | } | |
616 | ||
617 | /** @var CommentResponse $response */ | |
618 | foreach ($this->parameters['responses'] as $response) { | |
619 | (new CommentResponseEditor($response))->update(['isDisabled' => 0]); | |
620 | ||
621 | $comment = $response->getComment(); | |
622 | ||
623 | // update response count | |
624 | $commentEditor = new CommentEditor($comment); | |
625 | $commentEditor->updateCounters(['responses' => 1]); | |
626 | ||
627 | // do not prepend the response id as the approved response can appear anywhere | |
628 | $commentEditor->updateResponseIDs(); | |
629 | ||
630 | // update counter | |
631 | $this->commentProcessor->updateCounter($comment->objectID, 1); | |
632 | ||
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, | |
638 | null, | |
639 | $response->userID, | |
640 | $response->time | |
641 | ); | |
642 | } | |
643 | ||
644 | // fire notification event | |
4be8f184 TD |
645 | if ( |
646 | UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType . '.notification') | |
647 | && ( | |
648 | UserNotificationHandler::getInstance()->getEvent($objectType->objectType . '.response.notification', 'commentResponse') | |
649 | || UserNotificationHandler::getInstance()->getEvent($objectType->objectType . '.response.notification', 'commentResponseOwner') | |
650 | ) | |
651 | ) { | |
a9229942 | 652 | $notificationObject = new CommentResponseUserNotificationObject($response); |
3f10b1a2 | 653 | $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor($objectType->objectType . '.notification'); |
a9229942 TD |
654 | |
655 | if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType) { | |
656 | $recipientIDs = $notificationObjectType->getRecipientIDs($comment); | |
a9229942 | 657 | } else { |
8805008c | 658 | $recipientIDs = []; |
a9229942 | 659 | } |
3cabe141 | 660 | |
8805008c TD |
661 | $recipientIDs[] = $comment->userID; |
662 | ||
bb329797 MW |
663 | $userID = 0; |
664 | if ($notificationObjectType instanceof ICommentUserNotificationObjectType) { | |
665 | $userID = $notificationObjectType->getOwnerID($comment->commentID); | |
666 | } | |
c9bba0eb | 667 | |
23de7582 TD |
668 | // make sure that the response's author gets no notification |
669 | $recipientIDs = \array_diff($recipientIDs, [$response->getUserID()]); | |
670 | ||
4be8f184 TD |
671 | if (UserNotificationHandler::getInstance()->getEvent($objectType->objectType . '.response.notification', 'commentResponse')) { |
672 | UserNotificationHandler::getInstance()->fireEvent( | |
673 | 'commentResponse', | |
674 | $objectType->objectType . '.response.notification', | |
675 | $notificationObject, | |
676 | $recipientIDs, | |
677 | [ | |
678 | 'commentID' => $comment->commentID, | |
679 | 'objectID' => $comment->objectID, | |
680 | 'userID' => $comment->userID, | |
681 | ] | |
682 | ); | |
683 | } | |
c9bba0eb TD |
684 | |
685 | // notify the container owner | |
4be8f184 | 686 | if (UserNotificationHandler::getInstance()->getEvent($objectType->objectType . '.response.notification', 'commentResponseOwner')) { |
bb329797 | 687 | if ($userID && $userID != $comment->userID && $userID != $response->getUserID()) { |
c9bba0eb TD |
688 | UserNotificationHandler::getInstance()->fireEvent( |
689 | 'commentResponseOwner', | |
690 | $objectType->objectType . '.response.notification', | |
691 | $notificationObject, | |
692 | [$userID], | |
693 | [ | |
694 | 'commentID' => $comment->commentID, | |
695 | 'objectID' => $comment->objectID, | |
696 | 'objectUserID' => $userID, | |
697 | 'userID' => $comment->userID, | |
698 | ] | |
699 | ); | |
700 | } | |
701 | } | |
a9229942 TD |
702 | } |
703 | } | |
704 | } | |
705 | ||
706 | /** | |
707 | * Validates the `enable` action. | |
708 | * | |
709 | * @throws PermissionDeniedException | |
1b1ee406 | 710 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
711 | */ |
712 | public function validateEnable() | |
713 | { | |
714 | $this->comment = $this->getSingleObject()->getDecoratedObject(); | |
715 | ||
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(); | |
720 | } | |
721 | } | |
722 | ||
723 | /** | |
724 | * Enables a comment. | |
725 | * | |
726 | * @return int[] | |
1b1ee406 | 727 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
728 | */ |
729 | public function enable() | |
730 | { | |
731 | if ($this->comment === null) { | |
732 | $this->comment = \reset($this->objects); | |
733 | } | |
734 | ||
735 | if ($this->comment->isDisabled) { | |
736 | $action = new self([$this->comment], 'triggerPublication', [ | |
737 | 'commentProcessor' => $this->commentProcessor, | |
738 | 'objectTypeID' => $this->comment->objectTypeID, | |
739 | ]); | |
740 | $action->executeAction(); | |
741 | } | |
742 | ||
743 | ModerationQueueActivationManager::getInstance()->removeModeratedContent( | |
744 | 'com.woltlab.wcf.comment.comment', | |
745 | [$this->comment->commentID] | |
746 | ); | |
747 | ||
748 | return ['commentID' => $this->comment->commentID]; | |
749 | } | |
750 | ||
751 | /** | |
752 | * Validates the `enableResponse` action. | |
753 | * | |
754 | * @throws PermissionDeniedException | |
755 | * @throws UserInputException | |
1b1ee406 | 756 | * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
757 | */ |
758 | public function validateEnableResponse() | |
759 | { | |
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'); | |
764 | } | |
765 | ||
766 | $this->comment = $this->response->getComment(); | |
767 | ||
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(); | |
772 | } | |
773 | } | |
774 | ||
775 | /** | |
776 | * Enables a response. | |
777 | * | |
778 | * @return int[] | |
1b1ee406 | 779 | * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
780 | */ |
781 | public function enableResponse() | |
782 | { | |
783 | if ($this->comment === null) { | |
784 | $this->comment = \reset($this->objects); | |
785 | } | |
786 | if ($this->response === null) { | |
787 | $this->response = \reset($this->parameters['responses']); | |
788 | } | |
789 | ||
790 | if ($this->response->isDisabled) { | |
791 | $action = new self([], 'triggerPublicationResponse', [ | |
792 | 'commentProcessor' => $this->commentProcessor, | |
793 | 'objectTypeID' => $this->comment->objectTypeID, | |
794 | 'responses' => [$this->response], | |
795 | ]); | |
796 | $action->executeAction(); | |
797 | } | |
798 | ||
799 | ModerationQueueActivationManager::getInstance()->removeModeratedContent( | |
800 | 'com.woltlab.wcf.comment.response', | |
801 | [$this->response->responseID] | |
802 | ); | |
803 | ||
804 | return ['responseID' => $this->response->responseID]; | |
805 | } | |
806 | ||
a9229942 TD |
807 | /** |
808 | * @inheritDoc | |
1b1ee406 | 809 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
810 | */ |
811 | public function validateBeginEdit() | |
812 | { | |
27c1494a | 813 | $this->comment = $this->getSingleObject()->getDecoratedObject(); |
a9229942 | 814 | |
d74a8a86 MW |
815 | $objectType = ObjectTypeCache::getInstance()->getObjectType($this->comment->objectTypeID); |
816 | $processor = $objectType->getProcessor(); | |
27c1494a | 817 | if (!$processor->canEditComment($this->comment)) { |
a9229942 TD |
818 | throw new PermissionDeniedException(); |
819 | } | |
820 | ||
821 | $this->setDisallowedBBCodes(); | |
822 | } | |
823 | ||
824 | /** | |
825 | * @inheritDoc | |
1b1ee406 | 826 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
827 | */ |
828 | public function beginEdit() | |
829 | { | |
6abbfb9b C |
830 | $upcastProcessor = new HtmlUpcastProcessor(); |
831 | $upcastProcessor->process($this->comment->message, 'com.woltlab.wcf.comment'); | |
a9229942 TD |
832 | WCF::getTPL()->assign([ |
833 | 'comment' => $this->comment, | |
8ab34d7a | 834 | 'text' => $upcastProcessor->getHtml(), |
a9229942 TD |
835 | 'wysiwygSelector' => 'commentEditor' . $this->comment->commentID, |
836 | ]); | |
837 | ||
838 | return [ | |
839 | 'actionName' => 'beginEdit', | |
840 | 'template' => WCF::getTPL()->fetch('commentEditor', 'wcf'), | |
841 | ]; | |
842 | } | |
843 | ||
844 | /** | |
845 | * @inheritDoc | |
1b1ee406 | 846 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
847 | */ |
848 | public function validateSave() | |
849 | { | |
850 | $this->validateBeginEdit(); | |
851 | ||
852 | $this->validateMessage(); | |
853 | } | |
854 | ||
855 | /** | |
856 | * @inheritDoc | |
1b1ee406 | 857 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
858 | */ |
859 | public function save() | |
860 | { | |
861 | /** @var HtmlInputProcessor $htmlInputProcessor */ | |
862 | $htmlInputProcessor = $this->parameters['htmlInputProcessor']; | |
863 | ||
aa950db3 MS |
864 | $data = [ |
865 | 'message' => $htmlInputProcessor->getHtml(), | |
866 | ]; | |
867 | ||
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; | |
872 | } | |
873 | ||
a9229942 | 874 | $action = new self([$this->comment], 'update', [ |
aa950db3 | 875 | 'data' => $data, |
a9229942 TD |
876 | ]); |
877 | $action->executeAction(); | |
878 | ||
9d155f1f MS |
879 | $comment = new Comment($this->comment->getObjectID()); |
880 | ||
881 | if ($comment->hasEmbeddedObjects) { | |
882 | MessageEmbeddedObjectManager::getInstance()->loadObjects( | |
883 | 'com.woltlab.wcf.comment', | |
884 | [$comment->getObjectID()] | |
885 | ); | |
886 | } | |
887 | ||
a9229942 TD |
888 | return [ |
889 | 'actionName' => 'save', | |
9d155f1f | 890 | 'message' => $comment->getFormattedMessage(), |
a9229942 TD |
891 | ]; |
892 | } | |
893 | ||
894 | /** | |
895 | * Validates parameters to remove a comment or response. | |
896 | * | |
897 | * @throws PermissionDeniedException | |
898 | * @throws UserInputException | |
1b1ee406 | 899 | * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
900 | */ |
901 | public function validateRemove() | |
902 | { | |
903 | // validate comment id or response id | |
904 | try { | |
905 | $this->validateCommentID(); | |
906 | } catch (UserInputException $e) { | |
907 | try { | |
908 | $this->validateResponseID(); | |
909 | } catch (UserInputException $e) { | |
910 | throw new UserInputException('objectIDs'); | |
911 | } | |
912 | } | |
913 | ||
914 | // validate object type id | |
915 | $objectType = $this->validateObjectType(); | |
916 | ||
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(); | |
922 | } | |
923 | } else { | |
924 | if (!$this->commentProcessor->canDeleteResponse($this->response)) { | |
925 | throw new PermissionDeniedException(); | |
926 | } | |
927 | } | |
928 | } | |
929 | ||
930 | /** | |
931 | * Removes a comment or response. | |
932 | * | |
933 | * @return int[] | |
1b1ee406 | 934 | * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
935 | */ |
936 | public function remove() | |
937 | { | |
938 | if ($this->comment !== null) { | |
939 | $objectAction = new self([$this->comment], 'delete'); | |
940 | $objectAction->executeAction(); | |
941 | ||
942 | return ['commentID' => $this->comment->commentID]; | |
943 | } else { | |
944 | $objectAction = new CommentResponseAction([$this->response], 'delete'); | |
945 | $objectAction->executeAction(); | |
946 | ||
947 | return ['responseID' => $this->response->responseID]; | |
948 | } | |
949 | } | |
950 | ||
951 | /** | |
199a6b01 | 952 | * @since 6.0 |
1b1ee406 | 953 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 | 954 | */ |
199a6b01 | 955 | private function validateGetGuestDialog(): void |
a9229942 | 956 | { |
199a6b01 MW |
957 | if (!WCF::getUser()->userID) { |
958 | if (isset($this->parameters['data']['username'])) { | |
959 | $this->validateUsername(); | |
960 | $this->validateCaptcha(); | |
961 | } | |
a9229942 | 962 | } |
a9229942 TD |
963 | } |
964 | ||
965 | /** | |
966 | * Returns the dialog for guests when they try to write a comment letting | |
967 | * them enter a username and solving a captcha. | |
968 | * | |
a9229942 | 969 | * @throws SystemException |
1b1ee406 | 970 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 | 971 | */ |
199a6b01 | 972 | private function getGuestDialog(): ?string |
a9229942 | 973 | { |
199a6b01 MW |
974 | if (WCF::getUser()->userID) { |
975 | return null; | |
976 | } | |
977 | ||
978 | if (isset($this->parameters['data']['username']) && empty($this->validationErrors)) { | |
979 | return null; | |
980 | } | |
981 | ||
982 | if (!empty($this->validationErrors)) { | |
983 | if (!empty($this->parameters['data']['username'])) { | |
984 | WCF::getSession()->register('username', $this->parameters['data']['username']); | |
985 | } | |
986 | WCF::getTPL()->assign('errorType', $this->validationErrors); | |
987 | } | |
988 | ||
a9229942 TD |
989 | $captchaObjectType = null; |
990 | ||
991 | if (CAPTCHA_TYPE) { | |
992 | $captchaObjectType = CaptchaHandler::getInstance()->getObjectTypeByName(CAPTCHA_TYPE); | |
993 | if ($captchaObjectType === null) { | |
994 | throw new SystemException("Unknown captcha object type with name '" . CAPTCHA_TYPE . "'"); | |
995 | } | |
996 | ||
997 | if (!$captchaObjectType->getProcessor()->isAvailable()) { | |
998 | $captchaObjectType = null; | |
999 | } | |
1000 | } | |
1001 | ||
199a6b01 MW |
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'), | |
1008 | ]); | |
a9229942 TD |
1009 | } |
1010 | ||
1011 | /** | |
1012 | * Renders a comment. | |
1013 | * | |
1014 | * @param Comment $comment | |
1015 | * @param CommentResponse $response | |
1016 | * @return string|string[] | |
1b1ee406 | 1017 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1018 | */ |
1019 | protected function renderComment(Comment $comment, ?CommentResponse $response = null) | |
1020 | { | |
1021 | $comment = new StructuredComment($comment); | |
1022 | $comment->setIsDeletable($this->commentProcessor->canDeleteComment($comment->getDecoratedObject())); | |
1023 | $comment->setIsEditable($this->commentProcessor->canEditComment($comment->getDecoratedObject())); | |
1024 | ||
aa950db3 MS |
1025 | if ($comment->hasEmbeddedObjects) { |
1026 | MessageEmbeddedObjectManager::getInstance()->loadObjects( | |
1027 | 'com.woltlab.wcf.comment', | |
1028 | [$comment->getObjectID()] | |
1029 | ); | |
1030 | } | |
1031 | if ($response && $response->hasEmbeddedObjects) { | |
1032 | MessageEmbeddedObjectManager::getInstance()->loadObjects( | |
1033 | 'com.woltlab.wcf.comment.response', | |
1034 | [$response->getObjectID()] | |
1035 | ); | |
1036 | } | |
1037 | ||
a9229942 TD |
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) { | |
1043 | $response = null; | |
1044 | break; | |
1045 | } | |
1046 | } | |
1047 | } | |
1048 | ||
feb18f73 MW |
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. | |
a9229942 | 1052 | if ($comment->getDecoratedObject()->responses) { |
feb18f73 | 1053 | WCF::getTPL()->assign('ignoreLastResponseTime', true); |
a9229942 TD |
1054 | } |
1055 | ||
1056 | WCF::getTPL()->assign([ | |
199a6b01 MW |
1057 | 'commentCanAdd' => $this->commentProcessor->canAdd( |
1058 | $comment->getDecoratedObject()->objectID | |
1059 | ), | |
a9229942 TD |
1060 | 'commentCanModerate' => $this->commentProcessor->canModerate( |
1061 | $comment->getDecoratedObject()->objectTypeID, | |
1062 | $comment->getDecoratedObject()->objectID | |
1063 | ), | |
1064 | 'commentList' => [$comment], | |
1065 | 'commentManager' => $this->commentProcessor, | |
1066 | ]); | |
1067 | ||
1068 | // load like data | |
1069 | if (MODULE_LIKE) { | |
1070 | $likeData = []; | |
1071 | $commentObjectType = ReactionHandler::getInstance()->getObjectType('com.woltlab.wcf.comment'); | |
1072 | ReactionHandler::getInstance()->loadLikeObjects($commentObjectType, [$comment->commentID]); | |
1073 | $likeData['comment'] = ReactionHandler::getInstance()->getLikeObjects($commentObjectType); | |
1074 | ||
1075 | $responseIDs = []; | |
1076 | foreach ($comment as $visibleResponse) { | |
1077 | $responseIDs[] = $visibleResponse->responseID; | |
1078 | } | |
1079 | ||
1080 | if ($response !== null) { | |
1081 | $responseIDs[] = $response->responseID; | |
1082 | } | |
1083 | ||
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); | |
1088 | } | |
1089 | ||
1090 | WCF::getTPL()->assign('likeData', $likeData); | |
1091 | } | |
1092 | ||
1093 | $template = WCF::getTPL()->fetch('commentList'); | |
1094 | if ($response === null) { | |
1095 | return $template; | |
1096 | } | |
1097 | ||
1098 | return [ | |
1099 | 'template' => $template, | |
1100 | 'response' => $this->renderResponse($response), | |
1101 | ]; | |
1102 | } | |
1103 | ||
1104 | /** | |
1105 | * Renders a response. | |
1106 | * | |
1107 | * @param CommentResponse $response | |
1108 | * @return string | |
1b1ee406 | 1109 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1110 | */ |
1111 | protected function renderResponse(CommentResponse $response) | |
1112 | { | |
1113 | $response = new StructuredCommentResponse($response); | |
1114 | $response->setIsDeletable($this->commentProcessor->canDeleteResponse($response->getDecoratedObject())); | |
1115 | $response->setIsEditable($this->commentProcessor->canEditResponse($response->getDecoratedObject())); | |
1116 | ||
aa950db3 MS |
1117 | if ($response->hasEmbeddedObjects) { |
1118 | MessageEmbeddedObjectManager::getInstance()->loadObjects( | |
1119 | 'com.woltlab.wcf.comment.response', | |
1120 | [$response->getObjectID()] | |
1121 | ); | |
1122 | } | |
1123 | ||
a9229942 TD |
1124 | // render response |
1125 | WCF::getTPL()->assign([ | |
1126 | 'responseList' => [$response], | |
1127 | 'commentCanModerate' => $this->commentProcessor->canModerate( | |
1128 | $response->getComment()->objectTypeID, | |
1129 | $response->getComment()->objectID | |
1130 | ), | |
1131 | 'commentManager' => $this->commentProcessor, | |
1132 | ]); | |
1133 | ||
1134 | return WCF::getTPL()->fetch('commentResponseList'); | |
1135 | } | |
1136 | ||
1137 | /** | |
1138 | * Validates message parameters. | |
1139 | * | |
1140 | * @throws UserInputException | |
1b1ee406 | 1141 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 | 1142 | */ |
aa950db3 | 1143 | protected function validateMessage(bool $isResponse = false) |
a9229942 TD |
1144 | { |
1145 | $this->readString('message', false, 'data'); | |
1146 | $this->parameters['data']['message'] = MessageUtil::stripCrap($this->parameters['data']['message']); | |
1147 | ||
1148 | if (empty($this->parameters['data']['message'])) { | |
1149 | throw new UserInputException('message'); | |
1150 | } | |
1151 | ||
1152 | CommentHandler::enforceCensorship($this->parameters['data']['message']); | |
1153 | ||
1154 | $this->setDisallowedBBCodes(); | |
aa950db3 MS |
1155 | |
1156 | $htmlInputProcessor = new HtmlInputProcessor(); | |
1157 | if ($isResponse) { | |
1158 | $htmlInputProcessor->process( | |
1159 | $this->parameters['data']['message'], | |
1160 | 'com.woltlab.wcf.comment.response' | |
1161 | ); | |
1162 | } else { | |
1163 | $htmlInputProcessor->process( | |
1164 | $this->parameters['data']['message'], | |
1165 | 'com.woltlab.wcf.comment', | |
1166 | $this->comment !== null ? $this->comment->getObjectID() : 0 | |
1167 | ); | |
1168 | } | |
a9229942 TD |
1169 | |
1170 | // search for disallowed bbcodes | |
1171 | $disallowedBBCodes = $htmlInputProcessor->validate(); | |
1172 | if (!empty($disallowedBBCodes)) { | |
1173 | throw new UserInputException( | |
1174 | 'text', | |
1175 | WCF::getLanguage()->getDynamicVariable( | |
1176 | 'wcf.message.error.disallowedBBCodes', | |
1177 | ['disallowedBBCodes' => $disallowedBBCodes] | |
1178 | ) | |
1179 | ); | |
1180 | } | |
1181 | ||
1182 | if ($htmlInputProcessor->appearsToBeEmpty()) { | |
1183 | throw new UserInputException('message'); | |
1184 | } | |
1185 | ||
5b70df4d | 1186 | $commentTextContent = $htmlInputProcessor->getTextContent(); |
1187 | if (\mb_strlen($commentTextContent) > WCF::getSession()->getPermission('user.comment.maxLength')) { | |
1188 | throw new UserInputException( | |
1189 | 'text', | |
1190 | WCF::getLanguage()->getDynamicVariable( | |
1191 | 'wcf.message.error.tooLong', | |
1192 | ['maxTextLength' => WCF::getSession()->getPermission('user.comment.maxLength')] | |
1193 | ) | |
1194 | ); | |
1195 | } | |
1196 | ||
a9229942 TD |
1197 | $this->parameters['htmlInputProcessor'] = $htmlInputProcessor; |
1198 | } | |
1199 | ||
1200 | /** | |
1201 | * Validates object type id parameter. | |
1202 | * | |
1203 | * @param int $objectTypeID | |
1204 | * @return ObjectType | |
1205 | * @throws UserInputException | |
1b1ee406 | 1206 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1207 | */ |
1208 | protected function validateObjectType($objectTypeID = null) | |
1209 | { | |
1210 | if ($objectTypeID === null) { | |
1211 | $this->readInteger('objectTypeID', false, 'data'); | |
1212 | $objectTypeID = $this->parameters['data']['objectTypeID']; | |
1213 | } | |
1214 | ||
1215 | $objectType = ObjectTypeCache::getInstance()->getObjectType($objectTypeID); | |
1216 | if ($objectType === null) { | |
1217 | throw new UserInputException('objectTypeID'); | |
1218 | } | |
6e13b6b9 TD |
1219 | if ($objectType->getDefinition()->definitionName !== 'com.woltlab.wcf.comment.commentableContent') { |
1220 | throw new UserInputException('objectTypeID'); | |
1221 | } | |
a9229942 TD |
1222 | |
1223 | return $objectType; | |
1224 | } | |
1225 | ||
1226 | /** | |
1227 | * Validates comment id parameter. | |
1228 | * | |
1229 | * @throws UserInputException | |
1b1ee406 | 1230 | * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1231 | */ |
1232 | protected function validateCommentID() | |
1233 | { | |
1234 | $this->readInteger('commentID', false, 'data'); | |
1235 | ||
1236 | $this->comment = new Comment($this->parameters['data']['commentID']); | |
1237 | if ($this->comment === null || !$this->comment->commentID) { | |
1238 | throw new UserInputException('commentID'); | |
1239 | } | |
1240 | } | |
1241 | ||
1242 | /** | |
1243 | * Validates response id parameter. | |
1244 | * | |
1245 | * @throws UserInputException | |
1b1ee406 | 1246 | * @deprecated 6.0 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1247 | */ |
1248 | protected function validateResponseID() | |
1249 | { | |
1250 | if (isset($this->parameters['data']['responseID'])) { | |
1251 | $this->response = new CommentResponse($this->parameters['data']['responseID']); | |
1252 | } | |
1253 | if ($this->response === null || !$this->response->responseID) { | |
1254 | throw new UserInputException('responseID'); | |
1255 | } | |
1256 | } | |
1257 | ||
1258 | /** | |
1259 | * Validates the username parameter. | |
1b1ee406 | 1260 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1261 | */ |
1262 | protected function validateUsername() | |
1263 | { | |
1264 | if (WCF::getUser()->userID) { | |
1265 | return; | |
1266 | } | |
1267 | ||
1268 | try { | |
1269 | $this->readString('username', false, 'data'); | |
1270 | ||
1271 | if (!UserRegistrationUtil::isValidUsername($this->parameters['data']['username'])) { | |
1272 | throw new UserInputException('username', 'invalid'); | |
1273 | } | |
3552067d | 1274 | if (User::getUserByUsername($this->parameters['data']['username'])->userID) { |
a9229942 TD |
1275 | throw new UserInputException('username', 'notUnique'); |
1276 | } | |
1277 | } catch (UserInputException $e) { | |
1278 | $this->validationErrors['username'] = $e->getType(); | |
1279 | } | |
1280 | } | |
1281 | ||
1282 | /** | |
1283 | * Validates the captcha challenge. | |
1284 | * | |
1285 | * @throws SystemException | |
1b1ee406 | 1286 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1287 | */ |
1288 | protected function validateCaptcha() | |
1289 | { | |
1290 | if (WCF::getUser()->userID) { | |
1291 | return; | |
1292 | } | |
1293 | ||
1294 | if (CAPTCHA_TYPE) { | |
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 . "'"); | |
1298 | } | |
1299 | ||
1300 | if (!$this->captchaObjectType->getProcessor()->isAvailable()) { | |
1301 | $this->captchaObjectType = null; | |
1302 | } | |
1303 | } | |
1304 | ||
1305 | if ($this->captchaObjectType === null) { | |
1306 | return; | |
1307 | } | |
1308 | ||
1309 | try { | |
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()]); | |
1314 | } | |
1315 | } | |
1316 | ||
1317 | /** | |
1318 | * Sets the list of disallowed bbcodes for comments. | |
1b1ee406 | 1319 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1320 | */ |
1321 | protected function setDisallowedBBCodes() | |
1322 | { | |
1323 | BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( | |
1324 | ',', | |
1325 | WCF::getSession()->getPermission('user.comment.disallowedBBCodes') | |
1326 | )); | |
1327 | } | |
1328 | ||
1329 | /** | |
1330 | * Returns the current html input processor or a new one if `$message` is not null. | |
1331 | * | |
1332 | * @param string|null $message source message | |
1333 | * @param int $objectID object id | |
1334 | * @return HtmlInputProcessor | |
1b1ee406 | 1335 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1336 | */ |
1337 | public function getHtmlInputProcessor($message = null, $objectID = 0) | |
1338 | { | |
1339 | if ($message === null) { | |
1340 | return $this->htmlInputProcessor; | |
1341 | } | |
1342 | ||
1343 | $this->htmlInputProcessor = new HtmlInputProcessor(); | |
1344 | $this->htmlInputProcessor->process($message, 'com.woltlab.wcf.comment', $objectID); | |
1345 | ||
1346 | return $this->htmlInputProcessor; | |
1347 | } | |
1348 | ||
1349 | /** | |
1350 | * Returns the comment object. | |
1351 | * | |
1352 | * @return Comment | |
1b1ee406 | 1353 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1354 | */ |
1355 | public function getComment() | |
1356 | { | |
1357 | return $this->comment; | |
1358 | } | |
1359 | ||
1360 | /** | |
1361 | * Returns the comment response object. | |
1362 | * | |
1363 | * @return CommentResponse | |
1b1ee406 | 1364 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1365 | */ |
1366 | public function getResponse() | |
1367 | { | |
1368 | return $this->response; | |
1369 | } | |
1370 | ||
1371 | /** | |
1372 | * Returns the comment manager. | |
1373 | * | |
1374 | * @return ICommentManager | |
1b1ee406 | 1375 | * @deprecated 6.1 see https://docs.woltlab.com/6.1/migration/wsc60/php/#comment-backend |
a9229942 TD |
1376 | */ |
1377 | public function getCommentManager() | |
1378 | { | |
1379 | return $this->commentProcessor; | |
1380 | } | |
285b1d92 | 1381 | } |