Failed Conditions
Push — psr2 ( 8eb28c...c68e26 )
by Andreas
28s queued 20s
created

Configuration   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 8

Importance

Changes 4
Bugs 1 Features 0
Metric Value
dl 0
loc 202
rs 10
c 4
b 1
f 0
wmc 27
lcom 2
cbo 8

12 Methods

Rating   Name   Duplication   Size   Complexity  
A touch() 0 3 1
A getLangs() 0 3 1
C initSettings() 0 23 7
A __construct() 0 11 1
A getSettings() 0 3 1
A getUndefined() 0 3 1
A hasChanged() 0 3 1
A isLocked() 0 3 1
B updateSettings() 0 13 5
A save() 0 5 1
A instantiateClass() 0 12 2
B determineClassName() 0 16 5
1
<?php
2
3
namespace dokuwiki\plugin\config\core;
4
5
use dokuwiki\plugin\config\core\Setting\Setting;
6
use dokuwiki\plugin\config\core\Setting\SettingNoClass;
7
use dokuwiki\plugin\config\core\Setting\SettingNoDefault;
8
use dokuwiki\plugin\config\core\Setting\SettingNoKnownClass;
9
use dokuwiki\plugin\config\core\Setting\SettingUndefined;
10
11
/**
12
 * Holds all the current settings and proxies the Loader and Writer
13
 *
14
 * @author Chris Smith <[email protected]>
15
 * @author Ben Coburn <[email protected]>
16
 * @author Andreas Gohr <[email protected]>
17
 */
18
class Configuration {
19
20
    const KEYMARKER = '____';
21
22
    /** @var Setting[] metadata as array of Settings objects */
23
    protected $settings = array();
24
    /** @var Setting[] undefined and problematic settings */
25
    protected $undefined = array();
26
27
    /** @var array all metadata */
28
    protected $metadata;
29
    /** @var array all default settings */
30
    protected $default;
31
    /** @var array all local settings */
32
    protected $local;
33
    /** @var array all protected settings */
34
    protected $protected;
35
36
    /** @var bool have the settings been changed since loading from disk? */
37
    protected $changed = false;
38
39
    /** @var Loader */
40
    protected $loader;
41
    /** @var Writer */
42
    protected $writer;
43
44
    /**
45
     * ConfigSettings constructor.
46
     */
47
    public function __construct() {
48
        $this->loader = new Loader(new ConfigParser());
49
        $this->writer = new Writer();
50
51
        $this->metadata = $this->loader->loadMeta();
52
        $this->default = $this->loader->loadDefaults();
53
        $this->local = $this->loader->loadLocal();
54
        $this->protected = $this->loader->loadProtected();
55
56
        $this->initSettings();
57
    }
58
59
    /**
60
     * Get all settings
61
     *
62
     * @return Setting[]
63
     */
64
    public function getSettings() {
65
        return $this->settings;
66
    }
67
68
    /**
69
     * Get all unknown or problematic settings
70
     *
71
     * @return Setting[]
72
     */
73
    public function getUndefined() {
74
        return $this->undefined;
75
    }
76
77
    /**
78
     * Have the settings been changed since loading from disk?
79
     *
80
     * @return bool
81
     */
82
    public function hasChanged() {
83
        return $this->changed;
84
    }
85
86
    /**
87
     * Check if the config can be written
88
     *
89
     * @return bool
90
     */
91
    public function isLocked() {
92
        return $this->writer->isLocked();
93
    }
94
95
    /**
96
     * Update the settings using the data provided
97
     *
98
     * @param array $input as posted
99
     * @return bool true if all updates went through, false on errors
100
     */
101
    public function updateSettings($input) {
102
        $ok = true;
103
104
        foreach($this->settings as $key => $obj) {
105
            $value = isset($input[$key]) ? $input[$key] : null;
106
            if($obj->update($value)) {
107
                $this->changed = true;
108
            }
109
            if($obj->hasError()) $ok = false;
110
        }
111
112
        return $ok;
113
    }
114
115
    /**
116
     * Save the settings
117
     *
118
     * This save the current state as defined in this object, including the
119
     * undefined settings
120
     *
121
     * @throws \Exception
122
     */
123
    public function save() {
124
        // only save the undefined settings that have not been handled in settings
125
        $undefined = array_diff_key($this->undefined, $this->settings);
126
        $this->writer->save(array_merge($this->settings, $undefined));
127
    }
128
129
    /**
130
     * Touch the settings
131
     *
132
     * @throws \Exception
133
     */
134
    public function touch() {
135
        $this->writer->touch();
136
    }
137
138
    /**
139
     * Load the extension language strings
140
     *
141
     * @return array
142
     */
143
    public function getLangs() {
144
        return $this->loader->loadLangs();
145
    }
146
147
    /**
148
     * Initalizes the $settings and $undefined properties
149
     */
150
    protected function initSettings() {
151
        $keys = array_merge(
152
            array_keys($this->metadata),
153
            array_keys($this->default),
154
            array_keys($this->local),
155
            array_keys($this->protected)
156
        );
157
        $keys = array_unique($keys);
158
159
        foreach($keys as $key) {
160
            $obj = $this->instantiateClass($key);
161
162
            if($obj->shouldHaveDefault() && !isset($this->default[$key])) {
163
                $this->undefined[$key] = new SettingNoDefault($key);
164
            }
165
166
            $d = isset($this->default[$key]) ? $this->default[$key] : null;
167
            $l = isset($this->local[$key]) ? $this->local[$key] : null;
168
            $p = isset($this->protected[$key]) ? $this->protected[$key] : null;
169
170
            $obj->initialize($d, $l, $p);
171
        }
172
    }
173
174
    /**
175
     * Instantiates the proper class for the given config key
176
     *
177
     * The class is added to the $settings or $undefined arrays and returned
178
     *
179
     * @param string $key
180
     * @return Setting
181
     */
182
    protected function instantiateClass($key) {
183
        if(isset($this->metadata[$key])) {
184
            $param = $this->metadata[$key];
185
            $class = $this->determineClassName(array_shift($param), $key); // first param is class
186
            $obj = new $class($key, $param);
187
            $this->settings[$key] = $obj;
188
        } else {
189
            $obj = new SettingUndefined($key);
190
            $this->undefined[$key] = $obj;
191
        }
192
        return $obj;
193
    }
194
195
    /**
196
     * Return the class to load
197
     *
198
     * @param string $class the class name as given in the meta file
199
     * @param string $key the settings key
200
     * @return string
201
     */
202
    protected function determineClassName($class, $key) {
203
        // try namespaced class first
204
        if(is_string($class)) {
205
            $modern = str_replace('_', '', ucwords($class, '_'));
206
            $modern = '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting' . $modern;
207
            if($modern && class_exists($modern)) return $modern;
208
            // try class as given
209
            if(class_exists($class)) return $class;
210
            // class wasn't found add to errors
211
            $this->undefined[$key] = new SettingNoKnownClass($key);
212
        } else {
213
            // no class given, add to errors
214
            $this->undefined[$key] = new SettingNoClass($key);
215
        }
216
        return '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting';
217
    }
218
219
}
220