Files
thrillwiki_laravel/app/Models/Park.php

183 lines
4.6 KiB
PHP

<?php
namespace App\Models;
use App\Enums\ParkStatus;
use App\Traits\HasLocation;
use App\Traits\HasSlugHistory;
use App\Traits\HasParkStatistics;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Park extends Model
{
use HasFactory, HasSlugHistory, HasParkStatistics, HasLocation;
/**
* The attributes that are mass assignable.
*
* @var array<string>
*/
protected $fillable = [
'name',
'slug',
'description',
'status',
'opening_date',
'closing_date',
'operating_season',
'size_acres',
'website',
'operator_id',
'total_areas',
'operating_areas',
'closed_areas',
'total_rides',
'total_coasters',
'total_flat_rides',
'total_water_rides',
'total_daily_capacity',
'average_wait_time',
'average_rating',
'total_rides_operated',
'total_rides_retired',
'last_expansion_date',
'last_major_update',
'utilization_rate',
'peak_daily_attendance',
'guest_satisfaction',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'status' => ParkStatus::class,
'opening_date' => 'date',
'closing_date' => 'date',
'size_acres' => 'decimal:2',
'total_areas' => 'integer',
'operating_areas' => 'integer',
'closed_areas' => 'integer',
'total_rides' => 'integer',
'total_coasters' => 'integer',
'total_flat_rides' => 'integer',
'total_water_rides' => 'integer',
'total_daily_capacity' => 'integer',
'average_wait_time' => 'integer',
'average_rating' => 'decimal:2',
'total_rides_operated' => 'integer',
'total_rides_retired' => 'integer',
'last_expansion_date' => 'date',
'last_major_update' => 'date',
'utilization_rate' => 'decimal:2',
'peak_daily_attendance' => 'integer',
'guest_satisfaction' => 'decimal:2',
];
/**
* Get the operator that owns the park.
*/
public function operator(): BelongsTo
{
return $this->belongsTo(Operator::class);
}
/**
* Get the areas in the park.
*/
public function areas(): HasMany
{
return $this->hasMany(ParkArea::class);
}
/**
* Get formatted website URL (ensures proper URL format).
*/
public function getWebsiteUrlAttribute(): string
{
if (!$this->website) {
return '';
}
$website = $this->website;
if (!str_starts_with($website, 'http://') && !str_starts_with($website, 'https://')) {
$website = 'https://' . $website;
}
return $website;
}
/**
* Get the status display classes for Tailwind CSS.
*/
public function getStatusClassesAttribute(): string
{
return $this->status->getStatusClasses();
}
/**
* Get a formatted display of the park's size.
*/
public function getSizeDisplayAttribute(): string
{
return $this->size_acres ? number_format($this->size_acres, 1) . ' acres' : 'Unknown size';
}
/**
* Get the formatted opening year.
*/
public function getOpeningYearAttribute(): ?string
{
return $this->opening_date?->format('Y');
}
/**
* Get a brief description suitable for cards and previews.
*/
public function getBriefDescriptionAttribute(): string
{
$description = $this->description ?? '';
return strlen($description) > 200 ? substr($description, 0, 200) . '...' : $description;
}
/**
* Scope a query to only include operating parks.
*/
public function scopeOperating($query)
{
return $query->where('status', ParkStatus::OPERATING);
}
/**
* Scope a query to only include closed parks.
*/
public function scopeClosed($query)
{
return $query->whereIn('status', [
ParkStatus::CLOSED_TEMP,
ParkStatus::CLOSED_PERM,
ParkStatus::DEMOLISHED,
]);
}
/**
* Boot the model.
*/
protected static function boot()
{
parent::boot();
static::created(function (Park $park) {
$park->operator?->updateStatistics();
});
static::deleted(function (Park $park) {
$park->operator?->updateStatistics();
});
}
}