Deploy Ladill Meet / deploy (push) Failing after 7s
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>
101 lines
3.0 KiB
PHP
101 lines
3.0 KiB
PHP
<?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;
|
|
}
|
|
}
|