*/ private array $services = []; /** @var array */ private array $factories; public function __construct(Settings $settings) { $this->factories = [ TreeMapper::class => fn () => new TypeTreeMapper( $this->get(TypeParser::class), $this->get(RootNodeBuilder::class), ), ArgumentsMapper::class => fn () => new TypeArgumentsMapper( $this->get(FunctionDefinitionRepository::class), $this->get(RootNodeBuilder::class), ), RootNodeBuilder::class => fn () => new RootNodeBuilder( $this->get(NodeBuilder::class), $this->get(TypeDumper::class), $settings, ), NodeBuilder::class => function () use ($settings) { $builder = new TypeNodeBuilder( new ArrayNodeBuilder(), new ListNodeBuilder(), new ShapedArrayNodeBuilder(), new ScalarNodeBuilder(), new UnionNodeBuilder(), new NullNodeBuilder(), new MixedNodeBuilder(), new UndefinedObjectNodeBuilder(), new ObjectNodeBuilder( $this->get(ClassDefinitionRepository::class), $this->get(ObjectBuilderFactory::class), new InterfaceNodeBuilder( $this->get(InterfaceInferringContainer::class), new FunctionsContainer( $this->get(FunctionDefinitionRepository::class), $settings->customConstructors, ), $settings->exceptionFilter, ), $settings->exceptionFilter, ), ); return new ValueConverterNodeBuilder( $builder, $this->get(ConverterContainer::class), $this->get(ClassDefinitionRepository::class), $this->get(FunctionDefinitionRepository::class), $settings->exceptionFilter, ); }, ConverterContainer::class => fn () => new ConverterContainer( $this->get(FunctionDefinitionRepository::class), $settings->convertersSortedByPriority(), ), InterfaceInferringContainer::class => fn () => new InterfaceInferringContainer( new FunctionsContainer( $this->get(FunctionDefinitionRepository::class), $settings->inferredMapping, ), $this->get(TypeParser::class), ), ObjectBuilderFactory::class => function () use ($settings) { $constructors = new FunctionsContainer( $this->get(FunctionDefinitionRepository::class), $settings->customConstructors, ); $factory = new ReflectionObjectBuilderFactory(); $factory = new ConstructorObjectBuilderFactory($factory, $settings->nativeConstructors, $constructors); $factory = new DateTimeZoneObjectBuilderFactory($factory, $this->get(FunctionDefinitionRepository::class)); $factory = new DateTimeObjectBuilderFactory($factory, $settings->supportedDateFormats, $this->get(FunctionDefinitionRepository::class)); $factory = new SortingObjectBuilderFactory($factory); $factory = new CircularDependencyDetectorObjectBuilderFactory($factory); if (! $settings->allowPermissiveTypes) { $factory = new StrictTypesObjectBuilderFactory($factory); } return new InMemoryObjectBuilderFactory($factory); }, Transformer::class => function () use ($settings) { if (isset($settings->cache)) { return new CompiledTransformer( $this->get(TransformerDefinitionBuilder::class), $this->get(TypeFilesWatcher::class), new RuntimeCache($this->get(Cache::class)), // @phpstan-ignore argument.type $settings->transformersSortedByPriority(), ); } return new RecursiveTransformer( $this->get(ClassDefinitionRepository::class), $this->get(FunctionDefinitionRepository::class), $this->get(TransformerContainer::class), ); }, TransformerContainer::class => fn () => new TransformerContainer( $this->get(FunctionDefinitionRepository::class), $settings->transformersSortedByPriority(), ), ArrayNormalizer::class => fn () => new ArrayNormalizer( $this->get(Transformer::class), ), JsonNormalizer::class => fn () => new JsonNormalizer( $this->get(Transformer::class), ), TransformerDefinitionBuilder::class => fn () => new TransformerDefinitionBuilder( $this->get(ClassDefinitionRepository::class), $this->get(FunctionDefinitionRepository::class), $this->get(TransformerContainer::class), ), ClassDefinitionRepository::class => function () use ($settings) { $repository = new ReflectionClassDefinitionRepository( $this->get(TypeParserFactory::class), $settings->allowedAttributes(), ); if (isset($settings->cache)) { $repository = new CompiledClassDefinitionRepository( $repository, $this->get(Cache::class), new ClassDefinitionCompiler(), ); } return new InMemoryClassDefinitionRepository($repository); }, FunctionDefinitionRepository::class => function () use ($settings) { $repository = new ReflectionFunctionDefinitionRepository( $this->get(TypeParserFactory::class), new ReflectionAttributesRepository( $this->get(ClassDefinitionRepository::class), $settings->allowedAttributes(), ), ); if (isset($settings->cache)) { $repository = new CompiledFunctionDefinitionRepository( $repository, $this->get(Cache::class), new FunctionDefinitionCompiler(), ); } return new InMemoryFunctionDefinitionRepository($repository); }, TypeParserFactory::class => fn () => new TypeParserFactory(), TypeParser::class => fn () => $this->get(TypeParserFactory::class)->buildDefaultTypeParser(), TypeDumper::class => fn () => new TypeDumper( $this->get(ClassDefinitionRepository::class), $this->get(ObjectBuilderFactory::class), $this->get(InterfaceInferringContainer::class), new FunctionsContainer( $this->get(FunctionDefinitionRepository::class), $settings->customConstructors, ), ), RecursiveCacheWarmupService::class => fn () => new RecursiveCacheWarmupService( $this->get(TypeParser::class), $this->get(InterfaceInferringContainer::class), $this->get(ClassDefinitionRepository::class), $this->get(ObjectBuilderFactory::class), ), Cache::class => fn () => new KeySanitizerCache($settings->cache, $settings), TypeFilesWatcher::class => fn () => new TypeFilesWatcher( $settings, $this->get(ClassDefinitionRepository::class), ), ]; } public function treeMapper(): TreeMapper { return $this->get(TreeMapper::class); } public function argumentsMapper(): ArgumentsMapper { return $this->get(ArgumentsMapper::class); } /** * @template T of Normalizer * * @param Format $format * @return T */ public function normalizer(Format $format): Normalizer { return $this->get($format->type()); } public function cacheWarmupService(): RecursiveCacheWarmupService { return $this->get(RecursiveCacheWarmupService::class); } /** * @template T of object * @param class-string $name * @return T */ public function get(string $name): object { return $this->services[$name] ??= call_user_func($this->factories[$name]); // @phpstan-ignore-line } }