Enhance Service locator

This commit is contained in:
Eric Espie
2026-01-27 11:54:05 +01:00
parent 390b5c0bc3
commit bfa7a209d6
43 changed files with 338 additions and 210 deletions

View File

@@ -17,19 +17,9 @@ use utils;
*/
class DataModelDependantCache
{
private static DataModelDependantCache $oInstance;
public static function GetInstance(): DataModelDependantCache
{
if (!isset(self::$oInstance)) {
self::$oInstance = new DataModelDependantCache();
}
return self::$oInstance;
}
private ?string $sStorageRootDir; // Nullable for test purposes
private function __construct()
public function __construct()
{
$this->sStorageRootDir = null;
}

View File

@@ -1,20 +0,0 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Service\DependencyInjection;
use IssueLog;
use Throwable;
class DIException extends \Exception
{
public function __construct(string $sMessage = '', int $iCode = 0, ?Throwable $oPrevious = null, array $aContext = [])
{
parent::__construct($sMessage, $iCode, $oPrevious);
IssueLog::Exception(get_class($this).' occurs: '.$sMessage, $this, null, $aContext);
}
}

View File

@@ -1,64 +0,0 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Service\DependencyInjection;
use Psr\Container\ContainerInterface;
class ServiceLocator implements ContainerInterface
{
private static ServiceLocator $oInstance;
private array $aServices = [];
protected function __construct()
{
}
final public static function GetInstance(): ServiceLocator
{
if (!isset(static::$oInstance)) {
static::$oInstance = new ServiceLocator();
}
return static::$oInstance;
}
/**
* Register a service by name
*
* @param string $sName Name of the service to register
* @param mixed $oService Service to register
*
* @return void
*/
final public function RegisterService(string $sName, mixed $oService): void
{
$this->aServices[$sName] = $oService;
}
/**
* Get a previously registered service
*
* @param string $id Service id to search for
*
* @return mixed The service or null when the service is not found and $bMustBeFound is false
* @throws \Combodo\iTop\Service\DependencyInjection\DIException
*/
public function get(string $id): mixed
{
if (!isset($this->aServices[$id])) {
throw new DIException("Service ".json_encode($id)." not found");
}
return $this->aServices[$id];
}
public function has(string $id): bool
{
return isset($this->aServices[$id]);
}
}

View File

@@ -30,7 +30,7 @@ class InterfaceDiscovery
private function __construct()
{
$this->oCacheService = DataModelDependantCache::GetInstance();
$this->oCacheService = MetaModel::GetService('DataModelDependantCache');
}
public static function GetInstance(): InterfaceDiscovery

View File

@@ -0,0 +1,15 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Service\ServiceLocator;
use Combodo\iTop\Service\ServiceLocator\ServiceLocatorException;
use Psr\Container\NotFoundExceptionInterface;
class NotFoundException extends ServiceLocatorException implements NotFoundExceptionInterface
{
}

View File

@@ -0,0 +1,92 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Service\ServiceLocator;
use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
/**
* @since 3.3.0
*/
class ServiceLocator implements ContainerInterface
{
private array $aServices;
public function __construct()
{
$this->aServices = [];
}
/**
* Register a service by name
*
* @param string $sName Name of the service to register
* @param mixed $oService Service to register
*
* @return void
*/
final protected function RegisterService(string $sName, mixed $oService): void
{
$this->aServices[$sName] = $oService;
}
/**
* Get a previously registered service
*
* @param string $id Service id to search for
*
* @return mixed The service object
* @throws \Combodo\iTop\Service\ServiceLocator\NotFoundException When the service is not configured
* @throws \Combodo\iTop\Service\ServiceLocator\ServiceLocatorException If error during service instanciation
*/
public function get(string $id): mixed
{
if (!isset($this->aServices[$id])) {
throw new NotFoundException("Service ".json_encode($id)." not found");
}
try {
if (is_string($this->aServices[$id])) {
$oService = new $this->aServices[$id]();
$this->aServices[$id] = $oService;
}
} catch (\Throwable $t) {
throw new ServiceLocatorException("Service ".json_encode($id)." not found", $t);
}
return $this->aServices[$id];
}
public function has(string $id): bool
{
return isset($this->aServices[$id]);
}
/**
* Init Service locator for a configuration file corresponding to the category
*
* @see conf/production/service-locator-runtime-config.php
*
* @param string|null $sRelativeConfigFileName config file name relative to APPROOT
*
* @return void
*/
final public function Init(string $sRelativeConfigFileName = null): void
{
if (is_null($sRelativeConfigFileName)) {
$sConfigFile = APPROOT."sources/Service/ServiceLocator/service-locator-runtime-config.php";
} else {
$sConfigFile = APPROOT.$sRelativeConfigFileName;
}
if (!file_exists($sConfigFile)) {
return;
}
$this->aServices = include($sConfigFile);
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Service\ServiceLocator;
use Exception;
use IssueLog;
use Psr\Container\ContainerExceptionInterface;
use Throwable;
class ServiceLocatorException extends Exception implements ContainerExceptionInterface
{
public function __construct(string $sMessage = '', ?Throwable $oPrevious = null, array $aContext = [])
{
parent::__construct($sMessage, 0, $oPrevious);
IssueLog::Exception(get_class($this).' occurs: '.$sMessage, $this, null, $aContext);
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Combodo\iTop\Application\Dashlet\Service\DashletService;
use Combodo\iTop\Forms\Block\FormBlockService;
use Combodo\iTop\PropertyType\PropertyTypeService;
use Combodo\iTop\Service\Cache\DataModelDependantCache;
return [
'ModelReflection' => ModelReflectionRuntime::class,
'DashletService' => DashletService::class,
'PropertyTypeService' => PropertyTypeService::class,
'DataModelDependantCache' => DataModelDependantCache::class,
'FormBlockService' => FormBlockService::class,
];