19declare(strict_types=1);
61 private readonly
bool $is_moderator =
false,
62 bool $preventImplicitRead =
false
65 $this->db =
$DIC->database();
66 $this->
user = $DIC->user();
68 if (!$preventImplicitRead) {
75 $this->
setId((
int) $data[
'thr_pk']);
85 $this->
setSticky((
bool) $data[
'is_sticky']);
86 $this->
setClosed((
bool) $data[
'is_closed']);
91 if (isset(
$data[
'num_posts'])) {
94 if (isset(
$data[
'num_unread_posts'])) {
97 if (isset(
$data[
'usr_notification_is_enabled'])) {
104 if ($this->forum_id !== 0) {
105 $nextId = $this->db->nextId(
'frm_threads');
110 'thr_pk' => [
'integer', $nextId],
111 'thr_top_fk' => [
'integer', $this->forum_id],
112 'thr_subject' => [
'text', $this->subject],
113 'thr_display_user_id' => [
'integer', $this->display_user_id],
114 'thr_usr_alias' => [
'text', $this->user_alias],
115 'thr_num_posts' => [
'integer', $this->num_posts],
116 'thr_last_post' => [
'text', $this->last_post_string],
117 'thr_date' => [
'timestamp', $this->createdate],
118 'thr_update' => [
'timestamp',
null],
119 'import_name' => [
'text', $this->import_name],
120 'is_sticky' => [
'integer', (
int) $this->is_sticky],
121 'is_closed' => [
'integer', (
int) $this->is_closed],
122 'avg_rating' => [
'text', (
string) $this->average_rating],
123 'thr_author_id' => [
'integer', $this->thr_author_id]
137 if ($this->
id !== 0) {
138 $this->db->manipulateF(
148 [
'integer',
'text',
'timestamp',
'integer',
'text',
'text',
'integer'],
154 $this->last_post_string,
155 (
string) $this->average_rating,
168 if ($this->
id !== 0) {
169 $res = $this->db->queryF(
171 SELECT frm_threads.*, top_frm_fk frm_obj_id
173 INNER JOIN frm_data ON top_pk = thr_top_fk
181 if (is_object($row)) {
182 $this->forum_id = (
int) $row->thr_top_fk;
183 $this->display_user_id = (
int) $row->thr_display_user_id;
184 $this->user_alias = $row->thr_usr_alias;
185 $this->subject = html_entity_decode((
string) $row->thr_subject);
186 $this->createdate = $row->thr_date;
187 $this->changedate = $row->thr_update;
188 $this->import_name = $row->import_name;
189 $this->num_posts = (
int) $row->thr_num_posts;
190 $this->last_post_string = $row->thr_last_post;
191 $this->visits = (
int) $row->visits;
192 $this->is_sticky = (bool) $row->is_sticky;
193 $this->is_closed = (
bool) $row->is_closed;
194 $this->frm_obj_id = (
int) $row->frm_obj_id;
195 $this->average_rating = (
float) $row->avg_rating;
196 $this->thr_author_id = (
int) $row->thr_author_id;
209 return $this->
read();
214 $this->db->setLimit(1);
215 $res = $this->db->queryF(
216 'SELECT pos_fk FROM frm_posts_tree WHERE thr_fk = %s AND parent_pos = %s AND depth = %s ORDER BY rgt DESC',
217 [
'integer',
'integer',
'integer'],
221 if (($row = $this->db->fetchObject(
$res)) !==
null) {
222 return (
int) $row->pos_fk ?: 0;
229 $checkTime = time() - (60 * 60);
231 if (
ilSession::get(
'frm_visit_frm_threads_' . $this->
id) < $checkTime) {
234 $this->db->manipulateF(
235 'UPDATE frm_threads SET visits = visits + 1 WHERE thr_pk = %s',
244 $res = $this->db->queryF(
248 INNER JOIN frm_posts_tree ON frm_posts_tree.pos_fk = pos_pk
249 WHERE pos_thr_fk = %s' . ($ignoreRoot ?
' AND parent_pos != 0 ' :
''),
254 $row = $this->db->fetchAssoc(
$res);
255 if (is_array($row)) {
256 return (
int) $row[
'cnt'];
264 $res = $this->db->queryF(
268 INNER JOIN frm_posts_tree ON frm_posts_tree.pos_fk = pos_pk
269 WHERE (pos_status = %s
270 OR (pos_status = %s AND pos_display_user_id = %s))
271 AND pos_thr_fk = %s' . ($ignoreRoot ?
' AND parent_pos != 0 ' :
''),
272 [
'integer',
'integer',
'integer',
'integer'],
273 [
'1',
'0', $this->
user->getId(), $this->id]
276 $row = $this->db->fetchAssoc(
$res);
277 if (is_array($row)) {
278 return (
int) $row[
'cnt'];
286 $this->db->setLimit(1);
287 $res = $this->db->queryF(
291 INNER JOIN frm_posts_tree ON pos_fk = pos_pk
292 WHERE parent_pos = %s
295 [
'integer',
'integer'],
299 if ($row = $this->db->fetchAssoc(
$res)) {
300 $post =
new ilForumPost((
int) $row[
'pos_pk'], $isModerator, $preventImplicitRead);
301 $post->assignData($row);
305 throw new OutOfBoundsException(sprintf(
'Could not find first posting by id: %s', $this->
id));
310 $this->db->setLimit(1);
311 $res = $this->db->queryF(
315 INNER JOIN frm_posts_tree ON pos_fk = pos_pk
316 WHERE parent_pos != %s
320 [
'integer',
'integer',
'integer'],
324 if ($row = $this->db->fetchAssoc(
$res)) {
325 $post =
new ilForumPost((
int) $row[
'pos_pk'], $isModerator, $preventImplicitRead);
326 $post->assignData($row);
330 throw new OutOfBoundsException(sprintf(
'Could not find first posting by id: %s', $this->
id));
335 if ($this->
id !== 0) {
336 $this->db->setLimit(1);
337 $res = $this->db->queryF(
338 'SELECT pos_pk FROM frm_posts WHERE pos_thr_fk = %s ORDER BY pos_date DESC',
343 if (($row = $this->db->fetchObject(
$res)) !==
null) {
348 throw new OutOfBoundsException(sprintf(
'Could not find last posting by id: %s', $this->
id));
353 if ($this->
id !== 0) {
354 $this->db->setLimit(1);
355 $res = $this->db->queryF(
359 WHERE pos_thr_fk = %s
360 AND (pos_status = %s OR (pos_status = %s AND pos_display_user_id = %s))
361 ORDER BY pos_date DESC',
362 [
'integer',
'integer',
'integer',
'integer'],
363 [$this->
id,
'1',
'0', $this->
user->getId()]
366 if (($row = $this->db->fetchObject(
$res)) !==
null) {
371 throw new OutOfBoundsException(sprintf(
'Could not find last active posting by id: %s', $this->
id));
381 if ($this->
id !== 0) {
382 $res = $this->db->queryF(
'SELECT pos_pk FROM frm_posts WHERE pos_thr_fk = %s', [
'integer'], [$this->
id]);
385 $posts[(
int) $row->pos_pk] = (
int) $row->pos_pk;
404 if ($a_post_node->
getLft() > 1) {
405 $dummy_root_condition =
'lft >= %s AND lft < %s';
407 $dummy_root_condition =
'lft > %s AND lft < %s';
411 SELECT is_author_moderator, pos_author_id, pos_pk, fpt_date, rgt, pos_top_fk, pos_thr_fk,
412 pos_display_user_id, pos_usr_alias, pos_subject,
413 pos_status, pos_message, pos_date, pos_update, rcid,
414 update_user, pos_cens, pos_cens_com, notify,
415 import_name, fpt_pk, parent_pos, lft, depth,
417 WHEN fur.post_id IS NULL ' .
422 firstname, lastname, title, login
430 ON pos_display_user_id = usr_id
432 LEFT JOIN frm_user_read fur
433 ON fur.thread_id = pos_thr_fk
434 AND fur.post_id = pos_pk
437 WHERE ' . $dummy_root_condition .
'
439 $data_types[] =
'integer';
440 $data_types[] =
'integer';
441 $data_types[] =
'integer';
442 $data_types[] =
'integer';
448 if ($this->orderField !==
'') {
452 $res = $this->db->queryF($query, $data_types,
$data);
455 while ($row = $this->db->fetchAssoc(
$res)) {
457 $post->assignData($row);
459 if (!$this->is_moderator && !
$post->isActivated() &&
$post->getPosAuthorId() !== $this->user->getId()) {
463 if ((
int) $row[
'pos_display_user_id'] !== 0) {
464 $usr_ids[(
int) $row[
'pos_display_user_id']] = (
int) $row[
'pos_display_user_id'];
466 if ((
int) $row[
'update_user'] !== 0) {
467 $usr_ids[(
int) $row[
'update_user']] = (
int) $row[
'update_user'];
487 public function movePosts(
int $old_obj_id,
int $old_pk,
int $new_obj_id,
int $new_pk):
int
489 if ($this->
id === 0) {
496 foreach ($post_ids as $post_id) {
498 $moved = $file_obj->moveFilesOfPost($new_obj_id);
502 'from' => $old_obj_id,
504 'position_id' => $post_id
511 foreach ($postsMoved as $postedInformation) {
512 $file_obj =
new ilFileDataForum($postedInformation[
'to'], $postedInformation[
'position_id']);
513 $file_obj->moveFilesOfPost($postedInformation[
'from']);
521 $ilAtomQuery = $this->db->buildAtomQuery();
522 $ilAtomQuery->addTableLock(
'frm_user_read');
524 $ilAtomQuery->addQueryCallable(
static function (
ilDBInterface $ilDB) use ($new_obj_id, $current_id):
void {
526 'DELETE FROM frm_user_read WHERE obj_id = %s AND thread_id =%s',
527 [
'integer',
'integer'],
528 [$new_obj_id, $current_id]
532 'UPDATE frm_user_read SET obj_id = %s WHERE thread_id = %s',
533 [
'integer',
'integer'],
534 [$new_obj_id, $current_id]
540 $this->db->manipulateF(
541 'UPDATE frm_posts SET pos_top_fk = %s WHERE pos_thr_fk = %s',
542 [
'integer',
'integer'],
546 $res = $this->db->queryF(
547 'SELECT * FROM frm_posts WHERE pos_thr_fk = %s',
555 while (
$post = $this->db->fetchAssoc(
$res)) {
559 (
int)
$post[
'pos_pk'],
563 $news_item->setContextObjId($new_obj_id);
564 $news_item->update();
567 return count($post_ids);
574 $is_post_activation_enabled = $objProperties->isPostActivationEnabled();
576 if ($pos_id !==
null) {
577 $res = $this->db->queryF(
579 SELECT lft, rgt, depth
583 [
'integer',
'integer'],
600 fp.pos_display_user_id,
604 fp.is_author_moderator,
607 WHEN fur.post_id IS NULL ' .
612 COUNT(fpt2.pos_fk) children
614 FROM frm_posts_tree fpt
616 INNER JOIN frm_posts fp
617 ON fp.pos_pk = fpt.pos_fk
619 LEFT JOIN frm_posts_tree fpt2
620 ON fpt2.lft BETWEEN fpt.lft AND fpt.rgt
621 AND fpt.thr_fk = fpt2.thr_fk
622 AND fpt.pos_fk != fpt2.pos_fk ';
625 LEFT JOIN frm_user_read fur
626 ON fur.thread_id = fp.pos_thr_fk
627 AND fur.post_id = fp.pos_pk
628 AND fur.usr_id = ' . $this->db->quote($this->
user->getId(),
'integer') .
'
630 LEFT JOIN usr_data ud
631 ON ud.usr_id = fp.pos_display_user_id
633 WHERE fpt.thr_fk = ' . $this->db->quote($this->id,
'integer');
636 $query .=
' AND fpt.lft > ' . $this->db->quote(
$data[
'lft'],
'integer') .
637 ' AND fpt.lft < ' . $this->db->quote(
$data[
'rgt'],
'integer') .
' ';
639 if ($is_post_activation_enabled && !$this->is_moderator) {
640 $query .=
' AND (fp.pos_status = 1 OR fp.pos_status = 0 AND fp.pos_display_user_id = ' . $this->db->quote(
641 $this->
user->getId(),
646 if (
$data && is_numeric($num_levels)) {
647 $query .=
' AND fpt.depth <= ' . $this->db->quote((
int)
$data[
'depth'] + $num_levels,
'integer') .
' ';
650 $query .=
' GROUP BY fpt.depth,
659 fp.pos_display_user_id,
663 fp.is_author_moderator,
665 ORDER BY fpt.rgt DESC
670 FROM frm_posts_tree fpt
671 INNER JOIN frm_posts fp
672 ON fp.pos_pk = fpt.pos_fk
673 WHERE fpt.thr_fk = ' . $this->db->quote($this->
id,
'integer');
675 if ($is_post_activation_enabled && !$this->is_moderator) {
676 $queryCounter .=
' AND (fp.pos_status = 1 OR fp.pos_status = 0 AND fp.pos_display_user_id = ' . $this->db->quote(
677 $this->
user->getId(),
681 $queryCounter .=
' ORDER BY fpt.rgt DESC';
683 $resCounter = $this->db->query($queryCounter);
686 while ($row = $this->db->fetchAssoc($resCounter)) {
690 $res = $this->db->query($query);
693 while ($row = $this->db->fetchAssoc(
$res)) {
694 if ((
int) $row[
'pos_display_user_id'] !== 0) {
695 $usr_ids[] = (
int) $row[
'pos_display_user_id'];
698 $row[
'counter'] =
$counter[$row[
'pos_pk']];
700 $casted_row[
'depth'] = (
int) $row[
'depth'];
701 $casted_row[
'rgt'] = (
int) $row[
'rgt'];
702 $casted_row[
'parent_pos'] = (
int) $row[
'parent_pos'];
703 $casted_row[
'pos_pk'] = (
int) $row[
'pos_pk'];
704 $casted_row[
'pos_subject'] = (string) $row[
'pos_subject'];
705 $casted_row[
'pos_usr_alias'] = (string) $row[
'pos_usr_alias'];
706 $casted_row[
'pos_date'] = (string) $row[
'pos_date'];
707 $casted_row[
'pos_update'] = (string) $row[
'pos_update'];
708 $casted_row[
'pos_status'] = (
int) $row[
'pos_status'];
709 $casted_row[
'pos_display_user_id'] = (
int) $row[
'pos_display_user_id'];
710 $casted_row[
'import_name'] = (string) $row[
'import_name'];
711 $casted_row[
'pos_author_id'] = (
int) $row[
'pos_author_id'];
712 $casted_row[
'is_author_moderator'] = (
int) $row[
'is_author_moderator'];
713 $casted_row[
'post_id'] = (
int) $row[
'post_id'];
714 $casted_row[
'post_read'] = (
int) $row[
'post_read'];
715 $casted_row[
'children'] = (
int) $row[
'children'];
717 $children[] = $casted_row;
727 if ($this->
id && $a_user_id) {
728 $result = $this->db->queryF(
729 'SELECT COUNT(notification_id) cnt FROM frm_notification WHERE user_id = %s AND thread_id = %s',
730 [
'integer',
'integer'],
731 [$a_user_id, $this->
id]
734 if ($row = $this->db->fetchAssoc($result)) {
735 return (
int) $row[
'cnt'] > 0;
747 $nextId = $this->db->nextId(
'frm_notification');
748 $this->db->manipulateF(
750 INSERT INTO frm_notification
756 [
'integer',
'integer',
'integer'],
757 [$nextId, $a_user_id, $this->
id]
764 if ($this->
id && $a_user_id) {
765 $this->db->manipulateF(
766 'DELETE FROM frm_notification WHERE user_id = %s AND thread_id = %s',
767 [
'integer',
'integer'],
768 [$a_user_id, $this->
id]
775 if ($this->
id && !$this->is_sticky) {
776 $this->db->manipulateF(
777 'UPDATE frm_threads SET is_sticky = %s WHERE thr_pk = %s',
778 [
'integer',
'integer'],
782 $this->is_sticky =
true;
791 if ($this->
id && $this->is_sticky) {
792 $this->db->manipulateF(
793 'UPDATE frm_threads SET is_sticky = %s WHERE thr_pk = %s',
794 [
'integer',
'integer'],
798 $this->is_sticky =
false;
807 if ($this->
id && !$this->is_closed) {
808 $this->db->manipulateF(
809 'UPDATE frm_threads SET is_closed = %s WHERE thr_pk = %s',
810 [
'integer',
'integer'],
813 $this->is_closed =
true;
819 if ($this->
id && $this->is_closed) {
820 $this->db->manipulateF(
821 'UPDATE frm_threads SET is_closed = %s WHERE thr_pk = %s',
822 [
'integer',
'integer'],
826 $this->is_closed =
false;
840 public function setId(
int $a_id): void
852 $this->forum_id = $a_forum_id;
862 $this->display_user_id = $a_user_id;
872 $this->user_alias = $a_user_alias;
882 $this->subject = $a_subject;
892 $this->createdate = $a_createdate;
902 $this->changedate = $a_changedate;
912 $this->import_name = $a_import_name;
922 $this->last_post_string = $a_last_post;
932 $this->visits = $a_visits;
942 $this->is_sticky = $a_sticky;
952 $this->is_closed = $a_closed;
962 $this->orderField = $a_order_field;
991 'SELECT thr_subject FROM frm_threads WHERE thr_pk = %s',
997 return (
string) $row->thr_subject;
1007 [
'thr_subject' => [
'text', $this->
getSubject()]],
1008 [
'thr_pk' => [
'integer', $this->
getId()]]
1013 $first_node->setSubject($this->
getSubject());
1014 $first_node->update();
1015 }
catch (OutOfBoundsException) {
1021 $this->num_posts = $a_num_posts;
1043 $this->user_notification_enabled = $status;
1054 if (!in_array(strtoupper($direction), self::$possibleOrderDirections,
true)) {
1055 $direction = current(self::$possibleOrderDirections);
1058 $this->orderDirection = $direction;
1073 'SELECT thr_top_fk FROM frm_threads WHERE thr_pk = %s',
1080 return (
int) $row[
'thr_top_fk'];
1088 'thr_num_posts' => [
'integer', $this->
getNumPosts()],
1089 'visits' => [
'integer', $this->
getVisits()],
1091 'thr_subject' => [
'text', $this->
getSubject()]
1093 [
'thr_pk' => [
'integer', $this->
getId()]]
1103 'SELECT thr_date FROM frm_threads WHERE thr_pk = %s',
1110 if (is_array($row)) {
1111 $date = $row[
'thr_date'];
1124 $this->last_post =
$post;
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstance(int $a_obj_id=0)
setDisplayUserId(int $a_user_id)
isNotificationEnabled(int $a_user_id)
static lookupTitle(int $a_topic_id)
countPosts(bool $ignoreRoot=false)
isUserNotificationEnabled()
disableNotification(int $a_user_id)
enableNotification(int $a_user_id)
setLastPostString(?string $a_last_post)
setSticky(bool $a_sticky)
getPostTree(ilForumPost $a_post_node)
Fetches and returns an array of posts from the post tree, starting with the node object passed by the...
__construct(private int $id=0, private readonly bool $is_moderator=false, bool $preventImplicitRead=false)
Returns an object of a forum topic.
static array $possibleOrderDirections
countActivePosts(bool $ignoreRoot=false)
getFirstVisiblePostNode(bool $isModerator=false, bool $preventImplicitRead=false)
setChangeDate(?string $a_changedate)
setNumUnreadPosts(int $num_unread_posts)
setAverageRating(float $average_rating)
setClosed(bool $a_closed)
setUserAlias(?string $a_user_alias)
setCreateDate(?string $a_createdate)
getPostRootNode(bool $isModerator=false, bool $preventImplicitRead=false)
static lookupCreationDate(int $thread_id)
setOrderDirection(string $direction)
readonly ilDBInterface $db
bool $user_notification_enabled
setThrAuthorId(int $thr_author_id)
getLastPostForThreadOverview()
setSubject(string $a_subject)
static lookupForumIdByTopicId(int $a_topic_id)
movePosts(int $old_obj_id, int $old_pk, int $new_obj_id, int $new_pk)
Moves all posts within the current thread to a new forum.
getNestedSetPostChildren(?int $pos_id=null, ?int $num_levels=null)
setImportName(?string $a_import_name)
setForumId(int $a_forum_id)
setUserNotificationEnabled(bool $status)
setOrderField(string $a_order_field)
setNumPosts(int $a_num_posts)
setLastPostForThreadOverview(ilForumPost $post)
static _lookupObjIdForForumId(int $a_for_id)
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.
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.