Comment.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. namespace addons\blog\model;
  3. use addons\blog\library\Service;
  4. use addons\blog\library\CommentException;
  5. use app\common\library\Email;
  6. use think\Exception;
  7. use think\Model;
  8. use think\Validate;
  9. class Comment extends Model
  10. {
  11. // 表名
  12. protected $name = 'blog_comment';
  13. // 自动写入时间戳字段
  14. protected $autoWriteTimestamp = 'int';
  15. // 定义时间戳字段名
  16. protected $createTime = 'createtime';
  17. protected $updateTime = 'updatetime';
  18. // 追加属性
  19. protected $append = [
  20. 'create_date'
  21. ];
  22. protected $config;
  23. public function initialize()
  24. {
  25. $this->config = get_addon_config('blog');
  26. parent::initialize();
  27. }
  28. public function getCreateDateAttr($value, $data)
  29. {
  30. return human_date($data['createtime']);
  31. }
  32. public function getAvatarAttr($value, $data)
  33. {
  34. if ($this->config['commentavatarmode'] == 'letter') {
  35. return letter_avatar($data['username']);
  36. } else {
  37. return isset($data['avatar']) && $data['avatar'] ? $data['avatar'] : "https://secure.gravatar.com/avatar/" . md5($data['email']) . "?s=96&d=&r=X";
  38. }
  39. }
  40. public function getStatusList()
  41. {
  42. return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
  43. }
  44. public function getStatusTextAttr($value, $data)
  45. {
  46. $value = $value ? $value : $data['status'];
  47. $list = $this->getStatusList();
  48. return isset($list[$value]) ? $list[$value] : '';
  49. }
  50. public static function postComment($params)
  51. {
  52. $config = get_addon_config('blog');
  53. $request = request();
  54. $request->filter('trim,strip_tags,htmlspecialchars');
  55. $post_id = (int)$request->post("post_id");
  56. $pid = intval($request->post("pid", 0));
  57. $username = $request->post("username");
  58. $email = $request->post("email", "");
  59. $website = $request->post("website", "");
  60. $content = $request->post("content");
  61. $avatar = $request->post("avatar", "");
  62. $subscribe = intval($request->post("subscribe", 0));
  63. $useragent = substr($request->server('HTTP_USER_AGENT', ''), 0, 255);
  64. $ip = $request->ip();
  65. $website = $website != '' && substr($website, 0, 7) != 'http://' && substr($website, 0, 8) != 'https://' ? "http://" . $website : $website;
  66. $content = nl2br($content);
  67. $token = $request->post('__token__');
  68. $post = Post::get($post_id, ['category']);
  69. if (!$post || $post['status'] == 'hidden') {
  70. throw new Exception("日志未找到");
  71. }
  72. //审核状态
  73. $status = 'normal';
  74. if ($config['iscommentaudit'] == 1) {
  75. $status = 'hidden';
  76. } elseif ($config['iscommentaudit'] == 0) {
  77. $status = 'normal';
  78. } elseif ($config['iscommentaudit'] == -1) {
  79. if (!Service::isContentLegal($content)) {
  80. $status = 'hidden';
  81. }
  82. }
  83. $rule = [
  84. 'pid|父ID' => 'require|number',
  85. 'username|用户名' => 'require|chsDash|length:3,30',
  86. 'email|邮箱' => 'email|length:3,30',
  87. 'website|网站' => 'url|length:3,50',
  88. 'content|内容' => 'require|length:3,250',
  89. '__token__' => 'require|token',
  90. ];
  91. $data = [
  92. 'pid' => $pid,
  93. 'username' => $username,
  94. 'email' => $email,
  95. 'website' => $website,
  96. 'content' => $content,
  97. '__token__' => $token,
  98. ];
  99. $validate = new Validate($rule);
  100. $result = $validate->check($data);
  101. if (!$result) {
  102. throw new Exception($validate->getError());
  103. }
  104. $lastcomment = self::get(['post_id' => $post_id, 'email' => $email, 'ip' => $ip]);
  105. if ($lastcomment && time() - $lastcomment['createtime'] < 30) {
  106. throw new Exception("对不起!您发表评论的速度过快!请稍微休息一下,喝杯咖啡");
  107. }
  108. if ($lastcomment && $lastcomment['content'] == $content) {
  109. throw new Exception("您可能连续了相同的评论,请不要重复提交");
  110. }
  111. $data = [
  112. 'pid' => $pid,
  113. 'post_id' => $post_id,
  114. 'username' => $username,
  115. 'email' => $email,
  116. 'content' => $content,
  117. 'avatar' => $avatar,
  118. 'ip' => $ip,
  119. 'useragent' => $useragent,
  120. 'subscribe' => (int)$subscribe,
  121. 'website' => $website,
  122. 'status' => $status
  123. ];
  124. self::create($data);
  125. //发送通知
  126. if ($status === 'hidden') {
  127. throw new CommentException("发表评论成功,但评论需要显示审核后才会展示", 1);
  128. } else {
  129. $post->setInc('comments');
  130. if ($pid) {
  131. //查找父评论,是否并发邮件通知
  132. $parent = self::get($pid);
  133. if ($parent && $parent['subscribe'] && Validate::is($parent['email'], 'email') && $status == 'normal') {
  134. $title = "{$parent['username']},您发表在《{$post['title']}》上的评论有了新回复 - {$config['name']}";
  135. $post_url = $post->fullurl;
  136. $unsubscribe_url = addon_url("blog/comment/unsubscribe", ['id' => $parent['id'], 'key' => md5($parent['id'] . $parent['email'])]);
  137. $content = "亲爱的{$parent['username']}:<br />您于" . date("Y-m-d H:i:s") .
  138. "在《<a href='{$post_url}' target='_blank'>{$post['title']}</a>》上发表的评论<br /><blockquote>{$parent['content']}</blockquote>" .
  139. "<br />{$username}发表了回复,内容是<br /><blockquote>{$content}</blockquote><br />您可以<a href='{$post_url}'>点击查看评论详情</a>。" .
  140. "<br /><br />如果你不愿意再接受最新评论的通知,<a href='{$unsubscribe_url}'>请点击这里取消</a>";
  141. $email = new Email;
  142. $result = $email
  143. ->to($parent['email'])
  144. ->subject($title)
  145. ->message('<div style="min-height:550px; padding: 100px 55px 200px;">' . $content . '</div>')
  146. ->send();
  147. }
  148. }
  149. }
  150. return true;
  151. }
  152. public function sublist()
  153. {
  154. return $this->hasMany("Comment", "pid");
  155. }
  156. }