Completed
Pull Request — master (#191)
by De Cramer
04:00
created

DataProviderManager   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 97.22%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 9
dl 0
loc 227
rs 10
c 0
b 0
f 0
ccs 70
cts 72
cp 0.9722

9 Methods

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