5 * Copyright 1999-2000, Tim Perdue/Sourceforge
6 * Copyright 2002, Tim Perdue/GForge, LLC
7 * Copyright 2009, Roland Mas
9 * This file is part of FusionForge.
11 * FusionForge is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published
13 * by the Free Software Foundation; either version 2 of the License,
14 * or (at your option) any later version.
16 * FusionForge is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with FusionForge; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 require_once $gfcommon.'include/Error.class.php';
28 require_once $gfcommon.'forum/ForumMessage.class.php';
29 // This string is used when sending the notification mail for identifying the
31 define('FORUM_MAIL_MARKER', '#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+');
33 class Forum extends Error {
36 * Associative array of data from db.
38 * @var array $data_array.
47 var $Group; //group object
50 * An array of 'types' for this forum - nested, flat, ultimate, etc.
52 * @var array view_types.
56 var $current_user_perm;
61 * @param object The Group object to which this forum is associated.
62 * @param int The group_forum_id.
63 * @param array The associative array of data.
64 * @return boolean success.
66 function Forum(&$Group, $group_forum_id=false, $arr=false) {
68 if (!$Group || !is_object($Group)) {
69 $this->setError(sprintf(_('%1$s:: No Valid Group Object'), "Forum"));
72 if ($Group->isError()) {
73 $this->setError('Forum:: '.$Group->getErrorMessage());
76 $this->Group =& $Group;
78 if ($group_forum_id) {
79 if (!$arr || !is_array($arr)) {
80 if (!$this->fetchData($group_forum_id)) {
84 $this->data_array =& $arr;
85 if ($this->data_array['group_id'] != $this->Group->getID()) {
86 $this->setError(_('Group_id in db result does not match Group Object'));
87 $this->data_array = null;
92 // Make sure they can even access this object
94 if (!$this->userCanView()) {
95 $this->setPermissionDeniedError();
96 $this->data_array = null;
100 $this->view_types[]='ultimate';
101 $this->view_types[]='flat';
102 $this->view_types[]='nested';
103 $this->view_types[]='threaded';
108 * create - use this function to create a new entry in the database.
110 * @param string The name of the forum.
111 * @param string The description of the forum.
112 * @param int Pass (1) if it should be public (0) for private.
113 * @param string The email address to send all new posts to.
114 * @param int Pass (1) if a welcome message should be created (0) for no welcome message.
115 * @param int Pass (1) if we should allow non-logged-in users to post (0) for mandatory login.
116 * @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
117 * @return boolean success.
119 function create($forum_name,$description,$is_public=1,$send_all_posts_to='',$create_default_message=1,$allow_anonymous=1,$moderation_level=0) {
120 if (strlen($forum_name) < 3) {
121 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
124 if (strlen($description) < 10) {
125 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
128 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
129 $this->setError(_('Illegal Characters in Forum Name'));
132 if ($send_all_posts_to) {
133 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
134 $invalid_mails = validate_emails($send_all_posts_to);
135 if (count($invalid_mails) > 0) {
136 $this->setInvalidEmailError();
141 $project_name = $this->Group->getUnixName();
142 $result_list_samename = db_query_params ('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
144 array ($project_name.'-'.strtolower($forum_name),
145 $this->Group->getID())) ;
147 if (db_numrows($result_list_samename) > 0){
148 $this->setError(_('Mailing List Exists with same name'));
153 // This is a hack to allow non-site-wide-admins to post
154 // news. The news/submit.php checks for proper permissions.
155 // This needs to be revisited.
156 global $sys_news_group;
157 if ($this->Group->getID() == $sys_news_group) {
158 // Future check will be added.
161 // Current permissions check.
163 $perm =& $this->Group->getPermission( session_get_user() );
165 if (!$perm || !is_object($perm) || !$perm->isForumAdmin()) {
166 $this->setPermissionDeniedError();
172 $result = db_query_params('INSERT INTO forum_group_list (group_id,forum_name,is_public,description,send_all_posts_to,allow_anonymous,moderation_level) VALUES ($1,$2,$3,$4,$5,$6,$7)',
173 array ($this->Group->getID(),
174 strtolower($forum_name),
176 htmlspecialchars($description),
179 $moderation_level)) ;
182 $this->setError(_('Error Adding Forum').db_error());
185 $this->group_forum_id=db_insertid($result,'forum_group_list','group_forum_id');
186 $this->fetchData($this->group_forum_id);
188 if ($create_default_message) {
189 $fm=new ForumMessage($this);
190 // Use the system side default language
191 setup_gettext_from_sys_lang ();
192 $string=sprintf(_('Welcome to %1$s'), $forum_name);
193 // and switch back to the user preference
194 setup_gettext_from_context();
195 if (!$fm->create($string, $string)) {
196 $this->setError($fm->getErrorMessage());
202 $this->Group->normalizeAllRoles () ;
208 * fetchData - re-fetch the data for this forum from the database.
210 * @param int The forum_id.
211 * @return boolean success.
213 function fetchData($group_forum_id) {
214 global $sys_database_type;
216 if ($sys_database_type == "mysql") {
219 (SELECT count(*) AS `count`
221 SELECT DISTINCT group_forum_id, thread_id FROM forum
223 WHERE tmp.group_forum_id = fgl.group_forum_id
225 FROM forum_group_list_vw AS fgl
226 WHERE group_forum_id='$group_forum_id'";
227 $res = db_query_mysql ($sql);
229 $res = db_query_params ('SELECT * FROM forum_group_list_vw WHERE group_forum_id=$1',
230 array ($group_forum_id)) ;
232 if (!$res || db_numrows($res) < 1) {
233 $this->setError(_('Invalid forum group identifier'));
236 $this->data_array =& db_fetch_array($res);
237 db_free_result($res);
242 * getGroup - get the Group object this ArtifactType is associated with.
244 * @return object The Group object.
246 function &getGroup() {
251 * getID - The id of this forum.
253 * @return int The group_forum_id #.
256 return $this->data_array['group_forum_id'];
260 * getNextThreadID - The next thread_id for a new top in this forum.
262 * @return int The next thread_id #.
264 function getNextThreadID() {
265 $result = db_query_params ('SELECT nextval($1)',
266 array ('forum_thread_seq')) ;
267 if (!$result || db_numrows($result) < 1) {
271 return db_result($result,0,0);
275 * getUnixName - returns the name used by email gateway
277 * @return string unix name
279 function getUnixName() {
280 return $this->Group->getUnixName().'-'.$this->getName();
284 * getSavedDate - The unix time when the person last hit "save my place".
286 * @return int The unix time.
288 function getSavedDate() {
289 if (@$this->save_date) {
290 return $this->save_date;
292 if (session_loggedin()) {
293 $result = db_query_params ('SELECT save_date FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
296 if ($result && db_numrows($result) > 0) {
297 $this->save_date=db_result($result,0,'save_date');
298 return $this->save_date;
300 //highlight new messages from the past week only
301 $this->save_date=(time()-604800);
302 return $this->save_date;
305 //highlight new messages from the past week only
306 $this->save_date=(time()-604800);
307 return $this->save_date;
313 * allowAnonymous - does this forum allow non-logged in users to post.
315 * @return boolean allow_anonymous.
317 function allowAnonymous() {
318 return $this->data_array['allow_anonymous'];
322 * isPublic - Is this forum open to the general public.
324 * @return boolean is_public.
326 function isPublic() {
327 return $this->data_array['is_public'];
331 * getName - get the name of this forum.
333 * @return string The name of this forum.
336 return $this->data_array['forum_name'];
340 * getSendAllPostsTo - an optional email address to send all forum posts to.
342 * @return string The email address.
344 function getSendAllPostsTo() {
345 return $this->data_array['send_all_posts_to'];
349 * getDescription - the description of this forum.
351 * @return string The description.
353 function getDescription() {
354 return $this->data_array['description'];
358 * getModerationLevel - the moderation level of the forum
360 * @return int The moderation level.
362 function getModerationLevel() {
363 return $this->data_array['moderation_level'];
367 * getMessageCount - the total number of messages in this forum.
369 * @return int The count.
371 function getMessageCount() {
372 return $this->data_array['total'];
376 * getThreadCount - the total number of threads in this forum.
378 * @return int The count.
380 function getThreadCount() {
381 return $this->data_array['threads'];
385 * getMostRecentDate - the most recent date of a post to this board.
387 * @return int The most recent date.
389 function getMostRecentDate() {
390 return $this->data_array['recent'];
394 * getMonitoringIDs - return an array of user_id's for those monitoring this forum.
396 * @return array The array of user_id's.
398 function getMonitoringIDs() {
399 $result = db_query_params ('SELECT user_id FROM forum_monitored_forums WHERE forum_id=$1',
400 array ($this->getID())) ;
401 return util_result_column_to_array($result);
405 * getForumAdminIDs - return an array of user_id's for those users which are forum admins.
407 * @return array The array of user_id's.
409 function getForumAdminIDs() {
410 $result = db_query_params ('SELECT user_group.user_id FROM user_group, role_setting
411 WHERE role_setting.section_name=$1
412 AND role_setting.ref_id=$2
413 AND role_setting.value::integer > 1
414 AND user_group.role_id = role_setting.role_id',
417 return util_result_column_to_array($result);
421 * getReturnEmailAddress() - return the return email address for notification emails
423 * @return string return email address
425 function getReturnEmailAddress() {
426 global $sys_default_domain, $sys_use_gateways;
428 if($sys_use_gateways) {
429 $address .= $this->getUnixName();
431 $address .= 'noreply';
434 if($sys_use_gateways && isset($GLOBALS['sys_forum_return_domain'])) {
435 $address .= $GLOBALS['sys_forum_return_domain'];
437 $address .= $sys_default_domain;
443 * setMonitor - Add the current user to the list of people monitoring the forum.
445 * @return boolean success.
447 function setMonitor ($u = -1) {
449 if (!session_loggedin()) {
450 $this->setError(_('You can only monitor if you are logged in'));
455 $result = db_query_params ('SELECT * FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
458 if (!$result || db_numrows($result) < 1) {
460 User is not already monitoring thread, so
461 insert a row so monitoring can begin
463 $sql="INSERT INTO forum_monitored_forums (forum_id,user_id)
464 VALUES ('".$this->getID()."','$u')";
466 $result = db_query_params ('INSERT INTO forum_monitored_forums (forum_id,user_id) VALUES ($1,$2)',
467 array ($this->getID(),
471 $this->setError(_('Unable To Add Monitor').' : '.db_error());
480 * stopMonitor - Remove the current user from the list of people monitoring the forum.
482 * @return boolean success.
484 function stopMonitor ($u = -1) {
486 if (!session_loggedin()) {
487 $this->setError(_('You can only monitor if you are logged in'));
492 return db_query_params ('DELETE FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
498 * isMonitoring - See if the current user is in the list of people monitoring the forum.
500 * @return boolean is_monitoring.
502 function isMonitoring() {
503 if (!session_loggedin()) {
506 $result = db_query_params ('SELECT count(*) AS count FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
509 $row_count = db_fetch_array($result);
510 return $result && $row_count['count'] > 0;
514 * savePlace - set a unix time into the database for this user, so future messages can be highlighted.
516 * @return boolean success.
518 function savePlace() {
519 if (!session_loggedin()) {
520 $this->setError(_('You Can Only Save Your Place If You Are Logged In'));
523 $result = db_query_params ('SELECT * FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
527 if (!$result || db_numrows($result) < 1) {
529 User is not already monitoring thread, so
530 insert a row so monitoring can begin
532 $result = db_query_params ('INSERT INTO forum_saved_place (forum_id,user_id,save_date) VALUES ($1,$2,$3)',
533 array ($this->getID(),
538 $this->setError(_('Forum::savePlace()').': '.db_error());
543 $result = db_query_params ('UPDATE forum_saved_place SET save_date=$1 WHERE user_id=$2 AND forum_id=$3',
549 $this->setError('Forum::savePlace() '.db_error());
557 * update - use this function to update an entry in the database.
559 * @param string The name of the forum.
560 * @param string The description of the forum.
561 * @param int if it should be public (0) for private.
562 * @param int if we should allow non-logged-in users to post (0) for mandatory login.
563 * @param string The email address to send all new posts to.
564 * @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
565 * @return boolean success.
567 function update($forum_name,$description,$allow_anonymous,$is_public,$send_all_posts_to='',$moderation_level=0) {
568 if (strlen($forum_name) < 3) {
569 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
572 if (strlen($description) < 10) {
573 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
576 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
577 $this->setError(_('Illegal Characters in Forum Name'));
580 if ($send_all_posts_to) {
581 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
582 $invalid_mails = validate_emails($send_all_posts_to);
583 if (count($invalid_mails) > 0) {
584 $this->setInvalidEmailError();
589 if (!$this->userIsAdmin()) {
590 $this->setPermissionDeniedError();
594 $res = db_query_params ('UPDATE forum_group_list SET
597 send_all_posts_to=$3,
602 AND group_forum_id=$8',
603 array (strtolower($forum_name),
604 htmlspecialchars($description),
609 $this->Group->getID(),
612 if (!$res || db_affected_rows($res) < 1) {
613 $this->setError(_('Error On Update:').': '.db_error());
620 * delete - delete this forum and all its related data.
622 * @param bool I'm Sure.
623 * @param bool I'm REALLY sure.
624 * @return bool true/false;
626 function delete($sure, $really_sure) {
627 if (!$sure || !$really_sure) {
628 $this->setMissingParamsError();
631 if (!$this->userIsAdmin()) {
632 $this->setPermissionDeniedError();
636 db_query_params ('DELETE FROM forum_agg_msg_count WHERE group_forum_id=$1',
637 array ($this->getID())) ;
638 //echo '1'.db_error();
639 db_query_params ('DELETE FROM forum_monitored_forums WHERE forum_id=$1',
640 array ($this->getID())) ;
641 //echo '2'.db_error();
642 db_query_params ('DELETE FROM forum_saved_place WHERE forum_id=$1',
643 array ($this->getID())) ;
644 //echo '3'.db_error();
645 db_query_params ('DELETE FROM forum_attachment WHERE msg_id IN (SELECT msg_id from forum where group_forum_id=$1)',
646 array ($this->getID())) ;
647 db_query_params ('DELETE FROM forum WHERE group_forum_id=$1',
648 array ($this->getID())) ;
649 //echo '4'.db_error();
650 db_query_params ('DELETE FROM forum_group_list WHERE group_forum_id=$1',
651 array ($this->getID())) ;
652 //echo '5'.db_error();
653 //delete forum's role setting
654 db_query_params ('DELETE FROM role_setting WHERE section_name=$1 AND ref_id=$2',
660 $this->Group->normalizeAllRoles () ;
667 USER PERMISSION FUNCTIONS
672 * userCanView - determine if the user can view this forum.
674 * @return boolean user_can_view.
676 function userCanView() {
677 if ($this->isPublic()) {
680 if (!session_loggedin()) {
684 // You must have a role in the project if this forum is not public
686 if ($this->userIsAdmin() || $this->getCurrentUserPerm() >= 0) {
696 * userIsModLvl1 - see if the user goes into the moderated level 1 category
698 * @return boolean user_is_mod_lvl1
700 function userIsModLvl1() {
701 if (!session_loggedin()) {
702 if ( ($this->isPublic() && $this->allowAnonymous()) ) {
703 return true;//public forum, anonymous allowed, user not logged in
706 $perm =& $this->Group->getPermission( session_get_user() );
707 if ( (!$perm->isMember() )) {
708 //the user isn't a member of the project
716 * userIsModLvl2 - see if the user goes into the moderated level 2 category
718 * @return boolean user_is_mod_lvl1
720 function userIsModLvl2() {
721 if ( $this->userIsAdmin() ) {
729 * userCanPost - see if the logged-in user's perms are >= 1 or Group ForumAdmin.
731 * @return boolean user_can_post.
733 function userCanPost() {
734 if (($this->isPublic() && $this->allowAnonymous()) || $this->userIsAdmin()) {
736 } elseif ($this->isPublic() && session_loggedin()) {
739 if (!session_loggedin()) {
742 if ($this->getCurrentUserPerm() >= 1) {
752 * userIsAdmin - see if the logged-in user's perms are >= 2 or Group ForumAdmin.
754 * @return boolean user_is_admin.
756 function userIsAdmin() {
757 if (!session_loggedin()) {
760 $perm =& $this->Group->getPermission( session_get_user() );
762 if (($this->getCurrentUserPerm() >= 2) || ($perm->isForumAdmin())) {
771 * getCurrentUserPerm - get the logged-in user's perms from his role.
773 * @return int perm level for the logged-in user.
775 function getCurrentUserPerm() {
776 if (!session_loggedin()) {
779 if (!isset($this->current_user_perm)) {
780 $res = db_query_params ('SELECT role_setting.value::integer
781 FROM role_setting, user_group
782 WHERE role_setting.ref_id=$1
783 AND user_group.role_id=role_setting.role_id
784 AND user_group.user_id=$2
785 AND role_setting.section_name=$3',
786 array ($this->getID(),
789 $this->current_user_perm=db_result($res,0,0);
791 // Return no access if no access rights defined.
792 if (!$this->current_user_perm)
793 $this->current_user_perm=-1;
795 return $this->current_user_perm;
804 // c-file-style: "bsd"