Completed
Pull Request — master (#80)
by De Cramer
02:56
created

DataProviderManager::registerPlugin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

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