Completed
Pull Request — master (#309)
by De Cramer
14:06
created

DataProviderManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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