|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace eXpansion\Framework\Core\Services; |
|
4
|
|
|
|
|
5
|
|
|
use eXpansion\Framework\Core\DataProviders\AbstractDataProvider; |
|
6
|
|
|
use eXpansion\Framework\Core\Exceptions\DataProvider\UncompatibleException; |
|
7
|
|
|
use eXpansion\Framework\Core\Helpers\CompatibleFetcher; |
|
8
|
|
|
use eXpansion\Framework\Core\Model\CompatibilityCheckDataProviderInterface; |
|
9
|
|
|
use eXpansion\Framework\Core\Model\ProviderListener; |
|
10
|
|
|
use eXpansion\Framework\Core\Storage\GameDataStorage; |
|
11
|
|
|
use Maniaplanet\DedicatedServer\Structures\Map; |
|
12
|
|
|
use oliverde8\AssociativeArraySimplified\AssociativeArray; |
|
13
|
|
|
use Psr\Log\LoggerInterface; |
|
14
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Class DataProviderManager handles all the data providers. |
|
18
|
|
|
* |
|
19
|
|
|
* @package eXpansion\Framework\Core\Services |
|
20
|
|
|
*/ |
|
21
|
|
|
class DataProviderManager |
|
22
|
|
|
{ |
|
23
|
|
|
/** For compatibility with every title/mode/script */ |
|
24
|
|
|
const COMPATIBLE_ALL = "ALL"; |
|
25
|
|
|
|
|
26
|
|
|
/** @var int[][][][] List of providers by compatibility. */ |
|
27
|
|
|
protected $providersByCompatibility = []; |
|
28
|
|
|
|
|
29
|
|
|
/** @var string[] Name of the provider for a service Id. */ |
|
30
|
|
|
protected $providerById = []; |
|
31
|
|
|
|
|
32
|
|
|
/** @var string[] Interface a plugin needs extend/implement to be used by a provider. */ |
|
33
|
|
|
protected $providerInterfaces = []; |
|
34
|
|
|
|
|
35
|
|
|
/** @var ProviderListener[][] Providers that listen a certain event. */ |
|
36
|
|
|
protected $providerListeners = []; |
|
37
|
|
|
|
|
38
|
|
|
/** @var array[][] Enabled providers that listen to certain events. */ |
|
39
|
|
|
protected $enabledProviderListeners = []; |
|
40
|
|
|
|
|
41
|
|
|
/** @var ContainerInterface */ |
|
42
|
|
|
protected $container; |
|
43
|
|
|
|
|
44
|
|
|
/** @var GameDataStorage */ |
|
45
|
|
|
protected $gameDataStorage; |
|
46
|
|
|
|
|
47
|
|
|
/** @var Console */ |
|
48
|
|
|
protected $console; |
|
49
|
|
|
|
|
50
|
|
|
/** @var LoggerInterface */ |
|
51
|
|
|
protected $logger; |
|
52
|
|
|
|
|
53
|
|
|
/** @var CompatibleFetcher */ |
|
54
|
|
|
protected $compatibleFetcher; |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* DataProviderManager constructor. |
|
58
|
|
|
* |
|
59
|
|
|
* @param ContainerInterface $container |
|
60
|
|
|
* @param GameDataStorage $gameDataStorage |
|
61
|
|
|
* @param Console $console |
|
62
|
|
|
* @param LoggerInterface $logger |
|
63
|
|
|
* @param CompatibleFetcher $compatibleFetcher |
|
64
|
|
|
*/ |
|
65
|
150 |
View Code Duplication |
public function __construct( |
|
|
|
|
|
|
66
|
|
|
ContainerInterface $container, |
|
67
|
|
|
GameDataStorage $gameDataStorage, |
|
68
|
|
|
Console $console, |
|
69
|
|
|
LoggerInterface $logger, |
|
70
|
|
|
CompatibleFetcher $compatibleFetcher |
|
71
|
|
|
) { |
|
72
|
150 |
|
$this->container = $container; |
|
73
|
150 |
|
$this->gameDataStorage = $gameDataStorage; |
|
74
|
150 |
|
$this->console = $console; |
|
75
|
150 |
|
$this->logger = $logger; |
|
76
|
150 |
|
$this->compatibleFetcher = $compatibleFetcher; |
|
77
|
150 |
|
} |
|
78
|
|
|
|
|
79
|
|
|
/** |
|
80
|
|
|
* Reset |
|
81
|
|
|
* |
|
82
|
|
|
* @param PluginManager $pluginManager |
|
83
|
|
|
* @param Map $map |
|
84
|
|
|
*/ |
|
85
|
1 |
|
public function reset(PluginManager $pluginManager, Map $map) |
|
86
|
|
|
{ |
|
87
|
1 |
|
$title = $this->gameDataStorage->getTitle(); |
|
88
|
1 |
|
$mode = $this->gameDataStorage->getGameModeCode(); |
|
89
|
1 |
|
$script = strtolower($this->gameDataStorage->getGameInfos()->scriptName); |
|
90
|
1 |
|
$this->enabledProviderListeners = []; |
|
91
|
|
|
|
|
92
|
1 |
|
foreach ($this->providersByCompatibility as $provider => $data) { |
|
93
|
|
|
|
|
94
|
1 |
|
$providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script, $map); |
|
95
|
|
|
|
|
96
|
1 |
|
if ($providerId) { |
|
97
|
1 |
|
$providerService = $this->container->get($providerId); |
|
98
|
1 |
|
if ($pluginManager->isPluginEnabled($providerId)) { |
|
99
|
|
|
|
|
100
|
1 |
|
foreach ($this->providerListeners[$providerId] as $listener) { |
|
101
|
1 |
|
$this->enabledProviderListeners[$listener->getEventName()][] = [ |
|
102
|
1 |
|
$providerService, |
|
103
|
1 |
|
$listener->getMethod(), |
|
104
|
|
|
]; |
|
105
|
|
|
} |
|
106
|
|
|
} |
|
107
|
|
|
} |
|
108
|
|
|
} |
|
109
|
1 |
|
} |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* Register a provider. |
|
113
|
|
|
* |
|
114
|
|
|
* @param string $id |
|
115
|
|
|
* @param string $provider |
|
116
|
|
|
* @param string $interface |
|
117
|
|
|
* @param string[][] $compatibilities |
|
118
|
|
|
* @param string[] $listeners |
|
119
|
|
|
*/ |
|
120
|
150 |
|
public function registerDataProvider($id, $provider, $interface, $compatibilities, $listeners) |
|
121
|
|
|
{ |
|
122
|
150 |
|
foreach ($compatibilities as $compatibility) { |
|
123
|
150 |
|
$this->providersByCompatibility[$provider][$compatibility['title']][$compatibility['gamemode']][$compatibility['script']] = $id; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
150 |
|
$this->providerListeners[$id] = []; |
|
127
|
150 |
|
foreach ($listeners as $eventName => $method) { |
|
128
|
150 |
|
$this->providerListeners[$id][] = new ProviderListener($eventName, $provider, $method); |
|
129
|
|
|
} |
|
130
|
150 |
|
$this->providerInterfaces[$provider] = $interface; |
|
131
|
150 |
|
$this->providerById[$id] = $provider; |
|
132
|
150 |
|
} |
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Check of a provider is compatible |
|
136
|
|
|
* |
|
137
|
|
|
* @param string $provider |
|
138
|
|
|
* @param string $title |
|
139
|
|
|
* @param string $mode |
|
140
|
|
|
* @param string $script |
|
141
|
|
|
* @param Map $map |
|
142
|
|
|
* |
|
143
|
|
|
* @return bool |
|
144
|
|
|
*/ |
|
145
|
1 |
|
public function isProviderCompatible($provider, $title, $mode, $script, Map $map) |
|
146
|
|
|
{ |
|
147
|
1 |
|
return !is_null($this->getCompatibleProviderId($provider, $title, $mode, $script, $map)); |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* @param string $providerName |
|
152
|
|
|
* @param string $title |
|
153
|
|
|
* @param string $mode |
|
154
|
|
|
* @param string $script |
|
155
|
|
|
* @param Map $map |
|
156
|
|
|
* |
|
157
|
|
|
* @return string|null |
|
158
|
|
|
*/ |
|
159
|
4 |
|
public function getCompatibleProviderId($providerName, $title, $mode, $script, Map $map) |
|
160
|
|
|
{ |
|
161
|
4 |
|
$parameters = $this->compatibleFetcher->getChoicesByPriority($title, $mode, $script); |
|
162
|
|
|
|
|
163
|
4 |
|
foreach ($parameters as $parameter) { |
|
164
|
4 |
|
$parameter = array_merge([$providerName], $parameter); |
|
165
|
4 |
|
$id = AssociativeArray::getFromKey($this->providersByCompatibility, $parameter); |
|
166
|
4 |
|
if (!is_null($id)) { |
|
167
|
4 |
|
$provider = $this->container->get($id); |
|
168
|
4 |
|
if ($provider instanceof CompatibilityCheckDataProviderInterface) { |
|
|
|
|
|
|
169
|
|
|
if ($provider->isCompatible($map)) { |
|
170
|
|
|
return $id; |
|
171
|
|
|
} |
|
172
|
|
|
} else { |
|
173
|
4 |
|
return $id; |
|
174
|
|
|
} |
|
175
|
|
|
} |
|
176
|
|
|
} |
|
177
|
|
|
|
|
178
|
2 |
|
return null; |
|
179
|
|
|
} |
|
180
|
|
|
|
|
181
|
|
|
/** |
|
182
|
|
|
* Register a plugin to the DataProviders. |
|
183
|
|
|
* |
|
184
|
|
|
* @param string $provider The provider to register the plugin to. |
|
185
|
|
|
* @param string $pluginId The id of the plugin to be registered. |
|
186
|
|
|
* @param string $title The title to register it for. |
|
187
|
|
|
* @param string $mode The mode to register it for. |
|
188
|
|
|
* @param string $script The script to register it for. |
|
189
|
|
|
* @param Map $map Current map |
|
190
|
|
|
* |
|
191
|
|
|
* @throws UncompatibleException |
|
192
|
|
|
*/ |
|
193
|
2 |
|
public function registerPlugin($provider, $pluginId, $title, $mode, $script, Map $map) |
|
194
|
|
|
{ |
|
195
|
2 |
|
$providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script, $map); |
|
196
|
|
|
|
|
197
|
2 |
|
if (empty($providerId)) { |
|
198
|
|
|
return; |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
|
|
/** @var AbstractDataProvider $providerService */ |
|
202
|
2 |
|
$providerService = $this->container->get($providerId); |
|
203
|
2 |
|
$pluginService = $this->container->get($pluginId); |
|
204
|
2 |
|
$interface = $this->providerInterfaces[$provider]; |
|
205
|
|
|
|
|
206
|
2 |
|
if ($pluginService instanceof $interface) { |
|
207
|
1 |
|
$this->deletePlugin($provider, $pluginId); |
|
208
|
1 |
|
$providerService->registerPlugin($pluginId, $pluginService); |
|
209
|
|
|
} else { |
|
210
|
1 |
|
throw new UncompatibleException("Plugin $pluginId isn't compatible with $provider. Should be instance of $interface"); |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
1 |
|
$this->logger->info("Plugin '$pluginId' will use data provider '$provider' : '$providerId'"); |
|
214
|
1 |
|
} |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* Provider to delete a plugin from. |
|
218
|
|
|
* |
|
219
|
|
|
* @param $provider |
|
220
|
|
|
* @param $pluginId |
|
221
|
|
|
* |
|
222
|
|
|
*/ |
|
223
|
1 |
|
public function deletePlugin($provider, $pluginId) |
|
224
|
|
|
{ |
|
225
|
1 |
|
foreach ($this->providersByCompatibility[$provider] as $titleProviders) { |
|
226
|
1 |
|
foreach ($titleProviders as $modeProviders) { |
|
227
|
1 |
|
foreach ($modeProviders as $providerId) { |
|
228
|
1 |
|
$providerService = $this->container->get($providerId); |
|
229
|
1 |
|
$providerService->deletePlugin($pluginId); |
|
230
|
|
|
} |
|
231
|
|
|
} |
|
232
|
|
|
} |
|
233
|
1 |
|
} |
|
234
|
|
|
|
|
235
|
|
|
/** |
|
236
|
|
|
* Dispatch event to the data providers. |
|
237
|
|
|
* |
|
238
|
|
|
* @param $eventName |
|
239
|
|
|
* @param $params |
|
240
|
|
|
*/ |
|
241
|
1 |
|
public function dispatch($eventName, $params) |
|
242
|
|
|
{ |
|
243
|
1 |
|
if (isset($this->enabledProviderListeners[$eventName])) { |
|
244
|
1 |
|
foreach ($this->enabledProviderListeners[$eventName] as $callback) { |
|
245
|
1 |
|
call_user_func_array($callback, $params); |
|
246
|
|
|
} |
|
247
|
|
|
} |
|
248
|
1 |
|
} |
|
249
|
|
|
} |
|
250
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.