Expect::string()->default(null), 'projectName' => Expect::string()->default(null), 'adminHostPath' => Expect::string()->default(null), 'defaultCustomerRoute' => Expect::string()->default(':PortalCustomer:Home:'), 'defaultBackofficeRoute' => Expect::string()->default(':PortalBackoffice:Home:'), 'lostPasswordEnabled' => Expect::bool()->default(true), 'logoPublicPath' => Expect::string()->default(null), 'logoMenuPath' => Expect::string()->default(null), 'loginPageLogoPath' => Expect::string()->default(null), 'logoBitmapPublicPath' => Expect::string()->default(null), 'emailBackgroundColor' => Expect::string()->default(null), 'faviconFileNamePng' => Expect::string()->nullable()->default(null), 'faviconFileNameSvg' => Expect::string()->nullable()->default(null), 'hmr' => Expect::bool()->default(false), 'customerAclResource' => Expect::type(Resource::class)->default(AclResourceNameEnum::CUSTOMER_DASHBOARD), 'backofficeAclResource' => Expect::type(Resource::class)->default(AclResourceNameEnum::BACKOFFICE_DASHBOARD), 'fullDataAclResource' => Expect::type(Resource::class)->default(AclResourceNameEnum::FULL_DATA), 'context' => Expect::string()->default(null), 'jsComponentsConfig' => Expect::array()->default([]), 'locksDir' => Expect::string()->required(), 'keycloakEnabled' => Expect::bool()->default(false), 'colors' => Expect::structure([ 'backgroundColor' => Expect::string()->required(), 'dashboardAccentColor' => Expect::string()->required(), 'primaryColor' => Expect::string()->required(), 'primaryColorDark' => Expect::string()->required(), 'primaryColorDark20' => Expect::string()->required(), 'secondaryColor' => Expect::string()->required(), 'secondaryColorDark' => Expect::string()->required(), 'secondaryColorDarker' => Expect::string()->required(), 'ternaryColor' => Expect::string()->required(), 'ternaryTextColor' => Expect::string()->required(), 'loginBackground' => Expect::string()->required(), 'loginInputTextColor' => Expect::string()->required(), 'loginBackgroundInput' => Expect::string()->required(), 'loginBackgroundInputFocus' => Expect::string()->required(), 'inputBorder' => Expect::string()->required(), 'inputFocusBorder' => Expect::string()->required(), 'inputFocusBackground' => Expect::string()->required(), ]), ]); } public function loadConfiguration(): void { $builder = $this->getContainerBuilder(); $this->config = (new Processor)->process($this->getConfigSchema(), $this->config); $builder->addFactoryDefinition($this->prefix('sidePanelControlFactory')) ->setImplement(SidePanelControlFactory::class) ->getResultDefinition() ->setFactory(SidePanelControl::class); $builder->addDefinition($this->prefix('fancyAdminRouter')) ->setFactory(FancyAdminRouter::class); $builder->addDefinition($this->prefix('administration')) ->setFactory(FancyAdmin::class, [ 'project' => $this->config->project, 'projectName' => $this->config->projectName, 'adminHostPath' => $this->config->adminHostPath, 'logoPublicPath' => $this->config->logoPublicPath, 'logoMenuPath' => $this->config->logoMenuPath, 'loginPageLogoPath' => $this->config->loginPageLogoPath, 'logoBitmapPublicPath' => $this->config->logoBitmapPublicPath, 'lostPasswordEnabled' => $this->config->lostPasswordEnabled, 'defaultCustomerRoute' => $this->config->defaultCustomerRoute, 'defaultBackofficeRoute' => $this->config->defaultBackofficeRoute, 'emailBackgroundColor' => $this->config->emailBackgroundColor, 'faviconFileNamePng' => $this->config->faviconFileNamePng, 'faviconFileNameSvg' => $this->config->faviconFileNameSvg, 'hmr' => $this->config->hmr, 'customerAclResource' => $this->config->customerAclResource, 'backofficeAclResource' => $this->config->backofficeAclResource, 'fullDataAclResource' => $this->config->fullDataAclResource, 'jsComponentsConfig' => $this->config->jsComponentsConfig, 'context' => $this->config->context, 'colors' => (array) $this->config->colors, 'keycloakEnabled' => $this->config->keycloakEnabled, ]); $builder->addDefinition($this->prefix('jsComponents')) ->setFactory(JsComponents::class); // Keycloak — registrace KeycloakManager (instance se vytváří lazy z DB) if ($this->config->keycloakEnabled) { $builder->addDefinition($this->prefix('keycloakManager')) ->setFactory(KeycloakManager::class); } //$this->validateTraitInterfaceCompliance(); // command registration $defs[] = $builder->addDefinition($this->prefix('createIdentity')) ->setFactory(CreateIdentityCommand::class) ->setAutowired(false); $defs[] = $builder->addDefinition($this->prefix('generateMissingAclResources')) ->setFactory(GenerateMissingAclResourcesCommand::class, [ 'appDir' => $builder->parameters['appDir'], ]) ->setAutowired(false); foreach ($defs as $_def) { $_def->addSetup('setLocksDir', [$this->config->locksDir]); } } public function beforeCompile(): void { $builder = $this->getContainerBuilder(); $securityUserDef = $builder->getDefinitionByType(SecurityUser::class); $securityUserDef->addSetup('setFullDataAclResource', [$this->config->fullDataAclResource]); $securityUserDef->addSetup('setBackofficeAclResource', [$this->config->backofficeAclResource]); $authenticatorDef = $builder->getDefinitionByType(Authenticator::class); $authenticatorDef->addSetup('setFancyAdmin', [$this->prefix('@administration')]); $authenticatorDef->addSetup('setExpirationCallback', [ new Statement('Closure::fromCallable', ['@fancyadmin.sessionExpirationCallback']), ]); if ($this->config->keycloakEnabled) { $fancyAdminDef = $builder->getDefinition($this->prefix('administration')); $fancyAdminDef->addSetup('setKeycloakManager', [$this->prefix('@keycloakManager')]); } } private function validateTraitInterfaceCompliance(): void { $traitInterfaceMap = [ AclResourceTrait::class => AclResource::class, AclRoleTrait::class => AclRole::class, IdentityTrait::class => Identity::class, ProfileTrait::class => Profile::class, ]; $loader = new RobotLoader(); $loader->addDirectory(__DIR__ . '/../../../../../app/Model/Entities'); $loader->acceptFiles = ['*.php']; $loader->rebuild(); foreach (array_keys($loader->getIndexedClasses()) as $class) { if (!class_exists($class)) { continue; } $reflection = new ReflectionClass($class); if (!$reflection->isInstantiable() || $reflection->isAbstract()) { continue; } $usedTraits = $this->class_uses_recursive($class); foreach ($traitInterfaceMap as $trait => $interface) { if (in_array($trait, $usedTraits, true) && !$reflection->implementsInterface($interface)) { throw new RuntimeException("Třída $class používá $trait, ale neimplementuje požadované rozhraní $interface."); } } } } private function class_uses_recursive(string $class): array { $results = []; do { $results += class_uses($class); } while ($class = get_parent_class($class)); foreach ($results as $trait) { $results += $this->class_uses_recursive($trait); } return array_unique($results); } public function getTranslationResources(): array { return [__DIR__ . '/../lang']; } }