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 $forum_id 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.
82 * An array of 'types' for this forum - nested, flat, ultimate, etc.
84 * @var array view_types.
89 * flag : forum or news entry
98 * @param bool $group_forum_id
100 * @internal param \The $object Group object to which this forum is associated.
101 * @internal param \The $int group_forum_id.
102 * @internal param \The $array associative array of data.
103 * @return \Forum success.
105 function __construct(&$Group, $group_forum_id = false, $arr = false, $is_news = false) {
107 if (!$Group || !is_object($Group)) {
108 $this->setError(_('No Valid Group Object'));
111 if ($Group->isError()) {
112 $this->setError('Forums: '.$Group->getErrorMessage());
116 if ($group_forum_id) {
118 // Is this a news posting (or a real forum)?
120 $res = db_query_params('SELECT forum_id FROM news_bytes
122 array($group_forum_id));
123 $is_news = $res && db_numrows($res) >= 1;
125 if (!$is_news && !$Group->usesForum()) {
126 $this->setError(sprintf(_('%s does not use the Forum tool.'), $Group->getPublicName()));
129 $this->Group =& $Group;
131 if ($group_forum_id) {
132 if (!$arr || !is_array($arr)) {
133 if (!$this->fetchData($group_forum_id)) {
137 $this->data_array =& $arr;
138 if ($this->data_array['group_id'] != $this->Group->getID()) {
139 $this->setError(_('group_id in db result does not match Group Object'));
140 $this->data_array = null;
145 // Make sure they can even access this object
148 !forge_check_perm ('forum', $this->getID(), 'read')) {
149 $this->setPermissionDeniedError();
150 $this->data_array = null;
154 $this->view_types[] = 'ultimate';
155 $this->view_types[] = 'flat';
156 $this->view_types[] = 'nested';
157 $this->view_types[] = 'threaded';
158 $this->is_news = $is_news;
162 * create - use this function to create a new entry in the database.
164 * @param string The name of the forum.
165 * @param string The description of the forum.
166 * @param string The email address to send all new posts to.
167 * @param int Pass (1) if a welcome message should be created (0) for no welcome message.
168 * @return boolean success.
170 function create($forum_name, $description, $send_all_posts_to = '', $create_default_message = 1) {
171 if (!$this->is_news && strlen(trim($forum_name)) < 3) {
172 $this->setError(_('Forum name must be at least 3 characters.'));
175 if (!$this->is_news && strlen(trim($description)) < 10) {
176 $this->setError(_('Forum description must be at least 10 characters.'));
179 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
180 if (preg_match('/ /',$forum_name)){
181 $this->setError(_('Illegal characters in Forum name.').' - '._('No space allowed.'));
183 $this->setError(_('Illegal characters in Forum name.'));
187 if ($send_all_posts_to) {
188 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
189 $invalid_mails = validate_emails($send_all_posts_to);
190 if (count($invalid_mails) > 0) {
191 $this->setInvalidEmailError($send_all_posts_to);
196 $project_name = $this->Group->getUnixName();
197 $result_list_samename = db_query_params('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
199 array($project_name.'-'.strtolower($forum_name),
200 $this->Group->getID()));
202 if (db_numrows($result_list_samename) > 0){
203 $this->setError(_('Mailing List exists with same name.'));
207 // This is a hack to allow non-site-wide-admins to post
208 // news. The news/submit.php checks for proper permissions.
209 // This needs to be revisited.
211 if ($this->Group->getID() == forge_get_config('news_group')) {
212 // Future check will be added.
215 // Current permissions check.
217 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
218 $this->setPermissionDeniedError();
224 $result = db_query_params('INSERT INTO forum_group_list (group_id,forum_name,description,send_all_posts_to) VALUES ($1,$2,$3,$4)',
225 array($this->Group->getID(),
226 strtolower($forum_name),
227 htmlspecialchars($description),
228 $send_all_posts_to));
230 $this->setError(_('Error Adding Forum')._(': ').db_error());
234 $this->group_forum_id=db_insertid($result,'forum_group_list','group_forum_id');
235 $this->fetchData($this->group_forum_id);
237 if ($create_default_message) {
238 $fm=new ForumMessage($this);
239 // Use the system side default language
240 setup_gettext_from_sys_lang();
241 $string = sprintf(_('Welcome to %s'), $forum_name);
242 // and switch back to the user preference
243 setup_gettext_from_context();
244 if (!$fm->create($string, $string)) {
245 $this->setError($fm->getErrorMessage());
250 $this->Group->normalizeAllRoles () ;
256 * fetchData - re-fetch the data for this forum from the database.
258 * @param int The forum_id.
259 * @return boolean success.
261 function fetchData($group_forum_id) {
262 $res=db_query_params('SELECT * FROM forum_group_list_vw WHERE group_forum_id=$1 AND group_id=$2',
263 array($group_forum_id, $this->Group->getID()));
264 if (!$res || db_numrows($res) < 1) {
265 $this->setError(_('Invalid forum group identifier.'));
268 $this->data_array = db_fetch_array($res);
269 db_free_result($res);
274 * getGroup - get the Group object this ArtifactType is associated with.
276 * @return object The Group object.
278 function &getGroup() {
283 * getID - The id of this forum.
285 * @return int The group_forum_id #.
288 return $this->data_array['group_forum_id'];
292 * getNextThreadID - The next thread_id for a new top in this forum.
294 * @return int The next thread_id #.
296 function getNextThreadID() {
297 $result = db_query_params('SELECT nextval($1)',
298 array('forum_thread_seq'));
299 if (!$result || db_numrows($result) < 1) {
303 return db_result($result, 0, 0);
307 * getUnixName - returns the name used by email gateway
309 * @return string unix name
311 function getUnixName() {
312 return $this->Group->getUnixName().'-'.$this->getName();
316 * getSavedDate - The unix time when the person last hit "save my place".
318 * @return int The unix time.
320 function getSavedDate() {
321 if (isset($this->save_date)) {
322 return $this->save_date;
324 if (session_loggedin()) {
325 $result = db_query_params('SELECT save_date FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
328 if ($result && db_numrows($result) > 0) {
329 $this->save_date=db_result($result, 0, 'save_date');
330 return $this->save_date;
332 //highlight new messages from the past week only
333 $this->save_date=(time()-604800);
334 return $this->save_date;
337 //highlight new messages from the past week only
338 $this->save_date=(time()-604800);
339 return $this->save_date;
345 * getName - get the name of this forum.
347 * @return string The name of this forum.
350 return $this->data_array['forum_name'];
354 * getSendAllPostsTo - an optional email address to send all forum posts to.
356 * @return string The email address.
358 function getSendAllPostsTo() {
359 return $this->data_array['send_all_posts_to'];
363 * getDescription - the description of this forum.
365 * @return string The description.
367 function getDescription() {
368 return $this->data_array['description'];
372 * getMessageCount - the total number of messages in this forum.
374 * @return int The count.
376 function getMessageCount() {
377 return $this->data_array['total'];
381 * getThreadCount - the total number of threads in this forum.
383 * @return int The count.
385 function getThreadCount() {
386 return $this->data_array['threads'];
390 * getMostRecentDate - the most recent date of a post to this board.
392 * @return int The most recent date.
394 function getMostRecentDate() {
395 return $this->data_array['recent'];
399 * getMonitoringIDs - return an array of user_id's for those monitoring this forum.
401 * @return array The array of user_id's.
403 function getMonitoringIDs() {
404 $result = db_query_params('SELECT user_id FROM forum_monitored_forums WHERE forum_id=$1',
405 array($this->getID()));
406 return util_result_column_to_array($result);
410 * getReturnEmailAddress() - return the return email address for notification emails
412 * @return string return email address
414 function getReturnEmailAddress() {
416 if(forge_get_config('use_gateways')) {
417 $address = $this->getUnixName();
419 $address = 'noreply';
422 if(forge_get_config('use_gateways') && forge_get_config('forum_return_domain')) {
423 $address .= forge_get_config('forum_return_domain');
425 $address .= forge_get_config('web_host');
431 * setMonitor - Add the current user to the list of people monitoring the forum.
433 * @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.
434 * @return boolean success.
436 function setMonitor($u = -1) {
438 if (!session_loggedin()) {
439 $this->setError(_('You can only monitor if you are logged in.'));
444 $result = db_query_params('SELECT * FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
447 if (!$result || db_numrows($result) < 1) {
449 User is not already monitoring thread, so
450 insert a row so monitoring can begin
452 $result = db_query_params('INSERT INTO forum_monitored_forums (forum_id,user_id) VALUES ($1,$2)',
453 array($this->getID(),
457 $this->setError(_('Unable To Add Monitor').' : '.db_error());
466 * stopMonitor - Remove the current user from the list of people monitoring the forum.
469 * @return boolean success.
471 function stopMonitor($u = -1) {
473 if (!session_loggedin()) {
474 $this->setError(_('You can only monitor if you are logged in.'));
479 return db_query_params('DELETE FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
485 * isMonitoring - See if the current user is in the list of people monitoring the forum.
487 * @return boolean is_monitoring.
489 function isMonitoring() {
490 if (!session_loggedin()) {
493 $result = db_query_params('SELECT count(*) AS count FROM forum_monitored_forums WHERE user_id=$1 AND forum_id=$2',
496 $row_count = db_fetch_array($result);
497 return $result && $row_count['count'] > 0;
501 * savePlace - set a unix time into the database for this user, so future messages can be highlighted.
503 * @return boolean success.
505 function savePlace() {
506 if (!session_loggedin()) {
507 $this->setError(_('You can only save your place if you are logged in.'));
510 $result = db_query_params('SELECT * FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
514 if (!$result || db_numrows($result) < 1) {
516 User is not already monitoring thread, so
517 insert a row so monitoring can begin
519 $result = db_query_params('INSERT INTO forum_saved_place (forum_id,user_id,save_date) VALUES ($1,$2,$3)',
520 array($this->getID(),
525 $this->setError('Forum::savePlace()'._(': ').db_error());
530 $result = db_query_params('UPDATE forum_saved_place SET save_date=$1 WHERE user_id=$2 AND forum_id=$3',
536 $this->setError('Forum::savePlace() '.db_error());
544 * update - use this function to update an entry in the database.
546 * @param string The name of the forum.
547 * @param string The description of the forum.
548 * @param string The email address to send all new posts to.
549 * @return boolean success.
551 function update($forum_name, $description, $send_all_posts_to = '') {
552 if (strlen($forum_name) < 3) {
553 $this->setError(_('Forum name must be at least 3 characters.'));
556 if (strlen($description) < 10) {
557 $this->setError(_('Forum description must be at least 10 characters.'));
560 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
561 if (preg_match('/ /',$forum_name)){
562 $this->setError(_('Illegal characters in Forum name.').' - '._('No space allowed.'));
564 $this->setError(_('Illegal characters in Forum name.'));
568 if ($send_all_posts_to) {
569 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
570 $invalid_mails = validate_emails($send_all_posts_to);
571 if (count($invalid_mails) > 0) {
572 $this->setInvalidEmailError($send_all_posts_to);
577 if (!forge_check_perm('forum_admin', $this->Group->getID())) {
578 $this->setPermissionDeniedError();
582 $project_name = $this->Group->getUnixName();
583 $result_list_samename = db_query_params('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
585 array($project_name.'-'.strtolower($forum_name),
586 $this->Group->getID()));
588 if (db_numrows($result_list_samename) > 0){
589 $this->setError(_('Mailing List exists with same name.'));
593 $res = db_query_params('UPDATE forum_group_list SET
598 AND group_forum_id=$5',
599 array(strtolower($forum_name),
600 htmlspecialchars($description),
602 $this->Group->getID(),
605 if (!$res || db_affected_rows($res) < 1) {
606 $this->setError(_('Update failed')._(': ').db_error());
613 * delete - delete this forum and all its related data.
615 * @param bool I'm Sure.
616 * @param bool I'm REALLY sure.
617 * @return bool true/false;
619 function delete($sure, $really_sure) {
620 if (!$sure || !$really_sure) {
621 $this->setMissingParamsError(_('Please tick all checkboxes.'));
624 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
625 $this->setPermissionDeniedError();
629 $result = db_query_params('DELETE FROM forum_agg_msg_count WHERE group_forum_id=$1',
630 array($this->getID()));
632 $this->setError(_('Error Deleting Forum')._(': ').db_error());
637 $result = db_query_params('DELETE FROM forum_monitored_forums WHERE forum_id=$1',
638 array($this->getID()));
640 $this->setError(_('Error Deleting Forum')._(': ').db_error());
645 $result = db_query_params('DELETE FROM forum_saved_place WHERE forum_id=$1',
646 array($this->getID()));
648 $this->setError(_('Error Deleting Forum')._(': ').db_error());
653 $result = db_query_params('DELETE FROM forum_attachment WHERE msg_id IN (SELECT msg_id 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 WHERE group_forum_id=$1',
662 array($this->getID()));
664 $this->setError(_('Error Deleting Forum')._(': ').db_error());
669 $result = db_query_params('DELETE FROM forum_group_list WHERE group_forum_id=$1',
670 array($this->getID()));
672 $this->setError(_('Error Deleting Forum')._(': ').db_error());
679 $this->Group->normalizeAllRoles();
688 // c-file-style: "bsd"