ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
13 class 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 
883  self::preloadForumIdsByRefIds(array($ref_id));
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 
977  $forumId = self::lookupForumIdByRefId($ref_id);
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 
1108  $forumId = self::lookupForumIdByRefId($ref_id);
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 }
static $forum_last_post_cache
markAllThreadsRead($a_usr_id)
Class ilForumPostDraft.
static mergeForumUserRead($merge_source_thread_id, $merge_target_thread_id)
Class Forum core functions for forum.
settings()
Definition: settings.php:2
static _write($a_type, $a_setting, $a_value, $a_user=0, $a_block_id=0)
Write setting to database.
update($a_update_user_id=0)
update forum data public
$data
Definition: storeScorm.php:23
setThreadSorting($a_thr_pk, $a_sorting_value)
static lookupForumIdByObjId($obj_id)
$_GET["client_id"]
static lookupForumIdByRefId($ref_id)
static $obj_id_to_forum_id_cache
initDefaultRoles()
init default roles settings public
deleteDraftsByForumId($forum_id)
markPostRead($a_usr_id, $a_thread_id, $a_post_id)
markThreadRead($a_usr_id, $a_thread_id)
static preloadForumIdsByObjIds(array $obj_ids)
setPermissions($a_ref_id)
getOwner()
get object owner
static now()
Return current timestamp in Y-m-d H:i:s format.
user()
Definition: user.php:4
static createDefaultRole($a_title, $a_description, $a_tpl_name, $a_ref_id)
Class ilForumDraftHistory.
markPostUnread($a_user_id, $a_post_id)
saveData($a_roles=array())
static _lookupObjectId($a_ref_id)
lookup object id
updateLastAccess($a_usr_id, $a_thread_id)
static _deleteReadEntries($a_post_id)
static getInstance($a_obj_id=0)
static _getInstance($a_copy_id)
Get instance of copy wizard options.
updateModeratorRole($role_id)
static _lookupThreadSubject($a_thread_id)
foreach($_POST as $key=> $value) $res
getId()
get object id public
static _lookupDiskUsage($a_obj_id)
Returns the number of bytes used on the harddisk by the specified forum.
static _lookupModeratorRole($a_ref_id)
Lookup moderator role public.
global $DIC
Definition: goto.php:24
getTitle()
get object title public
getDescription()
get object description
$query
static _updateOldAccess($a_usr_id)
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
static _deleteAccessEntries($a_thread_id)
static $forum_statistics_cache
static _deleteUser($a_usr_id)
isRead($a_usr_id, $a_post_id)
global $ilSetting
Definition: privfeed.php:17
__construct(Container $dic, ilPlugin $plugin)
This class handles all operations on files for the forum object.
global $ilDB
static _getDefaultVisibilityForRefId($a_ref_id)
Get default visibility for reference id.
getRefId()
get reference id public
static lookupStatisticsByRefId($ref_id)
__construct($a_id=0, $a_call_by_reference=true)
Constructor public.
static $ref_id_to_forum_id_cache
$ilUser
Definition: imgupload.php:18
getCountUnread($a_usr_id, $a_thread_id=0, $ignoreRoot=false)
Class ilObjForum.
cloneAutoGeneratedRoles($new_obj)
Clone forum moderator role public.
static getUserIdsOfLastPostsByRefIdAndThreadIds($ref_id, array $thread_ids)
Class ilForumModerators.
static preloadForumIdsByRefIds(array $ref_ids)
getDiskUsage()
Gets the disk usage of the object in bytes.
static lookupLastPostByRefId($ref_id)
$i
Definition: metadata.php:24