OSDN Git Service

本家Nucleus CMS 4.0のリビジョン1626をコミット
[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          * Adds a new comment to the database
136          * @param string $timestamp
137          * @param array $comment
138          * @return mixed
139          */
140         function addComment($timestamp, $comment)
141         {
142                 global $CONF, $member, $manager;
143
144                 $blogid = getBlogIDFromItemID($this->itemid);
145
146                 $settings =& $manager->getBlog($blogid);
147                 $settings->readSettings();
148
149                 // begin if: comments disabled
150                 if ( !$settings->commentsEnabled() )
151                 {
152                         return _ERROR_COMMENTS_DISABLED;
153                 } // end if
154
155                 // begin if: public cannot comment
156                 if ( !$settings->isPublic() && !$member->isLoggedIn() )
157                 {
158                         return _ERROR_COMMENTS_NONPUBLIC;
159                 } // end if
160
161                 // begin if: comment uses a protected member name
162                 if ( $CONF['ProtectMemNames'] && !$member->isLoggedIn() && MEMBER::isNameProtected($comment['user']) )
163                 {
164                         return _ERROR_COMMENTS_MEMBERNICK;
165                 } // end if
166
167                 // begin if: email required, but missing (doesn't apply to members)
168                 if ( $settings->emailRequired() && i18n::strlen($comment['email']) == 0 && !$member->isLoggedIn() )
169                 {
170                         return _ERROR_EMAIL_REQUIRED;
171                 } // end if
172                 
173                 // begin if: commenter's name is too long
174                 if ( i18n::strlen($comment['user']) > 40 )
175                 {
176                         return _ERROR_USER_TOO_LONG;
177                 } // end if
178                 
179                 // begin if: commenter's email is too long
180                 if ( i18n::strlen($comment['email']) > 100 )
181                 {
182                         return _ERROR_EMAIL_TOO_LONG;
183                 } // end if
184                 
185                 // begin if: commenter's url is too long
186                 if ( i18n::strlen($comment['userid']) > 100 )
187                 {
188                         return _ERROR_URL_TOO_LONG;
189                 } // end if
190                 
191                 $comment['timestamp'] = $timestamp;
192                 $comment['host'] = gethostbyaddr(serverVar('REMOTE_ADDR') );
193                 $comment['ip'] = serverVar('REMOTE_ADDR');
194                 
195                 // begin if: member is logged in, use that data
196                 if ( $member->isLoggedIn() )
197                 {
198                         $comment['memberid'] = $member->getID();
199                         $comment['user'] = '';
200                         $comment['userid'] = '';
201                         $comment['email'] = '';
202                 }
203                 else
204                 {
205                         $comment['memberid'] = 0;
206                 }
207                 
208                 // spam check
209                 $continue = FALSE;
210                 $plugins = array();
211                 
212                 if ( isset($manager->subscriptions['ValidateForm']) )
213                 {
214                         $plugins = array_merge($plugins, $manager->subscriptions['ValidateForm']);
215                 }
216                 
217                 if ( isset($manager->subscriptions['PreAddComment']) )
218                 {
219                         $plugins = array_merge($plugins, $manager->subscriptions['PreAddComment']);
220                 }
221                 
222                 if ( isset($manager->subscriptions['PostAddComment']) )
223                 {
224                         $plugins = array_merge($plugins, $manager->subscriptions['PostAddComment']);
225                 }
226                 
227                 $plugins = array_unique($plugins);
228                 
229                 while ( list(, $plugin) = each($plugins) )
230                 {
231                         $p = $manager->getPlugin($plugin);
232                         $continue = $continue || $p->supportsFeature('handleSpam');
233                 }
234
235                 $spamcheck = array(
236                         'type'          => 'comment',
237                         'body'          => $comment['body'],
238                         'id'        => $comment['itemid'],
239                         'live'          => TRUE,
240                         'return'        => $continue
241                 );
242
243                 // begin if: member logged in
244                 if ( $member->isLoggedIn() )
245                 {
246                         $spamcheck['author'] = $member->displayname;
247                         $spamcheck['email'] = $member->email;
248                 }
249                 // else: public
250                 else
251                 {
252                         $spamcheck['author'] = $comment['user'];
253                         $spamcheck['email'] = $comment['email'];
254                         $spamcheck['url'] = $comment['userid'];
255                 } // end if
256
257                 $manager->notify('SpamCheck', array('spamcheck' => &$spamcheck) );
258
259                 if ( !$continue && isset($spamcheck['result']) && $spamcheck['result'] == TRUE )
260                 {
261                         return _ERROR_COMMENTS_SPAM;
262                 }
263
264                 // isValidComment returns either "1" or an error message
265                 $isvalid = $this->isValidComment($comment, $spamcheck);
266
267                 if ( $isvalid != 1 )
268                 {
269                         return $isvalid;
270                 }
271
272                 // begin if: send email to notification address
273                 if ( $settings->getNotifyAddress() && $settings->notifyOnComment() )
274                 {
275
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']);
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          * Checks if a comment is valid and call plugins
366          * that can check if the comment is a spam comment        
367          */
368         function isValidComment(&$comment, &$spamcheck) {
369
370                 global $member, $manager;
371
372                 // check if there exists a item for this date
373                 $item =& $manager->getItem($this->itemid, 0, 0);
374
375                 if (!$item)
376                 {
377                         return _ERROR_NOSUCHITEM;
378                 }
379
380                 if ($item['closed'])
381                 {
382                         return _ERROR_ITEMCLOSED;
383                 }
384
385                 # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
386                 # original eregi comparison: eregi('[a-zA-Z0-9|\.,;:!\?=\/\\]{90,90}', $comment['body']) != FALSE
387
388                 // don't allow words that are too long
389                 if (preg_match('/[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}/', $comment['body']) != 0)
390                 {
391                         return _ERROR_COMMENT_LONGWORD;
392                 }
393
394                 // check lengths of comment
395                 if (i18n::strlen($comment['body']) < 3)
396                 {
397                         return _ERROR_COMMENT_NOCOMMENT;
398                 }
399
400                 if (i18n::strlen($comment['body']) > 5000)
401                 {
402                         return _ERROR_COMMENT_TOOLONG;
403                 }
404
405                 // only check username if no member logged in
406                 if (!$member->isLoggedIn() )
407                 {
408
409                         if (i18n::strlen($comment['user']) < 2)
410                         {
411                                 return _ERROR_COMMENT_NOUSERNAME;
412                         }
413
414                 }
415
416                 if ((i18n::strlen($comment['email']) != 0) && !(isValidMailAddress(trim($comment['email']) ) ) )
417                 {
418                         return _ERROR_BADMAILADDRESS;
419                 }
420
421                 // let plugins do verification (any plugin which thinks the comment is invalid
422                 // can change 'error' to something other than '1')
423                 $result = 1;
424                 $manager->notify('ValidateForm', array('type' => 'comment', 'comment' => &$comment, 'error' => &$result, 'spamcheck' => &$spamcheck) );
425
426                 return $result;
427         }
428
429 }
430
431 ?>