Deploy Ladill Events / deploy (push) Successful in 47s
Speakers require email, get a personal holding page with programme and stage links, auto-invites when programme hosts are saved, and manual send for events without a schedule; also fix wallet copy on event create and anchor attendee comms. Co-authored-by: Cursor <cursoragent@cursor.com>
120 lines
3.6 KiB
PHP
120 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Events;
|
|
|
|
use App\Models\QrCode;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class EventProgrammeService
|
|
{
|
|
/** @return array{title: string, days: list<array<string, mixed>>}|null */
|
|
public function snapshot(?QrCode $programme): ?array
|
|
{
|
|
if (! $programme || $programme->type !== QrCode::TYPE_ITINERARY) {
|
|
return null;
|
|
}
|
|
|
|
$content = $programme->content();
|
|
|
|
return [
|
|
'title' => (string) ($content['title'] ?? $programme->label),
|
|
'subtitle' => (string) ($content['subtitle'] ?? ''),
|
|
'location' => (string) ($content['location'] ?? ''),
|
|
'days' => array_values((array) ($content['days'] ?? [])),
|
|
];
|
|
}
|
|
|
|
/** @param list<string> $itemRefs */
|
|
public function itemsForRefs(?array $snapshot, array $itemRefs): array
|
|
{
|
|
if (! $snapshot) {
|
|
return [];
|
|
}
|
|
|
|
$refs = array_flip($itemRefs);
|
|
$matched = [];
|
|
|
|
foreach ((array) ($snapshot['days'] ?? []) as $day) {
|
|
foreach ((array) ($day['items'] ?? []) as $item) {
|
|
$ref = (string) ($item['ref'] ?? '');
|
|
if ($ref !== '' && isset($refs[$ref])) {
|
|
$matched[] = $item;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
/** @param list<array<string, mixed>> $items */
|
|
public function hostsFromItems(array $items): array
|
|
{
|
|
return collect($items)
|
|
->flatMap(function ($item) {
|
|
if (! is_array($item)) {
|
|
return [];
|
|
}
|
|
|
|
$email = strtolower(trim((string) ($item['host_speaker_email'] ?? '')));
|
|
if ($email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
return [$email];
|
|
}
|
|
|
|
$host = trim((string) ($item['host'] ?? ''));
|
|
if ($host !== '' && filter_var($host, FILTER_VALIDATE_EMAIL)) {
|
|
return [$host];
|
|
}
|
|
|
|
if ($host !== '') {
|
|
return [$host];
|
|
}
|
|
|
|
return [];
|
|
})
|
|
->unique()
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
/** @return list<array{email: string, name: string}> */
|
|
public function speakerOptionsForProgramme(QrCode $programme): array
|
|
{
|
|
$options = [];
|
|
|
|
foreach ($this->eventsLinkedToProgramme($programme) as $event) {
|
|
foreach ((array) ($event->content()['speakers'] ?? []) as $speaker) {
|
|
if (! is_array($speaker)) {
|
|
continue;
|
|
}
|
|
|
|
$email = trim((string) ($speaker['email'] ?? ''));
|
|
$name = trim((string) ($speaker['name'] ?? ''));
|
|
if ($email === '' || ! filter_var($email, FILTER_VALIDATE_EMAIL) || $name === '') {
|
|
continue;
|
|
}
|
|
|
|
$options[strtolower($email)] = [
|
|
'email' => $email,
|
|
'name' => $name,
|
|
];
|
|
}
|
|
}
|
|
|
|
return array_values($options);
|
|
}
|
|
|
|
/** @return Collection<int, QrCode> */
|
|
public function eventsLinkedToProgramme(QrCode $programme): Collection
|
|
{
|
|
if ($programme->type !== QrCode::TYPE_ITINERARY) {
|
|
return collect();
|
|
}
|
|
|
|
return QrCode::query()
|
|
->where('user_id', $programme->user_id)
|
|
->where('type', QrCode::TYPE_EVENT)
|
|
->get()
|
|
->filter(fn (QrCode $event) => (int) ($event->content()['programme_qr_id'] ?? 0) === $programme->id);
|
|
}
|
|
}
|