Files
ladill-events/app/Services/Events/EventSpeakerService.php
T
isaaccladandCursor d2ec31f7a5
Deploy Ladill Events / deploy (push) Successful in 28s
Fix post-registration 404, add speaker management, and simplify event creation.
Proxy registration transaction paths on Events, add a join button on the
confirmation page, introduce speaker roster management, and replace the QR
design wizard with merchant-style create/show flows.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 13:44:53 +00:00

128 lines
3.8 KiB
PHP

<?php
namespace App\Services\Events;
use App\Models\QrCode;
use Illuminate\Support\Collection;
class EventSpeakerService
{
public function __construct(private readonly EventProgrammeService $programmes) {}
public function linkedProgramme(QrCode $event): ?QrCode
{
if ($event->type !== QrCode::TYPE_EVENT) {
return null;
}
$programmeId = (int) ($event->content()['programme_qr_id'] ?? 0);
if ($programmeId <= 0) {
return null;
}
return QrCode::query()
->where('id', $programmeId)
->where('user_id', $event->user_id)
->where('type', QrCode::TYPE_ITINERARY)
->first();
}
/** @return list<array{name: string, email: string, role: string, bio: string, source: string}> */
public function rosterFor(QrCode $event): array
{
if ($event->type !== QrCode::TYPE_EVENT) {
return [];
}
$content = $event->content();
$roster = [];
foreach ((array) ($content['speakers'] ?? []) as $speaker) {
if (! is_array($speaker)) {
continue;
}
$name = trim((string) ($speaker['name'] ?? ''));
if ($name === '') {
continue;
}
$roster[] = [
'name' => $name,
'email' => trim((string) ($speaker['email'] ?? '')),
'role' => trim((string) ($speaker['role'] ?? '')),
'bio' => trim((string) ($speaker['bio'] ?? '')),
'source' => 'roster',
];
}
foreach ($this->programmeAssignments($event) as $assignment) {
$name = trim((string) ($assignment['name'] ?? ''));
if ($name === '') {
continue;
}
$exists = collect($roster)->contains(fn ($row) => strcasecmp($row['name'], $name) === 0);
if ($exists) {
continue;
}
$roster[] = [
'name' => $name,
'email' => '',
'role' => trim((string) ($assignment['session'] ?? '')),
'bio' => '',
'source' => 'programme',
];
}
return $roster;
}
/** @return list<array{name: string, session: string, day: string, time: string}> */
public function programmeAssignments(QrCode $event): array
{
$programme = $this->linkedProgramme($event);
$snapshot = $this->programmes->snapshot($programme);
if (! $snapshot) {
return [];
}
$assignments = [];
foreach ((array) ($snapshot['days'] ?? []) as $day) {
$dayLabel = trim((string) ($day['date'] ?? $day['label'] ?? ''));
foreach ((array) ($day['items'] ?? []) as $item) {
if (! is_array($item)) {
continue;
}
$host = trim((string) ($item['host'] ?? ''));
if ($host === '') {
continue;
}
$assignments[] = [
'name' => $host,
'session' => trim((string) ($item['title'] ?? '')),
'day' => $dayLabel,
'time' => trim((string) ($item['time'] ?? '')),
];
}
}
return $assignments;
}
/** @return Collection<int, QrCode> */
public function eventsForAccount(int $userId, ?string $search = null): Collection
{
return QrCode::query()
->where('user_id', $userId)
->where('type', QrCode::TYPE_EVENT)
->when($search !== null && $search !== '', fn ($q) => $q->where('label', 'like', "%{$search}%"))
->latest()
->get();
}
}