Phases 0–18: core meetings, webinar, breakouts, team chat, live streaming, town hall, billing, and Ladill Mail calendar wiring. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Meet;
|
||||
|
||||
use App\Models\Channel;
|
||||
use App\Models\ChannelMember;
|
||||
use App\Models\ChannelMessage;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ChannelService
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user