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
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
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