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