Add newsletter subscription to petition form
Add Listmonk integration for newsletter subscriptions Add newsletter checkbox to form Handle newsletter subscription on form submission Add session flag for thank you page Remove duplicate sign-now ID from form section
This commit is contained in:
parent
afeeb658de
commit
054c59f177
3 changed files with 84 additions and 9 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
<h1>Show your support by signing here</h1>
|
<h1 id="sign-now">Show your support by signing here</h1>
|
||||||
|
|
||||||
<?= $petition_form ?? '' ?>
|
<?= $petition_form ?? '' ?>
|
||||||
<?= $petition_signatures ?? '' ?>
|
<?= $petition_signatures ?? '' ?>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<h1>Signer her for å vise din støtte</h1>
|
<h1 id="sign-now">Signer her for å vise din støtte</h1>
|
||||||
|
|
||||||
<?= $petition_form ?? '' ?>
|
<?= $petition_form ?? '' ?>
|
||||||
<?= $petition_signatures ?? '' ?>
|
<?= $petition_signatures ?? '' ?>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,61 @@ function petitionSanitizeCSV(string $value): string {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe email to Listmonk newsletter lists via public API
|
||||||
|
* Listmonk handles double opt-in (sends its own confirmation email)
|
||||||
|
*/
|
||||||
|
function petitionSubscribeToNewsletter(string $email, string $name): bool {
|
||||||
|
$configPath = dirname(__DIR__, 2) . '/listmonk-config.php';
|
||||||
|
if (!file_exists($configPath)) {
|
||||||
|
error_log("Listmonk config not found: {$configPath}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = require $configPath;
|
||||||
|
if (!$config['enabled']) {
|
||||||
|
error_log("Listmonk disabled in config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the UUIDs being used
|
||||||
|
error_log("Listmonk attempting subscription with UUIDs: " . implode(', ', $config['list_uuids']));
|
||||||
|
|
||||||
|
$payload = json_encode([
|
||||||
|
'email' => $email,
|
||||||
|
'name' => $name,
|
||||||
|
'list_uuids' => $config['list_uuids']
|
||||||
|
]);
|
||||||
|
|
||||||
|
$url = $config['url'] . '/api/public/subscription';
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt_array($ch, [
|
||||||
|
CURLOPT_POST => true,
|
||||||
|
CURLOPT_POSTFIELDS => $payload,
|
||||||
|
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_TIMEOUT => 10
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
$curlError = curl_error($ch);
|
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
if ($curlError) {
|
||||||
|
error_log("Listmonk curl error: {$curlError}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($httpCode < 200 || $httpCode >= 300) {
|
||||||
|
error_log("Listmonk subscription failed: HTTP {$httpCode}, URL: {$url}, Response: {$response}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_log("Listmonk subscription success for {$email}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check IP-based rate limiting to prevent email bombing and spam
|
* Check IP-based rate limiting to prevent email bombing and spam
|
||||||
* Returns true if IP is allowed, false if rate limit exceeded
|
* Returns true if IP is allowed, false if rate limit exceeded
|
||||||
|
|
@ -193,15 +248,15 @@ function petitionGetCsvPath(string $petitionId): string {
|
||||||
function petitionGetIdFromPath(string $pageDir): ?string {
|
function petitionGetIdFromPath(string $pageDir): ?string {
|
||||||
// Get the last directory segment as the petition ID
|
// Get the last directory segment as the petition ID
|
||||||
$petitionSlug = basename($pageDir);
|
$petitionSlug = basename($pageDir);
|
||||||
|
|
||||||
// Sanitize: remove any leading numeric prefix (e.g., "01-" becomes just the slug part)
|
// Sanitize: remove any leading numeric prefix (e.g., "01-" becomes just the slug part)
|
||||||
// This handles folders like "01-my-petition" -> "my-petition"
|
// This handles folders like "01-my-petition" -> "my-petition"
|
||||||
$petitionSlug = preg_replace('/^\d+-/', '', $petitionSlug);
|
$petitionSlug = preg_replace('/^\d+-/', '', $petitionSlug);
|
||||||
|
|
||||||
if (empty($petitionSlug)) {
|
if (empty($petitionSlug)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $petitionSlug;
|
return $petitionSlug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -795,7 +850,7 @@ function petitionRenderForm(Context $ctx, array $formData, array $errors, bool $
|
||||||
$currentTime = time();
|
$currentTime = time();
|
||||||
$regions = petitionGetRegions($ctx);
|
$regions = petitionGetRegions($ctx);
|
||||||
|
|
||||||
$html = '<section id="sign-now" class="petition-form">';
|
$html = '<section class="petition-form">';
|
||||||
// $html .= '<h2>' . htmlspecialchars(petitionT($ctx, 'petition', 'form_title')) . '</h2>';
|
// $html .= '<h2>' . htmlspecialchars(petitionT($ctx, 'petition', 'form_title')) . '</h2>';
|
||||||
|
|
||||||
// Error messages
|
// Error messages
|
||||||
|
|
@ -888,13 +943,18 @@ function petitionRenderForm(Context $ctx, array $formData, array $errors, bool $
|
||||||
$html .= '<a href="' . htmlspecialchars($privacyUrl) . '" target="_blank">' . htmlspecialchars(petitionT($ctx, 'petition', 'privacy_policy_link')) . '</a></p>';
|
$html .= '<a href="' . htmlspecialchars($privacyUrl) . '" target="_blank">' . htmlspecialchars(petitionT($ctx, 'petition', 'privacy_policy_link')) . '</a></p>';
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
// GDPR Consent checkbox
|
// GDPR Consent checkbox + Newsletter subscription
|
||||||
$consentChecked = isset($formData['gdpr_consent']) && $formData['gdpr_consent'] === 'on' ? ' checked' : '';
|
$consentChecked = isset($formData['gdpr_consent']) && $formData['gdpr_consent'] === 'on' ? ' checked' : '';
|
||||||
|
$newsletterChecked = isset($formData['newsletter']) && $formData['newsletter'] === 'on' ? ' checked' : '';
|
||||||
$html .= '<div class="form-group info-box info-box--green consent-group">';
|
$html .= '<div class="form-group info-box info-box--green consent-group">';
|
||||||
$html .= '<label class="consent-label">';
|
$html .= '<label class="consent-label">';
|
||||||
$html .= '<input type="checkbox" name="gdpr_consent" id="gdpr_consent" required' . $consentChecked . '> ';
|
$html .= '<input type="checkbox" name="gdpr_consent" id="gdpr_consent" required' . $consentChecked . '> ';
|
||||||
$html .= '<span>' . petitionT($ctx, 'petition', 'gdpr_consent_text') . ' <span class="required">*</span></span>';
|
$html .= '<span>' . petitionT($ctx, 'petition', 'gdpr_consent_text') . ' <span class="required">*</span></span>';
|
||||||
$html .= '</label>';
|
$html .= '</label>';
|
||||||
|
$html .= '<label class="consent-label">';
|
||||||
|
$html .= '<input type="checkbox" name="newsletter" id="newsletter"' . $newsletterChecked . '> ';
|
||||||
|
$html .= '<span>' . htmlspecialchars(petitionT($ctx, 'petition', 'newsletter_subscribe')) . '</span>';
|
||||||
|
$html .= '</label>';
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
// Submit button
|
// Submit button
|
||||||
|
|
@ -1001,7 +1061,7 @@ function petitionGetPageData(?Context $ctx): ?array {
|
||||||
if (!$petitionId) {
|
if (!$petitionId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$csvPath = petitionGetCsvPath($petitionId);
|
$csvPath = petitionGetCsvPath($petitionId);
|
||||||
// loadMetadata() already merges language-specific metadata via Hook::PROCESS_CONTENT
|
// loadMetadata() already merges language-specific metadata via Hook::PROCESS_CONTENT
|
||||||
$petitionTitle = $metadata['title'] ?? $petitionId;
|
$petitionTitle = $metadata['title'] ?? $petitionId;
|
||||||
|
|
@ -1186,7 +1246,16 @@ function petitionGetPageData(?Context $ctx): ?array {
|
||||||
|
|
||||||
// Send confirmation email
|
// Send confirmation email
|
||||||
if (petitionSendConfirmationEmail($signatureData, $confirmUrl, $petitionTitle, $ctx)) {
|
if (petitionSendConfirmationEmail($signatureData, $confirmUrl, $petitionTitle, $ctx)) {
|
||||||
|
// Subscribe to newsletter if opted in (fire and forget - don't block petition)
|
||||||
|
$newsletterOptIn = isset($_POST['newsletter']) && $_POST['newsletter'] === 'on';
|
||||||
|
error_log("Newsletter checkbox: " . ($newsletterOptIn ? 'checked' : 'not checked'));
|
||||||
|
if ($newsletterOptIn) {
|
||||||
|
$fullName = $formData['firstname'] . ' ' . $formData['surname'];
|
||||||
|
petitionSubscribeToNewsletter($formData['email'], $fullName);
|
||||||
|
}
|
||||||
|
|
||||||
$_SESSION['last_petition_submit'] = time();
|
$_SESSION['last_petition_submit'] = time();
|
||||||
|
$_SESSION['petition_subscribed_newsletter'] = $newsletterOptIn;
|
||||||
|
|
||||||
// Regenerate session ID to prevent session fixation
|
// Regenerate session ID to prevent session fixation
|
||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
|
|
@ -1208,7 +1277,7 @@ function petitionGetPageData(?Context $ctx): ?array {
|
||||||
if (!empty($formErrors)) {
|
if (!empty($formErrors)) {
|
||||||
$_SESSION['petition_errors'] = $formErrors;
|
$_SESSION['petition_errors'] = $formErrors;
|
||||||
$_SESSION['petition_form_data'] = $formData;
|
$_SESSION['petition_form_data'] = $formData;
|
||||||
|
|
||||||
$langPrefix = $ctx->get('langPrefix', '');
|
$langPrefix = $ctx->get('langPrefix', '');
|
||||||
$currentPath = trim($ctx->requestPath, '/');
|
$currentPath = trim($ctx->requestPath, '/');
|
||||||
$redirectUrl = "{$langPrefix}/{$currentPath}/#sign-now";
|
$redirectUrl = "{$langPrefix}/{$currentPath}/#sign-now";
|
||||||
|
|
@ -1254,5 +1323,11 @@ Hooks::add(Hook::TEMPLATE_VARS, function(array $vars, Context $ctx) {
|
||||||
$vars['petition_signatures'] = $data['signatures'];
|
$vars['petition_signatures'] = $data['signatures'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for newsletter subscription flag (for thank you page)
|
||||||
|
if (isset($_SESSION['petition_subscribed_newsletter'])) {
|
||||||
|
$vars['petition_subscribed_newsletter'] = $_SESSION['petition_subscribed_newsletter'];
|
||||||
|
unset($_SESSION['petition_subscribed_newsletter']);
|
||||||
|
}
|
||||||
|
|
||||||
return $vars;
|
return $vars;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue