getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); // Newsletter-Abonnenten laden $stmt = $conn->prepare(' SELECT n.*, c.first_name, c.last_name, c.email as customer_email FROM ws_newsletter n LEFT JOIN ws_customer c ON n.customer_id = c.id ORDER BY n.created_at DESC '); $stmt->execute(); $subscribers = $stmt->fetchAllAssociative(); // Newsletter-Templates laden $stmt = $conn->prepare('SELECT * FROM ws_newsletter_template ORDER BY created_at DESC'); $stmt->execute(); $templates = $stmt->fetchAllAssociative(); // Statistiken $stmt = $conn->prepare('SELECT COUNT(*) as total FROM ws_newsletter WHERE active = 1'); $stmt->execute(); $activeSubscribers = $stmt->fetchAssociative()['total']; $stmt = $conn->prepare('SELECT COUNT(*) as total FROM ws_newsletter WHERE active = 0'); $stmt->execute(); $inactiveSubscribers = $stmt->fetchAssociative()['total']; $this->render('admin/newsletter/index.html.twig', [ 'title' => 'Webshop Admin - Newsletter-Verwaltung', 'subscribers' => $subscribers, 'templates' => $templates, 'stats' => [ 'active' => $activeSubscribers, 'inactive' => $inactiveSubscribers, 'total' => $activeSubscribers + $inactiveSubscribers ] ]); } catch (Exception $e) { $this->render('admin/newsletter/index.html.twig', [ 'title' => 'Webshop Admin - Newsletter-Verwaltung', 'error' => 'Datenbankfehler: ' . $e->getMessage() ]); } } public function create() { if (!isset($_SESSION['admin_id'])) { header('Location: /admin/login'); exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->processCreate(); } else { $this->render('admin/newsletter/create.html.twig', [ 'title' => 'Webshop Admin - Newsletter erstellen' ]); } } private function processCreate() { $name = $_POST['name'] ?? ''; $subject = $_POST['subject'] ?? ''; $content = $_POST['content'] ?? ''; $type = $_POST['type'] ?? 'newsletter'; if (empty($name) || empty($subject) || empty($content)) { $this->render('admin/newsletter/create.html.twig', [ 'title' => 'Webshop Admin - Newsletter erstellen', 'errors' => ['Alle Felder sind erforderlich'], 'old' => $_POST ]); return; } $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); $stmt = $conn->prepare(' INSERT INTO ws_newsletter_template (name, subject, content, type, created_at) VALUES (?, ?, ?, ?, NOW()) '); $stmt->execute([$name, $subject, $content, $type]); header('Location: /admin/newsletter?success=1'); exit; } catch (Exception $e) { $this->render('admin/newsletter/create.html.twig', [ 'title' => 'Webshop Admin - Newsletter erstellen', 'errors' => ['Fehler beim Erstellen: ' . $e->getMessage()], 'old' => $_POST ]); } } public function edit($id) { if (!isset($_SESSION['admin_id'])) { header('Location: /admin/login'); exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->processEdit($id); } else { $this->loadTemplate($id); } } private function loadTemplate($id) { $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); $stmt = $conn->prepare('SELECT * FROM ws_newsletter_template WHERE id = ?'); $stmt->execute([$id]); $template = $stmt->fetchAssociative(); if (!$template) { header('Location: /admin/newsletter?error=Template nicht gefunden'); exit; } $this->render('admin/newsletter/edit.html.twig', [ 'title' => 'Webshop Admin - Newsletter bearbeiten', 'template' => $template ]); } catch (Exception $e) { header('Location: /admin/newsletter?error=' . urlencode($e->getMessage())); exit; } } private function processEdit($id) { $name = $_POST['name'] ?? ''; $subject = $_POST['subject'] ?? ''; $content = $_POST['content'] ?? ''; $type = $_POST['type'] ?? 'newsletter'; if (empty($name) || empty($subject) || empty($content)) { $this->render('admin/newsletter/edit.html.twig', [ 'title' => 'Webshop Admin - Newsletter bearbeiten', 'errors' => ['Alle Felder sind erforderlich'], 'template' => ['id' => $id] + $_POST ]); return; } $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); $stmt = $conn->prepare(' UPDATE ws_newsletter_template SET name = ?, subject = ?, content = ?, type = ?, updated_at = NOW() WHERE id = ? '); $stmt->execute([$name, $subject, $content, $type, $id]); header('Location: /admin/newsletter?success=1'); exit; } catch (Exception $e) { $this->render('admin/newsletter/edit.html.twig', [ 'title' => 'Webshop Admin - Newsletter bearbeiten', 'errors' => ['Fehler beim Aktualisieren: ' . $e->getMessage()], 'template' => ['id' => $id] + $_POST ]); } } public function delete($id) { if (!isset($_SESSION['admin_id'])) { header('Location: /admin/login'); exit; } $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); $stmt = $conn->prepare('DELETE FROM ws_newsletter_template WHERE id = ?'); $stmt->execute([$id]); header('Location: /admin/newsletter?success=1'); exit; } catch (Exception $e) { header('Location: /admin/newsletter?error=' . urlencode($e->getMessage())); exit; } } public function send($id) { if (!isset($_SESSION['admin_id'])) { header('Location: /admin/login'); exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->processSend($id); } else { $this->loadSendForm($id); } } private function loadSendForm($id) { $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); // Template laden $stmt = $conn->prepare('SELECT * FROM ws_newsletter_template WHERE id = ?'); $stmt->execute([$id]); $template = $stmt->fetchAssociative(); if (!$template) { header('Location: /admin/newsletter?error=Template nicht gefunden'); exit; } // Abonnenten laden $stmt = $conn->prepare('SELECT * FROM ws_newsletter WHERE active = 1'); $stmt->execute(); $subscribers = $stmt->fetchAllAssociative(); $this->render('admin/newsletter/send.html.twig', [ 'title' => 'Webshop Admin - Newsletter versenden', 'template' => $template, 'subscribers' => $subscribers ]); } catch (Exception $e) { header('Location: /admin/newsletter?error=' . urlencode($e->getMessage())); exit; } } private function processSend($id) { $templateId = $id; $testEmail = $_POST['test_email'] ?? ''; $sendToAll = isset($_POST['send_to_all']); $selectedSubscribers = $_POST['subscribers'] ?? []; $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); // Template laden $stmt = $conn->prepare('SELECT * FROM ws_newsletter_template WHERE id = ?'); $stmt->execute([$templateId]); $template = $stmt->fetchAssociative(); if (!$template) { throw new Exception('Template nicht gefunden'); } $sentCount = 0; $errors = []; if (!empty($testEmail)) { // Test-E-Mail senden $this->sendNewsletterEmail($template, $testEmail, 'Test Kunde'); $sentCount++; } elseif ($sendToAll) { // An alle Abonnenten senden $stmt = $conn->prepare('SELECT * FROM ws_newsletter WHERE active = 1'); $stmt->execute(); $subscribers = $stmt->fetchAllAssociative(); foreach ($subscribers as $subscriber) { try { $this->sendNewsletterEmail($template, $subscriber['email'], $subscriber['first_name']); $sentCount++; } catch (Exception $e) { $errors[] = 'Fehler bei ' . $subscriber['email'] . ': ' . $e->getMessage(); } } } elseif (!empty($selectedSubscribers)) { // An ausgewählte Abonnenten senden $placeholders = str_repeat('?,', count($selectedSubscribers) - 1) . '?'; $stmt = $conn->prepare("SELECT * FROM ws_newsletter WHERE id IN ($placeholders) AND active = 1"); $stmt->execute($selectedSubscribers); $subscribers = $stmt->fetchAllAssociative(); foreach ($subscribers as $subscriber) { try { $this->sendNewsletterEmail($template, $subscriber['email'], $subscriber['first_name']); $sentCount++; } catch (Exception $e) { $errors[] = 'Fehler bei ' . $subscriber['email'] . ': ' . $e->getMessage(); } } } // Newsletter-Log erstellen $stmt = $conn->prepare(' INSERT INTO ws_newsletter_log (template_id, sent_count, error_count, created_at) VALUES (?, ?, ?, NOW()) '); $stmt->execute([$templateId, $sentCount, count($errors)]); $message = "Newsletter erfolgreich versendet! $sentCount E-Mails gesendet."; if (!empty($errors)) { $message .= ' Fehler: ' . implode(', ', $errors); } header('Location: /admin/newsletter?success=' . urlencode($message)); exit; } catch (Exception $e) { header('Location: /admin/newsletter?error=' . urlencode($e->getMessage())); exit; } } private function sendNewsletterEmail($template, $email, $firstName) { $subject = $template['subject']; $content = $template['content']; // Platzhalter ersetzen $content = str_replace('{{first_name}}', $firstName, $content); $content = str_replace('{{email}}', $email, $content); $content = str_replace('{{unsubscribe_url}}', '/newsletter/unsubscribe?token=' . bin2hex(random_bytes(16)), $content); $headers = 'MIME-Version: 1.0' . "\r\n"; $headers .= 'Content-type: text/html; charset=UTF-8' . "\r\n"; $headers .= 'From: Webshop ' . "\r\n"; $headers .= 'Reply-To: info@webshop-system.de' . "\r\n"; $headers .= 'X-Mailer: PHP/' . phpversion(); if (!mail($email, $subject, $content, $headers)) { throw new Exception('E-Mail konnte nicht gesendet werden'); } } public function subscribers() { if (!isset($_SESSION['admin_id'])) { header('Location: /admin/login'); exit; } $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); $stmt = $conn->prepare(' SELECT n.*, c.first_name, c.last_name, c.email as customer_email FROM ws_newsletter n LEFT JOIN ws_customer c ON n.customer_id = c.id ORDER BY n.created_at DESC '); $stmt->execute(); $subscribers = $stmt->fetchAllAssociative(); $this->render('admin/newsletter/subscribers.html.twig', [ 'title' => 'Webshop Admin - Newsletter-Abonnenten', 'subscribers' => $subscribers ]); } catch (Exception $e) { $this->render('admin/newsletter/subscribers.html.twig', [ 'title' => 'Webshop Admin - Newsletter-Abonnenten', 'error' => 'Datenbankfehler: ' . $e->getMessage() ]); } } public function toggleSubscriber($id) { if (!isset($_SESSION['admin_id'])) { header('Location: /admin/login'); exit; } $connectionParams = [ 'dbname' => getenv('DB_DATABASE') ?: 'freeshop', 'user' => getenv('DB_USERNAME') ?: 'freeshop_user', 'password' => getenv('DB_PASSWORD') ?: 'freeshop_password', 'host' => getenv('DB_HOST') ?: 'db', 'driver' => 'pdo_mysql', 'port' => getenv('DB_PORT') ?: 3306, 'charset' => 'utf8mb4', ]; try { $conn = DriverManager::getConnection($connectionParams); $stmt = $conn->prepare(' UPDATE ws_newsletter SET active = NOT active, updated_at = NOW() WHERE id = ? '); $stmt->execute([$id]); header('Location: /admin/newsletter/subscribers?success=1'); exit; } catch (Exception $e) { header('Location: /admin/newsletter/subscribers?error=' . urlencode($e->getMessage())); exit; } } protected function render($template, $data = []) { // Einfache Template-Engine (später durch Twig ersetzen) extract($data); include __DIR__ . '/../../templates/' . $template; } }