container = $container; } public function create(string $className) : object { return $this->createByClassName($className); } public function createByClassName(string $className) : object { if (!class_exists($className)) { throw new Error("Class '{$className}' does not exist."); } $class = new \ReflectionClass($className); if ($class->implementsInterface('\\Espo\\Core\\Interfaces\\Injectable')) { return $this->createByClassNameInjectable($className); } return $this->createByClassNameByConstructorParams($className); } protected function createByClassNameByConstructorParams(string $className) { $class = new \ReflectionClass($className); $dependencyList = []; $constructor = $class->getConstructor(); if (!is_null($constructor)) { $params = $constructor->getParameters(); foreach ($params as $param) { $dependencyClassName = $param->getClass(); if (is_null($dependencyClassName)) { if ($param->isDefaultValueAvailable()) { $dependencyList[] = $param->getDefaultValue(); continue; } } $name = $param->getName(); $dependency = $this->getContainer()->get($name); if (!$dependency) { throw new Error("InjectableFactory: Could not create {$className}, dependency {$name} not found."); } $dependencyList[] = $dependency; } } return $class->newInstanceArgs($dependencyList); } protected function createByClassNameInjectable(string $className) { $obj = new $className(); $dependencyList = $obj->getDependencyList(); foreach ($dependencyList as $name) { $obj->inject($name, $this->container->get($name)); } if (method_exists($obj, 'prepare')) { $obj->prepare(); } return $obj; } protected function getContainer() { return $this->container; } }