$data */ public function create(User $user, Organization $organization, array $data): Channel { $ownerRef = $user->ownerRef(); $slug = Str::slug($data['name']); $channel = Channel::create([ 'owner_ref' => $ownerRef, 'organization_id' => $organization->id, 'branch_id' => $data['branch_id'] ?? null, 'name' => $data['name'], 'slug' => $this->uniqueSlug($organization->id, $slug), 'visibility' => $data['visibility'] ?? 'public', 'description' => $data['description'] ?? null, ]); $this->addMember($channel, $ownerRef, 'admin'); AuditLogger::record($ownerRef, 'channel.created', $organization->id, $ownerRef, Channel::class, $channel->id); return $channel; } public function addMember(Channel $channel, string $userRef, string $role = 'member'): ChannelMember { return ChannelMember::firstOrCreate( ['channel_id' => $channel->id, 'user_ref' => $userRef], ['role' => $role], ); } public function canAccess(Channel $channel, string $userRef): bool { if ($channel->visibility === 'public') { return true; } return $channel->members()->where('user_ref', $userRef)->exists(); } public function canPost(Channel $channel, string $userRef): bool { if ($channel->visibility === 'public') { return true; } return $channel->members()->where('user_ref', $userRef)->exists(); } public function postMessage(Channel $channel, User $user, string $body, ?int $parentId = null): ChannelMessage { abort_unless($this->canPost($channel, $user->ownerRef()), 403); return ChannelMessage::create([ 'owner_ref' => $channel->owner_ref, 'channel_id' => $channel->id, 'sender_ref' => $user->ownerRef(), 'sender_name' => $user->name, 'body' => trim($body), 'parent_id' => $parentId, ]); } public function react(ChannelMessage $message, string $emoji, string $userRef): ChannelMessage { $metadata = $message->metadata ?? []; $reactions = $metadata['reactions'] ?? []; $reactions[$emoji] = array_values(array_unique(array_merge($reactions[$emoji] ?? [], [$userRef]))); $metadata['reactions'] = $reactions; $message->update(['metadata' => $metadata]); return $message->fresh(); } protected function uniqueSlug(int $organizationId, string $base): string { $slug = $base; $i = 1; while (Channel::where('organization_id', $organizationId)->where('slug', $slug)->exists()) { $slug = $base.'-'.$i++; } return $slug; } }