feat(data): add review repository

This commit is contained in:
dualfroz committed 2026-08-24 12:42:00 +02:00
1 parent e2dbd78cc9
commit 0be2439890
1 file changed
+108
+108
View File
@@ -0,0 +1,108 @@
<?php
namespace Bazaar\Repositories;
use Bazaar\Core\Database;
final class ReviewRepository
{
public function __construct(private readonly Database $db)
{
}
public function create(int $productId, int $userId, int $rating, string $title, string $body): int
{
return $this->db->insert(
'INSERT INTO reviews (productId, userId, rating, title, body, status, createdAt)
VALUES (?, ?, ?, ?, ?, ?, ?)',
[$productId, $userId, $rating, $title, $body, 'pending', gmdate('c')]
);
}
public function find(int $id): ?array
{
return $this->db->selectOne('SELECT * FROM reviews WHERE id = ?', [$id]);
}
public function existsForUser(int $productId, int $userId): bool
{
return (int) $this->db->scalar(
'SELECT COUNT(*) FROM reviews WHERE productId = ? AND userId = ?',
[$productId, $userId]
) > 0;
}
public function approvedForProduct(int $productId): array
{
return $this->db->select(
'SELECT r.*, u.name AS authorName
FROM reviews r
JOIN users u ON u.id = r.userId
WHERE r.productId = ? AND r.status = ?
ORDER BY r.createdAt DESC, r.id DESC',
[$productId, 'approved']
);
}
public function summary(int $productId): array
{
$row = $this->db->selectOne(
'SELECT COUNT(*) AS reviewCount, COALESCE(AVG(rating), 0) AS average
FROM reviews WHERE productId = ? AND status = ?',
[$productId, 'approved']
);
return [
'count' => (int) $row['reviewCount'],
'average' => round((float) $row['average'], 2),
];
}
public function summaries(array $productIds): array
{
if ($productIds === []) {
return [];
}
$placeholders = implode(', ', array_fill(0, count($productIds), '?'));
$rows = $this->db->select(
"SELECT productId, COUNT(*) AS reviewCount, COALESCE(AVG(rating), 0) AS average
FROM reviews
WHERE status = 'approved' AND productId IN ({$placeholders})
GROUP BY productId",
$productIds
);
$byProduct = [];
foreach ($rows as $row) {
$byProduct[(int) $row['productId']] = [
'count' => (int) $row['reviewCount'],
'average' => round((float) $row['average'], 2),
];
}
return $byProduct;
}
public function moderationQueue(string $status = 'pending'): array
{
return $this->db->select(
'SELECT r.*, u.name AS authorName, u.email AS authorEmail, p.name AS productName, p.slug AS productSlug
FROM reviews r
JOIN users u ON u.id = r.userId
JOIN products p ON p.id = r.productId
WHERE r.status = ?
ORDER BY r.createdAt ASC, r.id ASC',
[$status]
);
}
public function setStatus(int $id, string $status): void
{
$this->db->statement(
'UPDATE reviews SET status = ?, moderatedAt = ? WHERE id = ?',
[$status, gmdate('c'), $id]
);
}
public function countByStatus(string $status): int
{
return (int) $this->db->scalar('SELECT COUNT(*) FROM reviews WHERE status = ?', [$status]);
}
}