178 lines
6.3 KiB
PHP
178 lines
6.3 KiB
PHP
<?php
|
|
/**
|
|
* File: VerificationController.php
|
|
* Version: 1.11
|
|
* Path: /app/Controllers/VerificationController.php
|
|
* Purpose: Handles email verification for newsletter and contact messages, including code expiration and attempt logging.
|
|
* Now wired to use EmailService for all post-verification messaging, including unified contact+newsletter handling.
|
|
* Project: Wizdom Networks Website
|
|
*/
|
|
|
|
namespace WizdomNetworks\WizeWeb\Controllers;
|
|
|
|
use WizdomNetworks\WizeWeb\Core\View;
|
|
use WizdomNetworks\WizeWeb\Utilities\Database;
|
|
use WizdomNetworks\WizeWeb\Utilities\Logger;
|
|
use WizdomNetworks\WizeWeb\Services\EmailService;
|
|
|
|
class VerificationController
|
|
{
|
|
private EmailService $emailService;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->emailService = new EmailService();
|
|
}
|
|
|
|
/**
|
|
* Handles email verification for newsletter and contact submissions using a unique code.
|
|
*
|
|
* - If the code matches an unverified record: marks it as verified and sends confirmations.
|
|
* - If already verified: shows a message.
|
|
* - If expired: prompts user to resend.
|
|
* - If invalid: redirects user to restart the process.
|
|
*
|
|
* @param string $code The verification code from the URL path.
|
|
* @return void
|
|
*/
|
|
public function verify(string $code): void
|
|
{
|
|
try {
|
|
if (empty($code)) {
|
|
Logger::error("Email verification attempted without a code.");
|
|
View::render('pages/verify_failed', [
|
|
'reason' => 'No verification code provided.',
|
|
'redirect' => true
|
|
]);
|
|
return;
|
|
}
|
|
|
|
$db = Database::getConnection();
|
|
$subscriber = null;
|
|
$table = null;
|
|
$type = null;
|
|
|
|
// Attempt to locate the subscriber record by code in either table
|
|
$stmt = $db->prepare("SELECT * FROM subscribers WHERE verification_code = ?");
|
|
$stmt->execute([$code]);
|
|
$subscriber = $stmt->fetch();
|
|
|
|
if ($subscriber) {
|
|
$table = 'subscribers';
|
|
$type = 'newsletter';
|
|
} else {
|
|
$stmt = $db->prepare("SELECT * FROM contact_messages WHERE verification_code = ?");
|
|
$stmt->execute([$code]);
|
|
$subscriber = $stmt->fetch();
|
|
|
|
if ($subscriber) {
|
|
$table = 'contact_messages';
|
|
$type = 'contact';
|
|
}
|
|
}
|
|
|
|
// If no record was found at all
|
|
if (!$subscriber) {
|
|
Logger::error("Invalid verification code attempted: $code");
|
|
View::render('pages/verify_failed', [
|
|
'reason' => 'That link is invalid. You may need to start a new submission.',
|
|
'redirect' => true
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Handle expired code case
|
|
if (!empty($subscriber['verification_expires_at']) && strtotime($subscriber['verification_expires_at']) < time()) {
|
|
Logger::info("Verification link expired: $code");
|
|
View::render('pages/verify_failed', [
|
|
'reason' => 'Your verification link has expired. Please request a new one.',
|
|
'type' => $type ?? 'unknown'
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Log the verification attempt regardless of outcome
|
|
$safeType = in_array($type, ['contact', 'newsletter', 'contact+newsletter'], true) ? $type : 'unknown';
|
|
$logAttempt = $db->prepare("
|
|
INSERT INTO verification_attempts (email, type, attempted_at, ip_address, user_agent)
|
|
VALUES (?, ?, NOW(), ?, ?)
|
|
");
|
|
$logAttempt->execute([
|
|
$subscriber['email'] ?? '[unknown]',
|
|
$safeType,
|
|
$_SERVER['REMOTE_ADDR'] ?? 'unknown',
|
|
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
|
|
]);
|
|
|
|
// If already verified
|
|
if ((int) $subscriber['is_verified'] === 1) {
|
|
View::render('pages/verify_success', [
|
|
'type' => $type ?? 'unknown',
|
|
'message' => 'This submission has already been verified.'
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Mark the submission as verified
|
|
$update = $db->prepare("UPDATE $table SET is_verified = 1 WHERE id = ?");
|
|
$update->execute([$subscriber['id']]);
|
|
|
|
Logger::info("Subscriber verified: ID {$subscriber['id']} via $type");
|
|
|
|
// Handle post-verification logic for contact submissions
|
|
if ($type === 'contact') {
|
|
$stmt = $db->prepare("
|
|
SELECT first_name, last_name, subject, message, pending_newsletter_opt_in
|
|
FROM contact_messages WHERE id = ?
|
|
");
|
|
$stmt->execute([$subscriber['id']]);
|
|
$details = $stmt->fetch();
|
|
|
|
$emailData = [
|
|
'email' => $subscriber['email'],
|
|
'first_name' => $details['first_name'] ?? '',
|
|
'last_name' => $details['last_name'] ?? '',
|
|
'subject' => $details['subject'] ?? '',
|
|
'message' => $details['message'] ?? '',
|
|
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
|
|
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
|
|
];
|
|
|
|
// If opted in to newsletter from contact form
|
|
if (!empty($details['pending_newsletter_opt_in'])) {
|
|
$this->emailService->sendContactAndNewsletterWelcome($emailData);
|
|
|
|
$db->prepare("UPDATE contact_messages SET pending_newsletter_opt_in = 0 WHERE id = ?")
|
|
->execute([$subscriber['id']]);
|
|
|
|
$db->prepare("
|
|
INSERT INTO subscribers (email, is_verified, created_at)
|
|
VALUES (?, 1, NOW())
|
|
ON DUPLICATE KEY UPDATE is_verified = 1
|
|
")->execute([$subscriber['email']]);
|
|
|
|
$type = 'contact+newsletter'; // Refined to reflect both intents
|
|
} else {
|
|
$this->emailService->sendConfirmationToUser($emailData);
|
|
}
|
|
|
|
$this->emailService->sendSalesNotification($emailData);
|
|
}
|
|
|
|
// Final success render
|
|
View::render('pages/verify_success', [
|
|
'type' => $type ?? 'unknown',
|
|
'message' => null
|
|
]);
|
|
|
|
} catch (\Throwable $e) {
|
|
Logger::error("Verification exception: " . $e->getMessage());
|
|
View::render('pages/verify_failed', [
|
|
'reason' => 'An error occurred during verification.',
|
|
'redirect' => true
|
|
]);
|
|
}
|
|
}
|
|
|
|
}
|