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
9 * Copyright 2013, Franck Villaume - TrivialDev
11 * This file is part of FusionForge. FusionForge is free software;
12 * you can redistribute it and/or modify it under the terms of the
13 * GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the Licence, or (at your option)
17 * FusionForge is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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', '#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+');
34 * Gets a Forum object from its id
36 * @param int the Forum id
37 * @return object the Forum object
39 function &forum_get_object($forum_id) {
40 $res = db_query_params('SELECT group_id FROM forum_group_list WHERE group_forum_id=$1',
42 if (!$res || db_numrows($res) < 1) {
46 $data = db_fetch_array($res);
47 $Group = group_get_object($data["group_id"]);
48 $f = new Forum($Group, $forum_id);
50 $f->fetchData($forum_id);
55 function forum_get_groupid ($forum_id) {
56 $res = db_query_params('SELECT group_id FROM forum_group_list WHERE group_forum_id=$1',
58 if (!$res || db_numrows($res) < 1) {
61 $arr = db_fetch_array($res);
62 return $arr['group_id'];
65 class Forum extends Error {
68 * Associative array of data from db.
70 * @var array $data_array.
79 var $Group; //group object
82 * An array of 'types' for this forum - nested, flat, ultimate, etc.
84 * @var array view_types.
91 * @param object The Group object to which this forum is associated.
92 * @param int The group_forum_id.
93 * @param array The associative array of data.
94 * @return boolean success.
96 function Forum(&$Group, $group_forum_id=false, $arr=false, $is_news=false) {
98 if (!$Group || !is_object($Group)) {
99 $this->setError(_('Forums: No Valid Group Object'));
102 if ($Group->isError()) {
103 $this->setError('Forums: '.$Group->getErrorMessage());
106 if (!$is_news && $group_forum_id) {
108 // Is this a news posting (or a real forum)?
110 $res = db_query_params('SELECT forum_id FROM news_bytes
112 array($group_forum_id));
113 $is_news = $res && db_numrows($res) >= 1;
115 if (!$is_news && !$Group->usesForum()) {
116 $this->setError(sprintf(_('%s does not use the Forum tool'),
117 $Group->getPublicName()));
120 $this->Group =& $Group;
122 if ($group_forum_id) {
123 if (!$arr || !is_array($arr)) {
124 if (!$this->fetchData($group_forum_id)) {
128 $this->data_array =& $arr;
129 if ($this->data_array['group_id'] != $this->Group->getID()) {
130 $this->setError(_('Group_id in db result does not match Group Object'));
131 $this->data_array = null;
136 // Make sure they can even access this object
139 !forge_check_perm ('forum', $this->getID(), 'read')) {
140 $this->setPermissionDeniedError();
141 $this->data_array = null;
145 $this->view_types[] = 'ultimate';
146 $this->view_types[] = 'flat';
147 $this->view_types[] = 'nested';
148 $this->view_types[] = 'threaded';
149 $this->is_news = $is_news;
154 * create - use this function to create a new entry in the database.
156 * @param string The name of the forum.
157 * @param string The description of the forum.
158 * @param string The email address to send all new posts to.
159 * @param int Pass (1) if a welcome message should be created (0) for no welcome message.
160 * @return boolean success.
162 function create($forum_name,$description,$send_all_posts_to='',$create_default_message=1) {
163 if (!$this->is_news && strlen(trim($forum_name)) < 3) {
164 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
167 if (!$this->is_news && strlen(trim($description)) < 10) {
168 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
171 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
172 if (preg_match('/ /',$forum_name)){
173 $this->setError(_('Illegal Characters in Forum Name').' - '._('No space'));
175 $this->setError(_('Illegal Characters in Forum Name'));
179 if ($send_all_posts_to) {
180 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
181 $invalid_mails = validate_emails($send_all_posts_to);
182 if (count($invalid_mails) > 0) {
183 $this->setInvalidEmailError($send_all_posts_to);
188 $project_name = $this->Group->getUnixName();
189 $result_list_samename = db_query_params('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
191 array($project_name.'-'.strtolower($forum_name),
192 $this->Group->getID()));
194 if (db_numrows($result_list_samename) > 0){
195 $this->setError(_('Mailing List Exists with same name'));
200 // This is a hack to allow non-site-wide-admins to post
201 // news. The news/submit.php checks for proper permissions.
202 // This needs to be revisited.
204 if ($this->Group->getID() == forge_get_config('news_group')) {
205 // Future check will be added.
208 // Current permissions check.
210 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
211 $this->setPermissionDeniedError();
217 $result = db_query_params('INSERT INTO forum_group_list (group_id,forum_name,description,send_all_posts_to) VALUES ($1,$2,$3,$4)',
218 array($this->Group->getID(),
219 strtolower($forum_name),
220 htmlspecialchars($description),
221 $send_all_posts_to));
223 $this->setError(_('Error Adding Forum:').' '.db_error());
227 $this->group_forum_id=db_insertid($result,'forum_group_list','group_forum_id');
228 $this->fetchData($this->group_forum_id);
230 if ($create_default_message) {
231 $fm=new ForumMessage($this);
232 // Use the system side default language
233 setup_gettext_from_sys_lang();
234 $string = sprintf(_('Welcome to %1$s'), $forum_name);
235 // and switch back to the user preference
236 setup_gettext_from_context();
237 if (!$fm->create($string, $string)) {
238 $this->setError($fm->getErrorMessage());
243 $this->Group->normalizeAllRoles () ;
249 * fetchData - re-fetch the data for this forum from the database.
251 * @param int The forum_id.
252 * @return boolean success.
254 function fetchData($group_forum_id) {
255 $res=db_query_params('SELECT * FROM forum_group_list_vw WHERE group_forum_id=$1 AND group_id=$2',
256 array($group_forum_id, $this->Group->getID()));
257 if (!$res || db_numrows($res) < 1) {
258 $this->setError(_('Invalid forum group identifier'));
261 $this->data_array = db_fetch_array($res);
262 db_free_result($res);
267 * getGroup - get the Group object this ArtifactType is associated with.
269 * @return object The Group object.
271 function &getGroup() {
276 * getID - The id of this forum.
278 * @return int The group_forum_id #.
281 return $this->data_array['group_forum_id'];
285 * getNextThreadID - The next thread_id for a new top in this forum.
287 * @return int The next thread_id #.
289 function getNextThreadID() {
290 $result = db_query_params('SELECT nextval($1)',
291 array('forum_thread_seq'));
292 if (!$result || db_numrows($result) < 1) {
296 return db_result($result, 0, 0);
300 * getUnixName - returns the name used by email gateway
302 * @return string unix name
304 function getUnixName() {
305 return $this->Group->getUnixName().'-'.$this->getName();
309 * getSavedDate - The unix time when the person last hit "save my place".
311 * @return int The unix time.
313 function getSavedDate() {
314 if (isset($this->save_date)) {
315 return $this->save_date;
317 if (session_loggedin()) {
318 $result = db_query_params('SELECT save_date FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
321 if ($result && db_numrows($result) > 0) {
322 $this->save_date=db_result($result, 0, 'save_date');
323 return $this->save_date;
325 //highlight new messages from the past week only
326 $this->save_date=(time()-604800);
327 return $this->save_date;
330 //highlight new messages from the past week only
331 $this->save_date=(time()-604800);
332 return $this->save_date;
338 * getName - get the name of this forum.
340 * @return string The name of this forum.
343 return $this->data_array['forum_name'];
347 * getSendAllPostsTo - an optional email address to send all forum posts to.
349 * @return string The email address.
351 function getSendAllPostsTo() {
352 return $this->data_array['send_all_posts_to'];
356 * getDescription - the description of this forum.
358 * @return string The description.
360 function getDescription() {
361 return $this->data_array['description'];
365 * getMessageCount - the total number of messages in this forum.
367 * @return int The count.
369 function getMessageCount() {
370 return $this->data_array['total'];
374 * getThreadCount - the total number of threads in this forum.
376 * @return int The count.
378 function getThreadCount() {
379 return $this->data_array['threads'];
383 * getMostRecentDate - the most recent date of a post to this board.
385 * @return int The most recent date.
387 function getMostRecentDate() {
388 return $this->data_array['recent'];
392 * getMonitoringIDs - return an array of user_id's for those monitoring this forum.
394 * @return array The array of user_id's.
396 function getMonitoringIDs() {
397 $result = db_query_params('SELECT user_id FROM forum_monitored_forums WHERE forum_id=$1',
398 array($this->getID()));
399 return util_result_column_to_array($result);
403 * getReturnEmailAddress() - return the return email address for notification emails
405 * @return string return email address
407 function getReturnEmailAddress() {
409 if(forge_get_config('use_gateways')) {
410 $address = $this->getUnixName();
412 $address = 'noreply';
415 if(forge_get_config('use_gateways') && forge_get_config('forum_return_domain')) {
416 $address .= forge_get_config('forum_return_domain');
418 $address .= forge_get_config('web_host');
424 * setMonitor - Add the current user to the list of people monitoring the forum.
426 * @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.
427 * @return boolean success.
429 function setMonitor($u = -1) {
431 if (!session_loggedin()) {
432 $this->setError(_('You can only monitor if you are logged in'));
437 $result = db_query_params('SELECT * FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
440 if (!$result || db_numrows($result) < 1) {
442 User is not already monitoring thread, so
443 insert a row so monitoring can begin
445 $result = db_query_params('INSERT INTO forum_monitored_forums (forum_id,user_id) VALUES ($1,$2)',
446 array($this->getID(),
450 $this->setError(_('Unable To Add Monitor').' : '.db_error());
459 * stopMonitor - Remove the current user from the list of people monitoring the forum.
461 * @return boolean success.
463 function stopMonitor($u = -1) {
465 if (!session_loggedin()) {
466 $this->setError(_('You can only monitor if you are logged in'));
471 return db_query_params('DELETE FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
477 * isMonitoring - See if the current user is in the list of people monitoring the forum.
479 * @return boolean is_monitoring.
481 function isMonitoring() {
482 if (!session_loggedin()) {
485 $result = db_query_params('SELECT count(*) AS count FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
488 $row_count = db_fetch_array($result);
489 return $result && $row_count['count'] > 0;
493 * savePlace - set a unix time into the database for this user, so future messages can be highlighted.
495 * @return boolean success.
497 function savePlace() {
498 if (!session_loggedin()) {
499 $this->setError(_('You Can Only Save Your Place If You Are Logged In'));
502 $result = db_query_params('SELECT * FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
506 if (!$result || db_numrows($result) < 1) {
508 User is not already monitoring thread, so
509 insert a row so monitoring can begin
511 $result = db_query_params('INSERT INTO forum_saved_place (forum_id,user_id,save_date) VALUES ($1,$2,$3)',
512 array($this->getID(),
517 $this->setError(_('Forum::savePlace()').': '.db_error());
522 $result = db_query_params('UPDATE forum_saved_place SET save_date=$1 WHERE user_id=$2 AND forum_id=$3',
528 $this->setError('Forum::savePlace() '.db_error());
536 * update - use this function to update an entry in the database.
538 * @param string The name of the forum.
539 * @param string The description of the forum.
540 * @param string The email address to send all new posts to.
541 * @return boolean success.
543 function update($forum_name, $description, $send_all_posts_to = '') {
544 if (strlen($forum_name) < 3) {
545 $this->setError(_('Forum Name Must Be At Least 3 Characters'));
548 if (strlen($description) < 10) {
549 $this->setError(_('Forum Description Must Be At Least 10 Characters'));
552 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
553 if (preg_match('/ /',$forum_name)){
554 $this->setError(_('Illegal Characters in Forum Name').' - '._('No space'));
556 $this->setError(_('Illegal Characters in Forum Name'));
560 if ($send_all_posts_to) {
561 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
562 $invalid_mails = validate_emails($send_all_posts_to);
563 if (count($invalid_mails) > 0) {
564 $this->setInvalidEmailError($send_all_posts_to);
569 if (!forge_check_perm('forum_admin', $this->Group->getID())) {
570 $this->setPermissionDeniedError();
574 $project_name = $this->Group->getUnixName();
575 $result_list_samename = db_query_params('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
577 array($project_name.'-'.strtolower($forum_name),
578 $this->Group->getID()));
580 if (db_numrows($result_list_samename) > 0){
581 $this->setError(_('Mailing List Exists with same name'));
585 $res = db_query_params('UPDATE forum_group_list SET
590 AND group_forum_id=$5',
591 array(strtolower($forum_name),
592 htmlspecialchars($description),
594 $this->Group->getID(),
597 if (!$res || db_affected_rows($res) < 1) {
598 $this->setError(_('Error On Update:').': '.db_error());
605 * delete - delete this forum and all its related data.
607 * @param bool I'm Sure.
608 * @param bool I'm REALLY sure.
609 * @return bool true/false;
611 function delete($sure, $really_sure) {
612 if (!$sure || !$really_sure) {
613 $this->setMissingParamsError(_('Please tick all checkboxes.'));
616 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
617 $this->setPermissionDeniedError();
621 $result = db_query_params('DELETE FROM forum_agg_msg_count WHERE group_forum_id=$1',
622 array($this->getID()));
624 $this->setError(_('Error Deleting Forum:').' '.db_error());
629 $result = db_query_params('DELETE FROM forum_monitored_forums WHERE forum_id=$1',
630 array($this->getID()));
632 $this->setError(_('Error Deleting Forum:').' '.db_error());
637 $result = db_query_params('DELETE FROM forum_saved_place WHERE forum_id=$1',
638 array($this->getID()));
640 $this->setError(_('Error Deleting Forum:').' '.db_error());
645 $result = 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()));
648 $this->setError(_('Error Deleting Forum:').' '.db_error());
653 $result = db_query_params('DELETE FROM forum WHERE group_forum_id=$1',
654 array($this->getID()));
656 $this->setError(_('Error Deleting Forum:').' '.db_error());
661 $result = db_query_params('DELETE FROM forum_group_list WHERE group_forum_id=$1',
662 array($this->getID()));
664 $this->setError(_('Error Deleting Forum:').' '.db_error());
671 $this->Group->normalizeAllRoles();
680 // c-file-style: "bsd"