moduleSubscriptionService === null) { $this->moduleSubscriptionService = service('moduleSubscription'); } return $this->moduleSubscriptionService; } /** * Получить конфигурацию модулей * * @return \Config\BusinessModules */ private function getModulesConfig(): \Config\BusinessModules { if ($this->modulesConfig === null) { $this->modulesConfig = config('BusinessModules'); } return $this->modulesConfig; } /** * Привязать события к конкретному модулю * * Все последующие вызовы moduleOn() будут проверять * подписку на указанный модуль. * * @param string $moduleCode Код модуля * @return $this */ public function forModule(string $moduleCode): self { $this->moduleCode = $moduleCode; $this->moduleActive = null; return $this; } /** * Проверить, активен ли модуль * * @return bool */ private function isModuleActive(): bool { if ($this->moduleCode === null) { return false; } if ($this->moduleActive === null) { $orgId = session('org_id') ?? null; $this->moduleActive = $this->getModuleSubscriptionService() ->isModuleActive($this->moduleCode, $orgId); } return $this->moduleActive; } /** * Подписаться на событие с проверкой подписки на модуль * * Обработчик будет выполнен только если: * 1. Модуль глобально включен в конфигурации * 2. У организации есть активная подписка на модуль * * @param string $event Имя события * @param callable $callback Обработчик события * @param int $priority Приоритет события (по умолчанию 100) * @return bool True если подписка создана, False если модуль не активен */ public function moduleOn( string $event, callable $callback, int $priority = 100 ): bool { if ($this->moduleCode === null) { throw new \RuntimeException( 'Module code not set. Use forModule() method first.' ); } $modulesConfig = $this->getModulesConfig(); // Проверяем, что модуль существует в конфигурации if (!isset($modulesConfig->modules[$this->moduleCode])) { log_message( 'error', "EventManager: Module '{$this->moduleCode}' not found in config" ); return false; } // Если модуль отключен глобально, не подписываемся // Проверяем наличие поля enabled (опционально) if (isset($modulesConfig->modules[$this->moduleCode]['enabled']) && empty($modulesConfig->modules[$this->moduleCode]['enabled'])) { log_message( 'info', "EventManager: Module '{$this->moduleCode}' is disabled globally" ); return false; } // Проверяем подписку организации if (!$this->isModuleActive()) { log_message( 'debug', "EventManager: Organization subscription not active for module '{$this->moduleCode}'" ); return false; } // Подписываемся на событие Events::on($event, $callback, $priority); log_message( 'debug', "EventManager: Subscribed to event '{$event}' for module '{$this->moduleCode}'" ); return true; } /** * Подписаться на событие без проверки подписки * * Обработчик будет выполнен всегда, независимо * от статуса подписки на модуль. * * Используется для системных событий, которые должны * работать для всех организаций. * * @param string $event Имя события * @param callable $callback Обработчик события * @param int $priority Приоритет события (по умолчанию 100) * @return void */ public function systemOn( string $event, callable $callback, int $priority = 100 ): void { Events::on($event, $callback, $priority); log_message( 'debug', "EventManager: System event subscribed: '{$event}'" ); } /** * Отписаться от события * * @param string $event Имя события * @param callable|null $callback Конкретный обработчик (если null - все обработчики) * @return void */ public function off(string $event, ?callable $callback = null): void { if ($callback === null) { Events::off($event); } else { Events::off($event, $callback); } } /** * Проверить, активен ли текущий модуль * * Удобный метод для использования внутри обработчиков событий. * * @return bool */ public function currentModuleActive(): bool { return $this->isModuleActive(); } /** * Получить код текущего модуля * * @return string|null */ public function getCurrentModuleCode(): ?string { return $this->moduleCode; } }