1<?php
2
3namespace dokuwiki\plugin\config\core;
4
5use dokuwiki\Extension\Event;
6
7/**
8 * Configuration loader
9 *
10 * Loads configuration meta data and settings from the various files. Honors the
11 * configuration cascade and installed plugins.
12 */
13class Loader
14{
15    /** @var ConfigParser */
16    protected $parser;
17
18    /** @var string[] list of enabled plugins */
19    protected $plugins;
20    /** @var string current template */
21    protected $template;
22
23    /**
24     * Loader constructor.
25     * @param ConfigParser $parser
26     * @triggers PLUGIN_CONFIG_PLUGINLIST
27     */
28    public function __construct(ConfigParser $parser)
29    {
30        global $conf;
31        $this->parser = $parser;
32        $this->plugins = plugin_list();
33        $this->template = $conf['template'];
34        // allow plugins to remove configurable plugins
35        Event::createAndTrigger('PLUGIN_CONFIG_PLUGINLIST', $this->plugins);
36    }
37
38    /**
39     * Read the settings meta data
40     *
41     * Reads the main file, plugins and template settings meta data
42     *
43     * @return array
44     */
45    public function loadMeta()
46    {
47        // load main file
48        $meta = [];
49        include DOKU_PLUGIN . 'config/settings/config.metadata.php';
50
51        // plugins
52        foreach ($this->plugins as $plugin) {
53            $meta = array_merge(
54                $meta,
55                $this->loadExtensionMeta(
56                    DOKU_PLUGIN . $plugin . '/conf/metadata.php',
57                    'plugin',
58                    $plugin
59                )
60            );
61        }
62
63        // current template
64        $meta = array_merge(
65            $meta,
66            $this->loadExtensionMeta(
67                tpl_incdir() . '/conf/metadata.php',
68                'tpl',
69                $this->template
70            )
71        );
72
73        return $meta;
74    }
75
76    /**
77     * Read the default values
78     *
79     * Reads the main file, plugins and template defaults
80     *
81     * @return array
82     */
83    public function loadDefaults()
84    {
85
86        // initialize array
87        $conf = [];
88
89        // plugins
90        foreach ($this->plugins as $plugin) {
91            $conf = array_merge(
92                $conf,
93                $this->loadExtensionConf(
94                    DOKU_PLUGIN . $plugin . '/conf/default.php',
95                    'plugin',
96                    $plugin
97                )
98            );
99        }
100
101        // current template
102        $conf = array_merge(
103            $conf,
104            $this->loadExtensionConf(
105                tpl_incdir() . '/conf/default.php',
106                'tpl',
107                $this->template
108            )
109        );
110
111        // load main files
112        global $config_cascade;
113        return array_merge(
114            $conf,
115            $this->loadConfigs($config_cascade['main']['default'])
116        );
117    }
118
119    /**
120     * Reads the language strings
121     *
122     * Only reads extensions, main one is loaded the usual way
123     *
124     * @return array
125     */
126    public function loadLangs()
127    {
128        $lang = [];
129
130        // plugins
131        foreach ($this->plugins as $plugin) {
132            $lang = array_merge(
133                $lang,
134                $this->loadExtensionLang(
135                    DOKU_PLUGIN . $plugin . '/',
136                    'plugin',
137                    $plugin
138                )
139            );
140        }
141
142        // current template
143        $lang = array_merge(
144            $lang,
145            $this->loadExtensionLang(
146                tpl_incdir() . '/',
147                'tpl',
148                $this->template
149            )
150        );
151
152        return $lang;
153    }
154
155    /**
156     * Read the local settings
157     *
158     * @return array
159     */
160    public function loadLocal()
161    {
162        global $config_cascade;
163        return $this->loadConfigs($config_cascade['main']['local']);
164    }
165
166    /**
167     * Read the protected settings
168     *
169     * @return array
170     */
171    public function loadProtected()
172    {
173        global $config_cascade;
174        return $this->loadConfigs($config_cascade['main']['protected']);
175    }
176
177    /**
178     * Read the config values from the given files
179     *
180     * @param string[] $files paths to config php's
181     * @return array
182     */
183    protected function loadConfigs($files)
184    {
185        $conf = [];
186        foreach ($files as $file) {
187            $conf = array_merge($conf, $this->parser->parse($file));
188        }
189        return $conf;
190    }
191
192    /**
193     * Read settings file from an extension
194     *
195     * This is used to read the settings.php files of plugins and templates
196     *
197     * @param string $file php file to read
198     * @param string $type should be 'plugin' or 'tpl'
199     * @param string $extname name of the extension
200     * @return array
201     */
202    protected function loadExtensionMeta($file, $type, $extname)
203    {
204        if (!file_exists($file)) return [];
205        $prefix = $type . Configuration::KEYMARKER . $extname . Configuration::KEYMARKER;
206
207        // include file
208        $meta = [];
209        include $file;
210        if ($meta === []) return [];
211
212        // read data
213        $data = [];
214        $data[$prefix . $type . '_settings_name'] = ['fieldset'];
215        foreach ($meta as $key => $value) {
216            if (isset($value[0]) && $value[0] == 'fieldset') continue; //plugins only get one fieldset
217            $data[$prefix . $key] = $value;
218        }
219
220        return $data;
221    }
222
223    /**
224     * Read a default file from an extension
225     *
226     * This is used to read the default.php files of plugins and templates
227     *
228     * @param string $file php file to read
229     * @param string $type should be 'plugin' or 'tpl'
230     * @param string $extname name of the extension
231     * @return array
232     */
233    protected function loadExtensionConf($file, $type, $extname)
234    {
235        if (!file_exists($file)) return [];
236        $prefix = $type . Configuration::KEYMARKER . $extname . Configuration::KEYMARKER;
237
238        // parse file
239        $conf = $this->parser->parse($file);
240        if (empty($conf)) return [];
241
242        // read data
243        $data = [];
244        foreach ($conf as $key => $value) {
245            $data[$prefix . $key] = $value;
246        }
247
248        return $data;
249    }
250
251    /**
252     * Read the language file of an extension
253     *
254     * @param string $dir directory of the extension
255     * @param string $type should be 'plugin' or 'tpl'
256     * @param string $extname name of the extension
257     * @return array
258     */
259    protected function loadExtensionLang($dir, $type, $extname)
260    {
261        global $conf;
262        $ll = $conf['lang'];
263        $prefix = $type . Configuration::KEYMARKER . $extname . Configuration::KEYMARKER;
264
265        // include files
266        $lang = [];
267        if (file_exists($dir . 'lang/en/settings.php')) {
268            include $dir . 'lang/en/settings.php';
269        }
270        if ($ll != 'en' && file_exists($dir . 'lang/' . $ll . '/settings.php')) {
271            include $dir . 'lang/' . $ll . '/settings.php';
272        }
273
274        // set up correct keys
275        $strings = [];
276        foreach ($lang as $key => $val) {
277            $strings[$prefix . $key] = $val;
278        }
279
280        // add fieldset key
281        $strings[$prefix . $type . '_settings_name'] = ucwords(str_replace('_', ' ', $extname));
282
283        return $strings;
284    }
285}
286