ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ilObjForumGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
27use ILIAS\Data\Factory as DataFactory;
32
41{
42 use ilForumRequestTrait;
43
44 private array $viewModeOptions = [
45 ilForumProperties::VIEW_TREE => 'sort_by_posts',
46 ilForumProperties::VIEW_DATE_ASC => 'sort_by_date',
47 ];
48
49 private array $sortationOptions = [
50 ilForumProperties::VIEW_DATE_ASC => 'ascending_order',
51 ilForumProperties::VIEW_DATE_DESC => 'descending_order',
52 ];
53
54 private \ILIAS\GlobalScreen\Services $globalScreen;
55 public string $modal_history = '';
60 private bool $is_moderator;
62 private bool $hideToolbar = false;
63 private \Psr\Http\Message\ServerRequestInterface $httpRequest;
66 private ?array $forumObjects = null;
67 private string $confirmation_gui_html = '';
70 private string $requestAction;
71 private array $modalActionsContainer = [];
72
74 public \ILIAS\DI\RBACServices $rbac;
78 private IRSS $irss;
79
80 private int $selectedSorting;
82 protected \ILIAS\Style\Content\Object\ObjectFacade $content_style_domain;
83 protected \ILIAS\Style\Content\GUIService $content_style_gui;
84 private array $modal_collection = [];
85 private readonly bool $in_page_editor_style_context;
87
88 public function __construct($data, int $id = 0, bool $call_by_reference = true, bool $prepare_output = true)
89 {
90 global $DIC;
91
92 $this->httpRequest = $DIC->http()->request();
93
94 $this->uiFactory = $DIC->ui()->factory();
95 $this->uiRenderer = $DIC->ui()->renderer();
96 $this->globalScreen = $DIC->globalScreen();
97
98 $this->irss = $DIC->resourceStorage();
99
100 $this->ilObjDataCache = $DIC['ilObjDataCache'];
101 $this->ilNavigationHistory = $DIC['ilNavigationHistory'];
102 $this->ilHelp = $DIC['ilHelp'];
103 $this->rbac = $DIC->rbac();
104 $this->factory = $DIC->ui()->factory();
105 $this->renderer = $DIC->ui()->renderer();
106
107 $this->type = 'frm';
109 $this->ctrl->saveParameter($this, ['ref_id']);
110 $this->tpl->addJavaScript('assets/js/Basic.js');
111
112 $this->lng->loadLanguageModule('forum');
113 $this->lng->loadLanguageModule('content');
114
115 $ref_id = $this->retrieveIntOrZeroFrom($this->http->wrapper()->query(), 'ref_id');
116
117 $this->objProperties = ilForumProperties::getInstance($this->ilObjDataCache->lookupObjId($ref_id));
118 $this->is_moderator = $this->access->checkAccess('moderate_frm', '', $ref_id);
119
120 $this->objCurrentTopic = new ilForumTopic($this->retrieveThrPk(), $this->is_moderator);
121 $this->requestAction = (string) ($this->httpRequest->getQueryParams()['action'] ?? '');
122 $cs = $DIC->contentStyle();
123 $this->content_style_gui = $cs->gui();
124 if (is_object($this->object)) {
125 $this->content_style_domain = $cs->domain()->styleForRefId($this->object->getRefId());
126 }
127 $this->in_page_editor_style_context = $this->http->wrapper()->query()->has('page_editor_style');
128 $this->ctrl->saveParameterByClass(ilObjectContentStyleSettingsGUI::class, 'page_editor_style');
129
130 $this->initSessionStorage();
131 $this->forum_thread_table_session_storage = new ForumThreadTableSessionStorage(
132 $this->ref_id,
133 $this->is_moderator
134 );
135 }
136
137 protected function initSessionStorage(): void
138 {
139 $forumValues = ilSession::get('frm');
140 if (!is_array($forumValues)) {
141 $forumValues = [];
142 ilSession::set('frm', $forumValues);
143 }
144
145 $threadId = $this->objCurrentTopic->getId();
146 if ($threadId > 0 && !isset($forumValues[$threadId])) {
147 $forumValues[(int) $threadId] = [];
148 ilSession::set('frm', $forumValues);
149 }
150
151 $this->selected_post_storage = new ilForumThreadSettingsSessionStorage('frm_selected_post');
152 }
153
154 private function retrieveThrPk(): int
155 {
156 return $this->retrieveIntOrZeroFrom($this->http->wrapper()->query(), 'thr_pk');
157 }
158
159 private function retrieveDraftId(bool $from_post = false): int
160 {
161 return $this->retrieveIntOrZeroFrom(
162 $from_post ? $this->http->wrapper()->post() : $this->http->wrapper()->query(),
163 'draft_id'
164 );
165 }
166
167 protected function toggleExplorerNodeStateObject(): void
168 {
169 $exp = new ilForumExplorerGUI(
170 'frm_exp_' . $this->objCurrentTopic->getId(),
171 $this,
172 'viewThread',
173 $this->objCurrentTopic,
174 $this->objCurrentTopic->getPostRootNode($this->is_moderator)
175 );
176 $exp->toggleExplorerNodeState();
177 }
178
180 array $subtree_nodes,
181 array $pagedPostings,
182 int $pageSize,
183 ilForumPost $firstForumPost
184 ): void {
185 if ($firstForumPost->getId() === $this->objCurrentPost->getId()) {
186 return;
187 }
188
189 if ($subtree_nodes !== [] && $this->objCurrentPost->getId() > 0) {
190 $isCurrentPostingInPage = array_filter($pagedPostings, fn(ilForumPost $posting): bool => (
191 $posting->getId() === $this->objCurrentPost->getId()
192 ));
193
194 if ([] === $isCurrentPostingInPage) {
195 $pageOfCurrentPosting = 0;
196 $i = 0;
197 foreach ($subtree_nodes as $node) {
198 if ($i > 0 && $i % $pageSize === 0) {
199 ++$pageOfCurrentPosting;
200 }
201
202 if ($node->getId() === $this->objCurrentPost->getId()) {
203 break;
204 }
205
206 ++$i;
207 }
208
209 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
210 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
211 $this->ctrl->setParameter($this, 'page', $pageOfCurrentPosting);
212 $this->ctrl->setParameter(
213 $this,
214 'orderby',
215 $this->getOrderByParam()
216 );
217 $this->ctrl->redirect($this, 'viewThread', (string) $this->objCurrentPost->getId());
218 }
219 }
220 }
221
222 public function ensureThreadBelongsToForum(int $objId, ilForumTopic $thread): void
223 {
225 if ($thread->getForumId() !== $forumId) {
226 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
227 }
228 }
229
230 private function decorateWithAutosave(ilPropertyFormGUI $form): void
231 {
234
235 $this->tpl->addJavaScript('assets/js/autosave_forum.js');
236 $autosave_cmd = 'autosaveDraftAsync';
237 if ($this->objCurrentPost->getId() === 0 && $this->objCurrentPost->getThreadId() === 0) {
238 $autosave_cmd = 'autosaveThreadDraftAsync';
239 }
240 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
241 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
242 $this->ctrl->setParameter($this, 'draft_id', $this->retrieveDraftId());
243 $this->ctrl->setParameter($this, 'action', ilUtil::stripSlashes($this->requestAction));
244 $this->tpl->addOnLoadCode(
245 "il.Language.setLangVar('saving', " . json_encode($this->lng->txt('saving'), JSON_THROW_ON_ERROR) . ');'
246 );
247
248 $this->tpl->addOnLoadCode('il.ForumDraftsAutosave.init(' . json_encode([
249 'loadingImgSrc' => ilUtil::getImagePath('media/loader.svg'),
250 'draftId' => $this->retrieveDraftId(),
251 'interval' => $interval * 1000,
252 'url' => $this->ctrl->getFormAction($this, $autosave_cmd, '', true),
253 'selectors' => [
254 'form' => '#form_' . $form->getId()
255 ]
256 ], JSON_THROW_ON_ERROR) . ');');
257 }
258 }
259
260 private function isTopLevelReplyCommand(): bool
261 {
262 return in_array(
263 strtolower($this->ctrl->getCmd() ?? ''),
264 array_map('strtolower', ['createTopLevelPost', 'saveTopLevelPost', 'saveTopLevelDraft']),
265 true
266 );
267 }
268
269 public function getUnsafeGetCommands(): array
270 {
271 return [
272 'enableForumNotification',
273 'disableForumNotification',
274 'toggleThreadNotification',
275 'confirmDeleteThreadDrafts'
276 ];
277 }
278
279 public function getSafePostCommands(): array
280 {
281 return [];
282 }
283
284 public function executeCommand(): void
285 {
286 $next_class = $this->ctrl->getNextClass($this) ?? '';
287 $cmd = $this->ctrl->getCmd() ?? '';
288
289 $exclude_cmds = [
290 'viewThread',
291 'markPostUnread',
292 'markPostRead',
293 'showThreadNotification',
294 'performPostActivation',
295 'askForPostActivation',
296 'askForPostDeactivation',
297 'toggleThreadNotification',
298 'toggleStickiness',
299 'cancelPost',
300 'savePost',
301 'saveTopLevelPost',
302 'createTopLevelPost',
303 'saveTopLevelDraft',
304 'quotePost',
305 'autosaveDraftAsync',
306 'autosaveThreadDraftAsync',
307 'saveAsDraft',
308 'editDraft',
309 'updateDraft',
310 'deliverDraftZipFile',
311 'deliverZipFile',
312 'cancelDraft',
313 'deleteThreadDrafts',
314 'deletePosting',
315 'deletePostingDraft',
316 'revokeCensorship',
317 'addCensorship',
318 'confirmDeleteThreadsObject'
319 ];
320
321 if (!in_array($cmd, $exclude_cmds, true)) {
322 $this->prepareOutput();
323 }
324
325 if (!$this->creation_mode) {
326 $this->checkUsersViewMode();
327 $pos_pk = $this->retrieveIntOrZeroFrom($this->http->wrapper()->query(), 'pos_pk');
328 if ($this->selectedSorting === ilForumProperties::VIEW_TREE &&
329 $this->selected_post_storage->get($this->objCurrentTopic->getId()) > 0) {
330 $this->objCurrentPost = new ilForumPost(
331 $this->selected_post_storage->get($this->objCurrentTopic->getId()) ?? 0,
332 $this->is_moderator
333 );
334 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
335 } else {
336 $this->selected_post_storage->set($this->objCurrentTopic->getId(), 0);
337 $this->objCurrentPost = new ilForumPost(
338 $pos_pk,
339 $this->is_moderator
340 );
341 }
342 }
343
344 if (!$this->getCreationMode() && !$this->ctrl->isAsynch() && $this->access->checkAccess(
345 'read',
346 '',
347 $this->object->getRefId()
348 )) {
350 $this->object->getRefId(),
351 ilLink::_getLink($this->object->getRefId(), 'frm'),
352 'frm'
353 );
354 }
355
356 switch (strtolower($next_class)) {
357 case strtolower(ilForumPageGUI::class):
358 if (in_array(strtolower($cmd), array_map('strtolower', [
359 self::UI_CMD_COPAGE_DOWNLOAD_FILE,
360 self::UI_CMD_COPAGE_DISPLAY_FULLSCREEN,
361 self::UI_CMD_COPAGE_DOWNLOAD_PARAGRAPH,
362 ]), true)
363 ) {
364 if (!$this->checkPermissionBool('read')) {
365 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
366 }
367 } elseif (!$this->checkPermissionBool('write') || $this->user->isAnonymous()) {
368 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
369 }
370
371 $this->content_style_gui->addCss($this->tpl, $this->ref_id);
372 $this->tpl->setCurrentBlock('SyntaxStyle');
373 $this->tpl->setVariable('LOCATION_SYNTAX_STYLESHEET', ilObjStyleSheet::getSyntaxStylePath());
374 $this->tpl->parseCurrentBlock();
375
377 $obj = $this->object;
378
379 $forwarder = new ilForumPageCommandForwarder(
380 $this->http,
381 $this->ctrl,
382 $this->tabs_gui,
383 $this->lng,
384 $obj,
385 $this->user,
386 $this->content_style_domain
387 );
388
389 $pageContent = $forwarder->forward();
390 if ($pageContent !== '') {
391 $this->tpl->setContent($pageContent);
392 }
393 break;
394
395 case strtolower(ilLearningProgressGUI::class):
396 if (!ilLearningProgressAccess::checkAccess($this->object->getRefId())) {
397 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
398 }
399
400 $this->tabs_gui->activateTab('learning_progress');
401
402 $usrId = $this->user->getId();
403 if (
404 isset($this->request->getQueryParams()['user_id']) &&
405 is_numeric($this->request->getQueryParams()['user_id'])
406 ) {
407 $usrId = (int) $this->request->getQueryParams()['user_id'];
408 }
409
410 $this->ctrl->forwardCommand(new ilLearningProgressGUI(
412 $this->object->getRefId(),
413 $usrId
414 ));
415 break;
416
417 case strtolower(ilObjectContentStyleSettingsGUI::class):
418 $this->checkPermission('write');
419
420 if ($this->in_page_editor_style_context) {
421 $this->tabs_gui->setBackTarget(
422 $this->lng->txt('back'),
423 $this->ctrl->getLinkTarget(new ilForumPageGUI($this->object->getId()), 'edit')
424 );
425 } else {
426 $forum_settings_gui = new ilForumSettingsGUI($this, $this->object);
427 $forum_settings_gui->settingsTabs();
428 }
429
430 $settings_gui = $this->content_style_gui
431 ->objectSettingsGUIForRefId(
432 null,
433 $this->ref_id
434 );
435 $this->ctrl->forwardCommand($settings_gui);
436 break;
437
438 case strtolower(ilForumSettingsGUI::class):
439 $forum_settings_gui = new ilForumSettingsGUI($this, $this->object);
440 $this->ctrl->forwardCommand($forum_settings_gui);
441 break;
442
443 case strtolower(ilRepositoryObjectSearchGUI::class):
444 $this->addHeaderAction();
445 $this->setSideBlocks();
446 $this->tabs_gui->activateTab('forums_threads');
447 $this->ctrl->setReturn($this, 'view');
448 $search_gui = new ilRepositoryObjectSearchGUI(
449 $this->object->getRefId(),
450 $this,
451 'view'
452 );
453 $this->ctrl->forwardCommand($search_gui);
454 break;
455
456 case strtolower(ilPermissionGUI::class):
457 $perm_gui = new ilPermissionGUI($this);
458 $this->ctrl->forwardCommand($perm_gui);
459 break;
460
461 case strtolower(ilForumExportGUI::class):
462 $fex_gui = new ilForumExportGUI();
463 $this->ctrl->forwardCommand($fex_gui);
464 $this->http->close();
465 break;
466
467 case strtolower(ilForumModeratorsGUI::class):
468 $fm_gui = new ilForumModeratorsGUI($this->object);
469 $this->ctrl->forwardCommand($fm_gui);
470 break;
471
472 case strtolower(ilInfoScreenGUI::class):
473 $this->infoScreen();
474 break;
475
476 case strtolower(ilColumnGUI::class):
477 $this->showThreadsObject();
478 break;
479
480 case strtolower(PublicProfileGUI::class):
481 $user = $this->retrieveIntOrZeroFrom($this->http->wrapper()->query(), 'user');
482 $profile_gui = new PublicProfileGUI($user);
483 $add = $this->getUserProfileAdditional($this->object->getRefId(), $user);
484 $profile_gui->setAdditional($add);
485 $ret = $this->ctrl->forwardCommand($profile_gui);
486 $this->tpl->setContent($ret);
487 break;
488
489 case strtolower(ilObjectCopyGUI::class):
490 $cp = new ilObjectCopyGUI($this);
491 $cp->setType('frm');
492 $this->ctrl->forwardCommand($cp);
493 break;
494
495 case strtolower(ilExportGUI::class):
496 $this->tabs_gui->activateTab('export');
497 $exp = new ilExportGUI($this);
498 $this->ctrl->forwardCommand($exp);
499 break;
500
501 case strtolower(ilRatingGUI::class):
502 if (!$this->objProperties->isIsThreadRatingEnabled() || $this->user->isAnonymous()) {
503 $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->MESSAGE);
504 }
505
506 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
507 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
508 }
509
510 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentTopic);
511
512 $rating_gui = new ilRatingGUI();
513 $rating_gui->setObject(
514 $this->object->getId(),
515 $this->object->getType(),
516 $this->objCurrentTopic->getId(),
517 'thread'
518 );
519
520 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
521 $this->ctrl->forwardCommand($rating_gui);
522
524 $this->object->getId(),
525 $this->object->getType(),
526 $this->objCurrentTopic->getId(),
527 'thread'
528 );
529 $this->objCurrentTopic->setAverageRating($avg['avg']);
530 $this->objCurrentTopic->update();
531
532 $this->ctrl->redirect($this, 'showThreads');
533
534 // no break
535 case strtolower(ilCommonActionDispatcherGUI::class):
536 $gui = ilCommonActionDispatcherGUI::getInstanceFromAjaxCall();
537 $this->ctrl->forwardCommand($gui);
538 break;
539
540 case strtolower(ilContainerNewsSettingsGUI::class):
541 $this->checkPermission('write');
542
543 $forum_settings_gui = new ilForumSettingsGUI($this, $this->object);
544 $forum_settings_gui->settingsTabs();
545
546 $this->lng->loadLanguageModule('cont');
547 $news_set_gui = new ilContainerNewsSettingsGUI($this);
548 $news_set_gui->setNewsBlockForced(true);
549 $news_set_gui->setPublicNotification(true);
550 $this->ctrl->forwardCommand($news_set_gui);
551 break;
552
553 default:
554 if (in_array($cmd, ['close', 'reopen', 'make_topics_non_sticky', 'makesticky', 'editThread', 'move'])) {
555 $cmd = 'performThreadsAction';
556 }
557
558 if ($cmd === null || $cmd === '') {
559 $cmd = 'showThreads';
560 }
561
562 $cmd .= 'Object';
563 $this->$cmd();
564
565 break;
566 }
567
568 if (!$this->in_page_editor_style_context &&
569 $cmd !== 'viewThreadObject' && $cmd !== 'showUserObject' && !in_array(
570 strtolower($next_class),
571 array_map('strtolower', [ilForumPageGUI::class]),
572 true
573 )) {
574 $this->addHeaderAction();
575 }
576 }
577
578 public function infoScreenObject(): void
579 {
580 $this->infoScreen();
581 }
582
583 protected function initEditCustomForm(ilPropertyFormGUI $a_form): void
584 {
585 $this->forum_settings_gui = new ilForumSettingsGUI($this, $this->object);
586 $this->forum_settings_gui->getCustomForm($a_form);
587 }
588
589 protected function getEditFormCustomValues(array &$a_values): void
590 {
591 $this->forum_settings_gui->getCustomValues($a_values);
592 }
593
594 protected function updateCustom(ilPropertyFormGUI $form): void
595 {
596 $this->forum_settings_gui->updateCustomValues($form);
597 }
598
599 public function updateThreadObject(): void
600 {
601 if (!$this->is_moderator) {
602 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
603 }
604
605 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
606 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
607 }
608
609 if ($this->objCurrentTopic->getId() === 0) {
610 $this->showThreadsObject();
611 return;
612 }
613
614 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentTopic);
615
616 $title = $this->getEditTitleModal($this->objCurrentTopic)->withRequest($this->http->request())->getData();
617 if (array_key_exists(0, $title)) {
618 $new_subject = $title[0];
619 if ($new_subject !== '') {
620 $this->objCurrentTopic->setSubject($new_subject);
621 $this->objCurrentTopic->updateThreadTitle();
622 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'));
623 }
624
625 $this->ctrl->redirect($this, 'showThreads');
626 }
627 }
628
629 public function markAllReadObject(): void
630 {
631 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
632 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
633 }
634
635 $this->object->markAllThreadsRead($this->user->getId());
636 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_all_threads_marked_read'));
637 $this->showThreadsObject();
638 }
639
640 public function showThreadsObject(): void
641 {
642 $this->setSideBlocks();
643 $this->getCenterColumnHTML();
644 }
645
646 public function getContent(): string
647 {
648 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
649 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
650 }
651
652 $cmd = $this->ctrl->getCmd();
653 $frm = $this->object->Forum;
654 $frm->setForumId($this->object->getId());
655 $frm->setForumRefId($this->object->getRefId());
656 $frm->setMDB2Wherecondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
657 // Import information: Topic (variable $topicData) means frm object, not thread
658 $frm_object = $frm->getOneTopic();
659 if ($frm_object->getTopPk() > 0) {
660 $frm->setDbTable('frm_data');
661 $frm->setMDB2WhereCondition('top_pk = %s ', ['integer'], [$frm_object->getTopPk()]);
662 $frm->updateVisits($frm_object->getTopPk());
663
665 $this->object->getType(),
666 $this->object->getRefId(),
667 $this->object->getId(),
668 $this->user->getId()
669 );
670
671 if ($cmd !== 'showThreads') {
672 $cmd = 'showThreads';
673 }
674 }
675 $this->tpl->setPermanentLink($this->object->getType(), $this->object->getRefId());
676
677 if (!$this->hideToolbar() && $this->access->checkAccess('add_thread', '', $this->object->getRefId())) {
678 $btn = $this->uiFactory->button()
679 ->standard(
680 $this->lng->txt('forums_new_thread'),
681 $this->ctrl->getLinkTarget($this, 'createThread')
682 );
683 $this->toolbar->addStickyItem($btn);
684 }
685
687 $this->addDraftButtonIfDraftsExists($cmd);
688 }
689
690 if ($this->confirmation_gui_html === '' && !$this->user->isAnonymous()) {
691 $this->toolbar->addButton(
692 $this->lng->txt('forums_mark_read'),
693 $this->ctrl->getLinkTarget($this, 'markAllRead')
694 );
695 $this->ctrl->clearParameters($this);
696 }
697
698 if (!$this->user->isAnonymous() && $this->access->checkAccess('write', '', $this->ref_id)) {
699 $this->lng->loadLanguageModule('cntr');
700 $this->toolbar->addComponent(
701 $this->uiFactory->button()->standard(
702 $this->lng->txt('cntr_text_media_editor'),
703 $this->ctrl->getLinkTargetByClass(ilForumPageGUI::class, 'edit')
704 )
705 );
706 }
707
708 $this->renderThreadOverview($frm, $frm_object);
709 return '';
710 }
711
712 private function renderThreadOverview(ilForum $frm, ForumDto $frm_object): void
713 {
714 $threads_page = $this->forum_thread_table_session_storage->fetchData($frm, $frm_object);
715
716 $sticky_threads = [];
717 $regular_threads = [];
718
719 if (count($threads_page->getForumTopics()) > 0) {
720 foreach ($threads_page->getForumTopics() as $thread) {
721 $ref_id = $this->object->getRefId();
722 $subject = $thread->getSubject();
723 if ($thread->isClosed()) {
724 $subject .= ' (' . $this->lng->txt('forums_closed') . ')';
725 }
726
727 $link = $this->getLinkActionForThread($ref_id, $subject, 'viewThread', $thread->getId());
728 $actions = $this->getActionsForThreadOverview($ref_id, $thread);
729
730 $list_item = $this->factory
731 ->item()
732 ->standard($link)
733 ->withActions($actions)
734 ->withProperties($this->getThreadProperties($thread));
735 $list_item = $this->markTopThreadInOverview($thread, $list_item);
736 if ($thread->isSticky()) {
737 $sticky_threads[] = $list_item;
738 } else {
739 $regular_threads[] = $list_item;
740 }
741 }
742 }
743
744 $sticky_threads_item_group = null;
745 if (count($sticky_threads) > 0) {
746 $sticky_threads_item_group = $this->factory->item()->group(
747 count($regular_threads) > 0 ? $this->lng->txt('top_thema') : '',
748 $sticky_threads
749 );
750 }
751
752 $regular_threads_item_group = null;
753 if (count($regular_threads) > 0) {
754 $regular_threads_item_group = $this->factory->item()->group(
755 count($sticky_threads) > 0 ? $this->lng->txt('thema') : '',
756 $regular_threads
757 );
758 }
759
760 $url = $this->http->request()->getRequestTarget();
761 $current_page = 0;
762 if ($this->http->wrapper()->query()->has(ilForumProperties::PAGE_NAME_THREAD_OVERVIEW)) {
763 $current_page = $this->http->wrapper()->query()->retrieve(
765 $this->refinery->kindlyTo()->int()
766 );
767 }
768
769 $view_controls[] = $this->getSortationViewControl(
770 $this->forum_thread_table_session_storage->getThreadPage(),
771 $this->forum_thread_table_session_storage->getThreadSortation()
772 );
773 $view_controls[] = $this->factory
774 ->viewControl()
775 ->pagination()
777 ->withTotalEntries($frm_object->getTopNumThreads())
779 ->withMaxPaginationButtons(5)
780 ->withCurrentPage($current_page);
781
782 $item_groups = array_filter([$sticky_threads_item_group, $regular_threads_item_group]);
783 if ($item_groups === []) {
784 $vc_container = $this->factory->panel()->listing()->standard(
785 $this->lng->txt('thread_overview'),
786 [$this->factory->item()->group($this->lng->txt('frm_no_threads'), [])]
787 );
788 } else {
789 $vc_container = $this->factory->panel()->listing()->standard(
790 $this->lng->txt('thread_overview'),
791 $item_groups
792 )->withViewControls($view_controls);
793 }
794
795 $default_html = $this->renderer->render($vc_container);
796 $modals = $this->renderer->render($this->modal_collection);
797
798 $this->initStyleSheets();
799
800 $forwarder = new ilForumPageCommandForwarder(
801 $GLOBALS['DIC']['http'],
802 $this->ctrl,
803 $this->tabs_gui,
804 $this->lng,
805 $this->object,
806 $this->user,
807 $this->content_style_domain
808 );
810
811 $this->tpl->setContent($forwarder->forward() . $default_html . $modals);
812 }
813
814 private function getSortationViewControl(
815 int $offset,
816 ThreadSortation $effective_sortation
817 ): \ILIAS\UI\Component\ViewControl\Sortation {
818 if ($offset > 0) {
819 $this->ctrl->setParameter($this, 'page', $offset);
820 }
821
822 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
823 $base_url = $this->ctrl->getLinkTarget($this, 'showThreads');
824
825 $translation_keys = [];
826 foreach (ThreadSortation::cases() as $sortation) {
827 $translation_keys[$sortation->value] = $this->lng->txt($sortation->languageId());
828 }
829 $this->ctrl->clearParameters($this);
830
831 return $this->factory->viewControl()->sortation(
832 $translation_keys,
833 (string) $effective_sortation->value
834 )->withTargetURL($base_url, ForumThreadTableSessionStorage::KEY_THREAD_SORTATION);
835 }
836
840 private function retrieveThreadIds(): array
841 {
842 $thread_ids = [];
843 $query = $this->http->wrapper()->query()->has('thr_pk');
844 $post = $this->http->wrapper()->post()->has('thread_ids');
845 if ($post) {
846 $thread_ids = $this->http->wrapper()->post()->retrieve(
847 'thread_ids',
848 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
849 );
850 } elseif ($query) {
851 $thread_ids = $this->http->wrapper()->query()->retrieve(
852 'thr_pk',
853 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
854 );
855 }
856
857 return $thread_ids;
858 }
859
863 private function getThreadProperties(ilForumTopic $forum_topic): array
864 {
865 $this->ctrl->setParameter($this, 'thr_pk', $forum_topic->getId());
866 $unread_counter = $forum_topic->getNumUnreadPosts();
867 $is_top_thread = $forum_topic->isSticky();
868
869 if ($unread_counter === 0) {
870 $unread = '';
871 } else {
872 $unread = ' (' . $unread_counter . ' ' . $this->lng->txt('unread') . ')';
873 }
874
875 $authorinfo = new ilForumAuthorInformation(
876 $forum_topic->getThrAuthorId(),
877 $forum_topic->getDisplayUserId(),
878 (string) $forum_topic->getUserAlias(),
879 (string) $forum_topic->getImportName()
880 );
881
882 $properties = [
883 $this->lng->txt('forums_created_by') => $authorinfo->getAuthorName(),
884 $this->lng->txt('forums_articles') => $forum_topic->getNumPosts() . $unread,
885 $this->lng->txt('forums_last_post') => $this->object->Forum->convertDate($forum_topic->getLastPost()->getCreateDate()),
886 $this->lng->txt('visits') => $forum_topic->getVisits(),
887 ];
888
889 if ($is_top_thread === true) {
890 $is_top_thread = [$this->lng->txt('relevance') => $this->lng->txt('sticky')];
891 $properties = array_merge($properties, $is_top_thread);
892 }
893
894 $rating_property = [];
895 if ($this->objProperties->isIsThreadRatingEnabled()) {
896 $rating = new ilRatingGUI();
897 $rating->setObject(
898 $this->object->getId(),
899 $this->object->getType(),
900 $forum_topic->getId(),
901 'thread'
902 );
903 $rating->setUserId($this->user->getId());
904 $rating_property = [$this->lng->txt('frm_rating') => $rating->getHTML()];
905 }
906 $this->ctrl->setParameter($this, 'thr_pk', null);
907
908 return array_merge($properties, $rating_property);
909 }
910
911 private function getLinkActionForThread(
912 int $ref_id,
913 string $title,
914 string $cmd,
915 ?int $thread_id = null
916 ): \ILIAS\UI\Component\Link\Link {
917 $this->ctrl->setParameter($this, 'ref_id', $ref_id);
918 $this->ctrl->setParameter($this, 'thr_pk', $thread_id);
919 $this->ctrl->setParameter($this, 'page', 0);
920 $url = $this->ctrl->getLinkTarget($this, $cmd);
921 $this->ctrl->setParameter($this, 'ref_id', null);
922 $this->ctrl->setParameter($this, 'thr_pk', null);
923 $this->ctrl->setParameter($this, 'page', null);
924
925 return $this->uiFactory->link()->standard($title, $url);
926 }
927
928 private function getActionsForThreadOverview(int $ref_id, ilForumTopic $forum_topic): Standard
929 {
930 $actions = $this->uiFactory->dropdown()->standard([]);
931 if ($this->is_moderator) {
932 $open_close = $this->getOpenCloseActionForThread($forum_topic, $ref_id);
933 $stick_or_no_stick = $this->getStickyActionForThread($forum_topic, $ref_id);
934 $edit_title_modal = $this->getEditTitleModal($forum_topic);
935 $this->modal_collection[] = $edit_title_modal;
936 $edit_title = $this->factory->button()->shy($this->lng->txt('frm_edit_title'), '#')->withOnClick(
937 $edit_title_modal->getShowSignal()
938 );
939
940 $move = $this->getLinkActionForThread(
941 $ref_id,
942 $this->lng->txt('move_thread_to_forum'),
943 'move',
944 $forum_topic->getId()
945 );
946 $merge = $this->getLinkActionForThread(
947 $ref_id,
948 $this->lng->txt('merge_posts_into_thread'),
949 'mergeThreads',
950 $forum_topic->getId()
951 );
952 $delete = $this->getLinkActionForThread(
953 $ref_id,
954 $this->lng->txt('delete_thread'),
955 'confirmDeleteThreads',
956 $forum_topic->getId()
957 );
958 $actions = $this->uiFactory->dropdown()->standard([
959 $stick_or_no_stick,
960 $open_close,
961 $edit_title,
962 $move,
963 $merge,
964 $delete
965 ]);
966 }
967
968 return $actions;
969 }
970
971 private function getEditTitleModal(ilForumTopic $topic): RoundTrip
972 {
973 $topic_id = $this->refinery->kindlyTo()->string()->transform($topic->getId());
974 $this->ctrl->setParameter($this, 'thr_pk', (string) $topic_id);
975 $target = $this->ctrl->getLinkTargetByClass(
976 ilObjForumGUI::class,
977 'editThread'
978 );
979 $this->ctrl->setParameter($this, 'thread_id', null);
980
981 return $this->factory->modal()->roundtrip(
982 $this->lng->txt('frm_edit_title'),
983 [],
984 [
985 $this->factory->input()->field()->text($this->lng->txt('frm_edit_title'))->withValue($topic->getSubject()),
986 ],
987 $target
988 );
989 }
990
991 private function addDraftButtonIfDraftsExists(string $cmd): void
992 {
994 $this->user->getId(),
995 ilObjForum::lookupForumIdByObjId($this->object->getId())
996 );
997 if ($drafts === []) {
998 return;
999 }
1000
1001 $table = new ForumDraftsTable(
1002 $this->object,
1003 $this->ui_factory,
1004 $this->httpRequest,
1005 $this->lng,
1006 $cmd,
1007 $this->ctrl,
1008 new DataFactory(),
1009 $this->user,
1010 $this->access->checkAccess('add_thread', '', $this->object->getRefId()),
1011 $this
1012 );
1013 $threadsTemplate = new ilTemplate(
1014 'tpl.forums_threads_liste.html',
1015 true,
1016 true,
1017 'components/ILIAS/Forum'
1018 );
1019 $threadsTemplate->setVariable('THREADS_DRAFTS_TABLE', $this->uiRenderer->render($table->getComponent()));
1020
1021 $draft_modal = $this->factory->modal()->roundtrip(
1022 $this->lng->txt('drafts'),
1023 [$this->factory->legacy()->content($threadsTemplate->get())]
1024 );
1025 $this->modal_collection[] = $draft_modal;
1026 $edit_title = $this->factory->button()->standard($this->lng->txt('drafts'), '#')->withOnClick(
1027 $draft_modal->getShowSignal()
1028 );
1029 $this->toolbar->addComponent($edit_title);
1030 }
1031
1032 private function getStickyActionForThread(ilForumTopic $forum_topic, int $ref_id): \ILIAS\UI\Component\Link\Link
1033 {
1034 return $this->getLinkActionForThread(
1035 $ref_id,
1036 $this->lng->txt($forum_topic->isSticky() ? 'make_topics_non_sticky' : 'make_topics_sticky'),
1037 $forum_topic->isSticky() ? 'make_topics_non_sticky' : 'makesticky',
1038 $forum_topic->getId()
1039 );
1040 }
1041
1042 private function getOpenCloseActionForThread(ilForumTopic $forum_topic, int $ref_id): \ILIAS\UI\Component\Link\Link
1043 {
1044 return $this->getLinkActionForThread(
1045 $ref_id,
1046 $this->lng->txt($forum_topic->isClosed() ? 'reopen_topics' : 'close_topics'),
1047 $forum_topic->isClosed() ? 'reopen' : 'close',
1048 $forum_topic->getId()
1049 );
1050 }
1051
1052 private function markTopThreadInOverview(
1053 ilForumTopic $current_thread,
1054 Item $list_item
1055 ): Item {
1056 if ($current_thread->isSticky()) {
1057 $df = new \ILIAS\Data\Factory();
1058 $list_item = $list_item->withColor($df->color('#B54F00'));
1059 }
1060
1061 return $list_item;
1062 }
1063
1064 private function initStyleSheets(): void
1065 {
1066 $this->content_style_gui->addCss($this->tpl, $this->ref_id);
1067 $this->tpl->setCurrentBlock('SyntaxStyle');
1068 $this->tpl->setVariable('LOCATION_SYNTAX_STYLESHEET', ilObjStyleSheet::getSyntaxStylePath());
1069 $this->tpl->parseCurrentBlock();
1070 }
1071
1072 private function editStylePropertiesObject(): void
1073 {
1074 $this->content_style_gui->redirectToObjectSettings();
1075 }
1076
1080 private function renderDraftContent(
1081 ilTemplate $tpl,
1082 string $action,
1083 ilForumPost $referencePosting,
1084 array $drafts
1085 ): void {
1086 $frm = $this->object->Forum;
1087
1088 $draft_id = $this->retrieveDraftId();
1089 foreach ($drafts as $draft) {
1090 $tmp_file_obj = new ilFileDataForumDrafts($this->object->getId(), $draft->getDraftId());
1091 $filesOfDraft = $tmp_file_obj->getFilesOfPost();
1092 ksort($filesOfDraft);
1093
1094 if ($action !== 'showdraft' && $filesOfDraft !== []) {
1095 foreach ($filesOfDraft as $file) {
1096 $tpl->setCurrentBlock('attachment_download_row');
1097 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
1098 $this->ctrl->setParameter($this, 'file', $file['md5']);
1099 $tpl->setVariable('HREF_DOWNLOAD', $this->ctrl->getLinkTarget($this, 'viewThread'));
1100 $tpl->setVariable('TXT_FILENAME', $file['name']);
1101 $this->ctrl->setParameter($this, 'file', '');
1102 $this->ctrl->setParameter($this, 'draft_id', '');
1103 $this->ctrl->clearParameters($this);
1104 $tpl->parseCurrentBlock();
1105 }
1106
1107 $tpl->setCurrentBlock('attachments');
1108 $tpl->setVariable('TXT_ATTACHMENTS_DOWNLOAD', $this->lng->txt('forums_attachments'));
1109 $tpl->setVariable(
1110 'DOWNLOAD_IMG',
1111 $this->uiRenderer->render(
1112 $this->uiFactory->symbol()->glyph()->attachment()
1113 )
1114 );
1115 if (count($filesOfDraft) > 1) {
1116 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
1117 $download_zip_button = $this->uiFactory->button()
1118 ->standard(
1119 $this->lng->txt('download'),
1120 $this->ctrl->getLinkTarget($this, 'deliverDraftZipFile')
1121 );
1122 $this->ctrl->setParameter($this, 'draft_id', '');
1123 $tpl->setVariable('DOWNLOAD_ZIP', $this->uiRenderer->render($download_zip_button));
1124 }
1125 $tpl->parseCurrentBlock();
1126 }
1127
1128 $page = $this->http->wrapper()->query()->retrieve(
1129 'page',
1130 $this->refinery->byTrying([$this->refinery->kindlyTo()->int(), $this->refinery->always(0)])
1131 );
1132
1133 $this->renderSplitButton(
1134 $tpl,
1135 $action,
1136 false,
1137 $referencePosting,
1138 (int) $page,
1139 $draft
1140 );
1141
1142 $rowCol = 'tblrowmarked';
1143 $tpl->setVariable('ROWCOL', ' ' . $rowCol);
1144 $depth = $referencePosting->getDepth() - 1;
1145 if ($this->selectedSorting === ilForumProperties::VIEW_TREE) {
1146 ++$depth;
1147 }
1148 $tpl->setVariable('DEPTH', $depth);
1149
1150 $this->ctrl->setParameter($this, 'pos_pk', $referencePosting->getId());
1151 $this->ctrl->setParameter($this, 'thr_pk', $referencePosting->getThreadId());
1152 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
1153
1154 $backurl = urlencode($this->ctrl->getLinkTarget($this, 'viewThread', (string) $referencePosting->getId()));
1155
1156 $this->ctrl->setParameter($this, 'backurl', $backurl);
1157 $this->ctrl->setParameter($this, 'thr_pk', $referencePosting->getThreadId());
1158 $this->ctrl->setParameter($this, 'user', $draft->getPostDisplayUserId());
1159
1160 $authorinfo = new ilForumAuthorInformation(
1161 $draft->getPostAuthorId(),
1162 $draft->getPostDisplayUserId(),
1163 $draft->getPostUserAlias(),
1164 '',
1165 [
1166 'href' => $this->ctrl->getLinkTarget($this, 'showUser')
1167 ]
1168 );
1169
1170 $this->ctrl->clearParameters($this);
1171
1172 if ($authorinfo->hasSuffix()) {
1173 $tpl->setVariable('AUTHOR', $authorinfo->getSuffix());
1174 $tpl->setVariable('USR_NAME', $draft->getPostUserAlias());
1175 } else {
1176 $tpl->setVariable('AUTHOR', $authorinfo->getLinkedAuthorShortName());
1177 if ($authorinfo->getAuthorName(true) && !$this->objProperties->isAnonymized()) {
1178 $tpl->setVariable('USR_NAME', $authorinfo->getAuthorName(true));
1179 }
1180 }
1181 $tpl->setVariable('DRAFT_ANCHOR', 'draft_' . $draft->getDraftId());
1182
1183 $tpl->setVariable('USR_IMAGE', $authorinfo->getProfilePicture());
1184 $tpl->setVariable(
1185 'USR_ICON_ALT',
1186 ilLegacyFormElementsUtil::prepareFormOutput($authorinfo->getAuthorShortName())
1187 );
1188 if ($authorinfo->getAuthor()->getId() && ilForum::_isModerator(
1189 $this->object->getRefId(),
1190 $draft->getPostAuthorId()
1191 )) {
1192 if ($authorinfo->getAuthor()->getGender() === 'f') {
1193 $tpl->setVariable('ROLE', $this->lng->txt('frm_moderator_f'));
1194 } elseif ($authorinfo->getAuthor()->getGender() === 'm') {
1195 $tpl->setVariable('ROLE', $this->lng->txt('frm_moderator_m'));
1196 } elseif ($authorinfo->getAuthor()->getGender() === 'n') {
1197 $tpl->setVariable('ROLE', $this->lng->txt('frm_moderator_n'));
1198 }
1199 }
1200
1201 if ($draft->getUpdateUserId() > 0) {
1202 $draft->setPostUpdate($draft->getPostUpdate());
1203
1204 $this->ctrl->setParameter($this, 'backurl', $backurl);
1205 $this->ctrl->setParameter($this, 'thr_pk', $referencePosting->getThreadId());
1206 $this->ctrl->setParameter($this, 'user', $referencePosting->getUpdateUserId());
1207 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
1208
1209 $authorinfo = new ilForumAuthorInformation(
1210 $draft->getPostAuthorId(),
1211 // We assume the editor is the author here
1212 $draft->getPostDisplayUserId(),
1213 $draft->getPostUserAlias(),
1214 '',
1215 ['href' => $this->ctrl->getLinkTarget($this, 'showUser')]
1216 );
1217
1218 $this->ctrl->clearParameters($this);
1219
1220 $tpl->setVariable(
1221 'POST_UPDATE_TXT',
1222 $this->lng->txt('edited_on') . ': ' . $frm->convertDate($draft->getPostUpdate()) . ' - ' . strtolower($this->lng->txt('by'))
1223 );
1224 $tpl->setVariable('UPDATE_AUTHOR', $authorinfo->getLinkedAuthorShortName());
1225 if ($authorinfo->getAuthorName(true) && !$this->objProperties->isAnonymized() && !$authorinfo->hasSuffix()) {
1226 $tpl->setVariable('UPDATE_USR_NAME', $authorinfo->getAuthorName(true));
1227 }
1228 }
1229
1230 $draft->setPostMessage($frm->prepareText($draft->getPostMessage()));
1231
1232 $tpl->setVariable('SUBJECT', $draft->getPostSubject());
1233 $tpl->setVariable('POST_DATE', $frm->convertDate($draft->getPostDate()));
1234
1235 $tpl->setVariable('POST_DRAFT_TEXT', $this->lng->txt('post_draft_info'));
1236
1237 if (!$referencePosting->isCensored() || ($this->objCurrentPost->getId() === $referencePosting->getId() && $action === 'censor')) {
1238 $spanClass = '';
1239 if (ilForum::_isModerator($this->ref_id, $draft->getPostDisplayUserId())) {
1240 $spanClass = 'moderator';
1241 }
1242
1243 if ($draft->getPostMessage() === strip_tags($draft->getPostMessage())) {
1244 // We can be sure, that there are not html tags
1245 $draft->setPostMessage(nl2br($draft->getPostMessage()));
1246 }
1247
1248 if ($spanClass !== '') {
1249 $tpl->setVariable(
1250 'POST',
1251 '<span class="' . $spanClass . '">' . ilRTE::_replaceMediaObjectImageSrc(
1252 $draft->getPostMessage(),
1253 1
1254 ) . '</span>'
1255 );
1256 } else {
1257 $tpl->setVariable('POST', ilRTE::_replaceMediaObjectImageSrc($draft->getPostMessage(), 1));
1258 }
1259 }
1260
1261 if ($action === 'editdraft' && $draft->getDraftId() === $draft_id) {
1262 $oEditReplyForm = $this->getReplyEditForm();
1263
1264 if (!$this->objCurrentTopic->isClosed() && in_array($this->requestAction, ['showdraft', 'editdraft'])) {
1265 $this->renderPostingForm($tpl, $frm, $referencePosting, $this->requestAction);
1266 }
1267
1268 $tpl->setVariable('EDIT_DRAFT_ANCHOR', 'draft_edit_' . $draft->getDraftId());
1269 $tpl->setVariable('DRAFT_FORM', $oEditReplyForm->getHTML() . $this->modal_history);
1270 }
1271
1272 $tpl->parseCurrentBlock();
1273 }
1274 }
1275
1276 protected function renderPostContent(
1277 ilTemplate $tpl,
1278 ilForumPost $node,
1279 string $action,
1280 int $pageIndex,
1281 int $postIndex
1282 ): void {
1283 $forumObj = $this->object;
1284 $frm = $this->object->Forum;
1285
1286 $fileDataOfForum = new ilFileDataForum($forumObj->getId(), $node->getId());
1287
1288 $filesOfPost = $fileDataOfForum->getFilesOfPost();
1289 ksort($filesOfPost);
1290 if ($filesOfPost !== [] && ($action !== 'showedit' || $node->getId() !== $this->objCurrentPost->getId())) {
1291 foreach ($filesOfPost as $file) {
1292 $tpl->setCurrentBlock('attachment_download_row');
1293 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
1294 $this->ctrl->setParameter($this, 'file', $file['md5']);
1295 $tpl->setVariable('HREF_DOWNLOAD', $this->ctrl->getLinkTarget($this, 'viewThread'));
1296 $tpl->setVariable('TXT_FILENAME', $file['name']);
1297 $this->ctrl->clearParameters($this);
1298 $tpl->parseCurrentBlock();
1299 }
1300 $tpl->setCurrentBlock('attachments');
1301 $tpl->setVariable('TXT_ATTACHMENTS_DOWNLOAD', $this->lng->txt('forums_attachments'));
1302 $tpl->setVariable(
1303 'DOWNLOAD_IMG',
1304 $this->uiRenderer->render(
1305 $this->uiFactory->symbol()->glyph()->attachment()
1306 )
1307 );
1308 if (count($filesOfPost) > 1) {
1309 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
1310 $download_zip_button = $this->uiFactory->button()
1311 ->standard(
1312 $this->lng->txt('download'),
1313 $this->ctrl->getLinkTarget($this, 'deliverZipFile')
1314 );
1315 $tpl->setVariable('DOWNLOAD_ZIP', $this->uiRenderer->render($download_zip_button));
1316 }
1317 $tpl->parseCurrentBlock();
1318 }
1319 $this->renderSplitButton($tpl, $action, true, $node, $pageIndex);
1320
1321 $tpl->setVariable('POST_ANKER', $node->getId());
1322 $tpl->setVariable('TXT_PERMA_LINK', $this->lng->txt('perma_link'));
1323 $tpl->setVariable('PERMA_TARGET', '_top');
1324
1325 $rowCol = ilUtil::switchColor($postIndex, 'tblrow1', 'tblrow2');
1326 if (($this->is_moderator || $node->isOwner($this->user->getId())) && !$node->isActivated() && !$this->objCurrentTopic->isClosed()) {
1327 $rowCol = 'ilPostingNeedsActivation';
1328 } elseif ($this->objProperties->getMarkModeratorPosts()) {
1329 $isAuthorModerator = ilForum::_isModerator($this->object->getRefId(), $node->getPosAuthorId());
1330 if ($isAuthorModerator && $node->isAuthorModerator() === null) {
1331 $rowCol = 'ilModeratorPosting';
1332 } elseif ($node->isAuthorModerator()) {
1333 $rowCol = 'ilModeratorPosting';
1334 }
1335 }
1336
1337 if (
1338 (!in_array($action, ['delete', 'censor']) && !$this->displayConfirmPostActivation()) ||
1339 $this->objCurrentPost->getId() !== $node->getId()
1340 ) {
1341 $tpl->setVariable('ROWCOL', ' ' . $rowCol);
1342 } else {
1343 $rowCol = 'tblrowmarked';
1344 }
1345
1346 if ($node->isCensored()) {
1347 if ($action !== 'censor') {
1348 $tpl->setVariable('TXT_CENSORSHIP_ADVICE', $this->lng->txt('post_censored_comment_by_moderator'));
1349 }
1350
1351 $rowCol = 'tblrowmarked';
1352 }
1353
1354 $tpl->setVariable('ROWCOL', ' ' . $rowCol);
1355 $tpl->setVariable('DEPTH', $node->getDepth() - 1);
1356 if (!$node->isActivated() && ($node->isOwner($this->user->getId()) || $this->is_moderator)) {
1357 $tpl->setVariable('POST_NOT_ACTIVATED_YET', $this->lng->txt('frm_post_not_activated_yet'));
1358 }
1359
1360 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
1361 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
1362 $backurl = urlencode($this->ctrl->getLinkTarget($this, 'viewThread', (string) $node->getId()));
1363 $this->ctrl->clearParameters($this);
1364
1365 $this->ctrl->setParameter($this, 'backurl', $backurl);
1366 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
1367 $this->ctrl->setParameter($this, 'user', $node->getDisplayUserId());
1368 $authorinfo = new ilForumAuthorInformation(
1369 $node->getPosAuthorId(),
1370 $node->getDisplayUserId(),
1371 (string) $node->getUserAlias(),
1372 (string) $node->getImportName(),
1373 [
1374 'href' => $this->ctrl->getLinkTarget($this, 'showUser')
1375 ]
1376 );
1377 $this->ctrl->clearParameters($this);
1378
1379 if ($authorinfo->hasSuffix()) {
1380 if (!$authorinfo->isDeleted()) {
1381 $tpl->setVariable('USR_NAME', $authorinfo->getAlias());
1382 }
1383 $tpl->setVariable('AUTHOR', $authorinfo->getSuffix());
1384 } else {
1385 if ($authorinfo->getAuthorName(true) && !$this->objProperties->isAnonymized()) {
1386 $tpl->setVariable('USR_NAME', $authorinfo->getAuthorName(true));
1387 }
1388 $tpl->setVariable('AUTHOR', $authorinfo->getLinkedAuthorShortName());
1389 }
1390
1391 $tpl->setVariable('USR_IMAGE', $authorinfo->getProfilePicture());
1392 $tpl->setVariable(
1393 'USR_ICON_ALT',
1394 ilLegacyFormElementsUtil::prepareFormOutput($authorinfo->getAuthorShortName())
1395 );
1396 $isModerator = ilForum::_isModerator($this->ref_id, $node->getPosAuthorId());
1397 if ($isModerator && $authorinfo->getAuthor()->getId()) {
1398 $authorRole = $this->lng->txt('frm_moderator_n');
1399 if (is_string($authorinfo->getAuthor()->getGender()) && $authorinfo->getAuthor()->getGender() !== '') {
1400 $authorRole = $this->lng->txt('frm_moderator_' . $authorinfo->getAuthor()->getGender());
1401 }
1402 $tpl->setVariable('ROLE', $authorRole);
1403 }
1404
1405 if ($node->getUpdateUserId() > 0) {
1406 $node->setChangeDate($node->getChangeDate());
1407
1408 $this->ctrl->setParameter($this, 'backurl', $backurl);
1409 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
1410 $this->ctrl->setParameter($this, 'user', $node->getUpdateUserId());
1411 $update_user_id = $node->getUpdateUserId();
1412 if ($node->getDisplayUserId() === 0 && $node->getPosAuthorId() === $node->getUpdateUserId()) {
1413 $update_user_id = $node->getDisplayUserId();
1414 }
1415 $authorinfo = new ilForumAuthorInformation(
1416 $node->getPosAuthorId(),
1417 $update_user_id,
1418 (string) $node->getUserAlias(),
1419 (string) $node->getImportName(),
1420 [
1421 'href' => $this->ctrl->getLinkTarget($this, 'showUser')
1422 ]
1423 );
1424 $this->ctrl->clearParameters($this);
1425
1426 $tpl->setVariable(
1427 'POST_UPDATE_TXT',
1428 $this->lng->txt('edited_on') . ': ' . $frm->convertDate($node->getChangeDate()) . ' - ' . strtolower($this->lng->txt('by'))
1429 );
1430 $tpl->setVariable('UPDATE_AUTHOR', $authorinfo->getLinkedAuthorShortName());
1431 if ($authorinfo->getAuthorName(true) && !$this->objProperties->isAnonymized() && !$authorinfo->hasSuffix()) {
1432 $tpl->setVariable('UPDATE_USR_NAME', $authorinfo->getAuthorName(true));
1433 }
1434 }
1435
1436 if ($this->selectedSorting === ilForumProperties::VIEW_TREE
1437 && $node->getId() !== $this->selected_post_storage->get($node->getThreadId())) {
1438 $target = $this->uiFactory->symbol()->icon()->custom(
1439 ilUtil::getImagePath('object/target.svg'),
1440 $this->lng->txt('target_select')
1441 );
1442
1443 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
1444 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
1445
1446 $tpl->setVariable(
1447 'TARGET',
1448 $this->uiRenderer->render(
1449 $this->uiFactory->link()->bulky(
1450 $target,
1451 $this->lng->txt('select'),
1452 new \ILIAS\Data\URI(
1453 ILIAS_HTTP_PATH . '/' . $this->ctrl->getLinkTarget($this, 'selectPost', (string) $node->getId())
1454 )
1455 )
1456 )
1457 );
1458 }
1459
1460 $node->setMessage($frm->prepareText($node->getMessage()));
1461
1462 if ($this->user->isAnonymous() || $node->isPostRead()) {
1463 $tpl->setVariable('SUBJECT', $node->getSubject());
1464 } else {
1465 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
1466 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
1467 $this->ctrl->setParameter($this, 'page', $pageIndex);
1468 $this->ctrl->setParameter(
1469 $this,
1470 'orderby',
1471 $this->getOrderByParam()
1472 );
1473 $this->ctrl->setParameter($this, 'viewmode', $this->selectedSorting);
1474 $mark_post_target = $this->ctrl->getLinkTarget($this, 'markPostRead', (string) $node->getId());
1475
1476 $tpl->setVariable(
1477 'SUBJECT',
1478 '<a href="' . $mark_post_target . '"><b>' . $node->getSubject() . '</b></a>'
1479 );
1480 }
1481
1482 $tpl->setVariable('POST_DATE', $frm->convertDate($node->getCreateDate()));
1483
1484 if (!$node->isCensored() || ($this->objCurrentPost->getId() === $node->getId() && $action === 'censor')) {
1485 $spanClass = '';
1486 if (ilForum::_isModerator($this->ref_id, $node->getDisplayUserId())) {
1487 $spanClass = 'moderator';
1488 }
1489
1490 // possible bugfix for mantis #8223
1491 if ($node->getMessage() === strip_tags($node->getMessage())) {
1492 // We can be sure, that there are not html tags
1493 $node->setMessage(nl2br($node->getMessage()));
1494 }
1495
1496 if ($spanClass !== '') {
1497 $tpl->setVariable(
1498 'POST',
1499 '<span class="' . $spanClass . '">' .
1501 '</span>'
1502 );
1503 } else {
1504 $tpl->setVariable('POST', ilRTE::_replaceMediaObjectImageSrc($node->getMessage(), 1));
1505 }
1506 } else {
1507 $tpl->setVariable(
1508 'POST',
1509 '<span class="moderator">' . nl2br((string) $node->getCensorshipComment()) . '</span>'
1510 );
1511 }
1512
1513 $tpl->parseCurrentBlock();
1514 }
1515
1516 protected function selectPostObject(): void
1517 {
1518 $thr_pk = (int) $this->httpRequest->getQueryParams()['thr_pk'];
1519 $pos_pk = (int) $this->httpRequest->getQueryParams()['pos_pk'];
1520
1521 $this->selected_post_storage->set(
1522 $thr_pk,
1523 $pos_pk
1524 );
1525
1526 $this->viewThreadObject();
1527 }
1528
1532 protected function afterSave(ilObject $new_object): void
1533 {
1534 $this->tpl->setOnScreenMessage('success', $this->lng->txt('frm_added'), true);
1535 $this->ctrl->setParameter($this, 'ref_id', $new_object->getRefId());
1536 $this->ctrl->redirect($this, 'createThread');
1537 }
1538
1539 protected function getTabs(): void
1540 {
1541 if ($this->in_page_editor_style_context) {
1542 return;
1543 }
1544
1545 $this->ilHelp->setScreenIdComponent('frm');
1546
1547 $this->ctrl->setParameter($this, 'ref_id', $this->ref_id);
1548
1549 $active = [
1550 '',
1551 'showThreads',
1552 'view',
1553 'markAllRead',
1554 'enableForumNotification',
1555 'disableForumNotification',
1556 'moveThreads',
1557 'performMoveThreads',
1558 'cancelMoveThreads',
1559 'performThreadsAction',
1560 'createThread',
1561 'addThread',
1562 'showUser',
1563 'confirmDeleteThreads',
1564 'merge',
1565 'mergeThreads',
1566 'performMergeThreads'
1567 ];
1568
1569 $force_active = false;
1570 if (in_array($this->ctrl->getCmd(), $active, true)) {
1571 $force_active = true;
1572 }
1573
1574 if ($this->access->checkAccess(
1575 'read',
1576 '',
1577 $this->ref_id
1578 )) {
1579 $this->tabs_gui->addTarget(
1580 self::UI_TAB_ID_THREADS,
1581 $this->ctrl->getLinkTarget($this, 'showThreads'),
1582 $this->ctrl->getCmd(),
1583 static::class,
1584 '',
1585 $force_active
1586 );
1587 }
1588
1589 if ($this->access->checkAccess('visible', '', $this->ref_id) || $this->access->checkAccess(
1590 'read',
1591 '',
1592 $this->ref_id
1593 )) {
1594 $cmdClass = $this->http->wrapper()->query()->retrieve(
1595 'cmdClass',
1596 $this->refinery->byTrying([$this->refinery->kindlyTo()->string(), $this->refinery->always('')])
1597 );
1598
1599 $force_active = $this->ctrl->getNextClass() === 'ilinfoscreengui' || strtolower($cmdClass) === 'ilnotegui';
1600 $this->tabs_gui->addTarget(
1601 self::UI_TAB_ID_INFO,
1602 $this->ctrl->getLinkTargetByClass([self::class, ilInfoScreenGUI::class], 'showSummary'),
1603 ['showSummary', 'infoScreen'],
1604 '',
1605 '',
1606 $force_active
1607 );
1608 }
1609
1610 if ($this->access->checkAccess('write', '', $this->ref_id)) {
1611 $force_active = $this->ctrl->getCmd() === 'edit';
1612 $this->tabs_gui->addTarget(
1613 self::UI_TAB_ID_SETTINGS,
1614 $this->ctrl->getLinkTarget($this, 'edit'),
1615 'edit',
1616 static::class,
1617 '',
1618 $force_active
1619 );
1620 }
1621
1622 if ($this->access->checkAccess('write', '', $this->ref_id)) {
1623 $this->tabs_gui->addTarget(
1624 self::UI_TAB_ID_MODERATORS,
1625 $this->ctrl->getLinkTargetByClass(ilForumModeratorsGUI::class, 'showModerators'),
1626 'showModerators',
1627 static::class
1628 );
1629 }
1630
1631 if (ilLearningProgressAccess::checkAccess($this->object->getRefId())) {
1632 $this->tabs_gui->addTab(
1633 'learning_progress',
1634 $this->lng->txt('learning_progress'),
1635 $this->ctrl->getLinkTargetByClass(ilLearningProgressGUI::class)
1636 );
1637 }
1638
1639 if ($this->settings->get('enable_fora_statistics', '0')) {
1640 $hasStatisticsAccess = $this->access->checkAccess('write', '', $this->ref_id);
1641 if (!$hasStatisticsAccess) {
1642 $hasStatisticsAccess = (
1643 $this->objProperties->isStatisticEnabled() &&
1644 $this->access->checkAccess('read', '', $this->ref_id)
1645 );
1646 }
1647
1648 if ($hasStatisticsAccess) {
1649 $force_active = $this->ctrl->getCmd() === 'showStatistics';
1650 $this->tabs_gui->addTarget(
1651 self::UI_TAB_ID_STATS,
1652 $this->ctrl->getLinkTarget($this, 'showStatistics'),
1653 'showStatistics',
1654 static::class,
1655 '',
1656 $force_active
1657 );
1658 }
1659 }
1660
1661 if ($this->access->checkAccess('write', '', $this->object->getRefId())) {
1662 $this->tabs_gui->addTarget(
1663 self::UI_TAB_ID_EXPORT,
1664 $this->ctrl->getLinkTargetByClass(ilExportGUI::class, ''),
1665 '',
1666 'ilexportgui'
1667 );
1668 }
1669
1670 if ($this->access->checkAccess('edit_permission', '', $this->ref_id)) {
1671 $this->tabs_gui->addTarget(
1672 self::UI_TAB_ID_PERMISSIONS,
1673 $this->ctrl->getLinkTargetByClass([static::class, ilPermissionGUI::class], 'perm'),
1674 ['perm', 'info', 'owner'],
1675 'ilpermissiongui'
1676 );
1677 }
1678 }
1679
1680 public function showStatisticsObject(): void
1681 {
1682 if (!$this->settings->get('enable_fora_statistics', '0')) {
1683 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1684 }
1685
1686 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
1687 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1688 }
1689
1690 if (!$this->objProperties->isStatisticEnabled()) {
1691 if ($this->access->checkAccess('write', '', $this->object->getRefId())) {
1692 $this->tpl->setOnScreenMessage('info', $this->lng->txt('frm_statistics_disabled_for_participants'));
1693 } else {
1694 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1695 }
1696 }
1697
1698 $this->object->Forum->setForumId($this->object->getId());
1699
1700 $tbl = new \ILIAS\Forum\Statistics\ForumStatisticsTable(
1701 $this->object,
1702 $this->objProperties,
1704 $this->access->checkRbacOrPositionPermissionAccess(
1705 'read_learning_progress',
1706 'read_learning_progress',
1707 $this->object->getRefId()
1708 ),
1709 $this->user,
1710 $this->ui_factory,
1711 $this->request,
1712 $this->lng
1713 );
1714 $this->tpl->setContent($this->uiRenderer->render($tbl->getComponent()));
1715 }
1716
1717 public static function _goto($a_target, $a_thread = 0, $a_posting = 0): void
1718 {
1719 global $DIC;
1720 $main_tpl = $DIC->ui()->mainTemplate();
1721
1722 $ilAccess = $DIC->access();
1723 $lng = $DIC->language();
1724 $ilErr = $DIC['ilErr'];
1725
1726 $a_target = is_numeric($a_target) ? (int) $a_target : 0;
1727 $a_thread = is_numeric($a_thread) ? (int) $a_thread : 0;
1728 if ($ilAccess->checkAccess('read', '', $a_target)) {
1729 if ($a_thread !== 0) {
1730 $objTopic = new ilForumTopic($a_thread);
1731 if ($objTopic->getFrmObjId() &&
1732 $objTopic->getFrmObjId() !== ilObject::_lookupObjectId($a_target)) {
1733 $ref_ids = ilObject::_getAllReferences($objTopic->getFrmObjId());
1734 foreach ($ref_ids as $ref_id) {
1735 if ($ilAccess->checkAccess('read', '', $ref_id)) {
1736 $new_ref_id = $ref_id;
1737 break;
1738 }
1739 }
1740
1741 if (isset($new_ref_id) && $new_ref_id !== $a_target) {
1742 $DIC->ctrl()->redirectToURL(
1743 ILIAS_HTTP_PATH . '/goto.php?target=frm_' . $new_ref_id . '_' . $a_thread . '_' . $a_posting
1744 );
1745 }
1746 }
1747
1748 $DIC->ctrl()->setParameterByClass(self::class, 'ref_id', (string) ((int) $a_target));
1749 if (is_numeric($a_thread)) {
1750 $DIC->ctrl()->setParameterByClass(self::class, 'thr_pk', (string) ((int) $a_thread));
1751 }
1752 if (is_numeric($a_posting)) {
1753 $DIC->ctrl()->setParameterByClass(self::class, 'pos_pk', (string) ((int) $a_posting));
1754 }
1755 $DIC->ctrl()->redirectByClass(
1756 [ilRepositoryGUI::class, self::class],
1757 'viewThread',
1758 is_numeric($a_posting) ? (string) ((int) $a_posting) : ''
1759 );
1760 } else {
1761 $DIC->ctrl()->setParameterByClass(self::class, 'ref_id', $a_target);
1762 $DIC->ctrl()->redirectByClass([ilRepositoryGUI::class, self::class,], '');
1763 $DIC->http()->close();
1764 }
1765 } elseif ($ilAccess->checkAccess('visible', '', $a_target)) {
1766 $DIC->ctrl()->setParameterByClass(ilInfoScreenGUI::class, 'ref_id', $a_target);
1767 $DIC->ctrl()->redirectByClass(
1768 [
1769 ilRepositoryGUI::class,
1770 self::class,
1771 ilInfoScreenGUI::class
1772 ],
1773 'showSummary'
1774 );
1775 } elseif ($ilAccess->checkAccess('read', '', ROOT_FOLDER_ID)) {
1776 $main_tpl->setOnScreenMessage('info', sprintf(
1777 $lng->txt('msg_no_perm_read_item'),
1779 ), true);
1780 $DIC->http()->close();
1781 }
1782
1783 $ilErr->raiseError($lng->txt('msg_no_perm_read'), $ilErr->FATAL);
1784 }
1785
1786 public function performDeleteThreadsObject(): void
1787 {
1788 $threadIds = $this->retrieveThreadIds();
1789 if ($threadIds === []) {
1790 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_at_least_one_thread'), true);
1791 $this->ctrl->redirect($this, 'showThreads');
1792 }
1793
1794 if (!$this->is_moderator) {
1795 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1796 }
1797
1798 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
1799 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1800 }
1801
1802 $forumObj = new ilObjForum($this->object->getRefId());
1803 $this->objProperties->setObjId($forumObj->getId());
1804
1805 $frm = new ilForum();
1806
1807 $success_message = 'forums_thread_deleted';
1808 if (count($threadIds) > 1) {
1809 $success_message = 'forums_threads_deleted';
1810 }
1811
1812 $threads = [];
1813 array_walk($threadIds, function (int $threadId) use (&$threads): void {
1814 $thread = new ilForumTopic($threadId);
1815 $this->ensureThreadBelongsToForum($this->object->getId(), $thread);
1816
1817 $threads[] = $thread;
1818 });
1819
1820 $frm->setForumId($forumObj->getId());
1821 $frm->setForumRefId($forumObj->getRefId());
1822 foreach ($threads as $thread) {
1823 $first_node = $frm->getFirstPostNode($thread->getId());
1824 if (isset($first_node['pos_pk']) && (int) $first_node['pos_pk']) {
1825 $frm->deletePost((int) $first_node['pos_pk']);
1826 $this->tpl->setOnScreenMessage('info', $this->lng->txt($success_message), true);
1827 }
1828 }
1829 $this->ctrl->redirect($this, 'showThreads');
1830 }
1831
1832 public function confirmDeleteThreadsObject(): void
1833 {
1834 $thread_ids = $this->retrieveThreadIds();
1835 if ($thread_ids === []) {
1836 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_at_least_one_thread'));
1837 $this->ctrl->redirect($this, 'showThreads');
1838 }
1839
1840 if (!$this->is_moderator) {
1841 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1842 }
1843
1844 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
1845 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1846 }
1847
1849 $threads = [];
1850 array_walk($thread_ids, function (int $threadId) use (&$threads): void {
1851 $thread = new ilForumTopic($threadId);
1852 $this->ensureThreadBelongsToForum($this->object->getId(), $thread);
1853
1854 $threads[] = $thread;
1855 });
1856
1857 $c_gui = new ilConfirmationGUI();
1858
1859 $c_gui->setFormAction($this->ctrl->getFormAction($this, 'performDeleteThreads'));
1860 $c_gui->setHeaderText($this->lng->txt('frm_sure_delete_threads'));
1861 $c_gui->setCancel($this->lng->txt('cancel'), 'showThreads');
1862 $c_gui->setConfirm($this->lng->txt('confirm'), 'performDeleteThreads');
1863
1864 foreach ($threads as $thread) {
1865 $c_gui->addItem('thread_ids[]', (string) $thread->getId(), $thread->getSubject());
1866 }
1867
1868 $this->confirmation_gui_html = $c_gui->getHTML();
1869
1870 $this->hideToolbar(true);
1871 $this->tpl->setContent($c_gui->getHTML());
1872 }
1873
1874 protected function confirmDeleteThreadDraftsObject(): void
1875 {
1876 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
1877 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1878 }
1879
1880 $draft_ids = $this->http->wrapper()->query()->retrieve(
1881 'forum_drafts_delete_draft_ids',
1882 $this->refinery->byTrying([
1883 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
1884 $this->refinery->always([])
1885 ])
1886 );
1887
1888 if ($draft_ids === []) {
1889 $draft_ids = $this->http->wrapper()->query()->retrieve(
1890 'forum_drafts_delete_draft_ids',
1891 $this->refinery->byTrying([
1892 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string()),
1893 $this->refinery->always([])
1894 ])
1895 );
1896
1897 if (!isset($draft_ids[0]) || $draft_ids[0] !== 'ALL_OBJECTS') {
1898 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_at_least_one_thread'));
1899 $this->showThreadsObject();
1900 return;
1901 }
1902
1903 $draft_ids = array_filter(array_map(
1904 static fn(array $draft): int => $draft['draft_id'] ?? 0,
1906 $this->user->getId(),
1907 ilObjForum::lookupForumIdByObjId($this->object->getId())
1908 )
1909 ));
1910 }
1911
1912 $confirmation = new ilConfirmationGUI();
1913 $confirmation->setFormAction($this->ctrl->getFormAction($this, 'deleteThreadDrafts'));
1914 $confirmation->setHeaderText($this->lng->txt('sure_delete_drafts'));
1915 $confirmation->setCancel($this->lng->txt('cancel'), 'showThreads');
1916 $confirmation->setConfirm($this->lng->txt('confirm'), 'deleteThreadDrafts');
1917 $instances = ilForumPostDraft::getDraftInstancesByUserId($this->user->getId());
1918 foreach ($draft_ids as $draftId) {
1919 if (array_key_exists($draftId, $instances)) {
1920 $confirmation->addItem('draft_ids[]', (string) $draftId, $instances[$draftId]->getPostSubject());
1921 }
1922 }
1923
1924 $this->tpl->setContent($confirmation->getHTML());
1925 }
1926
1927 public function prepareThreadScreen(ilObjForum $a_forum_obj): void
1928 {
1929 $this->ilHelp->setScreenIdComponent('frm');
1930
1931 $this->tpl->loadStandardTemplate();
1932
1933 $this->tpl->setTitleIcon(ilObject::_getIcon(0, 'big', 'frm'));
1934
1935 $this->tabs_gui->setBackTarget(
1936 $this->lng->txt('frm_all_threads'),
1937 $this->ctrl->getLinkTarget(
1938 $this,
1939 'showThreads'
1940 )
1941 );
1942
1944 $frm = $a_forum_obj->Forum;
1945 $frm->setForumId($a_forum_obj->getId());
1946 }
1947
1948 public function performPostActivationObject(): void
1949 {
1950 if (!$this->is_moderator) {
1951 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1952 }
1953
1954 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
1955 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
1956 }
1957
1958 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
1959
1960 $this->objCurrentPost->activatePost();
1961 $GLOBALS['ilAppEventHandler']->raise(
1962 'components/ILIAS/Forum',
1963 'activatedPost',
1964 [
1965 'object' => $this->object,
1966 'ref_id' => $this->object->getRefId(),
1967 'post' => $this->objCurrentPost
1968 ]
1969 );
1970 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_post_was_activated'), true);
1971
1972 $this->viewThreadObject();
1973 }
1974
1975 private function deletePostingObject(): void
1976 {
1977 if (
1978 !$this->user->isAnonymous() &&
1979 !$this->objCurrentTopic->isClosed() && (
1980 $this->is_moderator ||
1981 ($this->objCurrentPost->isOwner($this->user->getId()) && !$this->objCurrentPost->hasReplies())
1982 )
1983 ) {
1984 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
1985
1986 $oForumObjects = $this->getForumObjects();
1987 $forumObj = $oForumObjects['forumObj'];
1988
1989 $frm = new ilForum();
1990 $frm->setForumId($forumObj->getId());
1991 $frm->setForumRefId($forumObj->getRefId());
1992 $dead_thr = $frm->deletePost($this->objCurrentPost->getId());
1993
1994 // if complete thread was deleted ...
1995 if ($dead_thr === $this->objCurrentTopic->getId()) {
1996 $frm->setMDB2WhereCondition('top_frm_fk = %s ', ['integer'], [$forumObj->getId()]);
1997 $topicData = $frm->getOneTopic();
1998 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_post_deleted'), true);
1999 if ($topicData->getTopNumThreads() > 0) {
2000 $this->ctrl->redirect($this, 'showThreads');
2001 } else {
2002 $this->ctrl->redirect($this, 'createThread');
2003 }
2004 }
2005 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_post_deleted'), true);
2006 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
2007 $this->ctrl->redirect($this, 'viewThread');
2008 }
2009
2010 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2011 }
2012
2013 private function deletePostingDraftObject(): void
2014 {
2015 $this->deleteSelectedDraft();
2016 }
2017
2018 private function revokeCensorshipObject(): void
2019 {
2020 $this->handleCensorship(true);
2021 }
2022
2023 private function addCensorshipObject(): void
2024 {
2025 $this->handleCensorship();
2026 }
2027
2028 private function getModalActions(): string
2029 {
2030 $modalString = '';
2031 foreach ($this->modalActionsContainer as $modal) {
2032 $modalString .= $this->uiRenderer->render($modal);
2033 }
2034
2035 return $modalString;
2036 }
2037
2038 private function handleCensorship(bool $wasRevoked = false): void
2039 {
2040 $message = '';
2041 if ($this->is_moderator && !$this->objCurrentTopic->isClosed()) {
2042 if ($this->http->wrapper()->post()->has('formData')) {
2043 $formData = $this->http->wrapper()->post()->retrieve(
2044 'formData',
2045 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string())
2046 );
2047 $message = $this->handleFormInput($formData['cens_message']);
2048 }
2049
2050 if ($message === '' && $this->http->wrapper()->post()->has('cens_message')) {
2051 $cens_message = $this->http->wrapper()->post()->retrieve(
2052 'cens_message',
2053 $this->refinery->kindlyTo()->string()
2054 );
2055 $message = $this->handleFormInput($cens_message);
2056 }
2057 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
2058
2059 $oForumObjects = $this->getForumObjects();
2060 $frm = $oForumObjects['frm'];
2061
2062 if ($wasRevoked) {
2063 $frm->postCensorship($this->object, $message, $this->objCurrentPost->getId());
2064 $this->tpl->setOnScreenMessage('success', $this->lng->txt('frm_censorship_revoked'));
2065 } else {
2066 $frm->postCensorship($this->object, $message, $this->objCurrentPost->getId(), 1);
2067 $this->tpl->setOnScreenMessage('success', $this->lng->txt('frm_censorship_applied'));
2068 }
2069
2070 $this->viewThreadObject();
2071 return;
2072 }
2073
2074 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2075 }
2076
2077 public function askForPostActivationObject(): void
2078 {
2079 if (!$this->is_moderator) {
2080 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2081 }
2082
2083 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
2084 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2085 }
2086
2087 $this->setDisplayConfirmPostActivation(true);
2088
2089 $this->viewThreadObject();
2090 }
2091
2092 public function setDisplayConfirmPostActivation(bool $status = false): void
2093 {
2094 $this->display_confirm_post_activation = $status;
2095 }
2096
2097 public function displayConfirmPostActivation(): bool
2098 {
2099 return $this->display_confirm_post_activation;
2100 }
2101
2102 protected function toggleThreadNotificationObject(): void
2103 {
2104 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
2105 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2106 }
2107
2108 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentTopic);
2109
2110 if ($this->objCurrentTopic->isNotificationEnabled($this->user->getId())) {
2111 $this->objCurrentTopic->disableNotification($this->user->getId());
2112 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_notification_disabled'), true);
2113 } else {
2114 $this->objCurrentTopic->enableNotification($this->user->getId());
2115 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_notification_enabled'), true);
2116 }
2117
2118 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
2119 $this->ctrl->redirect($this, 'viewThread');
2120 }
2121
2122 protected function toggleStickinessObject(): void
2123 {
2124 if (!$this->is_moderator) {
2125 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2126 }
2127
2128 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
2129 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2130 }
2131
2132 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentTopic);
2133
2134 if ($this->objCurrentTopic->isSticky()) {
2135 $this->objCurrentTopic->unmakeSticky();
2136 } else {
2137 $this->objCurrentTopic->makeSticky();
2138 }
2139
2140 $this->viewThreadObject();
2141 }
2142
2143 public function cancelPostObject(): void
2144 {
2145 $this->requestAction = '';
2146 $draft_id = $this->retrieveDraftId(true);
2147 if ($draft_id > 0) {
2148 $draft = ilForumPostDraft::newInstanceByDraftId($draft_id);
2149 if ($this->hasDraftAccess($draft)) {
2150 $draft->deleteDraftsByDraftIds([$draft_id]);
2151 }
2152 }
2153
2154 $this->viewThreadObject();
2155 }
2156
2157 public function cancelDraftObject(): void
2158 {
2159 $this->requestAction = '';
2160 $draft_id = $this->retrieveDraftId();
2161 if ($draft_id > 0) {
2162 $history_entry = new ilForumDraftsHistory();
2163 $history_entry->populateWithFirstAutosaveByDraftId($draft_id);
2164 $draft = ilForumPostDraft::newInstanceByDraftId($history_entry->getDraftId());
2165 if ($this->hasDraftAccess($draft)) {
2166 $draft->setPostSubject($history_entry->getPostSubject());
2167 $draft->setPostMessage($history_entry->getPostMessage());
2168
2170 $history_entry->getPostMessage(),
2172 $history_entry->getHistoryId(),
2174 $draft->getDraftId()
2175 );
2176
2177 $draft->updateDraft();
2178
2179 $history_entry->deleteHistoryByDraftIds([$draft->getDraftId()]);
2180 }
2181 }
2182
2183 $this->ctrl->clearParameters($this);
2184 $this->viewThreadObject();
2185 }
2186
2188 {
2189 $form = new ilPropertyFormGUI();
2190 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
2191 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
2192 $this->ctrl->setParameter(
2193 $this,
2194 'orderby',
2195 $this->getOrderByParam()
2196 );
2197 $form->setFormAction($this->ctrl->getFormAction($this, 'performPostActivation'));
2198 $this->ctrl->clearParameters($this);
2199 $form->setId('frm_activate_post_' . $node->getId());
2200 $form_id = $form->getId();
2201 $message = $this->uiFactory->messageBox()->confirmation($this->lng->txt('activate_post_txt'));
2202 $submitBtn = $this->uiFactory->button()->primary(
2203 $this->lng->txt('activate_only_current'),
2204 '#'
2205 )->withOnLoadCode(
2206 static function (string $id) use ($form_id): string {
2207 return "
2208 (function () {
2209 const button = document.getElementById('$id');
2210 if (!button) return;
2211
2212 const form = document.getElementById('form_$form_id');
2213 if (!form) return;
2214
2215 button.addEventListener('click', (event) => {
2216 event.preventDefault();
2217 form.submit();
2218 }, true);
2219 }());
2220 ";
2221 }
2222 );
2223 $modal = $this->uiFactory->modal()->roundtrip(
2224 $this->lng->txt('activate_only_current'),
2225 [$this->uiFactory->legacy()->content($form->getHTML()), $message]
2226 )->withActionButtons([$submitBtn]);
2227 $action_button = $this->uiFactory->button()->standard($this->lng->txt('activate_post'), '#')->withOnClick(
2228 $modal->getShowSignal()
2229 );
2230 $this->modalActionsContainer[] = $modal;
2231 $this->ctrl->clearParameters($this);
2232
2233 return $action_button;
2234 }
2235
2236 public function getCensorshipFormHTML(): string
2237 {
2239 $frm = $this->object->Forum;
2240 $form_tpl = new ilTemplate('tpl.frm_censorship_post_form.html', true, true, 'components/ILIAS/Forum');
2241
2242 $form_tpl->setVariable('ANCHOR', $this->objCurrentPost->getId());
2243 $form_tpl->setVariable('SPACER', '<hr noshade="noshade" width="100%" size="1" align="center" />');
2244 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
2245 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
2246 $this->ctrl->setParameter(
2247 $this,
2248 'orderby',
2249 $this->getOrderByParam()
2250 );
2251 $form_tpl->setVariable('FORM_ACTION', $this->ctrl->getFormAction($this, 'viewThread'));
2252 $this->ctrl->clearParameters($this);
2253 $form_tpl->setVariable('TXT_CENS_MESSAGE', $this->lng->txt('forums_the_post'));
2254 $form_tpl->setVariable('TXT_CENS_COMMENT', $this->lng->txt('forums_censor_comment') . ':');
2255 $form_tpl->setVariable('CENS_MESSAGE', $frm->prepareText((string) $this->objCurrentPost->getCensorshipComment(), 2));
2256
2257 if ($this->objCurrentPost->isCensored()) {
2258 $form_tpl->setVariable('TXT_CENS', $this->lng->txt('forums_info_censor2_post'));
2259 $form_tpl->setVariable('YES_BUTTON', $this->lng->txt('confirm'));
2260 $form_tpl->setVariable('NO_BUTTON', $this->lng->txt('cancel'));
2261 $form_tpl->setVariable('CMD_REVOKE_CENSORSHIP', 'revokeCensorship');
2262 $form_tpl->setVariable('CMD_CANCEL_REVOKE_CENSORSHIP', 'viewThread');
2263 } else {
2264 $form_tpl->setVariable('TXT_CENS', $this->lng->txt('forums_info_censor_post'));
2265 $form_tpl->setVariable('CANCEL_BUTTON', $this->lng->txt('cancel'));
2266 $form_tpl->setVariable('CONFIRM_BUTTON', $this->lng->txt('confirm'));
2267 $form_tpl->setVariable('CMD_ADD_CENSORSHIP', 'addCensorship');
2268 $form_tpl->setVariable('CMD_CANCEL_ADD_CENSORSHIP', 'viewThread');
2269 }
2270
2271 return $form_tpl->get();
2272 }
2273
2274 private function initReplyEditForm(): void
2275 {
2276 $isReply = in_array($this->requestAction, ['showreply', 'ready_showreply']);
2277 $isDraft = in_array($this->requestAction, ['publishDraft', 'editdraft']);
2278
2279 $draft_id = $this->retrieveDraftId();
2280
2281 // init objects
2282 $oForumObjects = $this->getForumObjects();
2283 $frm = $oForumObjects['frm'];
2284 $oFDForum = $oForumObjects['file_obj'];
2285
2286 $this->replyEditForm = new ilPropertyFormGUI();
2287 $this->replyEditForm->setId('id_showreply');
2288 $this->replyEditForm->setTableWidth('100%');
2289 $cancel_cmd = 'cancelPost';
2290 if (in_array($this->requestAction, ['showreply', 'ready_showreply'])) {
2291 $this->ctrl->setParameter($this, 'action', 'ready_showreply');
2292 } elseif (in_array($this->requestAction, ['showdraft', 'editdraft'])) {
2293 $this->ctrl->setParameter($this, 'action', $this->requestAction);
2294 $this->ctrl->setParameter($this, 'draft_id', $draft_id);
2295 } else {
2296 $this->ctrl->setParameter($this, 'action', 'ready_showedit');
2297 }
2298
2299 $this->ctrl->setParameter($this, 'page', (int) ($this->httpRequest->getQueryParams()['page'] ?? 0));
2300 $this->ctrl->setParameter(
2301 $this,
2302 'orderby',
2303 $this->getOrderByParam()
2304 );
2305 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
2306 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
2307 if ($this->isTopLevelReplyCommand()) {
2308 $this->replyEditForm->setFormAction(
2309 $this->ctrl->getFormAction($this, 'saveTopLevelPost', 'frm_page_bottom')
2310 );
2311 } elseif (in_array($this->requestAction, ['publishDraft', 'editdraft'])) {
2312 $this->replyEditForm->setFormAction(
2313 $this->ctrl->getFormAction($this, 'publishDraft', (string) $this->objCurrentPost->getId())
2314 );
2315 } else {
2316 $this->replyEditForm->setFormAction(
2317 $this->ctrl->getFormAction($this, 'savePost', (string) $this->objCurrentPost->getId())
2318 );
2319 }
2320 $this->ctrl->clearParameters($this);
2321
2322 if ($isReply) {
2323 $this->replyEditForm->setTitle($this->lng->txt('forums_your_reply'));
2324 } elseif ($isDraft) {
2325 $this->replyEditForm->setTitle($this->lng->txt('forums_edit_draft'));
2326 } else {
2327 $this->replyEditForm->setTitle($this->lng->txt('forums_edit_post'));
2328 }
2329
2330 if (
2331 $this->isWritingWithPseudonymAllowed() &&
2332 in_array($this->requestAction, ['showreply', 'ready_showreply', 'editdraft'])
2333 ) {
2334 $oAnonymousNameGUI = new ilTextInputGUI($this->lng->txt('forums_your_name'), 'alias');
2335 $oAnonymousNameGUI->setMaxLength(64);
2336 $oAnonymousNameGUI->setInfo(sprintf($this->lng->txt('forums_use_alias'), $this->lng->txt('forums_anonymous')));
2337
2338 $this->replyEditForm->addItem($oAnonymousNameGUI);
2339 }
2340
2341 $oSubjectGUI = new ilTextInputGUI($this->lng->txt('forums_subject'), 'subject');
2342 $oSubjectGUI->setMaxLength(255);
2343 $oSubjectGUI->setRequired(true);
2344
2345 if ($this->objProperties->getSubjectSetting() === 'empty_subject') {
2346 $oSubjectGUI->setInfo($this->lng->txt('enter_new_subject'));
2347 }
2348
2349 $this->replyEditForm->addItem($oSubjectGUI);
2350
2351 $oPostGUI = new ilTextAreaInputGUI(
2352 $isReply ? $this->lng->txt('forums_your_reply') : $this->lng->txt('forums_edit_post'),
2353 'message'
2354 );
2355 $oPostGUI->setRequired(true);
2356 $oPostGUI->setRows(15);
2357 $oPostGUI->setUseRte(true);
2358
2359 $quotingAllowed = (
2360 !$this->isTopLevelReplyCommand() && (
2361 ($isReply && $this->objCurrentPost->getDepth() >= 2) ||
2362 (!$isDraft && !$isReply && $this->objCurrentPost->getDepth() > 2) ||
2363 ($isDraft && $this->objCurrentPost->getDepth() >= 2)
2364 )
2365 );
2366
2367 $oPostGUI->removePlugin('advlink');
2368 $oPostGUI->setRTERootBlockElement('');
2369 $oPostGUI->usePurifier(true);
2370 $oPostGUI->disableButtons([
2371 'charmap',
2372 'undo',
2373 'redo',
2374 'alignleft',
2375 'aligncenter',
2376 'alignright',
2377 'alignjustify',
2378 'anchor',
2379 'fullscreen',
2380 'cut',
2381 'copy',
2382 'paste',
2383 'pastetext',
2384 'formatselect'
2385 ]);
2386
2387 if (in_array($this->requestAction, ['showreply', 'ready_showreply', 'showdraft', 'editdraft'])) {
2388 $oPostGUI->setRTESupport(
2389 $this->user->getId(),
2390 'frm~',
2391 'frm_post',
2392 'tpl.tinymce_frm_post.js',
2393 false,
2394 '5.6.0'
2395 );
2396 } else {
2397 $oPostGUI->setRTESupport(
2398 $this->objCurrentPost->getId(),
2399 'frm',
2400 'frm_post',
2401 'tpl.tinymce_frm_post.js',
2402 false,
2403 '5.6.0'
2404 );
2405 }
2406
2407 $oPostGUI->setPurifier(ilHtmlPurifierFactory::getInstanceByType('frm_post'));
2408 $oPostGUI->setInfo($this->lng->txt('latex_edit_info'));
2409
2410 $this->replyEditForm->addItem($oPostGUI);
2411
2412 $umail = new ilMail($this->user->getId());
2413 if (!$this->user->isAnonymous() &&
2414 !$this->objProperties->isAnonymized() &&
2415 $this->rbac->system()->checkAccess('internal_mail', $umail->getMailObjectReferenceId()) &&
2416 !$frm->isThreadNotificationEnabled($this->user->getId(), $this->objCurrentPost->getThreadId())) {
2417 $oNotificationGUI = new ilCheckboxInputGUI($this->lng->txt('forum_direct_notification'), 'notify');
2418 $oNotificationGUI->setInfo($this->lng->txt('forum_notify_me'));
2419 $this->replyEditForm->addItem($oNotificationGUI);
2420 }
2421
2422 if ($this->objProperties->isFileUploadAllowed()) {
2423 $oFileUploadGUI = new ilFileWizardInputGUI($this->lng->txt('forums_attachments_add'), 'userfile');
2424 $oFileUploadGUI->setFilenames([0 => '']);
2425 $this->replyEditForm->addItem($oFileUploadGUI);
2426 }
2427
2428 $attachments_of_node = $oFDForum->getFilesOfPost();
2429 if (count($attachments_of_node) && in_array($this->requestAction, ['showedit', 'ready_showedit'])) {
2430 $oExistingAttachmentsGUI = new ilCheckboxGroupInputGUI($this->lng->txt('forums_delete_file'), 'del_file');
2431 foreach ($oFDForum->getFilesOfPost() as $file) {
2432 $oExistingAttachmentsGUI->addOption(new ilCheckboxOption($file['name'], $file['md5']));
2433 }
2434 $this->replyEditForm->addItem($oExistingAttachmentsGUI);
2435 }
2436
2438 if (in_array($this->requestAction, ['showdraft', 'editdraft'])) {
2439 $draftInfoGUI = new ilNonEditableValueGUI('', 'autosave_info', true);
2440 $draftInfoGUI->setValue(sprintf(
2441 $this->lng->txt('autosave_draft_info'),
2443 ));
2444 $this->replyEditForm->addItem($draftInfoGUI);
2445 } elseif (!in_array($this->requestAction, ['showedit', 'ready_showedit'])) {
2446 $draftInfoGUI = new ilNonEditableValueGUI('', 'autosave_info', true);
2447 $draftInfoGUI->setValue(sprintf(
2448 $this->lng->txt('autosave_post_draft_info'),
2450 ));
2451 $this->replyEditForm->addItem($draftInfoGUI);
2452 }
2453 }
2454
2455 $selected_draft_id = $draft_id;
2456 $draftObj = new ilForumPostDraft(
2457 $this->user->getId(),
2458 $this->objCurrentPost->getId(),
2459 $selected_draft_id
2460 );
2461 if ($draftObj->getDraftId() > 0) {
2462 $oFDForumDrafts = new ilFileDataForumDrafts(0, $draftObj->getDraftId());
2463 $files_of_draft = $oFDForumDrafts->getFilesOfPost();
2464
2465 if ($files_of_draft !== []) {
2466 $oExistingAttachmentsGUI = new ilCheckboxGroupInputGUI(
2467 $this->lng->txt('forums_delete_file'),
2468 'del_file'
2469 );
2470 foreach ($files_of_draft as $file) {
2471 $oExistingAttachmentsGUI->addOption(new ilCheckboxOption($file['name'], $file['md5']));
2472 }
2473 $this->replyEditForm->addItem($oExistingAttachmentsGUI);
2474 }
2475 }
2476
2477 if ($this->isTopLevelReplyCommand()) {
2478 $this->replyEditForm->addCommandButton('saveTopLevelPost', $this->lng->txt('create'));
2479 } elseif ($this->requestAction === 'editdraft' && ilForumPostDraft::isSavePostDraftAllowed()) {
2480 $this->replyEditForm->addCommandButton('publishDraft', $this->lng->txt('publish'));
2481 } else {
2482 $this->replyEditForm->addCommandButton('savePost', $this->lng->txt('save'));
2483 }
2484 $hidden_draft_id = new ilHiddenInputGUI('draft_id');
2485 $auto_save_draft_id = $this->retrieveDraftId();
2486
2487 $hidden_draft_id->setValue((string) $auto_save_draft_id);
2488 $this->replyEditForm->addItem($hidden_draft_id);
2489
2490 if (in_array($this->requestAction, ['showreply', 'ready_showreply', 'editdraft'])) {
2491 $show_rte = $this->http->wrapper()->post()->retrieve(
2492 'show_rte',
2493 $this->refinery->byTrying([$this->refinery->kindlyTo()->int(), $this->refinery->always(0)])
2494 );
2495
2496 if ($show_rte) {
2497 (new ilRTESettings($this->lng, $this->user))->setRichTextEditorUserState($show_rte);
2498 }
2499
2500 if ($quotingAllowed) {
2501 $this->replyEditForm->addCommandButton('quotePost', $this->lng->txt('forum_add_quote'));
2502 }
2503
2504 if (!$this->user->isAnonymous() &&
2505 in_array($this->requestAction, ['editdraft', 'showreply', 'ready_showreply']) &&
2508 $this->decorateWithAutosave($this->replyEditForm);
2509 }
2510
2511 if ($this->requestAction === 'editdraft') {
2512 $this->replyEditForm->addCommandButton('updateDraft', $this->lng->txt('save_message'));
2513 } elseif ($this->isTopLevelReplyCommand()) {
2514 $this->replyEditForm->addCommandButton('saveTopLevelDraft', $this->lng->txt('save_message'));
2515 } else {
2516 $this->replyEditForm->addCommandButton('saveAsDraft', $this->lng->txt('save_message'));
2517 }
2518
2519 $cancel_cmd = 'cancelDraft';
2520 }
2521 }
2522 $this->replyEditForm->addCommandButton($cancel_cmd, $this->lng->txt('cancel'));
2523 }
2524
2526 {
2527 if ($this->replyEditForm === null) {
2528 $this->initReplyEditForm();
2529 }
2530
2531 return $this->replyEditForm;
2532 }
2533
2534 public function createTopLevelPostObject(): void
2535 {
2536 $draft_obj = null;
2537 $draft_id = $this->retrieveDraftId();
2538
2539 if ($draft_id > 0 && !$this->user->isAnonymous()
2541 $draft_obj = new ilForumPostDraft(
2542 $this->user->getId(),
2543 $this->objCurrentPost->getId(),
2544 $draft_id
2545 );
2546 }
2547
2548 if ($draft_obj instanceof ilForumPostDraft && $draft_obj->getDraftId() > 0) {
2549 $this->ctrl->setParameter($this, 'action', 'editdraft');
2550 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
2551 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
2552 $this->ctrl->setParameter($this, 'draft_id', $draft_obj->getDraftId());
2553 $this->ctrl->setParameter($this, 'page', 0);
2554 $this->ctrl->setParameter(
2555 $this,
2556 'orderby',
2557 $this->getOrderByParam()
2558 );
2559 $this->ctrl->redirect($this, 'editDraft');
2560 } else {
2561 $this->viewThreadObject();
2562 }
2563 }
2564
2565 public function saveTopLevelPostObject(): void
2566 {
2567 $this->savePostObject();
2568 }
2569
2570 public function publishSelectedDraftObject(): void
2571 {
2572 $draft_id = $this->retrieveDraftId();
2573 if ($draft_id > 0) {
2574 $this->publishDraftObject(false);
2575 }
2576 }
2577
2578 public function publishDraftObject(bool $use_replyform = true): void
2579 {
2581 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
2582 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2583 }
2584
2585 if (!$this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
2586 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2587 }
2588
2589 if ($this->objCurrentTopic->getId() === 0) {
2590 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_deleted'), true);
2591 $this->ctrl->redirect($this);
2592 }
2593
2594 if ($this->objCurrentTopic->isClosed()) {
2595 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_closed'), true);
2596 $this->ctrl->redirect($this);
2597 }
2598
2599 if ($this->objCurrentPost->getId() === 0) {
2600 $this->requestAction = '';
2601 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_parent_deleted'));
2602 $this->viewThreadObject();
2603 return;
2604 }
2605
2606 $draft = new ilForumPostDraft($this->user->getId(), $this->objCurrentPost->getId(), $this->retrieveDraftId());
2607 $this->checkDraftAccess($draft->getDraftId());
2608
2609 if ($use_replyform) {
2610 $oReplyEditForm = $this->getReplyEditForm();
2611 if (!$oReplyEditForm->checkInput()) {
2612 $oReplyEditForm->setValuesByPost();
2613 $this->viewThreadObject();
2614 return;
2615 }
2616 $post_subject = $oReplyEditForm->getInput('subject');
2617 $post_message = $oReplyEditForm->getInput('message');
2618 $mob_direction = 0;
2619 } else {
2620 $post_subject = $draft->getPostSubject();
2621 $post_message = $draft->getPostMessage();
2622 $mob_direction = 1;
2623 }
2624
2625 $oForumObjects = $this->getForumObjects();
2626 $frm = $oForumObjects['frm'];
2627 $frm->setMDB2WhereCondition(' top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
2628
2629 // reply: new post
2630 $status = true;
2631 $send_activation_mail = false;
2632
2633 if ($this->objProperties->isPostActivationEnabled()) {
2634 if (!$this->is_moderator) {
2635 $status = false;
2636 $send_activation_mail = true;
2637 } elseif ($this->objCurrentPost->isAnyParentDeactivated()) {
2638 $status = false;
2639 }
2640 }
2641
2642 $newPost = $frm->generatePost(
2643 $draft->getForumId(),
2644 $draft->getThreadId(),
2645 $this->user->getId(),
2646 $draft->getPostDisplayUserId(),
2647 ilRTE::_replaceMediaObjectImageSrc($post_message, $mob_direction),
2648 $draft->getPostId(),
2649 $draft->isNotificationEnabled(),
2650 $this->handleFormInput($post_subject, false),
2651 $draft->getPostUserAlias(),
2652 '',
2653 $status,
2654 $send_activation_mail
2655 );
2656
2657 $this->object->markPostRead(
2658 $this->user->getId(),
2659 $this->objCurrentTopic->getId(),
2660 $this->objCurrentPost->getId()
2661 );
2662
2663 $uploadedObjects = ilObjMediaObject::_getMobsOfObject('frm~:html', $this->user->getId());
2664
2665 foreach ($uploadedObjects as $mob) {
2666 ilObjMediaObject::_removeUsage($mob, 'frm~:html', $this->user->getId());
2667 ilObjMediaObject::_saveUsage($mob, 'frm:html', $newPost);
2668 }
2669 ilForumUtil::saveMediaObjects($post_message, 'frm:html', $newPost, $mob_direction);
2670 $post_obj = new ilForumPost($newPost);
2671
2672 if ($draft->getRCID() > 0) {
2673 $post_obj->setRCID($draft->getRCID());
2674 $post_obj->update();
2675 }
2676
2677 if ($this->objProperties->isFileUploadAllowed()) {
2678 $file = $_FILES['userfile'] ?? [];
2679 if (is_array($file) && !empty($file)) {
2680 $tmp_file_obj = new ilFileDataForum($this->object->getId(), $newPost);
2681 $tmp_file_obj->storeUploadedFiles();
2682 }
2683 }
2684
2685 $GLOBALS['ilAppEventHandler']->raise(
2686 'components/ILIAS/Forum',
2687 'publishedDraft',
2688 [
2689 'draftObj' => $draft,
2690 'obj_id' => $this->object->getId(),
2691 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed()
2692 ]
2693 );
2694 $draft->deleteDraft();
2695
2696 $GLOBALS['ilAppEventHandler']->raise(
2697 'components/ILIAS/Forum',
2698 'createdPost',
2699 [
2700 'object' => $this->object,
2701 'ref_id' => $this->object->getRefId(),
2702 'post' => $post_obj,
2703 'notify_moderators' => $send_activation_mail
2704 ]
2705 );
2706
2707 $message = '';
2708 if (!$this->is_moderator && !$status) {
2709 $message .= $this->lng->txt('forums_post_needs_to_be_activated');
2710 } else {
2711 $message .= $this->lng->txt('forums_post_new_entry');
2712 }
2713
2714 $frm_session_values = ilSession::get('frm');
2715 if (is_array($frm_session_values)) {
2716 $frm_session_values[$this->objCurrentTopic->getId()]['openTreeNodes'][] = $this->objCurrentPost->getId();
2717 }
2718 ilSession::set('frm', $frm_session_values);
2719
2720 $this->ctrl->clearParameters($this);
2721 $this->tpl->setOnScreenMessage('success', $message, true);
2722 $this->ctrl->setParameter($this, 'pos_pk', $newPost);
2723 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
2724
2725 $this->ctrl->redirect($this, 'viewThread');
2726 }
2727
2728 public function savePostObject(): void
2729 {
2730 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
2731 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2732 }
2733
2734 if ($this->objCurrentTopic->getId() === 0) {
2735 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_deleted'), true);
2736 $this->ctrl->redirect($this);
2737 }
2738
2739 if ($this->objCurrentTopic->isClosed()) {
2740 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_closed'), true);
2741 $this->ctrl->redirect($this);
2742 }
2743
2744 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentTopic);
2745
2746 $oReplyEditForm = $this->getReplyEditForm();
2747 if ($oReplyEditForm->checkInput()) {
2748 if ($this->objCurrentPost->getId() === 0) {
2749 $this->requestAction = '';
2750 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_parent_deleted'), true);
2751 $this->viewThreadObject();
2752 return;
2753 }
2754
2755 $oForumObjects = $this->getForumObjects();
2756 $forumObj = $oForumObjects['forumObj'];
2757 $frm = $oForumObjects['frm'];
2758 $frm->setMDB2WhereCondition(' top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
2759 $topicData = $frm->getOneTopic();
2760
2761 $autosave_draft_id = $this->http->wrapper()->post()->retrieve(
2762 'draft_id',
2763 $this->refinery->byTrying([$this->refinery->kindlyTo()->int(), $this->refinery->always(0)])
2764 );
2765
2766 if ($this->requestAction === 'ready_showreply') {
2767 if (!$this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
2768 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2769 }
2770
2771 $status = true;
2772 $send_activation_mail = false;
2773
2774 if ($this->objProperties->isPostActivationEnabled()) {
2775 if (!$this->is_moderator) {
2776 $status = false;
2777 $send_activation_mail = true;
2778 } elseif ($this->objCurrentPost->isAnyParentDeactivated()) {
2779 $status = false;
2780 }
2781 }
2782
2783 if ($this->isWritingWithPseudonymAllowed()) {
2784 if ((string) $oReplyEditForm->getInput('alias') === '') {
2785 $user_alias = $this->lng->txt('forums_anonymous');
2786 } else {
2787 $user_alias = $oReplyEditForm->getInput('alias');
2788 }
2789 $display_user_id = 0;
2790 } else {
2791 $user_alias = $this->user->getLogin();
2792 $display_user_id = $this->user->getId();
2793 }
2794
2795 $newPost = $frm->generatePost(
2796 $topicData->getTopPk(),
2797 $this->objCurrentTopic->getId(),
2798 $this->user->getId(),
2799 $display_user_id,
2800 ilRTE::_replaceMediaObjectImageSrc($oReplyEditForm->getInput('message')),
2801 $this->objCurrentPost->getId(),
2802 $oReplyEditForm->getInput('notify') && !$this->user->isAnonymous(),
2803 $this->handleFormInput($oReplyEditForm->getInput('subject'), false),
2804 $user_alias,
2805 '',
2806 $status,
2807 $send_activation_mail
2808 );
2809
2810 if ($autosave_draft_id > 0) {
2811 $draft = new ilForumPostDraft(
2812 $this->user->getId(),
2813 $this->objCurrentPost->getId(),
2814 $autosave_draft_id
2815 );
2816 if ($this->hasDraftAccess($draft)) {
2817 $draft->deleteDraft();
2818 }
2819 }
2820
2821 // mantis #8115: Mark parent as read
2822 $this->object->markPostRead(
2823 $this->user->getId(),
2824 $this->objCurrentTopic->getId(),
2825 $this->objCurrentPost->getId()
2826 );
2827
2828 // copy temporary media objects (frm~)
2830 $oReplyEditForm->getInput('message'),
2831 'frm~:html',
2832 $this->user->getId(),
2833 'frm:html',
2834 $newPost
2835 );
2836
2837 if ($this->objProperties->isFileUploadAllowed()) {
2838 $oFDForum = new ilFileDataForum($forumObj->getId(), $newPost);
2839 $file = $_FILES['userfile'];
2840 if (is_array($file) && !empty($file)) {
2841 $oFDForum->storeUploadedFiles();
2842 }
2843 }
2844
2845 $GLOBALS['ilAppEventHandler']->raise(
2846 'components/ILIAS/Forum',
2847 'createdPost',
2848 [
2849 'object' => $this->object,
2850 'ref_id' => $this->object->getRefId(),
2851 'post' => new ilForumPost($newPost),
2852 'notify_moderators' => $send_activation_mail
2853 ]
2854 );
2855
2856 $message = '';
2857 if (!$this->is_moderator && !$status) {
2858 $message .= $this->lng->txt('forums_post_needs_to_be_activated');
2859 } else {
2860 $message .= $this->lng->txt('forums_post_new_entry');
2861 }
2862
2863 $this->tpl->setOnScreenMessage('success', $message, true);
2864 $this->ctrl->clearParameters($this);
2865 $this->ctrl->setParameter($this, 'post_created_below', $this->objCurrentPost->getId());
2866 $this->ctrl->setParameter($this, 'pos_pk', $newPost);
2867 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
2868 } else {
2869 if ((!$this->is_moderator &&
2870 !$this->objCurrentPost->isOwner($this->user->getId())) || $this->objCurrentPost->isCensored() ||
2871 $this->user->isAnonymous()) {
2872 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
2873 }
2874
2875 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
2876
2877 $oldMediaObjects = ilObjMediaObject::_getMobsOfObject('frm:html', $this->objCurrentPost->getId());
2878 $curMediaObjects = ilRTE::_getMediaObjects($oReplyEditForm->getInput('message'));
2879 foreach ($oldMediaObjects as $oldMob) {
2880 $found = false;
2881 foreach ($curMediaObjects as $curMob) {
2882 if ($oldMob === $curMob) {
2883 $found = true;
2884 break;
2885 }
2886 }
2887 if (!$found && ilObjMediaObject::_exists($oldMob)) {
2888 ilObjMediaObject::_removeUsage($oldMob, 'frm:html', $this->objCurrentPost->getId());
2889 $mob_obj = new ilObjMediaObject($oldMob);
2890 $mob_obj->delete();
2891 }
2892 }
2893
2894 // save old activation status for send_notification decision
2895 $old_status_was_active = $this->objCurrentPost->isActivated();
2896
2897 // if active post has been edited posting mus be activated again by moderator
2898 $status = true;
2899 $send_activation_mail = false;
2900
2901 if ($this->objProperties->isPostActivationEnabled()) {
2902 if (!$this->is_moderator) {
2903 $status = false;
2904 $send_activation_mail = true;
2905 } elseif ($this->objCurrentPost->isAnyParentDeactivated()) {
2906 $status = false;
2907 }
2908 }
2909 $this->objCurrentPost->setStatus($status);
2910
2911 $this->objCurrentPost->setSubject($this->handleFormInput($oReplyEditForm->getInput('subject'), false));
2912 $this->objCurrentPost->setMessage(ilRTE::_replaceMediaObjectImageSrc(
2913 $oReplyEditForm->getInput('message')
2914 ));
2915 $this->objCurrentPost->setNotification($oReplyEditForm->getInput('notify') && !$this->user->isAnonymous());
2916 $this->objCurrentPost->setChangeDate(date('Y-m-d H:i:s'));
2917 $this->objCurrentPost->setUpdateUserId($this->user->getId());
2918
2919 if ($this->objCurrentPost->update()) {
2920 $this->objCurrentPost->reload();
2921
2922 // Change news item accordingly
2923 // note: $this->objCurrentPost->getForumId() does not give us the forum ID here (why?)
2925 $forumObj->getId(),
2926 'frm',
2927 $this->objCurrentPost->getId(),
2928 'pos'
2929 );
2930 if ($news_id > 0) {
2931 $news_item = new ilNewsItem($news_id);
2932 $news_item->setTitle($this->objCurrentPost->getSubject());
2933 $news_item->setContent(
2934 ilRTE::_replaceMediaObjectImageSrc($frm->prepareText(
2935 $this->objCurrentPost->getMessage()
2936 ), 1)
2937 );
2938
2939 if ($this->objCurrentPost->getMessage() !== strip_tags($this->objCurrentPost->getMessage())) {
2940 $news_item->setContentHtml(true);
2941 } else {
2942 $news_item->setContentHtml(false);
2943 }
2944 $news_item->update();
2945 }
2946
2947 $oFDForum = $oForumObjects['file_obj'];
2948
2949 $file2delete = $oReplyEditForm->getInput('del_file');
2950 if (is_array($file2delete) && count($file2delete)) {
2951 $oFDForum->unlinkFilesByMD5Filenames($file2delete);
2952 }
2953
2954 if ($this->objProperties->isFileUploadAllowed()) {
2955 $file = $_FILES['userfile'];
2956 if (is_array($file) && !empty($file)) {
2957 $oFDForum->storeUploadedFiles();
2958 }
2959 }
2960
2961 $GLOBALS['ilAppEventHandler']->raise(
2962 'components/ILIAS/Forum',
2963 'updatedPost',
2964 [
2965 'ref_id' => $this->object->getRefId(),
2966 'post' => $this->objCurrentPost,
2967 'notify_moderators' => $send_activation_mail,
2968 'old_status_was_active' => $old_status_was_active
2969 ]
2970 );
2971
2972 $this->tpl->setOnScreenMessage('success', $this->lng->txt('forums_post_modified'), true);
2973 }
2974
2975 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
2976 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
2977 $this->ctrl->setParameter($this, 'viewmode', $this->selectedSorting);
2978 }
2979 $this->ctrl->redirect($this, 'viewThread');
2980 } else {
2981 $this->requestAction = substr($this->requestAction, 6);
2982 }
2983 $this->viewThreadObject();
2984 }
2985
2986 private function hideToolbar($a_flag = null)
2987 {
2988 if ($a_flag === null) {
2989 return $this->hideToolbar;
2990 }
2991
2992 $this->hideToolbar = $a_flag;
2993 return $this;
2994 }
2995
2996 public function quotePostObject(): void
2997 {
2998 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
2999 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3000 }
3001
3002 if ($this->objCurrentTopic->isClosed()) {
3003 $this->requestAction = '';
3004 $this->viewThreadObject();
3005 return;
3006 }
3007
3008 $oReplyEditForm = $this->getReplyEditForm();
3009
3010 $oReplyEditForm->getItemByPostVar('subject')->setRequired(false);
3011 $oReplyEditForm->getItemByPostVar('message')->setRequired(false);
3012
3013 $oReplyEditForm->checkInput();
3014
3015 $oReplyEditForm->getItemByPostVar('subject')->setRequired(true);
3016 $oReplyEditForm->getItemByPostVar('message')->setRequired(true);
3017
3018 $this->requestAction = 'showreply';
3019
3020 $this->viewThreadObject();
3021 }
3022
3026 private function getForumObjects(): array
3027 {
3028 if ($this->forumObjects === null) {
3029 $forumObj = $this->object;
3030 $file_obj = new ilFileDataForum($forumObj->getId(), $this->objCurrentPost->getId());
3031 $frm = $forumObj->Forum;
3032 $frm->setForumId($forumObj->getId());
3033 $frm->setForumRefId($forumObj->getRefId());
3034
3035 $this->forumObjects['forumObj'] = $forumObj;
3036 $this->forumObjects['frm'] = $frm;
3037 $this->forumObjects['file_obj'] = $file_obj;
3038 }
3039
3040 return $this->forumObjects;
3041 }
3042
3043 public function checkUsersViewMode(): void
3044 {
3045 $this->selectedSorting = $this->objProperties->getDefaultView();
3046
3047 if ($this->getObject() !== null) {
3048 $view_mode = 'viewmode_' . $this->getObject()->getId();
3049 if (in_array((int) ilSession::get($view_mode), [
3053 ], true)) {
3054 $this->selectedSorting = ilSession::get($view_mode);
3055 }
3056
3057 if (
3058 isset($this->httpRequest->getQueryParams()['viewmode']) &&
3059 (int) $this->httpRequest->getQueryParams()['viewmode'] !== $this->selectedSorting
3060 ) {
3061 $this->selectedSorting = (int) $this->httpRequest->getQueryParams()['viewmode'];
3062 }
3063
3064 if (!in_array($this->selectedSorting, [
3068 ], true)) {
3069 $this->selectedSorting = $this->objProperties->getDefaultView();
3070 }
3071
3072 ilSession::set($view_mode, $this->selectedSorting);
3073 }
3074 }
3075
3076 public function resetLimitedViewObject(): void
3077 {
3078 $this->selected_post_storage->set($this->objCurrentTopic->getId(), 0);
3079 $this->ctrl->redirect($this, 'viewThread');
3080 }
3081
3082 public function viewThreadObject(): void
3083 {
3084 $thr_pk = $this->objCurrentTopic->getId();
3085
3086 $bottom_toolbar = clone $this->toolbar;
3087 $toolbar_items = [];
3088
3089 // quick and dirty: check for treeview
3090 $thread_control_session_values = ilSession::get('thread_control');
3091 if (is_array($thread_control_session_values)) {
3092 if (!isset($thread_control_session_values['old'])) {
3093 $thread_control_session_values['old'] = $thr_pk;
3094 $thread_control_session_values['new'] = $thr_pk;
3095 ilSession::set('thread_control', $thread_control_session_values);
3096 } elseif (isset($thread_control_session_values['old']) && $thr_pk !== $thread_control_session_values['old']) {
3097 $thread_control_session_values['new'] = $thr_pk;
3098 ilSession::set('thread_control', $thread_control_session_values);
3099 }
3100 }
3101
3102 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
3103 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3104 }
3105
3106 $oForumObjects = $this->getForumObjects();
3107 $forumObj = $oForumObjects['forumObj'];
3108 $frm = $oForumObjects['frm'];
3109 $file_obj = $oForumObjects['file_obj'];
3110
3111 $selected_draft_id = (int) ($this->httpRequest->getQueryParams()['draft_id'] ?? 0);
3112 if (isset($this->httpRequest->getQueryParams()['file'])) {
3113 $file_obj_for_delivery = $file_obj;
3114 if ($selected_draft_id > 0 && ilForumPostDraft::isSavePostDraftAllowed()) {
3115 $file_obj_for_delivery = new ilFileDataForumDrafts($forumObj->getId(), $selected_draft_id);
3116 }
3117 $file_obj_for_delivery->deliverFile(ilUtil::stripSlashes($this->httpRequest->getQueryParams()['file']));
3118 }
3119
3120 if ($this->objCurrentTopic->getId() === 0) {
3121 $this->ctrl->redirect($this, 'showThreads');
3122 }
3123
3124 $pageIndex = 0;
3125 if (isset($this->httpRequest->getQueryParams()['page'])) {
3126 $pageIndex = max((int) $this->httpRequest->getQueryParams()['page'], $pageIndex);
3127 }
3128
3129 if ($this->selected_post_storage->get($this->objCurrentTopic->getId()) > 0) {
3130 $firstNodeInThread = new ilForumPost(
3131 $this->selected_post_storage->get($this->objCurrentTopic->getId()),
3132 $this->is_moderator,
3133 false
3134 );
3135 } else {
3136 $firstNodeInThread = $this->objCurrentTopic->getPostRootNode();
3137 }
3138
3139 $toolContext = $this->globalScreen
3140 ->tool()
3141 ->context()
3142 ->current();
3143
3144 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentTopic);
3145
3146 $threadContentTemplate = new ilTemplate(
3147 'tpl.forums_threads_view.html',
3148 true,
3149 true,
3150 'components/ILIAS/Forum'
3151 );
3152
3153
3154 if ($this->selectedSorting === ilForumProperties::VIEW_TREE) {
3155 $order_field = 'frm_posts_tree.rgt';
3156 $this->objCurrentTopic->setOrderDirection('DESC');
3157 $threadContentTemplate->setVariable('LIST_TYPE', $this->viewModeOptions[$this->selectedSorting]);
3158 } else {
3159 $order_field = 'frm_posts.pos_date';
3160 $this->objCurrentTopic->setOrderDirection(
3161 $this->selectedSorting === ilForumProperties::VIEW_DATE_DESC ? 'DESC' : 'ASC'
3162 );
3163 $threadContentTemplate->setVariable('LIST_TYPE', $this->sortationOptions[$this->selectedSorting]);
3164 }
3165 $this->objCurrentTopic->setOrderField($order_field);
3166
3167 $additionalDataExists = $toolContext->getAdditionalData()->exists(ForumGlobalScreenToolsProvider::SHOW_FORUM_THREADS_TOOL);
3168 $subtree_nodes = $this->objCurrentTopic->getPostTree($firstNodeInThread);
3169 $numberOfPostings = count($subtree_nodes);
3170 if ($numberOfPostings > 0 && !$additionalDataExists && $this->selectedSorting === ilForumProperties::VIEW_TREE) {
3171 $toolContext
3173 ->addAdditionalData(ForumGlobalScreenToolsProvider::REF_ID, $this->ref_id)
3174 ->addAdditionalData(ForumGlobalScreenToolsProvider::FORUM_THEAD, $this->objCurrentTopic)
3175 ->addAdditionalData(ForumGlobalScreenToolsProvider::FORUM_THREAD_ROOT, $firstNodeInThread)
3177 ->addAdditionalData(ForumGlobalScreenToolsProvider::PAGE, $pageIndex);
3178 }
3179 // Set context for login
3180 $append = '_' . $this->objCurrentTopic->getId() .
3181 ($this->objCurrentPost->getId() !== 0 ? '_' . $this->objCurrentPost->getId() : '');
3182 $this->tpl->setLoginTargetPar('frm_' . $this->object->getRefId() . $append);
3183
3184 // delete temporary media object (not in case a user adds media objects and wants to save an invalid form)
3185 if (!in_array($this->requestAction, ['showreply', 'showedit'])) {
3186 try {
3187 $mobs = ilObjMediaObject::_getMobsOfObject('frm~:html', $this->user->getId());
3188 foreach ($mobs as $mob) {
3189 if (ilObjMediaObject::_exists($mob)) {
3190 ilObjMediaObject::_removeUsage($mob, 'frm~:html', $this->user->getId());
3191 $mob_obj = new ilObjMediaObject($mob);
3192 $mob_obj->delete();
3193 }
3194 }
3195 } catch (Exception) {
3196 }
3197 }
3198
3199 if (!$this->getCreationMode() && $this->access->checkAccess('read', '', $this->object->getRefId())) {
3201 $this->object->getRefId(),
3202 ilLink::_getLink($this->object->getRefId(), 'frm'),
3203 'frm'
3204 );
3205 }
3206
3207 $this->prepareThreadScreen($forumObj);
3208
3209
3210 if (isset($this->httpRequest->getQueryParams()['anchor'])) {
3211 $threadContentTemplate->setVariable('JUMP2ANCHOR_ID', (int) $this->httpRequest->getQueryParams()['anchor']);
3212 }
3213 $frm->setMDB2WhereCondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
3214
3216 $this->object->getType(),
3217 $this->object->getRefId(),
3218 $this->object->getId(),
3219 $this->user->getId()
3220 );
3221
3222 if ($firstNodeInThread) {
3223 $this->objCurrentTopic->updateVisits();
3224
3225 $this->tpl->setTitle($this->lng->txt('forums_thread') . ' "' . $this->objCurrentTopic->getSubject() . '"');
3226
3227 $this->locator->addRepositoryItems();
3228 $this->locator->addItem($this->object->getTitle(), $this->ctrl->getLinkTarget($this, ''), '_top');
3229 $this->tpl->setLocator();
3230
3231 if (!$this->user->isAnonymous() &&
3232 $forumObj->getCountUnread($this->user->getId(), $this->objCurrentTopic->getId(), true)) {
3233 $this->ctrl->setParameter($this, 'mark_read', '1');
3234 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
3235
3236 $mark_thr_read_button = $this->uiFactory->button()->standard(
3237 $this->lng->txt('forums_mark_read'),
3238 $this->ctrl->getLinkTarget($this, 'viewThread')
3239 );
3240
3241 $toolbar_items[] = $mark_thr_read_button;
3242
3243 $this->ctrl->clearParameters($this);
3244 }
3245
3246 $this->ctrl->setParameterByClass(ilForumExportGUI::class, 'print_thread', $this->objCurrentTopic->getId());
3247 $this->ctrl->setParameterByClass(
3248 ilForumExportGUI::class,
3249 'thr_top_fk',
3250 $this->objCurrentTopic->getForumId()
3251 );
3252
3253 if ($numberOfPostings > 0 && $this->settings->get('forum_enable_print', '0')) {
3254 $print_thr_button = $this->uiFactory->button()->standard(
3255 $this->lng->txt('forums_print_thread'),
3256 $this->ctrl->getLinkTargetByClass(ilForumExportGUI::class, 'printThread')
3257 );
3258 $toolbar_items[] = $print_thr_button;
3259 }
3260
3261
3262 $this->ctrl->clearParametersByClass(ilForumExportGUI::class);
3263
3264 $this->addHeaderAction();
3265
3266 if (isset($this->httpRequest->getQueryParams()['mark_read'])) {
3267 $forumObj->markThreadRead($this->user->getId(), $this->objCurrentTopic->getId());
3268 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_thread_marked'), true);
3269 }
3270
3271 if ($firstNodeInThread instanceof ilForumPost &&
3272 !$this->isTopLevelReplyCommand() &&
3273 !$this->objCurrentTopic->isClosed() &&
3274 $this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
3275 $this->ctrl->setParameter($this, 'action', 'showreply');
3276 $this->ctrl->setParameter($this, 'pos_pk', $firstNodeInThread->getId());
3277 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
3278 $this->ctrl->setParameter(
3279 $this,
3280 'page',
3281 (int) ($this->httpRequest->getQueryParams()['page'] ?? 0)
3282 );
3283 $this->ctrl->setParameter(
3284 $this,
3285 'orderby',
3286 $this->getOrderByParam()
3287 );
3288 if ($numberOfPostings > 0) {
3289 $reply_button = $this->uiFactory->button()->standard(
3290 $this->lng->txt('add_new_answer'),
3291 $this->ctrl->getLinkTarget($this, 'createTopLevelPost', 'frm_page_bottom')
3292 );
3293 } else {
3294 $reply_button = $this->uiFactory->button()->primary(
3295 $this->lng->txt('add_new_answer'),
3296 $this->ctrl->getLinkTarget($this, 'createTopLevelPost', 'frm_page_bottom')
3297 );
3298 }
3299 $this->ctrl->clearParameters($this);
3300 array_unshift($toolbar_items, $reply_button);
3301 }
3302
3303 // no posts
3304 if ($numberOfPostings === 0 && $firstNodeInThread->getId() === 0) {
3305 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_no_posts_available'));
3306 }
3307
3308 $pageSize = $frm->getPageHits();
3309 $postIndex = 0;
3310 if ($numberOfPostings > $pageSize) {
3311 $this->ctrl->setParameter($this, 'ref_id', $this->object->getRefId());
3312 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
3313 $this->ctrl->setParameter(
3314 $this,
3315 'orderby',
3316 $this->getOrderByParam()
3317 );
3318 $paginationUrl = $this->ctrl->getLinkTarget($this, 'viewThread', '');
3319 $this->ctrl->clearParameters($this);
3320
3321 $pagination = $this->uiFactory->viewControl()
3322 ->pagination()
3323 ->withTargetURL($paginationUrl, 'page')
3324 ->withTotalEntries($numberOfPostings)
3325 ->withPageSize($pageSize)
3326 ->withMaxPaginationButtons(10)
3327 ->withCurrentPage($pageIndex);
3328
3329 $threadContentTemplate->setVariable('THREAD_MENU', $this->uiRenderer->render(
3330 $pagination
3331 ));
3332 $threadContentTemplate->setVariable('THREAD_MENU_BOTTOM', $this->uiRenderer->render(
3333 $pagination
3334 ));
3335 }
3336
3337 $doRenderDrafts = ilForumPostDraft::isSavePostDraftAllowed() && !$this->user->isAnonymous();
3338 $draftsObjects = [];
3339 if ($doRenderDrafts) {
3340 $draftsObjects = ilForumPostDraft::getSortedDrafts(
3341 $this->user->getId(),
3342 $this->objCurrentTopic->getId(),
3343 $this->selectedSorting
3344 );
3345 }
3346
3347 $pagedPostings = array_slice($subtree_nodes, $pageIndex * $pageSize, $pageSize);
3348
3349 $this->ensureValidPageForCurrentPosting($subtree_nodes, $pagedPostings, $pageSize, $firstNodeInThread);
3350
3351 $this->preloadPostingFileResources($pagedPostings, $draftsObjects);
3352 if ($doRenderDrafts && $pageIndex === 0 &&
3353 $this->selectedSorting === ilForumProperties::VIEW_DATE_DESC) {
3354 foreach ($draftsObjects as $draft) {
3355 $referencePosting = array_values(array_filter(
3356 $subtree_nodes,
3357 static fn(ilForumPost $post): bool => $draft->getPostId() === $post->getId()
3358 ))[0] ?? $firstNodeInThread;
3359
3360 $this->renderDraftContent(
3361 $threadContentTemplate,
3362 $this->requestAction,
3363 $referencePosting,
3364 [$draft]
3365 );
3366 }
3367 }
3368
3369 foreach ($pagedPostings as $node) {
3370 $this->ctrl->clearParameters($this);
3371
3372 if (!$this->isTopLevelReplyCommand() && $this->objCurrentPost->getId() === $node->getId() &&
3373 ($this->is_moderator || $node->isActivated() || $node->isOwner($this->user->getId()))) {
3374 if (!$this->objCurrentTopic->isClosed() && in_array($this->requestAction, [
3375 'showreply',
3376 'showedit',
3377 ])) {
3378 $this->renderPostingForm($threadContentTemplate, $frm, $node, $this->requestAction);
3379 } elseif ($this->requestAction === 'censor' &&
3380 !$this->objCurrentTopic->isClosed() && $this->is_moderator) {
3381 $threadContentTemplate->setVariable('FORM', $this->getCensorshipFormHTML());
3382 }
3383 }
3384
3385 $this->renderPostContent($threadContentTemplate, $node, $this->requestAction, $pageIndex, $postIndex);
3386 if ($doRenderDrafts && $this->selectedSorting === ilForumProperties::VIEW_TREE) {
3387 $this->renderDraftContent(
3388 $threadContentTemplate,
3389 $this->requestAction,
3390 $node,
3391 $draftsObjects[$node->getId()] ?? []
3392 );
3393 }
3394
3395 $postIndex++;
3396 }
3397
3398 if (
3399 $this->selectedSorting === ilForumProperties::VIEW_DATE_ASC &&
3400 $doRenderDrafts && $pageIndex === max(0, (int) (ceil($numberOfPostings / $pageSize) - 1))
3401 ) {
3402 foreach ($draftsObjects as $draft) {
3403 $referencePosting = array_values(array_filter(
3404 $subtree_nodes,
3405 static fn(ilForumPost $post): bool => $draft->getPostId() === $post->getId()
3406 ))[0] ?? $firstNodeInThread;
3407
3408 $this->renderDraftContent(
3409 $threadContentTemplate,
3410 $this->requestAction,
3411 $referencePosting,
3412 [$draft]
3413 );
3414 }
3415 }
3416
3417 if (
3418 $firstNodeInThread instanceof ilForumPost && $doRenderDrafts &&
3419 $this->selectedSorting === ilForumProperties::VIEW_TREE
3420 ) {
3421 $this->renderDraftContent(
3422 $threadContentTemplate,
3423 $this->requestAction,
3424 $firstNodeInThread,
3425 $draftsObjects[$firstNodeInThread->getId()] ?? []
3426 );
3427 }
3428
3429 if ($firstNodeInThread instanceof ilForumPost &&
3430 !$this->objCurrentTopic->isClosed() &&
3431 in_array($this->ctrl->getCmd(), ['createTopLevelPost', 'saveTopLevelPost', 'saveTopLevelDraft'], true) &&
3432 $this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
3433 // Important: Don't separate the following two lines (very fragile code ...)
3434 $this->objCurrentPost->setId($firstNodeInThread->getId());
3435 $form = $this->getReplyEditForm();
3436
3437 if (in_array($this->ctrl->getCmd(), ['saveTopLevelPost', 'saveTopLevelDraft'])) {
3438 $form->setValuesByPost();
3439 }
3440 $threadContentTemplate->setVariable('BOTTOM_FORM', $form->getHTML());
3441 }
3442 } else {
3443 $threadContentTemplate->setCurrentBlock('posts_no');
3444 $threadContentTemplate->setVariable(
3445 'TXT_MSG_NO_POSTS_AVAILABLE',
3446 $this->lng->txt('forums_posts_not_available')
3447 );
3448 $threadContentTemplate->parseCurrentBlock();
3449 }
3450
3451 $to_top_button = $this->uiFactory->button()
3452 ->standard($this->lng->txt('top_of_page'), '#frm_page_top');
3453 $bottom_toolbar->addComponent($to_top_button);
3454 if ($numberOfPostings > 0) {
3455 $threadContentTemplate->setVariable('TOOLBAR_BOTTOM', $bottom_toolbar->getHTML());
3456 }
3457
3458 if ($toolbar_items !== []) {
3459 foreach ($toolbar_items as $component_index => $item) {
3460 $this->toolbar->addComponent($item);
3461 $bottom_toolbar->addComponent($item);
3462 if ($component_index === 0 && $numberOfPostings > 0) {
3463 $this->renderViewModeControl($this->selectedSorting);
3464 if ($this->selectedSorting !== ilForumProperties::VIEW_TREE) {
3465 $this->renderSortationControl($this->selectedSorting);
3466 }
3467 }
3468 }
3469 }
3470
3471 $this->tpl->setPermanentLink(
3472 $this->object->getType(),
3473 $this->object->getRefId(),
3474 (string) $this->objCurrentTopic->getId()
3475 );
3476
3477 $this->tpl->addOnLoadCode(
3478 <<<EOD
3479 document.querySelectorAll('.ilFrmPostContent img').forEach((img) => {
3480 const maxWidth = img.getAttribute('width');
3481 const maxHeight = img.getAttribute('height');
3482
3483 if (maxWidth) {
3484 img.style.maxWidth = maxWidth + 'px';
3485 img.removeAttribute('width');
3486 }
3487
3488 if (maxHeight) {
3489 img.style.maxHeight = maxHeight + 'px';
3490 img.removeAttribute('height');
3491 }
3492 });
3493EOD
3494 );
3495
3496 if ($this->selectedSorting === ilForumProperties::VIEW_TREE && ($this->selected_post_storage->get($thr_pk) > 0)) {
3497 $info = $this->getResetLimitedViewInfo();
3498 }
3499
3500 $this->tpl->setContent(($info ?? '') . $threadContentTemplate->get() . $this->getModalActions());
3501 }
3502
3503 private function renderViewModeControl(int $currentViewMode): void
3504 {
3505 if ($currentViewMode === 3) {
3506 $currentViewMode = 2;
3507 }
3508 $translationKeys = [];
3509 foreach ($this->viewModeOptions as $sortingConstantKey => $languageKey) {
3510 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
3511 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
3512 $this->ctrl->setParameter($this, 'viewmode', $sortingConstantKey);
3513
3514 $translationKeys[$this->lng->txt($languageKey)] = $this->ctrl->getLinkTarget(
3515 $this,
3516 'viewThread',
3517 ''
3518 );
3519
3520 $this->ctrl->clearParameters($this);
3521 }
3522
3523 if ($currentViewMode > ilForumProperties::VIEW_DATE_ASC) {
3524 $currentViewMode = ilForumProperties::VIEW_DATE_ASC;
3525 }
3526
3527 $sortViewControl = $this->uiFactory
3528 ->viewControl()
3529 ->mode($translationKeys, $this->lng->txt($this->viewModeOptions[$currentViewMode]))
3530 ->withActive($this->lng->txt($this->viewModeOptions[$currentViewMode]));
3531 $this->toolbar->addComponent($sortViewControl);
3532 }
3533
3534 private function renderSortationControl(int $currentSorting): void
3535 {
3536 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
3537 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
3538 $target = $this->ctrl->getLinkTarget(
3539 $this,
3540 'viewThread',
3541 ''
3542 );
3543
3544 $translatedSortationOptions = array_map(fn($value): string => $this->lng->txt($value), $this->sortationOptions);
3545
3546 $sortingDirectionViewControl = $this->uiFactory
3547 ->viewControl()
3548 ->sortation($translatedSortationOptions, (string) $currentSorting)
3549 ->withTargetURL($target, 'viewmode');
3550 $this->toolbar->addComponent($sortingDirectionViewControl);
3551 }
3552
3553 private function getModifiedReOnSubject(): string
3554 {
3555 return (new \ILIAS\components\Forum\Subject\PostingReplySubjectBuilder(
3556 $this->lng->txt('post_reply'),
3557 $this->lng->txt('post_reply_count')
3558 ))->build($this->objCurrentPost->getSubject());
3559 }
3560
3561 public function showUserObject(): void
3562 {
3563 $user_id = $this->http->wrapper()->query()->retrieve(
3564 'user',
3565 $this->refinery->byTrying([$this->refinery->kindlyTo()->int(), $this->refinery->always(0)])
3566 );
3567 $backurl = $this->http->wrapper()->query()->retrieve(
3568 'backurl',
3569 $this->refinery->byTrying([$this->refinery->kindlyTo()->string(), $this->refinery->always('')])
3570 );
3571
3572 $profile_gui = new PublicProfileGUI($user_id);
3573 $add = $this->getUserProfileAdditional($this->object->getRefId(), $user_id);
3574 $profile_gui->setAdditional($add);
3575 $profile_gui->setBackUrl(ilUtil::stripSlashes($backurl));
3576 $this->tpl->setContent($this->ctrl->getHTML($profile_gui));
3577 }
3578
3579 protected function getUserProfileAdditional(int $a_forum_ref_id, int $a_user_id): array
3580 {
3581 if (!$this->access->checkAccess('read', '', $a_forum_ref_id)) {
3582 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3583 }
3584
3586 $ref_obj = ilObjectFactory::getInstanceByRefId($a_forum_ref_id);
3587 if ($ref_obj->getType() === 'frm') {
3588 $forumObj = new ilObjForum($a_forum_ref_id);
3589 $frm = $forumObj->Forum;
3590 $frm->setForumId($forumObj->getId());
3591 $frm->setForumRefId($forumObj->getRefId());
3592 } else {
3593 $frm = new ilForum();
3594 }
3595
3596 if ($this->access->checkAccess('moderate_frm', '', $a_forum_ref_id)) {
3597 $numPosts = $frm->countUserArticles($a_user_id);
3598 } else {
3599 $numPosts = $frm->countActiveUserArticles($a_user_id);
3600 }
3601
3602 return [$this->lng->txt('forums_posts') => $numPosts];
3603 }
3604
3605 public function performThreadsActionObject(): void
3606 {
3607 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
3608 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3609 }
3610
3611 ilSession::set('threads2move', []);
3612
3613 $thread_ids = $this->retrieveThreadIds();
3614 $cmd = $this->ctrl->getCmd();
3615 $message = null;
3616
3617 if ($thread_ids !== []) {
3618 if ($cmd === 'move') {
3619 if ($this->is_moderator) {
3620 ilSession::set('threads2move', $thread_ids);
3621 $this->moveThreadsObject();
3622 }
3623 } elseif ($cmd === 'enable_notifications' && (int) $this->settings->get('forum_notification', '0') !== 0) {
3624 foreach ($thread_ids as $thread_id) {
3625 $tmp_obj = new ilForumTopic($thread_id);
3626 $this->ensureThreadBelongsToForum($this->object->getId(), $tmp_obj);
3627 $tmp_obj->enableNotification($this->user->getId());
3628 }
3629
3630 $this->ctrl->redirect($this, 'showThreads');
3631 } elseif ($cmd === 'disable_notifications' && (int) $this->settings->get('forum_notification', '0') !== 0) {
3632 foreach ($thread_ids as $thread_id) {
3633 $tmp_obj = new ilForumTopic($thread_id);
3634 $this->ensureThreadBelongsToForum($this->object->getId(), $tmp_obj);
3635 $tmp_obj->disableNotification($this->user->getId());
3636 }
3637
3638 $this->ctrl->redirect($this, 'showThreads');
3639 } elseif ($cmd === 'close') {
3640 if ($this->is_moderator) {
3641 foreach ($thread_ids as $thread_id) {
3642 $tmp_obj = new ilForumTopic($thread_id);
3643 $this->ensureThreadBelongsToForum($this->object->getId(), $tmp_obj);
3644 $tmp_obj->close();
3645 }
3646 }
3647 $this->tpl->setOnScreenMessage('success', $this->lng->txt('selected_threads_closed'), true);
3648 $this->ctrl->redirect($this, 'showThreads');
3649 } elseif ($cmd === 'reopen') {
3650 if ($this->is_moderator) {
3651 foreach ($thread_ids as $thread_id) {
3652 $tmp_obj = new ilForumTopic($thread_id);
3653 $this->ensureThreadBelongsToForum($this->object->getId(), $tmp_obj);
3654 $tmp_obj->reopen();
3655 }
3656 }
3657
3658 $this->tpl->setOnScreenMessage('success', $this->lng->txt('selected_threads_reopened'), true);
3659 $this->ctrl->redirect($this, 'showThreads');
3660 } elseif ($cmd === 'makesticky') {
3661 if ($this->is_moderator) {
3662 $message = $this->lng->txt('sel_threads_make_sticky');
3663
3664 foreach ($thread_ids as $thread_id) {
3665 $tmp_obj = new ilForumTopic($thread_id);
3666 $this->ensureThreadBelongsToForum($this->object->getId(), $tmp_obj);
3667 $makeSticky = $tmp_obj->makeSticky();
3668 if (!$makeSticky) {
3669 $message = $this->lng->txt('sel_threads_already_sticky');
3670 }
3671 }
3672 }
3673 if ($message !== null) {
3674 $this->tpl->setOnScreenMessage('info', $message, true);
3675 }
3676 $this->ctrl->redirect($this, 'showThreads');
3677 } elseif ($cmd === 'unmakesticky' || $cmd === 'make_topics_non_sticky') {
3678 if ($this->is_moderator) {
3679 $message = $this->lng->txt('sel_threads_make_unsticky');
3680 foreach ($thread_ids as $thread_id) {
3681 $tmp_obj = new ilForumTopic($thread_id);
3682 $this->ensureThreadBelongsToForum($this->object->getId(), $tmp_obj);
3683 $unmakeSticky = $tmp_obj->unmakeSticky();
3684 if (!$unmakeSticky) {
3685 $message = $this->lng->txt('sel_threads_already_unsticky');
3686 }
3687 }
3688 }
3689
3690 if ($message !== null) {
3691 $this->tpl->setOnScreenMessage('info', $message, true);
3692 }
3693 $this->ctrl->redirect($this, 'showThreads');
3694 } elseif ($cmd === 'editThread') {
3695 if ($this->is_moderator) {
3696 $count = count($thread_ids);
3697 if ($count !== 1) {
3698 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_max_one_thread'), true);
3699 $this->ctrl->redirect($this, 'showThreads');
3700 } else {
3701 $this->updateThreadObject();
3702 return;
3703 }
3704 }
3705
3706 $this->ctrl->redirect($this, 'showThreads');
3707 } elseif ($cmd === 'confirmDeleteThreads') {
3708 $this->confirmDeleteThreadsObject();
3709 } elseif ($cmd === 'mergeThreads') {
3710 $this->mergeThreadsObject();
3711 } else {
3712 $this->tpl->setOnScreenMessage('info', $this->lng->txt('topics_please_select_one_action'), true);
3713 $this->ctrl->redirect($this, 'showThreads');
3714 }
3715 } else {
3716 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_at_least_one_thread'), true);
3717 $this->ctrl->redirect($this, 'showThreads');
3718 }
3719 }
3720
3721 public function performMoveThreadsObject(): void
3722 {
3723 if (!$this->is_moderator) {
3724 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3725 }
3726
3727 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
3728 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3729 }
3730
3731 $frm_ref_id = null;
3732 if ($this->http->wrapper()->post()->has('frm_ref_id')) {
3733 $frm_ref_id = $this->http->wrapper()->post()->retrieve(
3734 'frm_ref_id',
3735 $this->refinery->kindlyTo()->int()
3736 );
3737 } else {
3738 $this->error->raiseError('Please select a forum', $this->error->MESSAGE);
3739 }
3740
3741 $threads2move = ilSession::get('threads2move');
3742 if (!is_array($threads2move) || $threads2move === []) {
3743 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_at_least_one_thread'), true);
3744 $this->ctrl->redirect($this, 'showThreads');
3745 }
3746
3747 if (!$this->access->checkAccess('read', '', (int) $frm_ref_id)) {
3748 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3749 }
3750
3751 $threads = [];
3752 array_walk($threads2move, function (int $threadId) use (&$threads): void {
3753 $thread = new ilForumTopic($threadId);
3754 $this->ensureThreadBelongsToForum($this->object->getId(), $thread);
3755
3756 $threads[] = $threadId;
3757 });
3758
3759 if (isset($frm_ref_id) && (int) $frm_ref_id) {
3760 $errorMessages = $this->object->Forum->moveThreads(
3761 (array) (ilSession::get('threads2move') ?? []),
3762 $this->object,
3763 $this->ilObjDataCache->lookupObjId((int) $frm_ref_id)
3764 );
3765
3766 if ([] !== $errorMessages) {
3767 $this->tpl->setOnScreenMessage('failure', implode('<br><br>', $errorMessages), true);
3768 $this->ctrl->redirect($this, 'showThreads');
3769 }
3770
3771 ilSession::set('threads2move', []);
3772 $this->tpl->setOnScreenMessage('info', $this->lng->txt('threads_moved_successfully'), true);
3773 $this->ctrl->redirect($this, 'showThreads');
3774 } else {
3775 $this->tpl->setOnScreenMessage('info', $this->lng->txt('no_forum_selected'));
3776 $this->moveThreadsObject();
3777 }
3778 }
3779
3780 public function cancelMoveThreadsObject(): void
3781 {
3782 ilSession::set('threads2move', []);
3783 $this->ctrl->redirect($this, 'showThreads');
3784 }
3785
3786 public function moveThreadsObject(): bool
3787 {
3788 if (!$this->is_moderator) {
3789 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3790 }
3791
3792 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
3793 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3794 }
3795
3796 $frm_ref_id = $this->http->wrapper()->post()->retrieve(
3797 'frm_ref_id',
3798 $this->refinery->byTrying([$this->refinery->kindlyTo()->int(), $this->refinery->always(null)])
3799 );
3800
3801 $threads2move = ilSession::get('threads2move');
3802 if (!is_array($threads2move) || $threads2move === []) {
3803 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_at_least_one_thread'), true);
3804 $this->ctrl->redirect($this, 'showThreads');
3805 }
3806
3807 $threads = [];
3808 $isModerator = $this->is_moderator;
3809 array_walk($threads2move, function (int $threadId) use (&$threads, $isModerator): void {
3810 $thread = new ilForumTopic($threadId, $isModerator);
3811 $this->ensureThreadBelongsToForum($this->object->getId(), $thread);
3812
3813 $threads[] = $thread;
3814 });
3815
3816 $exp = new ilForumMoveTopicsExplorer($this, 'moveThreads');
3817 $exp->setPathOpen($this->object->getRefId());
3818 $exp->setNodeSelected(isset($frm_ref_id) && (int) $frm_ref_id ? (int) $frm_ref_id : 0);
3819 $exp->setCurrentFrmRefId($this->object->getRefId());
3820 $exp->setHighlightedNode((string) $this->object->getRefId());
3821 if (!$exp->handleCommand()) {
3822 $moveThreadTemplate = new ilTemplate(
3823 'tpl.forums_threads_move.html',
3824 true,
3825 true,
3826 'components/ILIAS/Forum'
3827 );
3828
3829 if (!$this->hideToolbar()) {
3830 $this->toolbar->addButton($this->lng->txt('back'), $this->ctrl->getLinkTarget($this));
3831 }
3832
3833 $messages = [];
3834 foreach ($threads as $thread) {
3835 $messages[] = $this->ui_factory->messageBox()->info(
3836 sprintf($this->lng->txt('move_chosen_topics'), $thread->getSubject())
3837 );
3838 }
3839 $moveThreadTemplate->setVariable('THREAD_MESSAGE', $this->uiRenderer->render($messages));
3840 $moveThreadTemplate->setVariable('FRM_SELECTION_TREE', $exp->getHTML());
3841 $moveThreadTemplate->setVariable('CMD_SUBMIT', 'performMoveThreads');
3842 $moveThreadTemplate->setVariable('TXT_SUBMIT', $this->lng->txt('move'));
3843 $moveThreadTemplate->setVariable('FORMACTION', $this->ctrl->getFormAction($this, 'performMoveThreads'));
3844
3845 $this->tpl->setContent($moveThreadTemplate->get());
3846 }
3847
3848 return true;
3849 }
3850
3851 private function isWritingWithPseudonymAllowed(): bool
3852 {
3853 return (
3854 $this->objProperties->isAnonymized() &&
3855 (!$this->is_moderator || !$this->objProperties->getMarkModeratorPosts())
3856 );
3857 }
3858
3859 protected function deleteThreadDraftsObject(): void
3860 {
3861 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
3862 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3863 }
3864
3865 $draftIds = array_filter((array) ($this->httpRequest->getParsedBody()['draft_ids'] ?? []));
3866
3867 $instances = ilForumPostDraft::getDraftInstancesByUserId($this->user->getId());
3868 $checkedDraftIds = [];
3869 foreach ($draftIds as $draftId) {
3870 if (array_key_exists($draftId, $instances)) {
3871 $checkedDraftIds[] = $draftId;
3872 $draft = $instances[$draftId];
3873
3874 $this->deleteMobsOfDraft($draft->getDraftId(), $draft->getPostMessage());
3875
3876 $GLOBALS['ilAppEventHandler']->raise(
3877 'components/ILIAS/Forum',
3878 'deletedDraft',
3879 [
3880 'draftObj' => $draft,
3881 'obj_id' => $this->object->getId(),
3882 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed(),
3883 ]
3884 );
3885
3886 $draftFileData = new ilFileDataForumDrafts();
3887 $draftFileData->delete([$draft->getDraftId()]);
3888
3889 $draft->deleteDraft();
3890 }
3891 }
3892
3893 if (count($checkedDraftIds) > 1) {
3894 $this->tpl->setOnScreenMessage('info', $this->lng->txt('delete_drafts_successfully'), true);
3895 } else {
3896 $this->tpl->setOnScreenMessage('info', $this->lng->txt('delete_draft_successfully'), true);
3897 }
3898 $this->ctrl->redirect($this, 'showThreads');
3899 }
3900
3901 private function buildThreadForm(bool $isDraft = false): ilForumThreadFormGUI
3902 {
3903 $draftId = (int) ($this->httpRequest->getQueryParams()['draft_id'] ?? 0);
3904 $allowNotification = !$this->objProperties->isAnonymized() && !$this->user->isAnonymous();
3905
3906 $mail = new ilMail($this->user->getId());
3907 if (!$this->rbac->system()->checkAccess('internal_mail', $mail->getMailObjectReferenceId())) {
3908 $allowNotification = false;
3909 }
3910
3911 $default_form = new ilForumThreadFormGUI(
3912 $this,
3913 $this->objProperties,
3914 $this->isWritingWithPseudonymAllowed(),
3915 $allowNotification,
3916 $isDraft,
3917 $draftId
3918 );
3919
3920 $default_form->addInputItem(ilForumThreadFormGUI::ALIAS_INPUT);
3921 $default_form->addInputItem(ilForumThreadFormGUI::SUBJECT_INPUT);
3922 $default_form->addInputItem(ilForumThreadFormGUI::MESSAGE_INPUT);
3923 $default_form->addInputItem(ilForumThreadFormGUI::FILE_UPLOAD_INPUT);
3924 $default_form->addInputItem(ilForumThreadFormGUI::ALLOW_NOTIFICATION_INPUT);
3925
3926 $default_form->generateDefaultForm();
3927
3928 $this->decorateWithAutosave($default_form);
3929
3930 return $default_form;
3931 }
3932
3933 private function buildMinimalThreadForm(bool $isDraft = false): ilForumThreadFormGUI
3934 {
3935 $draftId = (int) ($this->httpRequest->getQueryParams()['draft_id'] ?? 0);
3936 $allowNotification = !$this->objProperties->isAnonymized() && !$this->user->isAnonymous();
3937
3938 $mail = new ilMail($this->user->getId());
3939 if (!$this->rbac->system()->checkAccess('internal_mail', $mail->getMailObjectReferenceId())) {
3940 $allowNotification = false;
3941 }
3942
3943 $minimal_form = new ilForumThreadFormGUI(
3944 $this,
3945 $this->objProperties,
3946 $this->isWritingWithPseudonymAllowed(),
3947 $allowNotification,
3948 $isDraft,
3949 $draftId
3950 );
3951
3952 $minimal_form->addInputItem(ilForumThreadFormGUI::ALIAS_INPUT);
3953 $minimal_form->addInputItem(ilForumThreadFormGUI::SUBJECT_INPUT);
3954
3955 $minimal_form->generateMinimalForm();
3956
3957 return $minimal_form;
3958 }
3959
3960 private function createThreadObject(): void
3961 {
3962 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
3963 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3964 }
3965
3966 if (!$this->access->checkAccess('add_thread', '', $this->object->getRefId())) {
3967 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3968 }
3969
3970 $tpl = new ilTemplate('tpl.create_thread_form.html', true, true, 'components/ILIAS/Forum');
3971
3972 $accordion = new ilAccordionGUI();
3973 $accordion->setId('acc_' . $this->obj_id);
3974 $accordion->setBehaviour(ilAccordionGUI::FIRST_OPEN);
3975
3976 $accordion->addItem($this->lng->txt('new_thread_with_post'), $this->buildThreadForm()->getHTML());
3977 $accordion->addItem($this->lng->txt('empty_thread'), $this->buildMinimalThreadForm()->getHTML());
3978
3979 $tpl->setVariable('CREATE_FORM', $accordion->getHTML());
3980 $tpl->parseCurrentBlock();
3981
3982 $this->tpl->setContent($tpl->get());
3983 }
3984
3988 private function createThread(ilForumPostDraft $draft, bool $createFromDraft = false): void
3989 {
3990 if (!$this->access->checkAccess('add_thread', '', $this->object->getRefId()) ||
3991 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
3992 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
3993 }
3994
3995 $frm = $this->object->Forum;
3996 $frm->setForumId($this->object->getId());
3997 $frm->setForumRefId($this->object->getRefId());
3998 $frm->setMDB2WhereCondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
3999 $topicData = $frm->getOneTopic();
4000
4001 $form = $this->buildThreadForm($createFromDraft);
4002 $minimal_form = $this->buildMinimalThreadForm($createFromDraft);
4003
4004 if ($form->checkInput()) {
4005 $userIdForDisplayPurposes = $this->user->getId();
4006 if ($this->isWritingWithPseudonymAllowed()) {
4007 $userIdForDisplayPurposes = 0;
4008 }
4009
4010 $status = true;
4011 if (
4012 ($this->objProperties->isPostActivationEnabled() && !$this->is_moderator) ||
4013 $this->objCurrentPost->isAnyParentDeactivated()
4014 ) {
4015 $status = false;
4016 }
4017
4018 if ($createFromDraft) {
4019 $newThread = new ilForumTopic(0, true, true);
4020 $newThread->setForumId($topicData->getTopPk());
4021 $newThread->setThrAuthorId($draft->getPostAuthorId());
4022 $newThread->setDisplayUserId($draft->getPostDisplayUserId());
4023 $newThread->setSubject($this->handleFormInput($form->getInput('subject'), false));
4024 $newThread->setUserAlias($draft->getPostUserAlias());
4025
4026 $newPost = $frm->generateThread(
4027 $newThread,
4028 ilRTE::_replaceMediaObjectImageSrc($form->getInput('message')),
4029 $draft->isNotificationEnabled() && !$this->user->isAnonymous(),
4030 $draft->isPostNotificationEnabled() && !$this->user->isAnonymous(),
4031 $status
4032 );
4033 } else {
4034 $newThread = new ilForumTopic(0, true, true);
4035 $newThread->setForumId($topicData->getTopPk());
4036 $newThread->setThrAuthorId($this->user->getId());
4037 $newThread->setDisplayUserId($userIdForDisplayPurposes);
4038 $newThread->setSubject($this->handleFormInput($form->getInput('subject'), false));
4039 $newThread->setUserAlias(ilForumUtil::getPublicUserAlias(
4040 $form->getInput('alias'),
4041 $this->objProperties->isAnonymized()
4042 ));
4043
4044 $newPost = $frm->generateThread(
4045 $newThread,
4046 ilRTE::_replaceMediaObjectImageSrc($form->getInput('message')),
4047 $form->getItemByPostVar('notify') && $form->getInput('notify') && !$this->user->isAnonymous(),
4048 false, // #19980
4049 $status
4050 );
4051 }
4052
4053 $post_obj = new ilForumPost($newPost);
4054 if ($draft->getRCID() > 0) {
4055 $post_obj->setRCID($draft->getRCID());
4056 $post_obj->update();
4057 }
4058
4059 if ($this->objProperties->isFileUploadAllowed()) {
4060 $file = $_FILES['userfile'];
4061 if (is_array($file) && !empty($file)) {
4062 $fileData = new ilFileDataForum($this->object->getId(), $newPost);
4063 $fileData->storeUploadedFiles();
4064 }
4065 }
4066
4067 $frm->setDbTable('frm_data');
4068 $frm->setMDB2WhereCondition('top_pk = %s ', ['integer'], [$topicData->getTopPk()]);
4069 $frm->updateVisits($topicData->getTopPk());
4070
4071 if ($createFromDraft) {
4072 $mediaObjects = ilObjMediaObject::_getMobsOfObject('frm~:html', $this->user->getId());
4073 } else {
4074 $mediaObjects = ilRTE::_getMediaObjects($form->getInput('message'));
4075 }
4076 foreach ($mediaObjects as $mob) {
4077 if (ilObjMediaObject::_exists($mob)) {
4078 ilObjMediaObject::_removeUsage($mob, 'frm~:html', $this->user->getId());
4079 ilObjMediaObject::_saveUsage($mob, 'frm:html', $newPost);
4080 }
4081 }
4082
4083 if ($draft->getDraftId() > 0) {
4084 $draftHistory = new ilForumDraftsHistory();
4085 $draftHistory->deleteHistoryByDraftIds([$draft->getDraftId()]);
4086 $draft->deleteDraft();
4087 }
4088
4089 $GLOBALS['ilAppEventHandler']->raise(
4090 'components/ILIAS/Forum',
4091 'createdPost',
4092 [
4093 'object' => $this->object,
4094 'ref_id' => $this->object->getRefId(),
4095 'post' => $post_obj,
4096 'notify_moderators' => !$status
4097 ]
4098 );
4099
4100 $this->tpl->setOnScreenMessage('success', $this->lng->txt('forums_thread_new_entry'), true);
4101 $this->ctrl->redirect($this);
4102 }
4103
4104 $form->setValuesByPost();
4105 if (!$this->objProperties->isAnonymized()) {
4106 $form->getItemByPostVar('alias')->setValue($this->user->getLogin());
4107 }
4108
4109 $accordion = new ilAccordionGUI();
4110 $accordion->setId('acc_' . $this->obj_id);
4111 $accordion->setBehaviour(ilAccordionGUI::FIRST_OPEN);
4112 $accordion->addItem($this->lng->txt('new_thread_with_post'), $form->getHTML());
4113 $accordion->addItem($this->lng->txt('empty_thread'), $minimal_form->getHTML());
4114
4115 $this->tpl->setContent($accordion->getHTML());
4116 }
4117
4121 private function createEmptyThread(): void
4122 {
4123 if (!$this->access->checkAccess('add_thread', '', $this->object->getRefId()) ||
4124 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
4125 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4126 }
4127
4128 $frm = $this->object->Forum;
4129 $frm->setForumId($this->object->getId());
4130 $frm->setForumRefId($this->object->getRefId());
4131 $frm->setMDB2WhereCondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
4132 $topicData = $frm->getOneTopic();
4133
4134 $form = $this->buildThreadForm();
4135 $minimal_form = $this->buildMinimalThreadForm();
4136
4137 if ($minimal_form->checkInput()) {
4138 $userIdForDisplayPurposes = $this->user->getId();
4139 if ($this->isWritingWithPseudonymAllowed()) {
4140 $userIdForDisplayPurposes = 0;
4141 }
4142
4143 $status = true;
4144 if (
4145 ($this->objProperties->isPostActivationEnabled() && !$this->is_moderator) ||
4146 $this->objCurrentPost->isAnyParentDeactivated()
4147 ) {
4148 $status = false;
4149 }
4150
4151 $newThread = new ilForumTopic(0, true, true);
4152 $newThread->setForumId($topicData->getTopPk());
4153 $newThread->setThrAuthorId($this->user->getId());
4154 $newThread->setDisplayUserId($userIdForDisplayPurposes);
4155 $newThread->setSubject($this->handleFormInput($minimal_form->getInput('subject'), false));
4156 $newThread->setUserAlias(ilForumUtil::getPublicUserAlias(
4157 $minimal_form->getInput('alias'),
4158 $this->objProperties->isAnonymized()
4159 ));
4160
4161 $frm->generateThread(
4162 $newThread,
4163 '',
4164 false,
4165 false, // #19980
4166 $status,
4167 false
4168 );
4169
4170 $frm->setDbTable('frm_data');
4171 $frm->setMDB2WhereCondition('top_pk = %s ', ['integer'], [$topicData->getTopPk()]);
4172 $frm->updateVisits($topicData->getTopPk());
4173
4174 $this->tpl->setOnScreenMessage('success', $this->lng->txt('forums_thread_new_entry'), true);
4175 $this->ctrl->redirect($this);
4176 }
4177
4178 $form->setValuesByPost();
4179
4180 if (!$this->objProperties->isAnonymized()) {
4181 $form->getItemByPostVar('alias')->setValue($this->user->getLogin());
4182 }
4183
4184 $accordion = new ilAccordionGUI();
4185 $accordion->setId('acc_' . $this->obj_id);
4186 $accordion->setBehaviour(ilAccordionGUI::FIRST_OPEN);
4187 $accordion->addItem($this->lng->txt('new_thread_with_post'), $form->getHTML());
4188 $accordion->addItem($this->lng->txt('empty_thread'), $minimal_form->getHTML());
4189
4190 $this->tpl->setContent($accordion->getHTML());
4191 }
4192
4193 protected function publishThreadDraftObject(): void
4194 {
4196 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4197 }
4198
4199 $draft = ilForumPostDraft::newInstanceByDraftId($this->retrieveDraftId());
4200 $this->checkDraftAccess($draft);
4201
4202 $this->createThread($draft, true);
4203 }
4204
4205 protected function addThreadObject(): void
4206 {
4207 $draft = new ilForumPostDraft();
4208 if (ilForumPostDraft::isSavePostDraftAllowed() && $this->retrieveDraftId() > 0) {
4209 $draft = ilForumPostDraft::newInstanceByDraftId($this->retrieveDraftId());
4210 $this->checkDraftAccess($draft);
4211 }
4212
4213 $this->createThread($draft);
4214 }
4215
4216 protected function addEmptyThreadObject(): void
4217 {
4218 $this->createEmptyThread();
4219 }
4220
4221 protected function enableForumNotificationObject(): void
4222 {
4223 if (!$this->access->checkAccess('read', '', $this->object->getRefId()) || $this->user->isAnonymous()) {
4224 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4225 }
4226
4227 $frm = $this->object->Forum;
4228 $frm->setForumId($this->object->getId());
4229 $frm->enableForumNotification($this->user->getId());
4230
4231 if ($this->objCurrentTopic->getId() > 0) {
4232 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
4233 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_forum_notification_enabled'), true);
4234 $this->ctrl->redirect($this, 'viewThread');
4235 }
4236
4237 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_forum_notification_enabled'));
4238 $this->showThreadsObject();
4239 }
4240
4241 protected function disableForumNotificationObject(): void
4242 {
4243 if (!$this->access->checkAccess('read', '', $this->object->getRefId()) || $this->user->isAnonymous()) {
4244 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4245 }
4246
4247 $frm = $this->object->Forum;
4248 $frm->setForumId($this->object->getId());
4249 $frm->disableForumNotification($this->user->getId());
4250
4251 if ($this->objCurrentTopic->getId() > 0) {
4252 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
4253 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_forum_notification_disabled'), true);
4254 $this->ctrl->redirect($this, 'viewThread');
4255 }
4256
4257 $this->tpl->setOnScreenMessage('info', $this->lng->txt('forums_forum_notification_disabled'));
4258 $this->showThreadsObject();
4259 }
4260
4261 public function setColumnSettings(ilColumnGUI $column_gui): void
4262 {
4263 $column_gui->setBlockProperty('news', 'title', $this->lng->txt('frm_latest_postings'));
4264 $column_gui->setBlockProperty('news', 'prevent_aggregation', '1');
4265 $column_gui->setRepositoryMode(true);
4266
4267 if ($this->access->checkAccess('write', '', $this->object->getRefId())) {
4268 $news_set = new ilSetting('news');
4269 if ($news_set->get('enable_rss_for_internal')) {
4270 $column_gui->setBlockProperty('news', 'settings', '1');
4271 $column_gui->setBlockProperty('news', 'public_notifications_option', '1');
4272 }
4273 }
4274 }
4275
4276 protected function addLocatorItems(): void
4277 {
4278 if ($this->object instanceof ilObjForum) {
4279 $this->locator->addItem(
4280 $this->object->getTitle(),
4281 $this->ctrl->getLinkTarget($this),
4282 '',
4283 $this->object->getRefId()
4284 );
4285 }
4286 }
4287
4288 public function handleFormInput(string $a_text, bool $a_stripslashes = true): string
4289 {
4290 $a_text = str_replace(['<', '>'], ['&lt;', '&gt;'], $a_text);
4291 if ($a_stripslashes) {
4292 $a_text = ilUtil::stripSlashes($a_text);
4293 }
4294
4295 return $a_text;
4296 }
4297
4298 public function prepareFormOutput(string $a_text): string
4299 {
4300 $a_text = str_replace(['&lt;', '&gt;'], ['<', '>'], $a_text);
4301
4303 }
4304
4305 protected function infoScreen(): void
4306 {
4307 if (
4308 !$this->access->checkAccess('visible', '', $this->object->getRefId()) &&
4309 !$this->access->checkAccess('read', '', $this->object->getRefId())
4310 ) {
4311 $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->MESSAGE);
4312 }
4313
4314 if (strtolower($this->ctrl->getCmd() ?? '') === 'infoscreen') {
4315 $this->ctrl->redirectByClass(ilInfoScreenGUI::class, 'showSummary');
4316 }
4317
4318 $info = new ilInfoScreenGUI($this);
4319 $info->enablePrivateNotes();
4320 $this->ctrl->forwardCommand($info);
4321 }
4322
4323 protected function markPostUnreadObject(): void
4324 {
4325 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4326 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4327 }
4328
4329 if ($this->objCurrentPost->getId() > 0) {
4330 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
4331
4332 $this->object->markPostUnread($this->user->getId(), $this->objCurrentPost->getId());
4333 }
4334 $this->viewThreadObject();
4335 }
4336
4337 protected function markPostReadObject(): void
4338 {
4339 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4340 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4341 }
4342
4343 if ($this->objCurrentTopic->getId() > 0 && $this->objCurrentPost->getId() > 0) {
4344 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
4345
4346 $this->object->markPostRead(
4347 $this->user->getId(),
4348 $this->objCurrentTopic->getId(),
4349 $this->objCurrentPost->getId()
4350 );
4351 }
4352
4353 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
4354 $this->ctrl->redirect($this, 'viewThread');
4355 }
4356
4357 protected function initHeaderAction(?string $sub_type = null, ?int $sub_id = null): ?ilObjectListGUI
4358 {
4359 $lg = parent::initHeaderAction();
4360
4361 if (!($lg instanceof ilObjForumListGUI) || !((bool) $this->settings->get('forum_notification', '0'))) {
4362 return $lg;
4363 }
4364
4365 if ($this->user->isAnonymous() || !$this->access->checkAccess('read', '', $this->object->getRefId())) {
4366 return $lg;
4367 }
4368
4369 $frm = $this->object->Forum;
4370 $frm->setForumId($this->object->getId());
4371 $frm->setForumRefId($this->object->getRefId());
4372 $frm->setMDB2Wherecondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
4373
4374 $are_notifications_enabled = $frm->isForumNotificationEnabled($this->user->getId());
4375 $has_membership_enabled_parent_container = $this->object->isParentMembershipEnabledContainer();
4376 $user_may_disable_notifcations = (
4377 $this->isUserAllowedToDeactivateNotification() ||
4378 !$has_membership_enabled_parent_container
4379 );
4380
4381 if ($this->objCurrentTopic->getId() > 0) {
4382 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
4383 }
4384
4385 if (!$this->user->isAnonymous()) {
4386 if ($has_membership_enabled_parent_container) {
4387 if ($are_notifications_enabled && $user_may_disable_notifcations) {
4388 $lg->addCustomCommand(
4389 $this->ctrl->getLinkTarget($this, 'disableForumNotification'),
4390 'forums_disable_forum_notification'
4391 );
4392 } elseif (!$are_notifications_enabled) {
4393 $lg->addCustomCommand(
4394 $this->ctrl->getLinkTarget($this, 'enableForumNotification'),
4395 'forums_enable_forum_notification'
4396 );
4397 }
4398 } elseif ($are_notifications_enabled) {
4399 $lg->addCustomCommand(
4400 $this->ctrl->getLinkTarget($this, 'disableForumNotification'),
4401 'forums_disable_forum_notification'
4402 );
4403 } else {
4404 $lg->addCustomCommand(
4405 $this->ctrl->getLinkTarget($this, 'enableForumNotification'),
4406 'forums_enable_forum_notification'
4407 );
4408 }
4409 }
4410
4411 if ($are_notifications_enabled && $user_may_disable_notifcations && !$this->user->isAnonymous()) {
4412 $frm_noti = new ilForumNotification($this->object->getRefId());
4413 $frm_noti->setUserId($this->user->getId());
4414 $interested_events = $frm_noti->readInterestedEvents();
4415
4416 $events_form_builder = $this->eventsFormBuilder([
4417 'hidden_value' => '',
4418 'notify_modified' => (bool) ($interested_events & ilForumNotificationEvents::UPDATED),
4419 'notify_censored' => (bool) ($interested_events & ilForumNotificationEvents::CENSORED),
4420 'notify_uncensored' => (bool) ($interested_events & ilForumNotificationEvents::UNCENSORED),
4421 'notify_post_deleted' => (bool) ($interested_events & ilForumNotificationEvents::POST_DELETED),
4422 'notify_thread_deleted' => (bool) ($interested_events & ilForumNotificationEvents::THREAD_DELETED),
4423 ]);
4424
4425 $notificationsModal = $this->uiFactory->modal()->roundtrip(
4426 $this->lng->txt('notification_settings'),
4427 [$events_form_builder->build()]
4428 )->withActionButtons([
4429 $this->uiFactory
4430 ->button()
4431 ->primary($this->lng->txt('save'), '#')
4432 ->withOnLoadCode(function (string $id): string {
4433 return "
4434 (function () {
4435 const button = document.getElementById('$id');
4436 if (!button) return;
4437
4438 const modalDialog = button.closest('.modal-dialog');
4439 if (!modalDialog) return;
4440
4441 const form = modalDialog.querySelector('.modal-body form');
4442 if (!form) return;
4443
4444 form.classList.add('ilForumNotificationSettingsForm');
4445 button.addEventListener('click', (event) => {
4446 event.preventDefault();
4447 if (form) {
4448 form.submit();
4449 }
4450 }, true);
4451 }());
4452 ";
4453 })
4454 ]);
4455
4456 $showNotificationSettingsBtn = $this->uiFactory->button()
4457 ->shy($this->lng->txt('notification_settings'), '#')
4458 ->withOnClick(
4459 $notificationsModal->getShowSignal()
4460 );
4461
4462 $lg->addCustomCommandButton($showNotificationSettingsBtn, $notificationsModal);
4463 }
4464
4465 $are_thread_notifications_enabled = false;
4466 if (!$this->user->isAnonymous() && $this->objCurrentTopic->getId() > 0) {
4467 $are_thread_notifications_enabled = $this->objCurrentTopic->isNotificationEnabled($this->user->getId());
4468 if ($are_thread_notifications_enabled) {
4469 $lg->addCustomCommand(
4470 $this->ctrl->getLinkTarget($this, 'toggleThreadNotification'),
4471 'forums_disable_notification'
4472 );
4473 } else {
4474 $lg->addCustomCommand(
4475 $this->ctrl->getLinkTarget($this, 'toggleThreadNotification'),
4476 'forums_enable_notification'
4477 );
4478 }
4479 }
4480 $this->ctrl->setParameter($this, 'thr_pk', '');
4481
4482 if (!$this->user->isAnonymous()) {
4483 if ($are_notifications_enabled || $are_thread_notifications_enabled) {
4484 $lg->addHeaderIcon(
4485 'not_icon',
4486 ilUtil::getImagePath('object/notification_on.svg'),
4487 $this->lng->txt('frm_notification_activated')
4488 );
4489 } else {
4490 $lg->addHeaderIcon(
4491 'not_icon',
4492 ilUtil::getImagePath('object/notification_off.svg'),
4493 $this->lng->txt('frm_notification_deactivated')
4494 );
4495 }
4496 }
4497
4498 return $lg;
4499 }
4500
4505 private function eventsFormBuilder(?array $predefined_values = null): ilForumNotificationEventsFormGUI
4506 {
4507 if ($this->objCurrentTopic->getId() > 0) {
4508 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
4509 }
4510
4512 $this->ctrl->getFormAction($this, 'saveUserNotificationSettings'),
4513 $predefined_values,
4514 $this->uiFactory,
4515 $this->lng
4516 );
4517 }
4518
4520 {
4521 $events_form_builder = $this->eventsFormBuilder();
4522
4523 if ($this->httpRequest->getMethod() === 'POST') {
4524 $form = $events_form_builder->build()->withRequest($this->httpRequest);
4525 $formData = $form->getData();
4526
4527 $interested_events = ilForumNotificationEvents::DEACTIVATED;
4528
4529 foreach ($events_form_builder->getValidEvents() as $event) {
4530 $interested_events += isset($formData[$event]) && $formData[$event] ? $events_form_builder->getValueForEvent(
4531 $event
4532 ) : 0;
4533 }
4534
4535 $frm_noti = new ilForumNotification($this->object->getRefId());
4536 $frm_noti->setUserId($this->user->getId());
4537 $frm_noti->setInterestedEvents($interested_events);
4538 $frm_noti->updateInterestedEvents();
4539 }
4540
4541 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
4542
4543 if ($this->objCurrentTopic->getId() > 0) {
4544 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
4545 $this->ctrl->redirect($this, 'viewThread');
4546 }
4547
4548 $this->ctrl->redirect($this, 'showThreads');
4549 }
4550
4552 {
4553 if ($this->objProperties->getNotificationType() === NotificationType::DEFAULT) {
4554 return true;
4555 }
4556
4557 if (!$this->objProperties->isUserToggleNoti() &&
4558 $this->objProperties->getNotificationType() === NotificationType::ALL_USERS) {
4559 return true;
4560 }
4561
4562 if ($this->objProperties->getNotificationType() === NotificationType::PER_USER &&
4563 $this->object->isParentMembershipEnabledContainer()) {
4564 $frm_noti = new ilForumNotification($this->object->getRefId());
4565 $frm_noti->setUserId($this->user->getId());
4566
4567 return !$frm_noti->isUserToggleNotification();
4568 }
4569
4570 return false;
4571 }
4572
4573 public function mergeThreadsObject(): void
4574 {
4575 if (!$this->is_moderator) {
4576 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4577 }
4578
4579 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4580 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4581 }
4582
4583 $threadIdToMerge = $this->http->wrapper()->query()->retrieve(
4584 'thr_pk',
4585 $this->refinery->byTrying([
4586 $this->refinery->kindlyTo()->int(),
4587 $this->refinery->always(0)
4588 ])
4589 );
4590 if ($threadIdToMerge <= 0) {
4591 $threadIds = array_values(
4592 array_filter(array_map(intval(...), (array) ($this->httpRequest->getParsedBody()['thread_ids'] ?? [])))
4593 );
4594 if (count($threadIds) === 1) {
4595 $threadIdToMerge = current($threadIds);
4596 } else {
4597 $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_one'));
4598 $this->showThreadsObject();
4599 return;
4600 }
4601 }
4602
4603 $frm = $this->object->Forum;
4604 $frm->setForumId($this->object->getId());
4605 $frm->setForumRefId($this->object->getRefId());
4606
4607 $threadToMerge = new ilForumTopic($threadIdToMerge);
4608
4609 if (ilForum::_lookupObjIdForForumId($threadToMerge->getForumId()) !== $frm->getForumId()) {
4610 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('not_allowed_to_merge_into_another_forum'));
4611 $this->showThreadsObject();
4612 return;
4613 }
4614
4615 $frm->setMDB2Wherecondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
4616
4617 $threadsTemplate = new ilTemplate(
4618 'tpl.forums_threads_liste.html',
4619 true,
4620 true,
4621 'components/ILIAS/Forum'
4622 );
4623
4624 $topicData = $frm->getOneTopic();
4625 if ($topicData->getTopPk() > 0) {
4626 $this->ctrl->setParameter($this, 'merge_thread_id', $threadIdToMerge);
4627 $tbl = new ilForumTopicTableGUI(
4628 $this,
4629 'mergeThreads',
4630 (int) $this->httpRequest->getQueryParams()['ref_id'],
4631 $topicData,
4632 $this->is_moderator
4633 );
4634 $tbl->setSelectedThread($threadToMerge);
4635 $tbl->setMapper($frm)->fetchData();
4636 $tbl->init();
4637 $threadsTemplate->setVariable('THREADS_TABLE', $tbl->getHTML());
4638 $this->tpl->setContent($threadsTemplate->get());
4639 } else {
4640 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
4641 $this->showThreadsObject();
4642 }
4643 }
4644
4645 public function confirmMergeThreadsObject(): void
4646 {
4647 if (!$this->is_moderator) {
4648 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4649 }
4650
4651 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4652 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4653 }
4654
4655 $sourceThreadId = (int) ($this->httpRequest->getQueryParams()['merge_thread_id'] ?? 0);
4656 $targetThreadIds = array_values(
4657 array_filter(array_map(intval(...), (array) ($this->httpRequest->getParsedBody()['thread_ids'] ?? [])))
4658 );
4659
4660 if ($sourceThreadId <= 0 || count($targetThreadIds) !== 1) {
4661 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
4662 $this->mergeThreadsObject();
4663 return;
4664 }
4665
4666 $targetThreadId = current($targetThreadIds);
4667 if ($sourceThreadId === $targetThreadId) {
4668 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('error_same_thread_ids'));
4669 $this->showThreadsObject();
4670 return;
4671 }
4672
4673 if (ilForumTopic::lookupForumIdByTopicId($sourceThreadId) !== ilForumTopic::lookupForumIdByTopicId($targetThreadId)) {
4674 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('not_allowed_to_merge_into_another_forum'));
4675 $this->ctrl->clearParameters($this);
4676 $this->showThreadsObject();
4677 return;
4678 }
4679
4680 if (ilForumTopic::lookupCreationDate($sourceThreadId) < ilForumTopic::lookupCreationDate($targetThreadId)) {
4681 $this->tpl->setOnScreenMessage('info', $this->lng->txt('switch_threads_for_merge'));
4682 }
4683
4684 $this->ensureThreadBelongsToForum($this->object->getId(), new ilForumTopic($sourceThreadId));
4685 $this->ensureThreadBelongsToForum($this->object->getId(), new ilForumTopic($targetThreadId));
4686
4687 $c_gui = new ilConfirmationGUI();
4688
4689 $c_gui->setFormAction($this->ctrl->getFormAction($this, 'performMergeThreads'));
4690 $c_gui->setHeaderText($this->lng->txt('frm_sure_merge_threads'));
4691 $c_gui->setCancel($this->lng->txt('cancel'), 'showThreads');
4692 $c_gui->setConfirm($this->lng->txt('confirm'), 'performMergeThreads');
4693
4694 $c_gui->addItem(
4695 'thread_ids[]',
4696 (string) $sourceThreadId,
4697 sprintf($this->lng->txt('frm_merge_src'), ilForumTopic::lookupTitle($sourceThreadId))
4698 );
4699 $c_gui->addItem(
4700 'thread_ids[]',
4701 (string) $targetThreadId,
4702 sprintf($this->lng->txt('frm_merge_target'), ilForumTopic::lookupTitle($targetThreadId))
4703 );
4704 $this->tpl->setContent($c_gui->getHTML());
4705 }
4706
4707 public function performMergeThreadsObject(): void
4708 {
4709 if (!$this->is_moderator) {
4710 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4711 }
4712
4713 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4714 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4715 }
4716
4717 $threadIds = array_values(
4718 array_filter(array_map(intval(...), (array) ($this->httpRequest->getParsedBody()['thread_ids'] ?? [])))
4719 );
4720 if (count($threadIds) !== 2) {
4721 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
4722 $this->showThreadsObject();
4723 return;
4724 }
4725
4726 if ((int) $threadIds[0] === (int) $threadIds[1]) {
4727 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('error_same_thread_ids'));
4728 $this->showThreadsObject();
4729 return;
4730 }
4731
4732 try {
4733 $frm = new ilForum();
4734 $frm->setForumId($this->object->getId());
4735 $frm->setForumRefId($this->object->getRefId());
4736
4737 $this->ensureThreadBelongsToForum($this->object->getId(), new ilForumTopic((int) $threadIds[0]));
4738 $this->ensureThreadBelongsToForum($this->object->getId(), new ilForumTopic((int) $threadIds[1]));
4739
4740 $frm->mergeThreads((int) $threadIds[0], (int) $threadIds[1]);
4741 $this->tpl->setOnScreenMessage('success', $this->lng->txt('merged_threads_successfully'));
4742 } catch (ilException $e) {
4743 $this->tpl->setOnScreenMessage('failure', $this->lng->txt($e->getMessage()));
4744 }
4745
4746 $this->showThreadsObject();
4747 }
4748
4749 protected function setSideBlocks(): void
4750 {
4751 $content = $this->getRightColumnHTML();
4752 if (!$this->ctrl->isAsynch()) {
4753 $content = implode('', [
4754 ilRepositoryObjectSearchGUI::getSearchBlockHTML($this->lng->txt('frm_search')),
4755 $content,
4756 ]);
4757 }
4758 $this->tpl->setRightContent($content);
4759 }
4760
4761 protected function deliverDraftZipFileObject(): void
4762 {
4763 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4764 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4765 }
4766
4767 $draft = ilForumPostDraft::newInstanceByDraftId($this->retrieveDraftId());
4768 $this->checkDraftAccess($draft);
4769 $fileData = new ilFileDataForumDrafts(0, $draft->getDraftId());
4770 if (!$fileData->deliverZipFile()) {
4771 $this->ctrl->redirect($this);
4772 }
4773 }
4774
4775 protected function deliverZipFileObject(): void
4776 {
4777 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
4778 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4779 }
4780
4781 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
4782
4783 $fileData = new ilFileDataForum($this->object->getId(), $this->objCurrentPost->getId());
4784 if (!$fileData->deliverZipFile()) {
4785 $this->ctrl->redirect($this);
4786 }
4787 }
4788
4789 protected function editThreadDraftObject(?ilPropertyFormGUI $form = null): void
4790 {
4792 !$this->access->checkAccess('add_thread', '', $this->object->getRefId()) ||
4793 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
4794 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4795 }
4796
4797 $frm = $this->object->Forum;
4798 $frm->setForumId($this->object->getId());
4799 $frm->setForumRefId($this->object->getRefId());
4800
4801 $draft = new ilForumPostDraft();
4802 $draftId = (int) ($this->httpRequest->getQueryParams()['draft_id'] ?? 0);
4803 if ($draftId > 0) {
4804 $draft = ilForumPostDraft::newInstanceByDraftId($draftId);
4805 $this->checkDraftAccess($draft);
4806 }
4807
4808 $do_history_check = (bool) ($this->httpRequest->getQueryParams()['hist_check'] ?? true);
4809 if (!($form instanceof ilPropertyFormGUI) && $do_history_check) {
4810 $this->doHistoryCheck($draft->getDraftId());
4811 }
4812
4813 if ($form instanceof ilPropertyFormGUI) {
4814 $this->ctrl->setParameter($this, 'draft_id', $draftId);
4815 } else {
4816 $form = $this->buildThreadForm(true);
4817 $form->setValuesByArray([
4818 'alias' => $draft->getPostUserAlias(),
4819 'subject' => $draft->getPostSubject(),
4820 'message' => ilRTE::_replaceMediaObjectImageSrc($frm->prepareText($draft->getPostMessage(), 2), 1),
4821 'notify' => $draft->isNotificationEnabled() && !$this->user->isAnonymous(),
4822 'userfile' => '',
4823 'del_file' => [],
4824 'draft_id' => $draftId
4825 ]);
4826 }
4827
4828 $this->tpl->setContent($form->getHTML() . $this->modal_history);
4829 }
4830
4831 protected function restoreFromHistoryObject(): void
4832 {
4834 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4835 }
4836
4837 $historyId = (int) ($this->httpRequest->getQueryParams()['history_id'] ?? 0);
4838 $history = new ilForumDraftsHistory($historyId);
4839
4840 $this->checkDraftAccess($history->getDraftId());
4841
4842 $draft = $history->rollbackAutosave();
4843 if ($draft->getThreadId() === 0 && $draft->getPostId() === 0) {
4844 $this->ctrl->setParameter($this, 'draft_id', $history->getDraftId());
4845 $this->ctrl->redirect($this, 'editThreadDraft');
4846 }
4847
4848 $this->ctrl->clearParameters($this);
4849 $this->ctrl->setParameter($this, 'pos_pk', $draft->getPostId());
4850 $this->ctrl->setParameter($this, 'thr_pk', $draft->getThreadId());
4851 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
4852 $this->ctrl->setParameter($this, 'action', 'editdraft');
4853
4854 ilForumPostDraft::createDraftBackup($draft->getDraftId());
4855
4856 $this->ctrl->redirect($this, 'viewThread');
4857 }
4858
4859 protected function saveThreadAsDraftObject(): void
4860 {
4862 !$this->access->checkAccess('add_thread', '', $this->object->getRefId()) ||
4863 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
4864 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4865 }
4866
4867 $autosave_draft_id = (int) ($this->httpRequest->getParsedBody()['draft_id'] ?? 0);
4868 if ($autosave_draft_id <= 0) {
4869 $autosave_draft_id = (int) ($this->httpRequest->getQueryParams()['draft_id'] ?? 0);
4870 }
4871
4872 $frm = $this->object->Forum;
4873 $frm->setForumId($this->object->getId());
4874 $frm->setForumRefId($this->object->getRefId());
4875 $frm->setMDB2WhereCondition('top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
4876 $topicData = $frm->getOneTopic();
4877
4878 $form = $this->buildThreadForm();
4879 if ($form->checkInput()) {
4880 if ($autosave_draft_id === 0) {
4881 $draft = new ilForumPostDraft();
4882 $draft->setForumId($topicData->getTopPk());
4883 $draft->setThreadId(0);
4884 $draft->setPostId(0);
4885 } else {
4886 $draft = ilForumPostDraft::newInstanceByDraftId($autosave_draft_id);
4887 $this->checkDraftAccess($draft);
4888 }
4889
4890 $draft->setPostSubject($this->handleFormInput($form->getInput('subject'), false));
4891 $draft->setPostMessage(ilRTE::_replaceMediaObjectImageSrc($form->getInput('message')));
4892 $draft->setPostUserAlias(ilForumUtil::getPublicUserAlias(
4893 $form->getInput('alias'),
4894 $this->objProperties->isAnonymized()
4895 ));
4896 $draft->setNotificationStatus($form->getInput('notify') && !$this->user->isAnonymous());
4897 $draft->setPostAuthorId($this->user->getId());
4898 $draft->setPostDisplayUserId($this->isWritingWithPseudonymAllowed() ? 0 : $this->user->getId());
4899
4900 if ($autosave_draft_id === 0) {
4901 $draftId = $draft->saveDraft();
4902 } else {
4903 $draft->updateDraft();
4904 $draftId = $draft->getDraftId();
4905 }
4906
4907 $GLOBALS['ilAppEventHandler']->raise(
4908 'components/ILIAS/Forum',
4909 'savedAsDraft',
4910 [
4911 'draftObj' => $draft,
4912 'obj_id' => $this->object->getId(),
4913 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed(),
4914 ]
4915 );
4916
4917 ilForumUtil::moveMediaObjects($form->getInput('message'), 'frm~d:html', $draftId, 'frm~d:html', $draftId);
4918
4919 $draftFileData = new ilFileDataForumDrafts($this->object->getId(), $draftId);
4920
4921 $files2delete = $form->getInput('del_file');
4922 if (is_array($files2delete) && $files2delete !== []) {
4923 $draftFileData->unlinkFilesByMD5Filenames($files2delete);
4924 }
4925
4926 if ($this->objProperties->isFileUploadAllowed()) {
4927 $file = $_FILES['userfile'];
4928 if (is_array($file) && !empty($file)) {
4929 $draftFileData->storeUploadedFiles();
4930 }
4931 }
4932
4933 $this->tpl->setOnScreenMessage('success', $this->lng->txt('save_draft_successfully'), true);
4934 $this->ctrl->clearParameters($this);
4935 $this->ctrl->redirect($this, 'showThreads');
4936 }
4937
4938 $this->requestAction = substr($this->requestAction, 6);
4939 $form->setValuesByPost();
4940 $this->ctrl->setParameter($this, 'draft_id', $autosave_draft_id);
4941 $this->tpl->setContent($form->getHTML());
4942 }
4943
4944 protected function updateThreadDraftObject(): void
4945 {
4947 !$this->access->checkAccess('add_thread', '', $this->object->getRefId()) ||
4948 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
4949 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
4950 }
4951
4952 $draft = ilForumPostDraft::newInstanceByDraftId($this->retrieveDraftId());
4953 $this->checkDraftAccess($draft);
4954
4955 $form = $this->buildThreadForm(true);
4956 if ($form->checkInput()) {
4957 $draft->setPostSubject($this->handleFormInput($form->getInput('subject'), false));
4958 $draft->setPostMessage(ilRTE::_replaceMediaObjectImageSrc($form->getInput('message')));
4959 $draft->setPostUserAlias(ilForumUtil::getPublicUserAlias(
4960 $form->getInput('alias'),
4961 $this->objProperties->isAnonymized()
4962 ));
4963 $draft->setNotificationStatus($form->getInput('notify') && !$this->user->isAnonymous());
4964 $draft->setPostAuthorId($this->user->getId());
4965 $draft->setPostDisplayUserId($this->isWritingWithPseudonymAllowed() ? 0 : $this->user->getId());
4966 $draft->updateDraft();
4967
4968 $GLOBALS['ilAppEventHandler']->raise(
4969 'components/ILIAS/Forum',
4970 'updatedDraft',
4971 [
4972 'draftObj' => $draft,
4973 'obj_id' => $this->object->getId(),
4974 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed(),
4975 ]
4976 );
4977
4979 $form->getInput('message'),
4980 'frm~d:html',
4981 $draft->getDraftId(),
4982 'frm~d:html',
4983 $draft->getDraftId()
4984 );
4985
4986 $draftFileData = new ilFileDataForumDrafts($this->object->getId(), $draft->getDraftId());
4987
4988 $files2delete = $form->getInput('del_file');
4989 if (is_array($files2delete) && $files2delete !== []) {
4990 $draftFileData->unlinkFilesByMD5Filenames($files2delete);
4991 }
4992
4993 if ($this->objProperties->isFileUploadAllowed()) {
4994 $file = $_FILES['userfile'];
4995 if (is_array($file) && !empty($file) && isset($file['full_path'][0]) && !empty($file['full_path'][0])) {
4996 $draftFileData->storeUploadedFiles();
4997 }
4998 }
4999
5000 $this->tpl->setOnScreenMessage('success', $this->lng->txt('save_draft_successfully'), true);
5001 $this->ctrl->clearParameters($this);
5002 $this->ctrl->redirect($this, 'showThreads');
5003 }
5004
5005 $form->setValuesByPost();
5006 $this->ctrl->setParameter($this, 'hist_check', 0);
5007 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
5008 $this->editThreadDraftObject($form);
5009 }
5010
5011 public function saveTopLevelDraftObject(): void
5012 {
5013 $this->saveAsDraftObject();
5014 }
5015
5016 public function saveAsDraftObject(): void
5017 {
5019 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
5020 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5021 }
5022
5023 $autosave_draft_id = $this->http->wrapper()->post()->retrieve(
5024 'draft_id',
5025 $this->refinery->byTrying([
5026 $this->refinery->kindlyTo()->int(),
5027 $this->refinery->always(null)
5028 ])
5029 );
5030
5031 if ($this->objCurrentTopic->getId() === 0) {
5032 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_deleted'), true);
5033 $this->ctrl->redirect($this);
5034 }
5035
5036 if ($this->objCurrentTopic->isClosed()) {
5037 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_closed'), true);
5038 $this->ctrl->redirect($this);
5039 }
5040
5041 $oReplyEditForm = $this->getReplyEditForm();
5042 if ($oReplyEditForm->checkInput()) {
5043 if ($this->objCurrentPost->getId() === 0) {
5044 $this->requestAction = '';
5045 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_parent_deleted'), true);
5046 $this->viewThreadObject();
5047 return;
5048 }
5049
5050 $oForumObjects = $this->getForumObjects();
5051 $frm = $oForumObjects['frm'];
5052 $frm->setMDB2WhereCondition(' top_frm_fk = %s ', ['integer'], [$frm->getForumId()]);
5053 $topicData = $frm->getOneTopic();
5054
5055 if ($this->requestAction === 'ready_showreply') {
5056 if (!$this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
5057 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5058 }
5059
5060 if ($autosave_draft_id > 0) {
5061 $draftObj = ilForumPostDraft::newInstanceByDraftId($autosave_draft_id);
5062 $this->checkDraftAccess($draftObj->getDraftId());
5063 } else {
5064 $draftObj = new ilForumPostDraft();
5065 $this->ensureThreadBelongsToForum($this->object->getId(), $this->objCurrentPost->getThread());
5066 $draftObj->setForumId($topicData->getTopPk());
5067 $draftObj->setThreadId($this->objCurrentTopic->getId());
5068 $draftObj->setPostId($this->objCurrentPost->getId());
5069 }
5070
5071 $draftObj->setPostSubject($this->handleFormInput($oReplyEditForm->getInput('subject'), false));
5072 $draftObj->setPostMessage(ilRTE::_replaceMediaObjectImageSrc($oReplyEditForm->getInput('message')));
5073 $draftObj->setPostUserAlias(ilForumUtil::getPublicUserAlias(
5074 $oReplyEditForm->getInput('alias'),
5075 $this->objProperties->isAnonymized()
5076 ));
5077 $draftObj->setNotificationStatus($oReplyEditForm->getInput('notify') && !$this->user->isAnonymous());
5078 $draftObj->setPostNotificationStatus($oReplyEditForm->getInput('notify_post') && !$this->user->isAnonymous());
5079
5080 $draftObj->setPostAuthorId($this->user->getId());
5081 $draftObj->setPostDisplayUserId(($this->isWritingWithPseudonymAllowed() ? 0 : $this->user->getId()));
5082
5083 if ($autosave_draft_id === 0) {
5084 $draft_id = $draftObj->saveDraft();
5085 } else {
5086 $draftObj->updateDraft();
5087 $draft_id = $draftObj->getDraftId();
5088 }
5089
5090 // copy temporary media objects (frm~)
5092 $oReplyEditForm->getInput('message'),
5093 'frm~d:html',
5094 $draft_id,
5095 'frm~d:html',
5096 $draft_id
5097 );
5098
5099 if ($this->objProperties->isFileUploadAllowed()) {
5100 $file = $_FILES['userfile'];
5101 if (is_array($file) && !empty($file)) {
5102 $oFDForumDrafts = new ilFileDataForumDrafts($this->object->getId(), $draftObj->getDraftId());
5103 $oFDForumDrafts->storeUploadedFiles();
5104 }
5105 }
5106
5107 $GLOBALS['ilAppEventHandler']->raise(
5108 'components/ILIAS/Forum',
5109 'savedAsDraft',
5110 [
5111 'draftObj' => $draftObj,
5112 'obj_id' => $this->object->getId(),
5113 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed()
5114 ]
5115 );
5116
5117 $frm_session_values = ilSession::get('frm');
5118 if (is_array($frm_session_values)) {
5119 $frm_session_values[$this->objCurrentPost->getThreadId()]['openTreeNodes'][] = $this->objCurrentPost->getId();
5120 }
5121 ilSession::set('frm', $frm_session_values);
5122
5123 $this->tpl->setOnScreenMessage('success', $this->lng->txt('save_draft_successfully'), true);
5124 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
5125 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
5126 $this->ctrl->redirect($this, 'viewThread');
5127 }
5128 } else {
5129 $oReplyEditForm->setValuesByPost();
5130 $this->requestAction = substr($this->requestAction, 6);
5131 }
5132 $this->viewThreadObject();
5133 }
5134
5135 protected function editDraftObject(): void
5136 {
5137 $this->doHistoryCheck($this->retrieveDraftId());
5138 $this->viewThreadObject();
5139 }
5140
5141 public function updateDraftObject(): void
5142 {
5144 !$this->access->checkAccess('read', '', $this->object->getRefId())) {
5145 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5146 }
5147
5148 if ($this->objCurrentTopic->getId() === 0) {
5149 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_deleted'), true);
5150 $this->ctrl->redirect($this);
5151 }
5152
5153 if ($this->objCurrentTopic->isClosed()) {
5154 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_thr_closed'), true);
5155 $this->ctrl->redirect($this);
5156 }
5157
5158 if ($this->objCurrentPost->getId() === 0) {
5159 $this->requestAction = '';
5160 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('frm_action_not_possible_parent_deleted'));
5161 $this->viewThreadObject();
5162 return;
5163 }
5164
5165 $oReplyEditForm = $this->getReplyEditForm();
5166 if ($oReplyEditForm->checkInput()) {
5167 $oForumObjects = $this->getForumObjects();
5168 $forumObj = $oForumObjects['forumObj'];
5169
5170 if (!$this->user->isAnonymous() && in_array($this->requestAction, ['showdraft', 'editdraft'])) {
5171 if (!$this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
5172 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5173 }
5174
5175 $draft = new ilForumPostDraft(
5176 $this->user->getId(),
5177 $this->objCurrentPost->getId(),
5178 $this->retrieveDraftId()
5179 );
5180
5181 $this->checkDraftAccess($draft);
5182
5183 $draft->setPostSubject($this->handleFormInput($oReplyEditForm->getInput('subject'), false));
5184 $draft->setPostMessage(ilRTE::_replaceMediaObjectImageSrc(
5185 $oReplyEditForm->getInput('message')
5186 ));
5187 $draft->setPostUserAlias(ilForumUtil::getPublicUserAlias(
5188 $oReplyEditForm->getInput('alias'),
5189 $this->objProperties->isAnonymized()
5190 ));
5191 $draft->setNotificationStatus($oReplyEditForm->getInput('notify') && !$this->user->isAnonymous());
5192 $draft->setUpdateUserId($this->user->getId());
5193 $draft->setPostAuthorId($this->user->getId());
5194 $draft->setPostDisplayUserId($this->isWritingWithPseudonymAllowed() ? 0 : $this->user->getId());
5195
5196 $draft->updateDraft();
5197
5198 $GLOBALS['ilAppEventHandler']->raise(
5199 'components/ILIAS/Forum',
5200 'updatedDraft',
5201 [
5202 'draftObj' => $draft,
5203 'obj_id' => $this->object->getId(),
5204 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed()
5205 ]
5206 );
5207
5208 $uploadedObjects = ilObjMediaObject::_getMobsOfObject('frm~:html', $this->user->getId());
5209
5210 foreach ($uploadedObjects as $mob) {
5211 ilObjMediaObject::_removeUsage($mob, 'frm~:html', $this->user->getId());
5212 ilObjMediaObject::_saveUsage($mob, 'frm~d:html', $draft->getDraftId());
5213 }
5215 $oReplyEditForm->getInput('message'),
5216 'frm~d:html',
5217 $draft->getDraftId()
5218 );
5219
5220 $oFDForumDrafts = new ilFileDataForumDrafts($forumObj->getId(), $draft->getDraftId());
5221
5222 $file2delete = $oReplyEditForm->getInput('del_file');
5223 if (is_array($file2delete) && count($file2delete)) {
5224 $oFDForumDrafts->unlinkFilesByMD5Filenames($file2delete);
5225 }
5226
5227 if ($this->objProperties->isFileUploadAllowed()) {
5228 $file = $_FILES['userfile'];
5229 if (is_array($file) && !empty($file)) {
5230 $oFDForumDrafts->storeUploadedFiles();
5231 }
5232 }
5233
5234 $frm_session_values = ilSession::get('frm');
5235 if (is_array($frm_session_values)) {
5236 $frm_session_values[$this->objCurrentPost->getThreadId()]['openTreeNodes'][] = $this->objCurrentPost->getId();
5237 }
5238 ilSession::set('frm', $frm_session_values);
5239 $this->tpl->setOnScreenMessage('success', $this->lng->txt('save_draft_successfully'), true);
5240 $this->ctrl->clearParameters($this);
5241 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
5242 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
5243 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
5244 }
5245 } else {
5246 $this->ctrl->clearParameters($this);
5247 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
5248 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
5249 $this->ctrl->setParameter($this, 'draft_id', $this->retrieveDraftId());
5250 $this->ctrl->setParameter($this, 'action', 'editdraft');
5251 $oReplyEditForm->setValuesByPost();
5252 $this->viewThreadObject();
5253 return;
5254 }
5255 $this->ctrl->clearParameters($this);
5256 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
5257 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
5258 $this->ctrl->redirect($this, 'viewThread');
5259 }
5260
5261 protected function deleteMobsOfDraft(int $draft_id, string $message): void
5262 {
5263 $oldMediaObjects = ilObjMediaObject::_getMobsOfObject('frm~d:html', $draft_id);
5264 $curMediaObjects = ilRTE::_getMediaObjects($message);
5265 foreach ($oldMediaObjects as $oldMob) {
5266 $found = false;
5267 foreach ($curMediaObjects as $curMob) {
5268 if ($oldMob === $curMob) {
5269 $found = true;
5270 break;
5271 }
5272 }
5273 if (!$found && ilObjMediaObject::_exists($oldMob)) {
5274 ilObjMediaObject::_removeUsage($oldMob, 'frm~d:html', $draft_id);
5275 $mob_obj = new ilObjMediaObject($oldMob);
5276 $mob_obj->delete();
5277 }
5278 }
5279 }
5280
5281 protected function deleteSelectedDraft(): void
5282 {
5283 $draft = new ilForumPostDraft($this->user->getId(), $this->objCurrentPost->getId(), $this->retrieveDraftId());
5284 $this->checkDraftAccess($draft);
5285
5286 $this->deleteMobsOfDraft($draft->getDraftId(), $draft->getPostMessage());
5287
5288 $objFileDataForumDrafts = new ilFileDataForumDrafts($this->object->getId());
5289 $objFileDataForumDrafts->delete([$draft->getDraftId()]);
5290
5291 $GLOBALS['ilAppEventHandler']->raise(
5292 'components/ILIAS/Forum',
5293 'deletedDraft',
5294 [
5295 'draftObj' => $draft,
5296 'obj_id' => $this->object->getId(),
5297 'is_file_upload_allowed' => $this->objProperties->isFileUploadAllowed()
5298 ]
5299 );
5300 $draft->deleteDraft();
5301
5302 $this->tpl->setOnScreenMessage('success', $this->lng->txt('delete_draft_successfully'), true);
5303 $this->ctrl->clearParameters($this);
5304 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
5305 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
5306 $this->ctrl->redirect($this, 'viewThread');
5307 }
5308
5309 protected function autosaveDraftAsyncObject(): void
5310 {
5311 if ($this->requestAction !== 'ready_showreply' &&
5313 $this->access->checkAccess('read', '', $this->object->getRefId()) &&
5314 $this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
5315 $action = new ilForumAutoSaveAsyncDraftAction(
5316 $this->user,
5317 $this->getReplyEditForm(),
5318 $this->objProperties,
5319 $this->objCurrentTopic,
5320 $this->objCurrentPost,
5321 fn(string $message): string => $this->handleFormInput($message),
5322 $this->retrieveDraftId(),
5323 ilObjForum::lookupForumIdByRefId($this->ref_id),
5324 ilUtil::stripSlashes($this->requestAction)
5325 );
5326
5327 $this->http->saveResponse($this->http->response()->withBody(
5328 \ILIAS\Filesystem\Stream\Streams::ofString(json_encode(
5329 $action->executeAndGetResponseObject(),
5330 JSON_THROW_ON_ERROR
5331 ))
5332 ));
5333 }
5334
5335 $this->http->sendResponse();
5336 $this->http->close();
5337 }
5338
5339 protected function autosaveThreadDraftAsyncObject(): void
5340 {
5341 if ($this->requestAction !== 'ready_showreply' &&
5343 $this->access->checkAccess('read', '', $this->object->getRefId()) &&
5344 $this->access->checkAccess('add_thread', '', $this->object->getRefId())) {
5345 $action = new ilForumAutoSaveAsyncDraftAction(
5346 $this->user,
5347 $this->buildThreadForm(),
5348 $this->objProperties,
5349 $this->objCurrentTopic,
5350 $this->objCurrentPost,
5351 fn(string $message): string => $this->handleFormInput($message, false),
5352 $this->retrieveDraftId(),
5353 ilObjForum::lookupForumIdByRefId($this->ref_id),
5354 ilUtil::stripSlashes($this->requestAction)
5355 );
5356
5357 $this->http->saveResponse($this->http->response()->withBody(
5358 \ILIAS\Filesystem\Stream\Streams::ofString(json_encode(
5359 $action->executeAndGetResponseObject(),
5360 JSON_THROW_ON_ERROR
5361 ))
5362 ));
5363 }
5364
5365 $this->http->sendResponse();
5366 $this->http->close();
5367 }
5368
5369 private function renderSplitButton(
5370 ilTemplate $tpl,
5371 string $action,
5372 bool $is_post,
5373 ilForumPost $node,
5374 int $pageIndex = 0,
5375 ?ilForumPostDraft $draft = null
5376 ): void {
5377 $draft_id = $this->retrieveDraftId();
5378
5379 $actions = [];
5380 if ($is_post) {
5381 if (($this->objCurrentPost->getId() !== $node->getId() || (
5382 !in_array($action, ['showreply', 'showedit', 'censor', 'delete'], true) &&
5383 !$this->displayConfirmPostActivation()
5384 )) && ($this->is_moderator || $node->isActivated() || $node->isOwner($this->user->getId()))) {
5385 if ($this->is_moderator && !$this->objCurrentTopic->isClosed() && !$node->isActivated()) {
5386 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5387 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
5388 $this->ctrl->setParameter($this, 'page', $pageIndex);
5389 $this->ctrl->setParameter(
5390 $this,
5391 'orderby',
5392 $this->getOrderByParam()
5393 );
5394 $primary_action = $this->ctrl->getLinkTarget(
5395 $this,
5396 'askForPostActivation',
5397 (string) $node->getId()
5398 );
5399 $primary_action_language_id = 'activate_post';
5400 $this->ctrl->clearParameters($this);
5401 }
5402 if (
5403 !$this->objCurrentTopic->isClosed() && $node->isActivated() && !$node->isCensored() &&
5404 $this->access->checkAccess('add_reply', '', $this->object->getRefId())
5405 ) {
5406 $this->ctrl->setParameter($this, 'action', 'showreply');
5407 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5408 $this->ctrl->setParameter($this, 'page', $pageIndex);
5409 $this->ctrl->setParameter(
5410 $this,
5411 'orderby',
5412 $this->getOrderByParam()
5413 );
5414 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
5415 $primary_action = $this->ctrl->getLinkTarget(
5416 $this,
5417 'viewThread',
5418 'reply_' . $node->getId()
5419 );
5420 $primary_action_language_id = 'reply_to_postings';
5421 $this->ctrl->clearParameters($this);
5422 }
5423 if (
5424 !$this->objCurrentTopic->isClosed() &&
5425 !$node->isCensored() &&
5426 !$this->user->isAnonymous() &&
5427 ($node->isOwner($this->user->getId()) || $this->is_moderator)
5428 ) {
5429 $this->ctrl->setParameter($this, 'action', 'showedit');
5430 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5431 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
5432 $this->ctrl->setParameter($this, 'page', $pageIndex);
5433 $this->ctrl->setParameter(
5434 $this,
5435 'orderby',
5436 $this->getOrderByParam()
5437 );
5438 $actions['edit'] = $this->ctrl->getLinkTarget($this, 'viewThread', (string) $node->getId());
5439 $this->ctrl->clearParameters($this);
5440 }
5441 if (!$this->user->isAnonymous()) {
5442 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5443 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
5444 $this->ctrl->setParameter($this, 'page', $pageIndex);
5445 $this->ctrl->setParameter(
5446 $this,
5447 'orderby',
5448 $this->getOrderByParam()
5449 );
5450 $this->ctrl->setParameter($this, 'viewmode', $this->selectedSorting);
5451
5452 $read_undread_txt = 'frm_mark_as_read';
5453 $read_undread_cmd = 'markPostRead';
5454 if ($node->isPostRead()) {
5455 $read_undread_txt = 'frm_mark_as_unread';
5456 $read_undread_cmd = 'markPostUnread';
5457 }
5458 $actions[$read_undread_txt] = $this->ctrl->getLinkTarget(
5459 $this,
5460 $read_undread_cmd,
5461 (string) $node->getId()
5462 );
5463
5464 $this->ctrl->clearParameters($this);
5465 }
5466 if (!$node->isCensored()) {
5467 $this->ctrl->setParameterByClass(ilForumExportGUI::class, 'top_pk', $node->getForumId());
5468 $this->ctrl->setParameterByClass(ilForumExportGUI::class, 'thr_pk', $node->getThreadId());
5469
5470
5471 $this->ctrl->clearParameters($this);
5472 }
5473 if (
5474 !$this->objCurrentTopic->isClosed() &&
5475 !$this->user->isAnonymous() &&
5476 ($this->is_moderator || ($node->isOwner($this->user->getId()) && !$node->hasReplies()))
5477 ) {
5478 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5479 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
5480 $this->ctrl->setParameter($this, 'page', $pageIndex);
5481 $this->ctrl->setParameter(
5482 $this,
5483 'orderby',
5484 $this->getOrderByParam()
5485 );
5486 $actions['delete'] = $this->ctrl->getFormAction($this, 'deletePosting');
5487 $this->ctrl->clearParameters($this);
5488 }
5489 if ($this->is_moderator && !$this->objCurrentTopic->isClosed()) {
5490 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5491 $this->ctrl->setParameter($this, 'thr_pk', $node->getThreadId());
5492 $this->ctrl->setParameter($this, 'page', $pageIndex);
5493 $this->ctrl->setParameter(
5494 $this,
5495 'orderby',
5496 $this->getOrderByParam()
5497 );
5498 if ($node->isCensored()) {
5499 $this->ctrl->setParameter($this, 'action', 'viewThread');
5500 $actions['frm_revoke_censorship'] = $this->ctrl->getFormAction($this, 'revokeCensorship');
5501 } else {
5502 $actions['frm_censorship'] = $this->ctrl->getFormAction($this, 'addCensorship');
5503 }
5504 $this->ctrl->clearParameters($this);
5505 }
5506 }
5507 } elseif ($draft_id !== $draft->getDraftId() || !in_array($action, ['deletedraft', 'editdraft'])) {
5508 // get actions for drafts
5509 $this->ctrl->setParameter($this, 'action', 'publishdraft');
5510 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5511 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
5512 $this->ctrl->setParameter($this, 'page', $pageIndex);
5513 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
5514 $this->ctrl->setParameter(
5515 $this,
5516 'orderby',
5517 $this->getOrderByParam()
5518 );
5519 $primary_action = $this->ctrl->getLinkTarget($this, 'publishSelectedDraft', (string) $node->getId());
5520 $primary_action_language_id = 'publish';
5521 $this->ctrl->clearParameters($this);
5522
5523 $this->ctrl->setParameter($this, 'action', 'editdraft');
5524 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5525 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
5526 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
5527 $this->ctrl->setParameter($this, 'page', $pageIndex);
5528 $this->ctrl->setParameter(
5529 $this,
5530 'orderby',
5531 $this->getOrderByParam()
5532 );
5533 $actions['edit'] = $this->ctrl->getLinkTarget($this, 'editDraft', 'draft_edit_' . $draft->getDraftId());
5534 $this->ctrl->clearParameters($this);
5535
5536 $this->ctrl->setParameter($this, 'pos_pk', $node->getId());
5537 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
5538 $this->ctrl->setParameter($this, 'draft_id', $draft->getDraftId());
5539 $this->ctrl->setParameter($this, 'page', $pageIndex);
5540 $this->ctrl->setParameter(
5541 $this,
5542 'orderby',
5543 $this->getOrderByParam()
5544 );
5545 $actions['delete'] = $this->ctrl->getFormAction($this, 'deletePostingDraft');
5546 $this->ctrl->clearParameters($this);
5547
5548 if ($draft_id !== 0 && $action === 'editdraft') {
5549 $actions = [];
5550 }
5551 }
5552
5553 $tpl->setCurrentBlock('posts_row');
5554 if ($actions !== [] && !$this->objCurrentTopic->isClosed()) {
5555 $items = [];
5556 foreach ($actions as $lng_id => $url) {
5557 if ($lng_id === 'frm_revoke_censorship' || $lng_id === 'frm_censorship') {
5558 $modalTemplate = new ilTemplate('tpl.forums_censor_modal.html', true, true, 'components/ILIAS/Forum');
5559 $form_id = str_replace('.', '_', uniqid('form', true));
5560 $modalTemplate->setVariable('FORM_ID', $form_id);
5561
5562 if ($node->isCensored()) {
5563 $modalTemplate->setVariable('BODY', $this->lng->txt('forums_info_censor2_post'));
5564 } else {
5565 $modalTemplate->setVariable('BODY', $this->lng->txt('forums_info_censor_post'));
5566 $modalTemplate->touchBlock('message');
5567 }
5568
5569 $modalTemplate->setVariable('FORM_ACTION', $url);
5570
5571 $content = $this->uiFactory->legacy()->content($modalTemplate->get());
5572 $submitBtn = $this->uiFactory->button()->primary(
5573 $this->lng->txt('submit'),
5574 '#'
5575 )->withOnLoadCode(
5576 static function (string $id) use ($form_id): string {
5577 return "
5578 (function () {
5579 const button = document.getElementById('$id');
5580 if (!button) return;
5581
5582 const form = document.getElementById('$form_id');
5583 if (!form) return;
5584
5585 button.addEventListener('click', (event) => {
5586 event.preventDefault();
5587 form.submit();
5588 }, true);
5589 }());
5590 ";
5591 }
5592 );
5593 $modal = $this->uiFactory->modal()->roundtrip(
5594 $this->lng->txt($lng_id),
5595 [$content]
5596 )->withActionButtons([$submitBtn]);
5597 $items[] = $this->uiFactory->button()->shy($this->lng->txt($lng_id), '#')->withOnClick(
5598 $modal->getShowSignal()
5599 );
5600
5601 $this->modalActionsContainer[] = $modal;
5602 continue;
5603 }
5604
5605 if ($lng_id === 'delete') {
5606 $modal = $this->uiFactory->modal()->interruptive(
5607 $this->lng->txt($lng_id),
5608 str_contains($url, 'deletePostingDraft') ?
5609 $this->lng->txt('forums_info_delete_draft') :
5610 $this->lng->txt('forums_info_delete_post'),
5611 $url
5612 )->withActionButtonLabel(
5613 $this->lng->txt(str_contains($url, 'deletePostingDraft') ? 'deletePostingDraft' : 'deletePosting')
5614 );
5615
5616 $items[] = $this->uiFactory->button()->shy($this->lng->txt($lng_id), '#')->withOnClick(
5617 $modal->getShowSignal()
5618 );
5619
5620 $this->modalActionsContainer[] = $modal;
5621
5622
5623 continue;
5624 }
5625
5626 $items[] = $this->uiFactory->button()->shy($this->lng->txt($lng_id), $url);
5627 }
5628
5629 $dropdown = $this->uiFactory->dropdown()->standard($items);
5630 $render_action_buttons = [$dropdown];
5631 if (isset($primary_action, $primary_action_language_id)) {
5632 if ($primary_action_language_id === 'activate_post') {
5633 $action_button = $this->addActivationFormModal($node);
5634 } else {
5635 $action_button = $this->uiFactory->button()->standard(
5636 $this->lng->txt($primary_action_language_id),
5637 $primary_action
5638 );
5639 }
5640 $tpl->setVariable('MAIN_ACTION', $this->uiRenderer->render($action_button));
5641 }
5642 $tpl->setVariable('DROPDOWN_ACTIONS', $this->uiRenderer->render($render_action_buttons));
5643 }
5644 }
5645
5646 private function checkDraftAccess(int|ilForumPostDraft $draft): void
5647 {
5648 $draft = is_int($draft) ? ilForumPostDraft::newInstanceByDraftId($draft) : $draft;
5649 if (!$this->hasDraftAccess($draft)) {
5650 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5651 }
5652 }
5653
5654 private function hasDraftAccess(int|ilForumPostDraft $draft): bool
5655 {
5656 $draft = is_int($draft) ? ilForumPostDraft::newInstanceByDraftId($draft) : $draft;
5657 return (
5658 $draft->getDraftId() &&
5659 !$this->user->isAnonymous() &&
5660 $this->access->checkAccess('add_reply', '', $this->object->getRefId()) &&
5661 $this->user->getId() === $draft->getPostAuthorId()
5662 );
5663 }
5664
5665 private function doHistoryCheck(int $draftId): void
5666 {
5668 return;
5669 }
5670
5671 $this->checkDraftAccess($draftId);
5672
5674 $draftsFromHistory = ilForumDraftsHistory::getInstancesByDraftId($draftId);
5675 if ($draftsFromHistory !== []) {
5676 $form_tpl = new ilTemplate('tpl.restore_thread_draft.html', true, true, 'components/ILIAS/Forum');
5677
5678 $first_open = null;
5679 foreach ($draftsFromHistory as $history_instance) {
5680 $accordion = new ilAccordionGUI();
5681 $accordion->setId('acc_' . $history_instance->getHistoryId());
5682 $accordion->setBehaviour(ilAccordionGUI::ALL_CLOSED);
5683 if ($first_open === null) {
5684 $first_open = $history_instance->getHistoryId();
5685 $accordion->setBehaviour(ilAccordionGUI::FIRST_OPEN);
5686 }
5687
5688 $form_tpl->setCurrentBlock('list_item');
5689 $message = ilRTE::_replaceMediaObjectImageSrc($history_instance->getPostMessage(), 1);
5690
5691 $history_date = ilDatePresentation::formatDate(new ilDateTime(
5692 $history_instance->getDraftDate(),
5694 ));
5695 $this->ctrl->setParameter($this, 'history_id', $history_instance->getHistoryId());
5696 $header = $history_date . ': ' . $history_instance->getPostSubject();
5697
5698 $accordion_tpl = new ilTemplate(
5699 'tpl.restore_thread_draft_accordion_content.html',
5700 true,
5701 true,
5702 'components/ILIAS/Forum'
5703 );
5704 $accordion_tpl->setVariable('MESSAGE', $message);
5705 $accordion_tpl->setVariable(
5706 'BUTTON',
5707 $this->uiRenderer->render(
5708 $this->uiFactory->button()->standard(
5709 $this->lng->txt('restore'),
5710 $this->ctrl->getLinkTarget($this, 'restoreFromHistory')
5711 )
5712 )
5713 );
5714 $accordion->addItem($header, $accordion_tpl->get());
5715
5716 $form_tpl->setVariable('ACC_AUTO_SAVE', $accordion->getHTML());
5717 $form_tpl->parseCurrentBlock();
5718 }
5719
5720 $form_tpl->setVariable('RESTORE_DATA_EXISTS', 'found_threat_history_to_restore');
5721
5722 $modal = $this->ui_factory->modal()->interruptive(
5723 $this->lng->txt('restore_draft_from_autosave'),
5724 $form_tpl->get(),
5725 '#'
5726 )->withAdditionalOnLoadCode(function (string $id): string {
5727 return "document.getElementById('$id').dataset.modalId = 'frm_autosave_restore';";
5728 });
5729
5730 $this->modal_history = $this->ui_renderer->render($modal);
5731 } else {
5733 }
5734 }
5735
5736 private function renderPostingForm(ilTemplate $tpl, ilForum $frm, ilForumPost $node, string $action): void
5737 {
5738 $draft_id = $this->retrieveDraftId();
5739 if ($action === 'showedit' && (
5740 (!$this->is_moderator && !$node->isOwner($this->user->getId())) ||
5741 $this->user->isAnonymous() ||
5742 $node->isCensored()
5743 )) {
5744 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5745 } elseif ($action === 'showreply' && !$this->access->checkAccess('add_reply', '', $this->object->getRefId())) {
5746 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
5747 }
5748
5749 $tpl->setVariable('REPLY_ANKER', 'reply_' . $this->objCurrentPost->getId());
5750 $oEditReplyForm = $this->getReplyEditForm();
5751 $subject = '';
5752 if ($action !== 'editdraft') {
5753 switch ($this->objProperties->getSubjectSetting()) {
5754 case 'add_re_to_subject':
5755 $subject = $this->getModifiedReOnSubject();
5756 break;
5757
5758 case 'preset_subject':
5759 $subject = $this->objCurrentPost->getSubject();
5760 break;
5761
5762 case 'empty_subject':
5763 $subject = '';
5764 break;
5765 }
5766 }
5767
5768 switch ($action) {
5769 case 'showreply':
5770 if ($this->ctrl->getCmd() === 'savePost' || $this->ctrl->getCmd() === 'saveAsDraft') {
5771 $oEditReplyForm->setValuesByPost();
5772 } elseif ($this->ctrl->getCmd() === 'quotePost') {
5773 $authorinfo = new ilForumAuthorInformation(
5774 $node->getPosAuthorId(),
5775 $node->getDisplayUserId(),
5776 (string) $node->getUserAlias(),
5777 (string) $node->getImportName()
5778 );
5779
5780 $oEditReplyForm->setValuesByPost();
5781 $oEditReplyForm->getItemByPostVar('message')->setValue(
5783 $frm->prepareText(
5784 $node->getMessage(),
5785 1,
5786 $authorinfo->getAuthorName()
5787 ) . "\n" . $oEditReplyForm->getInput('message'),
5788 1
5789 )
5790 );
5791 } else {
5792 $oEditReplyForm->setValuesByArray([
5793 'draft_id' => $draft_id,
5794 'alias' => '',
5795 'subject' => $subject,
5796 'message' => '',
5797 'notify' => 0,
5798 'userfile' => '',
5799 'del_file' => []
5800 ]);
5801 }
5802 break;
5803
5804 case 'showedit':
5805 if ($this->ctrl->getCmd() === 'savePost') {
5806 $oEditReplyForm->setValuesByPost();
5807 } else {
5808 $oEditReplyForm->setValuesByArray([
5809 'alias' => '',
5810 'subject' => $this->objCurrentPost->getSubject(),
5812 $this->objCurrentPost->getMessage(),
5813 2
5814 ), 1),
5815 'notify' => $this->objCurrentPost->isNotificationEnabled() && !$this->user->isAnonymous(),
5816 'userfile' => '',
5817 'del_file' => [],
5818 'draft_id' => $draft_id
5819 ]);
5820 }
5821 break;
5822
5823 case 'editdraft':
5824 if (in_array($this->ctrl->getCmd(), ['saveDraft', 'updateDraft', 'publishDraft'])) {
5825 $oEditReplyForm->setValuesByPost();
5826 } elseif ($draft_id > 0) {
5827 $draftObject = new ilForumPostDraft(
5828 $this->user->getId(),
5829 $this->objCurrentPost->getId(),
5830 $draft_id
5831 );
5832 $oEditReplyForm->setValuesByArray([
5833 'alias' => $draftObject->getPostUserAlias(),
5834 'subject' => $draftObject->getPostSubject(),
5836 $draftObject->getPostMessage(),
5837 2
5838 ), 1),
5839 'notify' => $draftObject->isNotificationEnabled() && !$this->user->isAnonymous(),
5840 'userfile' => '',
5841 'del_file' => [],
5842 'draft_id' => $draft_id
5843 ]);
5844 }
5845 break;
5846 }
5847
5848 $this->ctrl->setParameter($this, 'pos_pk', $this->objCurrentPost->getId());
5849 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentPost->getThreadId());
5850 $this->ctrl->setParameter($this, 'page', (int) ($this->httpRequest->getQueryParams()['page'] ?? 0));
5851 $this->ctrl->setParameter(
5852 $this,
5853 'orderby',
5854 $this->getOrderByParam()
5855 );
5856 $this->ctrl->setParameter(
5857 $this,
5858 'action',
5859 ilUtil::stripSlashes($this->requestAction)
5860 );
5861 if ($action !== 'editdraft') {
5862 $tpl->setVariable('FORM', $oEditReplyForm->getHTML());
5863 }
5864 $this->ctrl->clearParameters($this);
5865 }
5866
5867 private function getResetLimitedViewInfo(): string
5868 {
5869 $this->ctrl->setParameter($this, 'thr_pk', $this->objCurrentTopic->getId());
5870
5871 $buttons = [
5872 $this->uiFactory->button()->standard(
5873 $this->lng->txt('reset_limited_view_button'),
5874 $this->ctrl->getLinkTarget($this, 'resetLimitedView')
5875 )
5876 ];
5877
5878 return $this->uiRenderer->render(
5879 $this->uiFactory
5880 ->messageBox()
5881 ->info($this->lng->txt('reset_limited_view_info'))
5882 ->withButtons($buttons)
5883 );
5884 }
5885
5886 private function getOrderByParam(): string
5887 {
5888 return ilUtil::stripSlashes($this->http->wrapper()->query()->retrieve(
5889 'orderby',
5890 $this->refinery->byTrying([
5891 $this->refinery->kindlyTo()->string(),
5892 $this->refinery->always('')
5893 ])
5894 ));
5895 }
5896
5901 private function preloadPostingFileResources(array $postings, array $draftsObjects): void
5902 {
5903 $collectionIds = [];
5904
5905 foreach ($postings as $posting) {
5906 $rcid = $posting->getRCID();
5907 if ($rcid !== ilForumPost::NO_RCID && !empty($rcid)) {
5908 $collection_ids[] = $rcid;
5909 }
5910 }
5911
5912 foreach ($draftsObjects as $draft) {
5913 $rcid = $draft->getRCID();
5914 if ($rcid !== ilForumPostDraft::NO_RCID && !empty($rcid)) {
5915 $collection_ids[] = $rcid;
5916 }
5917 }
5918
5919 if (!empty($collection_ids)) {
5920 $this->irss->preloadCollections(array_unique($collection_ids));
5921 }
5922 }
5923}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
ThreadSortation
renderer()
factory()
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:544
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
GUI class for public user profile presentation.
const IL_CAL_DATETIME
error(string $a_errmsg)
return true
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _recordReadEvent(string $a_type, int $a_ref_id, int $obj_id, int $usr_id, $a_ext_rc=null, $a_ext_time=null)
This class represents a property in a property form.
This class represents a checkbox property in a property form.
This class represents an option in a checkbox group.
Column user interface class.
setRepositoryMode(bool $a_repositorymode)
setBlockProperty(string $a_block_type, string $a_property, string $a_value)
This function is supposed to be used for block type specific properties, that should be passed to ilB...
Class ilCommonActionDispatcherGUI.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ?ilObjUser $user=null,)
@classDescription Date and time handling
Base class for ILIAS Exception handling.
Export User Interface Class.
This class represents a file wizard property in a property form.
Class ilForumDraftHistory.
static getInstancesByDraftId(int $draft_id)
Class ilForumExplorerGUI.
Forum export to HTML and Print.
@ilCtrl_Calls ilForumModeratorsGUI: ilRepositorySearchGUI
Class ilForumNotification.
const PRESENTATION_MODE_PRESENTATION
presentation mode for requesting
@ilCtrl_Calls ilForumPageGUI: ilPageEditorGUI, ilEditClipboardGUI, ilMDEditorGUI @ilCtrl_Calls ilForu...
Class ilForumPostDraft.
static getThreadDraftData(int $post_author_id, int $forum_id)
static createDraftBackup(int $draft_id)
static newInstanceByDraftId(int $draft_id)
static getDraftInstancesByUserId(int $user_id)
static getSortedDrafts(int $usrId, int $threadId, int $sorting=ilForumProperties::VIEW_DATE_ASC)
setMessage(string $a_message)
isOwner(int $a_user_id=0)
setChangeDate(?string $a_changedate)
static getInstance(int $a_obj_id=0)
@ilCtrl_Calls ilForumSettingsGUI: ilObjectContentStyleSettingsGUI
Class ilForumTopicTableGUI.
static lookupTitle(int $a_topic_id)
static lookupCreationDate(int $thread_id)
static lookupForumIdByTopicId(int $a_topic_id)
static getPublicUserAlias(string $user_alias, bool $is_anonymized)
static saveMediaObjects(string $post_message, string $target_type, int $target_id, int $direction=0)
static moveMediaObjects(string $post_message, string $source_type, int $source_id, string $target_type, int $target_id, int $direction=0)
Class Forum core functions for forum.
static _lookupObjIdForForumId(int $a_for_id)
prepareText(string $text, int $edit=0, string $quote_user='', string $type='')
static _isModerator(int $a_ref_id, int $a_usr_id)
Help GUI class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a hidden form property in a property form.
static getInstanceByType(string $type)
Class ilInfoScreenGUI.
Learning progress access checks.
static checkAccess(int $a_ref_id, bool $a_allow_only_read=true)
check access to learning progress
Class ilObjUserTrackingGUI.
static prepareFormOutput($a_str, bool $a_strip=false)
Last visited history for repository items.
addItem(int $a_ref_id, string $a_link, string $a_type, string $a_title="", ?int $a_sub_obj_id=null, string $a_goto_link="")
Add an item to the stack.
A news item can be created by different sources.
static getFirstNewsIdForContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Get first new id of news set related to a certain context.
This class represents a non editable value in a property form.
@ilCtrl_Calls ilObjForumGUI: ilPermissionGUI, ilForumExportGUI, ilInfoScreenGUI @ilCtrl_Calls ilObjFo...
setDisplayConfirmPostActivation(bool $status=false)
renderPostingForm(ilTemplate $tpl, ilForum $frm, ilForumPost $node, string $action)
addLocatorItems()
should be overwritten to add object specific items (repository items are preloaded)
afterSave(ilObject $new_object)
ForumThreadTableSessionStorage $forum_thread_table_session_storage
getOpenCloseActionForThread(ilForumTopic $forum_topic, int $ref_id)
getThreadProperties(ilForumTopic $forum_topic)
ilForumProperties $objProperties
ilForumPost $objCurrentPost
ilPropertyFormGUI $replyEditForm
renderSplitButton(ilTemplate $tpl, string $action, bool $is_post, ilForumPost $node, int $pageIndex=0, ?ilForumPostDraft $draft=null)
getStickyActionForThread(ilForumTopic $forum_topic, int $ref_id)
readonly bool $in_page_editor_style_context
checkDraftAccess(int|ilForumPostDraft $draft)
getTabs()
@abstract overwrite in derived GUI class of your object type
markTopThreadInOverview(ilForumTopic $current_thread, Item $list_item)
getEditFormCustomValues(array &$a_values)
Add values to custom edit fields.
static _goto($a_target, $a_thread=0, $a_posting=0)
renderDraftContent(ilTemplate $tpl, string $action, ilForumPost $referencePosting, array $drafts)
decorateWithAutosave(ilPropertyFormGUI $form)
initHeaderAction(?string $sub_type=null, ?int $sub_id=null)
Add header action menu.
addDraftButtonIfDraftsExists(string $cmd)
getEditTitleModal(ilForumTopic $topic)
ILIAS GlobalScreen Services $globalScreen
ilForumSettingsGUI $forum_settings_gui
addActivationFormModal(ilForumPost $node)
getSortationViewControl(int $offset, ThreadSortation $effective_sortation)
hideToolbar($a_flag=null)
setColumnSettings(ilColumnGUI $column_gui)
handleCensorship(bool $wasRevoked=false)
eventsFormBuilder(?array $predefined_values=null)
createThread(ilForumPostDraft $draft, bool $createFromDraft=false)
Refactored thread creation to method, refactoring to a separate class should be done in next refactor...
buildMinimalThreadForm(bool $isDraft=false)
updateCustom(ilPropertyFormGUI $form)
Insert custom update form values into object.
getSafePostCommands()
This method must return a list of safe POST commands.
hasDraftAccess(int|ilForumPostDraft $draft)
renderThreadOverview(ilForum $frm, ForumDto $frm_object)
editThreadDraftObject(?ilPropertyFormGUI $form=null)
ILIAS DI RBACServices $rbac
ilForumThreadSettingsSessionStorage $selected_post_storage
getUnsafeGetCommands()
This method must return a list of unsafe GET commands.
bool $display_confirm_post_activation
doHistoryCheck(int $draftId)
prepareFormOutput(string $a_text)
deleteMobsOfDraft(int $draft_id, string $message)
ILIAS Style Content Object ObjectFacade $content_style_domain
ilObjectDataCache $ilObjDataCache
getLinkActionForThread(int $ref_id, string $title, string $cmd, ?int $thread_id=null)
retrieveDraftId(bool $from_post=false)
ilForumTopic $objCurrentTopic
renderPostContent(ilTemplate $tpl, ilForumPost $node, string $action, int $pageIndex, int $postIndex)
handleFormInput(string $a_text, bool $a_stripslashes=true)
ilNavigationHistory $ilNavigationHistory
ensureValidPageForCurrentPosting(array $subtree_nodes, array $pagedPostings, int $pageSize, ilForumPost $firstForumPost)
publishDraftObject(bool $use_replyform=true)
buildThreadForm(bool $isDraft=false)
createEmptyThread()
Refactored thread creation to method, refactoring to a separate class should be done in next refactor...
ensureThreadBelongsToForum(int $objId, ilForumTopic $thread)
preloadPostingFileResources(array $postings, array $draftsObjects)
initEditCustomForm(ilPropertyFormGUI $a_form)
Add custom fields to update form.
renderSortationControl(int $currentSorting)
renderViewModeControl(int $currentViewMode)
ILIAS Style Content GUIService $content_style_gui
Psr Http Message ServerRequestInterface $httpRequest
__construct($data, int $id=0, bool $call_by_reference=true, bool $prepare_output=true)
getActionsForThreadOverview(int $ref_id, ilForumTopic $forum_topic)
Class ilObjForumListGUI.
Class ilObjForum.
static lookupForumIdByRefId(int $ref_id)
static lookupForumIdByObjId(int $obj_id)
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _removeUsage(int $a_mob_id, string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
Remove usage of mob in another container.
static _saveUsage(int $a_mob_id, string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
Save usage of mob within another container (e.g.
static _getMobsOfObject(string $a_type, int $a_id, int|false $a_usage_hist_nr=0, string $a_lang="-")
GUI class for the workflow of copying objects.
class ilObjectDataCache
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
Class ilObjectGUI Basic methods of all Output classes.
Class ilObject Basic functions for all objects.
static _lookupObjectId(int $ref_id)
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
static _getAllReferences(int $id)
get all reference ids for object ID
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
This class represents a property form user interface.
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
static _getMediaObjects(string $a_text, int $a_direction=0)
Returns all media objects found in the passed string.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getOverallRatingForObject(int $a_obj_id, string $a_obj_type, ?int $a_sub_obj_id=null, ?string $a_sub_obj_type=null, ?int $a_category_id=null)
Get overall rating for an object.
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
ILIAS Setting Class.
special template class to simplify handling of ITX/PEAR
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
get(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
Returns a block with all replacements done.
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
This class represents a text area property in a property form.
This class represents a text property in a property form.
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static switchColor(int $a_num, string $a_css1, string $a_css2)
switches style sheets for each even $a_num (used for changing colors of different result rows)
static initjQuery(?ilGlobalTemplateInterface $a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template
const ROOT_FOLDER_ID
Definition: constants.php:32
$info
Definition: entry_point.php:21
This describes a Standard Dropdown.
Definition: Standard.php:27
Common interface to all items.
Definition: Item.php:32
This is how the factory for UI elements looks.
Definition: Factory.php:38
An entity that renders components to a string output.
Definition: Renderer.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$ref_id
Definition: ltiauth.php:66
$post
Definition: ltitoken.php:46
static http()
Fetches the global http state from ILIAS.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
button(string $caption, string $cmd)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Bulky.php:21
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
Class ilChatroomConfigFileHandler \ILIAS\Chatroom\classes.
global $lng
Definition: privfeed.php:31
$ilErr
Definition: raiseError.php:33
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26
$url
Definition: shib_logout.php:70
$GLOBALS["DIC"]
Definition: wac.php:54
$objId
Definition: xapitoken.php:55