service container definition in metadata

This commit is contained in:
Yuri Kuznetsov
2019-12-04 12:30:33 +02:00
parent 4deb9d6d77
commit 9f21a722ec
7 changed files with 120 additions and 24 deletions
+10
View File
@@ -48,6 +48,7 @@ class Application
$GLOBALS['log'] = $this->getContainer()->get('log');
$this->initAutoloads();
$this->initPreloads();
}
protected function initContainer()
@@ -346,6 +347,15 @@ class Application
$autoload->register();
}
protected function initPreloads()
{
foreach ($this->getMetadata()->get(['app', 'containerServices']) ?? [] as $name => $defs) {
if ($defs['preload'] ?? false) {
$this->getContainer()->get($name);
}
}
}
public function setBasePath($basePath)
{
$this->getContainer()->get('clientManager')->setBasePath($basePath);
+33 -5
View File
@@ -61,9 +61,10 @@ class Container
$obj = $this->$loadMethod();
$this->data[$name] = $obj;
} else {
$metadata = $this->get('metadata');
try {
$className = $this->get('metadata')->get(['app', 'loaders', ucfirst($name)]);
$className = $metadata->get(['app', 'loaders', ucfirst($name)]);
} catch (\Exception $e) {}
if (!isset($className) || !class_exists($className)) {
@@ -73,19 +74,46 @@ class Container
}
}
$object = null;
if (class_exists($className)) {
$loadClass = new $className($this);
$this->data[$name] = $loadClass->load();
$loadClass = new $className($this);
$object = $loadClass->load();
$this->data[$name] = $object;
} else {
$className = $this->getServiceClassName($name);
if ($className && class_exists($className)) {
$dependencyList = $metadata->get(['app', 'containerServices', $name, 'dependencyList']) ?? [];
$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);
}
} else {
$object = $reflector->newInstanceArgs($dependencyObjectList);
}
$this->data[$name] = $object;
}
}
}
return null;
}
public function getServiceClassName(string $name, string $default)
public function getServiceClassName(string $name, ?string $default = null)
{
$metadata = $this->get('metadata');
$className = $metadata->get(['app', 'serviceContainer', 'classNames', $name], $default);
$className = $metadata->get(['app', 'containerServices', $name, 'className']) ??
$metadata->get(['app', 'serviceContainer', 'classNames', $name], $default);
return $className;
}
@@ -0,0 +1,58 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2019 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;
}
}
@@ -27,16 +27,10 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Loaders;
namespace Espo\Core\Interfaces;
class ClientManager extends Base
interface InjectableService
{
public function load()
{
return new \Espo\Core\Utils\ClientManager(
$this->getContainer()->get('config'),
$this->getContainer()->get('themeManager'),
$this->getContainer()->get('metadata')
);
}
public function inject(string $name, object $object);
}
+6 -9
View File
@@ -31,23 +31,20 @@ namespace Espo\Core\Portal;
class Container extends \Espo\Core\Container
{
public function getServiceClassName(string $name, string $default)
public function getServicePortalClassName(string $name, ?string $default = null)
{
$metadata = $this->get('metadata');
$className = $metadata->get(['app', 'serviceContainerPortal', 'classNames', $name], $default);
return $className;
return $metadata->get(['app', 'portalContainerServices', $name, 'className'], $default);
}
protected function getServiceMainClassName(string $name, string $default)
protected function getServiceMainClassName(string $name, ?string $default = null)
{
$metadata = $this->get('metadata');
$className = $metadata->get(['app', 'serviceContainer', 'classNames', $name], $default);
return $className;
return parent::getServiceClassName($name, $default);
}
protected function loadAclManager()
{
$className = $this->getServiceClassName('aclManager', '\\Espo\\Core\\Portal\\AclManager');
$className = $this->getServicePortalClassName('aclManager', '\\Espo\\Core\\Portal\\AclManager');
$mainClassName = $this->getServiceMainClassName('aclManager', '\\Espo\\Core\\AclManager');
$obj = new $className(
@@ -63,7 +60,7 @@ class Container extends \Espo\Core\Container
protected function loadAcl()
{
$className = $this->getServiceClassName('acl', '\\Espo\\Core\\Portal\\Acl');
$className = $this->getServicePortalClassName('acl', '\\Espo\\Core\\Portal\\Acl');
return new $className(
$this->get('aclManager'),
$this->get('user')
@@ -0,0 +1,6 @@
{
"clientManager": {
"className": "\\Espo\\Core\\Utils\\ClientManager",
"dependencyList": ["config", "themeManager", "metadata"]
}
}
@@ -2,6 +2,9 @@
"frontendHiddenPathList": [
["app", "metadata"],
["app", "loaders"],
["app", "containerServices"],
["app", "portalContainerServices"],
["app", "serviceContainer"],
["app", "consoleCommands"],
["app", "formula", "functionClassNameMap"],
["app", "fileStorage", "implementationClassNameMap"],