*/ private function getClassName(string $entityType): ?string { /** @var ?class-string */ return $this->classFinder->find('Entities', $entityType); } public function setEntityManager(EntityManager $entityManager): void { if ($this->entityManager) { throw new RuntimeException("EntityManager can be set only once."); } $this->entityManager = $entityManager; } public function setValueAccessorFactory(ValueAccessorFactory $valueAccessorFactory): void { if ($this->valueAccessorFactory) { throw new RuntimeException("ValueAccessorFactory can be set only once."); } $this->valueAccessorFactory = $valueAccessorFactory; } public function create(string $entityType): Entity { $className = $this->getClassName($entityType); if (!$className) { $className = BaseEntity::class; } if (!$this->entityManager) { throw new RuntimeException(); } $defs = $this->entityManager->getMetadata()->get($entityType); if (is_null($defs)) { throw new RuntimeException("Entity '{$entityType}' is not defined in metadata."); } $bindingContainer = $this->getBindingContainer($className, $entityType, $defs); return $this->injectableFactory->createWithBinding($className, $bindingContainer); } /** * @param class-string $className * @param array $defs */ private function getBindingContainer(string $className, string $entityType, array $defs): BindingContainer { if (!$this->entityManager || !$this->valueAccessorFactory) { throw new RuntimeException(); } $data = new BindingData(); $binder = new Binder($data); $binder ->for($className) ->bindValue('$entityType', $entityType) ->bindValue('$defs', $defs) ->bindInstance(EntityManager::class, $this->entityManager) ->bindInstance(ValueAccessorFactory::class, $this->valueAccessorFactory) ->bindInstance(Helper::class, $this->helper); return new BindingContainer($data); } }