523 lines
18 KiB
PHP
523 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* Copyright seit 2024 Webshop System
|
|
*
|
|
* Frontend-Kunden-Controller für das Webshop-System
|
|
*
|
|
* @author Webshop System
|
|
* @license GPL v3
|
|
*/
|
|
|
|
namespace App\Front\Controllers;
|
|
|
|
use Doctrine\DBAL\DriverManager;
|
|
use Doctrine\DBAL\Exception;
|
|
|
|
class CustomerController
|
|
{
|
|
public function register()
|
|
{
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->processRegistration();
|
|
} else {
|
|
$this->render('front/customer/register.html.twig', [
|
|
'title' => 'Webshop - Registrierung'
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function processRegistration()
|
|
{
|
|
$email = $_POST['email'] ?? '';
|
|
$password = $_POST['password'] ?? '';
|
|
$confirmPassword = $_POST['confirm_password'] ?? '';
|
|
$firstName = $_POST['first_name'] ?? '';
|
|
$lastName = $_POST['last_name'] ?? '';
|
|
$phone = $_POST['phone'] ?? '';
|
|
$newsletter = isset($_POST['newsletter']) ? 1 : 0;
|
|
|
|
// Validierung
|
|
$errors = [];
|
|
|
|
if (empty($email)) {
|
|
$errors[] = 'E-Mail-Adresse ist erforderlich';
|
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
$errors[] = 'Ungültige E-Mail-Adresse';
|
|
}
|
|
|
|
if (empty($password)) {
|
|
$errors[] = 'Passwort ist erforderlich';
|
|
} elseif (strlen($password) < 6) {
|
|
$errors[] = 'Passwort muss mindestens 6 Zeichen lang sein';
|
|
}
|
|
|
|
if ($password !== $confirmPassword) {
|
|
$errors[] = 'Passwörter stimmen nicht überein';
|
|
}
|
|
|
|
if (empty($firstName)) {
|
|
$errors[] = 'Vorname ist erforderlich';
|
|
}
|
|
|
|
if (empty($lastName)) {
|
|
$errors[] = 'Nachname ist erforderlich';
|
|
}
|
|
|
|
if (!empty($errors)) {
|
|
$this->render('front/customer/register.html.twig', [
|
|
'title' => 'Webshop - Registrierung',
|
|
'errors' => $errors,
|
|
'old' => $_POST
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// DB-Verbindung herstellen
|
|
$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);
|
|
|
|
// Prüfen ob E-Mail bereits existiert
|
|
$stmt = $conn->prepare('SELECT id FROM ws_customer WHERE email = ?');
|
|
$stmt->execute([$email]);
|
|
$existingCustomer = $stmt->fetchAssociative();
|
|
|
|
if ($existingCustomer) {
|
|
$this->render('front/customer/register.html.twig', [
|
|
'title' => 'Webshop - Registrierung',
|
|
'errors' => ['E-Mail-Adresse ist bereits registriert'],
|
|
'old' => $_POST
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Kunde erstellen
|
|
$stmt = $conn->prepare('
|
|
INSERT INTO ws_customer (email, password, first_name, last_name, phone, newsletter, active, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, 1, NOW())
|
|
');
|
|
|
|
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt->execute([$email, $hashedPassword, $firstName, $lastName, $phone, $newsletter]);
|
|
|
|
$customerId = $conn->lastInsertId();
|
|
|
|
// Session starten
|
|
session_start();
|
|
$_SESSION['customer_id'] = $customerId;
|
|
$_SESSION['customer_email'] = $email;
|
|
$_SESSION['customer_name'] = $firstName . ' ' . $lastName;
|
|
|
|
// Willkommens-E-Mail senden
|
|
$this->sendWelcomeEmail($email, $firstName);
|
|
|
|
// Weiterleitung zum Kundenkonto
|
|
header('Location: /account');
|
|
exit;
|
|
|
|
} catch (Exception $e) {
|
|
$this->render('front/customer/register.html.twig', [
|
|
'title' => 'Webshop - Registrierung',
|
|
'errors' => ['Registrierungsfehler: ' . $e->getMessage()],
|
|
'old' => $_POST
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function login()
|
|
{
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->processLogin();
|
|
} else {
|
|
$this->render('front/customer/login.html.twig', [
|
|
'title' => 'Webshop - Anmeldung'
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function processLogin()
|
|
{
|
|
$email = $_POST['email'] ?? '';
|
|
$password = $_POST['password'] ?? '';
|
|
$remember = isset($_POST['remember']);
|
|
|
|
if (empty($email) || empty($password)) {
|
|
$this->render('front/customer/login.html.twig', [
|
|
'title' => 'Webshop - Anmeldung',
|
|
'errors' => ['E-Mail und Passwort 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('
|
|
SELECT id, email, password, first_name, last_name, active
|
|
FROM ws_customer
|
|
WHERE email = ?
|
|
');
|
|
$stmt->execute([$email]);
|
|
$customer = $stmt->fetchAssociative();
|
|
|
|
if (!$customer || !password_verify($password, $customer['password'])) {
|
|
$this->render('front/customer/login.html.twig', [
|
|
'title' => 'Webshop - Anmeldung',
|
|
'errors' => ['Ungültige E-Mail oder Passwort'],
|
|
'old' => $_POST
|
|
]);
|
|
return;
|
|
}
|
|
|
|
if (!$customer['active']) {
|
|
$this->render('front/customer/login.html.twig', [
|
|
'title' => 'Webshop - Anmeldung',
|
|
'errors' => ['Ihr Konto ist deaktiviert'],
|
|
'old' => $_POST
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Session starten
|
|
session_start();
|
|
$_SESSION['customer_id'] = $customer['id'];
|
|
$_SESSION['customer_email'] = $customer['email'];
|
|
$_SESSION['customer_name'] = $customer['first_name'] . ' ' . $customer['last_name'];
|
|
|
|
// Remember Me
|
|
if ($remember) {
|
|
$token = bin2hex(random_bytes(32));
|
|
$stmt = $conn->prepare('
|
|
INSERT INTO ws_customer_token (customer_id, token, expires_at)
|
|
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 30 DAY))
|
|
');
|
|
$stmt->execute([$customer['id'], $token]);
|
|
|
|
setcookie('remember_token', $token, time() + (30 * 24 * 60 * 60), '/', '', true, true);
|
|
}
|
|
|
|
// Weiterleitung
|
|
$redirect = $_GET['redirect'] ?? '/account';
|
|
header('Location: ' . $redirect);
|
|
exit;
|
|
|
|
} catch (Exception $e) {
|
|
$this->render('front/customer/login.html.twig', [
|
|
'title' => 'Webshop - Anmeldung',
|
|
'errors' => ['Anmeldefehler: ' . $e->getMessage()],
|
|
'old' => $_POST
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function logout()
|
|
{
|
|
session_start();
|
|
session_destroy();
|
|
|
|
// Remember Me Token löschen
|
|
if (isset($_COOKIE['remember_token'])) {
|
|
$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_customer_token WHERE token = ?');
|
|
$stmt->execute([$_COOKIE['remember_token']]);
|
|
} catch (Exception $e) {
|
|
// Ignore errors
|
|
}
|
|
|
|
setcookie('remember_token', '', time() - 3600, '/');
|
|
}
|
|
|
|
header('Location: /');
|
|
exit;
|
|
}
|
|
|
|
public function account()
|
|
{
|
|
if (!isset($_SESSION['customer_id'])) {
|
|
header('Location: /login?redirect=' . urlencode('/account'));
|
|
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);
|
|
|
|
// Kundeninformationen laden
|
|
$stmt = $conn->prepare('
|
|
SELECT * FROM ws_customer WHERE id = ?
|
|
');
|
|
$stmt->execute([$_SESSION['customer_id']]);
|
|
$customer = $stmt->fetchAssociative();
|
|
|
|
// Bestellungen laden
|
|
$stmt = $conn->prepare('
|
|
SELECT * FROM ws_order
|
|
WHERE customer_id = ?
|
|
ORDER BY created_at DESC
|
|
LIMIT 10
|
|
');
|
|
$stmt->execute([$_SESSION['customer_id']]);
|
|
$orders = $stmt->fetchAllAssociative();
|
|
|
|
// Wunschliste laden
|
|
$stmt = $conn->prepare('
|
|
SELECT w.*, p.name, p.price, p.image
|
|
FROM ws_wishlist w
|
|
LEFT JOIN ws_product p ON w.product_id = p.id
|
|
WHERE w.customer_id = ?
|
|
ORDER BY w.created_at DESC
|
|
');
|
|
$stmt->execute([$_SESSION['customer_id']]);
|
|
$wishlist = $stmt->fetchAllAssociative();
|
|
|
|
// Bewertungen laden
|
|
$stmt = $conn->prepare('
|
|
SELECT r.*, p.name as product_name, p.id as product_id
|
|
FROM ws_review r
|
|
LEFT JOIN ws_product p ON r.product_id = p.id
|
|
WHERE r.customer_id = ?
|
|
ORDER BY r.created_at DESC
|
|
');
|
|
$stmt->execute([$_SESSION['customer_id']]);
|
|
$reviews = $stmt->fetchAllAssociative();
|
|
|
|
$this->render('front/customer/account.html.twig', [
|
|
'title' => 'Webshop - Mein Konto',
|
|
'customer' => $customer,
|
|
'orders' => $orders,
|
|
'wishlist' => $wishlist,
|
|
'reviews' => $reviews
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
$this->render('front/customer/account.html.twig', [
|
|
'title' => 'Webshop - Mein Konto',
|
|
'error' => 'Fehler beim Laden der Daten: ' . $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function profile()
|
|
{
|
|
if (!isset($_SESSION['customer_id'])) {
|
|
header('Location: /login?redirect=' . urlencode('/profile'));
|
|
exit;
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->updateProfile();
|
|
} else {
|
|
$this->loadProfile();
|
|
}
|
|
}
|
|
|
|
private function loadProfile()
|
|
{
|
|
$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_customer WHERE id = ?');
|
|
$stmt->execute([$_SESSION['customer_id']]);
|
|
$customer = $stmt->fetchAssociative();
|
|
|
|
$this->render('front/customer/profile.html.twig', [
|
|
'title' => 'Webshop - Profil bearbeiten',
|
|
'customer' => $customer
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
$this->render('front/customer/profile.html.twig', [
|
|
'title' => 'Webshop - Profil bearbeiten',
|
|
'error' => 'Fehler beim Laden der Daten: ' . $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function updateProfile()
|
|
{
|
|
$firstName = $_POST['first_name'] ?? '';
|
|
$lastName = $_POST['last_name'] ?? '';
|
|
$phone = $_POST['phone'] ?? '';
|
|
$newsletter = isset($_POST['newsletter']) ? 1 : 0;
|
|
$currentPassword = $_POST['current_password'] ?? '';
|
|
$newPassword = $_POST['new_password'] ?? '';
|
|
$confirmPassword = $_POST['confirm_password'] ?? '';
|
|
|
|
$errors = [];
|
|
|
|
if (empty($firstName)) {
|
|
$errors[] = 'Vorname ist erforderlich';
|
|
}
|
|
|
|
if (empty($lastName)) {
|
|
$errors[] = 'Nachname ist erforderlich';
|
|
}
|
|
|
|
if (!empty($newPassword)) {
|
|
if (empty($currentPassword)) {
|
|
$errors[] = 'Aktuelles Passwort ist erforderlich';
|
|
}
|
|
|
|
if (strlen($newPassword) < 6) {
|
|
$errors[] = 'Neues Passwort muss mindestens 6 Zeichen lang sein';
|
|
}
|
|
|
|
if ($newPassword !== $confirmPassword) {
|
|
$errors[] = 'Neue Passwörter stimmen nicht überein';
|
|
}
|
|
}
|
|
|
|
if (!empty($errors)) {
|
|
$this->render('front/customer/profile.html.twig', [
|
|
'title' => 'Webshop - Profil bearbeiten',
|
|
'errors' => $errors,
|
|
'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);
|
|
|
|
// Aktuelles Passwort prüfen
|
|
if (!empty($newPassword)) {
|
|
$stmt = $conn->prepare('SELECT password FROM ws_customer WHERE id = ?');
|
|
$stmt->execute([$_SESSION['customer_id']]);
|
|
$customer = $stmt->fetchAssociative();
|
|
|
|
if (!password_verify($currentPassword, $customer['password'])) {
|
|
$this->render('front/customer/profile.html.twig', [
|
|
'title' => 'Webshop - Profil bearbeiten',
|
|
'errors' => ['Aktuelles Passwort ist falsch'],
|
|
'old' => $_POST
|
|
]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Profil aktualisieren
|
|
if (!empty($newPassword)) {
|
|
$hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT);
|
|
$stmt = $conn->prepare('
|
|
UPDATE ws_customer
|
|
SET first_name = ?, last_name = ?, phone = ?, newsletter = ?, password = ?, updated_at = NOW()
|
|
WHERE id = ?
|
|
');
|
|
$stmt->execute([$firstName, $lastName, $phone, $newsletter, $hashedPassword, $_SESSION['customer_id']]);
|
|
} else {
|
|
$stmt = $conn->prepare('
|
|
UPDATE ws_customer
|
|
SET first_name = ?, last_name = ?, phone = ?, newsletter = ?, updated_at = NOW()
|
|
WHERE id = ?
|
|
');
|
|
$stmt->execute([$firstName, $lastName, $phone, $newsletter, $_SESSION['customer_id']]);
|
|
}
|
|
|
|
// Session aktualisieren
|
|
$_SESSION['customer_name'] = $firstName . ' ' . $lastName;
|
|
|
|
$this->render('front/customer/profile.html.twig', [
|
|
'title' => 'Webshop - Profil bearbeiten',
|
|
'success' => 'Profil erfolgreich aktualisiert',
|
|
'customer' => [
|
|
'first_name' => $firstName,
|
|
'last_name' => $lastName,
|
|
'phone' => $phone,
|
|
'newsletter' => $newsletter
|
|
]
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
$this->render('front/customer/profile.html.twig', [
|
|
'title' => 'Webshop - Profil bearbeiten',
|
|
'errors' => ['Fehler beim Aktualisieren: ' . $e->getMessage()],
|
|
'old' => $_POST
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function sendWelcomeEmail($email, $firstName)
|
|
{
|
|
// Einfache E-Mail-Funktion (später durch PHPMailer ersetzen)
|
|
$to = $email;
|
|
$subject = 'Willkommen bei Webshop!';
|
|
$message = "Hallo $firstName,\n\n";
|
|
$message .= "Vielen Dank für Ihre Registrierung bei Webshop!\n";
|
|
$message .= "Sie können sich jetzt mit Ihrer E-Mail-Adresse anmelden.\n\n";
|
|
$message .= "Mit freundlichen Grüßen\n";
|
|
$message .= "Ihr Webshop-Team";
|
|
|
|
$headers = 'From: noreply@webshop-system.de' . "\r\n" .
|
|
'Reply-To: info@webshop-system.de' . "\r\n" .
|
|
'X-Mailer: PHP/' . phpversion();
|
|
|
|
mail($to, $subject, $message, $headers);
|
|
}
|
|
|
|
protected function render($template, $data = [])
|
|
{
|
|
// Einfache Template-Engine (später durch Twig ersetzen)
|
|
extract($data);
|
|
include __DIR__ . '/../../templates/' . $template;
|
|
}
|
|
}
|