di improvements

This commit is contained in:
Yuri Kuznetsov
2020-06-18 20:24:26 +03:00
parent 74d18be94a
commit 74e4012fee
9 changed files with 115 additions and 140 deletions
@@ -29,29 +29,37 @@
namespace Espo\Core\AppParams;
class TemplateEntityTypeList extends \Espo\Core\Injectable
use Espo\Core\Acl;
use Espo\Core\SelectManagerFactory;
use Espo\ORM\EntityManager;
class TemplateEntityTypeList
{
protected function init()
protected $acl;
protected $selectManagerFactory;
protected $entityManager;
public function __construct(Acl $acl, SelectManagerFactory $selectManagerFactory, EntityManager $entityManager)
{
$this->addDependency('acl');
$this->addDependency('selectManagerFactory');
$this->addDependency('entityManager');
$this->acl = $acl;
$this->selectManagerFactory = $selectManagerFactory;
$this->entityManager = $entityManager;
}
public function get()
{
if (!$this->getInjection('acl')->checkScope('Template')) {
if (!$this->acl->checkScope('Template')) {
return [];
}
$list = [];
$selectManager = $this->getInjection('selectManagerFactory')->create('Template');
$selectManager = $this->selectManagerFactory->create('Template');
$selectParams = $selectManager->getEmptySelectParams();
$selectManager->applyAccess($selectParams);
$templateList = $this->getInjection('entityManager')->getRepository('Template')
$templateList = $this->entityManager->getRepository('Template')
->select(['entityType'])
->groupBy(['entityType'])
->find($selectParams);
+13 -13
View File
@@ -71,8 +71,10 @@ class Container
$metadata = $this->get('metadata');
try {
// deprecated
$className = $metadata->get(['app', 'containerServices', $name, 'loaderClassName']);
if (!$className) {
// deprecated
$className = $metadata->get(['app', 'loaders', ucfirst($name)]);
}
} catch (\Exception $e) {}
@@ -84,6 +86,7 @@ class Container
}
}
$object = null;
if (class_exists($className)) {
@@ -94,21 +97,18 @@ class Container
$className = $this->getServiceClassName($name);
if ($className && class_exists($className)) {
$dependencyList = $this->getServiceDependencyList($name);
$dependencyObjectList = [];
foreach ($dependencyList as $item) {
$dependencyObjectList[] = $this->get($item);
}
$reflector = new \ReflectionClass($className);
if ($reflector->isSubclassOf('\\Espo\\Core\\Interfaces\\InjectableService')) {
$object = $reflector->newInstance();
foreach ($dependencyObjectList as $i => $item) {
$object->inject($dependencyList[$i], $item);
if (!is_null($dependencyList)) {
$dependencyObjectList = [];
foreach ($dependencyList as $item) {
$dependencyObjectList[] = $this->get($item);
}
} else {
$reflector = new \ReflectionClass($className);
$object = $reflector->newInstanceArgs($dependencyObjectList);
} else {
$object = $this->get('injectableFactory')->create($className);
}
$this->data[$name] = $object;
}
}
@@ -117,9 +117,9 @@ class Container
return null;
}
protected function getServiceDependencyList(string $name) : array
protected function getServiceDependencyList(string $name) : ?array
{
return $this->get('metadata')->get(['app', 'containerServices', $name, 'dependencyList']) ?? [];
return $this->get('metadata')->get(['app', 'containerServices', $name, 'dependencyList']) ?? null;
}
protected function getServiceClassName(string $name, ?string $default = null)
+66 -19
View File
@@ -29,8 +29,12 @@
namespace Espo\Core;
use \Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Error;
/**
* Creates instance by class name. Uses either Injectable interface or constructor param names to detect
* which dependencies are needed. Only container services supported as dependencies.
*/
class InjectableFactory
{
private $container;
@@ -40,28 +44,71 @@ class InjectableFactory
$this->container = $container;
}
public function createByClassName($className)
public function create(string $className) : object
{
if (class_exists($className)) {
$service = new $className();
if (!($service instanceof \Espo\Core\Interfaces\Injectable)) {
throw new Error("Class '$className' is not instance of Injectable interface");
}
$dependencyList = $service->getDependencyList();
foreach ($dependencyList as $name) {
$service->inject($name, $this->container->get($name));
}
if (method_exists($service, 'prepare')) {
$service->prepare();
}
return $service;
}
throw new Error("Class '$className' does not exist");
return $this->createByClassName($className);
}
protected function getMetadata()
public function createByClassName(string $className) : object
{
return $this->getContainer()->get('metadata');
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()
@@ -1,58 +0,0 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core;
abstract class InjectableService implements \Espo\Core\Interfaces\InjectableService
{
protected $injections = [];
public function inject(string $name, object $object)
{
$this->injections[$name] = $object;
}
public function __call($methodName, $args)
{
if (strpos($methodName, 'get') === 0) {
$injectionName = lcfirst(substr($methodName, 3));
if (isset($this->injections[$injectionName])) {
return $this->getInjection($injectionName);
}
}
throw new \BadMethodCallException('Method ' . $methodName . ' does not exist');
}
protected function getInjection(string $name) : object
{
$object = $this->injections[$name] ?? null;
if (!$object) throw new \Exception("Injection {$name} is not set.");
return $object;
}
}
@@ -1,36 +0,0 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Interfaces;
interface InjectableService
{
public function inject(string $name, object $object);
}
@@ -34,7 +34,8 @@ class NotificatorFactory extends Base
public function load()
{
return new \Espo\Core\NotificatorFactory(
$this->getContainer()
$this->getContainer()->get('injectableFactory'),
$this->getContainer()->get('classFinder')
);
}
}
+14 -4
View File
@@ -29,23 +29,33 @@
namespace Espo\Core;
use Espo\Core\Utils\Util;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\ClassFinder;
use Espo\Core\Notificators\Base as BaseNotificator;
class NotificatorFactory extends InjectableFactory
class NotificatorFactory
{
protected $baseClassName = '\\Espo\\Core\\Notificators\\Base';
protected $injectableFactory;
protected $classFinder;
public function __construct(InjectableFactory $injectableFactory, ClassFinder $classFinder)
{
$this->injectableFactory = $injectableFactory;
$this->classFinder = $classFinder;
}
public function create(string $entityType) : BaseNotificator
{
$className = $this->getContainer()->get('classFinder')->find('Notificators', $entityType);
$className = $this->classFinder->find('Notificators', $entityType);
if (!$className || !class_exists($className)) {
$className = $this->baseClassName;
}
$obj = $this->createByClassName($className);
$obj = $this->injectableFactory->create($className);
$obj->setEntityType($entityType);
return $obj;
+1 -1
View File
@@ -43,7 +43,7 @@ class Container extends \Espo\Core\Container
return $metadata->get(['app', 'portalContainerServices', $name, 'className'], $default);
}
protected function getServiceDependencyList(string $name) : array
protected function getServiceDependencyList(string $name) : ?array
{
return $this->get('metadata')->get(['app', 'portalContainerServices', $name, 'dependencyList']) ??
parent::getServiceDependencyList($name);
@@ -1,4 +1,7 @@
{
"notificatorFactory": {
"className": "\\Espo\\Core\\NotificatorFactory"
},
"clientManager": {
"className": "\\Espo\\Core\\Utils\\ClientManager",
"dependencyList": ["config", "themeManager", "metadata"]