5 * Copyright 1999-2000, Tim Perdue/Sourceforge
6 * Copyright 2002, Tim Perdue/GForge, LLC
7 * Copyright 2009, Roland Mas
8 * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
10 * This file is part of FusionForge. FusionForge is free software;
11 * you can redistribute it and/or modify it under the terms of the
12 * GNU General Public License as published by the Free Software
13 * Foundation; either version 2 of the Licence, or (at your option)
16 * FusionForge is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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', '#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+');
33 * Gets a Forum object from its id
35 * @param int the Forum id
36 * @return object the Forum object
38 function &forum_get_object($forum_id) {
39 $res = db_query_params ('SELECT group_id FROM forum_group_list WHERE group_forum_id=$1',
41 if (!$res || db_numrows($res) < 1) {
45 $data = db_fetch_array($res);
46 $Group = group_get_object($data["group_id"]);
47 $f = new Forum ($Group, $forum_id);
49 $f->fetchData ($forum_id) ;
54 function forum_get_groupid ($forum_id) {
55 $res = db_query_params ('SELECT group_id FROM forum_group_list WHERE group_forum_id=$1',
57 if (!$res || db_numrows($res) < 1) {
60 $arr = db_fetch_array ($res);
61 return $arr['group_id'] ;
64 class Forum extends Error {
67 * Associative array of data from db.
69 * @var array $data_array.
78 var $Group; //group object
81 * An array of 'types' for this forum - nested, flat, ultimate, etc.
83 * @var array view_types.
90 * @param object The Group object to which this forum is associated.
91 * @param int The group_forum_id.
92 * @param array The associative array of data.
93 * @return boolean success.
95 function Forum(&$Group, $group_forum_id=false, $arr=false) {
97 if (!$Group || !is_object($Group)) {
98 $this->setError(_('Forums: No Valid Group Object'));
101 if ($Group->isError()) {
102 $this->setError('Forums: '.$Group->getErrorMessage());
105 $this->Group =& $Group;
107 if ($group_forum_id) {
108 if (!$arr || !is_array($arr)) {
109 if (!$this->fetchData($group_forum_id)) {
113 $this->data_array =& $arr;
114 if ($this->data_array['group_id'] != $this->Group->getID()) {
115 $this->setError(_('Group_id in db result does not match Group Object'));
116 $this->data_array = null;
121 // Is this a news posting (or a real forum)?
123 $res = db_query_params('SELECT forum_id FROM news_bytes
125 array($this->getID()));
126 $is_news = $res && db_numrows($res) >= 1;
128 // Make sure they can even access this object
131 !forge_check_perm ('forum', $this->getID(), 'read')) {
132 $this->setPermissionDeniedError();
133 $this->data_array = null;
137 $this->view_types[]='ultimate';
138 $this->view_types[]='flat';
139 $this->view_types[]='nested';
140 $this->view_types[]='threaded';
145 * create - use this function to create a new entry in the database.
147 * @param string The name of the forum.
148 * @param string The description of the forum.
149 * @param int Pass (1) if it should be public (0) for private.
150 * @param string The email address to send all new posts to.
151 * @param int Pass (1) if a welcome message should be created (0) for no welcome message.
152 * @param int Pass (1) if we should allow non-logged-in users to post (0) for mandatory login.
153 * @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
154 * @return boolean success.
156 function create($forum_name,$description,$is_public=1,$send_all_posts_to='',$create_default_message=1,$allow_anonymous=1,$moderation_level=0) {
157 if (strlen($forum_name) < 3) {
158 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
161 if (strlen($description) < 10) {
162 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
165 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
166 $this->setError(_('Illegal Characters in Forum Name'));
169 if ($send_all_posts_to) {
170 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
171 $invalid_mails = validate_emails($send_all_posts_to);
172 if (count($invalid_mails) > 0) {
173 $this->setInvalidEmailError($send_all_posts_to);
178 $project_name = $this->Group->getUnixName();
179 $result_list_samename = db_query_params ('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
181 array ($project_name.'-'.strtolower($forum_name),
182 $this->Group->getID())) ;
184 if (db_numrows($result_list_samename) > 0){
185 $this->setError(_('Mailing List Exists with same name'));
190 // This is a hack to allow non-site-wide-admins to post
191 // news. The news/submit.php checks for proper permissions.
192 // This needs to be revisited.
194 if ($this->Group->getID() == forge_get_config('news_group')) {
195 // Future check will be added.
198 // Current permissions check.
200 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
201 $this->setPermissionDeniedError();
207 $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)',
208 array ($this->Group->getID(),
209 strtolower($forum_name),
211 htmlspecialchars($description),
214 $moderation_level)) ;
216 $this->setError(_('Error Adding Forum').db_error());
220 $this->group_forum_id=db_insertid($result,'forum_group_list','group_forum_id');
221 $this->fetchData($this->group_forum_id);
223 if ($create_default_message) {
224 $fm=new ForumMessage($this);
225 // Use the system side default language
226 setup_gettext_from_sys_lang ();
227 $string=sprintf(_('Welcome to %1$s'), $forum_name);
228 // and switch back to the user preference
229 setup_gettext_from_context();
230 if (!$fm->create($string, $string)) {
231 $this->setError($fm->getErrorMessage());
236 $this->Group->normalizeAllRoles () ;
242 * fetchData - re-fetch the data for this forum from the database.
244 * @param int The forum_id.
245 * @return boolean success.
247 function fetchData($group_forum_id) {
248 $res=db_query_params('SELECT * FROM forum_group_list_vw WHERE group_forum_id=$1 AND group_id=$2',
249 array($group_forum_id, $this->Group->getID()));
250 if (!$res || db_numrows($res) < 1) {
251 $this->setError(_('Invalid forum group identifier'));
254 $this->data_array = db_fetch_array($res);
255 db_free_result($res);
260 * getGroup - get the Group object this ArtifactType is associated with.
262 * @return object The Group object.
264 function &getGroup() {
269 * getID - The id of this forum.
271 * @return int The group_forum_id #.
274 return $this->data_array['group_forum_id'];
278 * getNextThreadID - The next thread_id for a new top in this forum.
280 * @return int The next thread_id #.
282 function getNextThreadID() {
283 $result = db_query_params ('SELECT nextval($1)',
284 array ('forum_thread_seq')) ;
285 if (!$result || db_numrows($result) < 1) {
289 return db_result($result,0,0);
293 * getUnixName - returns the name used by email gateway
295 * @return string unix name
297 function getUnixName() {
298 return $this->Group->getUnixName().'-'.$this->getName();
302 * getSavedDate - The unix time when the person last hit "save my place".
304 * @return int The unix time.
306 function getSavedDate() {
307 if (isset($this->save_date)) {
308 return $this->save_date;
310 if (session_loggedin()) {
311 $result = db_query_params ('SELECT save_date FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
314 if ($result && db_numrows($result) > 0) {
315 $this->save_date=db_result($result,0,'save_date');
316 return $this->save_date;
318 //highlight new messages from the past week only
319 $this->save_date=(time()-604800);
320 return $this->save_date;
323 //highlight new messages from the past week only
324 $this->save_date=(time()-604800);
325 return $this->save_date;
331 * allowAnonymous - does this forum allow non-logged in users to post.
333 * @return boolean allow_anonymous.
335 function allowAnonymous() {
336 return $this->data_array['allow_anonymous'];
340 * isPublic - Is this forum open to the general public.
342 * @return boolean is_public.
344 function isPublic() {
345 return $this->data_array['is_public'];
349 * getName - get the name of this forum.
351 * @return string The name of this forum.
354 return $this->data_array['forum_name'];
358 * getSendAllPostsTo - an optional email address to send all forum posts to.
360 * @return string The email address.
362 function getSendAllPostsTo() {
363 return $this->data_array['send_all_posts_to'];
367 * getDescription - the description of this forum.
369 * @return string The description.
371 function getDescription() {
372 return $this->data_array['description'];
376 * getModerationLevel - the moderation level of the forum
378 * @return int The moderation level.
380 function getModerationLevel() {
381 return $this->data_array['moderation_level'];
385 * getMessageCount - the total number of messages in this forum.
387 * @return int The count.
389 function getMessageCount() {
390 return $this->data_array['total'];
394 * getThreadCount - the total number of threads in this forum.
396 * @return int The count.
398 function getThreadCount() {
399 return $this->data_array['threads'];
403 * getMostRecentDate - the most recent date of a post to this board.
405 * @return int The most recent date.
407 function getMostRecentDate() {
408 return $this->data_array['recent'];
412 * getMonitoringIDs - return an array of user_id's for those monitoring this forum.
414 * @return array The array of user_id's.
416 function getMonitoringIDs() {
417 $result = db_query_params ('SELECT user_id FROM forum_monitored_forums WHERE forum_id=$1',
418 array ($this->getID())) ;
419 return util_result_column_to_array($result);
423 * getReturnEmailAddress() - return the return email address for notification emails
425 * @return string return email address
427 function getReturnEmailAddress() {
430 if(forge_get_config('use_gateways')) {
431 $address .= $this->getUnixName();
433 $address .= 'noreply';
436 if(forge_get_config('use_gateways') && forge_get_config('forum_return_domain')) {
437 $address .= forge_get_config('forum_return_domain');
439 $address .= forge_get_config('web_host');
445 * setMonitor - Add the current user to the list of people monitoring the forum.
447 * @param int user id of the user which will be set to monitor this forum. Defaults to 0, meaning the current logged in user will be used.
448 * @return boolean success.
450 function setMonitor ($u = -1) {
452 if (!session_loggedin()) {
453 $this->setError(_('You can only monitor if you are logged in'));
459 $result = db_query_params ('SELECT * FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
462 if (!$result || db_numrows($result) < 1) {
464 User is not already monitoring thread, so
465 insert a row so monitoring can begin
467 $result = db_query_params ('INSERT INTO forum_monitored_forums (forum_id,user_id) VALUES ($1,$2)',
468 array ($this->getID(),
472 $this->setError(_('Unable To Add Monitor').' : '.db_error());
481 * stopMonitor - Remove the current user from the list of people monitoring the forum.
483 * @return boolean success.
485 function stopMonitor ($u = -1) {
487 if (!session_loggedin()) {
488 $this->setError(_('You can only monitor if you are logged in'));
493 return db_query_params ('DELETE FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
499 * isMonitoring - See if the current user is in the list of people monitoring the forum.
501 * @return boolean is_monitoring.
503 function isMonitoring() {
504 if (!session_loggedin()) {
507 $result = db_query_params ('SELECT count(*) AS count FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
510 $row_count = db_fetch_array($result);
511 return $result && $row_count['count'] > 0;
515 * savePlace - set a unix time into the database for this user, so future messages can be highlighted.
517 * @return boolean success.
519 function savePlace() {
520 if (!session_loggedin()) {
521 $this->setError(_('You Can Only Save Your Place If You Are Logged In'));
524 $result = db_query_params ('SELECT * FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
528 if (!$result || db_numrows($result) < 1) {
530 User is not already monitoring thread, so
531 insert a row so monitoring can begin
533 $result = db_query_params ('INSERT INTO forum_saved_place (forum_id,user_id,save_date) VALUES ($1,$2,$3)',
534 array ($this->getID(),
539 $this->setError(_('Forum::savePlace()').': '.db_error());
544 $result = db_query_params ('UPDATE forum_saved_place SET save_date=$1 WHERE user_id=$2 AND forum_id=$3',
550 $this->setError('Forum::savePlace() '.db_error());
558 * update - use this function to update an entry in the database.
560 * @param string The name of the forum.
561 * @param string The description of the forum.
562 * @param int if it should be public (0) for private.
563 * @param int if we should allow non-logged-in users to post (0) for mandatory login.
564 * @param string The email address to send all new posts to.
565 * @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
566 * @return boolean success.
568 function update($forum_name,$description,$allow_anonymous,$is_public,$send_all_posts_to='',$moderation_level=0) {
569 if (strlen($forum_name) < 3) {
570 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
573 if (strlen($description) < 10) {
574 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
577 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
578 $this->setError(_('Illegal Characters in Forum Name'));
581 if ($send_all_posts_to) {
582 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
583 $invalid_mails = validate_emails($send_all_posts_to);
584 if (count($invalid_mails) > 0) {
585 $this->setInvalidEmailError($send_all_posts_to);
590 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
591 $this->setPermissionDeniedError();
595 $res = db_query_params ('UPDATE forum_group_list SET
598 send_all_posts_to=$3,
603 AND group_forum_id=$8',
604 array (strtolower($forum_name),
605 htmlspecialchars($description),
610 $this->Group->getID(),
613 if (!$res || db_affected_rows($res) < 1) {
614 $this->setError(_('Error On Update:').': '.db_error());
621 * delete - delete this forum and all its related data.
623 * @param bool I'm Sure.
624 * @param bool I'm REALLY sure.
625 * @return bool true/false;
627 function delete($sure, $really_sure) {
628 if (!$sure || !$really_sure) {
629 $this->setMissingParamsError(_('Please tick all checkboxes.'));
632 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
633 $this->setPermissionDeniedError();
637 $result = db_query_params ('DELETE FROM forum_agg_msg_count WHERE group_forum_id=$1',
638 array ($this->getID())) ;
640 $this->setError(_('Error Deleting Forum').db_error());
645 $result = db_query_params ('DELETE FROM forum_monitored_forums WHERE forum_id=$1',
646 array ($this->getID())) ;
648 $this->setError(_('Error Deleting Forum').db_error());
653 $result = db_query_params ('DELETE FROM forum_saved_place WHERE forum_id=$1',
654 array ($this->getID())) ;
656 $this->setError(_('Error Deleting Forum').db_error());
661 $result = db_query_params ('DELETE FROM forum_attachment WHERE msg_id IN (SELECT msg_id from forum where group_forum_id=$1)',
662 array ($this->getID())) ;
663 db_query_params ('DELETE FROM forum WHERE group_forum_id=$1',
664 array ($this->getID())) ;
665 //echo '4'.db_error();
666 db_query_params ('DELETE FROM forum_group_list WHERE group_forum_id=$1',
667 array ($this->getID())) ;
668 //echo '5'.db_error();
671 $this->Group->normalizeAllRoles () ;
680 // c-file-style: "bsd"