netgescon-day0/app/Services/HookManager.php

280 lines
8.3 KiB
PHP
Executable File

<?php
namespace App\Services;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
/**
* NetGescon Hook Manager
*
* Sistema di hook per permettere ai moduli di interagire
* tra loro e con il sistema core senza accoppiamento stretto
*/
class HookManager
{
protected static $hooks = [];
protected static $instance = null;
/**
* Singleton pattern per garantire una sola istanza
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Registra un hook
*
* @param string $hookName Nome dell'hook
* @param callable $callback Funzione da eseguire
* @param int $priority Priorità di esecuzione (più basso = più priorità)
* @param string $moduleName Nome del modulo che registra l'hook
*/
public static function register($hookName, $callback, $priority = 10, $moduleName = 'core')
{
if (!isset(self::$hooks[$hookName])) {
self::$hooks[$hookName] = [];
}
self::$hooks[$hookName][] = [
'callback' => $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
*/