diff --git a/application/dashboardlayout.class.inc.php b/application/dashboardlayout.class.inc.php index 4ce55e230..61ae3e373 100644 --- a/application/dashboardlayout.class.inc.php +++ b/application/dashboardlayout.class.inc.php @@ -109,6 +109,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout */ public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = []) { + /** @var DashletService $oDashletService */ + $oDashletService = MetaModel::GetService('DashletService'); // Trim the list of cells to remove the invisible/empty ones at the end of the array $aCells = $this->TrimCellsArray($aCells); @@ -147,7 +149,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout $sDashletId = $oDashlet->GetID(); $sDashletClass = $oDashlet->GetDashletType(); $aDashletDenormalizedProperties = $oDashlet->GetModelData(); - $aDashletsInfo = DashletService::GetInstance()->GetDashletDefinition($sDashletClass); + $aDashletsInfo = $oDashletService->GetDashletDefinition($sDashletClass); // GRID LAYOUT: Set position relative to grid $iPositionX = $iGridCurrentX + $iGridCurrentColX; diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 318fe3775..218307c6e 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -22,6 +22,7 @@ use Combodo\iTop\Application\EventRegister\ApplicationEvents; use Combodo\iTop\Core\MetaModel\FriendlyNameType; use Combodo\iTop\Service\Events\EventData; use Combodo\iTop\Service\Events\EventService; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; require_once APPROOT.'core/modulehandler.class.inc.php'; require_once APPROOT.'core/querymodifier.class.inc.php'; @@ -142,6 +143,8 @@ abstract class MetaModel */ protected static array $m_aReentranceProtection = []; + private static ServiceLocator $oServiceLocator; + /** * MetaModel constructor. */ @@ -7026,6 +7029,44 @@ abstract class MetaModel } } } + + /** + * (Re)Init the global service locator with a configuration file + * + * @param string|null $sRelativeConfigFileName default to the runtime config file + * + * @return void + */ + public static function InitServiceLocator(string $sRelativeConfigFileName = null): void + { + if (!isset(self::$oServiceLocator)) { + self::$oServiceLocator = new ServiceLocator(); + } + + // Read the runtime service locator configuration + self::$oServiceLocator->Init($sRelativeConfigFileName); + } + + /** + * Get configured service + * + * @see conf/production/ServiceLocatorRuntimeConfig.php + * + * Example: $oModelReflection = \MetaModel::GetService('ModelReflexion'); + * + * @param string $sServiceName + * + * @return mixed + * @throws \Combodo\iTop\Service\ServiceLocator\ServiceLocatorException + */ + public static function GetService(string $sServiceName): mixed + { + if (!isset(self::$oServiceLocator)) { + // Read the runtime service locator configuration + self::InitServiceLocator(); + } + return self::$oServiceLocator->get($sServiceName); + } } // Standard attribute lists diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index ad2a9f1e1..e8f743513 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -639,8 +639,6 @@ return array( 'Combodo\\iTop\\Service\\Base\\ObjectRepository' => $baseDir . '/sources/Service/Base/ObjectRepository.php', 'Combodo\\iTop\\Service\\Base\\iDataPostProcessor' => $baseDir . '/sources/Service/Base/iDataPostProcessor.php', 'Combodo\\iTop\\Service\\Cache\\DataModelDependantCache' => $baseDir . '/sources/Service/Cache/DataModelDependantCache.php', - 'Combodo\\iTop\\Service\\DependencyInjection\\DIException' => $baseDir . '/sources/Service/DependencyInjection/DIException.php', - 'Combodo\\iTop\\Service\\DependencyInjection\\ServiceLocator' => $baseDir . '/sources/Service/DependencyInjection/ServiceLocator.php', 'Combodo\\iTop\\Service\\Events\\Description\\EventDataDescription' => $baseDir . '/sources/Service/Events/Description/EventDataDescription.php', 'Combodo\\iTop\\Service\\Events\\Description\\EventDescription' => $baseDir . '/sources/Service/Events/Description/EventDescription.php', 'Combodo\\iTop\\Service\\Events\\EventData' => $baseDir . '/sources/Service/Events/EventData.php', @@ -663,6 +661,8 @@ return array( 'Combodo\\iTop\\Service\\Router\\Exception\\RouteNotFoundException' => $baseDir . '/sources/Service/Router/Exception/RouteNotFoundException.php', 'Combodo\\iTop\\Service\\Router\\Exception\\RouterException' => $baseDir . '/sources/Service/Router/Exception/RouterException.php', 'Combodo\\iTop\\Service\\Router\\Router' => $baseDir . '/sources/Service/Router/Router.php', + 'Combodo\\iTop\\Service\\ServiceLocator\\ServiceLocator' => $baseDir . '/sources/Service/ServiceLocator/ServiceLocator.php', + 'Combodo\\iTop\\Service\\ServiceLocator\\ServiceLocatorException' => $baseDir . '/sources/Service/ServiceLocator/ServiceLocatorException.php', 'Combodo\\iTop\\Service\\SummaryCard\\SummaryCardService' => $baseDir . '/sources/Service/SummaryCard/SummaryCardService.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectConfig' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectConfig.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectGC' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectGC.php', @@ -3960,5 +3960,5 @@ return array( 'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php', 'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php', 'utils' => $baseDir . '/application/utils.inc.php', - '�' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', + '©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', ); diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 36b31b394..506c3aa9f 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -1025,8 +1025,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Service\\Base\\ObjectRepository' => __DIR__ . '/../..' . '/sources/Service/Base/ObjectRepository.php', 'Combodo\\iTop\\Service\\Base\\iDataPostProcessor' => __DIR__ . '/../..' . '/sources/Service/Base/iDataPostProcessor.php', 'Combodo\\iTop\\Service\\Cache\\DataModelDependantCache' => __DIR__ . '/../..' . '/sources/Service/Cache/DataModelDependantCache.php', - 'Combodo\\iTop\\Service\\DependencyInjection\\DIException' => __DIR__ . '/../..' . '/sources/Service/DependencyInjection/DIException.php', - 'Combodo\\iTop\\Service\\DependencyInjection\\ServiceLocator' => __DIR__ . '/../..' . '/sources/Service/DependencyInjection/ServiceLocator.php', 'Combodo\\iTop\\Service\\Events\\Description\\EventDataDescription' => __DIR__ . '/../..' . '/sources/Service/Events/Description/EventDataDescription.php', 'Combodo\\iTop\\Service\\Events\\Description\\EventDescription' => __DIR__ . '/../..' . '/sources/Service/Events/Description/EventDescription.php', 'Combodo\\iTop\\Service\\Events\\EventData' => __DIR__ . '/../..' . '/sources/Service/Events/EventData.php', @@ -1049,6 +1047,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Service\\Router\\Exception\\RouteNotFoundException' => __DIR__ . '/../..' . '/sources/Service/Router/Exception/RouteNotFoundException.php', 'Combodo\\iTop\\Service\\Router\\Exception\\RouterException' => __DIR__ . '/../..' . '/sources/Service/Router/Exception/RouterException.php', 'Combodo\\iTop\\Service\\Router\\Router' => __DIR__ . '/../..' . '/sources/Service/Router/Router.php', + 'Combodo\\iTop\\Service\\ServiceLocator\\ServiceLocator' => __DIR__ . '/../..' . '/sources/Service/ServiceLocator/ServiceLocator.php', + 'Combodo\\iTop\\Service\\ServiceLocator\\ServiceLocatorException' => __DIR__ . '/../..' . '/sources/Service/ServiceLocator/ServiceLocatorException.php', 'Combodo\\iTop\\Service\\SummaryCard\\SummaryCardService' => __DIR__ . '/../..' . '/sources/Service/SummaryCard/SummaryCardService.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectConfig' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectConfig.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectGC' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectGC.php', @@ -4346,7 +4346,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', 'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', 'utils' => __DIR__ . '/../..' . '/application/utils.inc.php', - '�' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', + '©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/sources/Application/Dashboard/Controller/DashboardController.php b/sources/Application/Dashboard/Controller/DashboardController.php index 997335551..c74d4ece4 100644 --- a/sources/Application/Dashboard/Controller/DashboardController.php +++ b/sources/Application/Dashboard/Controller/DashboardController.php @@ -20,13 +20,14 @@ use Combodo\iTop\Application\WebPage\DownloadPage; use Combodo\iTop\Application\WebPage\JsonPage; use Combodo\iTop\Forms\Block\FormBlockService; use Combodo\iTop\PropertyType\Serializer\XMLSerializer; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use DBObjectSearch; use DBObjectSet; use Dict; use DOMException; use Exception; use IssueLog; +use MetaModel; use ModelReflectionRuntime; use RuntimeDashboard; use SecurityException; @@ -37,6 +38,14 @@ class DashboardController extends Controller { public const ROUTE_NAMESPACE = 'dashboard'; + private FormBlockService $oFormBlockService; + + public function __construct($sViewPath = '', $sModuleName = 'core', $aAdditionalPaths = [], array $aThemes = ['application/forms/itop_console_layout.html.twig', 'application/forms/wip_form_demonstrator.html.twig']) + { + parent::__construct($sViewPath, $sModuleName, $aAdditionalPaths, $aThemes); + $this->oFormBlockService = MetaModel::GetService('FormBlockService'); + } + public function OperationGetDashlet() { // TODO 3.3 Do we want to use a readparam here or SF internal mechanism ? @@ -54,8 +63,6 @@ class DashboardController extends Controller $oDashlet = DashletFactory::GetInstance()->CreateDashlet($sDashletClass, $sDashletId); - // TODO 3.3 This is not the place to register this service, do better please - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); if (!empty($aValues)) { $oDashlet->FromModelData($aValues); } else { @@ -103,7 +110,7 @@ class DashboardController extends Controller try { // Get the form block from the service (and the compiler) $oRequest = $this->getRequest(); - $oFormBlock = FormBlockService::GetInstance()->GetFormBlockById('DashboardGrid', 'Dashboard'); + $oFormBlock = $this->oFormBlockService->GetFormBlockById('DashboardGrid', 'Dashboard'); $oBuilder = $this->GetFormBuilder($oFormBlock, $aViewData); $oForm = $oBuilder->getForm(); $oForm->handleRequest($oRequest); @@ -127,8 +134,7 @@ class DashboardController extends Controller $aFormErrors = $oForm->getErrors(true, true); $sMessage = $aFormErrors->__toString(); } - } - catch (Exception $e) { + } catch (Exception $e) { IssueLog::Exception($e->getMessage(), $e); $sStatus = 'error'; $sMessage = $e->getMessage(); @@ -205,11 +211,9 @@ class DashboardController extends Controller $oDoc = utils::ReadPostedDocument('dashboard_upload_file'); $oDashboard->FromXml($oDoc->GetData()); $oDashboard->PersistDashboard($oDoc->GetData()); - } - catch (DOMException $e) { + } catch (DOMException $e) { $aResult = ['error' => Dict::S('UI:Error:InvalidDashboardFile')]; - } - catch (Exception $e) { + } catch (Exception $e) { $aResult = ['error' => $e->getMessage()]; } } else { diff --git a/sources/Application/Dashboard/Dashboard.php b/sources/Application/Dashboard/Dashboard.php index a27b19b90..7342068c1 100644 --- a/sources/Application/Dashboard/Dashboard.php +++ b/sources/Application/Dashboard/Dashboard.php @@ -664,7 +664,9 @@ JS */ protected function GetAvailableDashlets(): array { - return DashletService::GetInstance()->GetAvailableDashlets(); + /** @var DashletService $oDashletService */ + $oDashletService = MetaModel::GetService('DashletService'); + return $oDashletService->GetAvailableDashlets(); } /** diff --git a/sources/Application/Dashboard/FormBlock/DashletFormBlock.php b/sources/Application/Dashboard/FormBlock/DashletFormBlock.php index 832b58ceb..c30b8cddb 100644 --- a/sources/Application/Dashboard/FormBlock/DashletFormBlock.php +++ b/sources/Application/Dashboard/FormBlock/DashletFormBlock.php @@ -6,13 +6,22 @@ use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock; use Combodo\iTop\Forms\Block\Base\FormBlock; use Combodo\iTop\Forms\Block\Base\IntegerFormBlock; use Combodo\iTop\PropertyType\PropertyTypeService; +use MetaModel; class DashletFormBlock extends FormBlock { + private PropertyTypeService $oPropertyTypeService; + + public function __construct(string $sName, array $aOptions = []) + { + parent::__construct($sName, $aOptions); + $this->oPropertyTypeService = MetaModel::GetService('PropertyTypeService'); + } + protected function BuildForm(): void { // type - $aPropertyTypes = PropertyTypeService::GetInstance()->ListPropertyTypesByType('Dashlet'); + $aPropertyTypes = $this->oPropertyTypeService->ListPropertyTypesByType('Dashlet'); $this->Add('class', ChoiceFormBlock::class, [ 'label' => 'Class', 'choices' => array_combine($aPropertyTypes, $aPropertyTypes), diff --git a/sources/Application/Dashboard/FormBlock/DashletPropertiesFormBlock.php b/sources/Application/Dashboard/FormBlock/DashletPropertiesFormBlock.php index 106742a53..b2038d9ec 100644 --- a/sources/Application/Dashboard/FormBlock/DashletPropertiesFormBlock.php +++ b/sources/Application/Dashboard/FormBlock/DashletPropertiesFormBlock.php @@ -6,11 +6,19 @@ use Combodo\iTop\Forms\Block\Base\FormBlock; use Combodo\iTop\Forms\IO\Format\StringIOFormat; use Combodo\iTop\Forms\Register\IORegister; use Combodo\iTop\PropertyType\PropertyTypeService; +use MetaModel; class DashletPropertiesFormBlock extends FormBlock { // inputs public const INPUT_DASHLET_TYPE = 'dashlet_type'; + private PropertyTypeService $oPropertyTypeService; + + public function __construct(string $sName, array $aOptions = []) + { + parent::__construct($sName, $aOptions); + $this->oPropertyTypeService = MetaModel::GetService('PropertyTypeService'); + } protected function RegisterIO(IORegister $oIORegister): void { @@ -21,7 +29,7 @@ class DashletPropertiesFormBlock extends FormBlock public function GetFormType(): string { $sDashletType = strval($this->GetInputValue(self::INPUT_DASHLET_TYPE)); - $oDashlet = PropertyTypeService::GetInstance()->GetFormBlockById($sDashletType, 'Dashlet'); + $oDashlet = $this->oPropertyTypeService->GetFormBlockById($sDashletType, 'Dashlet'); return $oDashlet->GetFormType(); } @@ -29,7 +37,7 @@ class DashletPropertiesFormBlock extends FormBlock public function GetOptions(): array { $sDashletType = strval($this->GetInputValue(self::INPUT_DASHLET_TYPE)); - $oDashlet = PropertyTypeService::GetInstance()->GetFormBlockById($sDashletType, 'Dashlet'); + $oDashlet = $this->oPropertyTypeService->GetFormBlockById($sDashletType, 'Dashlet'); return $oDashlet->GetOptions(); } diff --git a/sources/Application/Dashboard/Layout/DashboardLayoutGrid.php b/sources/Application/Dashboard/Layout/DashboardLayoutGrid.php index 00e34b768..2be9bdbdf 100644 --- a/sources/Application/Dashboard/Layout/DashboardLayoutGrid.php +++ b/sources/Application/Dashboard/Layout/DashboardLayoutGrid.php @@ -10,11 +10,14 @@ namespace Combodo\iTop\Application\Dashboard\Layout; use Combodo\iTop\Application\Dashlet\Service\DashletService; use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardGrid; use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock; +use MetaModel; class DashboardLayoutGrid extends \DashboardLayout { public function Render($oPage, $aDashlets, $bEditMode = false, array $aExtraParams = []) { + /** @var DashletService $oDashletService */ + $oDashletService = MetaModel::GetService('DashletService'); $oDashboardLayout = new DashboardLayoutUIBlock($aExtraParams['dashboard_div_id']); $oDashboardGrid = new DashboardGrid(); @@ -29,7 +32,7 @@ class DashboardLayoutGrid extends \DashboardLayout $sDashletId = $oDashlet->GetID(); $sDashletClass = $oDashlet->GetDashletType(); $aDashletDenormalizedProperties = $oDashlet->GetModelData(); - $aDashletsInfo = DashletService::GetInstance()->GetDashletDefinition($sDashletClass); + $aDashletsInfo = $oDashletService->GetDashletDefinition($sDashletClass); // Also set minimal height/width $iPositionX = $aPosDashlet['position_x'] ?? 0; diff --git a/sources/Application/Dashboard/RuntimeDashboard.php b/sources/Application/Dashboard/RuntimeDashboard.php index 0a811dea5..d14aea1e6 100644 --- a/sources/Application/Dashboard/RuntimeDashboard.php +++ b/sources/Application/Dashboard/RuntimeDashboard.php @@ -13,7 +13,7 @@ use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu; use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock; use Combodo\iTop\Application\WebPage\iTopWebPage; use Combodo\iTop\Application\WebPage\WebPage; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; /** * Class RuntimeDashboard @@ -35,7 +35,6 @@ class RuntimeDashboard extends Dashboard parent::__construct($sId); $this->oMetaModel = new ModelReflectionRuntime(); $this->oDashletFactory->SetModelReflectionRuntime($this->oMetaModel); - ServiceLocator::GetInstance()->RegisterService('ModelReflection', $this->oMetaModel); $this->bCustomized = false; } @@ -686,6 +685,8 @@ JS */ public static function GetDashletCreationForm($sOQL = null) { + /** @var DashletService $oDashletService */ + $oDashletService = MetaModel::GetService('DashletService'); $oAppContext = new ApplicationContext(); $sContextMenuId = $oAppContext->GetCurrentValue('menu', null); @@ -743,7 +744,7 @@ JS // Get the list of possible dashlets that support a creation from // an OQL - $aDashlets = DashletService::GetInstance()->GetAvailableDashlets('can_create_by_oql'); + $aDashlets = $oDashletService->GetAvailableDashlets('can_create_by_oql'); $oSelectorField = new DesignerFormSelectorField('dashlet_class', Dict::S('UI:DashletCreation:DashletType'), ''); $oForm->AddField($oSelectorField); diff --git a/sources/Application/Dashlet/Dashlet.php b/sources/Application/Dashlet/Dashlet.php index a66194fca..bb674f13c 100644 --- a/sources/Application/Dashlet/Dashlet.php +++ b/sources/Application/Dashlet/Dashlet.php @@ -13,7 +13,6 @@ use Combodo\iTop\Application\UI\Base\UIBlock; use Combodo\iTop\Application\WebPage\WebPage; use Combodo\iTop\DesignDocument; use Combodo\iTop\DesignElement; -use Combodo\iTop\PropertyType\Serializer\XMLNormalizer; use DesignerForm; use DesignerHiddenField; use Dict; diff --git a/sources/Application/Dashlet/DashletFactory.php b/sources/Application/Dashlet/DashletFactory.php index e53ad8d4d..247fea1c9 100644 --- a/sources/Application/Dashlet/DashletFactory.php +++ b/sources/Application/Dashlet/DashletFactory.php @@ -8,6 +8,7 @@ namespace Combodo\iTop\Application\Dashlet; use Combodo\iTop\Application\Dashlet\Service\DashletService; +use MetaModel; use ModelReflectionRuntime; class DashletFactory @@ -36,7 +37,9 @@ class DashletFactory public function CreateDashlet(string $sClass, string $sId): Dashlet { - if (!DashletService::GetInstance()->IsDashletAvailable($sClass)) { + /** @var DashletService $oDashletService */ + $oDashletService = MetaModel::GetService('DashletService'); + if (!$oDashletService->IsDashletAvailable($sClass)) { $sClass = 'DashletUnknown'; //throw new DashletException("Dashlet ".json_encode($sClass)." is not available"); } diff --git a/sources/Application/Dashlet/Service/DashletService.php b/sources/Application/Dashlet/Service/DashletService.php index 9f982c1a7..cb2504854 100644 --- a/sources/Application/Dashlet/Service/DashletService.php +++ b/sources/Application/Dashlet/Service/DashletService.php @@ -15,23 +15,15 @@ use utils; class DashletService { - private static DashletService $oInstance; private array $aDashlets = []; - protected function __construct() + public function __construct() { } - final public static function GetInstance(): DashletService - { - if (!isset(static::$oInstance)) { - static::$oInstance = new DashletService(); - } - - return static::$oInstance; - } - /** + * @param string $sCategory + * * @return array * @throws \Combodo\iTop\Application\Dashlet\DashletException * @throws \DOMFormatException @@ -109,7 +101,7 @@ class DashletService * @throws \Combodo\iTop\Application\Dashlet\DashletException * @throws \DOMFormatException */ - public function IsDashletAvailable(string $sClass) + public function IsDashletAvailable(string $sClass): bool { $this->InitDashletDefinitions(); @@ -121,6 +113,7 @@ class DashletService * * @return array * @throws \Combodo\iTop\Application\Dashlet\DashletException + * @throws \DOMFormatException */ public function GetDashletDefinition(string $sClass): array { diff --git a/sources/Application/UI/Base/Component/TurboForm/TurboFormUIBlockFactory.php b/sources/Application/UI/Base/Component/TurboForm/TurboFormUIBlockFactory.php index 592e71811..6621f3a3d 100644 --- a/sources/Application/UI/Base/Component/TurboForm/TurboFormUIBlockFactory.php +++ b/sources/Application/UI/Base/Component/TurboForm/TurboFormUIBlockFactory.php @@ -10,6 +10,7 @@ namespace Combodo\iTop\Application\UI\Base\Component\TurboForm; use Combodo\iTop\Application\UI\Base\AbstractUIBlockFactory; use Combodo\iTop\Forms\Block\FormBlockService; use Combodo\iTop\Forms\Controller\FormsController; +use MetaModel; use Symfony\Component\Form\FormView; use utils; @@ -59,7 +60,8 @@ class TurboFormUIBlockFactory extends AbstractUIBlockFactory */ public static function MakeForDashletConfiguration(string $sDashletClass, array $aData = [], string $sId = null): TurboForm { - $oBlockForm = FormBlockService::GetInstance()->GetFormBlockById($sDashletClass, 'Dashlet'); + $oFormBlockService = MetaModel::GetService('FormBlockService'); + $oBlockForm = $oFormBlockService->GetFormBlockById($sDashletClass, 'Dashlet'); $oController = new FormsController(); $oBuilder = $oController->GetFormBuilder($oBlockForm, $aData); $oForm = $oBuilder->getForm(); diff --git a/sources/Application/UI/Base/Layout/DashletPanel/DashletPanelFactory.php b/sources/Application/UI/Base/Layout/DashletPanel/DashletPanelFactory.php index 0bf22e7fc..2aa31ff33 100644 --- a/sources/Application/UI/Base/Layout/DashletPanel/DashletPanelFactory.php +++ b/sources/Application/UI/Base/Layout/DashletPanel/DashletPanelFactory.php @@ -3,14 +3,17 @@ namespace Combodo\iTop\Application\UI\Base\Layout\DashletPanel; use Combodo\iTop\Application\Dashlet\Service\DashletService; +use MetaModel; class DashletPanelFactory { public static function MakeForDashboardEditor(string $sId = null): DashletPanel { + /** @var DashletService $oDashletService */ + $oDashletService = MetaModel::GetService('DashletService'); $oDashletPanel = new DashletPanel($sId); - $aAvailableDashlets = DashletService::GetInstance()->GetAvailableDashlets('can_be_created'); + $aAvailableDashlets = $oDashletService->GetAvailableDashlets('can_be_created'); foreach ($aAvailableDashlets as $sDashletClass => $aDashletInformation) { $oDashletEntry = new DashletEntry($sDashletClass, $aDashletInformation['label'], $aDashletInformation['description'], $aDashletInformation['icon']); diff --git a/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php b/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php index cbc4abf44..e96f3bc35 100644 --- a/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php +++ b/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php @@ -15,8 +15,8 @@ use Combodo\iTop\Forms\IO\Format\ClassIOFormat; use Combodo\iTop\Forms\Register\IORegister; use Combodo\iTop\Forms\Register\OptionsRegister; use Combodo\iTop\Forms\Register\RegisterException; -use Combodo\iTop\Service\DependencyInjection\DIException; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocatorException; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use utils; /** @@ -61,7 +61,7 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock /** * @inheritdoc * - * @throws DIException + * @throws ServiceLocationException * @throws FormBlockException * @throws RegisterException */ @@ -89,11 +89,12 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock * @param string|null $sCategory * * @return array - * @throws \Combodo\iTop\Service\DependencyInjection\DIException + * @throws \Combodo\iTop\Service\ServiceLocator\ServiceLocatorException */ public static function ListAttributeCodesByCategory(string $sClass, string $sCategory = ''): array { - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + /** @var \ModelReflection $oModelReflection */ + $oModelReflection = \MetaModel::GetService('ModelReflection'); $aNonGroupableAttributes = [ 'AttributeLinkedSet', 'AttributeFriendlyName', diff --git a/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php b/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php index 78d4ba59c..bbb9228e1 100644 --- a/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php +++ b/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php @@ -13,7 +13,7 @@ use Combodo\iTop\Forms\IO\Format\AttributeIOFormat; use Combodo\iTop\Forms\IO\Format\ClassIOFormat; use Combodo\iTop\Forms\Register\IORegister; use Combodo\iTop\Forms\Register\OptionsRegister; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use Exception; /** @@ -58,7 +58,7 @@ class AttributeValueChoiceFormBlock extends ChoiceFormBlock try { /** @var \ModelReflection $oModelReflection */ - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + $oModelReflection = \MetaModel::GetService('ModelReflection'); $aValues = $oModelReflection->GetAllowedValues_att($sClass, $sAttCode); $oOptionsRegister->SetOption('choices', array_flip($aValues ?? [])); diff --git a/sources/Forms/Block/DataModel/Dashlet/AggregateFunctionFormBlock.php b/sources/Forms/Block/DataModel/Dashlet/AggregateFunctionFormBlock.php index 080cbce00..9f19a9f93 100644 --- a/sources/Forms/Block/DataModel/Dashlet/AggregateFunctionFormBlock.php +++ b/sources/Forms/Block/DataModel/Dashlet/AggregateFunctionFormBlock.php @@ -36,7 +36,6 @@ class AggregateFunctionFormBlock extends ChoiceFormBlock * * @throws \Combodo\iTop\Forms\Block\FormBlockException * @throws \Combodo\iTop\Forms\Register\RegisterException - * @throws \Combodo\iTop\Service\DependencyInjection\DIException */ public function UpdateOptions(OptionsRegister $oOptionsRegister): void { diff --git a/sources/Forms/Block/DataModel/Dashlet/ClassAttributeGroupByFormBlock.php b/sources/Forms/Block/DataModel/Dashlet/ClassAttributeGroupByFormBlock.php index 9b606b567..9cb8837a0 100644 --- a/sources/Forms/Block/DataModel/Dashlet/ClassAttributeGroupByFormBlock.php +++ b/sources/Forms/Block/DataModel/Dashlet/ClassAttributeGroupByFormBlock.php @@ -10,7 +10,7 @@ namespace Combodo\iTop\Forms\Block\DataModel\Dashlet; use Combodo\iTop\Forms\Block\DataModel\AttributeChoiceFormBlock; use Combodo\iTop\Forms\Block\FormBlockException; use Combodo\iTop\Forms\Register\OptionsRegister; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use Dict; use Exception; @@ -27,12 +27,13 @@ class ClassAttributeGroupByFormBlock extends AttributeChoiceFormBlock * * @throws \Combodo\iTop\Forms\Block\FormBlockException * @throws \Combodo\iTop\Forms\Register\RegisterException - * @throws \Combodo\iTop\Service\DependencyInjection\DIException + * @throws \Combodo\iTop\Service\ServiceLocator\ServiceLocatorException */ public function UpdateOptions(OptionsRegister $oOptionsRegister): void { parent::UpdateOptions($oOptionsRegister); - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + /** @var \ModelReflection $oModelReflection */ + $oModelReflection = \MetaModel::GetService('ModelReflection'); $aGroupBy = []; try { diff --git a/sources/Forms/Block/FormBlockService.php b/sources/Forms/Block/FormBlockService.php index 0e7430b7b..4dd74ed68 100644 --- a/sources/Forms/Block/FormBlockService.php +++ b/sources/Forms/Block/FormBlockService.php @@ -11,27 +11,18 @@ use Combodo\iTop\Forms\Block\Base\FormBlock; use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompiler; use Combodo\iTop\PropertyType\PropertyTypeService; use Combodo\iTop\Service\Cache\DataModelDependantCache; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use ModelReflection; use ModelReflectionRuntime; use utils; class FormBlockService { - private static FormBlockService $oInstance; + private PropertyTypeService $oPropertyTypeService; - protected function __construct(ModelReflection $oModelReflection = null) + public function __construct(ModelReflection $oModelReflection = null) { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', $oModelReflection ?? new ModelReflectionRuntime()); - } - - final public static function GetInstance(ModelReflection $oModelReflection = null): FormBlockService - { - if (!isset(static::$oInstance)) { - static::$oInstance = new FormBlockService($oModelReflection); - } - - return static::$oInstance; + $this->oPropertyTypeService = \MetaModel::GetService('PropertyTypeService'); } /** @@ -46,7 +37,7 @@ class FormBlockService */ public function GetFormBlockById(string $sId, string $sType): FormBlock { - return PropertyTypeService::GetInstance()->GetFormBlockById($sId, $sType); + return $this->oPropertyTypeService->GetFormBlockById($sId, $sType); } } diff --git a/sources/Forms/Controller/FormsController.php b/sources/Forms/Controller/FormsController.php index d8959cda3..34edf085f 100644 --- a/sources/Forms/Controller/FormsController.php +++ b/sources/Forms/Controller/FormsController.php @@ -12,15 +12,19 @@ use Combodo\iTop\Forms\Block\FormBlockService; use Combodo\iTop\ItopSdkFormDemonstrator\Helper\ItopSdkFormDemonstratorLog; use Exception; use IssueLog; +use MetaModel; class FormsController extends Controller { public const ROUTE_NAMESPACE = 'forms'; + private FormBlockService $oFormBlockService; + public function __construct($sViewPath = '', $sModuleName = 'core', $aAdditionalPaths = []) { $sModuleName = 'core'; $sViewPath = APPROOT.'templates/application/forms'; + $this->oFormBlockService = MetaModel::GetService('FormBlockService'); parent::__construct($sViewPath, $sModuleName, $aAdditionalPaths); } @@ -31,7 +35,7 @@ class FormsController extends Controller $sDashletClass = $oRequest->query->get('dashlet_class'); // Get the form block from the service (and the compiler) - $oFormBlock = FormBlockService::GetInstance()->GetFormBlockById($sDashletClass, 'Dashlet'); + $oFormBlock = $this->oFormBlockService->GetFormBlockById($sDashletClass, 'Dashlet'); $oBuilder = $this->GetFormBuilder($oFormBlock, []); $oForm = $oBuilder->getForm(); $oForm->handleRequest($oRequest); diff --git a/sources/Forms/IO/Converter/OqlToClassConverter.php b/sources/Forms/IO/Converter/OqlToClassConverter.php index 1211ecd07..ba71acb0c 100644 --- a/sources/Forms/IO/Converter/OqlToClassConverter.php +++ b/sources/Forms/IO/Converter/OqlToClassConverter.php @@ -7,8 +7,8 @@ namespace Combodo\iTop\Forms\IO\Converter; -use Combodo\iTop\Service\DependencyInjection\DIException; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocatorException; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use Combodo\iTop\Forms\IO\Format\ClassIOFormat; use Combodo\iTop\Forms\IO\FormBlockIOException; use Exception; @@ -23,7 +23,7 @@ use ModelReflection; class OqlToClassConverter extends AbstractConverter { /** @inheritdoc - * @throws DIException + * @throws ServiceLocationException * @throws FormBlockIOException */ public function Convert(mixed $oData): ?ClassIOFormat @@ -33,7 +33,7 @@ class OqlToClassConverter extends AbstractConverter } /** @var ModelReflection $oModelReflection */ - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + $oModelReflection = \MetaModel::GetService('ModelReflection'); try { $oQuery = $oModelReflection->GetQuery($oData); } catch (Exception $e) { diff --git a/sources/Forms/IO/Format/AttributeTypeArrayIOFormat.php b/sources/Forms/IO/Format/AttributeTypeArrayIOFormat.php index 132f6ff22..c26fbad2e 100644 --- a/sources/Forms/IO/Format/AttributeTypeArrayIOFormat.php +++ b/sources/Forms/IO/Format/AttributeTypeArrayIOFormat.php @@ -2,7 +2,7 @@ namespace Combodo\iTop\Forms\IO\Format; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use Combodo\iTop\Forms\IO\FormBlockIOException; /** diff --git a/sources/Forms/IO/Format/ClassIOFormat.php b/sources/Forms/IO/Format/ClassIOFormat.php index ec19e94ce..c813d41ce 100644 --- a/sources/Forms/IO/Format/ClassIOFormat.php +++ b/sources/Forms/IO/Format/ClassIOFormat.php @@ -2,7 +2,7 @@ namespace Combodo\iTop\Forms\IO\Format; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use Combodo\iTop\Forms\IO\FormBlockIOException; /** @@ -16,14 +16,14 @@ class ClassIOFormat extends AbstractIOFormat public string $sClassName; /** - * @throws \Combodo\iTop\Service\DependencyInjection\DIException + * @throws \Combodo\iTop\Service\ServiceLocator\ServiceLocatorException * @throws \Combodo\iTop\Forms\IO\FormBlockIOException */ public function __construct(string $sClassName) { // Check class validity /** @var \ModelReflection $oModelReflection */ - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + $oModelReflection = \MetaModel::GetService('ModelReflection'); if (!$oModelReflection->IsValidClass($sClassName)) { throw new FormBlockIOException("Class ".json_encode($sClassName)." is not valid"); } diff --git a/sources/Forms/Validator/AttributeExistValidator.php b/sources/Forms/Validator/AttributeExistValidator.php index f765a0393..a494547a8 100644 --- a/sources/Forms/Validator/AttributeExistValidator.php +++ b/sources/Forms/Validator/AttributeExistValidator.php @@ -8,7 +8,7 @@ namespace Combodo\iTop\Forms\Validator; use Combodo\iTop\Forms\IO\Converter\OqlToClassConverter; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Constraint; @@ -41,8 +41,8 @@ class AttributeExistValidator extends ConstraintValidator $sClass = "UserRequest"; - /** List attributes @var ModelReflection $oModelReflection */ - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + /** @var \ModelReflection $oModelReflection */ + $oModelReflection = \MetaModel::GetService('ModelReflection'); $aAttributeCodes = array_keys($oModelReflection->ListAttributes($sClass)); if (!in_array($value, $aAttributeCodes, true)) { diff --git a/sources/PropertyType/PropertyTypeService.php b/sources/PropertyType/PropertyTypeService.php index 055fd7f2b..2f06d70b7 100644 --- a/sources/PropertyType/PropertyTypeService.php +++ b/sources/PropertyType/PropertyTypeService.php @@ -13,6 +13,7 @@ use Combodo\iTop\Forms\Block\FormBlockService; use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompiler; use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException; use Combodo\iTop\Service\Cache\DataModelDependantCache; +use MetaModel; use utils; class PropertyTypeService @@ -21,20 +22,9 @@ class PropertyTypeService private DataModelDependantCache $oCacheService; - private static PropertyTypeService $oInstance; - - protected function __construct() + public function __construct() { - $this->oCacheService = DataModelDependantCache::GetInstance(); - } - - final public static function GetInstance(): PropertyTypeService - { - if (!isset(static::$oInstance)) { - static::$oInstance = new PropertyTypeService(); - } - - return static::$oInstance; + $this->oCacheService = MetaModel::GetService('DataModelDependantCache'); } /** diff --git a/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php b/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php index d3420d1ce..2ae8df600 100644 --- a/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php +++ b/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php @@ -11,9 +11,17 @@ use Combodo\iTop\DesignElement; use Combodo\iTop\Forms\Block\Base\PolymorphicFormBlock; use Combodo\iTop\PropertyType\PropertyTypeService; use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory; +use MetaModel; class ValueTypePolymorphic extends AbstractBranchValueType { + private PropertyTypeService $oPropertyTypeService; + + public function __construct() + { + $this->oPropertyTypeService = MetaModel::GetService('PropertyTypeService'); + } + public function GetFormBlockClass(): string { return PolymorphicFormBlock::class; @@ -41,7 +49,7 @@ class ValueTypePolymorphic extends AbstractBranchValueType $sType = $value['type']; $oPropertyNode->setAttribute('xsi:type', $sType); - $oPropertyType = PropertyTypeService::GetInstance()->GetPropertyType($sType); + $oPropertyType = $this->oPropertyTypeService->GetPropertyType($sType); $aProperties = $value['properties']; $oPropertyType->SerializeToDOMNode($aProperties, $oPropertyNode); @@ -50,7 +58,7 @@ class ValueTypePolymorphic extends AbstractBranchValueType public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed { $sType = $oDOMNode->getAttribute('xsi:type'); - $oPropertyType = PropertyTypeService::GetInstance()->GetPropertyType($sType); + $oPropertyType = $this->oPropertyTypeService->GetPropertyType($sType); return [ 'type' => $sType, diff --git a/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php b/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php index 003fe442a..6c763caf1 100644 --- a/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php +++ b/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php @@ -10,7 +10,7 @@ namespace Combodo\iTop\PropertyType\ValueType\Leaf; use Combodo\iTop\DesignElement; use Combodo\iTop\Forms\Block\Base\ChoiceImageFormBlock; use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use utils; /** @@ -31,7 +31,7 @@ class ValueTypeClass extends AbstractLeafValueType $sCategories = $oDomNode->GetChildText('categories-csv', ''); /** @var \ModelReflection $oModelReflection */ - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + $oModelReflection = \MetaModel::GetService('ModelReflection'); $sChoices = "[\n"; $sChoicesAttImages = "[\n"; diff --git a/sources/PropertyType/ValueType/Leaf/ValueTypeIcon.php b/sources/PropertyType/ValueType/Leaf/ValueTypeIcon.php index 41c21e3e2..0d723b3b8 100644 --- a/sources/PropertyType/ValueType/Leaf/ValueTypeIcon.php +++ b/sources/PropertyType/ValueType/Leaf/ValueTypeIcon.php @@ -11,7 +11,7 @@ use Combodo\iTop\DesignElement; use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock; use Combodo\iTop\Forms\Block\Base\ChoiceImageFormBlock; use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType; -use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Combodo\iTop\Service\ServiceLocator\ServiceLocator; use utils; /** @@ -30,7 +30,7 @@ class ValueTypeIcon extends AbstractLeafValueType // Search icons in iTop and extensions /** @var \ModelReflection $oModelReflection */ - $oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection'); + $oModelReflection = \MetaModel::GetService('ModelReflection'); $sChoices = "[\n"; $sChoicesAttImages = "[\n"; diff --git a/sources/Service/Cache/DataModelDependantCache.php b/sources/Service/Cache/DataModelDependantCache.php index 879a0f5da..e637fc071 100644 --- a/sources/Service/Cache/DataModelDependantCache.php +++ b/sources/Service/Cache/DataModelDependantCache.php @@ -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; } diff --git a/sources/Service/DependencyInjection/DIException.php b/sources/Service/DependencyInjection/DIException.php deleted file mode 100644 index 928f1c08c..000000000 --- a/sources/Service/DependencyInjection/DIException.php +++ /dev/null @@ -1,20 +0,0 @@ -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]); - } -} diff --git a/sources/Service/InterfaceDiscovery/InterfaceDiscovery.php b/sources/Service/InterfaceDiscovery/InterfaceDiscovery.php index 67a5ca2fa..547621c4b 100644 --- a/sources/Service/InterfaceDiscovery/InterfaceDiscovery.php +++ b/sources/Service/InterfaceDiscovery/InterfaceDiscovery.php @@ -30,7 +30,7 @@ class InterfaceDiscovery private function __construct() { - $this->oCacheService = DataModelDependantCache::GetInstance(); + $this->oCacheService = MetaModel::GetService('DataModelDependantCache'); } public static function GetInstance(): InterfaceDiscovery diff --git a/sources/Service/ServiceLocator/NotFoundException.php b/sources/Service/ServiceLocator/NotFoundException.php new file mode 100644 index 000000000..c4f96792a --- /dev/null +++ b/sources/Service/ServiceLocator/NotFoundException.php @@ -0,0 +1,15 @@ +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); + } +} diff --git a/sources/Service/ServiceLocator/ServiceLocatorException.php b/sources/Service/ServiceLocator/ServiceLocatorException.php new file mode 100644 index 000000000..bf208b1d2 --- /dev/null +++ b/sources/Service/ServiceLocator/ServiceLocatorException.php @@ -0,0 +1,22 @@ + ModelReflectionRuntime::class, + 'DashletService' => DashletService::class, + 'PropertyTypeService' => PropertyTypeService::class, + 'DataModelDependantCache' => DataModelDependantCache::class, + 'FormBlockService' => FormBlockService::class, +]; diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php index 4412b0c7b..bc08c3bf3 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php @@ -8,6 +8,7 @@ namespace Combodo\iTop\Test\UnitTest; use CMDBSource; +use Combodo\iTop\Service\DependencyInjection\ServiceLocator; use DeprecatedCallsLog; use DOMDocument; use MySQLTransactionNotClosedException; @@ -31,6 +32,8 @@ use const DEBUG_BACKTRACE_IGNORE_ARGS; abstract class ItopTestCase extends KernelTestCase { public const TEST_LOG_DIR = 'test'; + /** @var \Combodo\iTop\Service\DependencyInjection\ServiceLocator */ + protected static ServiceLocator $oServiceLocator; protected array $aFileToClean = []; /** @@ -81,6 +84,11 @@ abstract class ItopTestCase extends KernelTestCase // Required to boot the portal symfony Kernel $_ENV['PORTAL_ID'] = 'itop-portal'; + + // Default Service Locator + // Read the runtime service locator configuration + self::$oServiceLocator = new ServiceLocator(); + self::$oServiceLocator->Init(); } /** @@ -749,4 +757,18 @@ abstract class ItopTestCase extends KernelTestCase // as compared to the report given by assertEqualXMLStructure static::assertEquals($this->CanonicalizeXML($sExpected), $this->CanonicalizeXML($sActual), $sMessage); } + + /** + * Get configured service + * + * @see conf/production/ServiceLocatorRuntimeConfig.php + * + * Example: $oModelReflection = \MetaModel::GetService('ModelReflexion'); + * + * @throws \Combodo\iTop\Service\DependencyInjection\ServiceLocationException + */ + protected static function GetService(string $sServiceName): mixed + { + return self::$oServiceLocator->get($sServiceName); + } } diff --git a/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php b/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php index dfe1d36d3..b8bbe49cb 100644 --- a/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php @@ -28,8 +28,6 @@ class DashboardSerializerTest extends ItopDataTestCase */ public function testSerializeXML($normalizedValue, string $sXMLContent) { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); - $oDOMDocument = new PropertyTypeDesign(); $oDOMDocument->preserveWhiteSpace = false; $oDOMDocument->formatOutput = true; diff --git a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php index 52571528c..1a2111099 100644 --- a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php @@ -24,8 +24,6 @@ class FormsCompilerTest extends ItopDataTestCase */ public function testCompileFormFromXML(string $sXMLContent, string $sExpectedPHP) { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); - $sProducedPHP = PropertyTypeCompiler::GetInstance()->CompileFormFromXML($sXMLContent); $this->AssertPHPCodeIsValid($sProducedPHP); @@ -862,8 +860,6 @@ XML, public function testCompileFormForIconSelection() { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); - $sXMLContent = << @@ -899,8 +895,6 @@ PHP; public function testCompileFormForClassSelection() { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); - $sXMLContent = << diff --git a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php index b73023ba1..c9b301458 100644 --- a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php @@ -24,8 +24,6 @@ class XMLSerializerTest extends ItopDataTestCase */ public function testSerializeXML($normalizedValue, string $sPropertyTypeXML, string $sXMLContent) { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); - $oDOMDocument = new PropertyTypeDesign(); $oDOMDocument->preserveWhiteSpace = false; $oDOMDocument->formatOutput = true; @@ -369,8 +367,6 @@ XML, */ public function testUnserializeXML($normalizedValue, string $sPropertyTypeXML, string $sXMLContent) { - ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); - $oDoc = new PropertyTypeDesign(); $oDoc->loadXML($sXMLContent); /** @var \Combodo\iTop\DesignElement $oRoot */ diff --git a/tests/php-unit-tests/unitary-tests/sources/Service/Cache/DataModelDependantCacheTest.php b/tests/php-unit-tests/unitary-tests/sources/Service/Cache/DataModelDependantCacheTest.php index 33786d730..ca2cc985a 100644 --- a/tests/php-unit-tests/unitary-tests/sources/Service/Cache/DataModelDependantCacheTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/Service/Cache/DataModelDependantCacheTest.php @@ -17,7 +17,7 @@ class DataModelDependantCacheTest extends ItopTestCase $this->sCacheRootDir = self::CreateTmpdir(); - $this->oCacheService = DataModelDependantCache::GetInstance(); + $this->oCacheService = static::GetService('DataModelDependantCache'); $this->oCacheService->SetStorageRootDir($this->sCacheRootDir); } diff --git a/tests/php-unit-tests/unitary-tests/sources/Service/InterfaceDiscovery/InterfaceDiscoveryTest.php b/tests/php-unit-tests/unitary-tests/sources/Service/InterfaceDiscovery/InterfaceDiscoveryTest.php index 00ce4476f..7f45aa298 100644 --- a/tests/php-unit-tests/unitary-tests/sources/Service/InterfaceDiscovery/InterfaceDiscoveryTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/Service/InterfaceDiscovery/InterfaceDiscoveryTest.php @@ -19,7 +19,7 @@ class InterfaceDiscoveryTest extends ItopDataTestCase parent::setUp(); $this->oInterfaceDiscovery = InterfaceDiscovery::GetInstance(); $this->sCacheRootDir = self::CreateTmpdir(); - $this->oCacheService = DataModelDependantCache::GetInstance(); + $this->oCacheService = static::GetService('DataModelDependantCache'); $this->oCacheService->SetStorageRootDir($this->sCacheRootDir); $this->oInterfaceDiscovery->SetCacheService($this->oCacheService); } @@ -103,7 +103,7 @@ class InterfaceDiscoveryTest extends ItopDataTestCase public function testShouldNotProduceCacheForDevelopers() { - DataModelDependantCache::GetInstance()->Clear('InterfaceDiscovery'); + $this->oCacheService->Clear('InterfaceDiscovery'); MetaModel::GetConfig()->Set('developer_mode.enabled', true); MetaModel::GetConfig()->Set('developer_mode.interface_cache.enabled', false); @@ -114,7 +114,7 @@ class InterfaceDiscoveryTest extends ItopDataTestCase public function testShouldProduceDynamicCacheForDevelopersWillingTo() { - DataModelDependantCache::GetInstance()->Clear('InterfaceDiscovery'); + $this->oCacheService->Clear('InterfaceDiscovery'); MetaModel::GetConfig()->Set('developer_mode.enabled', true); MetaModel::GetConfig()->Set('developer_mode.interface_cache.enabled', true); @@ -131,7 +131,7 @@ class InterfaceDiscoveryTest extends ItopDataTestCase public function testShouldProduceStaticCacheForProduction() { - DataModelDependantCache::GetInstance()->Clear('InterfaceDiscovery'); + $this->oCacheService->Clear('InterfaceDiscovery'); MetaModel::GetConfig()->Set('developer_mode.enabled', false);