Completed
Pull Request — master (#307)
by
unknown
04:00
created

DataProviderManager   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 236
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 18.92%

Importance

Changes 0
Metric Value
dl 0
loc 236
ccs 14
cts 74
cp 0.1892
rs 10
c 0
b 0
f 0
wmc 26
lcom 1
cbo 9

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A init() 0 4 1
B reset() 0 25 5
A registerDataProvider() 0 13 3
A isProviderCompatible() 0 4 1
B getCompatibleProviderId() 0 28 5
A registerPlugin() 0 20 3
A deletePlugin() 0 11 4
A dispatch() 0 8 3
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\Model\CompatibilityCheckDataProviderInterface;
8
use eXpansion\Framework\Core\Model\ProviderListener;
9
use eXpansion\Framework\Core\Storage\GameDataStorage;
10
use Maniaplanet\DedicatedServer\Structures\Map;
11
use oliverde8\AssociativeArraySimplified\AssociativeArray;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13
14
/**
15
 * Class DataProviderManager handles all the data providers.
16
 *
17
 * @TODO handle game mode change.
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
    /**
51
     * DataProviderManager constructor.
52
     *
53
     * @param ContainerInterface $container
54
     * @param GameDataStorage    $gameDataStorage
55
     * @param Console            $console
56
     * @param string             $env
57
     */
58 164
    public function __construct(
59
        ContainerInterface $container,
60
        GameDataStorage $gameDataStorage,
61
        Console $console,
62
        $env
0 ignored issues
show
Unused Code introduced by
The parameter $env is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
63
    )
64
    {
65 164
        $this->container = $container;
66 164
        $this->gameDataStorage = $gameDataStorage;
67 164
        $this->console = $console;
68 164
    }
69
70
    /**
71
     * Initialize all the providers properly.
72
     *
73
     * @param PluginManager $pluginManager
74
     * @param Map           $map
75
     */
76
    public function init(PluginManager $pluginManager, Map $map)
77
    {
78
        $this->reset($pluginManager, $map);
79
    }
80
81
    /**
82
     * Reset
83
     *
84
     * @param PluginManager $pluginManager
85
     * @param Map           $map
86
     */
87
    public function reset(PluginManager $pluginManager, Map $map)
88
    {
89
        $title = $this->gameDataStorage->getTitle();
90
        $mode = $this->gameDataStorage->getGameModeCode();
91
        $script = $this->gameDataStorage->getGameInfos()->scriptName;
92
        $this->enabledProviderListeners = [];
93
94
        foreach ($this->providersByCompatibility as $provider => $data) {
95
96
            $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script, $map);
97
98
            if ($providerId) {
99
                $providerService = $this->container->get($providerId);
100
101
                if ($pluginManager->isPluginEnabled($providerId)) {
102
                    foreach ($this->providerListeners[$providerId] as $listener) {
103
                        $this->enabledProviderListeners[$listener->getEventName()][] = [
104
                            $providerService,
105
                            $listener->getMethod(),
106
                        ];
107
                    }
108
                }
109
            }
110
        }
111
    }
112
113
    /**
114
     * Register a provider.
115
     *
116
     * @param string $id
117
     * @param string $provider
118
     * @param string $interface
119
     * @param string[][] $compatibilities
120
     * @param string[] $listeners
121
     */
122 164
    public function registerDataProvider($id, $provider, $interface, $compatibilities, $listeners)
123
    {
124 164
        foreach ($compatibilities as $compatibility) {
125 164
            $this->providersByCompatibility[$provider][$compatibility['title']][$compatibility['gamemode']][$compatibility['script']] = $id;
126
        }
127
128 164
        $this->providerListeners[$id] = [];
129 164
        foreach ($listeners as $eventName => $method) {
130 164
            $this->providerListeners[$id][] = new ProviderListener($eventName, $provider, $method);
131
        }
132 164
        $this->providerInterfaces[$provider] = $interface;
133 164
        $this->providerById[$id] = $provider;
134 164
    }
135
136
    /**
137
     * Check of a provider is compatible
138
     *
139
     * @param string $provider
140
     * @param string $title
141
     * @param string $mode
142
     * @param string $script
143
     * @param Map    $map
144
     *
145
     * @return bool
146
     */
147
    public function isProviderCompatible($provider, $title, $mode, $script, Map $map)
148
    {
149
        return !is_null($this->getCompatibleProviderId($provider, $title, $mode, $script, $map));
150
    }
151
152
    /**
153
     * @param string $provider
154
     * @param string $title
155
     * @param string $mode
156
     * @param string $script
157
     * @param Map $map
158
     *
159
     * @return string|null
160
     */
161
    public function getCompatibleProviderId($provider, $title, $mode, $script, Map $map)
162
    {
163
        $parameters = [
164
            [$provider, $title, $mode, $script],
165
            [$provider, $title, $mode, self::COMPATIBLE_ALL],
166
            [$provider, $title, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
167
            [$provider, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
168
            // For modes that are common to all titles.
169
            [$provider, self::COMPATIBLE_ALL, $mode, self::COMPATIBLE_ALL],
170
            [$provider, self::COMPATIBLE_ALL, $mode, $script],
171
        ];
172
173
        foreach ($parameters as $parameter) {
174
            $id = AssociativeArray::getFromKey($this->providersByCompatibility, $parameter);
175
            if (!is_null($id)) {
176
                $provider = $this->container->get($id);
177
                if ($provider instanceof CompatibilityCheckDataProviderInterface) {
0 ignored issues
show
Bug introduced by
The class eXpansion\Framework\Core...ckDataProviderInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
178
                    if ($provider->isCompatible($map)) {
179
                        return $id;
180
                    }
181
                } else {
182
                    return $id;
183
                }
184
            }
185
        }
186
187
        return null;
188
    }
189
190
    /**
191
     * Register a plugin to the DataProviders.
192
     *
193
     * @param string $provider The provider to register the plugin to.
194
     * @param string $pluginId The id of the plugin to be registered.
195
     * @param string $title The title to register it for.
196
     * @param string $mode The mode to register it for.
197
     * @param string $script The script to register it for.
198
     * @param Map    $map Current map
199
     *
200
     * @throws UncompatibleException
201
     */
202
    public function registerPlugin($provider, $pluginId, $title, $mode, $script, Map $map)
203
    {
204
        $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script, $map);
205
206
        /** @var AbstractDataProvider $providerService */
207
        $providerService = $this->container->get($providerId);
208
        $pluginService = $this->container->get($pluginId);
209
        $interface = $this->providerInterfaces[$provider];
210
211
        if ($pluginService instanceof $interface) {
212
            $this->deletePlugin($provider, $pluginId);
213
            $providerService->registerPlugin($pluginId, $pluginService);
214
        } else {
215
            throw new UncompatibleException("Plugin $pluginId isn't compatible with $provider. Should be instance of $interface");
216
        }
217
218
        if ($this->container->getParameter('kernel.environment') == 'dev') {
219
            $this->console->getConsoleOutput()->writeln("\t<info>- $provider</info>");
220
        }
221
    }
222
223
    /**
224
     * Provider to delete a plugin from.
225
     *
226
     * @param $provider
227
     * @param $pluginId
228
     *
229
     */
230
    public function deletePlugin($provider, $pluginId)
231
    {
232
        foreach ($this->providersByCompatibility[$provider] as $titleProviders) {
233
            foreach ($titleProviders as $modeProviders) {
234
                foreach ($modeProviders as $providerId) {
235
                    $providerService = $this->container->get($providerId);
236
                    $providerService->deletePlugin($pluginId);
237
                }
238
            }
239
        }
240
    }
241
242
    /**
243
     * Dispatch event to the data providers.
244
     *
245
     * @param $eventName
246
     * @param $params
247
     */
248
    public function dispatch($eventName, $params)
249
    {
250
        if (isset($this->enabledProviderListeners[$eventName])) {
251
            foreach ($this->enabledProviderListeners[$eventName] as $callback) {
252
                call_user_func_array($callback, $params);
253
            }
254
        }
255
    }
256
}
257