Completed
Pull Request — master (#50)
by De Cramer
03:11
created

DataProviderManager::registerPlugin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
ccs 9
cts 9
cp 1
cc 2
eloc 9
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\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 44
    public function __construct(ContainerInterface $container)
50
    {
51 44
        $this->container = $container;
52 44
    }
53
54
    /**
55
     * Initialize all the providers properly.
56
     */
57 1
    public function init(PluginManager $pluginManager)
58
    {
59 1
        $this->reset($pluginManager);
60 1
    }
61
62 1
    public function reset(PluginManager $pluginManager)
63
    {
64
        // TODO run check in order not  to have same providers multiple times.
65
        // TODO get this data from the dedicated!
66 1
        $title = 'TMStadium@nadeo';
67 1
        $mode = 'script';
68 1
        $script = 'TimeAttack.script.txt';
69
70 1
        foreach ($this->providersByCompatibility as $provider => $data) {
71
72 1
            $providerId = $this->getCompatibleProviderId($provider, $title, $mode, $script);
73
74 1
            if ($providerId) {
75 1
                $providerService = $this->container->get($providerId);
76
77 1
                if ($pluginManager->isPluginEnabled($providerId)) {
78 1
                    foreach ($this->providerListeners[$providerId] as $listener) {
79 1
                        $this->enabledProviderListeners[$listener->getEventName()][] = [
80 1
                            $providerService,
81 1
                            $listener->getMethod()
82
                        ];
83
                    }
84
                }
85
            }
86
        }
87 1
    }
88
89
    /**
90
     * Register a provider.
91
     *
92
     * @param string $id
93
     * @param string $provider
94
     * @param string $interface
95
     * @param string[][] $compatibilities
96
     * @param string[] $listeners
97
     */
98 44
    public function registerDataProvider($id, $provider, $interface, $compatibilities, $listeners)
99
    {
100 44
        foreach ($compatibilities as $compatibility) {
101 44
            $this->providersByCompatibility[$provider][$compatibility['title']][$compatibility['mode']][$compatibility['script']] = $id;
102
        }
103
104 44
        foreach ($listeners as $eventName => $method) {
105 44
            $this->providerListeners[$id][] = new ProviderListner($eventName, $provider, $method);
106
        }
107 44
        $this->providerInterfaces[$provider] = $interface;
108 44
        $this->providerById[$id] = $provider;
109 44
    }
110
111
    /**
112
     * Checl of a provider is compatible
113
     *
114
     * @param string $provider
115
     * @param string $title
116
     * @param string $mode
117
     * @param string $script
118
     *
119
     * @return bool
120
     */
121 1
    public function isProviderCompatible($provider, $title, $mode, $script)
122
    {
123 1
        return !is_null($this->getCompatibleProviderId($provider, $title, $mode, $script));
124
    }
125
126
    /**
127
     * @param string $provider
128
     * @param string $title
129
     * @param string $mode
130
     * @param string $script
131
     *
132
     * @return string|null
133
     */
134 4
    public function getCompatibleProviderId($provider, $title, $mode, $script)
135
    {
136
        $parameters = [
137 4
            [$provider, $title, $mode, $script],
138 4
            [$provider, $title, $mode, self::COMPATIBLE_ALL],
139 4
            [$provider, $title, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
140 4
            [$provider, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL, self::COMPATIBLE_ALL],
141
        ];
142
143 4
        foreach ($parameters as $parameter) {
144 4
            $id = AssociativeArray::getFromKey($this->providersByCompatibility, $parameter);
145 4
            if (!is_null($id)) {
146 4
                return $id;
147
            }
148
        }
149
150 2
        return null;
151
    }
152
153
    /**
154
     * Register a plugin to the DataProviders.
155
     *
156
     * @param string $provider The provider to register the plugin to.
157
     * @param string $pluginId The id of the plugin to be registered.
158
     * @param string $title The title to register it for.
159
     * @param string $mode The mode to register it for.
160
     * @param string $script The script to register it for.
161
     *
162
     * @throws UncompatibleException
163
     */
164 2
    public function registerPlugin($provider, $pluginId, $title, $mode, $script)
165
    {
166
        /** @var AbstractDataProvider $providerService */
167 2
        $providerService = $this->container->get($this->getCompatibleProviderId($provider, $title, $mode, $script));
168 2
        $pluginService = $this->container->get($pluginId);
169 2
        $interface = $this->providerInterfaces[$provider];
170
171 2
        if ($pluginService instanceof $interface) {
172 1
            $this->deletePlugin($provider, $pluginId);
173 1
            $providerService->registerPlugin($pluginId, $pluginService);
174
        } else {
175 1
            throw new UncompatibleException("Plugin $pluginId isn't compatible with $provider. Should be instance of $interface");
176
        }
177 1
    }
178
179
    /**
180
     * Provider to delete a plugin from.
181
     *
182
     * @param $provider
183
     * @param $pluginId
184
     *
185
     */
186 1
    public function deletePlugin($provider, $pluginId)
187
    {
188 1
        foreach ($this->providersByCompatibility[$provider] as $titleProviders) {
189 1
            foreach ($titleProviders as $modeProviders) {
190 1
                foreach ($modeProviders as $providerId) {
191 1
                    $providerService = $this->container->get($providerId);
192 1
                    $providerService->deletePlugin($pluginId);
193
                }
194
            }
195
        }
196 1
    }
197
198
    /**
199
     * Dispatch event to the data providers.
200
     *
201
     * @param $eventName
202
     * @param $params
203
     */
204 25
    public function dispatch($eventName, $params)
205
    {
206 25
        if (isset($this->enabledProviderListeners[$eventName])) {
207 1
            foreach ($this->enabledProviderListeners[$eventName] as $callback) {
208 1
                call_user_func_array($callback, $params);
209
            }
210
        }
211 25
    }
212
}
213