Newwebshop/app/Admin/controllers/AdminNewsletterController.php

522 lines
18 KiB
PHP

<?php
/**
* Copyright seit 2024 Webshop System
*
* Admin-Newsletter-Controller für das Webshop-System
*
* @author Webshop System
* @license GPL v3
*/
namespace App\Admin\Controllers;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception;
class AdminNewsletterController
{
public function index()
{
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);
// 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 <noreply@webshop-system.de>' . "\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;
}
}