143 lines
4.4 KiB
PHP
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');
|
|
}
|
|
}
|