ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilObjForum.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2012 ILIAS open source, Extended GPL, see docs/LICENSE */
3
13class ilObjForum extends ilObject
14{
20 public $Forum;
21
22 // private $objProperties = null;
23
28 protected static $obj_id_to_forum_id_cache = array();
29
34 protected static $ref_id_to_forum_id_cache = array();
35
40 protected static $forum_statistics_cache = array();
41
46 protected static $forum_last_post_cache = array();
47
48 private $settings;
49 private $rbac;
50 private $ilBench;
51 private $user;
52 private $logger;
53
60 public function __construct($a_id = 0, $a_call_by_reference = true)
61 {
62 global $DIC;
63 $this->settings = $DIC->settings();
64 $this->rbac = $DIC->rbac();
65 $this->db = $DIC->database();
66 $this->ilBench = $DIC['ilBench'];
67 $this->user = $DIC->user();
68 $this->logger = $DIC->logger()->root();
69
70 $this->type = 'frm';
71 parent::__construct($a_id, $a_call_by_reference);
72
73 /*
74 * this constant is used for the information if a single post is marked as new
75 * All threads/posts created before this date are never marked as new
76 * Default is 8 weeks
77 *
78 */
79 $new_deadline = time() - 60 * 60 * 24 * 7 * ($this->settings->get('frm_store_new') ?
80 $this->settings->get('frm_store_new') :
81 8);
82 define('NEW_DEADLINE', $new_deadline);
83
84 // TODO: needs to rewrite scripts that are using Forum outside this class
85 $this->Forum = new ilForum();
86 }
87
91 public function create()
92 {
93 $id = parent::create();
94
95 $properties = ilForumProperties::getInstance($this->getId());
96 $properties->setDefaultView(ilForumProperties::VIEW_DATE_ASC);
97 $properties->setAnonymisation(0);
98 $properties->setStatisticsStatus(0);
99 $properties->setPostActivation(0);
100 $properties->setThreadSorting(0);
101 $properties->insert();
102
103 $this->createSettings();
104
105 $this->saveData();
106
107 return $id;
108 }
109
113 public function setPermissions($a_ref_id)
114 {
115 parent::setPermissions($a_ref_id);
116
117 // ...finally assign moderator role to creator of forum object
118 $roles = array(ilObjForum::_lookupModeratorRole($this->getRefId()));
119 $this->rbac->admin()->assignUser($roles[0], $this->getOwner(), 'n');
120 $this->updateModeratorRole($roles[0]);
121 }
122
126 public function updateModeratorRole($role_id)
127 {
128 $this->db->manipulate('UPDATE frm_data SET top_mods = ' . $this->db->quote($role_id, 'integer') . ' WHERE top_frm_fk = ' . $this->db->quote($this->getId(), 'integer'));
129 }
130
136 public function getDiskUsage()
137 {
138 return ilObjForumAccess::_lookupDiskUsage($this->id);
139 }
140
141 public static function _lookupThreadSubject($a_thread_id)
142 {
143 global $DIC;
144 $ilDB = $DIC->database();
145
146 $res = $ilDB->queryf(
147 '
148 SELECT thr_subject FROM frm_threads WHERE thr_pk = %s',
149 array('integer'),
150 array($a_thread_id)
151 );
152
153 while ($row = $ilDB->fetchObject($res)) {
154 return $row->thr_subject;
155 }
156 return '';
157 }
158
159 // METHODS FOR UN-READ STATUS
160 public function getCountUnread($a_usr_id, $a_thread_id = 0, $ignoreRoot = false)
161 {
162 $a_frm_id = $this->getId();
163
164 $this->ilBench->start("Forum", 'getCountRead');
165 if (!$a_thread_id) {
166 // Get topic_id
167 $res = $this->db->queryf(
168 '
169 SELECT top_pk FROM frm_data WHERE top_frm_fk = %s',
170 array('integer'),
171 array($a_frm_id)
172 );
173
174
175 while ($row = $this->db->fetchObject($res)) {
176 $topic_id = $row->top_pk;
177 }
178
179 // Get number of posts
180 $res = $this->db->queryf(
181 '
182 SELECT COUNT(pos_pk) num_posts
183 FROM frm_posts
184 LEFT JOIN frm_posts_tree ON frm_posts_tree.pos_fk = pos_pk
185 WHERE pos_top_fk = %s' . ($ignoreRoot ? ' AND parent_pos != 0 ' : ''),
186 array('integer'),
187 array($topic_id)
188 );
189
190 while ($row = $this->db->fetchObject($res)) {
191 $num_posts = $row->num_posts;
192 }
193
194 $res = $this->db->queryf(
195 '
196 SELECT COUNT(post_id) count_read FROM frm_user_read
197 WHERE obj_id = %s
198 AND usr_id = %s',
199 array('integer', 'integer'),
200 array($a_frm_id, $a_usr_id)
201 );
202
203 while ($row = $this->db->fetchObject($res)) {
204 $count_read = $row->count_read;
205 }
206 $unread = $num_posts - $count_read;
207
208 $this->ilBench->stop("Forum", 'getCountRead');
209 return $unread > 0 ? $unread : 0;
210 } else {
211 $res = $this->db->queryf(
212 '
213 SELECT COUNT(pos_pk) num_posts FROM frm_posts
214 LEFT JOIN frm_posts_tree ON frm_posts_tree.pos_fk = pos_pk
215 WHERE pos_thr_fk = %s' . ($ignoreRoot ? ' AND parent_pos != 0 ' : ''),
216 array('integer'),
217 array($a_thread_id)
218 );
219
220 $row = $this->db->fetchObject($res);
221 $num_posts = $row->num_posts;
222
223 $res = $this->db->queryf(
224 '
225 SELECT COUNT(post_id) count_read FROM frm_user_read
226 WHERE obj_id = %s
227 AND usr_id = %s
228 AND thread_id = %s',
229 array('integer', 'integer', 'integer'),
230 array($a_frm_id, $a_frm_id, $a_thread_id)
231 );
232
233 $row = $this->db->fetchObject($res);
234 $count_read = $row->count_read;
235
236 $unread = $num_posts - $count_read;
237
238 $this->ilBench->stop("Forum", 'getCountRead');
239 return $unread > 0 ? $unread : 0;
240 }
241 $this->ilBench->stop("Forum", 'getCountRead');
242 return false;
243 }
244
245
246 public function markThreadRead($a_usr_id, $a_thread_id)
247 {
248 // Get all post ids
249 $res = $this->db->queryf(
250 '
251 SELECT * FROM frm_posts WHERE pos_thr_fk = %s',
252 array('integer'),
253 array($a_thread_id)
254 );
255
256 while ($row = $this->db->fetchObject($res)) {
257 $this->markPostRead($a_usr_id, $a_thread_id, $row->pos_pk);
258 }
259 return true;
260 }
261
262 public function markAllThreadsRead($a_usr_id)
263 {
264 $res = $this->db->queryf(
265 '
266 SELECT * FROM frm_data, frm_threads
267 WHERE top_frm_fk = %s
268 AND top_pk = thr_top_fk',
269 array('integer'),
270 array($this->getId())
271 );
272
273 while ($row = $this->db->fetchObject($res)) {
274 $this->markThreadRead($a_usr_id, $row->thr_pk);
275 }
276
277 return true;
278 }
279
280
281 public function markPostRead($a_usr_id, $a_thread_id, $a_post_id)
282 {
283 // CHECK IF ENTRY EXISTS
284 $res = $this->db->queryf(
285 '
286 SELECT * FROM frm_user_read
287 WHERE usr_id = %s
288 AND obj_id = %s
289 AND thread_id = %s
290 AND post_id = %s',
291 array('integer', 'integer', 'integer', 'integer'),
292 array($a_usr_id, $this->getId(), $a_thread_id, $a_post_id)
293 );
294
295 if ($this->db->numRows($res)) {
296 return true;
297 }
298
299 $this->db->manipulateF(
300 '
301 INSERT INTO frm_user_read
302 ( usr_id,
303 obj_id,
304 thread_id,
305 post_id
306 )
307 VALUES (%s,%s,%s,%s)',
308 array('integer', 'integer', 'integer', 'integer'),
309 array($a_usr_id, $this->getId(), $a_thread_id, $a_post_id)
310 );
311
312 return true;
313 }
314
315 public function markPostUnread($a_user_id, $a_post_id)
316 {
317 $this->db->manipulateF(
318 '
319 DELETE FROM frm_user_read
320 WHERE usr_id = %s
321 AND post_id = %s',
322 array('integer', 'integer'),
323 array($a_user_id, $a_post_id)
324 );
325 }
326
327 public function isRead($a_usr_id, $a_post_id)
328 {
329 $res = $this->db->queryf(
330 '
331 SELECT * FROM frm_user_read
332 WHERE usr_id = %s
333 AND post_id = %s',
334 array('integer', 'integer'),
335 array($a_usr_id, $a_post_id)
336 );
337
338 return $this->db->numRows($res) ? true : false;
339 }
340
341 public function updateLastAccess($a_usr_id, $a_thread_id)
342 {
343 $res = $this->db->queryf(
344 '
345 SELECT * FROM frm_thread_access
346 WHERE usr_id = %s
347 AND obj_id = %s
348 AND thread_id = %s',
349 array('integer', 'integer', 'integer'),
350 array($a_usr_id, $this->getId(), $a_thread_id)
351 );
352 $data = $this->db->fetchAssoc($res);
353
354 $this->db->replace(
355 'frm_thread_access',
356 array(
357 'usr_id' => array('integer', $a_usr_id),
358 'obj_id' => array('integer', $this->getId()),
359 'thread_id' => array('integer', $a_thread_id)
360 ),
361 array(
362 'access_last' => array('integer', time()),
363 'access_old' => array('integer', isset($data['access_old']) ? $data['access_old'] : 0),
364 'access_old_ts' => array('timestamp', $data['access_old_ts'])
365 )
366 );
367
368 return true;
369 }
370
375 public static function _updateOldAccess($a_usr_id)
376 {
377 global $DIC;
378 $ilDB = $DIC->database();
379
380 $ilDB->manipulateF(
381 '
382 UPDATE frm_thread_access
383 SET access_old = access_last
384 WHERE usr_id = %s',
385 array('integer'),
386 array($a_usr_id)
387 );
388
389 $set = $ilDB->query(
390 "SELECT * FROM frm_thread_access " .
391 " WHERE usr_id = " . $ilDB->quote($a_usr_id, "integer")
392 );
393 while ($rec = $ilDB->fetchAssoc($set)) {
394 $ilDB->manipulate(
395 "UPDATE frm_thread_access SET " .
396 " access_old_ts = " . $ilDB->quote(date('Y-m-d H:i:s', $rec["access_old"]), "timestamp") .
397 " WHERE usr_id = " . $ilDB->quote($rec["usr_id"], "integer") .
398 " AND obj_id = " . $ilDB->quote($rec["obj_id"], "integer") .
399 " AND thread_id = " . $ilDB->quote($rec["thread_id"], "integer")
400 );
401 }
402
403 $new_deadline = time() - 60 * 60 * 24 * 7 * ($DIC->settings()->get('frm_store_new') ?
404 $DIC->settings()->get('frm_store_new') :
405 8);
406
407 $ilDB->manipulateF(
408 '
409 DELETE FROM frm_thread_access WHERE access_last < %s',
410 array('integer'),
411 array($new_deadline)
412 );
413 }
414
415 public static function _deleteUser($a_usr_id)
416 {
417 global $DIC;
418 $ilDB = $DIC->database();
419
420 $data = array($a_usr_id);
421
422 $ilDB->manipulateF(
423 '
424 DELETE FROM frm_user_read WHERE usr_id = %s',
425 array('integer'),
426 $data
427 );
428
429 $ilDB->manipulateF(
430 '
431 DELETE FROM frm_thread_access WHERE usr_id = %s',
432 array('integer'),
433 $data
434 );
435
436 // delete notifications of deleted user
437 $ilDB->manipulateF(
438 '
439 DELETE FROM frm_notification WHERE user_id = %s',
440 array('integer'),
441 $data
442 );
443
444 return true;
445 }
446
447
448 public static function _deleteReadEntries($a_post_id)
449 {
450 global $DIC;
451 $ilDB = $DIC->database();
452
453 $ilDB->manipulateF(
454 '
455 DELETE FROM frm_user_read WHERE post_id = %s',
456 array('integer'),
457 array($a_post_id)
458 );
459
460 return true;
461 }
462
463 public static function _deleteAccessEntries($a_thread_id)
464 {
465 global $DIC;
466 $ilDB = $DIC->database();
467 $ilDB->manipulateF(
468 '
469 DELETE FROM frm_thread_access WHERE thread_id = %s',
470 array('integer'),
471 array($a_thread_id)
472 );
473
474 return true;
475 }
476
481 public function update($a_update_user_id = 0)
482 {
483 if (!$a_update_user_id) {
484 $a_update_user_id = $this->user->getId();
485 }
486
487 if (parent::update()) {
488 $this->db->manipulateF(
489 '
490 UPDATE frm_data
491 SET top_name = %s,
492 top_description = %s,
493 top_update = %s,
494 update_user = %s
495 WHERE top_frm_fk =%s',
496 array('text', 'text', 'timestamp', 'integer', 'integer'),
497 array(
498 $this->getTitle(),
499 $this->getDescription(),
500 date("Y-m-d H:i:s"),
501 (int) $a_update_user_id,
502 (int) $this->getId()
503 )
504 );
505
506 return true;
507 }
508
509 return false;
510 }
511
518 public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
519 {
521 $new_obj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
522 $this->cloneAutoGeneratedRoles($new_obj);
523
524 ilForumProperties::getInstance($this->getId())->copy($new_obj->getId());
525 $this->Forum->setMDB2WhereCondition('top_frm_fk = %s ', array('integer'), array($this->getId()));
526 $topData = $this->Forum->getOneTopic();
527
528 $this->db->update('frm_data', array(
529 'top_name' => array('text', $topData['top_name']),
530 'top_description' => array('text', $topData['top_description']),
531 'top_num_posts' => array('integer', $topData['top_num_posts']),
532 'top_num_threads' => array('integer', $topData['top_num_threads']),
533 'top_last_post' => array('text', $topData['top_last_post']),
534 'top_date' => array('timestamp', $topData['top_date']),
535 'visits' => array('integer', $topData['visits']),
536 'top_update' => array('timestamp', $topData['top_update']),
537 'update_user' => array('integer', $topData['update_user']),
538 'top_usr_id' => array('integer', $topData['top_usr_id'])
539 ), array(
540 'top_frm_fk' => array('integer', $new_obj->getId())
541 ));
542
543 // read options
544 $cwo = ilCopyWizardOptions::_getInstance($a_copy_id);
545 $options = $cwo->getOptions($this->getRefId());
546
547 $options['threads'] = $this->Forum->_getThreads($this->getId());
548
549 // Generate starting threads
550 $new_frm = $new_obj->Forum;
551 $new_frm->setMDB2WhereCondition('top_frm_fk = %s ', array('integer'), array($new_obj->getId()));
552
553 $new_frm->setForumId($new_obj->getId());
554 $new_frm->setForumRefId($new_obj->getRefId());
555
556 $new_topic = $new_frm->getOneTopic();
557 foreach ($options['threads'] as $thread_id => $thread_subject) {
558 $this->Forum->setMDB2WhereCondition('thr_pk = %s ', array('integer'), array($thread_id));
559
560 $old_thread = $this->Forum->getOneThread();
561
562 $old_post_id = $this->Forum->getFirstPostByThread($old_thread['thr_pk']);
563 $old_post = $this->Forum->getOnePost($old_post_id);
564
565 $newThread = new ilForumTopic(0, true, true);
566 $newThread->setSticky($old_thread['is_sticky']);
567 $newThread->setForumId($new_topic['top_pk']);
568 $newThread->setThrAuthorId($old_thread['thr_author_id']);
569 $newThread->setDisplayUserId($old_thread['thr_display_user_id']);
570 $newThread->setSubject($old_thread['thr_subject']);
571 $newThread->setUserAlias($old_thread['thr_usr_alias']);
572 $newThread->setCreateDate($old_thread['thr_date']);
573
574 $old_thread_obj = new ilForumTopic($old_thread['thr_pk']);
575 $top_pos_pk = $old_thread_obj->getFirstPostId() ?: $old_post_id;
576 $top_pos = new ilForumPost($top_pos_pk);
577
578 $newPostId = $new_frm->generateThread(
579 $newThread,
580 $top_pos->getMessage(),
581 (int) $top_pos->isNotificationEnabled(),
582 0,
583 1,
584 (bool) ($old_thread_obj->getNumPosts() - 1)
585 );
586
587 $old_forum_files = new ilFileDataForum($this->getId(), $top_pos_pk);
588 $old_forum_files->ilClone($new_obj->getId(), $newPostId);
589 }
590
591 $sourceRefId = $this->getRefId();
592 $targetRefId = $new_obj->getRefId();
593
594 if (
595 $sourceRefId > 0 && $targetRefId > 0 &&
596 $this->tree->getParentId($sourceRefId) === $this->tree->getParentId($targetRefId)
597 ) {
598 $grpRefId = $this->tree->checkForParentType($targetRefId, 'grp');
599 $crsRefId = $this->tree->checkForParentType($targetRefId, 'crs');
600
601 if ($grpRefId > 0 || $crsRefId > 0) {
602 $notifications = new \ilForumNotification($targetRefId);
603 $notifications->cloneFromSource((int) $sourceRefId);
604 }
605 }
606
607 return $new_obj;
608 }
609
616 public function cloneAutoGeneratedRoles($new_obj)
617 {
618 $moderator = ilObjForum::_lookupModeratorRole($this->getRefId());
619 $new_moderator = ilObjForum::_lookupModeratorRole($new_obj->getRefId());
620
621 if (!$moderator || !$new_moderator || !$this->getRefId() || !$new_obj->getRefId()) {
622 $this->logger->write(__METHOD__ . ' : Error cloning auto generated role: il_frm_moderator');
623 }
624 $this->rbac->admin()->copyRolePermissions($moderator, $this->getRefId(), $new_obj->getRefId(), $new_moderator, true);
625 $this->logger->write(__METHOD__ . ' : Finished copying of role il_frm_moderator.');
626
627 $obj_mods = new ilForumModerators($this->getRefId());
628
629 $old_mods = $obj_mods->getCurrentModerators();
630 foreach ($old_mods as $user_id) {
631 // The object owner is already member of the moderator role when this method is called
632 // Since the new static caches are introduced with ILIAS 5.0, a database error occurs if we try to assign the user here.
633 if ($this->getOwner() != $user_id) {
634 $this->rbac->admin()->assignUser($new_moderator, $user_id);
635 }
636 }
637 }
638
644 public function delete()
645 {
646 // always call parent delete function first!!
647 if (!parent::delete()) {
648 return false;
649 }
650
651 // delete attachments
652 $tmp_file_obj = new ilFileDataForum($this->getId());
653 $tmp_file_obj->delete();
654 unset($tmp_file_obj);
655
656 $this->Forum->setMDB2WhereCondition('top_frm_fk = %s ', array('integer'), array($this->getId()));
657
658 $topData = $this->Forum->getOneTopic();
659
660 $threads = $this->Forum->getAllThreads($topData['top_pk']);
661 foreach ($threads['items'] as $thread) {
662 $thread_ids_to_delete[$thread->getId()] = $thread->getId();
663 }
664
665 // delete tree
666 $this->db->manipulate('DELETE FROM frm_posts_tree WHERE ' . $this->db->in('thr_fk', $thread_ids_to_delete, false, 'integer'));
667
668 // delete posts
669 $this->db->manipulate('DELETE FROM frm_posts WHERE ' . $this->db->in('pos_thr_fk', $thread_ids_to_delete, false, 'integer'));
670
671 // delete threads
672 $this->db->manipulate('DELETE FROM frm_threads WHERE ' . $this->db->in('thr_pk', $thread_ids_to_delete, false, 'integer'));
673
674 $obj_id = array($this->getId());
675 // delete forum
676 $this->db->manipulateF(
677 'DELETE FROM frm_data WHERE top_frm_fk = %s',
678 array('integer'),
679 $obj_id
680 );
681
682 // delete settings
683 $this->db->manipulateF(
684 'DELETE FROM frm_settings WHERE obj_id = %s',
685 array('integer'),
686 $obj_id
687 );
688
689 // delete read infos
690 $this->db->manipulateF(
691 'DELETE FROM frm_user_read WHERE obj_id = %s',
692 array('integer'),
693 $obj_id
694 );
695
696 // delete thread access entries
697 $this->db->manipulateF(
698 'DELETE FROM frm_thread_access WHERE obj_id = %s',
699 array('integer'),
700 $obj_id
701 );
702
703 //delete thread notifications
704 $this->db->manipulate('DELETE FROM frm_notification WHERE ' . $this->db->in('thread_id', $thread_ids_to_delete, false, 'integer'));
705
706 //delete forum notifications
707 $this->db->manipulateF('DELETE FROM frm_notification WHERE frm_id = %s', array('integer'), $obj_id);
708
709 // delete posts_deleted entries
710 $this->db->manipulateF('DELETE FROM frm_posts_deleted WHERE obj_id = %s', array('integer'), $obj_id);
711
712 //delete drafts
713 $this->deleteDraftsByForumId((int) $topData['top_pk']);
714
715 return true;
716 }
717
721 private function deleteDraftsByForumId($forum_id)
722 {
723 $res = $this->db->queryF(
724 'SELECT draft_id FROM frm_posts_drafts WHERE forum_id = %s',
725 array('integer'),
726 array((int) $forum_id)
727 );
728
729 $draft_ids = array();
730 while ($row = $this->db->fetchAssoc($res)) {
731 $draft_ids[] = $row['draft_id'];
732 }
733
734 if (count($draft_ids) > 0) {
735 $historyObj = new ilForumDraftsHistory();
736 $historyObj->deleteHistoryByDraftIds($draft_ids);
737
738 $draftObj = new ilForumPostDraft();
739 $draftObj->deleteDraftsByDraftIds($draft_ids);
740 }
741 }
742
748 public function initDefaultRoles()
749 {
751 'il_frm_moderator_' . $this->getRefId(),
752 "Moderator of forum obj_no." . $this->getId(),
753 'il_frm_moderator',
754 $this->getRefId()
755 );
756 return array();
757 }
758
766 public static function _lookupModeratorRole($a_ref_id)
767 {
768 global $DIC;
769 $ilDB = $DIC->database();
770
771 $mod_title = 'il_frm_moderator_' . $a_ref_id;
772
773 $res = $ilDB->queryf(
774 '
775 SELECT * FROM object_data WHERE title = %s',
776 array('text'),
777 array($mod_title)
778 );
779
780 while ($row = $ilDB->fetchObject($res)) {
781 return $row->obj_id;
782 }
783 return 0;
784 }
785
786
787 public function createSettings()
788 {
789 // news settings (public notifications yes/no)
790 $default_visibility = ilNewsItem::_getDefaultVisibilityForRefId($_GET["ref_id"]);
791 if ($default_visibility == "public") {
792 ilBlockSetting::_write("news", "public_notifications", 1, 0, $this->getId());
793 }
794
795 return true;
796 }
797
798 public function saveData($a_roles = array())
799 {
800 $nextId = $this->db->nextId('frm_data');
801
802 $top_data = array(
803 'top_frm_fk' => $this->getId(),
804 'top_name' => $this->getTitle(),
805 'top_description' => $this->getDescription(),
806 'top_num_posts' => 0,
807 'top_num_threads' => 0,
808 'top_last_post' => null,
809 'top_mods' => !is_numeric($a_roles[0]) ? 0 : $a_roles[0],
810 'top_usr_id' => $this->user->getId(),
811 'top_date' => ilUtil::now()
812 );
813
814 $this->db->manipulateF(
815 '
816 INSERT INTO frm_data
817 (
818 top_pk,
819 top_frm_fk,
820 top_name,
821 top_description,
822 top_num_posts,
823 top_num_threads,
824 top_last_post,
825 top_mods,
826 top_date,
827 top_usr_id
828 )
829 VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)',
830 array('integer', 'integer', 'text', 'text', 'integer', 'integer', 'text', 'integer', 'timestamp', 'integer'),
831 array(
832 $nextId,
833 $top_data['top_frm_fk'],
834 $top_data['top_name'],
835 $top_data['top_description'],
836 $top_data['top_num_posts'],
837 $top_data['top_num_threads'],
838 $top_data['top_last_post'],
839 $top_data['top_mods'],
840 $top_data['top_date'],
841 $top_data['top_usr_id']
842 )
843 );
844 }
845
846 public function setThreadSorting($a_thr_pk, $a_sorting_value)
847 {
848 $this->db->update(
849 'frm_threads',
850 array('thread_sorting' => array('integer',$a_sorting_value)),
851 array('thr_pk' => array('integer', $a_thr_pk))
852 );
853 }
854
855
861 public static function lookupForumIdByObjId($obj_id)
862 {
863 if (array_key_exists($obj_id, self::$obj_id_to_forum_id_cache)) {
864 return (int) self::$obj_id_to_forum_id_cache[$obj_id];
865 }
866
867 self::preloadForumIdsByObjIds(array($obj_id));
868
869 return (int) self::$obj_id_to_forum_id_cache[$obj_id];
870 }
871
877 public static function lookupForumIdByRefId($ref_id)
878 {
879 if (array_key_exists($ref_id, self::$ref_id_to_forum_id_cache)) {
880 return (int) self::$ref_id_to_forum_id_cache[$ref_id];
881 }
882
884
885 return (int) self::$ref_id_to_forum_id_cache[$ref_id];
886 }
887
892 public static function preloadForumIdsByObjIds(array $obj_ids)
893 {
894 global $DIC;
895 $ilDB = $DIC->database();
896
897 if (count($obj_ids) == 1) {
898 $in = " objr.obj_id = " . $ilDB->quote(current($obj_ids), 'integer') . " ";
899 } else {
900 $in = $ilDB->in('objr.obj_id', $obj_ids, false, 'integer');
901 }
902 $query = "
903 SELECT frmd.top_pk, objr.ref_id, objr.obj_id
904 FROM object_reference objr
905 INNER JOIN frm_data frmd ON frmd.top_frm_fk = objr.obj_id
906 WHERE $in
907 ";
908 $res = $ilDB->query($query);
909
910 // Prepare cache array
911 foreach ($obj_ids as $obj_id) {
912 self::$obj_id_to_forum_id_cache[$obj_id] = null;
913 }
914
915 while ($row = $ilDB->fetchAssoc($res)) {
916 self::$obj_id_to_forum_id_cache[$row['obj_id']] = $row['top_pk'];
917 self::$ref_id_to_forum_id_cache[$row['ref_id']] = $row['top_pk'];
918 }
919 }
920
925 public static function preloadForumIdsByRefIds(array $ref_ids)
926 {
927 global $DIC;
928 $ilDB = $DIC->database();
929
930 if (count($ref_ids) == 1) {
931 $in = " objr.ref_id = " . $ilDB->quote(current($ref_ids), 'integer') . " ";
932 } else {
933 $in = $ilDB->in('objr.ref_id', $ref_ids, false, 'integer');
934 }
935 $query = "
936 SELECT frmd.top_pk, objr.ref_id, objr.obj_id
937 FROM object_reference objr
938 INNER JOIN frm_data frmd ON frmd.top_frm_fk = objr.obj_id
939 WHERE $in
940 ";
941 $res = $ilDB->query($query);
942
943 // Prepare cache array
944 foreach ($ref_ids as $ref_id) {
945 self::$ref_id_to_forum_id_cache[$ref_id] = null;
946 }
947
948 while ($row = $ilDB->fetchAssoc($res)) {
949 self::$obj_id_to_forum_id_cache[$row['obj_id']] = $row['top_pk'];
950 self::$ref_id_to_forum_id_cache[$row['ref_id']] = $row['top_pk'];
951 }
952 }
953
959 public static function lookupStatisticsByRefId($ref_id)
960 {
961 global $DIC;
962 $ilAccess = $DIC->access();
963 $ilUser = $DIC->user();
964 $ilDB = $DIC->database();
965 $ilSetting = $DIC->settings();
966
967 if (isset(self::$forum_statistics_cache[$ref_id])) {
968 return self::$forum_statistics_cache[$ref_id];
969 }
970
971 $statistics = array(
972 'num_posts' => 0,
973 'num_unread_posts' => 0,
974 'num_new_posts' => 0
975 );
976
978 if (!$forumId) {
979 self::$forum_statistics_cache[$ref_id] = $statistics;
980 return self::$forum_statistics_cache[$ref_id];
981 }
982
984 $is_post_activation_enabled = $objProperties->isPostActivationEnabled();
985
986 $act_clause = '';
987
988 if ($is_post_activation_enabled && !$ilAccess->checkAccess('moderate_frm', '', $ref_id)) {
989 $act_clause .= " AND (frm_posts.pos_status = " . $ilDB->quote(1, "integer") . " OR frm_posts.pos_author_id = " . $ilDB->quote($ilUser->getId(), "integer") . ") ";
990 }
991
992 $new_deadline = date('Y-m-d H:i:s', time() - 60 * 60 * 24 * 7 * ($ilSetting->get('frm_store_new') ? $ilSetting->get('frm_store_new') : 8));
993
994 if (!$ilUser->isAnonymous()) {
995 $query = "
996 (SELECT COUNT(frm_posts.pos_pk) cnt
997 FROM frm_posts
998 INNER JOIN frm_posts_tree tree1
999 ON tree1.pos_fk = frm_posts.pos_pk
1000 AND tree1.parent_pos != 0
1001 INNER JOIN frm_threads ON frm_posts.pos_thr_fk = frm_threads.thr_pk
1002 WHERE frm_threads.thr_top_fk = %s $act_clause)
1003
1004 UNION ALL
1005
1006 (SELECT COUNT(DISTINCT(frm_user_read.post_id)) cnt
1007 FROM frm_user_read
1008 INNER JOIN frm_posts ON frm_user_read.post_id = frm_posts.pos_pk
1009 INNER JOIN frm_posts_tree tree1
1010 ON tree1.pos_fk = frm_posts.pos_pk
1011 AND tree1.parent_pos != 0
1012 INNER JOIN frm_threads ON frm_threads.thr_pk = frm_posts.pos_thr_fk
1013 WHERE frm_user_read.usr_id = %s AND frm_posts.pos_top_fk = %s $act_clause)
1014 ";
1015
1016 $types = array('integer', 'integer', 'integer');
1017 $values = array($forumId, $ilUser->getId(), $forumId);
1018
1019 $forum_overview_setting = (int) $ilSetting::_lookupValue('frma', 'forum_overview');
1020 if ($forum_overview_setting == ilForumProperties::FORUM_OVERVIEW_WITH_NEW_POSTS) {
1021 $news_types = array('integer', 'integer', 'integer', 'timestamp', 'integer');
1022 $news_values = array($ilUser->getId(), $ilUser->getId(), $forumId, $new_deadline, $ilUser->getId());
1023
1024 $query .= "
1025 UNION ALL
1026
1027 (SELECT COUNT(frm_posts.pos_pk) cnt
1028 FROM frm_posts
1029 INNER JOIN frm_posts_tree tree1
1030 ON tree1.pos_fk = frm_posts.pos_pk
1031 AND tree1.parent_pos != 0
1032 LEFT JOIN frm_user_read ON (post_id = frm_posts.pos_pk AND frm_user_read.usr_id = %s)
1033 LEFT JOIN frm_thread_access ON (frm_thread_access.thread_id = frm_posts.pos_thr_fk AND frm_thread_access.usr_id = %s)
1034 WHERE frm_posts.pos_top_fk = %s
1035 AND ( (frm_posts.pos_update > frm_thread_access.access_old_ts)
1036 OR (frm_thread_access.access_old IS NULL AND frm_posts.pos_update > %s)
1037 )
1038 AND frm_posts.pos_author_id != %s
1039 AND frm_user_read.usr_id IS NULL $act_clause)";
1040
1041 $types = array_merge($types, $news_types);
1042 $values = array_merge($values, $news_values);
1043 }
1044
1045 $mapping = array_keys($statistics);
1046 $res = $ilDB->queryF(
1047 $query,
1048 $types,
1049 $values
1050 );
1051 for ($i = 0; $i <= 2; $i++) {
1052 $row = $ilDB->fetchAssoc($res);
1053
1054 $statistics[$mapping[$i]] = (int) ((is_array($row) ? $row['cnt'] : 0));
1055
1056 if ($i == 1) {
1057 // unread = all - read
1058 $statistics[$mapping[$i]] = $statistics[$mapping[$i - 1]] - $statistics[$mapping[$i]];
1059 }
1060 }
1061 } else {
1062 $query = "
1063 SELECT COUNT(frm_posts.pos_pk) cnt
1064 FROM frm_posts
1065 INNER JOIN frm_posts_tree tree1
1066 ON tree1.pos_fk = frm_posts.pos_pk
1067 AND tree1.parent_pos != 0
1068 INNER JOIN frm_threads ON frm_posts.pos_thr_fk = frm_threads.thr_pk
1069 WHERE frm_threads.thr_top_fk = %s $act_clause
1070 ";
1071 $types = array('integer');
1072 $values = array($forumId);
1073 $res = $ilDB->queryF(
1074 $query,
1075 $types,
1076 $values
1077 );
1078 $row = $ilDB->fetchAssoc($res);
1079
1080 $statistics = array(
1081 'num_posts' => $row['cnt'],
1082 'num_unread_posts' => $row['cnt'],
1083 'num_new_posts' => $row['cnt']
1084 );
1085 }
1086
1087 self::$forum_statistics_cache[$ref_id] = $statistics;
1088
1089 return self::$forum_statistics_cache[$ref_id];
1090 }
1091
1097 public static function lookupLastPostByRefId($ref_id)
1098 {
1099 global $DIC;
1100 $ilAccess = $DIC->access();
1101 $ilUser = $DIC->user();
1102 $ilDB = $DIC->database();
1103
1104 if (isset(self::$forum_last_post_cache[$ref_id])) {
1105 return self::$forum_last_post_cache[$ref_id];
1106 }
1107
1109 if (!$forumId) {
1110 self::$forum_last_post_cache[$ref_id] = array();
1111 return self::$forum_last_post_cache[$ref_id];
1112 }
1113
1114 $act_clause = '';
1115 if (!$ilAccess->checkAccess('moderate_frm', '', $ref_id)) {
1116 $act_clause .= " AND (frm_posts.pos_status = " . $ilDB->quote(1, "integer") . " OR frm_posts.pos_author_id = " . $ilDB->quote($ilUser->getId(), "integer") . ") ";
1117 }
1118
1119 $ilDB->setLimit(1, 0);
1120 $query = "
1121 SELECT *
1122 FROM frm_posts
1123 INNER JOIN frm_posts_tree tree1
1124 ON tree1.pos_fk = frm_posts.pos_pk
1125 AND tree1.parent_pos != 0
1126 WHERE pos_top_fk = %s $act_clause
1127 ORDER BY pos_date DESC
1128 ";
1129 $res = $ilDB->queryF(
1130 $query,
1131 array('integer'),
1132 array($forumId)
1133 );
1134
1135 $data = $ilDB->fetchAssoc($res);
1136
1137 self::$forum_last_post_cache[$ref_id] = is_array($data) ? $data : array();
1138
1139 return self::$forum_last_post_cache[$ref_id];
1140 }
1141
1148 public static function getUserIdsOfLastPostsByRefIdAndThreadIds($ref_id, array $thread_ids)
1149 {
1150 global $DIC;
1151 $ilAccess = $DIC->access();
1152 $ilUser = $DIC->user();
1153 $ilDB = $DIC->database();
1154
1155 $act_clause = '';
1156 $act_inner_clause = '';
1157 if (!$ilAccess->checkAccess('moderate_frm', '', $ref_id)) {
1158 $act_clause .= " AND (t1.pos_status = " . $ilDB->quote(1, "integer") . " OR t1.pos_author_id = " . $ilDB->quote($ilUser->getId(), "integer") . ") ";
1159 $act_inner_clause .= " AND (t3.pos_status = " . $ilDB->quote(1, "integer") . " OR t3.pos_author_id = " . $ilDB->quote($ilUser->getId(), "integer") . ") ";
1160 }
1161
1162 $in = $ilDB->in("t1.pos_thr_fk", $thread_ids, false, 'integer');
1163 $inner_in = $ilDB->in("t3.pos_thr_fk", $thread_ids, false, 'integer');
1164
1165 $query = "
1166 SELECT t1.pos_display_user_id, t1.update_user
1167 FROM frm_posts t1
1168 INNER JOIN frm_posts_tree tree1 ON tree1.pos_fk = t1.pos_pk AND tree1.parent_pos != 0
1169 INNER JOIN (
1170 SELECT t3.pos_thr_fk, MAX(t3.pos_date) pos_date
1171 FROM frm_posts t3
1172 INNER JOIN frm_posts_tree tree2 ON tree2.pos_fk = t3.pos_pk AND tree2.parent_pos != 0
1173 WHERE $inner_in $act_inner_clause
1174 GROUP BY t3.pos_thr_fk
1175 ) t2 ON t2.pos_thr_fk = t1.pos_thr_fk AND t2.pos_date = t1.pos_date
1176 WHERE $in $act_clause
1177 GROUP BY t1.pos_thr_fk, t1.pos_display_user_id, t1.update_user
1178 ";
1180 $usr_ids = array();
1181
1182 $res = $ilDB->query($query);
1183 while ($row = $ilDB->fetchAssoc($res)) {
1184 if ((int) $row['pos_display_user_id']) {
1185 $usr_ids[] = (int) $row['pos_display_user_id'];
1186 }
1187 if ((int) $row['update_user']) {
1188 $usr_ids[] = (int) $row['update_user'];
1189 }
1190 }
1191
1192 return array_unique($usr_ids);
1193 }
1194
1195 public static function mergeForumUserRead($merge_source_thread_id, $merge_target_thread_id)
1196 {
1197 global $DIC;
1198 $ilDB = $DIC->database();
1199
1200 $ilDB->update(
1201 'frm_user_read',
1202 array('thread_id' => array('integer', $merge_target_thread_id)),
1203 array('thread_id' => array('integer',$merge_source_thread_id))
1204 );
1205 }
1206
1207 public function getNumStickyThreads() : int
1208 {
1209 $res = $this->db->query(
1210 'SELECT COUNT(is_sticky) num_sticky FROM frm_threads
1211 INNER JOIN frm_data ON top_pk = thr_top_fk
1212 WHERE frm_data.top_frm_fk = ' . $this->db->quote($this->getId(), 'integer') . '
1213 AND is_sticky = ' . $this->db->quote(1, 'integer')
1214 );
1215 if ($row = $this->db->fetchAssoc($res)) {
1216 return (int) $row['num_sticky'];
1217 }
1218 return 0;
1219 }
1220}
user()
Definition: user.php:4
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
return true
Flag indicating whether or not HTTP headers will be sent when outputting captcha image/audio.
static _write($a_type, $a_setting, $a_value, $a_user=0, $a_block_id=0)
Write setting to database.
static _getInstance($a_copy_id)
Get instance of copy wizard options.
This class handles all operations on files for the forum object.
Class ilForumDraftHistory.
Class ilForumModerators.
Class ilForumPostDraft.
static getInstance($a_obj_id=0)
Class Forum core functions for forum.
static _getDefaultVisibilityForRefId($a_ref_id)
Get default visibility for reference id.
static _lookupDiskUsage($a_obj_id)
Returns the number of bytes used on the harddisk by the specified forum.
Class ilObjForum.
static $obj_id_to_forum_id_cache
markPostRead($a_usr_id, $a_thread_id, $a_post_id)
__construct($a_id=0, $a_call_by_reference=true)
Constructor @access public.
static _lookupThreadSubject($a_thread_id)
getCountUnread($a_usr_id, $a_thread_id=0, $ignoreRoot=false)
markAllThreadsRead($a_usr_id)
update($a_update_user_id=0)
update forum data @access public
deleteDraftsByForumId($forum_id)
static $forum_last_post_cache
initDefaultRoles()
init default roles settings @access public
saveData($a_roles=array())
setPermissions($a_ref_id)
updateModeratorRole($role_id)
static _deleteReadEntries($a_post_id)
static $forum_statistics_cache
static preloadForumIdsByRefIds(array $ref_ids)
static lookupStatisticsByRefId($ref_id)
updateLastAccess($a_usr_id, $a_thread_id)
setThreadSorting($a_thr_pk, $a_sorting_value)
getDiskUsage()
Gets the disk usage of the object in bytes.
static lookupForumIdByRefId($ref_id)
isRead($a_usr_id, $a_post_id)
static _deleteUser($a_usr_id)
static _deleteAccessEntries($a_thread_id)
markPostUnread($a_user_id, $a_post_id)
static lookupLastPostByRefId($ref_id)
markThreadRead($a_usr_id, $a_thread_id)
cloneAutoGeneratedRoles($new_obj)
Clone forum moderator role @access public.
static getUserIdsOfLastPostsByRefIdAndThreadIds($ref_id, array $thread_ids)
static $ref_id_to_forum_id_cache
static preloadForumIdsByObjIds(array $obj_ids)
static _lookupModeratorRole($a_ref_id)
Lookup moderator role @access public.
static _updateOldAccess($a_usr_id)
static mergeForumUserRead($merge_source_thread_id, $merge_target_thread_id)
static lookupForumIdByObjId($obj_id)
static createDefaultRole($a_title, $a_description, $a_tpl_name, $a_ref_id)
Class ilObject Basic functions for all objects.
getOwner()
get object owner
static _lookupObjectId($a_ref_id)
lookup object id
getRefId()
get reference id @access public
getDescription()
get object description
getId()
get object id @access public
getTitle()
get object title @access public
static now()
Return current timestamp in Y-m-d H:i:s format.
global $DIC
Definition: goto.php:24
$ilUser
Definition: imgupload.php:18
$i
Definition: metadata.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $ilSetting
Definition: privfeed.php:17
$query
foreach($_POST as $key=> $value) $res
settings()
Definition: settings.php:2
global $ilDB
$data
Definition: storeScorm.php:23