@php use App\Helpers\SchemaCollector; // Only process testimonials that have a valid linked course $validTestimonials = collect($testimonials)->filter(fn($t) => !empty(optional($t->course)->id) && !empty(optional($t->course)->title)); // Group by course to compute aggregateRating per course $byCourse = $validTestimonials->groupBy(fn($t) => $t->course->id); $reviewItems = []; foreach($validTestimonials as $testimonial) { $courseGroup = $byCourse->get($testimonial->course->id, collect([$testimonial])); $totalCount = $courseGroup->count(); $avgRating = round($courseGroup->avg(fn($t) => (int)$t->star), 1); $reviewItems[] = [ '@type' => 'Review', 'datePublished' => optional($testimonial->created_at)->format('Y-m-d') ?? now()->format('Y-m-d'), 'author' => [ '@type' => 'Person', 'name' => $testimonial->author, ], 'reviewRating' => [ '@type' => 'Rating', 'ratingValue' => (int)$testimonial->star, 'bestRating' => 5, 'worstRating' => 1, ], 'reviewBody' => $testimonial->body, // itemReviewed used internally for grouping in _schema.blade.php 'itemReviewed' => [ '@type' => 'Course', 'name' => $testimonial->course->title, 'url' => courseDetailsUrl($testimonial->course->id, $testimonial->course->type, $testimonial->course->slug), 'description' => !empty($testimonial->course->about) ? strip_tags($testimonial->course->about) : $testimonial->course->title, 'provider' => [ '@type' => 'Organization', 'name' => Settings('site_title') ?? 'Website', 'url' => url('/'), ], 'aggregateRating' => [ '@type' => 'AggregateRating', 'ratingValue' => $avgRating, 'reviewCount' => $totalCount, 'bestRating' => 5, 'worstRating' => 1, ], ], ]; } if (!empty($reviewItems)) { SchemaCollector::addReviews($reviewItems); } @endphp