_singletons[$class])) { return $this->_singletons[$class]; } else if (!isset($this->_constructs[$class])) { return $this->resolve($class, $constrict, $config); } $definition = $this->_constructs[$class]; if (is_callable($definition, TRUE)) { return call_user_func($definition, $this, $constrict, $config); } else if (is_array($definition)) { $object = $this->resolveDefinition($definition, $class, $config, $constrict); } else if (is_object($definition)) { return $this->_singletons[$class] = $definition; } else { throw new NotFindClassException($class); } return $this->_singletons[$class] = $object; } /** * @param $definition * @param $class * @param $config * @param $constrict * @return mixed * @throws NotFindClassException * @throws ReflectionException */ private function resolveDefinition($definition, $class, $config, $constrict): mixed { if (!isset($definition['class'])) { throw new NotFindClassException($class); } $_className = $definition['class']; unset($definition['class']); $config = array_merge($definition, $config); $definition = $this->mergeParam($class, $constrict); if ($_className === $class) { $object = $this->resolve($class, $definition, $config); } else { $object = $this->get($class, $definition, $config); } return $object; } /** * @param $class * @param $constrict * @param $config * * @return object * @throws NotFindClassException * @throws ReflectionException */ private function resolve($class, $constrict, $config): object { /** * @var ReflectionClass $reflect * @var array $dependencies */ list($reflect, $dependencies) = $this->resolveDependencies($class); foreach ($constrict as $index => $param) { $dependencies[$index] = $param; } if (!$reflect->isInstantiable()) { throw new NotFindClassException($reflect->getName()); } if (empty($config)) { return $reflect->newInstanceArgs($dependencies ?? []); } if (!empty($dependencies) && $reflect->implementsInterface('Snowflake\Abstracts\Configure')) { $dependencies[count($dependencies) - 1] = $config; return $reflect->newInstanceArgs($dependencies); } $this->_param[$class] = $config; $object = $reflect->newInstanceArgs($dependencies ?? []); foreach ($config as $key => $val) { $object->{$key} = $val; } if (method_exists($object, 'afterInit')) { call_user_func([$object, 'afterInit']); } return $object; } /** * @param $class * * @return array * @throws ReflectionException * @throws NotFindClassException */ private function resolveDependencies($class): array { $dependencies = []; if (!class_exists($class) || !($reflection = $this->resolveClass($class))) { return []; }; $constructs = $reflection->getConstructor(); if (!($constructs instanceof \ReflectionMethod)) { return [$reflection, []]; } foreach ($constructs->getParameters() as $key => $param) { $dependencies[] = $this->resolveDefaultValue($param, $class); } $this->_constructs[$class] = $dependencies; return [$reflection, $dependencies]; } /** * @param $param * @return mixed * @throws NotFindClassException * @throws ReflectionException */ private function resolveDefaultValue(\ReflectionParameter $param, $class): mixed { if ($param->isOptional()) { return $param->getDefaultValue(); } try { $type = $param->getType(); var_dump($type); return match ($type) { 'mixed' => $param->getDefaultValue(), 'string' => '', 'int', 'float' => 0, 'bool' => false, '', null, 'object' => NULL, default => Snowflake::createObject($type) }; } catch (\Throwable $throwable) { var_dump($class, $throwable->getMessage(), $throwable->getFile(), $throwable->getLine()); echo PHP_EOL; return null; } } /** * @param $class * @return ReflectionClass|null */ private function resolveClass($class): ?ReflectionClass { if (!isset($this->_reflection[$class])) { $reflection = new ReflectionClass($class); if (!$reflection->isInstantiable()) { return null; } $this->_reflection[$class] = $reflection; } return $this->_reflection[$class]; } /** * @param $class * @return mixed */ public function getDependencies($class): mixed { return $this->_constructs[$class] ?? []; } /** * @param $class * @return ReflectionClass|null * @throws ReflectionException * @throws NotFindClassException */ public function getReflect($class): ?ReflectionClass { if (!isset($this->_reflection[$class])) { $this->resolveDependencies($class); } return $this->_reflection[$class] ?? null; } /** * @param $class */ public function unset($class) { if (is_array($class) && isset($class['class'])) { $class = $class['class']; } else if (is_object($class)) { $class = get_class($class); } unset( $this->_reflection[$class], $this->_singletons[$class], $this->_param[$class], $this->_constructs[$class] ); } /** * @return $this */ public function flush(): static { $this->_reflection = []; $this->_singletons = []; $this->_param = []; $this->_constructs = []; return $this; } /** * @param $class * @param $newParam * * @return mixed */ private function mergeParam($class, $newParam): array { if (empty($this->_param[$class])) { return $newParam; } else if (empty($newParam)) { return $this->_param[$class]; } $old = $this->_param[$class]; foreach ($newParam as $key => $val) { $old[$key] = $val; } return $old; } }