Completed
Pull Request — master (#50)
by De Cramer
02:53
created

PluginManager   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 213
Duplicated Lines 4.69 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 18.31%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 29
c 1
b 0
f 0
lcom 1
cbo 7
dl 10
loc 213
ccs 13
cts 71
cp 0.1831
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A init() 0 4 1
A reset() 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 eXpansion\Framework\Core\Storage\GameDataStorage;
9
use Symfony\Component\DependencyInjection\ContainerInterface;
10
11
/**
12
 * Class PluginManager handles all the plugins.
13
 *
14
 * @TODO handle gamemode change.
15
 *
16
 * @package eXpansion\Framework\Core\Services
17
 */
18
class PluginManager
19
{
20
    /** @var PluginDescription[] List of all the plugins adescriptions. */
21
    protected $plugins = [];
22
23
    /** @var PluginDescription[] Current List of enabled plugins */
24
    protected $enabledPlugins = [];
25
26
    /** @var PluginDescriptionFactory  */
27
    protected $pluginDescriptionFactory;
28
29
    /** @var ContainerInterface  */
30
    protected $container;
31
32
    /** @var DataProviderManager  */
33
    protected $dataProviderManager;
34
35
    /** @var GameDataStorage  */
36
    protected $gameDataStorage;
37
38
    /**
39
     * PluginManager constructor.
40
     *
41
     * @param ContainerInterface $container
42
     * @param DataProviderManager $dataProviderManager
43
     */
44 40
    public function __construct(
45
        ContainerInterface $container,
46
        PluginDescriptionFactory $pluginDescriptionFactory,
47
        DataProviderManager $dataProviderManager,
48
        GameDataStorage $gameDataStorage
49
    )
50
    {
51 40
        $this->container = $container;
52 40
        $this->pluginDescriptionFactory = $pluginDescriptionFactory;
53 40
        $this->dataProviderManager = $dataProviderManager;
54 40
        $this->gameDataStorage = $gameDataStorage;
55 40
    }
56
57
    /**
58
     * Initialize plugins.
59
     */
60
    public function init()
61
    {
62
        $this->reset();
63
    }
64
65
    public function reset()
66
    {
67
        // TODO get this data from the dedicated!
68
        $title = $this->gameDataStorage->getVersion();
69
        $mode = $this->gameDataStorage->getGameModeCode();
70
        $script = $this->gameDataStorage->getGameInfos()->scriptName;
71
72
        $this->enableDisablePlugins($title, $mode, $script);    }
0 ignored issues
show
Documentation introduced by
$title is of type object<Maniaplanet\Dedic...ver\Structures\Version>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
73
74
    /**
75
     * Enable all possible plugins.
76
     *
77
     * @param string $title
78
     * @param string $mode
79
     * @param string $script
80
     */
81
    protected function enableDisablePlugins($title, $mode, $script)
82
    {
83
        $pluginsToEnable = [];
84
        $pluginsToProcess = $this->plugins;
85
86
        do {
87
            $lastEnabledPluginCount = count($pluginsToEnable);
88
            $pluginsToProcessNew = [];
89
90
            foreach ($pluginsToProcess
91
92
                     as $pluginId => $plugin) {
93
                if ($this->isPluginCompatible($plugin, $pluginsToEnable, $title, $mode, $script)) {
94
                    $pluginsToEnable[$pluginId] = $plugin;
95
                } else {
96
                    $pluginsToProcessNew[$pluginId] = $plugin;
97
                }
98
            }
99
100
            $pluginsToProcess = $pluginsToProcessNew;
101
        } while ($lastEnabledPluginCount != count($pluginsToEnable) && !empty($pluginsToProcess));
102
103
        foreach ($pluginsToEnable as $plugin) {
104
            $this->enablePlugin($plugin, $title, $mode, $script);
105
        }
106
107
        foreach ($pluginsToProcess as $plugin) {
108
            $this->disablePlugin($plugin);
109
        }
110
    }
111
112
    /**
113
     * Check if a plugin is compatible or not.
114
     *
115
     * @param PluginDescription $plugin
116
     * @param $enabledPlugins
117
     * @param $title
118
     * @param $mode
119
     * @param $script
120
     *
121
     * @return bool
122
     */
123
    protected function isPluginCompatible(PluginDescription $plugin, $enabledPlugins, $title, $mode, $script) {
124
125
        // first check for other plugins.
126
        foreach ($plugin->getParents() as $parentPluginId) {
127
            if (!isset($enabledPlugins[$parentPluginId])) {
128
                // A parent plugin is missing. Can't enable plugin.
129
                return false;
130
            }
131
        }
132
133
        // Now check  for data providers.
134
        foreach ($plugin->getDataProviders() as $dataProvider) {
135
            $providerId = $this->dataProviderManager->getCompatibleProviderId($dataProvider, $title, $mode, $script);
136
137
            if (is_null($providerId) || !isset($enabledPlugins[$providerId])) {
138
                // Either there are no data providers compatible or the only one compatible
139
                return false;
140
            }
141
        }
142
143
        // If data provider need to check if it was "the chosen one".
144
        if ($plugin->isIsDataProvider()) {
145
            $selectedProvider = $this->dataProviderManager->getCompatibleProviderId($plugin->getDataProviderName(), $title, $mode, $script);
146
147
            if ($plugin->getPluginId() != $selectedProvider) {
148
                // This data provider wasn't the one selected and therefore the plugin isn't compatible.
149
                return false;
150
            }
151
        }
152
153
        return true;
154
    }
155
156
157
    /**
158
     * Enable a plugin for a certain game mode.
159
     *
160
     * @param PluginDescription $plugin
161
     * @param $title
162
     * @param $mode
163
     * @param $script
164
     */
165
    protected function enablePlugin(PluginDescription $plugin, $title, $mode, $script) {
166
        $plugin->setIsEnabled(true);
167
        $pluginService = $this->container->get($plugin->getPluginId());
168
169 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...
170
            $pluginService->setStatus(true);
171
        }
172
173
        foreach ($plugin->getDataProviders() as $provider) {
174
            $this->dataProviderManager->registerPlugin($provider, $plugin->getPluginId(), $title, $mode, $script);
175
        }
176
177
        $this->enabledPlugins[$plugin->getPluginId()] = $plugin;
178
    }
179
180
    /**
181
     * Disable a plugin.
182
     *
183
     * @param PluginDescription $plugin
184
     *
185
     */
186
    protected function disablePlugin(PluginDescription $plugin) {
187
        $plugin->setIsEnabled(false);
188
        $pluginService = $this->container->get($plugin->getPluginId());
189
190
        foreach ($plugin->getDataProviders() as $provider) {
191
            $this->dataProviderManager->deletePlugin($provider, $plugin->getPluginId());
192
        }
193
194 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...
195
            unset($this->enabledPlugins[$plugin->getPluginId()]);
196
197
            if ($pluginService instanceof StatusAwarePluginInterface) {
198
                $pluginService->setStatus(true);
199
            }
200
        }
201
    }
202
203
    /**
204
     * Check if a plugin is enabled or not.
205
     *
206
     * @param $pluginId
207
     *
208
     * @return bool
209
     */
210
    public function isPluginEnabled($pluginId) {
211
        return isset($this->enabledPlugins[$pluginId]);
212
    }
213
214
    /**
215
     * Register a plugin.
216
     *
217
     * @param string $id The service id of the plugin to register.
218
     * @param string[] $dataProviders The data providers it needs to work.
219
     * @param string[] $parents The parent plugins.
220
     */
221 40
    public function registerPlugin($id, $dataProviders, $parents, $dataProviderName = null) {
222 40
        if (!isset($this->plugins[$id])) {
223 40
            $this->plugins[$id] = $this->pluginDescriptionFactory->create($id);
224
        }
225
226 40
        $this->plugins[$id]->setDataProviders($dataProviders);
227 40
        $this->plugins[$id]->setParents($parents);
228 40
        $this->plugins[$id]->setDataProviderName($dataProviderName);
229 40
    }
230
}
231