Completed
Pull Request — master (#307)
by
unknown
04:00
created

PluginManager   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 275
Duplicated Lines 3.64 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 16.3%

Importance

Changes 0
Metric Value
dl 10
loc 275
ccs 15
cts 92
cp 0.163
rs 8.8
c 0
b 0
f 0
wmc 36
lcom 1
cbo 6

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 1
A init() 0 4 1
A reset() 0 8 1
C enableDisablePlugins() 0 43 11
C isPluginCompatible() 0 39 8
B enablePlugin() 3 21 6
B disablePlugin() 7 20 5
A isPluginEnabled() 0 4 1
A registerPlugin() 0 10 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace eXpansion\Framework\Core\Services;
4
5
use eXpansion\Framework\Core\Model\Plugin\PluginDescription;
6
use eXpansion\Framework\Core\Model\Plugin\PluginDescriptionFactory;
7
use eXpansion\Framework\Core\Plugins\StatusAwarePluginInterface;
8
use eXpansion\Framework\Core\Storage\GameDataStorage;
9
use Maniaplanet\DedicatedServer\Structures\Map;
10
use Symfony\Component\DependencyInjection\ContainerInterface;
11
12
/**
13
 * Class PluginManager handles all the plugins.
14
 *
15
 * @package eXpansion\Framework\Core\Services
16
 */
17
class PluginManager
18
{
19
    /** @var PluginDescription[] List of all the plugins adescriptions. */
20
    protected $plugins = [];
21
22
    /** @var PluginDescription[] Current List of enabled plugins */
23
    protected $enabledPlugins = [];
24
25
    /** @var PluginDescriptionFactory */
26
    protected $pluginDescriptionFactory;
27
28
    /** @var ContainerInterface */
29
    protected $container;
30
31
    /** @var DataProviderManager */
32
    protected $dataProviderManager;
33
34
    /** @var GameDataStorage */
35
    protected $gameDataStorage;
36
37
    /** @var Console */
38
    protected $console;
39
40
    /** @var string */
41
    private $env;
42
43
    /**
44
     * PluginManager constructor.
45
     *
46
     * @param ContainerInterface       $container
47
     * @param PluginDescriptionFactory $pluginDescriptionFactory
48
     * @param DataProviderManager      $dataProviderManager
49
     * @param GameDataStorage          $gameDataStorage
50
     * @param Console                  $console
51
     * @param                          $env
52
     */
53 164
    public function __construct(
54
        ContainerInterface $container,
55
        PluginDescriptionFactory $pluginDescriptionFactory,
56
        DataProviderManager $dataProviderManager,
57
        GameDataStorage $gameDataStorage,
58
        Console $console,
59
        $env
60
    ) {
61 164
        $this->container = $container;
62 164
        $this->pluginDescriptionFactory = $pluginDescriptionFactory;
63 164
        $this->dataProviderManager = $dataProviderManager;
64 164
        $this->gameDataStorage = $gameDataStorage;
65 164
        $this->console = $console;
66 164
        $this->env = $env;
67 164
    }
68
69
    /**
70
     * Initialize.
71
     *
72
     * @param Map $map
73
     * @throws \eXpansion\Framework\Core\Exceptions\DataProvider\UncompatibleException
74
     */
75
    public function init(Map $map)
76
    {
77
        $this->reset($map);
78
    }
79
80
    /**
81
     * Do a reset to plugins/
82
     *
83
     * @param Map $map
84
     * @throws \eXpansion\Framework\Core\Exceptions\DataProvider\UncompatibleException
85
     */
86
    public function reset(Map $map)
87
    {
88
        $title = $this->gameDataStorage->getTitle();
89
        $mode = $this->gameDataStorage->getGameModeCode();
90
        $script = $this->gameDataStorage->getGameInfos()->scriptName;
91
92
        $this->enableDisablePlugins($title, $mode, $script, $map);
93
    }
94
95
    /**
96
     * @param $title
97
     * @param $mode
98
     * @param $script
99
     * @param Map $map
100
     *
101
     * @throws \eXpansion\Framework\Core\Exceptions\DataProvider\UncompatibleException
102
     */
103
    protected function enableDisablePlugins($title, $mode, $script, Map $map)
104
    {
105
        $pluginsToEnable = [];
106
        $pluginsToProcess = $this->plugins;
107
108
        do {
109
            $lastEnabledPluginCount = count($pluginsToEnable);
110
            $pluginsToProcessNew = [];
111
112
            foreach ($pluginsToProcess as $pluginId => $plugin) {
113
                if ($this->isPluginCompatible($plugin, $pluginsToEnable, $title, $mode, $script, $map)) {
114
                    $pluginsToEnable[$pluginId] = $plugin;
115
                } else {
116
                    $pluginsToProcessNew[$pluginId] = $plugin;
117
                }
118
            }
119
120
            $pluginsToProcess = $pluginsToProcessNew;
121
        } while ($lastEnabledPluginCount != count($pluginsToEnable) && !empty($pluginsToProcess));
122
123
        /* Enable plugins so that the data providers are propelry connected */
124
        $enableNotify = [];
125
        foreach ($pluginsToEnable as $plugin) {
126
            $enableNotify[] = $this->enablePlugin($plugin, $title, $mode, $script, $map);
127
        }
128
129
        $disableNotify = [];
130
        foreach ($pluginsToProcess as $plugin) {
131
            $disableNotify[] = $this->disablePlugin($plugin);
132
        }
133
134
        /* Once all is connected send status update */
135
        foreach ($enableNotify as $plugin) {
136
            if (!is_null($plugin)) {
137
                $plugin->setStatus(true);
138
            }
139
        }
140
        foreach ($disableNotify as $plugin) {
141
            if (!is_null($plugin)) {
142
                $plugin->setStatus(false);
143
            }
144
        }
145
    }
146
147
    /**
148
     * Check if a plugin is compatible or not.
149
     *
150
     * @param PluginDescription $plugin
151
     * @param $enabledPlugins
152
     * @param $title
153
     * @param $mode
154
     * @param $script
155
     * @param $map
156
     *
157
     * @return bool
158
     */
159
    protected function isPluginCompatible(PluginDescription $plugin, $enabledPlugins, $title, $mode, $script, Map $map)
160
    {
161
162
        // first check for other plugins.
163
        foreach ($plugin->getParents() as $parentPluginId) {
164
            if (!isset($enabledPlugins[$parentPluginId])) {
165
                // A parent plugin is missing. Can't enable plugin.
166
                return false;
167
            }
168
        }
169
170
        // Now check for data providers.
171
        foreach ($plugin->getDataProviders() as $dataProvider) {
172
            $providerId = $this->dataProviderManager->getCompatibleProviderId($dataProvider, $title, $mode, $script, $map);
173
174
            if (is_null($providerId) || !isset($enabledPlugins[$providerId])) {
175
                // Either there are no data providers compatible or the only one compatible
176
                return false;
177
            }
178
        }
179
180
        // If data provider need to check if it was "the chosen one".
181
        if ($plugin->isIsDataProvider()) {
182
            $selectedProvider = $this->dataProviderManager->getCompatibleProviderId(
183
                $plugin->getDataProviderName(),
184
                $title,
185
                $mode,
186
                $script,
187
                $map
188
            );
189
190
            if ($plugin->getPluginId() != $selectedProvider) {
191
                // This data provider wasn't the one selected and therefore the plugin isn't compatible.
192
                return false;
193
            }
194
        }
195
196
        return true;
197
    }
198
199
    /**
200
     * Enable a certain plugin.
201
     *
202
     * @param PluginDescription $plugin
203
     * @param $title
204
     * @param $mode
205
     * @param $script
206
     * @param Map $map
207
     *
208
     * @return StatusAwarePluginInterface|null
209
     *
210
     * @throws \eXpansion\Framework\Core\Exceptions\DataProvider\UncompatibleException
211
     */
212
    protected function enablePlugin(PluginDescription $plugin, $title, $mode, $script, Map $map)
213
    {
214
        $notify = false;
215
        $plugin->setIsEnabled(true);
216
        $pluginService = $this->container->get($plugin->getPluginId());
217
218 View Code Duplication
        if ($pluginService instanceof StatusAwarePluginInterface && !isset($this->enabledPlugins[$plugin->getPluginId()])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
219
            $notify = true;
220
        }
221
        if ($this->env == 'dev') {
222
            $this->console->getConsoleOutput()
223
                ->writeln("<info>Plugin <comment>'{$plugin->getPluginId()}'</comment> data providers:</info>");
224
        }
225
        foreach ($plugin->getDataProviders() as $provider) {
226
            $this->dataProviderManager->registerPlugin($provider, $plugin->getPluginId(), $title, $mode, $script, $map);
227
        }
228
229
        $this->enabledPlugins[$plugin->getPluginId()] = $plugin;
230
231
        return $notify ? $pluginService : null;
232
    }
233
234
    /**
235
     * Disable a plugin
236
     *
237
     * @param PluginDescription $plugin
238
     *
239
     * @return StatusAwarePluginInterface|null
240
     */
241
    protected function disablePlugin(PluginDescription $plugin)
242
    {
243
        $notify = false;
244
        $plugin->setIsEnabled(false);
245
        $pluginService = $this->container->get($plugin->getPluginId());
246
247
        foreach ($plugin->getDataProviders() as $provider) {
248
            $this->dataProviderManager->deletePlugin($provider, $plugin->getPluginId());
249
        }
250
251 View Code Duplication
        if (isset($this->enabledPlugins[$plugin->getPluginId()])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
252
            unset($this->enabledPlugins[$plugin->getPluginId()]);
253
254
            if ($pluginService instanceof StatusAwarePluginInterface) {
255
                $notify = true;
256
            }
257
        }
258
259
        return $notify ? $pluginService : null;
260
    }
261
262
    /**
263
     * Check if a plugin is enabled or not.
264
     *
265
     * @param $pluginId
266
     *
267
     * @return bool
268
     */
269
    public function isPluginEnabled($pluginId)
270
    {
271
        return isset($this->enabledPlugins[$pluginId]);
272
    }
273
274
    /**
275
     * Register a plugin.
276
     *
277
     * @param string $id The service id of the plugin to register.
278
     * @param string[] $dataProviders The data providers it needs to work.
279
     * @param string[] $parents The parent plugins.
280
     */
281 164
    public function registerPlugin($id, $dataProviders, $parents, $dataProviderName = null)
282
    {
283 164
        if (!isset($this->plugins[$id])) {
284 164
            $this->plugins[$id] = $this->pluginDescriptionFactory->create($id);
285
        }
286
287 164
        $this->plugins[$id]->setDataProviders($dataProviders);
288 164
        $this->plugins[$id]->setParents($parents);
289 164
        $this->plugins[$id]->setDataProviderName($dataProviderName);
290 164
    }
291
}
292