'Cover image', 'design' => 'Page design', 'questions' => 'Checkout questions', 'sponsors' => 'Sponsors', 'announcements' => 'Announcements', 'discounts' => 'Automatic discounts (without a code)']; /** A copy of an uploaded image under a new name, so deleting one event never removes another event's image. */ function copy_upload(?string $name): ?string { $path = $name ? upload_path($name) : null; if (!$path) return null; $new = bin2hex(random_bytes(16)) . '.' . pathinfo($path, PATHINFO_EXTENSION); return gatecraft_fs()->copy($path, gatecraft_uploads()['dir'] . '/' . $new, false, gatecraft_file_mode()) ? $new : null; } /** * Copy an event. $o: starts_at (required), title, slug, status, series_id, user_id, copy [part => bool]. * Returns ['id' => new event id, 'notes' => string[]]. Runs inside the caller's transaction when there is one. */ function event_clone(int $srcId, array $o): array { $src = q1('SELECT * FROM {events} WHERE id = ?', [$srcId]) ?? throw new UserError('Event not found.'); $copy = (array)($o['copy'] ?? []); $delta = lstrtotime((string)$o['starts_at']) - lstrtotime($src['starts_at']); $shift = fn(?string $dt) => $dt ? ldate('Y-m-d H:i:s', lstrtotime($dt) + $delta) : null; $notes = []; $row = $src; foreach (['id', 'reminder_sent_at', 'capacity_alerted_at'] as $k) unset($row[$k]); $row['title'] = mb_substr((string)($o['title'] ?? $src['title']), 0, 190); $row['slug'] = eventpack_unique_slug((string)($o['slug'] ?? $src['slug'])); $row['status'] = in_array($o['status'] ?? 'draft', ['draft', 'published'], true) ? ($o['status'] ?? 'draft') : 'draft'; $row['starts_at'] = ldate('Y-m-d H:i:s', lstrtotime((string)$o['starts_at'])); $row['ends_at'] = $shift($src['ends_at']); $row['doors_at'] = $shift($src['doors_at']); $row['cover_image'] = !empty($copy['cover']) ? copy_upload($src['cover_image']) : null; if (empty($copy['design'])) $row['design'] = null; if (array_key_exists('series_id', $o)) $row['series_id'] = $o['series_id']; $row['created_by'] = $o['user_id'] ?? null; $row['created_at'] = $row['updated_at'] = now(); [$newId] = eventpack_insert('events', $row); $catMap = []; foreach (q('SELECT * FROM {ticket_categories} WHERE event_id = ? ORDER BY sort_order, id', [$srcId])->fetchAll() as $c) { $oldCat = (int)$c['id']; unset($c['id']); $c['event_id'] = $newId; [$catMap[$oldCat]] = eventpack_insert('ticket_categories', $c); foreach (q('SELECT * FROM {ticket_tiers} WHERE category_id = ? ORDER BY sort_order, id', [$oldCat])->fetchAll() as $t) { unset($t['id']); $t['category_id'] = $catMap[$oldCat]; $t['sale_start'] = $shift($t['sale_start']); $t['sale_end'] = $shift($t['sale_end']); eventpack_insert('ticket_tiers', $t); } } if (!empty($copy['questions']) && eventpack_has_table('event_questions')) { foreach (q('SELECT * FROM {event_questions} WHERE event_id = ? ORDER BY sort_order, id', [$srcId])->fetchAll() as $qn) { unset($qn['id']); $qn['event_id'] = $newId; $qn['category_id'] = $qn['category_id'] !== null ? ($catMap[(int)$qn['category_id']] ?? null) : null; eventpack_insert('event_questions', $qn); } } if (!empty($copy['sponsors'])) { foreach (q('SELECT * FROM {event_sponsors} WHERE event_id = ? ORDER BY sort_order, id', [$srcId])->fetchAll() as $s) { unset($s['id']); $s['event_id'] = $newId; $s['logo'] = copy_upload($s['logo']); $s['image'] = copy_upload($s['image']); $s['created_at'] = $s['updated_at'] = now(); eventpack_insert('event_sponsors', $s); } } if (!empty($copy['announcements'])) { foreach (q('SELECT * FROM {event_announcements} WHERE event_id = ? ORDER BY id', [$srcId])->fetchAll() as $a) { unset($a['id']); $a['event_id'] = $newId; foreach (['starts_at', 'ends_at', 'show_from', 'show_until'] as $k) if (array_key_exists($k, $a)) $a[$k] = $shift($a[$k]); eventpack_insert('event_announcements', $a); } } $coded = (int)qv('SELECT COUNT(*) FROM {discounts} WHERE event_id = ? AND code IS NOT NULL', [$srcId]); if (!empty($copy['discounts'])) { foreach (q('SELECT * FROM {discounts} WHERE event_id = ? AND code IS NULL ORDER BY id', [$srcId])->fetchAll() as $d) { unset($d['id']); $d['event_id'] = $newId; $d['category_id'] = $d['category_id'] !== null ? ($catMap[(int)$d['category_id']] ?? null) : null; $d['starts_at'] = $shift($d['starts_at']); $d['ends_at'] = $shift($d['ends_at']); $d['created_at'] = now(); eventpack_insert('discounts', $d); } } if ($coded) $notes[] = plural($coded, 'discount code') . ' not copied: codes are unique. Codes for all events (set under Discounts) work for the copy too.'; return ['id' => $newId, 'notes' => $notes]; } /** Defaults for the copy options: everything except announcements. */ function event_copy_defaults(): array { return ['cover' => true, 'design' => true, 'questions' => true, 'sponsors' => true, 'announcements' => false, 'discounts' => true]; } /** The copy options from a submitted form. */ function event_copy_from_post(): array { $out = []; foreach (array_keys(EVENT_COPY_PARTS) as $k) $out[$k] = (bool)post_bool('copy_' . $k); return $out; }