ldc-legaulois/app/Models/Rating.php
2025-06-24 15:53:57 +02:00

143 lines
4.4 KiB
PHP

<?php
namespace App\Models;
use App\Enums\RatingEnum;
use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Spatie\SchemaOrg\Schema;
/**
* @property \App\Models\Customer $customer_id Rating associated customer.
* @property integer $rating_id Rating key of the associated model.
* @property \App\Enums\RatingEnum $rate Rating note (Enum RatingEnum).
* @property string $rating_type Rating associated model.
* @property string $customer_username Rating customer author.
* @property \Carbon\Carbon $created_at Created date.
* @property \Carbon\Carbon $updated_at Updated date.
*
* @property-read \App\Models\Product $products Product polymorphic relationship.
*/
class Rating extends Model
{
use ActivityLog;
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'customer_id',
'rating_id',
'rate',
'rating_type',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'rate' => RatingEnum::class,
];
// * METHODS
/**
* Get all ratings data.
*
* @param \App\Models\Product|\App\Models\Recipe $model
* @return array
*/
public static function resetCache(Product|Recipe $model): array
{
Cache::forget(sprintf('%s-ratings', $model->slug));
return self::getRatings($model);
}
/**
* Get all ratings data.
*
* @param \App\Models\Product|\App\Models\Recipe $model
* @return array
*/
public static function getRatings(Product|Recipe $model): array
{
return Cache::remember(sprintf('%s-ratings', $model->slug), 86400, function () use ($model) {
/** @var \App\Models\Customer|null customerModel */
$customerModel = auth('club')->user();
return [
'total' => $model->ratings()->count(),
'totalRate' => round($model->ratings()->get()->avg(function (Rating $model) {
return $model->rate->value();
}), 1),
'ratings' => $model->ratings()->inRandomOrder()
->take(6)->with('customer')->get()->each(function (Rating $rating) {
$rating->customer_username = $rating->customer->username;
return $rating;
}),
'ratingType' => get_class($model),
'customerRating' => $customerModel
? $model->ratings()->where('customer_id', $customerModel->getkey())->first()
: null,
];
});
}
/**
* Create a SchemaOrg.
*
* @param \Illuminate\Support\Collection $modelCollection
* @return \Spatie\SchemaOrg\AggregateRating
*/
public static function toSchemaOrg(Collection $modelCollection): \Spatie\SchemaOrg\AggregateRating
{
return Schema::aggregateRating()
->ratingValue(self::getAverageRating($modelCollection))
->bestRating(5)
->worstRating(1)
->ratingCount($modelCollection->count());
}
/**
* Calculate and return the average rating of rating collection.
*
* @param \Illuminate\Support\Collection $modelCollection
* @return float
*/
public static function getAverageRating(Collection $modelCollection): float
{
return round($modelCollection->avg(function (Rating $model) {
return $model->rate->value();
}), 1);
}
// * RELATIONSHIPS
/**
* Get all of the products that are favorite by this customer.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function customer(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Customer::class);
}
/**
* Get the parent rateable model (Product or Recipe).
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function model(): \Illuminate\Database\Eloquent\Relations\MorphTo
{
return $this->morphTo('rating');
}
}