sendError('Method not allowed', 405); } $input = json_decode(file_get_contents('php://input'), true); if (!$input) { $this->sendError('Invalid JSON input', 400); } if (empty($input['email'])) { $this->sendError('Email is required', 400); } if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) { $this->sendError('Invalid email address', 400); } try { // Prüfen ob bereits abonniert $stmt = $this->conn->prepare(' SELECT id, active FROM ws_newsletter_subscriber WHERE email = ? '); $stmt->execute([$input['email']]); $existing = $stmt->fetchAssociative(); if ($existing) { if ($existing['active']) { $this->sendError('Email is already subscribed', 409); } else { // Reaktivieren $stmt = $this->conn->prepare(' UPDATE ws_newsletter_subscriber SET active = 1, updated_at = NOW() WHERE id = ? '); $stmt->execute([$existing['id']]); $this->sendResponse([ 'success' => true, 'message' => 'Newsletter subscription reactivated' ]); return; } } // Neues Abonnement erstellen $stmt = $this->conn->prepare(' INSERT INTO ws_newsletter_subscriber (email, first_name, last_name, preferences, active, created_at) VALUES (?, ?, ?, ?, 1, NOW()) '); $stmt->execute([ $input['email'], $input['first_name'] ?? '', $input['last_name'] ?? '', json_encode($input['preferences'] ?? []) ]); $subscriberId = $this->conn->lastInsertId(); // Willkommens-E-Mail senden $this->sendWelcomeEmail($input['email'], $input['first_name'] ?? ''); $this->sendResponse([ 'success' => true, 'data' => [ 'subscriber_id' => $subscriberId ], 'message' => 'Newsletter subscription successful' ]); } catch (Exception $e) { $this->sendError('Failed to subscribe: ' . $e->getMessage(), 500); } } /** * Newsletter abbestellen */ public function unsubscribe() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') { $this->sendError('Method not allowed', 405); } $input = json_decode(file_get_contents('php://input'), true); if (!$input) { $this->sendError('Invalid JSON input', 400); } if (empty($input['email'])) { $this->sendError('Email is required', 400); } if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) { $this->sendError('Invalid email address', 400); } try { $stmt = $this->conn->prepare(' UPDATE ws_newsletter_subscriber SET active = 0, unsubscribed_at = NOW() WHERE email = ? '); $stmt->execute([$input['email']]); if ($stmt->rowCount() === 0) { $this->sendError('Email not found in subscribers', 404); } $this->sendResponse([ 'success' => true, 'message' => 'Newsletter unsubscribed successfully' ]); } catch (Exception $e) { $this->sendError('Failed to unsubscribe: ' . $e->getMessage(), 500); } } /** * Newsletter-Präferenzen aktualisieren */ public function updatePreferences($subscriberId) { if ($_SERVER['REQUEST_METHOD'] !== 'PUT') { $this->sendError('Method not allowed', 405); } $input = json_decode(file_get_contents('php://input'), true); if (!$input) { $this->sendError('Invalid JSON input', 400); } try { $updateFields = []; $params = []; if (isset($input['first_name'])) { $updateFields[] = 'first_name = ?'; $params[] = $input['first_name']; } if (isset($input['last_name'])) { $updateFields[] = 'last_name = ?'; $params[] = $input['last_name']; } if (isset($input['preferences'])) { $updateFields[] = 'preferences = ?'; $params[] = json_encode($input['preferences']); } if (empty($updateFields)) { $this->sendError('No fields to update', 400); } $updateFields[] = 'updated_at = NOW()'; $params[] = $subscriberId; $sql = 'UPDATE ws_newsletter_subscriber SET ' . implode(', ', $updateFields) . ' WHERE id = ?'; $stmt = $this->conn->prepare($sql); $stmt->execute($params); if ($stmt->rowCount() === 0) { $this->sendError('Subscriber not found', 404); } $this->sendResponse([ 'success' => true, 'message' => 'Preferences updated successfully' ]); } catch (Exception $e) { $this->sendError('Failed to update preferences: ' . $e->getMessage(), 500); } } /** * Newsletter-Templates abrufen */ public function getTemplates() { try { $stmt = $this->conn->prepare(' SELECT id, name, subject, content, active, created_at FROM ws_newsletter_template WHERE active = 1 ORDER BY name ASC '); $stmt->execute(); $templates = $stmt->fetchAllAssociative(); $this->sendResponse([ 'success' => true, 'data' => $templates ]); } catch (Exception $e) { $this->sendError('Failed to fetch templates: ' . $e->getMessage(), 500); } } /** * Newsletter senden */ public function sendNewsletter() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') { $this->sendError('Method not allowed', 405); } $input = json_decode(file_get_contents('php://input'), true); if (!$input) { $this->sendError('Invalid JSON input', 400); } if (empty($input['template_id']) || empty($input['subject'])) { $this->sendError('Template ID and subject are required', 400); } try { // Template abrufen $stmt = $this->conn->prepare(' SELECT * FROM ws_newsletter_template WHERE id = ? AND active = 1 '); $stmt->execute([$input['template_id']]); $template = $stmt->fetchAssociative(); if (!$template) { $this->sendError('Template not found', 404); } // Aktive Abonnenten abrufen $stmt = $this->conn->prepare(' SELECT id, email, first_name, last_name, preferences FROM ws_newsletter_subscriber WHERE active = 1 '); $stmt->execute(); $subscribers = $stmt->fetchAllAssociative(); if (empty($subscribers)) { $this->sendError('No active subscribers found', 400); } $sentCount = 0; $failedCount = 0; foreach ($subscribers as $subscriber) { try { $this->sendNewsletterEmail($subscriber, $template, $input['subject']); $sentCount++; } catch (Exception $e) { $failedCount++; } } // Newsletter-Log erstellen $stmt = $this->conn->prepare(' INSERT INTO ws_newsletter_log (template_id, subject, sent_count, failed_count, created_at) VALUES (?, ?, ?, ?, NOW()) '); $stmt->execute([ $input['template_id'], $input['subject'], $sentCount, $failedCount ]); $this->sendResponse([ 'success' => true, 'data' => [ 'sent_count' => $sentCount, 'failed_count' => $failedCount, 'total_subscribers' => count($subscribers) ], 'message' => 'Newsletter sent successfully' ]); } catch (Exception $e) { $this->sendError('Failed to send newsletter: ' . $e->getMessage(), 500); } } /** * Newsletter-Statistiken */ public function getStats() { try { // Abonnenten-Statistiken $stmt = $this->conn->prepare(' SELECT COUNT(*) as total_subscribers, COUNT(CASE WHEN active = 1 THEN 1 END) as active_subscribers, COUNT(CASE WHEN active = 0 THEN 1 END) as inactive_subscribers FROM ws_newsletter_subscriber '); $stmt->execute(); $subscriberStats = $stmt->fetchAssociative(); // Newsletter-Log-Statistiken $stmt = $this->conn->prepare(' SELECT COUNT(*) as total_campaigns, SUM(sent_count) as total_sent, SUM(failed_count) as total_failed, AVG(sent_count) as avg_sent_per_campaign FROM ws_newsletter_log '); $stmt->execute(); $campaignStats = $stmt->fetchAssociative(); // Template-Statistiken $stmt = $this->conn->prepare(' SELECT COUNT(*) as total_templates FROM ws_newsletter_template WHERE active = 1 '); $stmt->execute(); $templateStats = $stmt->fetchAssociative(); $this->sendResponse([ 'success' => true, 'data' => [ 'subscribers' => $subscriberStats, 'campaigns' => $campaignStats, 'templates' => $templateStats ] ]); } catch (Exception $e) { $this->sendError('Failed to get newsletter stats: ' . $e->getMessage(), 500); } } /** * Willkommens-E-Mail senden */ private function sendWelcomeEmail($email, $firstName) { $subject = 'Willkommen beim Newsletter!'; $message = "
Hallo " . htmlspecialchars($firstName ?: 'Lieber Kunde') . ",
Vielen Dank für Ihr Abonnement unseres Newsletters. Sie erhalten nun regelmäßig Informationen über:
Falls Sie den Newsletter nicht mehr erhalten möchten, können Sie sich jederzeit hier abmelden.
Mit freundlichen Grüßen
Ihr Webshop-Team
' . htmlspecialchars($category['description']) . '
'; } return $content; } catch (Exception $e) { return ''; } } /** * E-Mail senden */ private function sendEmail($to, $subject, $message) { $headers = [ 'MIME-Version: 1.0', 'Content-type: text/html; charset=UTF-8', 'From: ' . (getenv('MAIL_FROM') ?: 'noreply@webshop.local'), 'Reply-To: ' . (getenv('MAIL_REPLY_TO') ?: 'support@webshop.local'), 'X-Mailer: Webshop System' ]; $result = mail($to, $subject, $message, implode("\r\n", $headers)); if (!$result) { throw new Exception('Failed to send email'); } } }