db = $db; $this->notification = $notification; } public function addReview($user_id, $product_id, $rating, $comment, $images = []) { // Start transaction $this->db->begin_transaction(); try { // Add review $stmt = $this->db->prepare("INSERT INTO reviews (user_id, product_id, rating, comment, created_at) VALUES (?, ?, ?, ?, NOW())"); $stmt->bind_param('iiis', $user_id, $product_id, $rating, $comment); $stmt->execute(); $review_id = $stmt->insert_id; // Add review images if any if (!empty($images)) { $stmt = $this->db->prepare("INSERT INTO review_images (review_id, image_path) VALUES (?, ?)"); foreach ($images as $image) { $stmt->bind_param('is', $review_id, $image); $stmt->execute(); } } // Update product rating $this->updateProductRating($product_id); // Notify product owner $this->notifyProductOwner($product_id, $user_id, $rating); $this->db->commit(); return $review_id; } catch (\Exception $e) { $this->db->rollback(); throw $e; } } public function getProductReviews($product_id, $limit = 10, $offset = 0) { $stmt = $this->db->prepare(" SELECT r.*, u.username, u.avatar, GROUP_CONCAT(ri.image_path) as images FROM reviews r LEFT JOIN users u ON r.user_id = u.id LEFT JOIN review_images ri ON r.id = ri.review_id WHERE r.product_id = ? GROUP BY r.id ORDER BY r.created_at DESC LIMIT ? OFFSET ? "); $stmt->bind_param('iii', $product_id, $limit, $offset); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); } public function getUserReviews($user_id, $limit = 10, $offset = 0) { $stmt = $this->db->prepare(" SELECT r.*, p.name as product_name, p.image as product_image, GROUP_CONCAT(ri.image_path) as images FROM reviews r LEFT JOIN products p ON r.product_id = p.id LEFT JOIN review_images ri ON r.id = ri.review_id WHERE r.user_id = ? GROUP BY r.id ORDER BY r.created_at DESC LIMIT ? OFFSET ? "); $stmt->bind_param('iii', $user_id, $limit, $offset); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); } public function updateReview($review_id, $user_id, $rating, $comment, $images = []) { $this->db->begin_transaction(); try { // Update review $stmt = $this->db->prepare("UPDATE reviews SET rating = ?, comment = ?, updated_at = NOW() WHERE id = ? AND user_id = ?"); $stmt->bind_param('isii', $rating, $comment, $review_id, $user_id); $stmt->execute(); // Update images if (!empty($images)) { // Delete old images $stmt = $this->db->prepare("DELETE FROM review_images WHERE review_id = ?"); $stmt->bind_param('i', $review_id); $stmt->execute(); // Add new images $stmt = $this->db->prepare("INSERT INTO review_images (review_id, image_path) VALUES (?, ?)"); foreach ($images as $image) { $stmt->bind_param('is', $review_id, $image); $stmt->execute(); } } // Update product rating $stmt = $this->db->prepare("SELECT product_id FROM reviews WHERE id = ?"); $stmt->bind_param('i', $review_id); $stmt->execute(); $result = $stmt->get_result()->fetch_assoc(); $this->updateProductRating($result['product_id']); $this->db->commit(); return true; } catch (\Exception $e) { $this->db->rollback(); throw $e; } } public function deleteReview($review_id, $user_id) { $this->db->begin_transaction(); try { // Get product_id before deletion $stmt = $this->db->prepare("SELECT product_id FROM reviews WHERE id = ? AND user_id = ?"); $stmt->bind_param('ii', $review_id, $user_id); $stmt->execute(); $result = $stmt->get_result()->fetch_assoc(); if (!$result) { throw new \Exception('Review not found or unauthorized'); } // Delete review images $stmt = $this->db->prepare("DELETE FROM review_images WHERE review_id = ?"); $stmt->bind_param('i', $review_id); $stmt->execute(); // Delete review $stmt = $this->db->prepare("DELETE FROM reviews WHERE id = ? AND user_id = ?"); $stmt->bind_param('ii', $review_id, $user_id); $stmt->execute(); // Update product rating $this->updateProductRating($result['product_id']); $this->db->commit(); return true; } catch (\Exception $e) { $this->db->rollback(); throw $e; } } private function updateProductRating($product_id) { $stmt = $this->db->prepare(" UPDATE products p SET rating = ( SELECT AVG(rating) FROM reviews WHERE product_id = ? ) WHERE id = ? "); $stmt->bind_param('ii', $product_id, $product_id); $stmt->execute(); } private function notifyProductOwner($product_id, $reviewer_id, $rating) { $stmt = $this->db->prepare("SELECT user_id FROM products WHERE id = ?"); $stmt->bind_param('i', $product_id); $stmt->execute(); $result = $stmt->get_result()->fetch_assoc(); if ($result) { $message = $rating >= 4 ? "Someone left a positive review on your product!" : "You received a new review on your product."; $this->notification->createNotification( $result['user_id'], 'product_review', $message, [ 'product_id' => $product_id, 'reviewer_id' => $reviewer_id, 'rating' => $rating ] ); } } }