Completed
Push — odev ( b6090c...84a1fd )
by De Cramer
04:24 queued 01:56
created

PluginManager   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 203
Duplicated Lines 4.93 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 16.05%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 28
lcom 1
cbo 5
dl 10
loc 203
ccs 13
cts 81
cp 0.1605
rs 10
c 1
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A init() 0 8 1
C enableDisablePlugins() 0 30 7
C isPluginCompatible() 0 32 8
A enablePlugin() 3 14 4
A disablePlugin() 7 16 4
A isPluginEnabled() 0 3 1
A registerPlugin() 0 9 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 Symfony\Component\DependencyInjection\ContainerInterface;
9
10
/**
11
 * Class PluginManager handles all the plugins.
12
 *
13
 * @TODO handle gamemode change.
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
    /**
35
     * PluginManager constructor.
36
     *
37
     * @param ContainerInterface $container
38
     * @param DataProviderManager $dataProviderManager
39
     */
40 37
    public function __construct(
41
        ContainerInterface $container,
42
        PluginDescriptionFactory $pluginDescriptionFactory,
43
        DataProviderManager $dataProviderManager
44
    )
45
    {
46 37
        $this->container = $container;
47 37
        $this->pluginDescriptionFactory = $pluginDescriptionFactory;
48 37
        $this->dataProviderManager = $dataProviderManager;
49 37
    }
50
51
    /**
52
     * Initialize plugins.
53
     */
54
    public function init() {
55
        // TODO get this data from the dedicated!
56
        $title = 'TMStadium@nadeo';
57
        $mode = 'script';
58
        $script = 'TimeAttack.script.txt';
59
60
        $this->enableDisablePlugins($title, $mode, $script);
61
    }
62
63
    /**
64
     * Enable all possible plugins.
65
     *
66
     * @param string $title
67
     * @param string $mode
68
     * @param string $script
69
     */
70
    protected function enableDisablePlugins($title, $mode, $script)
71
    {
72
        $pluginsToEnable = [];
73
        $pluginsToProcess = $this->plugins;
74
75
        do {
76
            $lastEnabledPluginCount = count($pluginsToEnable);
77
            $pluginsToProcessNew = [];
78
79
            foreach ($pluginsToProcess
80
81
                     as $pluginId => $plugin) {
82
                if ($this->isPluginCompatible($plugin, $pluginsToEnable, $title, $mode, $script)) {
83
                    $pluginsToEnable[$pluginId] = $plugin;
84
                } else {
85
                    $pluginsToProcessNew[$pluginId] = $plugin;
86
                }
87
            }
88
89
            $pluginsToProcess = $pluginsToProcessNew;
90
        } while ($lastEnabledPluginCount != count($pluginsToEnable) && !empty($pluginsToProcess));
91
92
        foreach ($pluginsToEnable as $plugin) {
93
            $this->enablePlugin($plugin, $title, $mode, $script);
94
        }
95
96
        foreach ($pluginsToProcess as $plugin) {
97
            $this->disablePlugin($plugin);
98
        }
99
    }
100
101
    /**
102
     * Check if a plugin is compatible or not.
103
     *
104
     * @param PluginDescription $plugin
105
     * @param $enabledPlugins
106
     * @param $title
107
     * @param $mode
108
     * @param $script
109
     *
110
     * @return bool
111
     */
112
    protected function isPluginCompatible(PluginDescription $plugin, $enabledPlugins, $title, $mode, $script) {
113
114
        // first check for other plugins.
115
        foreach ($plugin->getParents() as $parentPluginId) {
116
            if (!isset($enabledPlugins[$parentPluginId])) {
117
                // A parent plugin is missing. Can't enable plugin.
118
                return false;
119
            }
120
        }
121
122
        // Now check  for data providers.
123
        foreach ($plugin->getDataProviders() as $dataProvider) {
124
            $providerId = $this->dataProviderManager->getCompatibleProviderId($dataProvider, $title, $mode, $script);
125
126
            if (is_null($providerId) || !isset($enabledPlugins[$providerId])) {
127
                // Either there are no data providers compatible or the only one compatible
128
                return false;
129
            }
130
        }
131
132
        // If data provider need to check if it was "the chosen one".
133
        if ($plugin->isIsDataProvider()) {
134
            $selectedProvider = $this->dataProviderManager->getCompatibleProviderId($plugin->getDataProviderName(), $title, $mode, $script);
135
136
            if ($plugin->getPluginId() != $selectedProvider) {
137
                // This data provider wasn't the one selected and therefore the plugin isn't compatible.
138
                return false;
139
            }
140
        }
141
142
        return true;
143
    }
144
145
146
    /**
147
     * Enable a plugin for a certain game mode.
148
     *
149
     * @param PluginDescription $plugin
150
     * @param $title
151
     * @param $mode
152
     * @param $script
153
     */
154
    protected function enablePlugin(PluginDescription $plugin, $title, $mode, $script) {
155
        $plugin->setIsEnabled(true);
156
        $pluginService = $this->container->get($plugin->getPluginId());
157
158 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...
159
            $pluginService->setStatus(true);
160
        }
161
162
        foreach ($plugin->getDataProviders() as $provider) {
163
            $this->dataProviderManager->registerPlugin($provider, $plugin->getPluginId(), $title, $mode, $script);
164
        }
165
166
        $this->enabledPlugins[$plugin->getPluginId()] = $plugin;
167
    }
168
169
    /**
170
     * Disable a plugin.
171
     *
172
     * @param PluginDescription $plugin
173
     *
174
     */
175
    protected function disablePlugin(PluginDescription $plugin) {
176
        $plugin->setIsEnabled(false);
177
        $pluginService = $this->container->get($plugin->getPluginId());
178
179
        foreach ($plugin->getDataProviders() as $provider) {
180
            $this->dataProviderManager->deletePlugin($provider, $plugin->getPluginId());
181
        }
182
183 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...
184
            unset($this->enabledPlugins[$plugin->getPluginId()]);
185
186
            if ($pluginService instanceof StatusAwarePluginInterface) {
187
                $pluginService->setStatus(true);
188
            }
189
        }
190
    }
191
192
    /**
193
     * Check if a plugin is enabled or not.
194
     *
195
     * @param $pluginId
196
     *
197
     * @return bool
198
     */
199
    public function isPluginEnabled($pluginId) {
200
        return isset($this->enabledPlugins[$pluginId]);
201
    }
202
203
    /**
204
     * Register a plugin.
205
     *
206
     * @param string $id The service id of the plugin to register.
207
     * @param string[] $dataProviders The data providers it needs to work.
208
     * @param string[] $parents The parent plugins.
209
     */
210 37
    public function registerPlugin($id, $dataProviders, $parents, $dataProviderName = null) {
211 37
        if (!isset($this->plugins[$id])) {
212 37
            $this->plugins[$id] = $this->pluginDescriptionFactory->create($id);
213 37
        }
214
215 37
        $this->plugins[$id]->setDataProviders($dataProviders);
216 37
        $this->plugins[$id]->setParents($parents);
217 37
        $this->plugins[$id]->setDataProviderName($dataProviderName);
218 37
    }
219
}
220