Completed
Pull Request — master (#6)
by De Cramer
11:31
created

DataProviderManager   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 5
dl 0
loc 183
rs 10
c 0
b 0
f 0

8 Methods

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