Completed
Push — master ( 12202a...642001 )
by Tim
01:48
created

Modules   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 283
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 283
rs 8.2608
wmc 40
lcom 1
cbo 7

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A initialize() 0 6 1
A addRequiredApacheModule() 0 6 2
A addRequiredPhpModule() 0 6 2
A setRequiredApacheModules() 0 18 4
B setRequiredPhpModules() 0 22 4
B setRequiredSspModules() 0 20 7
A getAvailableApacheModules() 0 5 1
A getAvailablePhpModules() 0 5 1
A getRequiredModules() 0 4 1
A getModuleDependencies() 0 4 1
C invokeTestSuite() 0 47 10
B testRequirement() 0 25 5

How to fix   Complexity   

Complex Class

Complex classes like Modules often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Modules, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SimpleSAML\Module\monitor\TestSuite;
4
5
use \SimpleSAML\Module\monitor\TestConfiguration as TestConfiguration;
6
use \SimpleSAML\Module\monitor\State as State;
7
use \SimpleSAML\Module\monitor\TestData as TestData;
8
9
final class Modules extends \SimpleSAML\Module\monitor\TestSuiteFactory
10
{
11
    /**
12
     * @var array
13
     */
14
    private $requiredApacheModules = array();
15
16
    /**
17
     * @var array
18
     */
19
    private $requiredPhpModules = array();
20
21
    /**
22
     * @var array
23
     */
24
    // Important!!  Modules-names are handled case-sensitive!!
25
    private $storeApacheDependencies = array();
26
27
    /**
28
     * @var array
29
     */
30
    private $storePhpDependencies = array(
31
        'memcache' => 'memcached|memcache',
32
        'phpsession' => 'session',
33
        'redis' => 'redis',
34
        'redissentinel' => 'redis',
35
        'riak:Store' => 'riak',
36
        'sql' => 'PDO'
37
    );
38
39
    /**
40
     * @var array
41
     */
42
    private $moduleApacheDependencies = array(
43
        'negotiateext' => 'mod_auth_kerb|mod_auth_gssapi'
44
    );
45
46
    /**
47
     * @var array
48
     */
49
    private $modulePhpDependencies = array(
50
        'authfacebook' => array('curl', 'json'),
51
        'authYubiKey' => 'curl',
52
// TODO: consent only requires pdo when database backend is used.. Should probably add this to required-list when processing metadata
53
//        'consent' => 'PDO',
54
        'consentAdmin' => 'PDO',
55
        'ldap' => 'ldap',
56
        'memcacheMonitor' => 'memcached|memcache',
57
        'negotiate' => 'krb5',
58
        'radius' => 'radius',
59
        'riak' => 'riak',
60
        'sqlauth' => 'PDO'
61
    );
62
63
    /**
64
     * @param TestConfiguration|null $configuration
65
     */
66
    public function __construct($configuration = null)
67
    {
68
        parent::__construct($configuration);
69
    }
70
71
    /**
72
     * @return void
73
     */
74
    protected function initialize()
75
    {
76
        $this->setRequiredApacheModules();
77
        $this->setRequiredPhpModules();
78
        $this->setRequiredSspModules();
79
    }
80
81
    /**
82
     * @return void
83
     */
84
    private function addRequiredApacheModule($module)
85
    {
86
        if (!in_array($module, $this->requiredApacheModules)) {
87
            $this->requiredApacheModules[] = $module;
88
        }
89
    }
90
91
    /**
92
     * @return void
93
     */
94
    private function addRequiredPhpModule($module)
95
    {
96
        if (!in_array($module, $this->requiredPhpModules)) {
97
            $this->requiredPhpModules[] = $module;
98
        }
99
    }
100
101
    /**
102
     * @return void
103
     */
104
    private function setRequiredApacheModules()
105
    {
106
        // Apache Modules
107
        if (\SimpleSAML\Utils\HTTP::isHTTPS()) {
108
            $this->addRequiredApacheModule('mod_ssl');
109
        }
110
        if (function_exists('apache_get_modules')) {
111
            $this->addRequiredApacheModule('mod_php|mod_php5');
112
        }
113
114
        // Determine extra required modules
115
        $configuration = $this->getConfiguration();
116
        $globalConfig = $configuration->getGlobalConfig();
117
        $store = $globalConfig->getValue('store.type');
118
        if (array_key_exists($store, $this->storeApacheDependencies)) {
119
            $this->addRequiredApacheModule($this->storeApacheDependencies[$store]);
120
        }
121
    }
122
123
    /**
124
     * @return void
125
     */
126
    private function setRequiredPhpModules()
127
    {
128
        // PHP modules
129
        $composerFile = \SimpleSAML\Utils\System::resolvePath('composer.json');
130
        $composerData = file_get_contents($composerFile);
131
        $composer = json_decode($composerData, true);
132
        $composerRequired = $composer['require'];
133
134
        foreach ($composerRequired as $ext => $ver) {
135
            if (preg_match('/^ext-/', $ext)) {
136
                $this->addRequiredPhpModule(substr($ext, 4));
137
            }
138
        }
139
140
        // Determine extra required modules
141
        $configuration = $this->getConfiguration();
142
        $globalConfig = $configuration->getGlobalConfig();
143
        $store = $globalConfig->getValue('store.type');
144
        if (array_key_exists($store, $this->storePhpDependencies)) {
145
            $this->addRequiredPhpModule($this->storePhpDependencies[$store]);
146
        }
147
    }
148
149
    /**
150
     * @return void
151
     */
152
    private function setRequiredSspModules()
153
    {
154
        $modules = \SimpleSAML\Module::getModules();
155
        foreach ($modules as $module) {
156
            if (\SimpleSAML\Module::isModuleEnabled($module)) {
157
                if (array_key_exists($module, $this->moduleApacheDependencies)) {
158
                    $dependencies = \SimpleSAML\Utils\Arrays::Arrayize($this->moduleApacheDependencies[$module]);
159
                    foreach ($dependencies as $dependency) {
160
                        $this->addRequiredApacheModule($dependency);
161
                    }
162
                }
163
                if (array_key_exists($module, $this->modulePhpDependencies)) {
164
                    $dependencies = \SimpleSAML\Utils\Arrays::Arrayize($this->modulePhpDependencies[$module]);
165
                    foreach ($dependencies as $dependency) {
166
                        $this->addRequiredPhpModule($dependency);
167
                    }
168
                }
169
            }
170
        }
171
    }
172
173
    /**
174
     * @return string[]
175
     */
176
    public function getAvailableApacheModules()
177
    {
178
        $configuration = $this->getConfiguration();
179
        return $configuration->getAvailableApacheModules();
180
    }
181
182
    /**
183
     * @return string[]
184
     */
185
    public function getAvailablePhpModules()
186
    {
187
        $configuration = $this->getConfiguration();
188
        return $configuration->getAvailablePhpModules();
189
    }
190
191
    /**
192
     * @return array<string,array>
193
     */
194
    private function getRequiredModules()
195
    {
196
        return array('Apache' => $this->requiredApacheModules, 'Php' => $this->requiredPhpModules);
197
    }
198
199
    /**
200
     * @return array<string,array>
201
     */
202
    private function getModuleDependencies()
203
    {
204
        return array('Apache' => $this->moduleApacheDependencies, 'Php' => $this->modulePhpDependencies);
205
    }
206
207
    /**
208
     * @return void
209
     */
210
    protected function invokeTestSuite()
211
    {
212
        $configuration = $this->getConfiguration();
213
        $availableModules = array('Apache' => $configuration->getAvailableApacheModules(), 'Php' => $configuration->getAvailablePhpModules());
214
215
        $requiredModules = $this->getRequiredModules();
216
        $moduleDependencies = $this->getModuleDependencies();
217
        $output = array();
218
219
        // Test for the availability of required modules
220
        foreach ($availableModules as $category => $available) {
221
            if (is_null($available)) {
222
                $output[$category][] = array(State::SKIPPED, $category, implode(', ', $requiredModules[$category]), 'Unable to verify installed modules');
223
            } else {
224
                $dependencies = array_key_exists($category, $moduleDependencies) ? $moduleDependencies[$category] : array();
225
                $required = array_key_exists($category, $requiredModules) ? $requiredModules[$category] : array();
226
                $available = array_key_exists($category, $availableModules) ? $availableModules[$category] : array();
227
228
                foreach ($required as $require) {
229
                    $testData = new TestData(
230
                        array(
231
                            'require' => $require,
232
                            'available' => $available
233
                        )
234
                    );
235
                    $this->testRequirement($testData, $category, $dependencies, $output);
236
                }
237
            }
238
        }
239
240
        $tests = $this->getTests();
241
        foreach ($availableModules as $category => $available) {
242
            $categories = array_fill(0, count($tests), $category);
243
            if (!isSet($output[$category])) {
244
                $modules = array_map(
245
                  function($test, $category) {
246
                    return ($test->getCategory() === $category) ? $test->getModuleName() : false;
247
                  }, $tests, $categories
248
                );
249
                $modules = array_diff($modules, array(false));
250
                $output[$category][] = array(State::OK, $category, implode(', ', $modules), "All required modules are loaded");
251
            }
252
            $this->addMessages($output[$category], $category);
253
        }
254
255
        $this->calculateState();
256
    }
257
258
    /**
259
     * @param TestData $testData
260
     * @param string $category
261
     * @param array $dependencies
262
     * @param array $output
263
     *
264
     * @return void
265
     */
266
    private function testRequirement($testData, $category, $dependencies, &$output)
267
    {
268
        $require = $testData->getInput('require');
269
        $class = '\\SimpleSAML\\Module\\monitor\\TestCase\\Module\\' . $category;
270
271
        $test = new $class($this, $testData);
272
        $this->addTest($test);
273
274
        $state = $test->getState();
275
        if ($state !== State::OK) {
276
            $missing = array();
277
            while ($dependency = array_search($require, $dependencies)) {
278
                if (\SimpleSAML\Module::isModuleEnabled($dependency)) {
279
                    $missing[] = $dependency;
280
                }
281
                unset($dependencies[$dependency]);
282
            }
283
        }
284
285
        if (!empty($missing)) {
286
            $output[$category][] = array($state, $category, $test->getModuleName(), 'Module not loaded; dependency for ' . implode(', ', $missing));
287
        } else {
288
            $output[$category][] = array($state, $category, $test->getModuleName(), 'Module not loaded');
289
        }
290
    }
291
}
292