5 * Copyright 1999-2000, Tim Perdue/Sourceforge
6 * Copyright 2002, Tim Perdue/GForge, LLC
8 * This file is part of FusionForge.
10 * FusionForge is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published
12 * by the Free Software Foundation; either version 2 of the License,
13 * or (at your option) any later version.
15 * FusionForge is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with FusionForge; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 require_once $gfcommon.'include/Error.class.php';
27 require_once $gfcommon.'forum/ForumMessage.class.php';
28 // This string is used when sending the notification mail for identifying the
30 define('FORUM_MAIL_MARKER', '#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+');
32 class Forum extends Error {
35 * Associative array of data from db.
37 * @var array $data_array.
46 var $Group; //group object
49 * An array of 'types' for this forum - nested, flat, ultimate, etc.
51 * @var array view_types.
55 var $current_user_perm;
60 * @param object The Group object to which this forum is associated.
61 * @param int The group_forum_id.
62 * @param array The associative array of data.
63 * @return boolean success.
65 function Forum(&$Group, $group_forum_id=false, $arr=false) {
67 if (!$Group || !is_object($Group)) {
68 $this->setError(sprintf(_('%1$s:: No Valid Group Object'), "Forum"));
71 if ($Group->isError()) {
72 $this->setError('Forum:: '.$Group->getErrorMessage());
75 $this->Group =& $Group;
77 if ($group_forum_id) {
78 if (!$arr || !is_array($arr)) {
79 if (!$this->fetchData($group_forum_id)) {
83 $this->data_array =& $arr;
84 if ($this->data_array['group_id'] != $this->Group->getID()) {
85 $this->setError(_('Group_id in db result does not match Group Object'));
86 $this->data_array = null;
91 // Make sure they can even access this object
93 if (!$this->userCanView()) {
94 $this->setPermissionDeniedError();
95 $this->data_array = null;
99 $this->view_types[]='ultimate';
100 $this->view_types[]='flat';
101 $this->view_types[]='nested';
102 $this->view_types[]='threaded';
107 * create - use this function to create a new entry in the database.
109 * @param string The name of the forum.
110 * @param string The description of the forum.
111 * @param int Pass (1) if it should be public (0) for private.
112 * @param string The email address to send all new posts to.
113 * @param int Pass (1) if a welcome message should be created (0) for no welcome message.
114 * @param int Pass (1) if we should allow non-logged-in users to post (0) for mandatory login.
115 * @param int Pass (0) if the messages that are posted in the forum should go to moderation before available. 0-> no moderation 1-> moderation for anonymous and non-project members 2-> moderation for everyone
116 * @return boolean success.
118 function create($forum_name,$description,$is_public=1,$send_all_posts_to='',$create_default_message=1,$allow_anonymous=1,$moderation_level=0) {
119 if (strlen($forum_name) < 3) {
120 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
123 if (strlen($description) < 10) {
124 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
127 if (eregi('[^_\.0-9a-z-]',$forum_name)) {
128 $this->setError(_('Illegal Characters in Forum Name'));
131 if ($send_all_posts_to) {
132 $invalid_mails = validate_emails($send_all_posts_to);
133 if (count($invalid_mails) > 0) {
134 $this->setInvalidEmailError();
139 $project_name = $this->Group->getUnixName();
140 $result_list_samename = db_query('SELECT 1 FROM mail_group_list WHERE list_name = \''.$project_name.'-'.$forum_name.'\' AND group_id='.$this->Group->getID().'');
142 if (db_numrows($result_list_samename) > 0){
143 $this->setError(_('Mailing List Exists with same name'));
148 // This is a hack to allow non-site-wide-admins to post
149 // news. The news/submit.php checks for proper permissions.
150 // This needs to be revisited.
151 global $sys_news_group;
152 if ($this->Group->getID() == $sys_news_group) {
153 // Future check will be added.
156 // Current permissions check.
158 $perm =& $this->Group->getPermission( session_get_user() );
160 if (!$perm || !is_object($perm) || !$perm->isForumAdmin()) {
161 $this->setPermissionDeniedError();
166 $sql="INSERT INTO forum_group_list (group_id,forum_name,is_public,description,send_all_posts_to,allow_anonymous,moderation_level)
167 VALUES ('".$this->Group->getId()."',
168 '". strtolower($forum_name) ."',
170 '". htmlspecialchars($description) ."',
171 '$send_all_posts_to',
172 '$allow_anonymous','$moderation_level')";
175 $result=db_query($sql);
178 $this->setError(_('Error Adding Forum').db_error());
181 $this->group_forum_id=db_insertid($result,'forum_group_list','group_forum_id');
182 $this->fetchData($this->group_forum_id);
183 if ($create_default_message) {
184 $fm=new ForumMessage($this);
185 if (!$fm->create("Welcome to ".$forum_name,"Welcome to ".$forum_name)) {
186 $this->setError($fm->getErrorMessage());
195 * fetchData - re-fetch the data for this forum from the database.
197 * @param int The forum_id.
198 * @return boolean success.
200 function fetchData($group_forum_id) {
201 global $sys_database_type;
203 if ($sys_database_type == "mysql") {
206 (SELECT count(*) AS `count`
208 SELECT DISTINCT group_forum_id, thread_id FROM forum
210 WHERE tmp.group_forum_id = fgl.group_forum_id
212 FROM forum_group_list_vw AS fgl
213 WHERE group_forum_id='$group_forum_id'";
215 $sql="SELECT * FROM forum_group_list_vw
216 WHERE group_forum_id='$group_forum_id'";
219 if (!$res || db_numrows($res) < 1) {
220 $this->setError(_('Invalid forum group identifier'));
223 $this->data_array =& db_fetch_array($res);
224 db_free_result($res);
229 * getGroup - get the Group object this ArtifactType is associated with.
231 * @return object The Group object.
233 function &getGroup() {
238 * getID - The id of this forum.
240 * @return int The group_forum_id #.
243 return $this->data_array['group_forum_id'];
247 * getNextThreadID - The next thread_id for a new top in this forum.
249 * @return int The next thread_id #.
251 function getNextThreadID() {
252 global $sys_database_type;
254 if ($sys_database_type == "mysql") {
255 $sql="call newval('forum_thread_seq', @res)";
256 $result=db_mquery($sql);
263 $sql="SELECT nextval('forum_thread_seq')";
265 $result=db_query($sql);
266 if (!$result || db_numrows($result) < 1) {
270 return db_result($result,0,0);
274 * getUnixName - returns the name used by email gateway
276 * @return string unix name
278 function getUnixName() {
279 return $this->Group->getUnixName().'-'.$this->getName();
283 * getSavedDate - The unix time when the person last hit "save my place".
285 * @return int The unix time.
287 function getSavedDate() {
288 if (@$this->save_date) {
289 return $this->save_date;
291 if (session_loggedin()) {
292 $sql="SELECT save_date FROM forum_saved_place
293 WHERE user_id='".user_getid()."' AND forum_id='". $this->getID() ."';";
294 $result = db_query($sql);
295 if ($result && db_numrows($result) > 0) {
296 $this->save_date=db_result($result,0,'save_date');
297 return $this->save_date;
299 //highlight new messages from the past week only
300 $this->save_date=(time()-604800);
301 return $this->save_date;
304 //highlight new messages from the past week only
305 $this->save_date=(time()-604800);
306 return $this->save_date;
312 * allowAnonymous - does this forum allow non-logged in users to post.
314 * @return boolean allow_anonymous.
316 function allowAnonymous() {
317 return $this->data_array['allow_anonymous'];
321 * isPublic - Is this forum open to the general public.
323 * @return boolean is_public.
325 function isPublic() {
326 return $this->data_array['is_public'];
330 * getName - get the name of this forum.
332 * @return string The name of this forum.
335 return $this->data_array['forum_name'];
339 * getSendAllPostsTo - an optional email address to send all forum posts to.
341 * @return string The email address.
343 function getSendAllPostsTo() {
344 return $this->data_array['send_all_posts_to'];
348 * getDescription - the description of this forum.
350 * @return string The description.
352 function getDescription() {
353 return $this->data_array['description'];
357 * getModerationLevel - the moderation level of the forum
359 * @return int The moderation level.
361 function getModerationLevel() {
362 return $this->data_array['moderation_level'];
366 * getMessageCount - the total number of messages in this forum.
368 * @return int The count.
370 function getMessageCount() {
371 return $this->data_array['total'];
375 * getThreadCount - the total number of threads in this forum.
377 * @return int The count.
379 function getThreadCount() {
380 return $this->data_array['threads'];
384 * getMostRecentDate - the most recent date of a post to this board.
386 * @return int The most recent date.
388 function getMostRecentDate() {
389 return $this->data_array['recent'];
393 * getMonitoringIDs - return an array of user_id's for those monitoring this forum.
395 * @return array The array of user_id's.
397 function getMonitoringIDs() {
398 $sql="SELECT user_id FROM forum_monitored_forums WHERE forum_id='".$this->getID()."'";
399 $result=db_query($sql);
400 return util_result_column_to_array($result);
404 * getForumAdminIDs - return an array of user_id's for those users which are forum admins.
406 * @return array The array of user_id's.
408 function getForumAdminIDs() {
409 $sql = "SELECT user_group.user_id
410 FROM user_group, role_setting
411 WHERE role_setting.section_name='forum'
412 AND role_setting.ref_id='".$this->getID()."'
413 AND role_setting.value::integer > 1
414 AND user_group.role_id = role_setting.role_id";
415 $result = db_query($sql);
416 return util_result_column_to_array($result);
420 * getReturnEmailAddress() - return the return email address for notification emails
422 * @return string return email address
424 function getReturnEmailAddress() {
425 global $sys_default_domain, $sys_use_gateways;
427 if($sys_use_gateways) {
428 $address .= $this->getUnixName();
430 $address .= 'noreply';
433 if($sys_use_gateways && isset($GLOBALS['sys_forum_return_domain'])) {
434 $address .= $GLOBALS['sys_forum_return_domain'];
436 $address .= $sys_default_domain;
442 * setMonitor - Add the current user to the list of people monitoring the forum.
444 * @return boolean success.
446 function setMonitor() {
447 if (!session_loggedin()) {
448 $this->setError(_('You can only monitor if you are logged in'));
451 $sql="SELECT * FROM forum_monitored_forums
452 WHERE user_id='".user_getid()."' AND forum_id='".$this->getID()."';";
453 $result = db_query($sql);
455 if (!$result || db_numrows($result) < 1) {
457 User is not already monitoring thread, so
458 insert a row so monitoring can begin
460 $sql="INSERT INTO forum_monitored_forums (forum_id,user_id)
461 VALUES ('".$this->getID()."','".user_getid()."')";
463 $result = db_query($sql);
466 $this->setError(_('Unable To Add Monitor').' : '.db_error());
475 * stopMonitor - Remove the current user from the list of people monitoring the forum.
477 * @return boolean success.
479 function stopMonitor() {
480 if (!session_loggedin()) {
481 $this->setError(_('You can only monitor if you are logged in'));
484 $sql="DELETE FROM forum_monitored_forums
485 WHERE user_id='".user_getid()."' AND forum_id='".$this->getID()."';";
486 return db_query($sql);
490 * isMonitoring - See if the current user is in the list of people monitoring the forum.
492 * @return boolean is_monitoring.
494 function isMonitoring() {
495 if (!session_loggedin()) {
498 $sql="SELECT count(*) AS count FROM forum_monitored_forums WHERE user_id='".user_getid()."' AND forum_id='".$this->getID()."';";
499 $result = db_query($sql);
500 $row_count = db_fetch_array($result);
501 return $result && $row_count['count'] > 0;
505 * savePlace - set a unix time into the database for this user, so future messages can be highlighted.
507 * @return boolean success.
509 function savePlace() {
510 if (!session_loggedin()) {
511 $this->setError(_('You Can Only Save Your Place If You Are Logged In'));
514 $sql="SELECT * FROM forum_saved_place
515 WHERE user_id='".user_getid()."' AND forum_id='".$this->getID()."'";
517 $result = db_query($sql);
519 if (!$result || db_numrows($result) < 1) {
521 User is not already monitoring thread, so
522 insert a row so monitoring can begin
524 $sql="INSERT INTO forum_saved_place (forum_id,user_id,save_date)
525 VALUES ('".$this->getID()."','".user_getid()."','".time()."')";
527 $result = db_query($sql);
530 $this->setError(_('Forum::savePlace()').': '.db_error());
535 $sql="UPDATE forum_saved_place
536 SET save_date='".time()."'
537 WHERE user_id='".user_getid()."' AND forum_id='".$this->getID()."'";
538 $result = db_query($sql);
541 $this->setError('Forum::savePlace() '.db_error());
549 * update - use this function to update an entry in the database.
551 * @param string The name of the forum.
552 * @param string The description of the forum.
553 * @param int if it should be public (0) for private.
554 * @param int if we should allow non-logged-in users to post (0) for mandatory login.
555 * @param string The email address to send all new posts to.
556 * @param int if the messages that are posted in the forum should go to moderation before available. 0-> no moderation 1-> moderation for anonymous and non-project members 2-> moderation for everyone
557 * @return boolean success.
559 function update($forum_name,$description,$allow_anonymous,$is_public,$send_all_posts_to='',$moderation_level=0) {
560 if (strlen($forum_name) < 3) {
561 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
564 if (strlen($description) < 10) {
565 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
568 if (eregi('[^_\.0-9a-z-]',$forum_name)) {
569 $this->setError(_('Illegal Characters in Forum Name'));
572 if ($send_all_posts_to) {
573 $invalid_mails = validate_emails($send_all_posts_to);
574 if (count($invalid_mails) > 0) {
575 $this->setInvalidEmailError();
580 if (!$this->userIsAdmin()) {
581 $this->setPermissionDeniedError();
585 $res=db_query("UPDATE forum_group_list SET
586 forum_name='". strtolower($forum_name) ."',
587 description='". htmlspecialchars($description) ."',
588 send_all_posts_to='".$send_all_posts_to ."',
589 allow_anonymous='" .$allow_anonymous . "',
590 moderation_level='" .$moderation_level . "',
591 is_public='" .$is_public . "'
592 WHERE group_id='".$this->Group->getID()."'
593 AND group_forum_id='".$this->getID()."'");
595 if (!$res || db_affected_rows($res) < 1) {
596 $this->setError(_('Error On Update:').': '.db_error());
603 * delete - delete this forum and all its related data.
605 * @param bool I'm Sure.
606 * @param bool I'm REALLY sure.
607 * @return bool true/false;
609 function delete($sure, $really_sure) {
610 if (!$sure || !$really_sure) {
611 $this->setMissingParamsError();
614 if (!$this->userIsAdmin()) {
615 $this->setPermissionDeniedError();
619 db_query("DELETE FROM forum_agg_msg_count
620 WHERE group_forum_id='".$this->getID()."'");
621 //echo '1'.db_error();
622 db_query("DELETE FROM forum_monitored_forums
623 WHERE forum_id='".$this->getID()."'");
624 //echo '2'.db_error();
625 db_query("DELETE FROM forum_saved_place
626 WHERE forum_id='".$this->getID()."'");
627 //echo '3'.db_error();
628 $res = db_query("SELECT msg_id from forum where group_forum_id='".$this->getID()."'");//get the messages for this forum, to delete its attachments
629 $delete_ids = array();
630 for ($i=0;$i<db_numrows($res);$i++) {
631 $aux = db_fetch_array($res);
632 $delete_ids[] = $aux[0];
634 foreach ($delete_ids as $id) {
635 db_query("DELETE FROM forum_attachment where msg_id='$id'");
638 db_query("DELETE FROM forum
639 WHERE group_forum_id='".$this->getID()."'");
640 //echo '4'.db_error();
641 db_query("DELETE FROM forum_group_list
642 WHERE group_forum_id='".$this->getID()."'");
643 //echo '5'.db_error();
650 USER PERMISSION FUNCTIONS
655 * userCanView - determine if the user can view this forum.
657 * @return boolean user_can_view.
659 function userCanView() {
660 if ($this->isPublic()) {
663 if (!session_loggedin()) {
667 // You must have a role in the project if this forum is not public
669 if ($this->userIsAdmin() || $this->getCurrentUserPerm() >= 0) {
679 * userIsModLvl1 - see if the user goes into the moderated level 1 category
681 * @return boolean user_is_mod_lvl1
683 function userIsModLvl1() {
684 if (!session_loggedin()) {
685 if ( ($this->isPublic() && $this->allowAnonymous()) ) {
686 return true;//public forum, anonymous allowed, user not logged in
689 $perm =& $this->Group->getPermission( session_get_user() );
690 if ( (!$perm->isMember() )) {
691 //the user isn't a member of the project
699 * userIsModLvl2 - see if the user goes into the moderated level 2 category
701 * @return boolean user_is_mod_lvl1
703 function userIsModLvl2() {
704 if ( $this->userIsAdmin() ) {
712 * userCanPost - see if the logged-in user's perms are >= 1 or Group ForumAdmin.
714 * @return boolean user_can_post.
716 function userCanPost() {
717 if (($this->isPublic() && $this->allowAnonymous()) || $this->userIsAdmin()) {
719 } elseif ($this->isPublic() && session_loggedin()) {
722 if (!session_loggedin()) {
725 if ($this->getCurrentUserPerm() >= 1) {
735 * userIsAdmin - see if the logged-in user's perms are >= 2 or Group ForumAdmin.
737 * @return boolean user_is_admin.
739 function userIsAdmin() {
740 if (!session_loggedin()) {
743 $perm =& $this->Group->getPermission( session_get_user() );
745 if (($this->getCurrentUserPerm() >= 2) || ($perm->isForumAdmin())) {
754 * getCurrentUserPerm - get the logged-in user's perms from his role.
756 * @return int perm level for the logged-in user.
758 function getCurrentUserPerm() {
759 if (!session_loggedin()) {
762 if (!isset($this->current_user_perm)) {
763 $sql="SELECT role_setting.value::integer
764 FROM role_setting, user_group
765 WHERE role_setting.ref_id='". $this->getID() ."'
766 AND user_group.role_id = role_setting.role_id
767 AND user_group.user_id='".user_getid()."'
768 AND role_setting.section_name='forum'";
769 $this->current_user_perm=db_result(db_query($sql),0,0);
771 // Return no access if no access rights defined.
772 if (!$this->current_user_perm)
773 $this->current_user_perm=-1;
775 return $this->current_user_perm;
784 // c-file-style: "bsd"