comment.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. /**
  3. * Comment Management Class
  4. * Handles all comment-related operations including creation, moderation, and replies
  5. */
  6. class Comment {
  7. private $db;
  8. public function __construct() {
  9. $this->db = Database::getInstance();
  10. }
  11. /**
  12. * Create a new comment
  13. */
  14. public function create($data) {
  15. $sql = "INSERT INTO comments (publication_id, parent_id, name, email, content, ip_address, user_agent)
  16. VALUES (?, ?, ?, ?, ?, ?, ?)";
  17. return $this->db->execute($sql, [
  18. $data['publication_id'],
  19. $data['parent_id'] ?? null,
  20. $data['name'],
  21. $data['email'] ?? null,
  22. $data['content'],
  23. $_SERVER['REMOTE_ADDR'] ?? null,
  24. $_SERVER['HTTP_USER_AGENT'] ?? null
  25. ]);
  26. }
  27. /**
  28. * Create an admin reply (bypasses captcha, auto-approved)
  29. */
  30. public function createAdminReply($data) {
  31. $sql = "INSERT INTO comments (publication_id, parent_id, name, content, status, admin_reply, replied_by)
  32. VALUES (?, ?, ?, ?, 'approved', TRUE, ?)";
  33. return $this->db->execute($sql, [
  34. $data['publication_id'],
  35. $data['parent_id'],
  36. $data['name'] ?? 'Admin',
  37. $data['content'],
  38. $data['replied_by']
  39. ]);
  40. }
  41. /**
  42. * Get approved comments for a publication
  43. */
  44. public function getApprovedByPublication($publicationId) {
  45. $sql = "SELECT c.*, u.username as replied_by_username
  46. FROM comments c
  47. LEFT JOIN users u ON c.replied_by = u.id
  48. WHERE c.publication_id = ? AND c.status = 'approved'
  49. ORDER BY c.created_at ASC";
  50. return $this->db->fetchAll($sql, [$publicationId]);
  51. }
  52. /**
  53. * Get all comments for admin (including pending)
  54. */
  55. public function getAll($status = null, $limit = 50, $offset = 0) {
  56. $sql = "SELECT c.*, p.title as publication_title, u.username as replied_by_username
  57. FROM comments c
  58. LEFT JOIN publications p ON c.publication_id = p.id
  59. LEFT JOIN users u ON c.replied_by = u.id";
  60. $params = [];
  61. if ($status) {
  62. $sql .= " WHERE c.status = ?";
  63. $params[] = $status;
  64. }
  65. $sql .= " ORDER BY c.created_at DESC LIMIT ? OFFSET ?";
  66. $params[] = $limit;
  67. $params[] = $offset;
  68. return $this->db->fetchAll($sql, $params);
  69. }
  70. /**
  71. * Get comment by ID
  72. */
  73. public function getById($id) {
  74. $sql = "SELECT c.*, p.title as publication_title, u.username as replied_by_username
  75. FROM comments c
  76. LEFT JOIN publications p ON c.publication_id = p.id
  77. LEFT JOIN users u ON c.replied_by = u.id
  78. WHERE c.id = ?";
  79. return $this->db->fetch($sql, [$id]);
  80. }
  81. /**
  82. * Update comment status (approve/reject)
  83. */
  84. public function updateStatus($id, $status) {
  85. $sql = "UPDATE comments SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?";
  86. return $this->db->execute($sql, [$status, $id]);
  87. }
  88. /**
  89. * Delete a comment
  90. */
  91. public function delete($id) {
  92. $sql = "DELETE FROM comments WHERE id = ?";
  93. return $this->db->execute($sql, [$id]);
  94. }
  95. /**
  96. * Get comment count by status
  97. */
  98. public function getCountByStatus($status = null) {
  99. if ($status) {
  100. $sql = "SELECT COUNT(*) as count FROM comments WHERE status = ?";
  101. $result = $this->db->fetch($sql, [$status]);
  102. } else {
  103. $sql = "SELECT COUNT(*) as count FROM comments";
  104. $result = $this->db->fetch($sql);
  105. }
  106. return $result['count'];
  107. }
  108. /**
  109. * Get comment count for a publication
  110. */
  111. public function getCountByPublication($publicationId) {
  112. $sql = "SELECT COUNT(*) as count FROM comments
  113. WHERE publication_id = ? AND status = 'approved'";
  114. $result = $this->db->fetch($sql, [$publicationId]);
  115. return $result['count'];
  116. }
  117. /**
  118. * Validate comment data
  119. */
  120. public function validate($data, $isAdmin = false) {
  121. $errors = [];
  122. // Common validations
  123. if (empty($data['content'])) {
  124. $errors[] = 'Comment content is required';
  125. } elseif (strlen($data['content']) > 2000) {
  126. $errors[] = 'Comment content is too long (max 2000 characters)';
  127. }
  128. if (empty($data['publication_id'])) {
  129. $errors[] = 'Publication ID is required';
  130. }
  131. // Public user validations (not for admin)
  132. if (!$isAdmin) {
  133. if (empty($data['name'])) {
  134. $errors[] = 'Name is required';
  135. } elseif (strlen($data['name']) > 100) {
  136. $errors[] = 'Name is too long (max 100 characters)';
  137. }
  138. if (!empty($data['email']) && !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
  139. $errors[] = 'Invalid email address';
  140. }
  141. }
  142. return $errors;
  143. }
  144. /**
  145. * Check if user can reply to comment
  146. */
  147. public function canReply($commentId, $userId) {
  148. // Admins can reply to any comment
  149. if ($userId) {
  150. $userSql = "SELECT role FROM users WHERE id = ?";
  151. $user = $this->db->fetch($userSql, [$userId]);
  152. if ($user && $user['role'] === 'admin') {
  153. return true;
  154. }
  155. }
  156. // Check if this is a reply to own comment (for future enhancement)
  157. $commentSql = "SELECT user_id FROM comments WHERE id = ?";
  158. $comment = $this->db->fetch($commentSql, [$commentId]);
  159. return false; // Only admins can reply for now
  160. }
  161. /**
  162. * Get recent comments for admin dashboard
  163. */
  164. public function getRecent($limit = 10) {
  165. $sql = "SELECT c.*, p.title as publication_title
  166. FROM comments c
  167. LEFT JOIN publications p ON c.publication_id = p.id
  168. ORDER BY c.created_at DESC
  169. LIMIT ?";
  170. return $this->db->fetchAll($sql, [$limit]);
  171. }
  172. /**
  173. * Get pending comments count
  174. */
  175. public function getPendingCount() {
  176. return $this->getCountByStatus('pending');
  177. }
  178. }