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-2014 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/FFError.class.php';
28 require_once $gfcommon.'forum/ForumMessage.class.php';
29 require_once $gfcommon.'include/MonitorElement.class.php';
31 // This string is used when sending the notification mail for identifying the
33 define('FORUM_MAIL_MARKER', '#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+');
36 * Gets a Forum object from its id
38 * @param int $forum_id the Forum id
39 * @return object the Forum object
41 function &forum_get_object($forum_id) {
42 $res = db_query_params('SELECT group_id FROM forum_group_list WHERE group_forum_id=$1',
44 if (!$res || db_numrows($res) < 1) {
48 $data = db_fetch_array($res);
49 $Group = group_get_object($data['group_id']);
50 $f = new Forum($Group, $forum_id);
52 $f->fetchData($forum_id);
57 function forum_get_groupid ($forum_id) {
58 $res = db_query_params('SELECT group_id FROM forum_group_list WHERE group_forum_id=$1',
60 if (!$res || db_numrows($res) < 1) {
63 $arr = db_fetch_array($res);
64 return $arr['group_id'];
67 class Forum extends FFError {
70 * Associative array of data from db.
72 * @var array $data_array.
84 * An array of 'types' for this forum - nested, flat, ultimate, etc.
86 * @var array view_types.
91 * flag : forum or news entry
100 * @param bool $group_forum_id
102 * @internal param \The $object Group object to which this forum is associated.
103 * @internal param \The $int group_forum_id.
104 * @internal param \The $array associative array of data.
105 * @return \Forum success.
107 function __construct(&$Group, $group_forum_id = false, $arr = false, $is_news = false) {
109 if (!$Group || !is_object($Group)) {
110 $this->setError(_('No Valid Group Object'));
113 if ($Group->isError()) {
114 $this->setError('Forums: '.$Group->getErrorMessage());
118 if ($group_forum_id) {
120 // Is this a news posting (or a real forum)?
122 $res = db_query_params('SELECT forum_id FROM news_bytes
124 array($group_forum_id));
125 $is_news = $res && db_numrows($res) >= 1;
128 $this->Group =& $Group;
130 if ($group_forum_id) {
131 if (!$arr || !is_array($arr)) {
132 if (!$this->fetchData($group_forum_id)) {
136 $this->data_array =& $arr;
137 if ($this->data_array['group_id'] != $this->Group->getID()) {
138 $this->setError(_('group_id in db result does not match Group Object'));
139 $this->data_array = null;
144 // Make sure they can even access this object
147 !forge_check_perm ('forum', $this->getID(), 'read')) {
148 $this->setPermissionDeniedError();
149 $this->data_array = null;
153 $this->view_types[] = 'ultimate';
154 $this->view_types[] = 'flat';
155 $this->view_types[] = 'nested';
156 $this->view_types[] = 'threaded';
157 $this->is_news = $is_news;
161 * create - use this function to create a new entry in the database.
163 * @param string $forum_name The name of the forum.
164 * @param string $description The description of the forum.
165 * @param string $send_all_posts_to The email address to send all new posts to.
166 * @param int $create_default_message Pass (1) if a welcome message should be created (0) for no welcome message.
167 * @return bool success.
169 function create($forum_name, $description, $send_all_posts_to = '', $create_default_message = 1) {
170 if (!$this->is_news && strlen(trim($forum_name)) < 3) {
171 $this->setError(_('Forum name must be at least 3 characters.'));
174 if (!$this->is_news && strlen(trim($description)) < 10) {
175 $this->setError(_('Forum description must be at least 10 characters.'));
178 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
179 if (preg_match('/ /',$forum_name)){
180 $this->setError(_('Illegal characters in Forum name.').' - '._('No space allowed.'));
182 $this->setError(_('Illegal characters in Forum name.'));
186 if ($send_all_posts_to) {
187 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
188 $invalid_mails = validate_emails($send_all_posts_to);
189 if (count($invalid_mails) > 0) {
190 $this->setInvalidEmailError($send_all_posts_to);
195 $project_name = $this->Group->getUnixName();
196 $result_list_samename = db_query_params('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
198 array($project_name.'-'.strtolower($forum_name),
199 $this->Group->getID()));
201 if (db_numrows($result_list_samename) > 0){
202 $this->setError(_('Mailing List exists with same name.'));
206 // This is a hack to allow non-site-wide-admins to post
207 // news. The news/submit.php checks for proper permissions.
208 // This needs to be revisited.
210 if ($this->Group->getID() == forge_get_config('news_group')) {
211 // Future check will be added.
214 // Current permissions check.
216 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
217 $this->setPermissionDeniedError();
223 $result = db_query_params('INSERT INTO forum_group_list (group_id,forum_name,description,send_all_posts_to) VALUES ($1,$2,$3,$4)',
224 array($this->Group->getID(),
225 strtolower($forum_name),
226 htmlspecialchars($description),
227 $send_all_posts_to));
229 $this->setError(_('Error Adding Forum')._(': ').db_error());
233 $this->group_forum_id=db_insertid($result,'forum_group_list','group_forum_id');
234 $this->fetchData($this->group_forum_id);
236 if ($create_default_message) {
237 $fm=new ForumMessage($this);
238 // Use the system side default language
239 setup_gettext_from_sys_lang();
240 $string = sprintf(_('Welcome to %s'), $forum_name);
241 // and switch back to the user preference
242 setup_gettext_from_context();
243 if (!$fm->create($string, $string)) {
244 $this->setError($fm->getErrorMessage());
249 $this->Group->normalizeAllRoles () ;
255 * fetchData - re-fetch the data for this forum from the database.
257 * @param int $group_forum_id The forum_id.
258 * @return boolean success.
260 function fetchData($group_forum_id) {
261 $res=db_query_params('SELECT * FROM forum_group_list_vw WHERE group_forum_id=$1 AND group_id=$2',
262 array($group_forum_id, $this->Group->getID()));
263 if (!$res || db_numrows($res) < 1) {
264 $this->setError(_('Invalid forum group identifier.'));
267 $this->data_array = db_fetch_array($res);
268 db_free_result($res);
273 * getGroup - get the Group object this ArtifactType is associated with.
275 * @return object The Group object.
277 function &getGroup() {
282 * getID - The id of this forum.
284 * @return int The group_forum_id #.
287 return $this->data_array['group_forum_id'];
291 * getNextThreadID - The next thread_id for a new top in this forum.
293 * @return int The next thread_id #.
295 function getNextThreadID() {
296 $result = db_query_params('SELECT nextval($1)',
297 array('forum_thread_seq'));
298 if (!$result || db_numrows($result) < 1) {
302 return db_result($result, 0, 0);
306 * getUnixName - returns the name used by email gateway
308 * @return string unix name
310 function getUnixName() {
311 return $this->Group->getUnixName().'-'.$this->getName();
315 * getSavedDate - The unix time when the person last hit "save my place".
317 * @return int The unix time.
319 function getSavedDate() {
320 if (isset($this->save_date)) {
321 return $this->save_date;
323 if (session_loggedin()) {
324 $result = db_query_params('SELECT save_date FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
327 if ($result && db_numrows($result) > 0) {
328 $this->save_date=db_result($result, 0, 'save_date');
329 return $this->save_date;
331 //highlight new messages from the past week only
332 $this->save_date=(time()-604800);
333 return $this->save_date;
336 //highlight new messages from the past week only
337 $this->save_date=(time()-604800);
338 return $this->save_date;
344 * getName - get the name of this forum.
346 * @return string The name of this forum.
349 return $this->data_array['forum_name'];
353 * getSendAllPostsTo - an optional email address to send all forum posts to.
355 * @return string The email address.
357 function getSendAllPostsTo() {
358 return $this->data_array['send_all_posts_to'];
362 * getDescription - the description of this forum.
364 * @return string The description.
366 function getDescription() {
367 return $this->data_array['description'];
371 * getMessageCount - the total number of messages in this forum.
373 * @return int The count.
375 function getMessageCount() {
376 return $this->data_array['total'];
380 * getThreadCount - the total number of threads in this forum.
382 * @return int The count.
384 function getThreadCount() {
385 return $this->data_array['threads'];
389 * getMostRecentDate - the most recent date of a post to this board.
391 * @return int The most recent date.
393 function getMostRecentDate() {
394 return $this->data_array['recent'];
398 * getMonitoringIDs - return an array of user_id's for those monitoring this forum.
400 * @return array The array of user_id's.
402 function getMonitoringIDs() {
403 $MonitorElementObject = new MonitorElement('forum');
404 return $MonitorElementObject->getMonitorUsersIdsInArray($this->getID());
408 * getReturnEmailAddress() - return the return email address for notification emails
410 * @return string return email address
412 function getReturnEmailAddress() {
414 if(forge_get_config('use_gateways')) {
415 $address = $this->getUnixName();
417 $address = 'noreply';
420 if(forge_get_config('use_gateways') && forge_get_config('forum_return_domain')) {
421 $address .= forge_get_config('forum_return_domain');
423 $address .= forge_get_config('web_host');
429 * setMonitor - Add the current user to the list of people monitoring the forum.
431 * @param int $u 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.
432 * @return boolean success.
434 function setMonitor($u = -1) {
436 if (!session_loggedin()) {
437 $this->setError(_('You can only monitor if you are logged in.'));
442 $MonitorElementObject = new MonitorElement('forum');
443 if (!$MonitorElementObject->enableMonitoringByUserId($this->getID(), $u)) {
444 $this->setError($MonitorElementObject->getErrorMessage());
451 * stopMonitor - Remove the current user from the list of people monitoring the forum.
454 * @return boolean success.
456 function stopMonitor($u = -1) {
458 if (!session_loggedin()) {
459 $this->setError(_('You can only monitor if you are logged in.'));
464 $MonitorElementObject = new MonitorElement('forum');
465 if (!$MonitorElementObject->disableMonitoringByUserId($this->getID(), $u)) {
466 $this->setError($MonitorElementObject->getErrorMessage());
473 * isMonitoring - See if the current user is in the list of people monitoring the forum.
475 * @return boolean is_monitoring.
477 function isMonitoring() {
478 if (!session_loggedin()) {
481 $MonitorElementObject = new MonitorElement('forum');
482 return $MonitorElementObject->isMonitoredByUserId($this->getID(), user_getid());
486 * savePlace - set a unix time into the database for this user, so future messages can be highlighted.
488 * @return boolean success.
490 function savePlace() {
491 if (!session_loggedin()) {
492 $this->setError(_('You can only save your place if you are logged in.'));
495 $result = db_query_params('SELECT * FROM forum_saved_place WHERE user_id=$1 AND forum_id=$2',
499 if (!$result || db_numrows($result) < 1) {
501 User is not already monitoring thread, so
502 insert a row so monitoring can begin
504 $result = db_query_params('INSERT INTO forum_saved_place (forum_id,user_id,save_date) VALUES ($1,$2,$3)',
505 array($this->getID(),
510 $this->setError('Forum::savePlace()'._(': ').db_error());
515 $result = db_query_params('UPDATE forum_saved_place SET save_date=$1 WHERE user_id=$2 AND forum_id=$3',
521 $this->setError('Forum::savePlace() '.db_error());
529 * update - use this function to update an entry in the database.
531 * @param string $forum_name The name of the forum.
532 * @param string $description The description of the forum.
533 * @param string $send_all_posts_to The email address to send all new posts to.
534 * @return boolean success.
536 function update($forum_name, $description, $send_all_posts_to = '') {
537 if (strlen($forum_name) < 3) {
538 $this->setError(_('Forum name must be at least 3 characters.'));
541 if (strlen($description) < 10) {
542 $this->setError(_('Forum description must be at least 10 characters.'));
545 if (!preg_match('/^([_\.0-9a-z-])*$/i',$forum_name)) {
546 if (preg_match('/ /',$forum_name)){
547 $this->setError(_('Illegal characters in Forum name.').' - '._('No space allowed.'));
549 $this->setError(_('Illegal characters in Forum name.'));
553 if ($send_all_posts_to) {
554 $send_all_posts_to = str_replace(';', ',', $send_all_posts_to);
555 $invalid_mails = validate_emails($send_all_posts_to);
556 if (count($invalid_mails) > 0) {
557 $this->setInvalidEmailError($send_all_posts_to);
562 if (!forge_check_perm('forum_admin', $this->Group->getID())) {
563 $this->setPermissionDeniedError();
567 $project_name = $this->Group->getUnixName();
568 $result_list_samename = db_query_params('SELECT 1 FROM mail_group_list WHERE list_name=$1 AND group_id=$2',
570 array($project_name.'-'.strtolower($forum_name),
571 $this->Group->getID()));
573 if (db_numrows($result_list_samename) > 0){
574 $this->setError(_('Mailing List exists with same name.'));
578 $res = db_query_params('UPDATE forum_group_list SET
583 AND group_forum_id=$5',
584 array(strtolower($forum_name),
585 htmlspecialchars($description),
587 $this->Group->getID(),
590 if (!$res || db_affected_rows($res) < 1) {
591 $this->setError(_('Update failed')._(': ').db_error());
598 * delete - delete this forum and all its related data.
600 * @param bool $sure I'm Sure.
601 * @param bool $really_sure I'm REALLY sure.
602 * @return bool true/false;
604 function delete($sure, $really_sure) {
605 if (!$sure || !$really_sure) {
606 $this->setMissingParamsError(_('Please tick all checkboxes.'));
609 if (!forge_check_perm ('forum_admin', $this->Group->getID())) {
610 $this->setPermissionDeniedError();
614 $result = db_query_params('DELETE FROM forum_agg_msg_count WHERE group_forum_id=$1',
615 array($this->getID()));
617 $this->setError(_('Error Deleting Forum')._(': ').db_error());
622 $MonitorElementObject = new MonitorElement('forum');
623 $result = $MonitorElementObject->clearMonitor($this->getID());
625 $this->setError(_('Error Deleting Forum')._(': ').db_error());
630 $result = db_query_params('DELETE FROM forum_saved_place WHERE forum_id=$1',
631 array($this->getID()));
633 $this->setError(_('Error Deleting Forum')._(': ').db_error());
638 $result = db_query_params('DELETE FROM forum_attachment WHERE msg_id IN (SELECT msg_id from forum where group_forum_id=$1)',
639 array($this->getID()));
641 $this->setError(_('Error Deleting Forum')._(': ').db_error());
645 # TODO: remove attachments from the filesystem
647 $result = db_query_params('DELETE FROM forum WHERE group_forum_id=$1',
648 array($this->getID()));
650 $this->setError(_('Error Deleting Forum')._(': ').db_error());
655 $result = db_query_params('DELETE FROM forum_group_list WHERE group_forum_id=$1',
656 array($this->getID()));
658 $this->setError(_('Error Deleting Forum')._(': ').db_error());
665 $this->Group->normalizeAllRoles();
674 // c-file-style: "bsd"