340 lines
11 KiB
PHP
340 lines
11 KiB
PHP
<?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'
|
|
];
|
|
}
|
|
}
|