Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
servicelocator.php
1<?php
2
3namespace Bitrix\Main\DI;
4
8use Psr\Container\ContainerExceptionInterface;
9use Psr\Container\NotFoundExceptionInterface;
10
11final class ServiceLocator implements \Psr\Container\ContainerInterface
12{
14 private array $services = [];
15 private array $instantiated = [];
16 private static ServiceLocator $instance;
17
18 private function __construct()
19 {}
20
21 private function __clone()
22 {}
23
24 public static function getInstance(): self
25 {
26 if (!isset(self::$instance))
27 {
28 self::$instance = new self();
29 }
30
31 return self::$instance;
32 }
33
39 public function addInstance(string $code, mixed $service): void
40 {
41 $this->instantiated[$code] = $service;
42 }
43
51 public function addInstanceLazy(string $id, $configuration): void
52 {
53 if (!isset($configuration['className']) && !isset($configuration['constructor']))
54 {
55 throw $this->buildBadRegistrationExceptions($id);
56 }
57
58 $furtherClassMetadata = $configuration['className'] ?? $configuration['constructor'];
59
60 $this->services[$id] = [$furtherClassMetadata, $configuration['constructorParams'] ?? []];
61 }
62
68 public function registerByModuleSettings(string $moduleName): void
69 {
70 $configuration = Configuration::getInstance($moduleName);
71 $services = $configuration['services'] ?? [];
72 foreach ($services as $code => $config)
73 {
74 if ($this->has($code))
75 {
76 //It means that there is overridden service in global .setting.php or extra settings.
77 //Or probably service was registered manually.
78 continue;
79 }
80
81 $this->addInstanceLazy($code, $config);
82 }
83 }
84
89 public function registerByGlobalSettings(): void
90 {
91 $configuration = Configuration::getInstance();
92 $services = $configuration['services'] ?? [];
93 foreach ($services as $code => $config)
94 {
95 $this->addInstanceLazy($code, $config);
96 }
97 }
98
104 public function has(string $id): bool
105 {
106 return isset($this->services[$id]) || isset($this->instantiated[$id]);
107 }
108
116 public function get(string $id)
117 {
118 if (isset($this->instantiated[$id]))
119 {
120 return $this->instantiated[$id];
121 }
122
123 if (!isset($this->services[$id]))
124 {
125 throw $this->buildNotFoundException($id);
126 }
127
128 [$class, $args] = $this->services[$id];
129
130 if ($class instanceof \Closure)
131 {
132 $object = $class();
133 }
134 else
135 {
136 if ($args instanceof \Closure)
137 {
138 $args = $args();
139 }
140 $object = new $class(...array_values($args));
141 }
142
143 $this->instantiated[$id] = $object;
144
145 return $object;
146 }
147
148 private function buildNotFoundException(string $id): ObjectNotFoundException|NotFoundExceptionInterface
149 {
150 return new class("Could not find service by code {$id}.") extends ObjectNotFoundException
151 implements NotFoundExceptionInterface {}
152 ;
153 }
154
155 private function buildBadRegistrationExceptions(string $id): SystemException|ContainerExceptionInterface
156 {
157 $message =
158 "Could not register service {{$id}}." .
159 "There is no {className} to find class or {constructor} to build instance."
160 ;
161
162 return new class($message) extends SystemException implements ContainerExceptionInterface {};
163 }
164}
addInstance(string $code, mixed $service)
registerByModuleSettings(string $moduleName)
addInstanceLazy(string $id, $configuration)