'datetime', 'metadata' => 'array', ]; /** * Get the creator of the conversation */ public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } /** * Get all participants */ public function participants(): BelongsToMany { return $this->belongsToMany(User::class, 'ext_social_conversation_participants', 'conversation_id', 'user_id') ->withPivot('last_read_at', 'is_muted', 'is_archived', 'is_pinned') ->withTimestamps(); } /** * Get all messages */ public function messages(): HasMany { return $this->hasMany(Message::class)->orderBy('created_at', 'asc'); } /** * Get the last message */ public function lastMessage() { return $this->hasOne(Message::class)->latestOfMany(); } /** * Get unread messages count for a user */ public function getUnreadCountForUser($userId): int { $participant = $this->participants()->where('user_id', $userId)->first(); if (!$participant) { return 0; } return $this->messages() ->where('sender_id', '!=', $userId) ->where('created_at', '>', $participant->pivot->last_read_at ?? $this->created_at) ->count(); } /** * Mark conversation as read for user */ public function markAsReadForUser($userId): void { $this->participants()->updateExistingPivot($userId, [ 'last_read_at' => now(), ]); } /** * Check if user is participant */ public function hasParticipant($userId): bool { return $this->participants()->where('user_id', $userId)->exists(); } /** * Get other participant in a direct conversation */ public function getOtherParticipant($userId) { if ($this->type !== 'direct') { return null; } return $this->participants()->where('user_id', '!=', $userId)->first(); } /** * Find or create a direct conversation between two users */ public static function findOrCreateDirectConversation($userId1, $userId2): self { // Try to find existing conversation $conversation = self::where('type', 'direct') ->whereHas('participants', function ($query) use ($userId1) { $query->where('user_id', $userId1); }) ->whereHas('participants', function ($query) use ($userId2) { $query->where('user_id', $userId2); }) ->first(); if ($conversation) { return $conversation; } // Create new conversation $conversation = self::create([ 'type' => 'direct', 'created_by' => $userId1, ]); $conversation->participants()->attach([$userId1, $userId2]); return $conversation; } /** * Check if conversation is pinned for a user */ public function isPinnedForUser($userId): bool { $participant = $this->participants()->where('user_id', $userId)->first(); return $participant ? (bool) $participant->pivot->is_pinned : false; } /** * Toggle pinned status for a user */ public function togglePinForUser($userId): bool { $participant = $this->participants()->where('user_id', $userId)->first(); if (!$participant) { return false; } $newPinnedStatus = !$participant->pivot->is_pinned; $this->participants()->updateExistingPivot($userId, [ 'is_pinned' => $newPinnedStatus ]); return $newPinnedStatus; } }