Passed
Push — 2.x ( 28b8a0...887434 )
by Terry
01:53
created

saveCofigCheckDataDriverSqlLite()   B

Complexity

Conditions 7
Paths 40

Size

Total Lines 73
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 7
eloc 37
c 4
b 0
f 0
nc 40
nop 1
dl 0
loc 73
rs 8.3946

How to fix   Long Method   

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
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 * 
10
 * php version 7.1.0
11
 * 
12
 * @category  Web-security
13
 * @package   Shieldon
14
 * @author    Terry Lin <[email protected]>
15
 * @copyright 2019 terrylinooo
16
 * @license   https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT
17
 * @link      https://github.com/terrylinooo/shieldon
18
 * @see       https://shieldon.io
19
 */
20
21
declare(strict_types=1);
22
23
namespace Shieldon\Firewall\Panel;
24
25
use function Shieldon\Firewall\__;
26
27
use PDO;
28
use PDOException;
29
use Redis;
30
use Exception;
31
use function class_exists;
32
use function file_exists;
33
use function is_numeric;
34
use function is_string;
35
use function is_writable;
36
use function mkdir;
37
use function password_hash;
38
use function preg_split;
39
use function rtrim;
40
use function str_replace;
41
use function umask;
42
43
/*
44
 * @since 2.0.0
45
 */
46
trait ConfigMethodsTrait
47
{
48
    /**
49
     *   Public methods       | Desctiotion
50
     *  ----------------------|---------------------------------------------
51
     *                        | No public methods.
52
     *  ----------------------|---------------------------------------------
53
     */
54
55
    /**
56
     * Get a variable from configuration.
57
     *
58
     * @param string $field The field of the configuration.
59
     *
60
     * @return mixed
61
     */
62
    abstract public function getConfig(string $field);
63
64
    /**
65
     * Set a variable to the configuration.
66
     *
67
     * @param string $field The field of the configuration.
68
     * @param mixed  $value The vale of a field in the configuration.
69
     *
70
     * @return void
71
     */
72
    abstract public function setConfig(string $field, $value): void;
73
74
    /**
75
     * Response message to front.
76
     *
77
     * @param string $type The message status type. error|success
78
     * @param string $text The message body.
79
     *
80
     * @return void
81
     */
82
    abstract protected function pushMessage(string $type, string $text): void;
83
84
    /**
85
     * Parse the POST fields and set them into configuration data structure.
86
     * Used for saveConfig method only.
87
     *
88
     * @param array $postParams The PSR-7 variable of $_POST
89
     *
90
     * @return void
91
     */
92
    protected function saveConfigPrepareSettings(array $postParams): void
93
    {
94
        foreach ($postParams as $postKey => $postData) {
95
96
            if (is_string($postData)) {
97
                if ($postData === 'on') {
98
                    $this->setConfig(str_replace('__', '.', $postKey), true);
99
100
                } elseif ($postData === 'off') {
101
                    $this->setConfig(str_replace('__', '.', $postKey), false);
102
103
                } elseif ($postKey === 'ip_variable_source') {
104
                    $this->setConfig('ip_variable_source.REMOTE_ADDR', false);
105
                    $this->setConfig('ip_variable_source.HTTP_CF_CONNECTING_IP', false);
106
                    $this->setConfig('ip_variable_source.HTTP_X_FORWARDED_FOR', false);
107
                    $this->setConfig('ip_variable_source.HTTP_X_FORWARDED_HOST', false);
108
                    $this->setConfig('ip_variable_source.' . $postData, true);
109
110
                } elseif ($postKey === 'dialog_ui__shadow_opacity') {
111
                    $this->setConfig('dialog_ui.shadow_opacity', (string) $postData);
112
113
                } elseif ($postKey === 'admin__pass') {
114
                    if (strlen($postParams['admin__pass']) < 58) {
115
                        $this->setConfig('admin.pass', password_hash($postData, PASSWORD_BCRYPT));
116
                    }
117
118
                } else if (strpos($postKey, 'config__recipients') !== false) {
119
                    // For example: 
120
                    // messengers__sendgrid__config__recipients
121
                    // => messengers.sendgrid.config.recipients
122
                    $this->setConfig(
123
                        str_replace('__', '.', $postKey),
124
                        preg_split(
125
                            '/\r\n|[\r\n]/',
126
                            $postData
127
                        )
128
                    );
129
130
                } elseif (is_numeric($postData)) {
131
                    $this->setConfig(str_replace('__', '.', $postKey), (int) $postData);
132
133
                } else {
134
                    $this->setConfig(str_replace('__', '.', $postKey), $postData);
135
                }
136
            }
137
        }
138
    }
139
140
    /**
141
     * Check the settings of Action Logger.
142
     * 
143
     * @param bool $result The result passed from previous check.
144
     *
145
     * @return bool
146
     */
147
    protected function saveConfigCheckActionLogger(bool $result): bool
148
    {
149
        if (!$result) {
150
            return false;
151
        }
152
153
        // Check Action Logger settings.
154
        $enableActionLogger = $this->getConfig('loggers.action.enable');
155
156
        $actionLogDir = rtrim($this->getConfig('loggers.action.config.directory_path'), '\\/ ');
157
158
        if ($enableActionLogger) {
159
            if (empty($actionLogDir)) {
160
                $actionLogDir = $this->directory . '/action_logs';
161
            }
162
163
            $this->setConfig('loggers.action.config.directory_path', $actionLogDir);
164
165
            if (!is_dir($actionLogDir)) {
166
                // @codeCoverageIgnoreStart
167
                $originalUmask = umask(0);
168
                mkdir($actionLogDir, 0777, true);
169
                umask($originalUmask);
170
                // @codeCoverageIgnoreEnd
171
            }
172
173
            if (!is_writable($actionLogDir)) {
174
                // @codeCoverageIgnoreStart
175
                $result = false;
176
                $this->pushMessage(
177
                    'error',
178
                    __(
179
                        'panel',
180
                        'error_logger_directory_not_writable',
181
                        'Action Logger requires the storage directory writable.'
182
                    )
183
                );
184
                // @codeCoverageIgnoreEnd
185
            }
186
        }
187
188
        return $result;
189
    }
190
191
    /**
192
     * Check the settings of iptables.
193
     * 
194
     * @param bool $result The result passed from previous check.
195
     *
196
     * @return bool
197
     */
198
    protected function saveConfigCheckIptables(bool $result): bool
199
    {
200
        if (!$result) {
201
            return false;
202
        }
203
204
        // System firewall.
205
        $enableiptables = $this->getConfig('iptables.enable');
206
207
        // $iptablesWatchingFolder = rtrim($this->getConfig('iptables.config.watching_folder'), '\\/ ');
208
        $iptablesWatchingFolder = $this->directory . '/iptables';
209
        
210
        if ($enableiptables) {
211
            $this->setConfig('iptables.config.watching_folder', $iptablesWatchingFolder);
212
213
            if (!is_dir($iptablesWatchingFolder)) {
214
                // @codeCoverageIgnoreStart
215
                $originalUmask = umask(0);
216
                mkdir($iptablesWatchingFolder, 0777, true);
217
                umask($originalUmask);
218
                // @codeCoverageIgnoreEnd
219
            }
220
    
221
            // Create default log files.
222
            if (is_writable($iptablesWatchingFolder)) {
223
                fopen($iptablesWatchingFolder . '/iptables_queue.log', 'w+');
224
                fopen($iptablesWatchingFolder . '/ipv4_status.log',    'w+');
225
                fopen($iptablesWatchingFolder . '/ipv6_status.log',    'w+');
226
                fopen($iptablesWatchingFolder . '/ipv4_command.log',   'w+');
227
                fopen($iptablesWatchingFolder . '/ipv6_command.log',   'w+');
228
229
                return $result;
230
            }
231
232
            // @codeCoverageIgnoreStart
233
            $result = false;
234
235
            $this->pushMessage(
236
                'error',
237
                __(
238
                    'panel',
239
                    'error_ip6tables_directory_not_writable',
240
                    'iptables watching folder requires the storage directory writable.'
241
                )
242
            );
243
            // @codeCoverageIgnoreEnd
244
        }
245
246
        return $result;
247
    }
248
249
    /**
250
     * Check the settings of Data drivers.
251
     *
252
     * @param bool $result The result passed from previous check.
253
     *
254
     * @return bool
255
     */
256
    protected function saveConfigCheckDataDriver(bool $result): bool
257
    {
258
        if (!$result) {
259
            return false;
260
        }
261
262
        $type = $this->getConfig('driver_type');
263
264
        $methods = [
265
            'mysql'  => 'saveCofigCheckDataDriverMySql',
266
            'sqlite' => 'saveCofigCheckDataDriverSqlLite',
267
            'redis'  => 'saveCofigCheckDataDriverRedis',
268
            'file'   => 'saveCofigCheckDataDriverFile',
269
        ];
270
271
        $method = $methods[$type];
272
        $result = $this->{$method}($result);
273
274
        return $result;
275
    }
276
277
    /**
278
     * Check the settings of Data drivers.
279
     *
280
     * @param bool $result The result passed from previous check.
281
     *
282
     * @return bool
283
     */
284
    protected function saveCofigCheckDataDriverMySql(bool $result): bool
285
    {
286
        if (class_exists('PDO')) {
287
288
            $db = [
289
                'host'    => $this->getConfig('drivers.mysql.host'),
290
                'dbname'  => $this->getConfig('drivers.mysql.dbname'),
291
                'user'    => $this->getConfig('drivers.mysql.user'),
292
                'pass'    => $this->getConfig('drivers.mysql.pass'),
293
                'charset' => $this->getConfig('drivers.mysql.charset'),
294
            ];
295
296
            try {
297
                new PDO(
298
                    'mysql:host=' . $db['host'] . ';dbname=' . $db['dbname'] . ';charset=' . $db['charset'],
299
                    (string) $db['user'],
300
                    (string) $db['pass']
301
                );
302
            } catch (PDOException $e) {
303
304
                $result = false;
305
306
                $this->pushMessage(
307
                    'error', 
308
                    __(
309
                        'panel',
310
                        'error_mysql_connection',
311
                        'Cannot access to your MySQL database, please check your settings.'
312
                    )
313
                );
314
            }
315
            return $result;
316
        }
317
318
        // @codeCoverageIgnoreStart
319
320
        $result = false;
321
322
        $this->pushMessage(
323
            'error',
324
            __(
325
                'panel',
326
                'error_mysql_driver_not_supported',
327
                'Your system doesn’t support MySQL driver.'
328
            )
329
        );
330
331
        return $result;
332
333
        // @codeCoverageIgnoreEnd
334
    }
335
336
    /**
337
     * Check the settings of Data drivers.
338
     *
339
     * @param bool $result The result passed from previous check.
340
     *
341
     * @return bool
342
     */
343
    protected function saveCofigCheckDataDriverSqlLite(bool $result): bool
344
    {
345
        $fileDir = rtrim($this->getConfig('drivers.file.directory_path'), '\\/ ');
346
347
        if (empty($fileDir)) {
348
            $fileDir = $this->directory . '/data_driver_file';
349
            $this->setConfig('drivers.file.directory_path', $fileDir);
350
        }
351
352
        $this->setConfig('drivers.file.directory_path', $fileDir);
353
354
        $sqliteDir = rtrim($this->getConfig('drivers.sqlite.directory_path'), '\\/ ');
355
356
        if (empty($sqliteDir)) {
357
            $sqliteDir = $this->directory . '/data_driver_sqlite';
358
            $this->setConfig('drivers.sqlite.directory_path', $sqliteDir);
359
        }
360
361
        $sqliteFilePath = $sqliteDir . '/shieldon.sqlite3';
362
363
        if (!is_dir($sqliteDir)) {
364
            // @codeCoverageIgnoreStart
365
            $originalUmask = umask(0);
366
            mkdir($sqliteDir, 0777, true);
367
            umask($originalUmask);
368
            // @codeCoverageIgnoreEnd
369
        }
370
371
        if (class_exists('PDO')) {
372
373
            try {
374
                new PDO('sqlite:' . $sqliteFilePath);
375
376
                // @codeCoverageIgnoreStart
377
            } catch (PDOException $e) { 
378
                $this->pushMessage('error', $e->getMessage());
379
                $result = false;
380
            }
381
382
            // @codeCoverageIgnoreEnd
383
384
            if (!is_writable($sqliteFilePath)) {
385
386
                // @codeCoverageIgnoreStart
387
                $this->pushMessage(
388
                    'error',
389
                    __(
390
                        'panel',
391
                        'error_sqlite_directory_not_writable',
392
                        'SQLite data driver requires the storage directory writable.'
393
                    )
394
                );
395
                $result = false;
396
                // @codeCoverageIgnoreEnd
397
            }
398
399
            return $result;
400
        }
401
402
        // @codeCoverageIgnoreStart
403
404
        $result = false;
405
406
        $this->pushMessage(
407
            'error',
408
            __(
409
                'panel',
410
                'error_sqlite_driver_not_supported',
411
                'Your system doesn’t support SQLite driver.'
412
            )
413
        );
414
415
        return $result;
416
417
        // @codeCoverageIgnoreEnd
418
    }
419
420
    /**
421
     * Check the settings of Data drivers.
422
     *
423
     * @param bool $result The result passed from previous check.
424
     *
425
     * @return bool
426
     */
427
    protected function saveCofigCheckDataDriverRedis(bool $result): bool
428
    {
429
        if (class_exists('Redis')) {
430
431
            try {
432
                $redis = new Redis();
433
                $redis->connect(
434
                    (string) $this->getConfig('drivers.redis.host'), 
435
                    (int)    $this->getConfig('drivers.redis.port')
436
                );
437
                unset($redis);
438
439
            } catch (Exception $e) {
440
                $this->pushMessage('error', $e->getMessage());
441
                $result = false;
442
            }
443
444
            return $result;
445
        }
446
447
        // @codeCoverageIgnoreStart
448
449
        $result = false;
450
451
        $this->pushMessage(
452
            'error',
453
            __(
454
                'panel',
455
                'error_redis_driver_not_supported',
456
                'Your system doesn’t support Redis driver.'
457
            )
458
        );
459
460
        return $result;
461
462
        // @codeCoverageIgnoreEnd
463
    }
464
465
    /**
466
     * Check the settings of Data drivers.
467
     *
468
     * @param bool $result The result passed from previous check.
469
     *
470
     * @return bool
471
     */
472
    protected function saveCofigCheckDataDriverFile(bool $result): bool
473
    {
474
        $fileDir = rtrim($this->getConfig('drivers.file.directory_path'), '\\/ ');
475
476
        if (empty($fileDir)) {
477
            $fileDir = $this->directory . '/data_driver_file';
478
            $this->setConfig('drivers.file.directory_path', $fileDir);
479
        }
480
481
        $this->setConfig('drivers.file.directory_path', $fileDir);
482
483
        if (!is_dir($fileDir)) {
484
            // @codeCoverageIgnoreStart
485
            $originalUmask = umask(0);
486
            mkdir($fileDir, 0777, true);
487
            umask($originalUmask);
488
            // @codeCoverageIgnoreEnd
489
        }
490
491
        if (!is_writable($fileDir)) {
492
            // @codeCoverageIgnoreStart
493
            $result = false;
494
            $this->pushMessage(
495
                'error',
496
                __(
497
                    'panel',
498
                    'error_file_directory_not_writable',
499
                    'File data driver requires the storage directory writable.'
500
                )
501
            );
502
            // @codeCoverageIgnoreEnd
503
        }
504
505
        return $result;
506
    }
507
}
508