$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' ]; } }