diff --git a/application/Espo/Core/Loaders/ServiceFactory.php b/application/Espo/Core/Loaders/ServiceFactory.php index 9864f71620..d3a98152ac 100644 --- a/application/Espo/Core/Loaders/ServiceFactory.php +++ b/application/Espo/Core/Loaders/ServiceFactory.php @@ -34,7 +34,8 @@ class ServiceFactory extends Base public function load() { return new \Espo\Core\ServiceFactory( - $this->getContainer() + $this->getContainer()->get('classFinder'), + $this->getContainer()->get('injectableFactory') ); } } diff --git a/application/Espo/Core/ServiceFactory.php b/application/Espo/Core/ServiceFactory.php index 8db3a6bb60..caec0fce08 100644 --- a/application/Espo/Core/ServiceFactory.php +++ b/application/Espo/Core/ServiceFactory.php @@ -31,26 +31,27 @@ namespace Espo\Core; use Espo\Core\Exceptions\Error; +use Espo\Core\Utils\ClassFinder; +use Espo\Core\InjectableFactory; + class ServiceFactory { - private $container; + protected $classFinder; + protected $injectableFactory; - public function __construct(Container $container) + public function __construct(ClassFinder $classFinder, InjectableFactory $injectableFactory) { - $this->container = $container; + $this->classFinder = $classFinder; + $this->injectableFactory = $injectableFactory; } - protected function getContainer() + protected function getClassName(string $name) { - return $this->container; + return $this->classFinder->find('Services', $name, true); } - protected function getClassName($name) + public function checkExists(string $name) : bool { - return $this->getContainer()->get('classFinder')->find('Services', $name); - } - - public function checkExists($name) { $className = $this->getClassName($name); if (!$className) { return false; @@ -58,28 +59,19 @@ class ServiceFactory return true; } - public function create($name) + public function create(string $name) : object { $className = $this->getClassName($name); if (!$className) { throw new Error("Service '{$name}' was not found."); } - return $this->createByClassName($className); - } - protected function createByClassName($className) - { - if (class_exists($className)) { - $service = new $className(); - $dependencyList = $service->getDependencyList(); - foreach ($dependencyList as $name) { - $service->inject($name, $this->container->get($name)); - } - if (method_exists($service, 'prepare')) { - $service->prepare(); - } - return $service; + $obj = $this->injectableFactory->create($className); + + if (method_exists($obj, 'prepare')) { + $obj->prepare(); } - throw new Error("Class '$className' does not exist."); + + return $obj; } } diff --git a/application/Espo/Core/Utils/ClassFinder.php b/application/Espo/Core/Utils/ClassFinder.php index d761aa566b..51f355c573 100644 --- a/application/Espo/Core/Utils/ClassFinder.php +++ b/application/Espo/Core/Utils/ClassFinder.php @@ -49,9 +49,9 @@ class ClassFinder /** * Find class name by category (e.g. Controllers, Services) and name. */ - public function find(string $category, string $name) : ?string + public function find(string $category, string $name, bool $subDirs = false) : ?string { - $map = $this->getMap($category); + $map = $this->getMap($category, $subDirs); $className = $map[$name] ?? null; return $className; } @@ -59,19 +59,19 @@ class ClassFinder /** * Get [name => class-name] map. */ - public function getMap(string $category) : array + public function getMap(string $category, bool $subDirs = false) : array { if (!array_key_exists($category, $this->dataHash)) { - $this->load($category); + $this->load($category, $subDirs); } return $this->dataHash[$category] ?? []; } - protected function load(string $category) + protected function load(string $category, bool $subDirs = false) { $path = $this->buildPaths($category); $cacheFile = $this->buildCacheFilePath($category); - $this->dataHash[$category] = $this->classParser->getData($path, $cacheFile); + $this->dataHash[$category] = $this->classParser->getData($path, $cacheFile, null, $subDirs); } protected function buildPaths(string $category) : array diff --git a/application/Espo/Core/Utils/File/ClassParser.php b/application/Espo/Core/Utils/File/ClassParser.php index 3117f7bedc..1da103b7fb 100644 --- a/application/Espo/Core/Utils/File/ClassParser.php +++ b/application/Espo/Core/Utils/File/ClassParser.php @@ -77,7 +77,7 @@ class ClassParser * @param $cacheFile Full path for a cache file, ex. data/cache/application/entryPoints.php. * @param $allowedMethods If specified, classes w/o specified method will be ignored. */ - public function getData($paths, ?string $cacheFile = null, ?array $allowedMethods = null) : array + public function getData($paths, ?string $cacheFile = null, ?array $allowedMethods = null, bool $subDirs = false) : array { $data = null; @@ -96,18 +96,18 @@ class ClassParser } if (!is_array($data)) { - $data = $this->getClassNameHash($paths['corePath'], $allowedMethods); + $data = $this->getClassNameHash($paths['corePath'], $allowedMethods, $subDirs); if (isset($paths['modulePath'])) { foreach ($this->getMetadata()->getModuleList() as $moduleName) { $path = str_replace('{*}', $moduleName, $paths['modulePath']); - $data = array_merge($data, $this->getClassNameHash($path, $allowedMethods)); + $data = array_merge($data, $this->getClassNameHash($path, $allowedMethods, $subDirs)); } } if (isset($paths['customPath'])) { - $data = array_merge($data, $this->getClassNameHash($paths['customPath'], $allowedMethods)); + $data = array_merge($data, $this->getClassNameHash($paths['customPath'], $allowedMethods, $subDirs)); } if ($cacheFile && $this->getConfig()->get('useCache')) { @@ -121,7 +121,7 @@ class ClassParser return $data; } - protected function getClassNameHash($dirs, ?array $allowedMethods = []) + protected function getClassNameHash($dirs, ?array $allowedMethods = [], bool $subDirs = false) { if (is_string($dirs)) { $dirs = (array) $dirs; @@ -130,31 +130,44 @@ class ClassParser $data = []; foreach ($dirs as $dir) { if (file_exists($dir)) { - $fileList = $this->getFileManager()->getFileList($dir, false, '\.php$', true); + $fileList = $this->getFileManager()->getFileList($dir, $subDirs, '\.php$', true); - foreach ($fileList as $file) { - $filePath = Util::concatPath($dir, $file); - $className = Util::getClassName($filePath); - $fileName = $this->getFileManager()->getFileName($filePath); - - $scopeName = ucfirst($fileName); - $normalizedScopeName = Util::normilizeScopeName($scopeName); - - if (empty($allowedMethods)) { - $data[$normalizedScopeName] = $className; - continue; - } - - foreach ($allowedMethods as $methodName) { - if (method_exists($className, $methodName)) { - $data[$normalizedScopeName] = $className; - } - } - - } + $this->fillHashFromFileList($fileList, $dir, $allowedMethods, $data); } } return $data; } + + protected function fillHashFromFileList( + array $fileList, string $dir, ?array $allowedMethods, array &$data, string $category = '' + ) { + foreach ($fileList as $key => $file) { + if (is_string($key)) { + if (is_array($file)) { + $this->fillHashFromFileList($file, $dir . '/'. $key, $allowedMethods, $data, $category . $key . '\\'); + } + continue; + } + + $filePath = Util::concatPath($dir, $file); + $className = Util::getClassName($filePath); + $fileName = $this->getFileManager()->getFileName($filePath); + + $name = Util::normilizeScopeName(ucfirst($fileName)); + + $name = $category . $name; + + if (empty($allowedMethods)) { + $data[$name] = $className; + continue; + } + + foreach ($allowedMethods as $methodName) { + if (method_exists($className, $methodName)) { + $data[$name] = $className; + } + } + } + } }