166 lines
4.7 KiB
PHP
166 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Enums\HuntDifficulty;
|
|
use App\Enums\HuntStatus;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Laravel\Scout\Searchable;
|
|
|
|
class Hunts extends Model
|
|
{
|
|
use HasFactory;
|
|
use Searchable;
|
|
|
|
protected $table = 'hunts';
|
|
|
|
protected $fillable = [
|
|
'partner_id',
|
|
'title',
|
|
'slug',
|
|
'description',
|
|
'status',
|
|
'difficulty',
|
|
'city',
|
|
'latitude',
|
|
'longitude',
|
|
'is_public',
|
|
'estimated_duration_min',
|
|
'start_at',
|
|
'end_at',
|
|
'image',
|
|
'creator_id',
|
|
];
|
|
|
|
protected $casts = [
|
|
'is_public' => 'boolean',
|
|
'start_at' => 'datetime',
|
|
'end_at' => 'datetime',
|
|
'latitude' => 'float',
|
|
'longitude' => 'float',
|
|
'estimated_duration_min' => 'integer',
|
|
'status' => HuntStatus::class,
|
|
'difficulty' => HuntDifficulty::class,
|
|
];
|
|
|
|
public function steps(): HasMany
|
|
{
|
|
return $this->hasMany(HuntSteps::class, 'hunt_id');
|
|
}
|
|
|
|
public function creator(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'creator_id');
|
|
}
|
|
|
|
public function participants(): BelongsToMany
|
|
{
|
|
return $this->belongsToMany(User::class, 'hunt_participants', 'hunt_id', 'user_id')
|
|
->withPivot(['current_step_number', 'status'])
|
|
->withTimestamps();
|
|
}
|
|
|
|
public function totalXp(): int
|
|
{
|
|
if ($this->relationLoaded('steps')) {
|
|
return (int) $this->steps->sum('xp');
|
|
}
|
|
|
|
$stepsSumXp = $this->getAttribute('steps_sum_xp');
|
|
|
|
if ($stepsSumXp !== null) {
|
|
return (int) $stepsSumXp;
|
|
}
|
|
|
|
return (int) $this->steps()->sum('xp');
|
|
}
|
|
|
|
/**
|
|
* Configure Meilisearch index settings
|
|
*/
|
|
public function searchableOptions(): array
|
|
{
|
|
return [
|
|
'filterableAttributes' => [
|
|
'city',
|
|
'difficulty',
|
|
'status',
|
|
'is_public',
|
|
'creator_id',
|
|
'participant_ids',
|
|
'start_at_timestamp',
|
|
'end_at_timestamp',
|
|
'created_at_timestamp',
|
|
],
|
|
'sortableAttributes' => [
|
|
'start_at_timestamp',
|
|
'end_at_timestamp',
|
|
'created_at_timestamp',
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array{
|
|
* id: int,
|
|
* title: string,
|
|
* slug: string,
|
|
* description: string|null,
|
|
* city: string,
|
|
* status: string,
|
|
* difficulty: string,
|
|
* is_public: bool,
|
|
* creator_id: int,
|
|
* latitude: float|null,
|
|
* longitude: float|null,
|
|
* start_at: string|null,
|
|
* end_at: string|null,
|
|
* start_at_timestamp: int|null,
|
|
* end_at_timestamp: int|null,
|
|
* created_at_timestamp: int,
|
|
* participant_ids: array<int>
|
|
* }
|
|
*/
|
|
public function toSearchableArray(): array
|
|
{
|
|
$status = $this->status instanceof HuntStatus ? $this->status->value : $this->status;
|
|
$difficulty = $this->difficulty instanceof HuntDifficulty ? $this->difficulty->value : $this->difficulty;
|
|
|
|
try {
|
|
$participantIds = $this->participants()->pluck('user_id')->toArray();
|
|
} catch (\Throwable $e) {
|
|
\Illuminate\Support\Facades\Log::error('TO_SEARCHABLE_ARRAY_PARTICIPANTS_ERROR', [
|
|
'hunt_id' => $this->id,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
$participantIds = [];
|
|
}
|
|
|
|
return [
|
|
'id' => $this->id,
|
|
'title' => $this->title,
|
|
'slug' => $this->slug,
|
|
'description' => $this->description,
|
|
'city' => $this->city,
|
|
'status' => $status,
|
|
'difficulty' => $difficulty,
|
|
'is_public' => $this->is_public,
|
|
'creator_id' => $this->creator_id,
|
|
'latitude' => $this->latitude,
|
|
'longitude' => $this->longitude,
|
|
'start_at' => $this->start_at?->toAtomString(),
|
|
'end_at' => $this->end_at?->toAtomString(),
|
|
// Timestamps Unix pour les filtres de date dans Meilisearch
|
|
'start_at_timestamp' => $this->start_at?->timestamp,
|
|
'end_at_timestamp' => $this->end_at?->timestamp,
|
|
'created_at_timestamp' => $this->created_at->timestamp,
|
|
// IDs des participants pour le filtre de participation
|
|
'participant_ids' => $participantIds,
|
|
];
|
|
}
|
|
}
|