Files
fitme3070.pt/site/evento.php
T
2026-06-12 21:20:23 +01:00

238 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// ── Event landing page ──────────────────────────────────────────────────────
// Branded, time-limited landing page reached at /evento/<slug> (see .htaccess).
// Visible to the public only while the event is live (db_events_active rule);
// logged-in staff may preview drafts/scheduled/expired events. Carries an
// optional lead-capture form that stores submissions in event_leads.
require_once __DIR__ . '/../config/db.php';
require_once __DIR__ . '/../config/functions.php';
// Resolve any SSO session up front (mirrors _open.php) so the is_staff() preview
// gate below sees a logged-in admin. _open.php's later call then no-ops.
if (empty($_SESSION['user_id']) && identity_is_federated()) {
sso_resolve_session($pdo);
}
$slug = preg_replace('/[^a-z0-9\-]/', '', strtolower((string) ($_GET['slug'] ?? '')));
$event = $slug !== '' ? db_events_get_by_slug($pdo, $slug) : null;
// Gate: live for everyone, otherwise only staff (preview).
$can_view = $event && (events_is_live($event) || is_staff());
// ── Lead form submission (PRG) ──────────────────────────────────────────────
$lead_errors = [];
if ($can_view && $_SERVER['REQUEST_METHOD'] === 'POST') {
csrf_check();
$back = base_url('evento/' . rawurlencode($event['slug']));
// Honeypot: a filled "website" field means a bot — silently accept & drop.
if (trim((string) ($_POST['website'] ?? '')) !== '') {
header('Location: ' . $back . '?ok=1#inscricao');
exit;
}
// The exact wording the visitor consents to — stored for GDPR evidence.
$consent_text = 'Autorizo o contacto e o tratamento dos meus dados para efeitos desta inscrição, nos termos da Política de Privacidade.';
$lead = [
'name' => trim((string) ($_POST['lead_name'] ?? '')),
'email' => trim((string) ($_POST['lead_email'] ?? '')),
'phone' => trim((string) ($_POST['lead_phone'] ?? '')),
'message' => trim((string) ($_POST['lead_message'] ?? '')),
'consent' => !empty($_POST['lead_consent']) ? 1 : 0,
'consent_text' => $consent_text,
// First hop of X-Forwarded-For (behind the id.andmore.pt proxy), else peer.
'ip' => trim(explode(',', (string) ($_SERVER['HTTP_X_FORWARDED_FOR'] ?? ''))[0]) ?: ($_SERVER['REMOTE_ADDR'] ?? ''),
'user_agent' => (string) ($_SERVER['HTTP_USER_AGENT'] ?? ''),
];
if ($lead['name'] === '') $lead_errors[] = 'Indica o teu nome.';
if ($lead['email'] === '' && $lead['phone'] === '') $lead_errors[] = 'Indica um email ou um telefone para te podermos contactar.';
if ($lead['email'] !== '' && !filter_var($lead['email'], FILTER_VALIDATE_EMAIL)) $lead_errors[] = 'O email indicado não é válido.';
if (!$lead['consent']) $lead_errors[] = 'É necessário aceitar o tratamento dos dados para enviar a inscrição.';
if (!$lead_errors) {
db_event_lead_create($pdo, (int) $event['e_id'], $lead);
header('Location: ' . $back . '?ok=1#inscricao');
exit;
}
// fall through and re-render with $lead_errors + the submitted $lead values
$lead_old = $lead;
}
// ── Not found / not visible ─────────────────────────────────────────────────
if (!$can_view) {
http_response_code(404);
$current_uri_2 = '';
require __DIR__ . '/_open.php';
?>
<section class="event-notfound" style="padding:160px 0 90px;text-align:center;">
<div class="container">
<h1 style="font-size:2.4rem;">Evento não encontrado</h1>
<p class="text-muted">Este evento pode já ter terminado ou o link estar incorreto.</p>
<a href="<?= base_url('/') ?>" class="site-btn mt-3">Voltar ao início</a>
</div>
</section>
<?php
echo view('footer');
return;
}
// ── Visible: render the landing page ────────────────────────────────────────
$is_preview = !events_is_live($event);
$hero_url = $event['hero_image'] !== '' ? base_url('uploads/events/' . rawurlencode($event['hero_image'])) : '';
$accent = $event['cor'] !== '' ? $event['cor'] : '#C2D500';
// Human date line for the event window.
$date_line = '';
if (!empty($event['event_starts_at'])) {
$date_line = format_date_pt((string) $event['event_starts_at']);
if (!empty($event['event_ends_at'])
&& substr((string) $event['event_ends_at'], 0, 10) !== substr((string) $event['event_starts_at'], 0, 10)) {
$date_line .= ' – ' . format_date_pt((string) $event['event_ends_at']);
}
}
// CTA target: explicit URL, else the on-page form (when shown), else contacts.
$cta_label = trim((string) $event['cta_label']);
$cta_href = trim((string) $event['cta_url']);
if ($cta_href === '') {
$cta_href = ((int) $event['show_lead_form'] === 1) ? '#inscricao' : base_url('home/contactos');
}
// ── SEO ─────────────────────────────────────────────────────────────────────
// include.php / seo.php honour these globals when set before _open.php runs.
$event_url = base_url('evento/' . rawurlencode($event['slug']));
$seo_desc = $event['summary'] !== ''
? $event['summary']
: trim(mb_substr(strip_tags((string) ($event['subtitle'] ?: $event['description'])), 0, 200));
$current_uri_2 = 'evento';
$GLOBALS['_page_meta_override'] = [
($event['title'] !== '' ? $event['title'] : 'Evento') . ' | FitMe 3070',
$seo_desc,
];
$GLOBALS['_canonical_override'] = $event_url;
$GLOBALS['_og_type_override'] = 'article';
if ($hero_url !== '') $GLOBALS['_og_image_override'] = $hero_url;
// Event structured data (schema.org/Event) for rich link previews / search.
$info = site_info($pdo);
$ld_event = [
'@context' => 'https://schema.org',
'@type' => 'Event',
'name' => $event['title'],
'description' => $seo_desc !== '' ? $seo_desc : $event['title'],
'url' => $event_url,
'eventStatus' => 'https://schema.org/EventScheduled',
'eventAttendanceMode' => 'https://schema.org/OfflineEventAttendanceMode',
];
if ($hero_url !== '') $ld_event['image'] = [$hero_url];
if (!empty($event['event_starts_at'])) $ld_event['startDate'] = str_replace(' ', 'T', (string) $event['event_starts_at']);
if (!empty($event['event_ends_at'])) $ld_event['endDate'] = str_replace(' ', 'T', (string) $event['event_ends_at']);
$ld_event['location'] = $event['location'] !== ''
? ['@type' => 'Place', 'name' => $event['location']]
: ['@type' => 'Place',
'name' => ($info['name'] ?? '') !== '' ? $info['name'] : 'FitMe 3070',
'address' => $info['adress'] ?? ''];
$ld_event['organizer'] = [
'@type' => 'Organization',
'name' => ($info['name'] ?? '') !== '' ? $info['name'] : 'FitMe 3070',
'url' => base_url(),
];
$GLOBALS['_jsonld_extra'] = $ld_event;
require __DIR__ . '/_open.php';
?>
<?php if ($is_preview): ?>
<div class="event-preview-bar">Pré-visualização — este evento não está visível ao público (<?= htmlspecialchars(events_status($event)) ?>).</div>
<?php endif; ?>
<section class="event-hero set-bg<?= $hero_url ? '' : ' event-hero--plain' ?>"
<?= $hero_url ? 'style="background-image:url(\'' . htmlspecialchars($hero_url, ENT_QUOTES) . '\')"' : '' ?>>
<div class="event-hero-overlay"></div>
<div class="container">
<div class="event-hero-inner">
<span class="event-hero-eyebrow" style="color:<?= htmlspecialchars($accent, ENT_QUOTES) ?>">Evento</span>
<h1><?= htmlspecialchars($event['title']) ?></h1>
<?php if ($event['subtitle'] !== ''): ?><p class="event-hero-sub"><?= htmlspecialchars($event['subtitle']) ?></p><?php endif; ?>
<ul class="event-hero-meta">
<?php if ($date_line !== ''): ?><li><i class="fas fa-calendar-alt"></i> <?= htmlspecialchars($date_line) ?></li><?php endif; ?>
<?php if ($event['location'] !== ''): ?><li><i class="fas fa-map-marker-alt"></i> <?= htmlspecialchars($event['location']) ?></li><?php endif; ?>
</ul>
<?php if ($cta_label !== ''): ?>
<a href="<?= htmlspecialchars($cta_href, ENT_QUOTES) ?>" class="site-btn event-hero-cta"
style="background:<?= htmlspecialchars($accent, ENT_QUOTES) ?>"
<?= ($cta_href[0] ?? '') === '#' ? 'data-scroll' : '' ?>><?= htmlspecialchars($cta_label) ?></a>
<?php endif; ?>
</div>
</div>
</section>
<?php if (trim((string) $event['description']) !== ''): ?>
<section class="event-body">
<div class="container">
<div class="row justify-content-md-center">
<div class="col-lg-8">
<?php /* description is admin-authored HTML — sanitised allowlist HTML */ ?>
<?= clean_richtext($event['description']) ?>
</div>
</div>
</div>
</section>
<?php endif; ?>
<?php if ((int) $event['show_lead_form'] === 1): ?>
<section class="event-leadform" id="inscricao">
<div class="container">
<div class="row justify-content-md-center">
<div class="col-lg-7">
<div class="section-title text-center deco">
<span class="section-eyebrow">Participa</span>
<h2>Inscreve-te</h2>
<p class="section-subtitle">Deixa os teus dados e entramos em contacto.</p>
</div>
<?php if (isset($_GET['ok'])): ?>
<div class="event-alert event-alert--ok">Inscrição enviada com sucesso. Obrigado!</div>
<?php endif; ?>
<?php foreach ($lead_errors as $e): ?>
<div class="event-alert event-alert--err"><?= htmlspecialchars($e) ?></div>
<?php endforeach; ?>
<form method="POST" action="<?= base_url('evento/' . rawurlencode($event['slug'])) ?>#inscricao" class="event-form">
<?= csrf_field() ?>
<!-- honeypot: must stay empty -->
<input type="text" name="website" tabindex="-1" autocomplete="off" class="event-hp" aria-hidden="true">
<div class="event-form-grid">
<div class="event-field">
<label>Nome *</label>
<input type="text" name="lead_name" required maxlength="150" value="<?= htmlspecialchars($lead_old['name'] ?? '') ?>">
</div>
<div class="event-field">
<label>Telefone</label>
<input type="tel" name="lead_phone" maxlength="40" value="<?= htmlspecialchars($lead_old['phone'] ?? '') ?>">
</div>
<div class="event-field event-field--full">
<label>Email</label>
<input type="email" name="lead_email" maxlength="190" value="<?= htmlspecialchars($lead_old['email'] ?? '') ?>">
</div>
<div class="event-field event-field--full">
<label>Mensagem</label>
<textarea name="lead_message" rows="3" maxlength="1000"><?= htmlspecialchars($lead_old['message'] ?? '') ?></textarea>
</div>
</div>
<label class="event-consent">
<input type="checkbox" name="lead_consent" value="1" required <?= !empty($lead_old['consent']) ? 'checked' : '' ?>>
<span>Autorizo o contacto e o tratamento dos meus dados para esta inscrição, nos termos da <a href="<?= base_url('home/privacidade') ?>" target="_blank" rel="noopener">Política de Privacidade</a>.</span>
</label>
<div class="text-center mt-3">
<button type="submit" class="site-btn" style="background:<?= htmlspecialchars($accent, ENT_QUOTES) ?>">Enviar inscrição</button>
</div>
</form>
</div>
</div>
</div>
</section>
<?php endif; ?>
<?php
echo view('footer');