From 5739cc1200c2e720ed88d6d7dd3694e1c42a36c1 Mon Sep 17 00:00:00 2001 From: fs Date: Thu, 19 Mar 2026 08:23:14 +0100 Subject: [PATCH] Refactor helper drift in lib: centralize theme/translation and remove app() hotspots --- .../Container/Registrars/AccessRegistrar.php | 4 +- .../Registrars/ServiceFactoryRegistrar.php | 4 +- lib/Http/AccessControl.php | 7 +-- .../User/UserListQueryRepository.php | 2 +- lib/Service/Access/AccessPolicyFactory.php | 28 ++++++----- lib/Service/Access/UiAccessService.php | 22 ++++---- lib/Service/Auth/AuthSettingsGateway.php | 10 ++++ lib/Service/Auth/SsoUserLinkService.php | 7 +-- .../Directory/DirectoryGatewayFactory.php | 3 +- .../Directory/DirectorySettingsGateway.php | 11 +++- lib/Service/I18n/ServiceTranslator.php | 19 +++++++ lib/Service/I18n/TranslatesServiceText.php | 11 ++++ lib/Service/Import/ImportService.php | 14 ++---- lib/Service/Scheduler/ScheduledJobService.php | 13 ++--- lib/Service/Settings/SettingsAppGateway.php | 50 +++++++++++++++++-- lib/Service/Tenant/TenantService.php | 3 +- lib/Service/User/UserAccountService.php | 8 +-- .../User/UserLifecycleRestoreService.php | 8 +-- .../User/UserPasswordPolicyService.php | 15 ++---- lib/Service/User/UserServicesFactory.php | 3 +- lib/Service/User/UserSettingsGateway.php | 18 +++++++ lib/Support/SearchConfig.php | 19 ++++++- lib/Support/helpers/app.php | 4 ++ web/index.php | 2 +- 24 files changed, 197 insertions(+), 88 deletions(-) create mode 100644 lib/Service/I18n/ServiceTranslator.php create mode 100644 lib/Service/I18n/TranslatesServiceText.php diff --git a/lib/App/Container/Registrars/AccessRegistrar.php b/lib/App/Container/Registrars/AccessRegistrar.php index fc6598d..642aa0b 100644 --- a/lib/App/Container/Registrars/AccessRegistrar.php +++ b/lib/App/Container/Registrars/AccessRegistrar.php @@ -4,6 +4,7 @@ namespace MintyPHP\App\Container\Registrars; use MintyPHP\App\AppContainer; use MintyPHP\App\Container\ContainerRegistrar; +use MintyPHP\App\Module\ModuleRegistry; use MintyPHP\Repository\Access\PermissionRepository; use MintyPHP\Repository\Access\RoleAssignableRoleRepository; use MintyPHP\Repository\Access\RolePermissionRepository; @@ -23,7 +24,8 @@ final class AccessRegistrar implements ContainerRegistrar { $container->set(AuthorizationService::class, static fn (AppContainer $c): AuthorizationService => $c->get(AccessServicesFactory::class)->createAuthorizationService()); $container->set(UiAccessService::class, static fn (AppContainer $c): UiAccessService => new UiAccessService( - $c->get(AuthorizationService::class) + $c->get(AuthorizationService::class), + $c->has(ModuleRegistry::class) ? $c->get(ModuleRegistry::class) : null )); $container->set(PermissionService::class, static fn (AppContainer $c): PermissionService => $c->get(AccessServicesFactory::class)->createPermissionService()); // RoleService lives in DirectoryServicesFactory (not AccessServicesFactory) because diff --git a/lib/App/Container/Registrars/ServiceFactoryRegistrar.php b/lib/App/Container/Registrars/ServiceFactoryRegistrar.php index 486c670..bcf6fe3 100644 --- a/lib/App/Container/Registrars/ServiceFactoryRegistrar.php +++ b/lib/App/Container/Registrars/ServiceFactoryRegistrar.php @@ -4,6 +4,7 @@ namespace MintyPHP\App\Container\Registrars; use MintyPHP\App\AppContainer; use MintyPHP\App\Container\ContainerRegistrar; +use MintyPHP\App\Module\ModuleRegistry; use MintyPHP\Http\CookieStoreInterface; use MintyPHP\Http\RequestRuntimeInterface; use MintyPHP\Http\SessionStoreInterface; @@ -113,7 +114,8 @@ final class ServiceFactoryRegistrar implements ContainerRegistrar )); $container->set(AccessPolicyFactory::class, static fn (AppContainer $c): AccessPolicyFactory => new AccessPolicyFactory( $c->get(PermissionService::class), - $c->get(TenantScopeService::class) + $c->get(TenantScopeService::class), + $c->has(ModuleRegistry::class) ? $c->get(ModuleRegistry::class) : null )); $container->set(UserGatewayFactory::class, static fn (AppContainer $c): UserGatewayFactory => new UserGatewayFactory( $c->get(AccessServicesFactory::class), diff --git a/lib/Http/AccessControl.php b/lib/Http/AccessControl.php index 25ed10d..fe6d7b4 100644 --- a/lib/Http/AccessControl.php +++ b/lib/Http/AccessControl.php @@ -20,10 +20,12 @@ class AccessControl ]; private array $configuredPublicPaths; + private IntendedUrlService $intendedUrlService; - public function __construct(?array $publicPaths = null) + public function __construct(?array $publicPaths = null, ?IntendedUrlService $intendedUrlService = null) { $this->configuredPublicPaths = $publicPaths ?? (defined('APP_PUBLIC_PATHS') ? APP_PUBLIC_PATHS : []); + $this->intendedUrlService = $intendedUrlService ?? new IntendedUrlService(); } /** @@ -74,8 +76,7 @@ class AccessControl $loginPath = Request::withLocale('login', $locale); $requestUri = $_SERVER['REQUEST_URI'] ?? ''; - $intendedUrlService = app(IntendedUrlService::class); - $loginTarget = $intendedUrlService->buildLoginRedirect($loginPath, $requestUri); + $loginTarget = $this->intendedUrlService->buildLoginRedirect($loginPath, $requestUri); Router::redirect($loginTarget); diff --git a/lib/Repository/User/UserListQueryRepository.php b/lib/Repository/User/UserListQueryRepository.php index 61c3e3f..06f7413 100644 --- a/lib/Repository/User/UserListQueryRepository.php +++ b/lib/Repository/User/UserListQueryRepository.php @@ -15,7 +15,7 @@ class UserListQueryRepository implements UserListQueryRepositoryInterface $createdFrom = trim((string) ($options['created_from'] ?? '')); $createdTo = trim((string) ($options['created_to'] ?? '')); $tenant = trim((string) ($options['tenant'] ?? '')); - $tenantUuids = array_filter(array_map('trim', explode(',', (string) ($options['tenants'] ?? '')))); + $tenantUuids = RepoQuery::normalizeStringList($options['tenants'] ?? []); $roleIds = RepoQuery::normalizeIdList($options['roles'] ?? []); $departmentIds = RepoQuery::normalizeIdList($options['departments'] ?? []); $emailVerified = $options['email_verified'] ?? null; diff --git a/lib/Service/Access/AccessPolicyFactory.php b/lib/Service/Access/AccessPolicyFactory.php index 494501a..3ab0961 100644 --- a/lib/Service/Access/AccessPolicyFactory.php +++ b/lib/Service/Access/AccessPolicyFactory.php @@ -2,6 +2,7 @@ namespace MintyPHP\Service\Access; +use MintyPHP\App\Module\ModuleRegistry; use MintyPHP\Service\Tenant\TenantScopeService; class AccessPolicyFactory @@ -17,7 +18,8 @@ class AccessPolicyFactory public function __construct( private readonly PermissionService $permissionService, - private readonly TenantScopeService $tenantScopeService + private readonly TenantScopeService $tenantScopeService, + private readonly ?ModuleRegistry $moduleRegistry = null ) { } @@ -85,20 +87,20 @@ class AccessPolicyFactory ]; // Append module-contributed authorization policies. - try { - /** @var \MintyPHP\App\Module\ModuleRegistry $registry */ - $registry = app(\MintyPHP\App\Module\ModuleRegistry::class); - foreach ($registry->getAuthorizationPolicies() as $policyClass) { - if (!is_string($policyClass) || trim($policyClass) === '') { - continue; - } - $policy = $this->instantiateModulePolicy($policyClass); - if ($policy instanceof AuthorizationPolicyInterface) { - $policies[] = $policy; + if ($this->moduleRegistry !== null) { + try { + foreach ($this->moduleRegistry->getAuthorizationPolicies() as $policyClass) { + if (!is_string($policyClass) || trim($policyClass) === '') { + continue; + } + $policy = $this->instantiateModulePolicy($policyClass); + if ($policy instanceof AuthorizationPolicyInterface) { + $policies[] = $policy; + } } + } catch (\Throwable) { + // fail-open: no module registry available in this context } - } catch (\Throwable) { - // fail-open: no module registry available in this context } return $this->authorizationService = new AuthorizationService($policies); diff --git a/lib/Service/Access/UiAccessService.php b/lib/Service/Access/UiAccessService.php index d970f23..3447a9d 100644 --- a/lib/Service/Access/UiAccessService.php +++ b/lib/Service/Access/UiAccessService.php @@ -2,13 +2,16 @@ namespace MintyPHP\Service\Access; +use MintyPHP\App\Module\ModuleRegistry; + final class UiAccessService { /** @var array */ private array $decisionCache = []; public function __construct( - private readonly AuthorizationService $authorizationService + private readonly AuthorizationService $authorizationService, + private readonly ?ModuleRegistry $moduleRegistry = null ) { } @@ -88,17 +91,16 @@ final class UiAccessService { $map = UiCapabilityMap::LAYOUT; - // Merge module-contributed layout capabilities dynamically. - try { - /** @var \MintyPHP\App\Module\ModuleRegistry $registry */ - $registry = app(\MintyPHP\App\Module\ModuleRegistry::class); - if ($registry instanceof \MintyPHP\App\Module\ModuleRegistry) { - foreach ($registry->getLayoutCapabilities() as $key => $ability) { - $map[$key] = $ability; + // Merge module UI slot abilities directly into the capability map. + // Each ability string is used as both key and value (no indirection). + if ($this->moduleRegistry !== null) { + try { + foreach ($this->moduleRegistry->getModuleUiAbilities() as $ability) { + $map[$ability] = $ability; } + } catch (\Throwable) { + // fail-open: no module registry available in this context } - } catch (\Throwable) { - // fail-open: no module registry available in this context } return $this->resolveMap($actorUserId, $map); diff --git a/lib/Service/Auth/AuthSettingsGateway.php b/lib/Service/Auth/AuthSettingsGateway.php index 4a3bf02..ff01d5f 100644 --- a/lib/Service/Auth/AuthSettingsGateway.php +++ b/lib/Service/Auth/AuthSettingsGateway.php @@ -49,6 +49,16 @@ class AuthSettingsGateway return (string) $this->settingsAppGateway->getAppTheme(); } + public function defaultTheme(): string + { + return $this->settingsAppGateway->resolveDefaultTheme(); + } + + public function normalizeTheme(?string $theme): string + { + return $this->settingsAppGateway->normalizeTheme($theme); + } + public function getDefaultRoleId(): int { return (int) $this->settingsDefaultsGateway->getDefaultRoleId(); diff --git a/lib/Service/Auth/SsoUserLinkService.php b/lib/Service/Auth/SsoUserLinkService.php index fbe2db7..1663e8e 100644 --- a/lib/Service/Auth/SsoUserLinkService.php +++ b/lib/Service/Auth/SsoUserLinkService.php @@ -269,11 +269,6 @@ class SsoUserLinkService private function resolveInitialTheme(?string $theme): string { - $theme = strtolower(trim((string) ($theme ?? ''))); - $themes = function_exists('appThemes') ? appThemes() : ['light' => 'Light']; - if ($theme !== '' && isset($themes[$theme])) { - return $theme; - } - return isset($themes['light']) ? 'light' : (string) array_key_first($themes); + return $this->settingsGateway->normalizeTheme($theme); } } diff --git a/lib/Service/Directory/DirectoryGatewayFactory.php b/lib/Service/Directory/DirectoryGatewayFactory.php index 8aeb600..780d75b 100644 --- a/lib/Service/Directory/DirectoryGatewayFactory.php +++ b/lib/Service/Directory/DirectoryGatewayFactory.php @@ -17,7 +17,8 @@ class DirectoryGatewayFactory public function createDirectorySettingsGateway(): DirectorySettingsGateway { return $this->directorySettingsGateway ??= new DirectorySettingsGateway( - $this->settingServicesFactory->createSettingsDefaultsGateway() + $this->settingServicesFactory->createSettingsDefaultsGateway(), + $this->settingServicesFactory->createSettingsAppGateway() ); } diff --git a/lib/Service/Directory/DirectorySettingsGateway.php b/lib/Service/Directory/DirectorySettingsGateway.php index 887537d..91cbe08 100644 --- a/lib/Service/Directory/DirectorySettingsGateway.php +++ b/lib/Service/Directory/DirectorySettingsGateway.php @@ -2,11 +2,15 @@ namespace MintyPHP\Service\Directory; +use MintyPHP\Service\Settings\SettingsAppGateway; use MintyPHP\Service\Settings\SettingsDefaultsGateway; class DirectorySettingsGateway { - public function __construct(private readonly SettingsDefaultsGateway $settingsDefaultsGateway) + public function __construct( + private readonly SettingsDefaultsGateway $settingsDefaultsGateway, + private readonly SettingsAppGateway $settingsAppGateway + ) { } @@ -24,4 +28,9 @@ class DirectorySettingsGateway { $this->settingsDefaultsGateway->setDefaultRoleId($roleId); } + + public function isAllowedTheme(string $theme): bool + { + return $this->settingsAppGateway->isAllowedTheme($theme); + } } diff --git a/lib/Service/I18n/ServiceTranslator.php b/lib/Service/I18n/ServiceTranslator.php new file mode 100644 index 0000000..caf7509 --- /dev/null +++ b/lib/Service/I18n/ServiceTranslator.php @@ -0,0 +1,19 @@ + (string) $arg, $args)); + } +} diff --git a/lib/Service/I18n/TranslatesServiceText.php b/lib/Service/I18n/TranslatesServiceText.php new file mode 100644 index 0000000..5c440a0 --- /dev/null +++ b/lib/Service/I18n/TranslatesServiceText.php @@ -0,0 +1,11 @@ + (string) $arg, $args)); - } - } diff --git a/lib/Service/Scheduler/ScheduledJobService.php b/lib/Service/Scheduler/ScheduledJobService.php index f7db841..380bb8a 100644 --- a/lib/Service/Scheduler/ScheduledJobService.php +++ b/lib/Service/Scheduler/ScheduledJobService.php @@ -4,9 +4,12 @@ namespace MintyPHP\Service\Scheduler; use MintyPHP\Repository\Scheduler\ScheduledJobRepositoryInterface; use MintyPHP\Repository\Scheduler\ScheduledJobRunRepositoryInterface; +use MintyPHP\Service\I18n\TranslatesServiceText; class ScheduledJobService { + use TranslatesServiceText; + private const RUN_RETENTION_DAYS = 90; public function __construct( @@ -280,14 +283,4 @@ class ScheduledJobService }; } - private function translate(string $text, mixed ...$args): string - { - if (function_exists('t')) { - return t($text, ...$args); - } - if ($args === []) { - return $text; - } - return vsprintf($text, array_map(static fn ($arg) => (string) $arg, $args)); - } } diff --git a/lib/Service/Settings/SettingsAppGateway.php b/lib/Service/Settings/SettingsAppGateway.php index 503a7b5..96916b5 100644 --- a/lib/Service/Settings/SettingsAppGateway.php +++ b/lib/Service/Settings/SettingsAppGateway.php @@ -57,7 +57,7 @@ class SettingsAppGateway { $value = $this->settingsMetadataGateway->getValue(SettingKeys::APP_THEME_KEY); $value = $value !== null ? strtolower(trim($value)) : ''; - if (!in_array($value, $this->allowedThemes(), true)) { + if (!$this->isAllowedTheme($value)) { return null; } @@ -67,7 +67,7 @@ class SettingsAppGateway public function setAppTheme(?string $theme, ?string $description = null): bool { $value = $theme !== null ? strtolower(trim($theme)) : ''; - if ($value === '' || !in_array($value, $this->allowedThemes(), true)) { + if ($value === '' || !$this->isAllowedTheme($value)) { $value = null; } @@ -75,6 +75,50 @@ class SettingsAppGateway return $this->settingsMetadataGateway->set(SettingKeys::APP_THEME_KEY, $value, $desc); } + /** + * @return array + */ + public function listThemes(): array + { + return $this->themeConfigService->all(); + } + + public function isAllowedTheme(?string $theme): bool + { + $value = strtolower(trim((string) $theme)); + return $value !== '' && in_array($value, $this->allowedThemes(), true); + } + + public function resolveDefaultTheme(): string + { + $settingTheme = $this->getAppTheme(); + if ($settingTheme !== null) { + return $settingTheme; + } + + $envTheme = strtolower(trim((string) (getenv('APP_THEME') ?: ''))); + if ($this->isAllowedTheme($envTheme)) { + return $envTheme; + } + + $allowedThemes = $this->allowedThemes(); + if (in_array('light', $allowedThemes, true)) { + return 'light'; + } + + return (string) ($allowedThemes[0] ?? 'light'); + } + + public function normalizeTheme(?string $theme): string + { + $value = strtolower(trim((string) $theme)); + if ($this->isAllowedTheme($value)) { + return $value; + } + + return $this->resolveDefaultTheme(); + } + public function isUserThemeAllowed(): bool { $value = $this->settingsMetadataGateway->getValue(SettingKeys::APP_THEME_USER_KEY); @@ -146,7 +190,7 @@ class SettingsAppGateway private function allowedThemes(): array { - return array_keys($this->themeConfigService->all()); + return array_keys($this->listThemes()); } public function normalizeLocale(?string $locale): string diff --git a/lib/Service/Tenant/TenantService.php b/lib/Service/Tenant/TenantService.php index 3687f70..dfc5e69 100644 --- a/lib/Service/Tenant/TenantService.php +++ b/lib/Service/Tenant/TenantService.php @@ -247,8 +247,7 @@ class TenantService ) { $errors[] = t('Primary color is invalid'); } - $themes = function_exists('appThemes') ? appThemes() : []; - if ($form['default_theme'] !== '' && !isset($themes[$form['default_theme']])) { + if ($form['default_theme'] !== '' && !$this->settingsGateway->isAllowedTheme((string) $form['default_theme'])) { $errors[] = t('Default theme is invalid'); } if (!in_array($form['allow_user_theme_mode'], ['', '0', '1'], true)) { diff --git a/lib/Service/User/UserAccountService.php b/lib/Service/User/UserAccountService.php index 667499f..762d3c2 100644 --- a/lib/Service/User/UserAccountService.php +++ b/lib/Service/User/UserAccountService.php @@ -724,12 +724,8 @@ class UserAccountService private function normalizeTheme($value): string { - $theme = strtolower(trim((string) $value)); - $themes = function_exists('appThemes') ? appThemes() : ['light' => 'Light', 'dark' => 'Dark']; - if ($theme === '' || !isset($themes[$theme])) { - return function_exists('appDefaultTheme') ? appDefaultTheme() : 'light'; - } - return $theme; + $theme = is_scalar($value) ? (string) $value : null; + return $this->settingsGateway->normalizeTheme($theme); } private function normalizeLocale($value): string diff --git a/lib/Service/User/UserLifecycleRestoreService.php b/lib/Service/User/UserLifecycleRestoreService.php index 5dac63d..1d9a715 100644 --- a/lib/Service/User/UserLifecycleRestoreService.php +++ b/lib/Service/User/UserLifecycleRestoreService.php @@ -14,7 +14,8 @@ class UserLifecycleRestoreService private readonly UserReadRepositoryInterface $userReadRepository, private readonly UserWriteRepositoryInterface $userWriteRepository, private readonly UserLifecycleAuditService $userLifecycleAuditService, - private readonly DatabaseSessionRepository $databaseSessionRepository + private readonly DatabaseSessionRepository $databaseSessionRepository, + private readonly UserSettingsGateway $userSettingsGateway ) { } @@ -171,8 +172,7 @@ class UserLifecycleRestoreService private function normalizeTheme(mixed $value): string { - $theme = strtolower(trim((string) $value)); - $themes = appThemes(); - return isset($themes[$theme]) ? $theme : appDefaultTheme(); + $theme = is_scalar($value) ? (string) $value : null; + return $this->userSettingsGateway->normalizeTheme($theme); } } diff --git a/lib/Service/User/UserPasswordPolicyService.php b/lib/Service/User/UserPasswordPolicyService.php index aee2e03..f31821e 100644 --- a/lib/Service/User/UserPasswordPolicyService.php +++ b/lib/Service/User/UserPasswordPolicyService.php @@ -2,8 +2,12 @@ namespace MintyPHP\Service\User; +use MintyPHP\Service\I18n\TranslatesServiceText; + class UserPasswordPolicyService { + use TranslatesServiceText; + private const PASSWORD_MIN_LENGTH = 12; public function validate(string $password, string $password2, bool $required, ?string $email): array @@ -61,15 +65,4 @@ class UserPasswordPolicyService return self::PASSWORD_MIN_LENGTH; } - // Wrapper so this service can be used in tests before the t() helper is loaded. - private function translate(string $text, mixed ...$args): string - { - if (function_exists('t')) { - return t($text, ...$args); - } - if ($args === []) { - return $text; - } - return vsprintf($text, array_map(static fn ($arg) => (string) $arg, $args)); - } } diff --git a/lib/Service/User/UserServicesFactory.php b/lib/Service/User/UserServicesFactory.php index 680af26..ea91f30 100644 --- a/lib/Service/User/UserServicesFactory.php +++ b/lib/Service/User/UserServicesFactory.php @@ -153,7 +153,8 @@ class UserServicesFactory $this->createUserReadRepository(), $this->createUserWriteRepository(), $this->createUserLifecycleAuditService(), - $this->databaseSessionRepository + $this->databaseSessionRepository, + $this->createUserSettingsGateway() ); } diff --git a/lib/Service/User/UserSettingsGateway.php b/lib/Service/User/UserSettingsGateway.php index 9f92ab2..af2d774 100644 --- a/lib/Service/User/UserSettingsGateway.php +++ b/lib/Service/User/UserSettingsGateway.php @@ -35,6 +35,24 @@ class UserSettingsGateway return $this->settingsAppGateway->getAppTheme(); } + /** + * @return array + */ + public function appThemes(): array + { + return $this->settingsAppGateway->listThemes(); + } + + public function defaultTheme(): string + { + return $this->settingsAppGateway->resolveDefaultTheme(); + } + + public function normalizeTheme(?string $theme): string + { + return $this->settingsAppGateway->normalizeTheme($theme); + } + public function getUserInactivityDeactivateDays(): int { return $this->settingsUserLifecycleGateway->getUserInactivityDeactivateDays(); diff --git a/lib/Support/SearchConfig.php b/lib/Support/SearchConfig.php index 6a39bf6..cf9c80b 100644 --- a/lib/Support/SearchConfig.php +++ b/lib/Support/SearchConfig.php @@ -18,6 +18,15 @@ class SearchConfig /** @var array key→provider lookup */ private static array $moduleProviderByKey = []; + /** @var (callable(): ModuleRegistry)|null */ + private static $moduleRegistryResolver = null; + + public static function configure(callable $moduleRegistryResolver): void + { + self::$moduleRegistryResolver = $moduleRegistryResolver; + self::resetModuleProviders(); + } + public static function tenantScopeFilters(): array { $filters = SearchSqlResourceProvider::tenantScopeFilters(); @@ -136,9 +145,15 @@ class SearchConfig self::$moduleProviders = []; self::$moduleProviderByKey = []; + if (!is_callable(self::$moduleRegistryResolver)) { + return self::$moduleProviders; + } + try { - /** @var ModuleRegistry $registry */ - $registry = app(ModuleRegistry::class); + $registry = (self::$moduleRegistryResolver)(); + if (!$registry instanceof ModuleRegistry) { + return self::$moduleProviders; + } foreach ($registry->getSearchResources() as $providerClass) { if (!class_exists($providerClass)) { continue; diff --git a/lib/Support/helpers/app.php b/lib/Support/helpers/app.php index ff73d66..3baebe5 100644 --- a/lib/Support/helpers/app.php +++ b/lib/Support/helpers/app.php @@ -59,6 +59,10 @@ function setAppContainer(\MintyPHP\App\AppContainer $container): void static fn (): \MintyPHP\Service\Access\AuthorizationService => $container->get(\MintyPHP\Service\Access\AuthorizationService::class) ); + \MintyPHP\Support\SearchConfig::configure( + static fn (): \MintyPHP\App\Module\ModuleRegistry => $container->get(\MintyPHP\App\Module\ModuleRegistry::class) + ); + } /** diff --git a/web/index.php b/web/index.php index d6193d3..679a234 100644 --- a/web/index.php +++ b/web/index.php @@ -248,7 +248,7 @@ $allPublicPaths = array_values(array_unique(array_merge( defined('APP_PUBLIC_PATHS') ? APP_PUBLIC_PATHS : [], $moduleRegistry->getPublicPaths() ))); -$accessControl = new AccessControl($allPublicPaths); +$accessControl = new AccessControl($allPublicPaths, app(IntendedUrlService::class)); $accessControl->requireAuthOrRedirect($pathWithoutLocale, !empty($_SESSION['user']['id'])); // ── 9. Code analysis (debug only) ──────────────────────────────────