Newwebshop/app/controllers/admin/ShopController.php

485 lines
14 KiB
PHP

<?php
/**
* Copyright seit 2024 Webshop System
*
* Shop Controller für das Admin-Bereich
*
* @author Webshop System
* @license GPL v3
*/
namespace App\Controllers\Admin;
use App\Core\MultiShop;
use App\Core\SessionHandler;
use App\Core\Configuration;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception;
class ShopController extends AdminController
{
private $multiShop;
public function __construct()
{
parent::__construct();
$this->multiShop = new MultiShop();
}
/**
* Shop-Übersicht
*/
public function index()
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
$shops = $this->multiShop->getAllShops();
$currentShop = $this->multiShop->getCurrentShop();
// Statistiken für jeden Shop
$shopStats = [];
foreach ($shops as $shop) {
$shopStats[$shop['id']] = $this->multiShop->getShopStatistics($shop['id']);
}
$this->render('admin/shop/index.html.twig', [
'title' => 'Shop-Verwaltung',
'shops' => $shops,
'current_shop' => $currentShop,
'shop_stats' => $shopStats
]);
}
/**
* Shop erstellen
*/
public function create()
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$this->handleShopCreate();
}
$this->render('admin/shop/create.html.twig', [
'title' => 'Neuen Shop erstellen'
]);
}
/**
* Shop bearbeiten
*/
public function edit($id)
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
$shop = $this->multiShop->getShop($id);
if (!$shop) {
$this->addFlashMessage('Shop nicht gefunden', 'error');
$this->redirect('/admin/shop');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$this->handleShopUpdate($id);
}
$shopConfig = $this->getShopConfiguration($id);
$this->render('admin/shop/edit.html.twig', [
'title' => 'Shop bearbeiten: ' . $shop['name'],
'shop' => $shop,
'shop_config' => $shopConfig
]);
}
/**
* Shop löschen
*/
public function delete($id)
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
$shop = $this->multiShop->getShop($id);
if (!$shop) {
$this->addFlashMessage('Shop nicht gefunden', 'error');
$this->redirect('/admin/shop');
}
if ($shop['is_default']) {
$this->addFlashMessage('Standard-Shop kann nicht gelöscht werden', 'error');
$this->redirect('/admin/shop');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($this->multiShop->deleteShop($id)) {
$this->addFlashMessage('Shop erfolgreich gelöscht', 'success');
} else {
$this->addFlashMessage('Fehler beim Löschen des Shops', 'error');
}
$this->redirect('/admin/shop');
}
$this->render('admin/shop/delete.html.twig', [
'title' => 'Shop löschen: ' . $shop['name'],
'shop' => $shop
]);
}
/**
* Shop-Konfiguration
*/
public function config($id)
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
$shop = $this->multiShop->getShop($id);
if (!$shop) {
$this->addFlashMessage('Shop nicht gefunden', 'error');
$this->redirect('/admin/shop');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$this->handleConfigUpdate($id);
}
$shopConfig = $this->getShopConfiguration($id);
$availableCurrencies = $this->getAvailableCurrencies();
$availableLanguages = $this->getAvailableLanguages();
$availableCountries = $this->getAvailableCountries();
$this->render('admin/shop/config.html.twig', [
'title' => 'Shop-Konfiguration: ' . $shop['name'],
'shop' => $shop,
'shop_config' => $shopConfig,
'currencies' => $availableCurrencies,
'languages' => $availableLanguages,
'countries' => $availableCountries
]);
}
/**
* Shop-Statistiken
*/
public function statistics($id)
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
$shop = $this->multiShop->getShop($id);
if (!$shop) {
$this->addFlashMessage('Shop nicht gefunden', 'error');
$this->redirect('/admin/shop');
}
$statistics = $this->multiShop->getShopStatistics($id);
$recentOrders = $this->getRecentOrders($id);
$topProducts = $this->getTopProducts($id);
$customerGrowth = $this->getCustomerGrowth($id);
$this->render('admin/shop/statistics.html.twig', [
'title' => 'Shop-Statistiken: ' . $shop['name'],
'shop' => $shop,
'statistics' => $statistics,
'recent_orders' => $recentOrders,
'top_products' => $topProducts,
'customer_growth' => $customerGrowth
]);
}
/**
* Shop-Wechsel
*/
public function switch($id)
{
if (!$this->checkAdminSession()) {
$this->redirect('/admin/login');
}
if ($this->multiShop->switchShop($id)) {
$this->addFlashMessage('Shop gewechselt', 'success');
} else {
$this->addFlashMessage('Fehler beim Shop-Wechsel', 'error');
}
$this->redirect('/admin/shop');
}
/**
* Shop erstellen verarbeiten
*/
private function handleShopCreate()
{
$data = [
'name' => $_POST['name'] ?? '',
'description' => $_POST['description'] ?? '',
'domain' => $_POST['domain'] ?? '',
'ssl_enabled' => isset($_POST['ssl_enabled']),
'force_ssl' => isset($_POST['force_ssl']),
'active' => isset($_POST['active']),
'sort_order' => intval($_POST['sort_order'] ?? 0)
];
// Validierung
if (empty($data['name'])) {
$this->addFlashMessage('Shop-Name ist erforderlich', 'error');
return;
}
if (!empty($data['domain']) && !$this->multiShop->validateShopDomain($data['domain'])) {
$this->addFlashMessage('Domain ist bereits vergeben oder ungültig', 'error');
return;
}
$shopId = $this->multiShop->createShop($data);
if ($shopId) {
$this->addFlashMessage('Shop erfolgreich erstellt', 'success');
$this->redirect('/admin/shop');
} else {
$this->addFlashMessage('Fehler beim Erstellen des Shops', 'error');
}
}
/**
* Shop aktualisieren verarbeiten
*/
private function handleShopUpdate($id)
{
$data = [
'name' => $_POST['name'] ?? '',
'description' => $_POST['description'] ?? '',
'domain' => $_POST['domain'] ?? '',
'ssl_enabled' => isset($_POST['ssl_enabled']),
'force_ssl' => isset($_POST['force_ssl']),
'active' => isset($_POST['active']),
'sort_order' => intval($_POST['sort_order'] ?? 0)
];
// Validierung
if (empty($data['name'])) {
$this->addFlashMessage('Shop-Name ist erforderlich', 'error');
return;
}
if (!empty($data['domain']) && !$this->multiShop->validateShopDomain($data['domain'], $id)) {
$this->addFlashMessage('Domain ist bereits vergeben oder ungültig', 'error');
return;
}
if ($this->multiShop->updateShop($id, $data)) {
$this->addFlashMessage('Shop erfolgreich aktualisiert', 'success');
$this->redirect('/admin/shop');
} else {
$this->addFlashMessage('Fehler beim Aktualisieren des Shops', 'error');
}
}
/**
* Konfiguration aktualisieren
*/
private function handleConfigUpdate($id)
{
$configKeys = [
'SHOP_NAME', 'SHOP_DESCRIPTION', 'SHOP_EMAIL', 'SHOP_PHONE',
'SHOP_ADDRESS', 'SHOP_CITY', 'SHOP_POSTAL_CODE', 'SHOP_COUNTRY',
'SHOP_CURRENCY', 'SHOP_LANGUAGE', 'SHOP_TIMEZONE',
'SHOP_DATE_FORMAT', 'SHOP_TIME_FORMAT', 'SHOP_TAX_RATE',
'SHOP_SHIPPING_COST', 'SHOP_FREE_SHIPPING_THRESHOLD',
'SHOP_MIN_ORDER_AMOUNT', 'SHOP_MAX_ORDER_AMOUNT',
'SHOP_STOCK_WARNING', 'SHOP_REVIEWS_ENABLED',
'SHOP_NEWSLETTER_ENABLED', 'SHOP_MAINTENANCE_MODE',
'SHOP_MAINTENANCE_MESSAGE'
];
foreach ($configKeys as $key) {
$value = $_POST[strtolower($key)] ?? '';
$this->multiShop->setShopConfig($key, $value);
}
$this->addFlashMessage('Shop-Konfiguration aktualisiert', 'success');
$this->redirect("/admin/shop/config/$id");
}
/**
* Shop-Konfiguration abrufen
*/
private function getShopConfiguration($shopId)
{
$config = [];
$configKeys = [
'SHOP_NAME', 'SHOP_DESCRIPTION', 'SHOP_EMAIL', 'SHOP_PHONE',
'SHOP_ADDRESS', 'SHOP_CITY', 'SHOP_POSTAL_CODE', 'SHOP_COUNTRY',
'SHOP_CURRENCY', 'SHOP_LANGUAGE', 'SHOP_TIMEZONE',
'SHOP_DATE_FORMAT', 'SHOP_TIME_FORMAT', 'SHOP_TAX_RATE',
'SHOP_SHIPPING_COST', 'SHOP_FREE_SHIPPING_THRESHOLD',
'SHOP_MIN_ORDER_AMOUNT', 'SHOP_MAX_ORDER_AMOUNT',
'SHOP_STOCK_WARNING', 'SHOP_REVIEWS_ENABLED',
'SHOP_NEWSLETTER_ENABLED', 'SHOP_MAINTENANCE_MODE',
'SHOP_MAINTENANCE_MESSAGE'
];
foreach ($configKeys as $key) {
$config[strtolower($key)] = $this->multiShop->getShopConfig($key, '');
}
return $config;
}
/**
* Verfügbare Währungen
*/
private function getAvailableCurrencies()
{
return [
'EUR' => 'Euro (€)',
'USD' => 'US Dollar ($)',
'GBP' => 'British Pound (£)',
'CHF' => 'Swiss Franc (CHF)',
'JPY' => 'Japanese Yen (¥)',
'CAD' => 'Canadian Dollar (C$)',
'AUD' => 'Australian Dollar (A$)'
];
}
/**
* Verfügbare Sprachen
*/
private function getAvailableLanguages()
{
return [
'de' => 'Deutsch',
'en' => 'English',
'fr' => 'Français',
'es' => 'Español',
'it' => 'Italiano',
'nl' => 'Nederlands',
'pl' => 'Polski',
'ru' => 'Русский'
];
}
/**
* Verfügbare Länder
*/
private function getAvailableCountries()
{
try {
$stmt = $this->conn->prepare('
SELECT code, name FROM ws_country
WHERE active = 1
ORDER BY name ASC
');
$stmt->execute();
$countries = $stmt->fetchAllAssociative();
$result = [];
foreach ($countries as $country) {
$result[$country['code']] = $country['name'];
}
return $result;
} catch (Exception $e) {
return [
'DE' => 'Deutschland',
'AT' => 'Österreich',
'CH' => 'Schweiz',
'US' => 'United States',
'GB' => 'United Kingdom',
'FR' => 'France',
'IT' => 'Italy',
'ES' => 'Spain'
];
}
}
/**
* Letzte Bestellungen
*/
private function getRecentOrders($shopId)
{
try {
$stmt = $this->conn->prepare('
SELECT o.*, c.first_name, c.last_name
FROM ws_order o
LEFT JOIN ws_customer c ON o.customer_id = c.id
WHERE o.shop_id = ?
ORDER BY o.created_at DESC
LIMIT 10
');
$stmt->execute([$shopId]);
return $stmt->fetchAllAssociative();
} catch (Exception $e) {
return [];
}
}
/**
* Top-Produkte
*/
private function getTopProducts($shopId)
{
try {
$stmt = $this->conn->prepare('
SELECT p.*,
COUNT(oi.id) as order_count,
SUM(oi.quantity) as total_quantity,
SUM(oi.price * oi.quantity) as total_revenue
FROM ws_product p
LEFT JOIN ws_order_item oi ON p.id = oi.product_id
LEFT JOIN ws_order o ON oi.order_id = o.id
WHERE p.shop_id = ? AND o.status = "completed"
GROUP BY p.id
ORDER BY total_revenue DESC
LIMIT 10
');
$stmt->execute([$shopId]);
return $stmt->fetchAllAssociative();
} catch (Exception $e) {
return [];
}
}
/**
* Kundenwachstum
*/
private function getCustomerGrowth($shopId)
{
try {
$stmt = $this->conn->prepare('
SELECT DATE(created_at) as date,
COUNT(*) as new_customers
FROM ws_customer
WHERE shop_id = ?
AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY DATE(created_at)
ORDER BY date ASC
');
$stmt->execute([$shopId]);
return $stmt->fetchAllAssociative();
} catch (Exception $e) {
return [];
}
}
}