$callback, 'priority' => $priority, 'module' => $moduleName ]; // Ordina per priorità usort(self::$hooks[$hookName], function ($a, $b) { return $a['priority'] <=> $b['priority']; }); Log::debug("Hook registrato: {$hookName} da modulo {$moduleName} con priorità {$priority}"); } /** * Esegue tutti gli hook registrati per un evento * * @param string $hookName Nome dell'hook * @param mixed $data Dati da passare agli hook * @return mixed Dati modificati dagli hook */ public static function execute($hookName, $data = null) { if (!isset(self::$hooks[$hookName])) { return $data; } Log::debug("Esecuzione hook: {$hookName} con " . count(self::$hooks[$hookName]) . " callback"); foreach (self::$hooks[$hookName] as $hook) { try { $result = call_user_func($hook['callback'], $data); // Se l'hook ritorna un valore, lo usa come nuovo $data if ($result !== null) { $data = $result; } } catch (\Exception $e) { Log::error("Errore nell'esecuzione hook {$hookName} del modulo {$hook['module']}: " . $e->getMessage()); // Continua con gli altri hook anche se uno fallisce continue; } } return $data; } /** * Rimuove tutti gli hook di un modulo * * @param string $moduleName Nome del modulo */ public static function unregisterModule($moduleName) { foreach (self::$hooks as $hookName => &$hooks) { $hooks = array_filter($hooks, function ($hook) use ($moduleName) { return $hook['module'] !== $moduleName; }); // Rimuovi hook vuoti if (empty($hooks)) { unset(self::$hooks[$hookName]); } } Log::info("Tutti gli hook del modulo {$moduleName} sono stati rimossi"); } /** * Rimuove un hook specifico * * @param string $hookName Nome dell'hook * @param string $moduleName Nome del modulo (opzionale) */ public static function unregister($hookName, $moduleName = null) { if (!isset(self::$hooks[$hookName])) { return; } if ($moduleName) { self::$hooks[$hookName] = array_filter(self::$hooks[$hookName], function ($hook) use ($moduleName) { return $hook['module'] !== $moduleName; }); } else { unset(self::$hooks[$hookName]); } Log::debug("Hook rimosso: {$hookName}" . ($moduleName ? " del modulo {$moduleName}" : "")); } /** * Ottieni la lista di tutti gli hook registrati * * @return array */ public static function getRegisteredHooks() { return array_map(function ($hooks) { return array_map(function ($hook) { return [ 'module' => $hook['module'], 'priority' => $hook['priority'] ]; }, $hooks); }, self::$hooks); } /** * Verifica se un hook è registrato * * @param string $hookName Nome dell'hook * @return bool */ public static function hasHook($hookName) { return isset(self::$hooks[$hookName]) && !empty(self::$hooks[$hookName]); } /** * Conta il numero di callback registrati per un hook * * @param string $hookName Nome dell'hook * @return int */ public static function countHooks($hookName) { return isset(self::$hooks[$hookName]) ? count(self::$hooks[$hookName]) : 0; } /** * Carica gli hook di tutti i moduli attivi */ public static function loadModuleHooks() { $moduleManager = app(ModuleManager::class); $activeModules = $moduleManager->getActiveModules(); foreach ($activeModules as $module) { self::loadModuleHooksFile($module->name); } } /** * Carica il file hooks.php di un modulo specifico * * @param string $moduleName Nome del modulo */ public static function loadModuleHooksFile($moduleName) { $hooksFile = app_path("Modules/{$moduleName}/hooks.php"); if (file_exists($hooksFile)) { include_once $hooksFile; Log::debug("Hook file caricato per modulo: {$moduleName}"); } } } // ================================================ // HOOK PREDEFINITI DEL SISTEMA CORE // ================================================ /** * Helper function per registrare hook più facilmente */ if (!function_exists('hook_register')) { function hook_register($hookName, $callback, $priority = 10, $moduleName = 'core') { HookManager::register($hookName, $callback, $priority, $moduleName); } } /** * Helper function per eseguire hook più facilmente */ if (!function_exists('hook_execute')) { function hook_execute($hookName, $data = null) { return HookManager::execute($hookName, $data); } } /** * Lista degli hook disponibili nel sistema NetGescon * * CORE HOOKS: * - 'user_login' => Dopo il login di un utente * - 'user_logout' => Dopo il logout di un utente * - 'user_created' => Dopo la creazione di un utente * - 'user_updated' => Dopo l'aggiornamento di un utente * - 'user_deleted' => Dopo l'eliminazione di un utente * * STABILI HOOKS: * - 'stabile_created' => Dopo la creazione di uno stabile * - 'stabile_updated' => Dopo l'aggiornamento di uno stabile * - 'stabile_deleted' => Dopo l'eliminazione di uno stabile * * UNITA IMMOBILIARI HOOKS: * - 'unita_created' => Dopo la creazione di un'unità * - 'unita_updated' => Dopo l'aggiornamento di un'unità * - 'unita_deleted' => Dopo l'eliminazione di un'unità * * CONTABILITA HOOKS: * - 'movimento_created' => Dopo la creazione di un movimento contabile * - 'movimento_updated' => Dopo l'aggiornamento di un movimento * - 'bilancio_generated' => Dopo la generazione di un bilancio * - 'rate_generated' => Dopo la generazione delle rate * - 'rata_created' => Dopo la creazione di una rata singola * - 'rata_paid' => Dopo il pagamento di una rata * * DOCUMENTI HOOKS: * - 'document_uploaded' => Dopo l'upload di un documento * - 'document_downloaded' => Dopo il download di un documento * - 'document_deleted' => Dopo l'eliminazione di un documento * * MENU HOOKS: * - 'menu_building' => Durante la costruzione del menu * - 'sidebar_rendering' => Durante il rendering della sidebar * * DASHBOARD HOOKS: * - 'dashboard_stats' => Durante il calcolo delle statistiche dashboard * - 'dashboard_widgets' => Durante il caricamento dei widget dashboard * * STAMPE HOOKS: * - 'before_print' => Prima della generazione di una stampa * - 'after_print' => Dopo la generazione di una stampa * - 'print_template_loading' => Durante il caricamento del template di stampa * * NOTIFICATIONS HOOKS: * - 'notification_sending' => Prima dell'invio di una notifica * - 'notification_sent' => Dopo l'invio di una notifica * - 'email_sending' => Prima dell'invio di una email * - 'email_sent' => Dopo l'invio di una email */