Completed
Pull Request — master (#331)
by
unknown
03:33
created

DataProviderManager::dispatch()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 3

Importance

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