Passed
Push — master ( 3f508b...939a62 )
by El
05:26
created

Configuration::__construct()   D

Complexity

Conditions 27
Paths 111

Size

Total Lines 108
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 59
CRAP Score 27

Importance

Changes 0
Metric Value
cc 27
eloc 67
nc 111
nop 0
dl 0
loc 108
ccs 59
cts 59
cp 1
crap 27
rs 4.3724
c 0
b 0
f 0

How to fix   Long Method    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
 * PrivateBin
4
 *
5
 * a zero-knowledge paste bin
6
 *
7
 * @link      https://github.com/PrivateBin/PrivateBin
8
 * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
9
 * @license   https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
10
 * @version   1.1.1
11
 */
12
13
namespace PrivateBin;
14
15
use Exception;
16
use PDO;
17
use PrivateBin\Persistence\DataStore;
0 ignored issues
show
Bug introduced by El RIDO
The type PrivateBin\Persistence\DataStore was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
19
/**
20
 * Configuration
21
 *
22
 * parses configuration file, ensures default values present
23
 */
24
class Configuration
25
{
26
    /**
27
     * parsed configuration
28
     *
29
     * @var array
30
     */
31
    private $_configuration;
32
33
    /**
34
     * default configuration
35
     *
36
     * @var array
37
     */
38
    private static $_defaults = array(
39
        'main' => array(
40
            'name'                     => 'PrivateBin',
41
            'discussion'               => true,
42
            'opendiscussion'           => false,
43
            'password'                 => true,
44
            'fileupload'               => false,
45
            'burnafterreadingselected' => false,
46
            'instantburnafterreading'  => false,
47
            'defaultformatter'         => 'plaintext',
48
            'syntaxhighlightingtheme'  => null,
49
            'sizelimit'                => 2097152,
50
            'template'                 => 'bootstrap',
51
            'notice'                   => '',
52
            'languageselection'        => false,
53
            'languagedefault'          => '',
54
            'urlshortener'             => '',
55
            'qrcode'                   => true,
56
            'icon'                     => 'identicon',
57
            'cspheader'                => 'default-src \'none\'; manifest-src \'self\'; connect-src *; form-action \'none\'; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups',
58
            'zerobincompatibility'     => false,
59
        ),
60
        'expire' => array(
61
            'default' => '1week',
62
            'clone'   => true,
63
        ),
64
        'expire_options' => array(
65
            '5min'   => 300,
66
            '10min'  => 600,
67
            '1hour'  => 3600,
68
            '1day'   => 86400,
69
            '1week'  => 604800,
70
            '1month' => 2592000,
71
            '1year'  => 31536000,
72
            'never'  => 0,
73
        ),
74
        'formatter_options' => array(
75
            'plaintext'          => 'Plain Text',
76
            'syntaxhighlighting' => 'Source Code',
77
            'markdown'           => 'Markdown',
78
        ),
79
        'traffic' => array(
80
            'limit'  => 10,
81
            'header' => null,
82
            'dir'    => 'data',
83
        ),
84
        'purge' => array(
85
            'limit'     => 300,
86
            'batchsize' => 10,
87
            'dir'       => 'data',
88
        ),
89
        'model' => array(
90
            'class' => 'Filesystem',
91
        ),
92
        'model_options' => array(
93
            'dir' => 'data',
94
        ),
95
    );
96
97
    /**
98
     * parse configuration file and ensure default configuration values are present
99
     *
100
     * @throws Exception
101
     */
102 127
    public function __construct()
103
    {
104 127
        $config     = array();
105 127
        $configFile = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php';
106 127
        $configIni  = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini';
107
108
        // rename INI files to avoid configuration leakage
109 127
        if (is_readable($configIni)) {
110 2
            DataStore::prependRename($configIni, $configFile, ';');
111
112
            // cleanup sample, too
113 2
            $configIniSample = $configIni . '.sample';
114 2
            if (is_readable($configIniSample)) {
115 2
                DataStore::prependRename($configIniSample, PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.sample.php', ';');
116
            }
117
        }
118
119 127
        if (is_readable($configFile)) {
120 125
            $config = parse_ini_file($configFile, true);
121 125
            foreach (array('main', 'model', 'model_options') as $section) {
122 125
                if (!array_key_exists($section, $config)) {
0 ignored issues
show
Bug introduced by El RIDO
It seems like $config can also be of type false; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

122
                if (!array_key_exists($section, /** @scrutinizer ignore-type */ $config)) {
Loading history...
123 125
                    throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 2);
124
                }
125
            }
126
        }
127
128 124
        $opts = '_options';
129 124
        foreach (self::getDefaults() as $section => $values) {
130
            // fill missing sections with default values
131 124
            if (!array_key_exists($section, $config) || count($config[$section]) == 0) {
132 6
                $this->_configuration[$section] = $values;
133 6
                if (array_key_exists('dir', $this->_configuration[$section])) {
134 6
                    $this->_configuration[$section]['dir'] = PATH . $this->_configuration[$section]['dir'];
135
                }
136 6
                continue;
137
            }
138
            // provide different defaults for database model
139
            elseif (
140 118
                $section == 'model_options' && in_array(
141 118
                    $this->_configuration['model']['class'],
142 118
                    array('Database', 'privatebin_db', 'zerobin_db')
143
                )
144
            ) {
145
                $values = array(
146 60
                    'dsn' => 'sqlite:' . PATH . 'data' . DIRECTORY_SEPARATOR . 'db.sq3',
147
                    'tbl' => null,
148
                    'usr' => null,
149
                    'pwd' => null,
150
                    'opt' => array(PDO::ATTR_PERSISTENT => true),
151
                );
152
            }
153
154
            // "*_options" sections don't require all defaults to be set
155
            if (
156 118
                $section !== 'model_options' &&
157 118
                ($from = strlen($section) - strlen($opts)) >= 0 &&
158 118
                strpos($section, $opts, $from) !== false
159
            ) {
160 118
                if (is_int(current($values))) {
161 118
                    $config[$section] = array_map('intval', $config[$section]);
162
                }
163 118
                $this->_configuration[$section] = $config[$section];
164
            }
165
            // check for missing keys and set defaults if necessary
166
            else {
167 118
                foreach ($values as $key => $val) {
168 118
                    if ($key == 'dir') {
169 118
                        $val = PATH . $val;
170
                    }
171 118
                    $result = $val;
172 118
                    if (array_key_exists($key, $config[$section])) {
173 118
                        if ($val === null) {
174 3
                            $result = $config[$section][$key];
175 118
                        } elseif (is_bool($val)) {
176 118
                            $val = strtolower($config[$section][$key]);
177 118
                            if (in_array($val, array('true', 'yes', 'on'))) {
178 1
                                $result = true;
179 118
                            } elseif (in_array($val, array('false', 'no', 'off'))) {
180 1
                                $result = false;
181
                            } else {
182 118
                                $result = (bool) $config[$section][$key];
183
                            }
184 118
                        } elseif (is_int($val)) {
185 118
                            $result = (int) $config[$section][$key];
186 118
                        } elseif (is_string($val) && !empty($config[$section][$key])) {
187 118
                            $result = (string) $config[$section][$key];
188
                        }
189
                    }
190 118
                    $this->_configuration[$section][$key] = $result;
191
                }
192
            }
193
        }
194
195
        // support for old config file format, before the fork was renamed and PSR-4 introduced
196 124
        $this->_configuration['model']['class'] = str_replace(
197 124
            'zerobin_', 'privatebin_',
198 124
            $this->_configuration['model']['class']
199
        );
200
201 124
        $this->_configuration['model']['class'] = str_replace(
202 124
            array('privatebin_data', 'privatebin_db'),
203 124
            array('Filesystem', 'Database'),
204 124
            $this->_configuration['model']['class']
205
        );
206
207
        // ensure a valid expire default key is set
208 124
        if (!array_key_exists($this->_configuration['expire']['default'], $this->_configuration['expire_options'])) {
209 1
            $this->_configuration['expire']['default'] = key($this->_configuration['expire_options']);
210
        }
211 124
    }
212
213
    /**
214
     * get configuration as array
215
     *
216
     * return array
217
     */
218 6
    public function get()
219
    {
220 6
        return $this->_configuration;
221
    }
222
223
    /**
224
     * get default configuration as array
225
     *
226
     * return array
227
     */
228 125
    public static function getDefaults()
229
    {
230 125
        return self::$_defaults;
231
    }
232
233
    /**
234
     * get a key from the configuration, typically the main section or all keys
235
     *
236
     * @param string $key
237
     * @param string $section defaults to main
238
     * @throws Exception
239
     * return mixed
240
     */
241 116
    public function getKey($key, $section = 'main')
242
    {
243 116
        $options = $this->getSection($section);
244 116
        if (!array_key_exists($key, $options)) {
245 1
            throw new Exception(I18n::_('Invalid data.') . " $section / $key", 4);
246
        }
247 115
        return $this->_configuration[$section][$key];
248
    }
249
250
    /**
251
     * get a section from the configuration, must exist
252
     *
253
     * @param string $section
254
     * @throws Exception
255
     * return mixed
256
     */
257 116
    public function getSection($section)
258
    {
259 116
        if (!array_key_exists($section, $this->_configuration)) {
260 1
            throw new Exception(I18n::_('%s requires configuration section [%s] to be present in configuration file.', I18n::_($this->getKey('name')), $section), 3);
261
        }
262 116
        return $this->_configuration[$section];
263
    }
264
}
265