2026-05-29 00:33:00 +03:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
2026-06-01 00:24:05 +03:00
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
2026-05-29 00:33:00 +03:00
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
2026-05-30 11:23:24 +03:00
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
|
use Laravel\Scout\Searchable;
|
2026-05-29 00:33:00 +03:00
|
|
|
use Spatie\Sluggable\HasSlug;
|
|
|
|
|
use Spatie\Sluggable\SlugOptions;
|
|
|
|
|
|
|
|
|
|
class Game extends Model
|
|
|
|
|
{
|
2026-05-30 11:23:24 +03:00
|
|
|
use HasSlug, Searchable;
|
2026-05-29 00:33:00 +03:00
|
|
|
|
|
|
|
|
protected $fillable = [
|
2026-06-01 00:24:05 +03:00
|
|
|
'igdb_id', 'slug', 'title', 'summary', 'storyline', 'cover_url', 'cover_thumb_url',
|
2026-05-29 00:33:00 +03:00
|
|
|
'release_date', 'release_year', 'rating_avg', 'rating_count', 'review_count',
|
2026-06-01 00:24:05 +03:00
|
|
|
'library_count', 'status', 'collection_id', 'age_rating_pegi', 'age_rating_esrb',
|
|
|
|
|
'aggregated_rating', 'aggregated_rating_count', 'similar_game_igdb_ids',
|
2026-05-29 00:33:00 +03:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected $casts = [
|
2026-06-01 00:24:05 +03:00
|
|
|
'release_date' => 'date',
|
|
|
|
|
'rating_avg' => 'decimal:2',
|
|
|
|
|
'similar_game_igdb_ids' => 'array',
|
2026-05-29 00:33:00 +03:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
public function getSlugOptions(): SlugOptions
|
|
|
|
|
{
|
|
|
|
|
return SlugOptions::create()->generateSlugsFrom('title')->saveSlugsTo('slug');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getRouteKeyName(): string { return 'slug'; }
|
|
|
|
|
|
2026-06-01 00:24:05 +03:00
|
|
|
public function collection(): BelongsTo
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(Collection::class);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-29 00:33:00 +03:00
|
|
|
public function genres(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(Genre::class, 'game_genre');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function platforms(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(Platform::class, 'game_platform');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function companies(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(Company::class, 'game_company')->withPivot('role');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function screenshots(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(GameScreenshot::class)->orderBy('order');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function userGames(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(UserGame::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function reviews(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(Review::class)->latest();
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-30 12:02:24 +03:00
|
|
|
public function comments(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(GameComment::class);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-01 00:24:05 +03:00
|
|
|
public function gameModes(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(GameMode::class, 'game_game_mode');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function themes(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(Theme::class, 'game_theme');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function playerPerspectives(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(PlayerPerspective::class, 'game_player_perspective');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function videos(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(GameVideo::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function websites(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(GameWebsite::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function similarGames(): BelongsToMany
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsToMany(
|
|
|
|
|
Game::class,
|
|
|
|
|
'similar_games',
|
|
|
|
|
'game_id',
|
|
|
|
|
'similar_game_id'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-30 11:23:24 +03:00
|
|
|
public function toSearchableArray(): array
|
|
|
|
|
{
|
|
|
|
|
return [
|
|
|
|
|
'id' => $this->id,
|
|
|
|
|
'title' => $this->title,
|
|
|
|
|
'summary' => $this->summary,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-29 00:33:00 +03:00
|
|
|
public function scopePublished($query)
|
|
|
|
|
{
|
|
|
|
|
return $query->where('status', 'published');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function recalculateRating(): void
|
|
|
|
|
{
|
|
|
|
|
$stats = $this->userGames()->whereNotNull('rating')->selectRaw('AVG(rating) as avg, COUNT(*) as cnt')->first();
|
|
|
|
|
$this->update([
|
|
|
|
|
'rating_avg' => $stats->avg ? round($stats->avg, 2) : null,
|
|
|
|
|
'rating_count' => $stats->cnt ?? 0,
|
|
|
|
|
]);
|
2026-05-30 11:23:24 +03:00
|
|
|
|
|
|
|
|
Cache::forget('home.top_rated');
|
|
|
|
|
Cache::forget('games.top_rated.1');
|
2026-05-29 00:33:00 +03:00
|
|
|
}
|
|
|
|
|
}
|