Failed Conditions
Push — wl-redirect-consistency ( e9fede )
by Henry
06:33 queued 03:33
created

admin_plugin_config::addLang()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Configuration Manager admin plugin
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Christopher Smith <[email protected]>
7
 * @author     Ben Coburn <[email protected]>
8
 */
9
// must be run within Dokuwiki
10
if(!defined('DOKU_INC')) die();
11
12
define('CM_KEYMARKER','____');            // used for settings with multiple dimensions of array indices
13
14
define('PLUGIN_SELF',dirname(__FILE__).'/');
15
define('PLUGIN_METADATA',PLUGIN_SELF.'settings/config.metadata.php');
16
if(!defined('DOKU_PLUGIN_IMAGES')) define('DOKU_PLUGIN_IMAGES',DOKU_BASE.'lib/plugins/config/images/');
17
18
require_once(PLUGIN_SELF.'settings/config.class.php');  // main configuration class and generic settings classes
19
require_once(PLUGIN_SELF.'settings/extra.class.php');   // settings classes specific to these settings
20
21
/**
22
 * All DokuWiki plugins to extend the admin function
23
 * need to inherit from this class
24
 */
25
class admin_plugin_config extends DokuWiki_Admin_Plugin {
26
27
    protected $_file = PLUGIN_METADATA;
28
    protected $_config = null;
29
    protected $_input = null;
30
    protected $_changed = false;          // set to true if configuration has altered
31
    protected $_error = false;
32
    protected $_session_started = false;
33
    protected $_localised_prompts = false;
34
35
    /**
36
     * @return int
37
     */
38
    public function getMenuSort() { return 100; }
39
40
    /**
41
     * handle user request
42
     */
43
    public function handle() {
44
        global $ID, $INPUT;
45
46
        if(!$this->_restore_session() || $INPUT->int('save') != 1 || !checkSecurityToken()) {
47
            $this->_close_session();
48
            return;
49
        }
50
51
        if(is_null($this->_config)) {
52
            $this->_config = new configuration($this->_file);
53
        }
54
55
        // don't go any further if the configuration is locked
56
        if($this->_config->locked) {
57
            $this->_close_session();
58
            return;
59
        }
60
61
        $this->_input = $INPUT->arr('config');
62
63
        foreach ($this->_config->setting as $key => $value){
64
            $input = isset($this->_input[$key]) ? $this->_input[$key] : null;
65
            if ($this->_config->setting[$key]->update($input)) {
66
                $this->_changed = true;
67
            }
68
            if ($this->_config->setting[$key]->error()) $this->_error = true;
69
        }
70
71
        if ($this->_changed  && !$this->_error) {
72
            $this->_config->save_settings($this->getPluginName());
73
74
            // save state & force a page reload to get the new settings to take effect
75
            $_SESSION['PLUGIN_CONFIG'] = array('state' => 'updated', 'time' => time());
76
            $this->_close_session();
77
            send_redirect(wl($ID, 'do=admin&page=config'), true, '&'));
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ')'
Loading history...
78
            exit();
79
        } elseif(!$this->_error) {
80
            $this->_config->touch_settings(); // just touch to refresh cache
81
        }
82
83
        $this->_close_session();
84
    }
85
86
    /**
87
     * output appropriate html
88
     */
89
    public function html() {
90
        $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
91
        global $lang;
92
        global $ID;
93
94
        if (is_null($this->_config)) { $this->_config = new configuration($this->_file); }
95
        $this->setupLocale(true);
96
97
        print $this->locale_xhtml('intro');
98
99
        ptln('<div id="config__manager">');
100
101
        if ($this->_config->locked)
102
            ptln('<div class="info">'.$this->getLang('locked').'</div>');
103
        elseif ($this->_error)
104
            ptln('<div class="error">'.$this->getLang('error').'</div>');
105
        elseif ($this->_changed)
106
            ptln('<div class="success">'.$this->getLang('updated').'</div>');
107
108
        // POST to script() instead of wl($ID) so config manager still works if
109
        // rewrite config is broken. Add $ID as hidden field to remember
110
        // current ID in most cases.
111
        ptln('<form action="'.script().'" method="post">');
112
        ptln('<div class="no"><input type="hidden" name="id" value="'.$ID.'" /></div>');
113
        formSecurityToken();
114
        $this->_print_h1('dokuwiki_settings', $this->getLang('_header_dokuwiki'));
115
116
        /** @var setting[] $undefined_settings */
117
        $undefined_settings = array();
118
        $in_fieldset = false;
119
        $first_plugin_fieldset = true;
120
        $first_template_fieldset = true;
121
        foreach($this->_config->setting as $setting) {
122
            if (is_a($setting, 'setting_hidden')) {
123
                // skip hidden (and undefined) settings
124
                if ($allow_debug && is_a($setting, 'setting_undefined')) {
125
                    $undefined_settings[] = $setting;
126
                } else {
127
                    continue;
128
                }
129
            } else if (is_a($setting, 'setting_fieldset')) {
130
                // config setting group
131
                if ($in_fieldset) {
132
                    ptln('  </table>');
133
                    ptln('  </div>');
134
                    ptln('  </fieldset>');
135
                } else {
136
                    $in_fieldset = true;
137
                }
138
                if ($first_plugin_fieldset && substr($setting->_key, 0, 10)=='plugin'.CM_KEYMARKER) {
139
                    $this->_print_h1('plugin_settings', $this->getLang('_header_plugin'));
140
                    $first_plugin_fieldset = false;
141
                } else if ($first_template_fieldset && substr($setting->_key, 0, 7)=='tpl'.CM_KEYMARKER) {
142
                    $this->_print_h1('template_settings', $this->getLang('_header_template'));
143
                    $first_template_fieldset = false;
144
                }
145
                ptln('  <fieldset id="'.$setting->_key.'">');
146
                ptln('  <legend>'.$setting->prompt($this).'</legend>');
147
                ptln('  <div class="table">');
148
                ptln('  <table class="inline">');
149
            } else {
150
                // config settings
151
                list($label,$input) = $setting->html($this, $this->_error);
152
153
                $class = $setting->is_default() ? ' class="default"' : ($setting->is_protected() ? ' class="protected"' : '');
154
                $error = $setting->error() ? ' class="value error"' : ' class="value"';
155
                $icon = $setting->caution() ? '<img src="'.DOKU_PLUGIN_IMAGES.$setting->caution().'.png" alt="'.$setting->caution().'" title="'.$this->getLang($setting->caution()).'" />' : '';
156
157
                ptln('    <tr'.$class.'>');
158
                ptln('      <td class="label">');
159
                ptln('        <span class="outkey">'.$setting->_out_key(true, true).'</span>');
160
                ptln('        '.$icon.$label);
161
                ptln('      </td>');
162
                ptln('      <td'.$error.'>'.$input.'</td>');
163
                ptln('    </tr>');
164
            }
165
        }
166
167
        ptln('  </table>');
168
        ptln('  </div>');
169
        if ($in_fieldset) {
170
            ptln('  </fieldset>');
171
        }
172
173
        // show undefined settings list
174
        if ($allow_debug && !empty($undefined_settings)) {
175
            /**
176
             * Callback for sorting settings
177
             *
178
             * @param setting $a
179
             * @param setting $b
180
             * @return int if $a is lower/equal/higher than $b
181
             */
182
            function _setting_natural_comparison($a, $b) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
183
                return strnatcmp($a->_key, $b->_key);
184
            }
185
186
            usort($undefined_settings, '_setting_natural_comparison');
187
            $this->_print_h1('undefined_settings', $this->getLang('_header_undefined'));
188
            ptln('<fieldset>');
189
            ptln('<div class="table">');
190
            ptln('<table class="inline">');
191
            $undefined_setting_match = array();
192
            foreach($undefined_settings as $setting) {
193
                if (preg_match('/^(?:plugin|tpl)'.CM_KEYMARKER.'.*?'.CM_KEYMARKER.'(.*)$/', $setting->_key, $undefined_setting_match)) {
194
                    $undefined_setting_key = $undefined_setting_match[1];
195
                } else {
196
                    $undefined_setting_key = $setting->_key;
197
                }
198
                ptln('  <tr>');
199
                ptln('    <td class="label"><span title="$meta[\''.$undefined_setting_key.'\']">$'.$this->_config->_name.'[\''.$setting->_out_key().'\']</span></td>');
200
                ptln('    <td>'.$this->getLang('_msg_'.get_class($setting)).'</td>');
201
                ptln('  </tr>');
202
            }
203
            ptln('</table>');
204
            ptln('</div>');
205
            ptln('</fieldset>');
206
        }
207
208
        // finish up form
209
        ptln('<p>');
210
        ptln('  <input type="hidden" name="do"     value="admin" />');
211
        ptln('  <input type="hidden" name="page"   value="config" />');
212
213
        if (!$this->_config->locked) {
214
            ptln('  <input type="hidden" name="save"   value="1" />');
215
            ptln('  <button type="submit" name="submit" accesskey="s">'.$lang['btn_save'].'</button>');
216
            ptln('  <button type="reset">'.$lang['btn_reset'].'</button>');
217
        }
218
219
        ptln('</p>');
220
221
        ptln('</form>');
222
        ptln('</div>');
223
    }
224
225
    /**
226
     * @return boolean   true - proceed with handle, false - don't proceed
227
     */
228
    protected function _restore_session() {
229
230
        // dokuwiki closes the session before act_dispatch. $_SESSION variables are all set,
231
        // however they can't be changed without starting the session again
232
        if (!headers_sent()) {
233
            session_start();
234
            $this->_session_started = true;
235
        }
236
237
        if (!isset($_SESSION['PLUGIN_CONFIG'])) return true;
238
239
        $session = $_SESSION['PLUGIN_CONFIG'];
240
        unset($_SESSION['PLUGIN_CONFIG']);
241
242
        // still valid?
243
        if (time() - $session['time'] > 120) return true;
244
245
        switch ($session['state']) {
246
            case 'updated' :
247
                $this->_changed = true;
248
                return false;
249
        }
250
251
        return true;
252
    }
253
254
    protected function _close_session() {
255
      if ($this->_session_started) session_write_close();
256
    }
257
258
    /**
259
     * @param bool $prompts
260
     */
261
    public function setupLocale($prompts=false) {
262
263
        parent::setupLocale();
264
        if (!$prompts || $this->_localised_prompts) return;
265
266
        $this->_setup_localised_plugin_prompts();
267
        $this->_localised_prompts = true;
268
269
    }
270
271
    /**
272
     * @return bool
273
     */
274
    protected function _setup_localised_plugin_prompts() {
275
        global $conf;
276
277
        $langfile   = '/lang/'.$conf['lang'].'/settings.php';
278
        $enlangfile = '/lang/en/settings.php';
279
280
        if ($dh = opendir(DOKU_PLUGIN)) {
281
            while (false !== ($plugin = readdir($dh))) {
282
                if ($plugin == '.' || $plugin == '..' || $plugin == 'tmp' || $plugin == 'config') continue;
283
                if (is_file(DOKU_PLUGIN.$plugin)) continue;
284
285
                if (file_exists(DOKU_PLUGIN.$plugin.$enlangfile)){
286
                    $lang = array();
287
                    @include(DOKU_PLUGIN.$plugin.$enlangfile);
288
                    if ($conf['lang'] != 'en') @include(DOKU_PLUGIN.$plugin.$langfile);
289
                    foreach ($lang as $key => $value){
290
                        $this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.$key] = $value;
291
                    }
292
                }
293
294
                // fill in the plugin name if missing (should exist for plugins with settings)
295
                if (!isset($this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'])) {
296
                    $this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'] =
297
                      ucwords(str_replace('_', ' ', $plugin));
298
                }
299
            }
300
            closedir($dh);
301
      }
302
303
        // the same for the active template
304
        $tpl = $conf['template'];
305
306
        if (file_exists(tpl_incdir().$enlangfile)){
307
            $lang = array();
308
            @include(tpl_incdir().$enlangfile);
309
            if ($conf['lang'] != 'en') @include(tpl_incdir().$langfile);
310
            foreach ($lang as $key => $value){
311
                $this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.$key] = $value;
312
            }
313
        }
314
315
        // fill in the template name if missing (should exist for templates with settings)
316
        if (!isset($this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'])) {
317
            $this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'] =
318
              ucwords(str_replace('_', ' ', $tpl));
319
        }
320
321
        return true;
322
    }
323
324
    /**
325
     * Generates a two-level table of contents for the config plugin.
326
     *
327
     * @author Ben Coburn <[email protected]>
328
     *
329
     * @return array
330
     */
331
    public function getTOC() {
332
        if (is_null($this->_config)) { $this->_config = new configuration($this->_file); }
333
        $this->setupLocale(true);
334
335
        $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
336
337
        // gather toc data
338
        $has_undefined = false;
339
        $toc = array('conf'=>array(), 'plugin'=>array(), 'template'=>null);
340
        foreach($this->_config->setting as $setting) {
341
            if (is_a($setting, 'setting_fieldset')) {
342
                if (substr($setting->_key, 0, 10)=='plugin'.CM_KEYMARKER) {
343
                    $toc['plugin'][] = $setting;
344
                } else if (substr($setting->_key, 0, 7)=='tpl'.CM_KEYMARKER) {
345
                    $toc['template'] = $setting;
346
                } else {
347
                    $toc['conf'][] = $setting;
348
                }
349
            } else if (!$has_undefined && is_a($setting, 'setting_undefined')) {
350
                $has_undefined = true;
351
            }
352
        }
353
354
        // build toc
355
        $t = array();
356
357
        $check = false;
358
        $title = $this->getLang('_configuration_manager');
359
        $t[] = html_mktocitem(sectionID($title, $check), $title, 1);
360
        $t[] = html_mktocitem('dokuwiki_settings', $this->getLang('_header_dokuwiki'), 1);
361
        /** @var setting $setting */
362
        foreach($toc['conf'] as $setting) {
363
            $name = $setting->prompt($this);
364
            $t[] = html_mktocitem($setting->_key, $name, 2);
365
        }
366
        if (!empty($toc['plugin'])) {
367
            $t[] = html_mktocitem('plugin_settings', $this->getLang('_header_plugin'), 1);
368
        }
369
        foreach($toc['plugin'] as $setting) {
370
            $name = $setting->prompt($this);
371
            $t[] = html_mktocitem($setting->_key, $name, 2);
372
        }
373
        if (isset($toc['template'])) {
374
            $t[] = html_mktocitem('template_settings', $this->getLang('_header_template'), 1);
375
            $setting = $toc['template'];
376
            $name = $setting->prompt($this);
377
            $t[] = html_mktocitem($setting->_key, $name, 2);
378
        }
379
        if ($has_undefined && $allow_debug) {
380
            $t[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1);
381
        }
382
383
        return $t;
384
    }
385
386
    /**
387
     * @param string $id
388
     * @param string $text
389
     */
390
    protected function _print_h1($id, $text) {
391
        ptln('<h1 id="'.$id.'">'.$text.'</h1>');
392
    }
393
394
    /**
395
     * Adds a translation to this plugin's language array
396
     *
397
     * @param string $key
398
     * @param string $value
399
     */
400
    public function addLang($key, $value) {
401
        if (!$this->localised) $this->setupLocale();
402
        $this->lang[$key] = $value;
403
    }
404
}
405