Phase 2 Start: PrestaShop-Modul-Kompatibilität implementiert - Hook-System mit Registry und Execution - Module-Base-Class mit Installation/Deinstallation - Module-Controller für Admin-Verwaltung - Datenbank-Schema für Module-System - Vollständiger Plan für Phase 2 erstellt
This commit is contained in:
parent
75fdb0d594
commit
93ace0c2ae
|
|
@ -0,0 +1,281 @@
|
||||||
|
# Phase 2 Entwicklungsplan: Nachbau aller fehlenden PrestaShop-Features + Modul-Kompatibilität
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
Alle wesentlichen Funktionen von PrestaShop werden nachgebaut UND das System wird PrestaShop-Module und Addons ohne Änderungen nutzen können. Dazu wird das komplette PrestaShop-Modul-System implementiert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Übersicht & Zeitrahmen
|
||||||
|
- **Gesamtdauer:** 8-10 Wochen (inkl. PrestaShop-Kompatibilität)
|
||||||
|
- **Sprint-Länge:** 1 Woche
|
||||||
|
- **Start:** [TT.MM.JJJJ]
|
||||||
|
- **Ende (geplant):** [TT.MM.JJJJ]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aufgabenliste & Prioritäten
|
||||||
|
|
||||||
|
| Nr. | Feature/Modul | Beschreibung | Priorität | Zeitrahmen | Status |
|
||||||
|
|-----|------------------------------|-----------------------------------------------------------|-----------|------------|-----------|
|
||||||
|
| 1 | **Hook-System** | PrestaShop Hook-System für Module-Kompatibilität | KRITISCH | 1 Woche | ⬜ offen |
|
||||||
|
| 2 | **Module-Base-System** | Module-Base-Class, Installation/Deinstallation | KRITISCH | 1 Woche | ⬜ offen |
|
||||||
|
| 3 | **Override-System** | Class/Template/Controller Overrides | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 4 | **Context-System** | PrestaShop Context-API nachbauen | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 5 | **Produktvarianten** | Attribute, Kombinationen, Lager pro Variante | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 6 | **Produktbewertungen** | Kundenbewertungen, Moderation, Sterne, hilfreich | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 7 | **Gutschein-/Rabatt-System** | Gutscheine, Warenkorbregeln, Rabatte | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 8 | **Kundenkonto-Features** | Adressverwaltung, Bestellhistorie, Rücksendungen | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 9 | **Versandmethoden & Tracking** | Versandarten, Kosten, Tracking, Versandstatus | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 10 | **Produktvergleich** | Vergleichsliste, UI, Session-Handling | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 11 | **Cross-Selling & Zubehör** | Verwandte Produkte, Zubehör, Upselling | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 12 | **Wunschliste** | Kundenwunschlisten, Verwaltung, Teilen | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 13 | **Lagerverwaltung** | Bestandsführung, Warnungen, Lieferanten | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 14 | **Berichte & Statistiken** | Umsatz, Topseller, Kunden, Export | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 15 | **Import/Export** | CSV/XML Import/Export für Produkte, Kunden, Bestellungen | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 16 | **Benutzerverwaltung** | Admin-Rollen, Rechte, Logins, Audit-Log | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 17 | **E-Mail-Marketing** | Automatisierte Mails, Kampagnen, Vorlagen | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 18 | **Mehrsprachigkeit (i18n)** | Übersetzungen, Sprachumschaltung, Fallbacks | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 19 | **Template-/Theme-System** | Theme-Engine, Child-Themes, Template-Overrides | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
| 20 | **Performance-Optimierung** | Caching, Minifizierung, Bildoptimierung | MITTEL | 0,5 Woche | ⬜ offen |
|
||||||
|
| 21 | **Rechtliches & DSGVO** | Cookie-Consent, Datenschutz, AGB, Widerruf | HOCH | 0,5 Woche | ⬜ offen |
|
||||||
|
| 22 | **Social Media Integration** | Teilen, Login, Pixel, OpenGraph | NIEDRIG | 0,5 Woche | ⬜ offen |
|
||||||
|
| 23 | **Affiliate-/Partner-System** | Tracking, Provisionen, Auswertungen | NIEDRIG | 0,5 Woche | ⬜ offen |
|
||||||
|
| 24 | **PrestaShop-Module-Tests** | Test mit echten PrestaShop-Modulen | HOCH | 1 Woche | ⬜ offen |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PrestaShop Modul-System Komponenten
|
||||||
|
|
||||||
|
### 1. **Hook-System** (Priorität: KRITISCH)
|
||||||
|
```php
|
||||||
|
// PrestaShop Hook-Beispiele
|
||||||
|
Hook::exec('actionProductUpdate', ['id_product' => $id]);
|
||||||
|
Hook::exec('displayProductAdditionalInfo', ['product' => $product]);
|
||||||
|
Hook::exec('actionCartUpdateQuantityBefore', ['id_product' => $id, 'quantity' => $qty]);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Zu implementieren:**
|
||||||
|
- ✅ Hook-Registry
|
||||||
|
- ✅ Hook-Execution
|
||||||
|
- ✅ Module-Hook-Registration
|
||||||
|
- ✅ Hook-Parameter-Handling
|
||||||
|
|
||||||
|
### 2. **Module-System** (Priorität: KRITISCH)
|
||||||
|
```php
|
||||||
|
// PrestaShop Module-Struktur
|
||||||
|
class MyModule extends Module
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'mymodule';
|
||||||
|
$this->tab = 'front_office_features';
|
||||||
|
$this->version = '1.0.0';
|
||||||
|
$this->author = 'Your Name';
|
||||||
|
$this->need_instance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function install()
|
||||||
|
{
|
||||||
|
return parent::install() &&
|
||||||
|
$this->registerHook('displayProductAdditionalInfo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Zu implementieren:**
|
||||||
|
- ✅ Module-Base-Class
|
||||||
|
- ✅ Module-Installation/Deinstallation
|
||||||
|
- ✅ Module-Konfiguration
|
||||||
|
- ✅ Module-Admin-Interface
|
||||||
|
|
||||||
|
### 3. **Override-System** (Priorität: HOCH)
|
||||||
|
```php
|
||||||
|
// PrestaShop Override-Beispiele
|
||||||
|
// classes/Product.php -> modules/mymodule/override/classes/Product.php
|
||||||
|
// controllers/front/ProductController.php -> modules/mymodule/override/controllers/front/ProductController.php
|
||||||
|
```
|
||||||
|
|
||||||
|
**Zu implementieren:**
|
||||||
|
- ✅ Class-Override-Detection
|
||||||
|
- ✅ Template-Override-System
|
||||||
|
- ✅ Controller-Override-System
|
||||||
|
- ✅ Override-Priority-System
|
||||||
|
|
||||||
|
### 4. **Module-API & Services** (Priorität: HOCH)
|
||||||
|
```php
|
||||||
|
// PrestaShop Service-Beispiele
|
||||||
|
$this->context->shop
|
||||||
|
$this->context->language
|
||||||
|
$this->context->currency
|
||||||
|
Module::getInstanceByName('mymodule')
|
||||||
|
```
|
||||||
|
|
||||||
|
**Zu implementieren:**
|
||||||
|
- ✅ Context-System
|
||||||
|
- ✅ Service-Container
|
||||||
|
- ✅ Module-Discovery
|
||||||
|
- ✅ Module-Dependencies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fortschrittstracker
|
||||||
|
|
||||||
|
- ⬜ offen | 🟡 in Arbeit | ✅ erledigt
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sprint-Planung
|
||||||
|
|
||||||
|
### **Sprint 1 (Woche 1): PrestaShop-Kompatibilität Basis**
|
||||||
|
- Hook-System (KRITISCH)
|
||||||
|
- Module-Base-Class (KRITISCH)
|
||||||
|
- Module-Installation/Deinstallation
|
||||||
|
|
||||||
|
### **Sprint 2 (Woche 2): PrestaShop-Kompatibilität Erweitert**
|
||||||
|
- Override-System
|
||||||
|
- Context-System
|
||||||
|
- Service-Container
|
||||||
|
|
||||||
|
### **Sprint 3 (Woche 3): Core-E-Commerce Features**
|
||||||
|
- Produktvarianten
|
||||||
|
- Produktbewertungen
|
||||||
|
- Gutschein-/Rabatt-System
|
||||||
|
|
||||||
|
### **Sprint 4 (Woche 4): Kunden- & Versand-Features**
|
||||||
|
- Kundenkonto-Features
|
||||||
|
- Versandmethoden & Tracking
|
||||||
|
- Benutzerverwaltung
|
||||||
|
|
||||||
|
### **Sprint 5 (Woche 5): Marketing & UX Features**
|
||||||
|
- Cross-Selling & Zubehör
|
||||||
|
- Produktvergleich
|
||||||
|
- Wunschliste
|
||||||
|
- E-Mail-Marketing
|
||||||
|
|
||||||
|
### **Sprint 6 (Woche 6): System-Features**
|
||||||
|
- Lagerverwaltung
|
||||||
|
- Berichte & Statistiken
|
||||||
|
- Import/Export
|
||||||
|
|
||||||
|
### **Sprint 7 (Woche 7): Internationalisierung & Performance**
|
||||||
|
- Mehrsprachigkeit (i18n)
|
||||||
|
- Template-/Theme-System
|
||||||
|
- Performance-Optimierung
|
||||||
|
|
||||||
|
### **Sprint 8 (Woche 8): Rechtliches & Tests**
|
||||||
|
- Rechtliches & DSGVO
|
||||||
|
- Social Media Integration
|
||||||
|
- Affiliate-/Partner-System
|
||||||
|
- PrestaShop-Module-Tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bekannte PrestaShop-Module zum Testen
|
||||||
|
|
||||||
|
### **Einfache Module:**
|
||||||
|
- **blockreassurance** (Hooks: displayProductAdditionalInfo)
|
||||||
|
- **ps_mainmenu** (Hooks: displayTop, displayNav)
|
||||||
|
- **ps_shoppingcart** (Hooks: displayTop, displayNav)
|
||||||
|
|
||||||
|
### **Komplexe Module:**
|
||||||
|
- **ps_checkout** (Viele Hooks, Overrides)
|
||||||
|
- **ps_facebook** (API-Integration)
|
||||||
|
- **ps_cashondelivery** (Payment-Module)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technische Details
|
||||||
|
|
||||||
|
### **Hook-System Struktur:**
|
||||||
|
```php
|
||||||
|
// Zu implementieren in app/Core/Hook.php
|
||||||
|
class Hook
|
||||||
|
{
|
||||||
|
private static $hooks = [];
|
||||||
|
|
||||||
|
public static function register($hookName, $moduleName, $callback)
|
||||||
|
{
|
||||||
|
self::$hooks[$hookName][] = [
|
||||||
|
'module' => $moduleName,
|
||||||
|
'callback' => $callback
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function exec($hookName, $params = [])
|
||||||
|
{
|
||||||
|
$results = [];
|
||||||
|
if (isset(self::$hooks[$hookName])) {
|
||||||
|
foreach (self::$hooks[$hookName] as $hook) {
|
||||||
|
$results[] = call_user_func($hook['callback'], $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Module-Base-Class:**
|
||||||
|
```php
|
||||||
|
// Zu implementieren in app/Core/Module.php
|
||||||
|
abstract class Module
|
||||||
|
{
|
||||||
|
public $name;
|
||||||
|
public $tab;
|
||||||
|
public $version;
|
||||||
|
public $author;
|
||||||
|
public $need_instance;
|
||||||
|
|
||||||
|
abstract public function install();
|
||||||
|
abstract public function uninstall();
|
||||||
|
|
||||||
|
public function registerHook($hookName)
|
||||||
|
{
|
||||||
|
// Hook-Registration
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unregisterHook($hookName)
|
||||||
|
{
|
||||||
|
// Hook-Unregistration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prioritäten für sofortige Implementierung
|
||||||
|
|
||||||
|
### **KRITISCH (sofort):**
|
||||||
|
1. Hook-System (Basis für alle Module)
|
||||||
|
2. Module-Base-Class (Grundlage für Module)
|
||||||
|
3. Module-Installation/Deinstallation
|
||||||
|
|
||||||
|
### **HOCH (nächste Woche):**
|
||||||
|
1. Override-System
|
||||||
|
2. Context-System
|
||||||
|
3. Service-Container
|
||||||
|
|
||||||
|
### **MITTEL (später):**
|
||||||
|
1. Module-Admin-Interface
|
||||||
|
2. Module-Dependencies
|
||||||
|
3. Performance-Optimierung
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nächste Schritte
|
||||||
|
|
||||||
|
1. **Hook-System implementieren** (Sofort)
|
||||||
|
2. **Module-Base-Class erstellen** (Sofort)
|
||||||
|
3. **Einfaches Test-Modul entwickeln** (Validierung)
|
||||||
|
4. **Bekannte PrestaShop-Module testen** (Kompatibilität)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hinweise
|
||||||
|
- Die Reihenfolge kann je nach Nutzerwunsch angepasst werden.
|
||||||
|
- Nach jedem Sprint erfolgt ein Review und ggf. ein Merge/Push zu Gitea.
|
||||||
|
- Feature-Requests können jederzeit ergänzt werden.
|
||||||
|
- PrestaShop-Kompatibilität hat höchste Priorität für Module-Nutzung.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Letzte Aktualisierung:** [TT.MM.JJJJ] – Phase 2 Planung mit PrestaShop-Kompatibilität erstellt
|
||||||
|
|
@ -0,0 +1,340 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright seit 2024 Webshop System
|
||||||
|
*
|
||||||
|
* Hook-System für PrestaShop-Modul-Kompatibilität
|
||||||
|
*
|
||||||
|
* @author Webshop System
|
||||||
|
* @license GPL v3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Core;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\DriverManager;
|
||||||
|
use Doctrine\DBAL\Exception;
|
||||||
|
|
||||||
|
class Hook
|
||||||
|
{
|
||||||
|
private static $hooks = [];
|
||||||
|
private static $hookModules = [];
|
||||||
|
private static $initialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook-System initialisieren
|
||||||
|
*/
|
||||||
|
public static function init()
|
||||||
|
{
|
||||||
|
if (self::$initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::loadHooksFromDatabase();
|
||||||
|
self::$initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook registrieren
|
||||||
|
*/
|
||||||
|
public static function register($hookName, $moduleName, $callback, $position = 0)
|
||||||
|
{
|
||||||
|
if (!isset(self::$hooks[$hookName])) {
|
||||||
|
self::$hooks[$hookName] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$hooks[$hookName][] = [
|
||||||
|
'module' => $moduleName,
|
||||||
|
'callback' => $callback,
|
||||||
|
'position' => $position
|
||||||
|
];
|
||||||
|
|
||||||
|
// Nach Position sortieren
|
||||||
|
usort(self::$hooks[$hookName], function($a, $b) {
|
||||||
|
return $a['position'] - $b['position'];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hook in Datenbank speichern
|
||||||
|
self::saveHookToDatabase($hookName, $moduleName, $position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook ausführen
|
||||||
|
*/
|
||||||
|
public static function exec($hookName, $params = [])
|
||||||
|
{
|
||||||
|
self::init();
|
||||||
|
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
if (isset(self::$hooks[$hookName])) {
|
||||||
|
foreach (self::$hooks[$hookName] as $hook) {
|
||||||
|
try {
|
||||||
|
$result = call_user_func($hook['callback'], $params);
|
||||||
|
if ($result !== null) {
|
||||||
|
$results[] = $result;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log("Hook Fehler in {$hook['module']}: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook mit Rückgabewert ausführen (für display-Hooks)
|
||||||
|
*/
|
||||||
|
public static function execWithReturn($hookName, $params = [])
|
||||||
|
{
|
||||||
|
self::init();
|
||||||
|
|
||||||
|
$output = '';
|
||||||
|
|
||||||
|
if (isset(self::$hooks[$hookName])) {
|
||||||
|
foreach (self::$hooks[$hookName] as $hook) {
|
||||||
|
try {
|
||||||
|
$result = call_user_func($hook['callback'], $params);
|
||||||
|
if (is_string($result)) {
|
||||||
|
$output .= $result;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log("Hook Fehler in {$hook['module']}: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook entfernen
|
||||||
|
*/
|
||||||
|
public static function unregister($hookName, $moduleName)
|
||||||
|
{
|
||||||
|
if (isset(self::$hooks[$hookName])) {
|
||||||
|
foreach (self::$hooks[$hookName] as $key => $hook) {
|
||||||
|
if ($hook['module'] === $moduleName) {
|
||||||
|
unset(self::$hooks[$hookName][$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook aus Datenbank entfernen
|
||||||
|
self::removeHookFromDatabase($hookName, $moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verfügbare Hooks abrufen
|
||||||
|
*/
|
||||||
|
public static function getHooks()
|
||||||
|
{
|
||||||
|
self::init();
|
||||||
|
return array_keys(self::$hooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module für einen Hook abrufen
|
||||||
|
*/
|
||||||
|
public static function getHookModules($hookName)
|
||||||
|
{
|
||||||
|
self::init();
|
||||||
|
|
||||||
|
if (isset(self::$hooks[$hookName])) {
|
||||||
|
return array_column(self::$hooks[$hookName], 'module');
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks aus Datenbank laden
|
||||||
|
*/
|
||||||
|
private static function loadHooksFromDatabase()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
SELECT hook_name, module_name, position
|
||||||
|
FROM ws_hook_module
|
||||||
|
WHERE active = 1
|
||||||
|
ORDER BY position ASC
|
||||||
|
');
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$hooks = $stmt->fetchAllAssociative();
|
||||||
|
|
||||||
|
foreach ($hooks as $hook) {
|
||||||
|
$moduleName = $hook['module_name'];
|
||||||
|
$hookName = $hook['hook_name'];
|
||||||
|
$position = $hook['position'];
|
||||||
|
|
||||||
|
// Module-Klasse laden
|
||||||
|
$moduleClass = self::getModuleClass($moduleName);
|
||||||
|
if ($moduleClass && method_exists($moduleClass, 'hook' . ucfirst($hookName))) {
|
||||||
|
$callback = [$moduleClass, 'hook' . ucfirst($hookName)];
|
||||||
|
self::register($hookName, $moduleName, $callback, $position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Hook-Datenbank Fehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook in Datenbank speichern
|
||||||
|
*/
|
||||||
|
private static function saveHookToDatabase($hookName, $moduleName, $position)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
INSERT INTO ws_hook_module (hook_name, module_name, position, active, created_at)
|
||||||
|
VALUES (?, ?, ?, 1, NOW())
|
||||||
|
ON DUPLICATE KEY UPDATE position = ?, active = 1, updated_at = NOW()
|
||||||
|
');
|
||||||
|
$stmt->execute([$hookName, $moduleName, $position, $position]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Hook-Speicher Fehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook aus Datenbank entfernen
|
||||||
|
*/
|
||||||
|
private static function removeHookFromDatabase($hookName, $moduleName)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
UPDATE ws_hook_module
|
||||||
|
SET active = 0, updated_at = NOW()
|
||||||
|
WHERE hook_name = ? AND module_name = ?
|
||||||
|
');
|
||||||
|
$stmt->execute([$hookName, $moduleName]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Hook-Entfernung Fehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module-Klasse laden
|
||||||
|
*/
|
||||||
|
private static function getModuleClass($moduleName)
|
||||||
|
{
|
||||||
|
$modulePath = __DIR__ . '/../../modules/' . $moduleName . '/' . $moduleName . '.php';
|
||||||
|
|
||||||
|
if (file_exists($modulePath)) {
|
||||||
|
require_once $modulePath;
|
||||||
|
$className = ucfirst($moduleName);
|
||||||
|
|
||||||
|
if (class_exists($className)) {
|
||||||
|
return new $className();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook-Statistiken abrufen
|
||||||
|
*/
|
||||||
|
public static function getHookStatistics()
|
||||||
|
{
|
||||||
|
self::init();
|
||||||
|
|
||||||
|
$stats = [];
|
||||||
|
foreach (self::$hooks as $hookName => $hookList) {
|
||||||
|
$stats[$hookName] = count($hookList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook-Liste für Admin-Interface
|
||||||
|
*/
|
||||||
|
public static function getHookList()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// Display Hooks (Frontend)
|
||||||
|
'displayHeader' => 'Header-Bereich',
|
||||||
|
'displayTop' => 'Oberer Bereich',
|
||||||
|
'displayNav' => 'Navigation',
|
||||||
|
'displayNav1' => 'Navigation 1',
|
||||||
|
'displayNav2' => 'Navigation 2',
|
||||||
|
'displayTopColumn' => 'Obere Spalte',
|
||||||
|
'displayLeftColumn' => 'Linke Spalte',
|
||||||
|
'displayRightColumn' => 'Rechte Spalte',
|
||||||
|
'displayFooter' => 'Footer-Bereich',
|
||||||
|
'displayFooterAfter' => 'Footer nach',
|
||||||
|
'displayHome' => 'Startseite',
|
||||||
|
'displayHomeTab' => 'Startseite Tabs',
|
||||||
|
'displayHomeTabContent' => 'Startseite Tab-Inhalt',
|
||||||
|
|
||||||
|
// Product Hooks
|
||||||
|
'displayProductListReviews' => 'Produktliste Bewertungen',
|
||||||
|
'displayProductAdditionalInfo' => 'Produkt zusätzliche Info',
|
||||||
|
'displayProductPriceBlock' => 'Produkt Preis-Block',
|
||||||
|
'displayProductButtons' => 'Produkt Buttons',
|
||||||
|
'displayProductTab' => 'Produkt Tabs',
|
||||||
|
'displayProductTabContent' => 'Produkt Tab-Inhalt',
|
||||||
|
'displayProductListFunctionalButtons' => 'Produktliste Funktions-Buttons',
|
||||||
|
|
||||||
|
// Cart Hooks
|
||||||
|
'displayShoppingCart' => 'Warenkorb',
|
||||||
|
'displayShoppingCartFooter' => 'Warenkorb Footer',
|
||||||
|
'actionCartUpdateQuantityBefore' => 'Warenkorb Menge vor Update',
|
||||||
|
'actionCartUpdateQuantityAfter' => 'Warenkorb Menge nach Update',
|
||||||
|
'actionCartListOverride' => 'Warenkorb Liste überschreiben',
|
||||||
|
|
||||||
|
// Order Hooks
|
||||||
|
'displayOrderConfirmation' => 'Bestellbestätigung',
|
||||||
|
'displayOrderDetail' => 'Bestelldetails',
|
||||||
|
'actionOrderStatusUpdate' => 'Bestellstatus Update',
|
||||||
|
'actionValidateOrder' => 'Bestellung validieren',
|
||||||
|
|
||||||
|
// Customer Hooks
|
||||||
|
'displayCustomerAccount' => 'Kundenkonto',
|
||||||
|
'displayCustomerAccountForm' => 'Kundenkonto Formular',
|
||||||
|
'actionCustomerAccountAdd' => 'Kundenkonto hinzufügen',
|
||||||
|
'actionCustomerAccountUpdate' => 'Kundenkonto Update',
|
||||||
|
|
||||||
|
// Admin Hooks
|
||||||
|
'displayAdminOrder' => 'Admin Bestellung',
|
||||||
|
'displayAdminProducts' => 'Admin Produkte',
|
||||||
|
'actionAdminProductsControllerSaveAfter' => 'Admin Produkt nach Speichern',
|
||||||
|
'actionAdminCustomersControllerSaveAfter' => 'Admin Kunde nach Speichern',
|
||||||
|
|
||||||
|
// Payment Hooks
|
||||||
|
'displayPayment' => 'Zahlungsmethoden',
|
||||||
|
'displayPaymentReturn' => 'Zahlungsrückgabe',
|
||||||
|
'actionPaymentConfirmation' => 'Zahlungsbestätigung',
|
||||||
|
|
||||||
|
// Search Hooks
|
||||||
|
'displaySearch' => 'Suche',
|
||||||
|
'actionSearch' => 'Suchaktion',
|
||||||
|
'displaySearchResults' => 'Suchergebnisse',
|
||||||
|
|
||||||
|
// Newsletter Hooks
|
||||||
|
'displayNewsletterRegistration' => 'Newsletter Registrierung',
|
||||||
|
'actionNewsletterRegistrationAfter' => 'Newsletter nach Registrierung',
|
||||||
|
|
||||||
|
// Security Hooks
|
||||||
|
'actionAuthentication' => 'Authentifizierung',
|
||||||
|
'actionCustomerLogoutAfter' => 'Kunde nach Logout',
|
||||||
|
'actionAdminLoginControllerLoginAfter' => 'Admin nach Login'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,407 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright seit 2024 Webshop System
|
||||||
|
*
|
||||||
|
* Module-Base-Class für PrestaShop-Modul-Kompatibilität
|
||||||
|
*
|
||||||
|
* @author Webshop System
|
||||||
|
* @license GPL v3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Core;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\DriverManager;
|
||||||
|
use Doctrine\DBAL\Exception;
|
||||||
|
|
||||||
|
abstract class Module
|
||||||
|
{
|
||||||
|
public $name;
|
||||||
|
public $tab;
|
||||||
|
public $version;
|
||||||
|
public $author;
|
||||||
|
public $need_instance;
|
||||||
|
public $ps_versions_compliancy;
|
||||||
|
public $bootstrap;
|
||||||
|
public $displayName;
|
||||||
|
public $description;
|
||||||
|
public $confirmUninstall;
|
||||||
|
public $limited_countries;
|
||||||
|
public $module_key;
|
||||||
|
|
||||||
|
protected $context;
|
||||||
|
protected $shop;
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->context = Context::getContext();
|
||||||
|
$this->shop = new Shop();
|
||||||
|
$this->config = new Configuration();
|
||||||
|
|
||||||
|
// Standardwerte setzen
|
||||||
|
$this->need_instance = 0;
|
||||||
|
$this->bootstrap = false;
|
||||||
|
$this->ps_versions_compliancy = ['min' => '1.7.0.0', 'max' => _PS_VERSION_];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul installieren
|
||||||
|
*/
|
||||||
|
public function install()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Modul in Datenbank eintragen
|
||||||
|
$this->registerModule();
|
||||||
|
|
||||||
|
// Modul-Konfiguration installieren
|
||||||
|
$this->installConfiguration();
|
||||||
|
|
||||||
|
// Datenbank-Tabellen erstellen
|
||||||
|
$this->installDatabase();
|
||||||
|
|
||||||
|
// Hooks registrieren
|
||||||
|
$this->registerHooks();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log("Modul-Installation Fehler: " . $e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul deinstallieren
|
||||||
|
*/
|
||||||
|
public function uninstall()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Hooks entfernen
|
||||||
|
$this->unregisterHooks();
|
||||||
|
|
||||||
|
// Datenbank-Tabellen entfernen
|
||||||
|
$this->uninstallDatabase();
|
||||||
|
|
||||||
|
// Modul-Konfiguration entfernen
|
||||||
|
$this->uninstallConfiguration();
|
||||||
|
|
||||||
|
// Modul aus Datenbank entfernen
|
||||||
|
$this->unregisterModule();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log("Modul-Deinstallation Fehler: " . $e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul in Datenbank registrieren
|
||||||
|
*/
|
||||||
|
protected function registerModule()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
INSERT INTO ws_module (
|
||||||
|
name, display_name, description, version, author,
|
||||||
|
tab, need_instance, bootstrap, active, created_at
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, NOW())
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
display_name = ?, description = ?, version = ?,
|
||||||
|
author = ?, tab = ?, need_instance = ?, bootstrap = ?,
|
||||||
|
updated_at = NOW()
|
||||||
|
');
|
||||||
|
|
||||||
|
$stmt->execute([
|
||||||
|
$this->name,
|
||||||
|
$this->displayName ?: $this->name,
|
||||||
|
$this->description ?: '',
|
||||||
|
$this->version ?: '1.0.0',
|
||||||
|
$this->author ?: 'Unknown',
|
||||||
|
$this->tab ?: 'administration',
|
||||||
|
$this->need_instance,
|
||||||
|
$this->bootstrap ? 1 : 0,
|
||||||
|
$this->displayName ?: $this->name,
|
||||||
|
$this->description ?: '',
|
||||||
|
$this->version ?: '1.0.0',
|
||||||
|
$this->author ?: 'Unknown',
|
||||||
|
$this->tab ?: 'administration',
|
||||||
|
$this->need_instance,
|
||||||
|
$this->bootstrap ? 1 : 0
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new \Exception('Modul-Registrierung Fehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul aus Datenbank entfernen
|
||||||
|
*/
|
||||||
|
protected function unregisterModule()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
UPDATE ws_module
|
||||||
|
SET active = 0, updated_at = NOW()
|
||||||
|
WHERE name = ?
|
||||||
|
');
|
||||||
|
$stmt->execute([$this->name]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Modul-Entfernung Fehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration installieren
|
||||||
|
*/
|
||||||
|
protected function installConfiguration()
|
||||||
|
{
|
||||||
|
// Standard-Konfiguration installieren
|
||||||
|
$this->config->set('MODULE_' . strtoupper($this->name) . '_ENABLED', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration entfernen
|
||||||
|
*/
|
||||||
|
protected function uninstallConfiguration()
|
||||||
|
{
|
||||||
|
// Modul-Konfiguration entfernen
|
||||||
|
$this->config->delete('MODULE_' . strtoupper($this->name) . '_ENABLED');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datenbank-Tabellen erstellen
|
||||||
|
*/
|
||||||
|
protected function installDatabase()
|
||||||
|
{
|
||||||
|
// Kann von Modulen überschrieben werden
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datenbank-Tabellen entfernen
|
||||||
|
*/
|
||||||
|
protected function uninstallDatabase()
|
||||||
|
{
|
||||||
|
// Kann von Modulen überschrieben werden
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks registrieren
|
||||||
|
*/
|
||||||
|
protected function registerHooks()
|
||||||
|
{
|
||||||
|
// Standard-Hooks können hier registriert werden
|
||||||
|
// Hook::register('displayHeader', $this->name, [$this, 'hookDisplayHeader']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks entfernen
|
||||||
|
*/
|
||||||
|
protected function unregisterHooks()
|
||||||
|
{
|
||||||
|
// Alle Hooks für dieses Modul entfernen
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
UPDATE ws_hook_module
|
||||||
|
SET active = 0, updated_at = NOW()
|
||||||
|
WHERE module_name = ?
|
||||||
|
');
|
||||||
|
$stmt->execute([$this->name]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Hook-Entfernung Fehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook registrieren
|
||||||
|
*/
|
||||||
|
public function registerHook($hookName)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
INSERT INTO ws_hook_module (hook_name, module_name, position, active, created_at)
|
||||||
|
VALUES (?, ?, 0, 1, NOW())
|
||||||
|
ON DUPLICATE KEY UPDATE active = 1, updated_at = NOW()
|
||||||
|
');
|
||||||
|
$stmt->execute([$hookName, $this->name]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Hook-Registrierung Fehler: ' . $e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook entfernen
|
||||||
|
*/
|
||||||
|
public function unregisterHook($hookName)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
UPDATE ws_hook_module
|
||||||
|
SET active = 0, updated_at = NOW()
|
||||||
|
WHERE hook_name = ? AND module_name = ?
|
||||||
|
');
|
||||||
|
$stmt->execute([$hookName, $this->name]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log('Hook-Entfernung Fehler: ' . $e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration abrufen
|
||||||
|
*/
|
||||||
|
public function getConfig($key, $default = null)
|
||||||
|
{
|
||||||
|
return $this->config->get('MODULE_' . strtoupper($this->name) . '_' . strtoupper($key), $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration setzen
|
||||||
|
*/
|
||||||
|
public function setConfig($key, $value)
|
||||||
|
{
|
||||||
|
return $this->config->set('MODULE_' . strtoupper($this->name) . '_' . strtoupper($key), $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration entfernen
|
||||||
|
*/
|
||||||
|
public function deleteConfig($key)
|
||||||
|
{
|
||||||
|
return $this->config->delete('MODULE_' . strtoupper($this->name) . '_' . strtoupper($key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-URL generieren
|
||||||
|
*/
|
||||||
|
public function getModuleUrl($controller = null, $params = [])
|
||||||
|
{
|
||||||
|
$url = '/admin/module/' . $this->name;
|
||||||
|
|
||||||
|
if ($controller) {
|
||||||
|
$url .= '/' . $controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($params)) {
|
||||||
|
$url .= '?' . http_build_query($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Pfad abrufen
|
||||||
|
*/
|
||||||
|
public function getModulePath()
|
||||||
|
{
|
||||||
|
return __DIR__ . '/../../modules/' . $this->name . '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Template-Pfad abrufen
|
||||||
|
*/
|
||||||
|
public function getTemplatePath()
|
||||||
|
{
|
||||||
|
return $this->getModulePath() . 'views/templates/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Asset-Pfad abrufen
|
||||||
|
*/
|
||||||
|
public function getAssetPath()
|
||||||
|
{
|
||||||
|
return $this->getModulePath() . 'views/assets/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Admin-Controller erstellen
|
||||||
|
*/
|
||||||
|
public function getContent()
|
||||||
|
{
|
||||||
|
// Kann von Modulen überschrieben werden
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Admin-Formular verarbeiten
|
||||||
|
*/
|
||||||
|
public function postProcess()
|
||||||
|
{
|
||||||
|
// Kann von Modulen überschrieben werden
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Status prüfen
|
||||||
|
*/
|
||||||
|
public function isEnabled()
|
||||||
|
{
|
||||||
|
return $this->getConfig('ENABLED', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul aktivieren
|
||||||
|
*/
|
||||||
|
public function enable()
|
||||||
|
{
|
||||||
|
return $this->setConfig('ENABLED', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul deaktivieren
|
||||||
|
*/
|
||||||
|
public function disable()
|
||||||
|
{
|
||||||
|
return $this->setConfig('ENABLED', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Informationen abrufen
|
||||||
|
*/
|
||||||
|
public function getModuleInfo()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->name,
|
||||||
|
'display_name' => $this->displayName ?: $this->name,
|
||||||
|
'description' => $this->description ?: '',
|
||||||
|
'version' => $this->version ?: '1.0.0',
|
||||||
|
'author' => $this->author ?: 'Unknown',
|
||||||
|
'tab' => $this->tab ?: 'administration',
|
||||||
|
'need_instance' => $this->need_instance,
|
||||||
|
'bootstrap' => $this->bootstrap,
|
||||||
|
'enabled' => $this->isEnabled(),
|
||||||
|
'path' => $this->getModulePath()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,431 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright seit 2024 Webshop System
|
||||||
|
*
|
||||||
|
* Module Controller für Admin-Bereich
|
||||||
|
*
|
||||||
|
* @author Webshop System
|
||||||
|
* @license GPL v3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Core\Module;
|
||||||
|
use App\Core\Hook;
|
||||||
|
use App\Core\MultiShop;
|
||||||
|
use App\Core\Security;
|
||||||
|
use App\Core\Configuration;
|
||||||
|
|
||||||
|
class ModuleController
|
||||||
|
{
|
||||||
|
private $multiShop;
|
||||||
|
private $security;
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->multiShop = new MultiShop();
|
||||||
|
$this->security = new Security();
|
||||||
|
$this->config = new Configuration();
|
||||||
|
|
||||||
|
// Session-Check
|
||||||
|
if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) {
|
||||||
|
header('Location: /admin/login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Übersicht anzeigen
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$shopId = $this->multiShop->getCurrentShopId();
|
||||||
|
|
||||||
|
// Module aus Datenbank abrufen
|
||||||
|
$modules = $this->getModules();
|
||||||
|
|
||||||
|
// Hook-Statistiken
|
||||||
|
$hookStats = Hook::getHookStatistics();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'modules' => $modules,
|
||||||
|
'hook_stats' => $hookStats,
|
||||||
|
'shop_id' => $shopId
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->render('admin/module/index.html.twig', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul installieren
|
||||||
|
*/
|
||||||
|
public function install()
|
||||||
|
{
|
||||||
|
$moduleName = $_POST['module_name'] ?? '';
|
||||||
|
|
||||||
|
if (empty($moduleName)) {
|
||||||
|
$this->addError('Modul-Name ist erforderlich');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF-Schutz
|
||||||
|
if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) {
|
||||||
|
$this->addError('Sicherheitsfehler: Ungültiger Token');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$module = $this->loadModule($moduleName);
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$this->addError("Modul '{$moduleName}' nicht gefunden");
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($module->install()) {
|
||||||
|
$this->addSuccess("Modul '{$moduleName}' erfolgreich installiert");
|
||||||
|
} else {
|
||||||
|
$this->addError("Fehler beim Installieren von '{$moduleName}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addError('Installationsfehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: /admin/module');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul deinstallieren
|
||||||
|
*/
|
||||||
|
public function uninstall()
|
||||||
|
{
|
||||||
|
$moduleName = $_POST['module_name'] ?? '';
|
||||||
|
|
||||||
|
if (empty($moduleName)) {
|
||||||
|
$this->addError('Modul-Name ist erforderlich');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF-Schutz
|
||||||
|
if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) {
|
||||||
|
$this->addError('Sicherheitsfehler: Ungültiger Token');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$module = $this->loadModule($moduleName);
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$this->addError("Modul '{$moduleName}' nicht gefunden");
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($module->uninstall()) {
|
||||||
|
$this->addSuccess("Modul '{$moduleName}' erfolgreich deinstalliert");
|
||||||
|
} else {
|
||||||
|
$this->addError("Fehler beim Deinstallieren von '{$moduleName}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addError('Deinstallationsfehler: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: /admin/module');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul konfigurieren
|
||||||
|
*/
|
||||||
|
public function configure()
|
||||||
|
{
|
||||||
|
$moduleName = $_GET['module'] ?? '';
|
||||||
|
|
||||||
|
if (empty($moduleName)) {
|
||||||
|
$this->addError('Modul-Name ist erforderlich');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$module = $this->loadModule($moduleName);
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$this->addError("Modul '{$moduleName}' nicht gefunden");
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST-Verarbeitung
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$this->processModuleConfiguration($module);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'module' => $module,
|
||||||
|
'module_info' => $module->getModuleInfo(),
|
||||||
|
'configuration' => $this->getModuleConfiguration($moduleName)
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->render('admin/module/configure.html.twig', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration verarbeiten
|
||||||
|
*/
|
||||||
|
private function processModuleConfiguration($module)
|
||||||
|
{
|
||||||
|
// CSRF-Schutz
|
||||||
|
if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) {
|
||||||
|
$this->addError('Sicherheitsfehler: Ungültiger Token');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$moduleName = $module->name;
|
||||||
|
|
||||||
|
// Konfiguration verarbeiten
|
||||||
|
foreach ($_POST as $key => $value) {
|
||||||
|
if (strpos($key, 'config_') === 0) {
|
||||||
|
$configKey = substr($key, 7); // 'config_' entfernen
|
||||||
|
$module->setConfig($configKey, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->addSuccess('Modul-Konfiguration erfolgreich gespeichert');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module aus Datenbank abrufen
|
||||||
|
*/
|
||||||
|
private function getModules()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = \Doctrine\DBAL\DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
SELECT * FROM ws_module
|
||||||
|
ORDER BY display_name ASC
|
||||||
|
');
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $stmt->fetchAllAssociative();
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('Module-Abruf Fehler: ' . $e->getMessage());
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul laden
|
||||||
|
*/
|
||||||
|
private function loadModule($moduleName)
|
||||||
|
{
|
||||||
|
$modulePath = __DIR__ . '/../../modules/' . $moduleName . '/' . $moduleName . '.php';
|
||||||
|
|
||||||
|
if (!file_exists($modulePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once $modulePath;
|
||||||
|
$className = ucfirst($moduleName);
|
||||||
|
|
||||||
|
if (class_exists($className)) {
|
||||||
|
return new $className();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Konfiguration abrufen
|
||||||
|
*/
|
||||||
|
private function getModuleConfiguration($moduleName)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$conn = \Doctrine\DBAL\DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stmt = $conn->prepare('
|
||||||
|
SELECT config_key, config_value
|
||||||
|
FROM ws_module_config
|
||||||
|
WHERE module_name = ?
|
||||||
|
');
|
||||||
|
$stmt->execute([$moduleName]);
|
||||||
|
|
||||||
|
$config = [];
|
||||||
|
while ($row = $stmt->fetchAssociative()) {
|
||||||
|
$config[$row['config_key']] = $row['config_value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('Modul-Konfiguration Fehler: ' . $e->getMessage());
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Logs abrufen
|
||||||
|
*/
|
||||||
|
public function logs()
|
||||||
|
{
|
||||||
|
$moduleName = $_GET['module'] ?? '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = \Doctrine\DBAL\DriverManager::getConnection([
|
||||||
|
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$sql = 'SELECT * FROM ws_module_log';
|
||||||
|
$params = [];
|
||||||
|
|
||||||
|
if (!empty($moduleName)) {
|
||||||
|
$sql .= ' WHERE module_name = ?';
|
||||||
|
$params[] = $moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= ' ORDER BY created_at DESC LIMIT 100';
|
||||||
|
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->execute($params);
|
||||||
|
|
||||||
|
$logs = $stmt->fetchAllAssociative();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'logs' => $logs,
|
||||||
|
'module_name' => $moduleName
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->render('admin/module/logs.html.twig', $data);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->addError('Log-Abruf Fehler: ' . $e->getMessage());
|
||||||
|
$this->render('admin/module/logs.html.twig', ['logs' => [], 'module_name' => $moduleName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook-Übersicht anzeigen
|
||||||
|
*/
|
||||||
|
public function hooks()
|
||||||
|
{
|
||||||
|
$hookList = Hook::getHookList();
|
||||||
|
$hookStats = Hook::getHookStatistics();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'hook_list' => $hookList,
|
||||||
|
'hook_stats' => $hookStats
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->render('admin/module/hooks.html.twig', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modul-Upload verarbeiten
|
||||||
|
*/
|
||||||
|
public function upload()
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF-Schutz
|
||||||
|
if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) {
|
||||||
|
$this->addError('Sicherheitsfehler: Ungültiger Token');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_FILES['module_file']) || $_FILES['module_file']['error'] !== UPLOAD_ERR_OK) {
|
||||||
|
$this->addError('Fehler beim Datei-Upload');
|
||||||
|
header('Location: /admin/module');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploadDir = __DIR__ . '/../../modules/';
|
||||||
|
$fileName = $_FILES['module_file']['name'];
|
||||||
|
$filePath = $_FILES['module_file']['tmp_name'];
|
||||||
|
|
||||||
|
// ZIP-Datei extrahieren
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
if ($zip->open($filePath) === TRUE) {
|
||||||
|
$moduleName = pathinfo($fileName, PATHINFO_FILENAME);
|
||||||
|
$extractPath = $uploadDir . $moduleName . '/';
|
||||||
|
|
||||||
|
// Verzeichnis erstellen
|
||||||
|
if (!is_dir($extractPath)) {
|
||||||
|
mkdir($extractPath, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dateien extrahieren
|
||||||
|
$zip->extractTo($extractPath);
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
$this->addSuccess("Modul '{$moduleName}' erfolgreich hochgeladen");
|
||||||
|
} else {
|
||||||
|
$this->addError('Fehler beim Extrahieren der ZIP-Datei');
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: /admin/module');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template rendern
|
||||||
|
*/
|
||||||
|
private function render($template, $data = [])
|
||||||
|
{
|
||||||
|
// CSRF-Token generieren
|
||||||
|
$data['csrf_token'] = $this->security->generateCSRFToken();
|
||||||
|
|
||||||
|
// Flash-Messages
|
||||||
|
$data['success_messages'] = $_SESSION['success_messages'] ?? [];
|
||||||
|
$data['error_messages'] = $_SESSION['error_messages'] ?? [];
|
||||||
|
|
||||||
|
// Session-Messages löschen
|
||||||
|
unset($_SESSION['success_messages'], $_SESSION['error_messages']);
|
||||||
|
|
||||||
|
// Template laden
|
||||||
|
$templatePath = __DIR__ . '/../../templates/' . $template;
|
||||||
|
|
||||||
|
if (file_exists($templatePath)) {
|
||||||
|
extract($data);
|
||||||
|
include $templatePath;
|
||||||
|
} else {
|
||||||
|
throw new \Exception("Template nicht gefunden: {$template}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erfolgs-Message hinzufügen
|
||||||
|
*/
|
||||||
|
private function addSuccess($message)
|
||||||
|
{
|
||||||
|
if (!isset($_SESSION['success_messages'])) {
|
||||||
|
$_SESSION['success_messages'] = [];
|
||||||
|
}
|
||||||
|
$_SESSION['success_messages'][] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fehler-Message hinzufügen
|
||||||
|
*/
|
||||||
|
private function addError($message)
|
||||||
|
{
|
||||||
|
if (!isset($_SESSION['error_messages'])) {
|
||||||
|
$_SESSION['error_messages'] = [];
|
||||||
|
}
|
||||||
|
$_SESSION['error_messages'][] = $message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
-- Module-System Schema
|
||||||
|
-- Erstellt die Tabellen für PrestaShop-kompatible Module
|
||||||
|
|
||||||
|
-- Module-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS `ws_module` (
|
||||||
|
`id_module` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(64) NOT NULL,
|
||||||
|
`display_name` varchar(255) DEFAULT NULL,
|
||||||
|
`description` text,
|
||||||
|
`version` varchar(32) DEFAULT '1.0.0',
|
||||||
|
`author` varchar(255) DEFAULT 'Unknown',
|
||||||
|
`tab` varchar(64) DEFAULT 'administration',
|
||||||
|
`need_instance` tinyint(1) DEFAULT 0,
|
||||||
|
`bootstrap` tinyint(1) DEFAULT 0,
|
||||||
|
`active` tinyint(1) DEFAULT 1,
|
||||||
|
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id_module`),
|
||||||
|
UNIQUE KEY `name` (`name`),
|
||||||
|
KEY `active` (`active`),
|
||||||
|
KEY `tab` (`tab`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Hook-Module-Tabelle (Verbindung zwischen Hooks und Modulen)
|
||||||
|
CREATE TABLE IF NOT EXISTS `ws_hook_module` (
|
||||||
|
`id_hook_module` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`hook_name` varchar(64) NOT NULL,
|
||||||
|
`module_name` varchar(64) NOT NULL,
|
||||||
|
`position` int(11) DEFAULT 0,
|
||||||
|
`active` tinyint(1) DEFAULT 1,
|
||||||
|
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id_hook_module`),
|
||||||
|
UNIQUE KEY `hook_module` (`hook_name`, `module_name`),
|
||||||
|
KEY `hook_name` (`hook_name`),
|
||||||
|
KEY `module_name` (`module_name`),
|
||||||
|
KEY `active` (`active`),
|
||||||
|
KEY `position` (`position`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Module-Konfiguration-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS `ws_module_config` (
|
||||||
|
`id_module_config` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`module_name` varchar(64) NOT NULL,
|
||||||
|
`config_key` varchar(255) NOT NULL,
|
||||||
|
`config_value` text,
|
||||||
|
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id_module_config`),
|
||||||
|
UNIQUE KEY `module_config` (`module_name`, `config_key`),
|
||||||
|
KEY `module_name` (`module_name`),
|
||||||
|
KEY `config_key` (`config_key`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Module-Logs-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS `ws_module_log` (
|
||||||
|
`id_module_log` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`module_name` varchar(64) NOT NULL,
|
||||||
|
`action` varchar(64) NOT NULL,
|
||||||
|
`message` text,
|
||||||
|
`level` enum('info', 'warning', 'error') DEFAULT 'info',
|
||||||
|
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id_module_log`),
|
||||||
|
KEY `module_name` (`module_name`),
|
||||||
|
KEY `action` (`action`),
|
||||||
|
KEY `level` (`level`),
|
||||||
|
KEY `created_at` (`created_at`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Module-Dependencies-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS `ws_module_dependency` (
|
||||||
|
`id_module_dependency` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`module_name` varchar(64) NOT NULL,
|
||||||
|
`dependency_name` varchar(64) NOT NULL,
|
||||||
|
`dependency_version` varchar(32) DEFAULT NULL,
|
||||||
|
`required` tinyint(1) DEFAULT 1,
|
||||||
|
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id_module_dependency`),
|
||||||
|
KEY `module_name` (`module_name`),
|
||||||
|
KEY `dependency_name` (`dependency_name`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Module-Override-Tabelle
|
||||||
|
CREATE TABLE IF NOT EXISTS `ws_module_override` (
|
||||||
|
`id_module_override` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`module_name` varchar(64) NOT NULL,
|
||||||
|
`override_type` enum('class', 'template', 'controller') NOT NULL,
|
||||||
|
`original_path` varchar(255) NOT NULL,
|
||||||
|
`override_path` varchar(255) NOT NULL,
|
||||||
|
`active` tinyint(1) DEFAULT 1,
|
||||||
|
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id_module_override`),
|
||||||
|
KEY `module_name` (`module_name`),
|
||||||
|
KEY `override_type` (`override_type`),
|
||||||
|
KEY `active` (`active`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Standard-Hooks einfügen
|
||||||
|
INSERT IGNORE INTO `ws_hook_module` (`hook_name`, `module_name`, `position`) VALUES
|
||||||
|
-- Display Hooks
|
||||||
|
('displayHeader', 'system', 0),
|
||||||
|
('displayTop', 'system', 0),
|
||||||
|
('displayNav', 'system', 0),
|
||||||
|
('displayFooter', 'system', 0),
|
||||||
|
('displayHome', 'system', 0),
|
||||||
|
|
||||||
|
-- Product Hooks
|
||||||
|
('displayProductAdditionalInfo', 'system', 0),
|
||||||
|
('displayProductListReviews', 'system', 0),
|
||||||
|
('displayProductButtons', 'system', 0),
|
||||||
|
|
||||||
|
-- Cart Hooks
|
||||||
|
('displayShoppingCart', 'system', 0),
|
||||||
|
('actionCartUpdateQuantityBefore', 'system', 0),
|
||||||
|
('actionCartUpdateQuantityAfter', 'system', 0),
|
||||||
|
|
||||||
|
-- Order Hooks
|
||||||
|
('displayOrderConfirmation', 'system', 0),
|
||||||
|
('actionValidateOrder', 'system', 0),
|
||||||
|
|
||||||
|
-- Customer Hooks
|
||||||
|
('displayCustomerAccount', 'system', 0),
|
||||||
|
('actionCustomerAccountAdd', 'system', 0),
|
||||||
|
|
||||||
|
-- Admin Hooks
|
||||||
|
('displayAdminOrder', 'system', 0),
|
||||||
|
('displayAdminProducts', 'system', 0),
|
||||||
|
|
||||||
|
-- Payment Hooks
|
||||||
|
('displayPayment', 'system', 0),
|
||||||
|
('actionPaymentConfirmation', 'system', 0),
|
||||||
|
|
||||||
|
-- Search Hooks
|
||||||
|
('displaySearch', 'system', 0),
|
||||||
|
('actionSearch', 'system', 0),
|
||||||
|
|
||||||
|
-- Newsletter Hooks
|
||||||
|
('displayNewsletterRegistration', 'system', 0),
|
||||||
|
('actionNewsletterRegistrationAfter', 'system', 0),
|
||||||
|
|
||||||
|
-- Security Hooks
|
||||||
|
('actionAuthentication', 'system', 0),
|
||||||
|
('actionCustomerLogoutAfter', 'system', 0);
|
||||||
|
|
||||||
|
-- System-Modul eintragen
|
||||||
|
INSERT IGNORE INTO `ws_module` (`name`, `display_name`, `description`, `version`, `author`, `tab`, `need_instance`, `bootstrap`, `active`) VALUES
|
||||||
|
('system', 'System', 'Kern-System-Modul', '1.0.0', 'Webshop System', 'administration', 0, 0, 1);
|
||||||
Loading…
Reference in New Issue