Completed
Push — master ( abcd9a...93b1c1 )
by Tim
02:00
created

Modules::invokeTestSuite()   D

Complexity

Conditions 10
Paths 54

Size

Total Lines 46
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 30
c 1
b 0
f 0
nc 54
nop 0
dl 0
loc 46
rs 4.983

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        $availableModules = array('Apache' => $this->getAvailableApacheModules(), 'Php' => $this->getAvailablePhpModules());
213
214
        $requiredModules = $this->getRequiredModules();
215
        $moduleDependencies = $this->getModuleDependencies();
216
        $output = array();
217
218
        // Test for the availability of required modules
219
        foreach ($availableModules as $category => $available) {
220
            if (is_null($available)) {
221
                $output[$category][] = array(State::SKIPPED, $category, implode(', ', $requiredModules[$category]), 'Unable to verify installed modules');
222
            } else {
223
                $dependencies = array_key_exists($category, $moduleDependencies) ? $moduleDependencies[$category] : array();
224
                $required = array_key_exists($category, $requiredModules) ? $requiredModules[$category] : array();
225
                $available = array_key_exists($category, $availableModules) ? $availableModules[$category] : array();
226
227
                foreach ($required as $require) {
228
                    $testData = new TestData(
229
                        array(
230
                            'require' => $require,
231
                            'available' => $available
232
                        )
233
                    );
234
                    $this->testRequirement($testData, $category, $dependencies, $output);
235
                }
236
            }
237
        }
238
239
        $tests = $this->getTests();
240
        foreach ($availableModules as $category => $available) {
241
            $categories = array_fill(0, count($tests), $category);
242
            if (!isSet($output[$category])) {
243
                $modules = array_map(
244
                  function($test, $category) {
245
                    return ($test->getCategory() === $category) ? $test->getModuleName() : false;
246
                  }, $tests, $categories
247
                );
248
                $modules = array_diff($modules, array(false));
249
                $output[$category][] = array(State::OK, $category, implode(', ', $modules), "All required modules are loaded");
250
            }
251
            $this->addMessages($output[$category], $category);
252
        }
253
254
        $this->calculateState();
255
    }
256
257
    /**
258
     * @param TestData $testData
259
     * @param string $category
260
     * @param array $dependencies
261
     * @param array $output
262
     *
263
     * @return void
264
     */
265
    private function testRequirement($testData, $category, $dependencies, &$output)
266
    {
267
        $require = $testData->getInput('require');
268
        $class = '\\SimpleSAML\\Module\\monitor\\TestCase\\Module\\' . $category;
269
270
        $test = new $class($this, $testData);
271
        $this->addTest($test);
272
273
        $state = $test->getState();
274
        if ($state !== State::OK) {
275
            $missing = array();
276
            while ($dependency = array_search($require, $dependencies)) {
277
                if (\SimpleSAML\Module::isModuleEnabled($dependency)) {
278
                    $missing[] = $dependency;
279
                }
280
                unset($dependencies[$dependency]);
281
            }
282
        }
283
284
        if (!empty($missing)) {
285
            $output[$category][] = array($state, $category, $test->getModuleName(), 'Module not loaded; dependency for ' . implode(', ', $missing));
286
        } else {
287
            $output[$category][] = array($state, $category, $test->getModuleName(), 'Module not loaded');
288
        }
289
    }
290
}
291