OSDN Git Service

code cleanup for my next commit
[nucleus-jp/nucleus-next.git] / nucleus / libs / COMMENTS.php
1 <?php
2
3 /*
4  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
5  * Copyright (C) 2002-2009 The Nucleus Group
6  *
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)
12  */
13 /**
14  * A class representing the comments (all of them) for a certain post on a ceratin blog
15  *
16  * @license http://nucleuscms.org/license.txt GNU General Public License
17  * @copyright Copyright (C) 2002-2009 The Nucleus Group
18  * @version $Id: COMMENTS.php 1527 2011-06-21 10:43:44Z sakamocchi $
19  */
20
21 if ( !function_exists('requestVar') ) exit;
22 require_once dirname(__FILE__) . '/COMMENTACTIONS.php';
23
24 class COMMENTS {
25
26         // item for which comment are being displayed
27         var $itemid;
28
29         // reference to the itemActions object that is calling the showComments function
30         var $itemActions;
31
32         // total amount of comments displayed
33         var $commentcount;
34
35         /**
36          * Creates a new COMMENTS object for the given blog and item
37          *
38          * @param $itemid
39          *              id of the item
40          */
41         function COMMENTS($itemid) {
42                 $this->itemid = intval($itemid);
43         }
44         
45         /**
46          * Used when parsing comments
47          *
48          * @param $itemActions
49          *              itemActions object, that will take care of the parsing
50          */
51         function setItemActions(&$itemActions) {
52                 $this->itemActions =& $itemActions;
53         }
54
55         /**
56          * Shows maximum $max comments to the given item using the given template
57          * returns the amount of shown comments (if maxToShow = -1, then there is no limit)
58          *
59          * @param template
60          *              template to use
61          * @param maxToShow
62          *              max. comments to show
63          * @param showNone
64          *              indicates if the 'no comments' thingie should be outputted when there are no comments
65          *              (useful for closed items)
66          * @param highlight
67          *              Highlight to use (if any)
68          */
69         function showComments($template, $maxToShow = -1, $showNone = 1, $highlight = '') {
70                 global $CONF, $manager;
71
72                 // create parser object & action handler
73                 $actions = new COMMENTACTIONS($this);
74                 $parser = new PARSER($actions->getDefinedActions(),$actions);
75                 $actions->setTemplate($template);
76                 $actions->setParser($parser);
77
78                 if ($maxToShow == 0) {
79                         $this->commentcount = $this->amountComments();
80                 } else {
81                         $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'
82                                    . ' FROM '.sql_table('comment').' as c'
83                                    . ' WHERE c.citem=' . $this->itemid
84                                    . ' ORDER BY c.ctime';
85
86                         $comments = sql_query($query);
87                         $this->commentcount = sql_num_rows($comments);
88                 }
89
90                 // if no result was found
91                 if ($this->commentcount == 0) {
92                         // note: when no reactions, COMMENTS_HEADER and COMMENTS_FOOTER are _NOT_ used
93                         if ($showNone) $parser->parse($template['COMMENTS_NONE']);
94                         return 0;
95                 }
96
97                 // if too many comments to show
98                 if (($maxToShow != -1) && ($this->commentcount > $maxToShow)) {
99                         $parser->parse($template['COMMENTS_TOOMUCH']);
100                         return 0;
101                 }
102
103                 $parser->parse($template['COMMENTS_HEADER']);
104
105                 while ( $comment = sql_fetch_assoc($comments) ) {
106                         $comment['timestamp'] = strtotime($comment['ctime']);
107                         $actions->setCurrentComment($comment);
108                         $actions->setHighlight($highlight);
109                         $manager->notify('PreComment', array('comment' => &$comment));
110                         $parser->parse($template['COMMENTS_BODY']);
111                         $manager->notify('PostComment', array('comment' => &$comment));
112                 }
113
114                 $parser->parse($template['COMMENTS_FOOTER']);
115
116                 sql_free_result($comments);
117
118                 return $this->commentcount;
119         }
120
121         /**
122          * Returns the amount of comments for this itemid
123          */
124         function amountComments() {
125                 $query =  'SELECT COUNT(*)'
126                            . ' FROM '.sql_table('comment').' as c'
127                            . ' WHERE c.citem='. $this->itemid;
128                 $res = sql_query($query);
129                 $arr = sql_fetch_row($res);
130
131                 return $arr[0];
132         }
133
134         /**
135          * COMMENTS::addComment()
136          * Adds a new comment to the database
137          * 
138          * @param string $timestamp
139          * @param array $comment
140          * @return mixed
141          */
142         function addComment($timestamp, $comment)
143         {
144                 global $CONF, $member, $manager;
145                 
146                 $blogid = getBlogIDFromItemID($this->itemid);
147                 
148                 $settings =& $manager->getBlog($blogid);
149                 $settings->readSettings();
150                 
151                 // begin if: comments disabled
152                 if ( !$settings->commentsEnabled() )
153                 {
154                         return _ERROR_COMMENTS_DISABLED;
155                 }
156                 
157                 // begin if: public cannot comment
158                 if ( !$settings->isPublic() && !$member->isLoggedIn() )
159                 {
160                         return _ERROR_COMMENTS_NONPUBLIC;
161                 }
162                 
163                 // begin if: comment uses a protected member name
164                 if ( $CONF['ProtectMemNames'] && !$member->isLoggedIn() && MEMBER::isNameProtected($comment['user']) )
165                 {
166                         return _ERROR_COMMENTS_MEMBERNICK;
167                 }
168                 
169                 // begin if: email required, but missing (doesn't apply to members)
170                 if ( $settings->emailRequired() && i18n::strlen($comment['email']) == 0 && !$member->isLoggedIn() )
171                 {
172                         return _ERROR_EMAIL_REQUIRED;
173                 }
174                 
175                 // begin if: commenter's name is too long
176                 if ( i18n::strlen($comment['user']) > 40 )
177                 {
178                         return _ERROR_USER_TOO_LONG;
179                 }
180                 
181                 // begin if: commenter's email is too long
182                 if ( i18n::strlen($comment['email']) > 100 )
183                 {
184                         return _ERROR_EMAIL_TOO_LONG;
185                 }
186                 
187                 // begin if: commenter's url is too long
188                 if ( i18n::strlen($comment['userid']) > 100 )
189                 {
190                         return _ERROR_URL_TOO_LONG;
191                 }
192                 
193                 $comment['timestamp'] = $timestamp;
194                 $comment['host'] = gethostbyaddr(serverVar('REMOTE_ADDR') );
195                 $comment['ip'] = serverVar('REMOTE_ADDR');
196                 
197                 // begin if: member is logged in, use that data
198                 if ( $member->isLoggedIn() )
199                 {
200                         $comment['memberid'] = $member->getID();
201                         $comment['user'] = '';
202                         $comment['userid'] = '';
203                         $comment['email'] = '';
204                 }
205                 else
206                 {
207                         $comment['memberid'] = 0;
208                 }
209                 
210                 // spam check
211                 $continue = FALSE;
212                 $plugins = array();
213                 
214                 if ( isset($manager->subscriptions['ValidateForm']) )
215                 {
216                         $plugins = array_merge($plugins, $manager->subscriptions['ValidateForm']);
217                 }
218                 
219                 if ( isset($manager->subscriptions['PreAddComment']) )
220                 {
221                         $plugins = array_merge($plugins, $manager->subscriptions['PreAddComment']);
222                 }
223                 
224                 if ( isset($manager->subscriptions['PostAddComment']) )
225                 {
226                         $plugins = array_merge($plugins, $manager->subscriptions['PostAddComment']);
227                 }
228                 
229                 $plugins = array_unique($plugins);
230                 
231                 while ( list(, $plugin) = each($plugins) )
232                 {
233                         $p = $manager->getPlugin($plugin);
234                         $continue = $continue || $p->supportsFeature('handleSpam');
235                 }
236
237                 $spamcheck = array(
238                         'type'          => 'comment',
239                         'body'          => $comment['body'],
240                         'id'        => $comment['itemid'],
241                         'live'          => TRUE,
242                         'return'        => $continue
243                 );
244                 
245                 // begin if: member logged in
246                 if ( $member->isLoggedIn() )
247                 {
248                         $spamcheck['author'] = $member->displayname;
249                         $spamcheck['email'] = $member->email;
250                 }
251                 // else: public
252                 else
253                 {
254                         $spamcheck['author'] = $comment['user'];
255                         $spamcheck['email'] = $comment['email'];
256                         $spamcheck['url'] = $comment['userid'];
257                 }
258                 
259                 $manager->notify('SpamCheck', array('spamcheck' => &$spamcheck) );
260                 
261                 if ( !$continue && isset($spamcheck['result']) && $spamcheck['result'] == TRUE )
262                 {
263                         return _ERROR_COMMENTS_SPAM;
264                 }
265                 
266                 // isValidComment returns either "1" or an error message
267                 $isvalid = $this->isValidComment($comment, $spamcheck);
268                 
269                 if ( $isvalid != 1 )
270                 {
271                         return $isvalid;
272                 }
273                 
274                 // begin if: send email to notification address
275                 if ( $settings->getNotifyAddress() && $settings->notifyOnComment() )
276                 {
277                         $mailto_msg = _NOTIFY_NC_MSG . ' ' . $this->itemid . "\n";
278                         $temp = parse_url($CONF['Self']);
279                         
280                         if ( $temp['scheme'] )
281                         {
282                                 $mailto_msg .= createItemLink($this->itemid) . "\n\n";
283                         }
284                         else
285                         {
286                                 $tempurl = $settings->getURL();
287                                 
288                                 if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' )
289                                 {
290                                         $mailto_msg .= $tempurl . '?itemid=' . $this->itemid . "\n\n";
291                                 }
292                                 else
293                                 {
294                                         $mailto_msg .= $tempurl . '/?itemid=' . $this->itemid . "\n\n";
295                                 }
296                         }
297                         
298                         if ( $comment['memberid'] == 0 )
299                         {
300                                 $mailto_msg .= _NOTIFY_USER . ' ' . $comment['user'] . "\n";
301                                 $mailto_msg .= _NOTIFY_USERID . ' ' . $comment['userid'] . "\n";
302                         }
303                         else
304                         {
305                                 $mailto_msg .= _NOTIFY_MEMBER .' ' . $member->getDisplayName() . ' (ID=' . $member->getID() . ")\n";
306                         }
307                         
308                         $mailto_msg .= _NOTIFY_HOST . ' ' . $comment['host'] . "\n";
309                         $mailto_msg .= _NOTIFY_COMMENT . "\n " . $comment['body'] . "\n";
310                         $mailto_msg .= getMailFooter();
311                         
312                         $item =& $manager->getItem($this->itemid, 0, 0);
313                         $mailto_title = _NOTIFY_NC_TITLE . ' ' . strip_tags($item['title']) . ' (' . $this->itemid . ')';
314                         
315                         $frommail = $member->getNotifyFromMailAddress($comment['email']);
316                         
317                         $notify = new NOTIFICATION($settings->getNotifyAddress() );
318                         $notify->notify($mailto_title, $mailto_msg , $frommail);
319                 }
320                 
321                 $comment = COMMENT::prepare($comment);
322                 
323                 $manager->notify('PreAddComment', array('comment' => &$comment, 'spamcheck' => &$spamcheck) );
324                 
325                 $name           = sql_real_escape_string($comment['user']);
326                 $url            = sql_real_escape_string($comment['userid']);
327                 $email      = sql_real_escape_string($comment['email']);
328                 $body           = sql_real_escape_string($comment['body']);
329                 $host           = sql_real_escape_string($comment['host']);
330                 $ip                     = sql_real_escape_string($comment['ip']);
331                 $memberid       = intval($comment['memberid']);
332                 $timestamp      = date('Y-m-d H:i:s', $comment['timestamp']);
333                 $itemid         = $this->itemid;
334                 
335                 $qSql       = 'SELECT COUNT(*) AS result '
336                                         . 'FROM ' . sql_table('comment')
337                                         . ' WHERE '
338                                         .      'cmail   = "' . $url . '"'
339                                         . ' AND cmember = "' . $memberid . '"'
340                                         . ' AND cbody   = "' . $body . '"'
341                                         . ' AND citem   = "' . $itemid . '"'
342                                         . ' AND cblog   = "' . $blogid . '"';
343                 $result     = (integer) quickQuery($qSql);
344                 
345                 if ( $result > 0 )
346                 {
347                         return _ERROR_BADACTION;
348                 }
349                 
350                 $query = 'INSERT INTO '.sql_table('comment').' (CUSER, CMAIL, CEMAIL, CMEMBER, CBODY, CITEM, CTIME, CHOST, CIP, CBLOG) '
351                            . "VALUES ('$name', '$url', '$email', $memberid, '$body', $itemid, '$timestamp', '$host', '$ip', '$blogid')";
352                 
353                 sql_query($query);
354                 
355                 // post add comment
356                 $commentid = sql_insert_id();
357                 $manager->notify('PostAddComment', array('comment' => &$comment, 'commentid' => &$commentid, 'spamcheck' => &$spamcheck) );
358                 
359                 // succeeded !
360                 return TRUE;
361         }
362
363
364         /**
365          * COMMENTS::isValidComment()
366          * Checks if a comment is valid and call plugins
367          * that can check if the comment is a spam comment        
368          * 
369          * @param       Array   $comment        array with comment elements
370          * @param       Array   $spamcheck      array with spamcheck elements
371          */
372         function isValidComment(&$comment, &$spamcheck)
373         {
374                 global $member, $manager;
375                 
376                 // check if there exists a item for this date
377                 $item =& $manager->getItem($this->itemid, 0, 0);
378                 
379                 if ( !$item )
380                 {
381                         return _ERROR_NOSUCHITEM;
382                 }
383                 
384                 if ( $item['closed'] )
385                 {
386                         return _ERROR_ITEMCLOSED;
387                 }
388                 
389                 // don't allow words that are too long
390                 if ( preg_match('/[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}/', $comment['body']) != 0 )
391                 {
392                         return _ERROR_COMMENT_LONGWORD;
393                 }
394                 
395                 // check lengths of comment
396                 if ( i18n::strlen($comment['body']) < 3 )
397                 {
398                         return _ERROR_COMMENT_NOCOMMENT;
399                 }
400                 
401                 if ( i18n::strlen($comment['body']) > 5000 )
402                 {
403                         return _ERROR_COMMENT_TOOLONG;
404                 }
405                 
406                 // only check username if no member logged in
407                 if ( !$member->isLoggedIn() && (i18n::strlen($comment['user']) < 2) )
408                 {
409                         return _ERROR_COMMENT_NOUSERNAME;
410                 }
411                 
412                 if ( (i18n::strlen($comment['email']) != 0) && !isValidMailAddress(trim($comment['email'])) )
413                 {
414                         return _ERROR_BADMAILADDRESS;
415                 }
416                 
417                 // let plugins do verification (any plugin which thinks the comment is invalid
418                 // can change 'error' to something other than '1')
419                 $result = 1;
420                 $manager->notify('ValidateForm', array('type' => 'comment', 'comment' => &$comment, 'error' => &$result, 'spamcheck' => &$spamcheck) );
421                 
422                 return $result;
423         }
424 }