@@ -168,47 +168,6 @@ public function approveReview(int $reviewId): bool
168168 return $ review ->update (['approved ' => true ]);
169169 }
170170
171- /**
172- * Get all reviews (with attached ratings) for the model,
173- * filtered by the approved status.
174- *
175- * @param bool $approved
176- * @param bool $withRatings
177- * @return Collection
178- */
179- public function getReviews (bool $ approved = true , bool $ withRatings = true ): Collection
180- {
181- $ query = $ this ->reviews ()->where ('approved ' , $ approved );
182-
183- if ($ withRatings ) {
184- $ query ->with ('ratings ' );
185- }
186-
187- return $ query ->get ();
188- }
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-
212171 /**
213172 * Calculate the average rating for a given key, filtering reviews by approval.
214173 *
@@ -321,6 +280,47 @@ public function averageRatingsByDepartment(string $department, bool $approved =
321280 return $ averages ;
322281 }
323282
283+ /**
284+ * Get all reviews (with attached ratings) for the model,
285+ * filtered by the approved status.
286+ *
287+ * @param bool $approved
288+ * @param bool $withRatings
289+ * @return Collection
290+ */
291+ public function getReviews (bool $ approved = true , bool $ withRatings = true ): Collection
292+ {
293+ $ query = $ this ->reviews ()->where ('approved ' , $ approved );
294+
295+ if ($ withRatings ) {
296+ $ query ->with ('ratings ' );
297+ }
298+
299+ return $ query ->get ();
300+ }
301+
302+ /**
303+ * Get all reviews (with attached ratings) for a department,
304+ * filtered by the approved status.
305+ *
306+ * @param string $department
307+ * @param bool $approved
308+ * @param bool $withRatings
309+ * @return Collection
310+ */
311+ public function getReviewsByDepartment (string $ department , bool $ approved = true , bool $ withRatings = true ): Collection
312+ {
313+ $ query = $ this ->reviews ()
314+ ->where ('department ' , $ department )
315+ ->where ('approved ' , $ approved );
316+
317+ if ($ withRatings ) {
318+ $ query ->with ('ratings ' );
319+ }
320+
321+ return $ query ->get ();
322+ }
323+
324324 /**
325325 * Get the total number of reviews for the model.
326326 *
@@ -333,8 +333,9 @@ public function totalReviews(bool $approved = true): int
333333 }
334334
335335 /**
336- * Get the total number of reviews for the model.
336+ * Get the total number of reviews for the model by department .
337337 *
338+ * @param string $department
338339 * @param bool $approved
339340 * @return int
340341 */
@@ -419,4 +420,56 @@ public function ratingCounts(?string $department = null, bool $approved = true):
419420
420421 return $ counts ;
421422 }
423+
424+ /**
425+ * Return an array with:
426+ * • counts: [1 => x, 2 => y, …, 5 => z]
427+ * • percentages: [1 => pct1, …, 5 => pct5]
428+ * • total: total number of ratings
429+ *
430+ * @param string|null $department
431+ * @param bool $approved
432+ * @return array
433+ */
434+ public function ratingStats (?string $ department = null , bool $ approved = true ): array
435+ {
436+ $ min = config ('review-rateable.min_rating_value ' , 1 );
437+ $ max = config ('review-rateable.max_rating_value ' , 5 );
438+ $ reviewTable = (new Review )->getTable ();
439+ $ ratingTable = (new Rating )->getTable ();
440+
441+ // base query: gives you value => count
442+ $ raw = Rating::select ("{$ ratingTable }.value " , DB ::raw ('COUNT(*) as count ' ))
443+ ->join ($ reviewTable , "{$ ratingTable }.review_id " , '= ' , "{$ reviewTable }.id " )
444+ ->where ("{$ reviewTable }.reviewable_type " , $ this ->getMorphClass ())
445+ ->where ("{$ reviewTable }.reviewable_id " , $ this ->getKey ())
446+ ->where ("{$ reviewTable }.approved " , $ approved )
447+ ->when ($ department , fn ($ q ) => $ q ->where ("{$ reviewTable }.department " , $ department ))
448+ ->groupBy ("{$ ratingTable }.value " )
449+ ->pluck ('count ' , 'value ' )
450+ ->all ();
451+
452+ // zero-fill missing star values
453+ $ counts = [];
454+ for ($ i = $ min ; $ i <= $ max ; $ i ++) {
455+ $ counts [$ i ] = $ raw [$ i ] ?? 0 ;
456+ }
457+
458+ // total number of ratings
459+ $ total = array_sum ($ counts );
460+
461+ // percentages (integer 0–100)
462+ $ percentages = [];
463+ foreach ($ counts as $ star => $ count ) {
464+ $ percentages [$ star ] = $ total
465+ ? round (($ count / $ total ) * 100 )
466+ : 0 ;
467+ }
468+
469+ return [
470+ 'counts ' => $ counts ,
471+ 'percentages ' => $ percentages ,
472+ 'total ' => $ total ,
473+ ];
474+ }
422475}
0 commit comments