113 lines
3.0 KiB
PHP
113 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Support\Str;
|
|
use Laravel\Scout\Searchable;
|
|
|
|
use App\Models\MessageRead;
|
|
|
|
/**
|
|
* @property int $id
|
|
* @property int $conversation_id
|
|
* @property int $sender_id
|
|
* @property string $body
|
|
* @property \Carbon\Carbon|null $edited_at
|
|
* @property \Carbon\Carbon|null $deleted_at
|
|
* @property \Carbon\Carbon $created_at
|
|
* @property \Carbon\Carbon $updated_at
|
|
*/
|
|
class Message extends Model
|
|
{
|
|
use HasFactory, SoftDeletes, Searchable;
|
|
|
|
protected $fillable = [
|
|
'uuid',
|
|
'client_temp_id',
|
|
'conversation_id',
|
|
'sender_id',
|
|
'message_type',
|
|
'body',
|
|
'meta_json',
|
|
'reply_to_message_id',
|
|
'edited_at',
|
|
];
|
|
|
|
protected $casts = [
|
|
'meta_json' => 'array',
|
|
'edited_at' => 'datetime',
|
|
];
|
|
|
|
protected static function booted(): void
|
|
{
|
|
static::creating(function (self $message): void {
|
|
if (! $message->uuid) {
|
|
$message->uuid = (string) Str::uuid();
|
|
}
|
|
});
|
|
}
|
|
|
|
// ── Relationships ────────────────────────────────────────────────────────
|
|
|
|
public function conversation(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Conversation::class);
|
|
}
|
|
|
|
public function sender(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'sender_id');
|
|
}
|
|
|
|
public function reactions(): HasMany
|
|
{
|
|
return $this->hasMany(MessageReaction::class);
|
|
}
|
|
|
|
public function attachments(): HasMany
|
|
{
|
|
return $this->hasMany(MessageAttachment::class);
|
|
}
|
|
|
|
public function reads(): HasMany
|
|
{
|
|
return $this->hasMany(MessageRead::class);
|
|
}
|
|
|
|
public function setBodyAttribute(?string $value): void
|
|
{
|
|
$sanitized = trim(strip_tags((string) $value));
|
|
$this->attributes['body'] = $sanitized;
|
|
}
|
|
|
|
public function searchableAs(): string
|
|
{
|
|
return config('messaging.search.index', 'messages');
|
|
}
|
|
|
|
public function shouldBeSearchable(): bool
|
|
{
|
|
return $this->deleted_at === null;
|
|
}
|
|
|
|
public function toSearchableArray(): array
|
|
{
|
|
return [
|
|
'id' => (int) $this->id,
|
|
'conversation_id' => (int) $this->conversation_id,
|
|
'sender_id' => (int) $this->sender_id,
|
|
'sender_username' => (string) ($this->sender?->username ?? ''),
|
|
'body_text' => trim(strip_tags((string) $this->body)),
|
|
'created_at' => optional($this->created_at)->timestamp ?? now()->timestamp,
|
|
'has_attachments' => $this->relationLoaded('attachments')
|
|
? $this->attachments->isNotEmpty()
|
|
: $this->attachments()->exists(),
|
|
];
|
|
}
|
|
}
|