Completed
Push — master ( fff0f0...89663a )
by De Cramer
02:26
created

DataProviderManager::init()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

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