|
2 | 2 |
|
3 | 3 | namespace Codebyray\ReviewRateable\Traits; |
4 | 4 |
|
| 5 | +use Codebyray\ReviewRateable\Models\Rating; |
5 | 6 | use Codebyray\ReviewRateable\Models\Review; |
6 | 7 | use Illuminate\Database\Eloquent\Collection; |
| 8 | +use Illuminate\Support\Facades\DB; |
7 | 9 |
|
8 | 10 | trait ReviewRateable |
9 | 11 | { |
@@ -185,6 +187,28 @@ public function getReviews(bool $approved = true, bool $withRatings = true): Col |
185 | 187 | return $query->get(); |
186 | 188 | } |
187 | 189 |
|
| 190 | + /** |
| 191 | + * Get all reviews (with attached ratings) for a department, |
| 192 | + * filtered by the approved status. |
| 193 | + * |
| 194 | + * @param string $department |
| 195 | + * @param bool $approved |
| 196 | + * @param bool $withRatings |
| 197 | + * @return Collection |
| 198 | + */ |
| 199 | + public function getReviewsByDepartment(string $department, bool $approved = true, bool $withRatings = true): Collection |
| 200 | + { |
| 201 | + $query = $this->reviews() |
| 202 | + ->where('department', $department) |
| 203 | + ->where('approved', $approved); |
| 204 | + |
| 205 | + if ($withRatings) { |
| 206 | + $query->with('ratings'); |
| 207 | + } |
| 208 | + |
| 209 | + return $query->get(); |
| 210 | + } |
| 211 | + |
188 | 212 | /** |
189 | 213 | * Calculate the average rating for a given key, filtering reviews by approval. |
190 | 214 | * |
@@ -344,4 +368,46 @@ public function deleteReview(int $reviewId): bool |
344 | 368 | return false; |
345 | 369 | } |
346 | 370 |
|
| 371 | + /** |
| 372 | + * Return an array of rating value ⇒ count, for the full model |
| 373 | + * or for a given department. |
| 374 | + * |
| 375 | + * @param string|null $department If null, counts across all departments. |
| 376 | + * @param bool $approved Only count approved reviews? |
| 377 | + * @return array [1 => 12, 2 => 5, 3 => 23, 4 => 17, 5 => 42] |
| 378 | + */ |
| 379 | + public function ratingCounts(?string $department = null, bool $approved = true): array |
| 380 | + { |
| 381 | + $min = config('review-rateable.min_rating_value', 1); |
| 382 | + $max = config('review-rateable.max_rating_value', 5); |
| 383 | + |
| 384 | + $reviewQuery = $this->reviews() |
| 385 | + ->where('approved', $approved); |
| 386 | + |
| 387 | + if ($department) { |
| 388 | + $reviewQuery->where('department', $department); |
| 389 | + } |
| 390 | + |
| 391 | + $rawCounts = Rating::select('value', DB::raw('count(*) as count')) |
| 392 | + ->whereHas('review', function ($q) use ($reviewQuery) { |
| 393 | + $sql = $reviewQuery->toBase()->getQuery()->toSql(); |
| 394 | + $bindings = $reviewQuery->getBindings(); |
| 395 | + $q->from(DB::raw("({$sql}) as reviews_sub")) |
| 396 | + ->whereColumn('reviews_sub.id', 'ratings.review_id'); |
| 397 | + foreach ($bindings as $i => $b) { |
| 398 | + $q->addBinding($b, 'where'); |
| 399 | + } |
| 400 | + }) |
| 401 | + ->groupBy('value') |
| 402 | + ->pluck('count', 'value') |
| 403 | + ->all(); |
| 404 | + |
| 405 | + $counts = []; |
| 406 | + for ($i = $min; $i <= $max; $i++) { |
| 407 | + $counts[$i] = $rawCounts[$i] ?? 0; |
| 408 | + } |
| 409 | + |
| 410 | + return $counts; |
| 411 | + } |
| 412 | + |
347 | 413 | } |
0 commit comments