1<?php 2/* Copyright (c) 1998-2012 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4/** 5* @author Michael Jansen <mjansen@databay.de> 6* @version $Id:$ 7* 8* @ingroup ModulesForum 9*/ 10class ilForumTopic 11{ 12 private $id = 0; 13 14 private $forum_id = 0; 15 16 private $frm_obj_id = 0; 17 18 private $display_user_id = 0; 19 20 private $user_alias = ''; 21 22 private $subject = ''; 23 24 private $createdate = null; 25 26 private $changedate = null; 27 28 private $num_posts = 0; 29 30 private $last_post_string = ''; 31 32 private $visits = 0; 33 34 private $import_name = ''; 35 36 private $is_sticky = 0; 37 38 private $is_closed = 0; 39 40 private $orderField = ''; 41 42 /** @var null|ilForumPost */ 43 private $last_post = null; 44 45 private $db = null; 46 47 private $is_moderator = false; 48 49 private $thr_author_id = 0; 50 51 /** 52 * @var double 53 */ 54 private $average_rating = 0; 55 56 private $orderDirection = 'DESC'; 57 58 protected static $possibleOrderDirections = array('ASC', 'DESC'); 59 60 /** 61 * Constructor 62 * 63 * Returns an object of a forum topic. The constructor calls the private method read() 64 * to load the topic data from database into the object. 65 * 66 * @param integer $a_id primary key of a forum topic (optional) 67 * @param bool $a_is_moderator moderator-status of the current user (optional) 68 * @param bool $preventImplicitRead Prevents the implicit database query if an id was passed 69 * 70 * @access public 71 */ 72 public function __construct($a_id = 0, $a_is_moderator = false, $preventImplicitRead = false) 73 { 74 global $DIC; 75 76 $this->is_moderator = $a_is_moderator; 77 $this->db = $DIC->database(); 78 $this->user = $DIC->user(); 79 $this->id = $a_id; 80 81 if (!$preventImplicitRead) { 82 $this->read(); 83 } 84 } 85 86 /** 87 * @param $data 88 */ 89 public function assignData($data) 90 { 91 $this->setId((int) $data['thr_pk']); 92 $this->setForumId((int) $data['thr_top_fk']); 93 $this->setSubject($data['thr_subject']); 94 $this->setDisplayUserId((int) $data['thr_display_user_id']); 95 $this->setUserAlias($data['thr_usr_alias']); 96 $this->setLastPostString($data['last_post_string']); 97 $this->setCreateDate($data['thr_date']); 98 $this->setChangeDate($data['thr_update']); 99 $this->setVisits((int) $data['visits']); 100 $this->setImportName($data['import_name']); 101 $this->setSticky((int) $data['is_sticky']); 102 $this->setClosed((int) $data['is_closed']); 103 $this->setAverageRating($data['avg_rating']); 104 $this->setThrAuthorId($data['thr_author_id']); 105 106 // Aggregated values 107 $this->setNumPosts((int) $data['num_posts']); 108 $this->setNumUnreadPosts((int) $data['num_unread_posts']); 109 $this->setNumNewPosts((int) $data['num_new_posts']); 110 $this->setUserNotificationEnabled((bool) $data['usr_notification_is_enabled']); 111 } 112 113 /** 114 * Inserts the object data into database 115 * 116 * @return bool true in case of success, false in case of failure 117 * @access public 118 */ 119 public function insert() 120 { 121 if ($this->forum_id) { 122 $nextId = $this->db->nextId('frm_threads'); 123 124 $this->db->insert( 125 'frm_threads', 126 array( 127 'thr_pk' => array('integer', $nextId), 128 'thr_top_fk' => array('integer', $this->forum_id), 129 'thr_subject' => array('text', $this->subject), 130 'thr_display_user_id' => array('integer', $this->display_user_id), 131 'thr_usr_alias' => array('text', $this->user_alias), 132 'thr_num_posts' => array('integer', $this->num_posts), 133 'thr_last_post' => array('text', $this->last_post_string), 134 'thr_date' => array('timestamp', $this->createdate), 135 'thr_update' => array('timestamp', null), 136 'import_name' => array('text', $this->import_name), 137 'is_sticky' => array('integer', $this->is_sticky), 138 'is_closed' => array('integer', $this->is_closed), 139 'avg_rating' => array('float', $this->average_rating), 140 'thr_author_id' => array('integer', $this->thr_author_id) 141 ) 142 ); 143 144 $this->id = $nextId; 145 146 return true; 147 } 148 149 return false; 150 } 151 152 /** 153 * Updates an existing topic 154 * 155 * @return bool true in case of success, false in case of failure 156 * @access public 157 */ 158 public function update() 159 { 160 if ($this->id) { 161 $this->db->manipulateF( 162 ' 163 UPDATE frm_threads 164 SET thr_top_fk = %s, 165 thr_subject = %s, 166 thr_update = %s, 167 thr_num_posts = %s, 168 thr_last_post = %s, 169 avg_rating = %s 170 WHERE thr_pk = %s', 171 array('integer', 'text','timestamp', 'integer', 'text', 'float', 'integer'), 172 array( $this->forum_id, 173 $this->subject, 174 /* $this->changedate, */ 175 date('Y-m-d H:i:s'), 176 $this->num_posts, 177 $this->last_post_string, 178 $this->average_rating, 179 $this->id 180 ) 181 ); 182 183 return true; 184 } 185 186 return false; 187 } 188 189 /** 190 * Reads the data of the current object id from database and loads it into the object. 191 * 192 * @return bool true in case of success, false in case of failure 193 * 194 * @access private 195 */ 196 private function read() 197 { 198 if ($this->id) { 199 $res = $this->db->queryf( 200 ' 201 SELECT frm_threads.*, top_frm_fk frm_obj_id 202 FROM frm_threads 203 INNER JOIN frm_data ON top_pk = thr_top_fk 204 WHERE thr_pk = %s', 205 array('integer'), 206 array($this->id) 207 ); 208 209 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT); 210 211 if (is_object($row)) { 212 $this->thr_pk = $row->pos_pk; // thr_pk = pos_pk ??!??! 213 $this->forum_id = $row->thr_top_fk; 214 $this->display_user_id = $row->thr_display_user_id; 215 $this->user_alias = $row->thr_usr_alias; 216 $this->subject = html_entity_decode($row->thr_subject); 217 $this->createdate = $row->thr_date; 218 $this->changedate = $row->thr_update; 219 $this->import_name = $row->import_name; 220 $this->num_posts = $row->thr_num_posts; 221 $this->last_post_string = $row->thr_last_post; 222 $this->visits = $row->visits; 223 $this->is_sticky = $row->is_sticky; 224 $this->is_closed = $row->is_closed; 225 $this->frm_obj_id = $row->frm_obj_id; 226 $this->average_rating = $row->avg_rating; 227 $this->thr_author_id = $row->thr_author_id; 228 229 return true; 230 } 231 $this->id = 0; 232 return false; 233 } 234 235 return false; 236 } 237 238 /** 239 * Calls the private method read() to load the topic data from database into the object. 240 * 241 * @return bool true in case of success, false in case of failure 242 * @access public 243 */ 244 public function reload() 245 { 246 return $this->read(); 247 } 248 249 /** 250 * Fetches the primary key of the first post node of the current topic from database and returns it. 251 * 252 * @return integer primary key of the first post node 253 * @access public 254 */ 255 public function getFirstPostId() 256 { 257 $res = $this->db->queryf( 258 ' 259 SELECT * FROM frm_posts_tree 260 WHERE thr_fk = %s 261 AND parent_pos = %s', 262 array('integer', 'integer'), 263 array($this->id, '1') 264 ); 265 266 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT); 267 268 return $row->pos_fk ? $row->pos_fk : 0; 269 } 270 271 /** 272 * Updates the visit counter of the current topic. 273 * 274 * @access public 275 */ 276 public function updateVisits() 277 { 278 $checkTime = time() - (60 * 60); 279 280 if ($_SESSION['frm_visit_frm_threads_' . $this->id] < $checkTime) { 281 $_SESSION['frm_visit_frm_threads_' . $this->id] = time(); 282 283 $this->db->manipulateF( 284 ' 285 UPDATE frm_threads 286 SET visits = visits + 1 287 WHERE thr_pk = %s', 288 array('integer'), 289 array($this->id) 290 ); 291 } 292 293 return true; 294 } 295 296 /** 297 * Fetches and returns the number of posts for the given user id. 298 * 299 * @param integer $a_user_id user id 300 * @return integer number of posts 301 * @access public 302 */ 303 public function countPosts($ignoreRoot = false) 304 { 305 $res = $this->db->queryf( 306 ' 307 SELECT COUNT(*) cnt 308 FROM frm_posts 309 INNER JOIN frm_posts_tree ON frm_posts_tree.pos_fk = pos_pk 310 WHERE pos_thr_fk = %s' . ($ignoreRoot ? ' AND parent_pos != 0 ' : ''), 311 array('integer'), 312 array($this->id) 313 ); 314 315 $rec = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC); 316 317 return $rec['cnt']; 318 } 319 320 /** 321 * Fetches and returns the number of active posts for the given user id. 322 * 323 * @param bool $ignoreRoot 324 * @return integer number of active posts 325 * @access public 326 */ 327 public function countActivePosts($ignoreRoot = false) 328 { 329 $res = $this->db->queryf( 330 ' 331 SELECT COUNT(*) cnt 332 FROM frm_posts 333 INNER JOIN frm_posts_tree ON frm_posts_tree.pos_fk = pos_pk 334 WHERE (pos_status = %s 335 OR (pos_status = %s AND pos_display_user_id = %s)) 336 AND pos_thr_fk = %s' . ($ignoreRoot ? ' AND parent_pos != 0 ' : ''), 337 array('integer', 'integer', 'integer', 'integer'), 338 array('1', '0', $this->user->getId(), $this->id) 339 ); 340 341 $rec = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC); 342 343 return $rec['cnt']; 344 } 345 346 /** 347 * Fetches and returns an object of the first post in the current topic 348 * @param bool $isModerator 349 * @param bool $preventImplicitRead 350 * @return ilForumPost object of a post 351 */ 352 public function getFirstPostNode($isModerator = false, $preventImplicitRead = false) 353 { 354 $res = $this->db->queryF( 355 ' 356 SELECT * 357 FROM frm_posts 358 INNER JOIN frm_posts_tree ON pos_fk = pos_pk 359 WHERE parent_pos = %s 360 AND thr_fk = %s', 361 array('integer', 'integer'), 362 array(0, $this->id) 363 ); 364 365 $row = $this->db->fetchAssoc($res); 366 367 $post = new ilForumPost($row['pos_pk'], $isModerator, $preventImplicitRead); 368 $post->assignData($row); 369 370 return $post; 371 } 372 373 /** 374 * Fetches and returns an object of the last post in the current topic. 375 * 376 * @return ilForumPost object of the last post 377 * @access public 378 */ 379 public function getLastPost() 380 { 381 if ($this->id) { 382 $this->db->setLimit(1); 383 $res = $this->db->queryf( 384 ' 385 SELECT pos_pk 386 FROM frm_posts 387 WHERE pos_thr_fk = %s 388 ORDER BY pos_date DESC', 389 array('integer'), 390 array($this->id) 391 ); 392 393 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT); 394 395 return new ilForumPost($row->pos_pk); 396 } 397 398 return false; 399 } 400 401 /** 402 * Fetches and returns an object of the last active post in the current topic. 403 * 404 * @return ilForumPost object of the last active post 405 * @access public 406 */ 407 public function getLastActivePost() 408 { 409 if ($this->id) { 410 $this->db->setLimit(1); 411 $res = $this->db->queryf( 412 ' 413 SELECT pos_pk 414 FROM frm_posts 415 WHERE pos_thr_fk = %s 416 AND (pos_status = %s OR 417 (pos_status = %s AND pos_display_user_id = %s)) 418 ORDER BY pos_date DESC', 419 array('integer', 'integer', 'integer', 'integer'), 420 array($this->id, '1', '0', $this->user->getId()) 421 ); 422 423 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT); 424 425 return new ilForumPost($row->pos_pk); 426 } 427 428 return false; 429 } 430 431 public function getAllPosts() 432 { 433 $posts = array(); 434 435 if ($this->id) { 436 $res = $this->db->queryf( 437 ' 438 SELECT pos_pk 439 FROM frm_posts 440 WHERE pos_thr_fk = %s', 441 array('integer'), 442 array($this->id) 443 ); 444 445 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) { 446 $posts[$row->pos_pk] = $row; 447 } 448 } 449 450 return is_array($posts) ? $posts : array(); 451 } 452 453 /** 454 * Fetches and returns an array of posts from the post tree, starting with the node object passed by 455 * the first paramter. 456 * 457 * @param ilForumPost $a_post_node node-object of a post 458 * @return array array of post objects 459 * @access public 460 */ 461 public function getPostTree(ilForumPost $a_post_node) 462 { 463 $posts = array(); 464 465 $data = array(); 466 $data_types = array(); 467 468 $query = ' 469 SELECT is_author_moderator, pos_author_id, pos_pk, fpt_date, rgt, pos_top_fk, pos_thr_fk, 470 pos_display_user_id, pos_usr_alias, pos_subject, 471 pos_status, pos_message, pos_date, pos_update, 472 update_user, pos_cens, pos_cens_com, notify, 473 import_name, fpt_pk, parent_pos, lft, depth, 474 (CASE 475 WHEN fur.post_id IS NULL ' . 476 ($this->user->getId() == ANONYMOUS_USER_ID ? ' AND 1 = 2 ' : '') . ' 477 THEN 0 478 ELSE 1 479 END) post_read, 480 firstname, lastname, title, login 481 482 FROM frm_posts_tree 483 484 INNER JOIN frm_posts 485 ON pos_fk = pos_pk 486 487 LEFT JOIN usr_data 488 ON pos_display_user_id = usr_id 489 490 LEFT JOIN frm_user_read fur 491 ON fur.thread_id = pos_thr_fk 492 AND fur.post_id = pos_pk 493 AND fur.usr_id = %s 494 495 WHERE lft > %s AND lft < %s 496 AND thr_fk = %s'; 497 498 array_push($data_types, 'integer', 'integer', 'integer', 'integer'); 499 array_push($data, $this->user->getId(), $a_post_node->getLft(), $a_post_node->getRgt(), $a_post_node->getThreadId()); 500 501 if ($this->orderField != "") { 502 $query .= " ORDER BY " . $this->orderField . " " . $this->getOrderDirection(); 503 } 504 505 $res = $this->db->queryF($query, $data_types, $data); 506 507 $usr_ids = []; 508 while ($row = $this->db->fetchAssoc($res)) { 509 $post = new ilForumPost($row['pos_pk'], false, true); 510 $post->assignData($row); 511 512 if (!$this->is_moderator) { 513 if (!$post->isActivated() && $post->getPosAuthorId() != $this->user->getId()) { 514 continue; 515 } 516 } 517 518 if ((int) $row['pos_display_user_id']) { 519 $usr_ids[(int) $row['pos_display_user_id']] = (int) $row['pos_display_user_id']; 520 } 521 if ((int) $row['update_user']) { 522 $usr_ids[(int) $row['update_user']] = (int) $row['update_user']; 523 } 524 525 $posts[] = $post; 526 } 527 528 ilForumAuthorInformationCache::preloadUserObjects(array_values($usr_ids)); 529 530 return $posts; 531 } 532 533 /** 534 * Moves all posts within the current thread to a new forum 535 * 536 * @param integer $old_obj_id object id of the current forum 537 * @param integer $old_pk primary key of old forum 538 * @param integer $new_obj_id object id of the new forum 539 * @param integer $new_pk primary key of new forum 540 * @return integer number of afffected rows by updating posts 541 * @access public 542 */ 543 public function movePosts($old_obj_id, $old_pk, $new_obj_id, $new_pk) 544 { 545 if ($this->id) { 546 $nodes = $this->getAllPosts(); 547 if (is_array($nodes)) { 548 $postsMoved = array(); 549 // Move attachments 550 try { 551 foreach ($nodes as $node) { 552 $file_obj = new ilFileDataForum((int) $old_obj_id, (int) $node->pos_pk); 553 $moved = $file_obj->moveFilesOfPost((int) $new_obj_id); 554 555 if (true === $moved) { 556 $postsMoved[] = array( 557 'from' => $old_obj_id, 558 'to' => $new_obj_id, 559 'position_id' => (int) $node->pos_pk 560 ); 561 } 562 563 unset($file_obj); 564 } 565 } catch (\ilFileUtilsException $exception) { 566 foreach ($postsMoved as $postedInformation) { 567 $file_obj = new ilFileDataForum($postedInformation['to'], $postedInformation['position_id']); 568 $file_obj->moveFilesOfPost($postedInformation['from']); 569 } 570 571 throw $exception; 572 } 573 } 574 575 $current_id = $this->id; 576 577 $ilAtomQuery = $this->db->buildAtomQuery(); 578 $ilAtomQuery->addTableLock('frm_user_read'); 579 $ilAtomQuery->addTableLock('frm_thread_access'); 580 581 $ilAtomQuery->addQueryCallable(function (ilDBInterface $ilDB) use ($new_obj_id, $current_id) { 582 $ilDB->manipulateF( 583 ' 584 DELETE FROM frm_user_read 585 WHERE obj_id = %s AND thread_id =%s', 586 array('integer', 'integer'), 587 array($new_obj_id, $current_id) 588 ); 589 590 $ilDB->manipulateF( 591 ' 592 UPDATE frm_user_read 593 SET obj_id = %s 594 WHERE thread_id = %s', 595 array('integer', 'integer'), 596 array($new_obj_id, $current_id) 597 ); 598 599 $ilDB->manipulateF( 600 ' 601 DELETE FROM frm_thread_access 602 WHERE obj_id = %s AND thread_id =%s', 603 array('integer', 'integer'), 604 array($new_obj_id, $current_id) 605 ); 606 607 $ilDB->manipulateF( 608 ' 609 UPDATE frm_thread_access 610 SET obj_id = %s 611 WHERE thread_id =%s', 612 array('integer', 'integer'), 613 array($new_obj_id, $current_id) 614 ); 615 }); 616 617 $ilAtomQuery->run(); 618 619 $this->db->manipulateF( 620 ' 621 UPDATE frm_posts 622 SET pos_top_fk = %s 623 WHERE pos_thr_fk = %s', 624 array('integer', 'integer'), 625 array($new_pk, $this->id) 626 ); 627 628 // update all related news 629 $posts = $this->db->queryf( 630 ' 631 SELECT * FROM frm_posts WHERE pos_thr_fk = %s', 632 array('integer'), 633 array($this->id) 634 ); 635 636 $old_obj_id = ilForum::_lookupObjIdForForumId($old_pk); 637 638 $new_obj_id = ilForum::_lookupObjIdForForumId($new_pk); 639 640 while ($post = $posts->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) { 641 $news_id = ilNewsItem::getFirstNewsIdForContext( 642 $old_obj_id, 643 "frm", 644 $post["pos_pk"], 645 "pos" 646 ); 647 $news_item = new ilNewsItem($news_id); 648 $news_item->setContextObjId($new_obj_id); 649 $news_item->update(); 650 //echo "<br>-".$post["pos_pk"]."-".$old_obj_id."-".$new_obj_id."-"; 651 } 652 653 return count($nodes); 654 } 655 656 return 0; 657 } 658 659 public function getNestedSetPostChildren($pos_id = null, $levels = null) 660 { 661 $data = null; 662 $objProperties = ilForumProperties::getInstance($this->getFrmObjId()); 663 $is_post_activation_enabled = $objProperties->isPostActivationEnabled(); 664 665 if ($pos_id !== null) { 666 $res = $this->db->queryF( 667 " 668 SELECT lft, rgt, depth 669 FROM frm_posts_tree 670 WHERE pos_fk = %s 671 AND thr_fk = %s", 672 array('integer', 'integer'), 673 array($pos_id, $this->id) 674 ); 675 676 $data = $this->db->fetchAssoc($res); 677 } 678 679 $query = ' 680 SELECT fpt.depth, 681 fpt.rgt, 682 fpt.parent_pos, 683 fp.pos_pk, 684 fp.pos_subject, 685 fp.pos_usr_alias, 686 fp.pos_date, 687 fp.pos_update, 688 fp.pos_status, 689 fp.pos_display_user_id, 690 fp.pos_usr_alias, 691 fp.import_name, 692 fp.pos_author_id, 693 fp.is_author_moderator, 694 fur.post_id, 695 (CASE 696 WHEN fur.post_id IS NULL ' . 697 ($this->user->getId() == ANONYMOUS_USER_ID ? ' AND 1 = 2 ' : '') . ' 698 THEN 0 699 ELSE 1 700 END) post_read, 701 COUNT(fpt2.pos_fk) children 702 703 FROM frm_posts_tree fpt 704 705 INNER JOIN frm_posts fp 706 ON fp.pos_pk = fpt.pos_fk 707 708 LEFT JOIN frm_posts_tree fpt2 709 ON fpt2.lft BETWEEN fpt.lft AND fpt.rgt 710 AND fpt.thr_fk = fpt2.thr_fk 711 AND fpt.pos_fk != fpt2.pos_fk '; 712 713 714 $query .= ' 715 LEFT JOIN frm_user_read fur 716 ON fur.thread_id = fp.pos_thr_fk 717 AND fur.post_id = fp.pos_pk 718 AND fur.usr_id = ' . $this->db->quote($this->user->getId(), 'integer') . ' 719 720 LEFT JOIN usr_data ud 721 ON ud.usr_id = fp.pos_display_user_id 722 723 WHERE fpt.thr_fk = ' . $this->db->quote($this->id, 'integer'); 724 725 if ($data) { 726 $query .= ' AND fpt.lft > ' . $this->db->quote($data['lft'], 'integer') . 727 ' AND fpt.lft < ' . $this->db->quote($data['rgt'], 'integer') . ' '; 728 } 729 if ($is_post_activation_enabled && !$this->is_moderator) { 730 $query .= ' AND (fp.pos_status = 1 OR fp.pos_status = 0 AND fp.pos_display_user_id = ' . $this->db->quote($this->user->getId(), 'integer') . ') '; 731 } 732 733 if ($data && is_numeric($levels)) { 734 $query .= ' AND fpt.depth <= ' . $this->db->quote($data['depth'] + $levels, 'integer') . ' '; 735 } 736 737 $query .= ' GROUP BY fpt.depth, 738 fpt.rgt, 739 fpt.parent_pos, 740 fp.pos_pk, 741 fp.pos_subject, 742 fp.pos_usr_alias, 743 fp.pos_date, 744 fp.pos_update, 745 fp.pos_status, 746 fp.pos_display_user_id, 747 fp.pos_usr_alias, 748 fp.import_name, 749 fp.pos_author_id, 750 fp.is_author_moderator, 751 fur.post_id 752 ORDER BY fpt.rgt DESC 753 '; 754 755 $queryCounter = ' 756 SELECT pos_fk 757 FROM frm_posts_tree fpt 758 INNER JOIN frm_posts fp 759 ON fp.pos_pk = fpt.pos_fk 760 WHERE fpt.thr_fk = ' . $this->db->quote($this->id, 'integer'); 761 762 if ($is_post_activation_enabled && !$this->is_moderator) { 763 $queryCounter .= ' AND (fp.pos_status = 1 OR fp.pos_status = 0 AND fp.pos_display_user_id = ' . $this->db->quote($this->user->getId(), 'integer') . ') '; 764 } 765 $queryCounter .= ' ORDER BY fpt.rgt DESC'; 766 767 $resCounter = $this->db->query($queryCounter); 768 $counter = array(); 769 $i = 0; 770 while ($row = $this->db->fetchAssoc($resCounter)) { 771 $counter[$row['pos_fk']] = $i++; 772 } 773 774 $res = $this->db->query($query); 775 $children = array(); 776 $usr_ids = array(); 777 while ($row = $this->db->fetchAssoc($res)) { 778 if ((int) $row['pos_display_user_id']) { 779 $usr_ids[] = (int) $row['pos_display_user_id']; 780 } 781 782 $row['counter'] = $counter[$row['pos_pk']]; 783 $children[] = $row; 784 } 785 786 ilForumAuthorInformationCache::preloadUserObjects(array_unique($usr_ids)); 787 788 return $children; 789 } 790 791 /** 792 * Check whether a user's notification about new posts in a thread is enabled (result > 0) or not (result == 0). 793 * @param integer $a_user_id id of an user 794 * @return bool true in case of success, false in case of failure 795 * @access public 796 */ 797 public function isNotificationEnabled($a_user_id) 798 { 799 if ($this->id && $a_user_id) { 800 $result = $this->db->queryf( 801 ' 802 SELECT COUNT(notification_id) cnt FROM frm_notification 803 WHERE user_id = %s AND thread_id = %s', 804 array('integer', 'integer'), 805 array($a_user_id, $this->id) 806 ); 807 808 while ($record = $this->db->fetchAssoc($result)) { 809 return (bool) $record['cnt']; 810 } 811 812 return false; 813 } 814 815 return false; 816 } 817 818 /** 819 * Enable a user's notification about new posts in a thread. 820 * @param integer $a_user_id id of an user 821 * @return bool true in case of success, false in case of failure 822 * @access public 823 */ 824 public function enableNotification($a_user_id) 825 { 826 if ($this->id && $a_user_id) { 827 if (!$this->isNotificationEnabled($a_user_id)) { 828 $nextId = $this->db->nextId('frm_notification'); 829 $this->db->manipulateF( 830 ' 831 INSERT INTO frm_notification 832 ( notification_id, 833 user_id, 834 thread_id 835 ) 836 VALUES(%s, %s, %s)', 837 array('integer', 'integer', 'integer'), 838 array($nextId, $a_user_id, $this->id) 839 ); 840 841 return true; 842 } 843 return false; 844 } 845 846 return false; 847 } 848 849 /** 850 * Disable a user's notification about new posts in a thread. 851 * @param integer $a_user_id id of an user 852 * @return bool true in case of success, false in case of failure 853 * @access public 854 */ 855 public function disableNotification($a_user_id) 856 { 857 if ($this->id && $a_user_id) { 858 $this->db->manipulateF( 859 ' 860 DELETE FROM frm_notification 861 WHERE user_id = %s 862 AND thread_id = %s', 863 array('integer', 'integer'), 864 array($a_user_id, $this->id) 865 ); 866 867 return false; 868 } 869 870 return false; 871 } 872 873 /** 874 * Sets the current topic sticky. 875 * 876 * @return bool true in case of success, false in case of failure 877 * @access public 878 */ 879 public function makeSticky() 880 { 881 if ($this->id && !$this->is_sticky) { 882 $this->db->manipulateF( 883 ' 884 UPDATE frm_threads 885 SET is_sticky = %s 886 WHERE thr_pk = %s', 887 array('integer', 'integer'), 888 array('1', $this->id) 889 ); 890 891 $this->is_sticky = 1; 892 893 return true; 894 } 895 896 return false; 897 } 898 899 /** 900 * Sets the current topic non-sticky. 901 * 902 * @return bool true in case of success, false in case of failure 903 * @access public 904 */ 905 public function unmakeSticky() 906 { 907 if ($this->id && $this->is_sticky) { 908 $this->db->manipulateF( 909 ' 910 UPDATE frm_threads 911 SET is_sticky = %s 912 WHERE thr_pk = %s', 913 array('integer', 'integer'), 914 array('0', $this->id) 915 ); 916 917 $this->is_sticky = 0; 918 919 return true; 920 } 921 922 return false; 923 } 924 925 /** 926 * Closes the current topic. 927 * 928 * @return bool true in case of success, false in case of failure 929 * @access public 930 */ 931 public function close() 932 { 933 if ($this->id && !$this->is_closed) { 934 $this->db->manipulateF( 935 ' 936 UPDATE frm_threads 937 SET is_closed = %s 938 WHERE thr_pk = %s', 939 array('integer', 'integer'), 940 array('1', $this->id) 941 ); 942 943 $this->is_closed = 1; 944 945 return true; 946 } 947 948 return false; 949 } 950 951 /** 952 * Reopens the current topic. 953 * 954 * @return bool true in case of success, false in case of failure 955 * @access public 956 */ 957 public function reopen() 958 { 959 if ($this->id && $this->is_closed) { 960 $this->db->manipulateF( 961 ' 962 UPDATE frm_threads 963 SET is_closed = %s 964 WHERE thr_pk = %s', 965 array('integer', 'integer'), 966 array('0', $this->id) 967 ); 968 969 $this->is_closed = 0; 970 971 return true; 972 } 973 974 return false; 975 } 976 977 /** 978 * @return int 979 */ 980 public function getAverageRating() 981 { 982 return $this->average_rating; 983 } 984 985 /** 986 * @param int $average_rating 987 */ 988 public function setAverageRating($average_rating) 989 { 990 $this->average_rating = $average_rating; 991 } 992 993 public function setId($a_id) 994 { 995 $this->id = $a_id; 996 } 997 public function getId() 998 { 999 return $this->id; 1000 } 1001 public function setForumId($a_forum_id) 1002 { 1003 $this->forum_id = $a_forum_id; 1004 } 1005 public function getForumId() 1006 { 1007 return $this->forum_id; 1008 } 1009 public function setDisplayUserId($a_user_id) 1010 { 1011 $this->display_user_id = $a_user_id; 1012 } 1013 public function getDisplayUserId() 1014 { 1015 return $this->display_user_id; 1016 } 1017 public function setUserAlias($a_user_alias) 1018 { 1019 $this->user_alias = $a_user_alias; 1020 } 1021 public function getUserAlias() 1022 { 1023 return $this->user_alias; 1024 } 1025 public function setSubject($a_subject) 1026 { 1027 $this->subject = $a_subject; 1028 } 1029 public function getSubject() 1030 { 1031 return $this->subject; 1032 } 1033 public function setCreateDate($a_createdate) 1034 { 1035 $this->createdate = $a_createdate; 1036 } 1037 public function getCreateDate() 1038 { 1039 return $this->createdate; 1040 } 1041 public function setChangeDate($a_changedate) 1042 { 1043 if ($a_changedate == '0000-00-00 00:00:00') { 1044 $this->changedate = null; 1045 } else { 1046 $this->changedate = $a_changedate; 1047 } 1048 } 1049 public function getChangeDate() 1050 { 1051 return $this->changedate; 1052 } 1053 public function setImportName($a_import_name) 1054 { 1055 $this->import_name = $a_import_name; 1056 } 1057 public function getImportName() 1058 { 1059 return $this->import_name; 1060 } 1061 public function setLastPostString($a_last_post) 1062 { 1063 if ($a_last_post == '') { 1064 $a_last_post = null; 1065 } 1066 1067 $this->last_post_string = $a_last_post; 1068 } 1069 public function getLastPostString() 1070 { 1071 return $this->last_post_string; 1072 } 1073 public function setVisits($a_visits) 1074 { 1075 $this->visits = $a_visits; 1076 } 1077 public function getVisits() 1078 { 1079 return $this->visits; 1080 } 1081 public function setSticky($a_sticky) 1082 { 1083 $this->is_sticky = $a_sticky; 1084 } 1085 public function isSticky() 1086 { 1087 return $this->is_sticky == 1 ? true : false; 1088 } 1089 public function setClosed($a_closed) 1090 { 1091 $this->is_closed = $a_closed; 1092 } 1093 public function isClosed() 1094 { 1095 return $this->is_closed == 1 ? true : false; 1096 } 1097 public function setOrderField($a_order_field) 1098 { 1099 $this->orderField = $a_order_field; 1100 } 1101 public function getOrderField() 1102 { 1103 return $this->orderField; 1104 } 1105 public function setModeratorRight($bool) 1106 { 1107 $this->is_moderator = $bool; 1108 } 1109 public function getModeratorRight() 1110 { 1111 return $this->is_moderator; 1112 } 1113 public function getFrmObjId() 1114 { 1115 return $this->frm_obj_id; 1116 } 1117 1118 /** 1119 * @param int $thr_author_id 1120 */ 1121 public function setThrAuthorId($thr_author_id) 1122 { 1123 $this->thr_author_id = $thr_author_id; 1124 } 1125 1126 /** 1127 * @return int 1128 */ 1129 public function getThrAuthorId() 1130 { 1131 return $this->thr_author_id; 1132 } 1133 1134 /** 1135 * Looks up the title/subject of a topic/thread 1136 * 1137 * @param integer id of the topic/thread 1138 * @return string title/subject of the topic/thread 1139 * @access public 1140 * @static 1141 */ 1142 public static function _lookupTitle($a_topic_id) 1143 { 1144 global $DIC; 1145 $ilDB = $DIC->database(); 1146 1147 $res = $ilDB->queryf( 1148 ' 1149 SELECT thr_subject 1150 FROM frm_threads 1151 WHERE thr_pk = %s', 1152 array('integer'), 1153 array($a_topic_id) 1154 ); 1155 $row = $ilDB->fetchObject($res); 1156 1157 if (is_object($row)) { 1158 return $row->thr_subject; 1159 } 1160 1161 return ''; 1162 } 1163 1164 public function updateThreadTitle() 1165 { 1166 $this->db->update( 1167 'frm_threads', 1168 array('thr_subject' => array('text',$this->getSubject())), 1169 array('thr_pk' => array('integer', $this->getId())) 1170 ); 1171 1172 $first_node = $this->getFirstPostNode(); 1173 $first_node->setSubject($this->getSubject()); 1174 $first_node->update(); 1175 } 1176 1177 /** 1178 * @param $a_num_posts 1179 * @return ilForumTopic 1180 */ 1181 public function setNumPosts($a_num_posts) 1182 { 1183 $this->num_posts = $a_num_posts; 1184 return $this; 1185 } 1186 1187 /** 1188 * @return int 1189 */ 1190 public function getNumPosts() 1191 { 1192 return $this->num_posts; 1193 } 1194 1195 /** 1196 * @param int $num_new_posts 1197 * @return ilForumTopic 1198 */ 1199 public function setNumNewPosts($num_new_posts) 1200 { 1201 $this->num_new_posts = $num_new_posts; 1202 return $this; 1203 } 1204 1205 /** 1206 * @return int 1207 */ 1208 public function getNumNewPosts() 1209 { 1210 return $this->num_new_posts; 1211 } 1212 1213 /** 1214 * @param int $num_unread_posts 1215 * @return ilForumTopic 1216 */ 1217 public function setNumUnreadPosts($num_unread_posts) 1218 { 1219 $this->num_unread_posts = $num_unread_posts; 1220 return $this; 1221 } 1222 1223 /** 1224 * @return int 1225 */ 1226 public function getNumUnreadPosts() 1227 { 1228 return $this->num_unread_posts; 1229 } 1230 1231 /** 1232 * @param boolean $user_notification_enabled 1233 * @return ilForumTopic 1234 */ 1235 public function setUserNotificationEnabled($user_notification_enabled) 1236 { 1237 $this->user_notification_enabled = $user_notification_enabled; 1238 return $this; 1239 } 1240 1241 /** 1242 * @return boolean 1243 */ 1244 public function getUserNotificationEnabled() 1245 { 1246 return $this->user_notification_enabled; 1247 } 1248 1249 public function setOrderDirection($direction) 1250 { 1251 if (!in_array(strtoupper($direction), self::$possibleOrderDirections)) { 1252 $direction = current(self::$possibleOrderDirections); 1253 } 1254 1255 $this->orderDirection = $direction; 1256 return $this; 1257 } 1258 1259 public function getOrderDirection() 1260 { 1261 return $this->orderDirection; 1262 } 1263 1264 public static function lookupForumIdByTopicId($a_topic_id) 1265 { 1266 global $DIC; 1267 $ilDB = $DIC->database(); 1268 1269 $res = $ilDB->queryF( 1270 'SELECT thr_top_fk FROM frm_threads WHERE thr_pk = %s', 1271 array('integer'), 1272 array($a_topic_id) 1273 ); 1274 1275 $row = $ilDB->fetchAssoc($res); 1276 1277 return $row['thr_top_fk']; 1278 } 1279 1280 public function getSorting() 1281 { 1282 return $this->thread_sorting; 1283 } 1284 public function updateMergedThread() 1285 { 1286 $this->db->update( 1287 'frm_threads', 1288 array( 1289 'thr_num_posts' => array('integer', $this->getNumPosts()), 1290 'visits' => array('integer', $this->getVisits()), 1291 'thr_last_post' => array('text', $this->getLastPostString()), 1292 'thr_subject' => array('text', $this->getSubject()) 1293 ), 1294 array('thr_pk' => array('integer', $this->getId())) 1295 ); 1296 } 1297 1298 /** 1299 * @param integer $thread_id 1300 * @return string datetime 1301 */ 1302 public static function _lookupDate($thread_id) 1303 { 1304 global $DIC; 1305 $ilDB = $DIC->database(); 1306 1307 $res = $ilDB->queryF( 1308 'SELECT thr_date FROM frm_threads WHERE thr_pk = %s', 1309 array('integer'), 1310 array((int) $thread_id) 1311 ); 1312 1313 $row = $ilDB->fetchAssoc($res); 1314 1315 return $row['thr_date'] ? $row['thr_date'] : '0000-00-00 00:00:00'; 1316 } 1317 1318 /** 1319 * @return ilForumPost|null 1320 */ 1321 public function getLastPostForThreadOverview() 1322 { 1323 return $this->last_post; 1324 } 1325 1326 /** 1327 * @param ilForumPost $post 1328 */ 1329 public function setLastPostForThreadOverview(ilForumPost $post) 1330 { 1331 $this->last_post = $post; 1332 } 1333} 1334