Completed
Push — dev ( 8eacd8...04be10 )
by De Cramer
02:44
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
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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\ProviderListner;
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 ProviderListner[][] Providers that listen a certain event. */
37
    protected $providerListeners = [];
38
39
    /** @var ProviderListner[][] 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
     */
56 49
    public function __construct(ContainerInterface $container, GameDataStorage $gameDataStorage, Console $console)
57
    {
58 49
        $this->container = $container;
59 49
        $this->gameDataStorage = $gameDataStorage;
60 49
        $this->console = $console;
61 49
    }
62
63
    /**
64
     * Initialize all the providers properly.
65
     */
66 1
    public function init(PluginManager $pluginManager)
67
    {
68 1
        $this->reset($pluginManager);
69 1
    }
70
71 1
    public function reset(PluginManager $pluginManager)
72
    {
73 1
        $title = $this->gameDataStorage->getTitle();
74 1
        $mode = $this->gameDataStorage->getGameModeCode();
75 1
        $script = $this->gameDataStorage->getGameInfos()->scriptName;
76
77 1
        foreach ($this->providersByCompatibility as $provider => $data) {
78
79 1
            $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script);
80
81 1
            if ($providerId) {
82 1
                $providerService = $this->container->get($providerId);
83
84 1
                if ($pluginManager->isPluginEnabled($providerId)) {
85 1
                    foreach ($this->providerListeners[$providerId] as $listener) {
86 1
                        $this->enabledProviderListeners[$listener->getEventName()][] = [
87 1
                            $providerService,
88 1
                            $listener->getMethod()
89
                        ];
90
                    }
91
                }
92
            }
93
        }
94 1
    }
95
96
    /**
97
     * Register a provider.
98
     *
99
     * @param string $id
100
     * @param string $provider
101
     * @param string $interface
102
     * @param string[][] $compatibilities
103
     * @param string[] $listeners
104
     */
105 49
    public function registerDataProvider($id, $provider, $interface, $compatibilities, $listeners)
106
    {
107 49
        foreach ($compatibilities as $compatibility) {
108 49
            $this->providersByCompatibility[$provider][$compatibility['title']][$compatibility['mode']][$compatibility['script']] = $id;
109
        }
110
111 49
        foreach ($listeners as $eventName => $method) {
112 49
            $this->providerListeners[$id][] = new ProviderListner($eventName, $provider, $method);
113
        }
114 49
        $this->providerInterfaces[$provider] = $interface;
115 49
        $this->providerById[$id] = $provider;
116 49
    }
117
118
    /**
119
     * Checl of a provider is compatible
120
     *
121
     * @param string $provider
122
     * @param string $title
123
     * @param string $mode
124
     * @param string $script
125
     *
126
     * @return bool
127
     */
128 1
    public function isProviderCompatible($provider, $title, $mode, $script)
129
    {
130 1
        return !is_null($this->getCompatibleProviderId($provider, $title, $mode, $script));
131
    }
132
133
    /**
134
     * @param string $provider
135
     * @param string $title
136
     * @param string $mode
137
     * @param string $script
138
     *
139
     * @return string|null
140
     */
141 4
    public function getCompatibleProviderId($provider, $title, $mode, $script)
142
    {
143
        $parameters = [
144 4
            [$provider, $title, $mode, $script],
145 4
            [$provider, $title, $mode, self::COMPATIBLE_ALL],
146 4
            [$provider, $title, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
147 4
            [$provider, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
148
        ];
149
150 4
        foreach ($parameters as $parameter) {
151 4
            $id = AssociativeArray::getFromKey($this->providersByCompatibility, $parameter);
152 4
            if (!is_null($id)) {
153 4
                return $id;
154
            }
155
        }
156
157 2
        return null;
158
    }
159
160
    /**
161
     * Register a plugin to the DataProviders.
162
     *
163
     * @param string $provider The provider to register the plugin to.
164
     * @param string $pluginId The id of the plugin to be registered.
165
     * @param string $title The title to register it for.
166
     * @param string $mode The mode to register it for.
167
     * @param string $script The script to register it for.
168
     *
169
     * @throws UncompatibleException
170
     */
171 2
    public function registerPlugin($provider, $pluginId, $title, $mode, $script)
172
    {
173 2
        $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script);
174
        /** @var AbstractDataProvider $providerService */
175 2
        $providerService = $this->container->get($providerId);
176 2
        $pluginService = $this->container->get($pluginId);
177 2
        $interface = $this->providerInterfaces[$provider];
178
179 2
        if ($pluginService instanceof $interface) {
180 1
            $this->deletePlugin($provider, $pluginId);
181 1
            $providerService->registerPlugin($pluginId, $pluginService);
182
        } else {
183 1
            throw new UncompatibleException("Plugin $pluginId isn't compatible with $provider. Should be instance of $interface");
184
        }
185
186 1
        $this->console->getConsoleOutput()->writeln("\t<info>- $provider : $providerId</info>");
187 1
    }
188
189
    /**
190
     * Provider to delete a plugin from.
191
     *
192
     * @param $provider
193
     * @param $pluginId
194
     *
195
     */
196 1
    public function deletePlugin($provider, $pluginId)
197
    {
198 1
        foreach ($this->providersByCompatibility[$provider] as $titleProviders) {
199 1
            foreach ($titleProviders as $modeProviders) {
200 1
                foreach ($modeProviders as $providerId) {
201 1
                    $providerService = $this->container->get($providerId);
202 1
                    $providerService->deletePlugin($pluginId);
203
                }
204
            }
205
        }
206 1
    }
207
208
    /**
209
     * Dispatch event to the data providers.
210
     *
211
     * @param $eventName
212
     * @param $params
213
     */
214 1
    public function dispatch($eventName, $params)
215
    {
216 1
        if (isset($this->enabledProviderListeners[$eventName])) {
217 1
            foreach ($this->enabledProviderListeners[$eventName] as $callback) {
218 1
                call_user_func_array($callback, $params);
219
            }
220
        }
221 1
    }
222
}
223