Completed
Push — master ( f31586...66eb65 )
by De Cramer
04:28
created

DataProviderManager::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
cc 1
eloc 2
nc 1
nop 2
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\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 game mode 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 138
    public function __construct(ContainerInterface $container, GameDataStorage $gameDataStorage, Console $console)
61
    {
62 138
        $this->container = $container;
63 138
        $this->gameDataStorage = $gameDataStorage;
64 138
        $this->console = $console;
65 138
    }
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 1
        $this->enabledProviderListeners = [];
90
91 1
        foreach ($this->providersByCompatibility as $provider => $data) {
92
93 1
            $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script, $map);
94
95 1
            if ($providerId) {
96 1
                $providerService = $this->container->get($providerId);
97
98 1
                if ($pluginManager->isPluginEnabled($providerId)) {
99 1
                    foreach ($this->providerListeners[$providerId] as $listener) {
100 1
                        $this->enabledProviderListeners[$listener->getEventName()][] = [
101 1
                            $providerService,
102 1
                            $listener->getMethod(),
103
                        ];
104
                    }
105
                }
106
            }
107
        }
108 1
    }
109
110
    /**
111
     * Register a provider.
112
     *
113
     * @param string $id
114
     * @param string $provider
115
     * @param string $interface
116
     * @param string[][] $compatibilities
117
     * @param string[] $listeners
118
     */
119 138
    public function registerDataProvider($id, $provider, $interface, $compatibilities, $listeners)
120
    {
121 138
        foreach ($compatibilities as $compatibility) {
122 138
            $this->providersByCompatibility[$provider][$compatibility['title']][$compatibility['gamemode']][$compatibility['script']] = $id;
123
        }
124
125 138
        $this->providerListeners[$id] = [];
126 138
        foreach ($listeners as $eventName => $method) {
127 138
            $this->providerListeners[$id][] = new ProviderListener($eventName, $provider, $method);
128
        }
129 138
        $this->providerInterfaces[$provider] = $interface;
130 138
        $this->providerById[$id] = $provider;
131 138
    }
132
133
    /**
134
     * Check of a provider is compatible
135
     *
136
     * @param string $provider
137
     * @param string $title
138
     * @param string $mode
139
     * @param string $script
140
     * @param Map    $map
141
     *
142
     * @return bool
143
     */
144 1
    public function isProviderCompatible($provider, $title, $mode, $script, Map $map)
145
    {
146 1
        return !is_null($this->getCompatibleProviderId($provider, $title, $mode, $script, $map));
147
    }
148
149
    /**
150
     * @param string $provider
151
     * @param string $title
152
     * @param string $mode
153
     * @param string $script
154
     * @param Map $map
155
     *
156
     * @return string|null
157
     */
158 4
    public function getCompatibleProviderId($provider, $title, $mode, $script, Map $map)
159
    {
160
        $parameters = [
161 4
            [$provider, $title, $mode, $script],
162 4
            [$provider, $title, $mode, self::COMPATIBLE_ALL],
163 4
            [$provider, $title, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
164 4
            [$provider, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
165
            // For modes that are common to all titles.
166 4
            [$provider, self::COMPATIBLE_ALL, $mode, self::COMPATIBLE_ALL],
167 4
            [$provider, self::COMPATIBLE_ALL, $mode, $script],
168
        ];
169
170 4
        foreach ($parameters as $parameter) {
171 4
            $id = AssociativeArray::getFromKey($this->providersByCompatibility, $parameter);
172 4
            if (!is_null($id)) {
173 4
                $provider = $this->container->get($id);
174 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...
175
                    if ($provider->isCompatible($map)) {
176
                        return $id;
177
                    }
178
                } else {
179 4
                    return $id;
180
                }
181
            }
182
        }
183
184 2
        return null;
185
    }
186
187
    /**
188
     * Register a plugin to the DataProviders.
189
     *
190
     * @param string $provider The provider to register the plugin to.
191
     * @param string $pluginId The id of the plugin to be registered.
192
     * @param string $title The title to register it for.
193
     * @param string $mode The mode to register it for.
194
     * @param string $script The script to register it for.
195
     * @param Map    $map Current map
196
     *
197
     * @throws UncompatibleException
198
     */
199 2
    public function registerPlugin($provider, $pluginId, $title, $mode, $script, Map $map)
200
    {
201 2
        $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script, $map);
202
203
        /** @var AbstractDataProvider $providerService */
204 2
        $providerService = $this->container->get($providerId);
205 2
        $pluginService = $this->container->get($pluginId);
206 2
        $interface = $this->providerInterfaces[$provider];
207
208 2
        if ($pluginService instanceof $interface) {
209 1
            $this->deletePlugin($provider, $pluginId);
210 1
            $providerService->registerPlugin($pluginId, $pluginService);
211
        } else {
212 1
            throw new UncompatibleException("Plugin $pluginId isn't compatible with $provider. Should be instance of $interface");
213
        }
214
215 1
        $this->console->getConsoleOutput()->writeln("\t<info>- $provider : $providerId</info>");
216 1
    }
217
218
    /**
219
     * Provider to delete a plugin from.
220
     *
221
     * @param $provider
222
     * @param $pluginId
223
     *
224
     */
225 1
    public function deletePlugin($provider, $pluginId)
226
    {
227 1
        foreach ($this->providersByCompatibility[$provider] as $titleProviders) {
228 1
            foreach ($titleProviders as $modeProviders) {
229 1
                foreach ($modeProviders as $providerId) {
230 1
                    $providerService = $this->container->get($providerId);
231 1
                    $providerService->deletePlugin($pluginId);
232
                }
233
            }
234
        }
235 1
    }
236
237
    /**
238
     * Dispatch event to the data providers.
239
     *
240
     * @param $eventName
241
     * @param $params
242
     */
243 1
    public function dispatch($eventName, $params)
244
    {
245 1
        if (isset($this->enabledProviderListeners[$eventName])) {
246 1
            foreach ($this->enabledProviderListeners[$eventName] as $callback) {
247 1
                call_user_func_array($callback, $params);
248
            }
249
        }
250 1
    }
251
}
252