Completed
Push — master ( fa81e5...c1047a )
by De Cramer
04:54 queued 01:25
created

DataProviderManager::getCompatibleProviderId()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.1158

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 10
cts 12
cp 0.8333
rs 8.7624
c 0
b 0
f 0
cc 5
eloc 13
nc 5
nop 5
crap 5.1158
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(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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) {
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...
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