4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
5 * Copyright (C) 2002-2012 The Nucleus Group
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 * (see nucleus/documentation/index.html#license for more info)
13 * A class representing the comments (all of them) for a certain post on a ceratin blog
16 if ( !function_exists('requestVar') ) exit;
17 require_once dirname(__FILE__) . '/COMMENTACTIONS.php';
21 // item for which comment are being displayed
24 // reference to the itemActions object that is calling the showComments function
27 // total amount of comments displayed
31 * Creates a new COMMENTS object for the given blog and item
36 function COMMENTS($itemid) {
37 $this->itemid = intval($itemid);
41 * Used when parsing comments
44 * itemActions object, that will take care of the parsing
46 function setItemActions(&$itemActions) {
47 $this->itemActions =& $itemActions;
51 * Shows maximum $max comments to the given item using the given template
52 * returns the amount of shown comments (if maxToShow = -1, then there is no limit)
57 * max. comments to show
59 * indicates if the 'no comments' thingie should be outputted when there are no comments
60 * (useful for closed items)
62 * Highlight to use (if any)
64 function showComments($template, $maxToShow = -1, $showNone = 1, $highlight = '') {
65 global $CONF, $manager;
67 // create parser object & action handler
68 $actions = new COMMENTACTIONS($this);
69 $parser = new PARSER($actions->getDefinedActions(), $actions);
70 $actions->setTemplate($template);
71 $actions->setParser($parser);
73 if ($maxToShow == 0) {
74 $this->commentcount = $this->amountComments();
76 $query = 'SELECT c.citem as itemid, c.cnumber as commentid, c.cbody as body, c.cuser as user, c.cmail as userid, c.cemail as email, c.cmember as memberid, c.ctime, c.chost as host, c.cip as ip, c.cblog as blogid'
77 . ' FROM '.sql_table('comment').' as c'
78 . ' WHERE c.citem=' . $this->itemid
79 . ' ORDER BY c.ctime';
81 $comments = sql_query($query);
82 $this->commentcount = sql_num_rows($comments);
85 // if no result was found
86 if ($this->commentcount == 0) {
87 // note: when no reactions, COMMENTS_HEADER and COMMENTS_FOOTER are _NOT_ used
88 if ($showNone) $parser->parse($template['COMMENTS_NONE']);
92 // if too many comments to show
93 if (($maxToShow != -1) && ($this->commentcount > $maxToShow)) {
94 $parser->parse($template['COMMENTS_TOOMUCH']);
98 $parser->parse($template['COMMENTS_HEADER']);
100 while ( $comment = sql_fetch_assoc($comments) ) {
101 $comment['timestamp'] = strtotime($comment['ctime']);
102 $actions->setCurrentComment($comment);
103 $actions->setHighlight($highlight);
104 $param = array('comment' => &$comment);
105 $manager->notify('PreComment', $param);
106 $parser->parse($template['COMMENTS_BODY']);
107 $param = array('comment' => &$comment);
108 $manager->notify('PostComment', $param);
111 $parser->parse($template['COMMENTS_FOOTER']);
113 sql_free_result($comments);
115 return $this->commentcount;
119 * Returns the amount of comments for this itemid
121 function amountComments() {
122 $query = 'SELECT COUNT(*)'
123 . ' FROM '.sql_table('comment').' as c'
124 . ' WHERE c.citem='. $this->itemid;
125 $res = sql_query($query);
126 $arr = sql_fetch_row($res);
132 * Adds a new comment to the database
133 * @param string $timestamp
134 * @param array $comment
137 function addComment($timestamp, $comment)
139 global $CONF, $member, $manager;
141 $blogid = getBlogIDFromItemID($this->itemid);
143 $settings =& $manager->getBlog($blogid);
144 $settings->readSettings();
146 // begin if: comments disabled
147 if ( !$settings->commentsEnabled() )
149 return _ERROR_COMMENTS_DISABLED;
152 // begin if: public cannot comment
153 if ( !$settings->isPublic() && !$member->isLoggedIn() )
155 return _ERROR_COMMENTS_NONPUBLIC;
158 // begin if: comment uses a protected member name
159 if ( $CONF['ProtectMemNames'] && !$member->isLoggedIn() && MEMBER::isNameProtected($comment['user']) )
161 return _ERROR_COMMENTS_MEMBERNICK;
164 // begin if: email required, but missing (doesn't apply to members)
165 if ( $settings->emailRequired() && strlen($comment['email']) == 0 && !$member->isLoggedIn() )
167 return _ERROR_EMAIL_REQUIRED;
170 ## Note usage of mb_strlen() vs strlen() below ##
172 // begin if: commenter's name is too long
173 if ( mb_strlen($comment['user']) > 40 )
175 return _ERROR_USER_TOO_LONG;
178 // begin if: commenter's email is too long
179 if ( mb_strlen($comment['email']) > 100 )
181 return _ERROR_EMAIL_TOO_LONG;
184 // begin if: commenter's url is too long
185 if ( mb_strlen($comment['userid']) > 100 )
187 return _ERROR_URL_TOO_LONG;
190 $comment['timestamp'] = $timestamp;
191 $comment['host'] = gethostbyaddr(serverVar('REMOTE_ADDR') );
192 $comment['ip'] = serverVar('REMOTE_ADDR');
194 // begin if: member is logged in, use that data
195 if ( $member->isLoggedIn() )
197 $comment['memberid'] = $member->getID();
198 $comment['user'] = '';
199 $comment['userid'] = '';
200 $comment['email'] = '';
204 $comment['memberid'] = 0;
211 if ( isset($manager->subscriptions['ValidateForm']) )
213 $plugins = array_merge($plugins, $manager->subscriptions['ValidateForm']);
216 if ( isset($manager->subscriptions['PreAddComment']) )
218 $plugins = array_merge($plugins, $manager->subscriptions['PreAddComment']);
221 if ( isset($manager->subscriptions['PostAddComment']) )
223 $plugins = array_merge($plugins, $manager->subscriptions['PostAddComment']);
226 $plugins = array_unique($plugins);
228 while ( list(, $plugin) = each($plugins) )
230 $p = $manager->getPlugin($plugin);
231 $continue = $continue || $p->supportsFeature('handleSpam');
236 'body' => $comment['body'],
237 'id' => $comment['itemid'],
239 'return' => $continue
242 // begin if: member logged in
243 if ( $member->isLoggedIn() )
245 $spamcheck['author'] = $member->displayname;
246 $spamcheck['email'] = $member->email;
251 $spamcheck['author'] = $comment['user'];
252 $spamcheck['email'] = $comment['email'];
253 $spamcheck['url'] = $comment['userid'];
256 $param = array('spamcheck' => &$spamcheck);
257 $manager->notify('SpamCheck', $param);
259 if ( !$continue && isset($spamcheck['result']) && $spamcheck['result'] == TRUE )
261 return _ERROR_COMMENTS_SPAM;
264 // isValidComment returns either "1" or an error message
265 $isvalid = $this->isValidComment($comment, $spamcheck);
272 // begin if: send email to notification address
273 if ( $settings->getNotifyAddress() && $settings->notifyOnComment() )
276 $mailto_msg = _NOTIFY_NC_MSG . ' ' . $this->itemid . "\n";
277 // $mailto_msg .= $CONF['IndexURL'] . 'index.php?itemid=' . $this->itemid . "\n\n";
278 $temp = parse_url($CONF['Self']);
280 if ( $temp['scheme'] )
282 $mailto_msg .= createItemLink($this->itemid) . "\n\n";
286 $tempurl = $settings->getURL();
288 if ( substr($tempurl, -1) == '/' || substr($tempurl, -4) == '.php' )
290 $mailto_msg .= $tempurl . '?itemid=' . $this->itemid . "\n\n";
294 $mailto_msg .= $tempurl . '/?itemid=' . $this->itemid . "\n\n";
298 if ( $comment['memberid'] == 0 )
300 $mailto_msg .= _NOTIFY_USER . ' ' . $comment['user'] . "\n";
301 $mailto_msg .= _NOTIFY_USERID . ' ' . $comment['userid'] . "\n";
305 $mailto_msg .= _NOTIFY_MEMBER .' ' . $member->getDisplayName() . ' (ID=' . $member->getID() . ")\n";
308 $mailto_msg .= _NOTIFY_HOST . ' ' . $comment['host'] . "\n";
309 $mailto_msg .= _NOTIFY_COMMENT . "\n " . $comment['body'] . "\n";
310 $mailto_msg .= getMailFooter();
312 $item =& $manager->getItem($this->itemid, 0, 0);
313 $mailto_title = _NOTIFY_NC_TITLE . ' ' . strip_tags($item['title']) . ' (' . $this->itemid . ')';
315 $frommail = $member->getNotifyFromMailAddress($comment['email']);
317 $notify = new NOTIFICATION($settings->getNotifyAddress() );
318 $notify->notify($mailto_title, $mailto_msg , $frommail);
321 $comment = COMMENT::prepare($comment);
324 'comment' => &$comment,
325 'spamcheck' => &$spamcheck
327 $manager->notify('PreAddComment', $param);
329 $name = sql_real_escape_string($comment['user']);
330 $url = sql_real_escape_string($comment['userid']);
331 $email = sql_real_escape_string($comment['email']);
332 $body = sql_real_escape_string($comment['body']);
333 $host = sql_real_escape_string($comment['host']);
334 $ip = sql_real_escape_string($comment['ip']);
335 $memberid = intval($comment['memberid']);
336 $timestamp = date('Y-m-d H:i:s', $comment['timestamp']);
337 $itemid = $this->itemid;
339 $qSql = 'SELECT COUNT(*) AS result '
340 . 'FROM ' . sql_table('comment')
342 . 'cmail = "' . $url . '"'
343 . ' AND cmember = "' . $memberid . '"'
344 . ' AND cbody = "' . $body . '"'
345 . ' AND citem = "' . $itemid . '"'
346 . ' AND cblog = "' . $blogid . '"';
347 $result = (integer) quickQuery($qSql);
351 return _ERROR_BADACTION;
354 $query = 'INSERT INTO '.sql_table('comment').' (CUSER, CMAIL, CEMAIL, CMEMBER, CBODY, CITEM, CTIME, CHOST, CIP, CBLOG) '
355 . "VALUES ('$name', '$url', '$email', $memberid, '$body', $itemid, '$timestamp', '$host', '$ip', '$blogid')";
360 $commentid = sql_insert_id();
362 'comment' => &$comment,
363 'commentid' => &$commentid,
364 'spamcheck' => &$spamcheck
366 $manager->notify('PostAddComment', $param);
374 * Checks if a comment is valid and call plugins
375 * that can check if the comment is a spam comment
377 function isValidComment(&$comment, &$spamcheck) {
379 global $member, $manager;
381 // check if there exists a item for this date
382 $item =& $manager->getItem($this->itemid, 0, 0);
386 return _ERROR_NOSUCHITEM;
391 return _ERROR_ITEMCLOSED;
394 # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
395 # original eregi comparison: eregi('[a-zA-Z0-9|\.,;:!\?=\/\\]{90,90}', $comment['body']) != FALSE
397 // don't allow words that are too long
398 if (preg_match('/[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}/', $comment['body']) != 0)
400 return _ERROR_COMMENT_LONGWORD;
403 // check lengths of comment
404 if (strlen($comment['body']) < 3)
406 return _ERROR_COMMENT_NOCOMMENT;
409 if (strlen($comment['body']) > 5000)
411 return _ERROR_COMMENT_TOOLONG;
414 // only check username if no member logged in
415 if (!$member->isLoggedIn() )
418 if (strlen($comment['user']) < 2)
420 return _ERROR_COMMENT_NOUSERNAME;
425 if ((strlen($comment['email']) != 0) && !(isValidMailAddress(trim($comment['email']) ) ) )
427 return _ERROR_BADMAILADDRESS;
430 // let plugins do verification (any plugin which thinks the comment is invalid
431 // can change 'error' to something other than '1')
435 'comment' => &$comment,
437 'spamcheck' => &$spamcheck
439 $manager->notify('ValidateForm', $param);