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