xref: /dokuwiki/lib/plugins/config/admin.php (revision 077c27b25c8a3979615b1fd09426bce452b27423)
110449332Schris<?php
210449332Schris/**
310449332Schris * Configuration Manager admin plugin
410449332Schris *
510449332Schris * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
610449332Schris * @author     Christopher Smith <chris@jalakai.co.uk>
7685bdd2eSBen Coburn * @author     Ben Coburn <btcoburn@silicodon.net>
810449332Schris */
910449332Schris
10c6639e6aSAndreas Gohruse dokuwiki\plugin\config\core\Configuration;
11*077c27b2SAndreas Gohruse dokuwiki\plugin\config\core\Setting;
12*077c27b2SAndreas Gohruse dokuwiki\plugin\config\core\SettingFieldset;
13*077c27b2SAndreas Gohruse dokuwiki\plugin\config\core\SettingHidden;
1410449332Schris
1510449332Schris/**
1610449332Schris * All DokuWiki plugins to extend the admin function
1710449332Schris * need to inherit from this class
1810449332Schris */
1910449332Schrisclass admin_plugin_config extends DokuWiki_Admin_Plugin {
2010449332Schris
21c6639e6aSAndreas Gohr    const METADATA = __DIR__ . 'settings/config.metadata.php';
22c6639e6aSAndreas Gohr    const IMGDIR = DOKU_BASE . 'lib/plugins/config/images/';
23c6639e6aSAndreas Gohr
2461e35c35SAndreas Gohr    protected $_localised_prompts = false;
2510449332Schris
26*077c27b2SAndreas Gohr    /** @var Configuration */
27*077c27b2SAndreas Gohr    protected $configuration;
28*077c27b2SAndreas Gohr
29253d4b48SGerrit Uitslag    /**
30*077c27b2SAndreas Gohr     * admin_plugin_config constructor.
31253d4b48SGerrit Uitslag     */
32*077c27b2SAndreas Gohr    public function __construct() {
33*077c27b2SAndreas Gohr        $this->configuration = new Configuration();
34*077c27b2SAndreas Gohr    }
3510449332Schris
3610449332Schris    /**
3710449332Schris     * handle user request
3810449332Schris     */
3961e35c35SAndreas Gohr    public function handle() {
40392c9b52SHakan Sandell        global $ID, $INPUT;
4110449332Schris
42*077c27b2SAndreas Gohr        if(!$INPUT->bool('save') || !checkSecurityToken()) {
43253d4b48SGerrit Uitslag            return;
44253d4b48SGerrit Uitslag        }
4510449332Schris
4610449332Schris        // don't go any further if the configuration is locked
47*077c27b2SAndreas Gohr        if($this->configuration->isLocked()) return;
48*077c27b2SAndreas Gohr
49*077c27b2SAndreas Gohr        // update settings and redirect of successful
50*077c27b2SAndreas Gohr        $ok = $this->configuration->updateSettings($INPUT->arr('config'));
51*077c27b2SAndreas Gohr        if($ok) { // no errors
52*077c27b2SAndreas Gohr            try {
53*077c27b2SAndreas Gohr                if($this->configuration->hasChanged()) {
54*077c27b2SAndreas Gohr                    $this->configuration->save();
55*077c27b2SAndreas Gohr                } else {
56*077c27b2SAndreas Gohr                    $this->configuration->touch();
57253d4b48SGerrit Uitslag                }
58*077c27b2SAndreas Gohr                msg($this->getLang('updated'), -1);
59*077c27b2SAndreas Gohr            } catch(Exception $e) {
60*077c27b2SAndreas Gohr                msg($this->getLang('error'), -1);
6110449332Schris            }
623295f40aSAndreas Gohr            send_redirect(wl($ID, array('do' => 'admin', 'page' => 'config'), true, '&'));
6310449332Schris        }
6410449332Schris    }
6510449332Schris
6610449332Schris    /**
6710449332Schris     * output appropriate html
6810449332Schris     */
6961e35c35SAndreas Gohr    public function html() {
70685bdd2eSBen Coburn        $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
7110449332Schris        global $lang;
72400497e1Schris        global $ID;
7310449332Schris
7489d74a2fSchris        $this->setupLocale(true);
7510449332Schris
7610449332Schris        print $this->locale_xhtml('intro');
7710449332Schris
7824a33b42SAndreas Gohr        ptln('<div id="config__manager">');
7910449332Schris
80*077c27b2SAndreas Gohr        if($this->configuration->isLocked()) {
81e4a98f5cSAnika Henke            ptln('<div class="info">' . $this->getLang('locked') . '</div>');
82*077c27b2SAndreas Gohr        }
8310449332Schris
845d85efc6SAdrian Lang        // POST to script() instead of wl($ID) so config manager still works if
855d85efc6SAdrian Lang        // rewrite config is broken. Add $ID as hidden field to remember
865d85efc6SAdrian Lang        // current ID in most cases.
87f338aa80SAndreas Gohr        ptln('<form action="' . script() . '" method="post">');
88f24af591SAnika Henke        ptln('<div class="no"><input type="hidden" name="id" value="' . $ID . '" /></div>');
89634d7150SAndreas Gohr        formSecurityToken();
904fa2dffcSBen Coburn        $this->_print_h1('dokuwiki_settings', $this->getLang('_header_dokuwiki'));
9110449332Schris
924fa2dffcSBen Coburn        $in_fieldset = false;
934fa2dffcSBen Coburn        $first_plugin_fieldset = true;
944fa2dffcSBen Coburn        $first_template_fieldset = true;
95*077c27b2SAndreas Gohr        foreach($this->configuration->getSettings() as $setting) {
96*077c27b2SAndreas Gohr            if(is_a($setting, SettingHidden::class)) {
97685bdd2eSBen Coburn                continue;
98*077c27b2SAndreas Gohr            } else if(is_a($setting, settingFieldset::class)) {
994fa2dffcSBen Coburn                // config setting group
1004fa2dffcSBen Coburn                if($in_fieldset) {
1014fa2dffcSBen Coburn                    ptln('  </table>');
102e260f93bSAnika Henke                    ptln('  </div>');
1034fa2dffcSBen Coburn                    ptln('  </fieldset>');
1044fa2dffcSBen Coburn                } else {
1054fa2dffcSBen Coburn                    $in_fieldset = true;
1064fa2dffcSBen Coburn                }
107*077c27b2SAndreas Gohr                // fixme this should probably be a function in setting:
108*077c27b2SAndreas Gohr                if($first_plugin_fieldset && substr($setting->getKey(), 0, 10) == 'plugin' . Configuration::KEYMARKER) {
1094fa2dffcSBen Coburn                    $this->_print_h1('plugin_settings', $this->getLang('_header_plugin'));
1104fa2dffcSBen Coburn                    $first_plugin_fieldset = false;
111*077c27b2SAndreas Gohr                } else if($first_template_fieldset && substr($setting->getKey(), 0, 7) == 'tpl' . Configuration::KEYMARKER) {
1124fa2dffcSBen Coburn                    $this->_print_h1('template_settings', $this->getLang('_header_template'));
1134fa2dffcSBen Coburn                    $first_template_fieldset = false;
1144fa2dffcSBen Coburn                }
115*077c27b2SAndreas Gohr                ptln('  <fieldset id="' . $setting->getKey() . '">');
1164fa2dffcSBen Coburn                ptln('  <legend>' . $setting->prompt($this) . '</legend>');
117c7b28ffdSAnika Henke                ptln('  <div class="table">');
1184fa2dffcSBen Coburn                ptln('  <table class="inline">');
1194fa2dffcSBen Coburn            } else {
1204fa2dffcSBen Coburn                // config settings
12110449332Schris                list($label, $input) = $setting->html($this, $this->_error);
12210449332Schris
12364159a61SAndreas Gohr                $class = $setting->is_default()
12464159a61SAndreas Gohr                    ? ' class="default"'
12564159a61SAndreas Gohr                    : ($setting->is_protected() ? ' class="protected"' : '');
12664159a61SAndreas Gohr                $error = $setting->error()
12764159a61SAndreas Gohr                    ? ' class="value error"'
12864159a61SAndreas Gohr                    : ' class="value"';
12964159a61SAndreas Gohr                $icon = $setting->caution()
130c6639e6aSAndreas Gohr                    ? '<img src="' . self::IMGDIR . $setting->caution() . '.png" ' .
13164159a61SAndreas Gohr                    'alt="' . $setting->caution() . '" title="' . $this->getLang($setting->caution()) . '" />'
13264159a61SAndreas Gohr                    : '';
13310449332Schris
13410449332Schris                ptln('    <tr' . $class . '>');
135dde31035SAndreas Gohr                ptln('      <td class="label">');
1367ed33b2aSAnika Henke                ptln('        <span class="outkey">' . $setting->_out_key(true, true) . '</span>');
137bccdba06SAndreas Gohr                ptln('        ' . $icon . $label);
138dde31035SAndreas Gohr                ptln('      </td>');
13910449332Schris                ptln('      <td' . $error . '>' . $input . '</td>');
14010449332Schris                ptln('    </tr>');
14110449332Schris            }
1424fa2dffcSBen Coburn        }
14310449332Schris
14410449332Schris        ptln('  </table>');
145c7b28ffdSAnika Henke        ptln('  </div>');
1464fa2dffcSBen Coburn        if($in_fieldset) {
1474fa2dffcSBen Coburn            ptln('  </fieldset>');
1484fa2dffcSBen Coburn        }
14910449332Schris
150685bdd2eSBen Coburn        // show undefined settings list
151*077c27b2SAndreas Gohr        $undefined_settings = $this->configuration->getUndefined();
152685bdd2eSBen Coburn        if($allow_debug && !empty($undefined_settings)) {
153253d4b48SGerrit Uitslag            /**
154253d4b48SGerrit Uitslag             * Callback for sorting settings
155253d4b48SGerrit Uitslag             *
156*077c27b2SAndreas Gohr             * @param Setting $a
157*077c27b2SAndreas Gohr             * @param Setting $b
158253d4b48SGerrit Uitslag             * @return int if $a is lower/equal/higher than $b
159253d4b48SGerrit Uitslag             */
160253d4b48SGerrit Uitslag            function _setting_natural_comparison($a, $b) {
161*077c27b2SAndreas Gohr                return strnatcmp($a->getKey(), $b->getKey());
162253d4b48SGerrit Uitslag            }
163253d4b48SGerrit Uitslag
164685bdd2eSBen Coburn            usort($undefined_settings, '_setting_natural_comparison');
165685bdd2eSBen Coburn            $this->_print_h1('undefined_settings', $this->getLang('_header_undefined'));
166685bdd2eSBen Coburn            ptln('<fieldset>');
167c7b28ffdSAnika Henke            ptln('<div class="table">');
168685bdd2eSBen Coburn            ptln('<table class="inline">');
169685bdd2eSBen Coburn            $undefined_setting_match = array();
170685bdd2eSBen Coburn            foreach($undefined_settings as $setting) {
17164159a61SAndreas Gohr                if(
17264159a61SAndreas Gohr                preg_match(
173c6639e6aSAndreas Gohr                    '/^(?:plugin|tpl)' . Configuration::KEYMARKER . '.*?' . Configuration::KEYMARKER . '(.*)$/',
174*077c27b2SAndreas Gohr                    $setting->getKey(),
17564159a61SAndreas Gohr                    $undefined_setting_match
17664159a61SAndreas Gohr                )
17764159a61SAndreas Gohr                ) {
178685bdd2eSBen Coburn                    $undefined_setting_key = $undefined_setting_match[1];
179685bdd2eSBen Coburn                } else {
180*077c27b2SAndreas Gohr                    $undefined_setting_key = $setting->getKey();
181685bdd2eSBen Coburn                }
182685bdd2eSBen Coburn                ptln('  <tr>');
183*077c27b2SAndreas Gohr                ptln(
184*077c27b2SAndreas Gohr                    '    <td class="label"><span title="$meta[\'' . $undefined_setting_key . '\']">$' .
185*077c27b2SAndreas Gohr                    'conf' . '[\'' . $setting->_out_key() . '\']</span></td>'
186*077c27b2SAndreas Gohr                );
187685bdd2eSBen Coburn                ptln('    <td>' . $this->getLang('_msg_' . get_class($setting)) . '</td>');
188685bdd2eSBen Coburn                ptln('  </tr>');
189685bdd2eSBen Coburn            }
190685bdd2eSBen Coburn            ptln('</table>');
191c7b28ffdSAnika Henke            ptln('</div>');
192685bdd2eSBen Coburn            ptln('</fieldset>');
193685bdd2eSBen Coburn        }
194685bdd2eSBen Coburn
195685bdd2eSBen Coburn        // finish up form
19610449332Schris        ptln('<p>');
19710449332Schris        ptln('  <input type="hidden" name="do"     value="admin" />');
19810449332Schris        ptln('  <input type="hidden" name="page"   value="config" />');
19910449332Schris
200*077c27b2SAndreas Gohr        if(!$this->configuration->isLocked()) {
20110449332Schris            ptln('  <input type="hidden" name="save"   value="1" />');
202ae614416SAnika Henke            ptln('  <button type="submit" name="submit" accesskey="s">' . $lang['btn_save'] . '</button>');
203ae614416SAnika Henke            ptln('  <button type="reset">' . $lang['btn_reset'] . '</button>');
20410449332Schris        }
20510449332Schris
20610449332Schris        ptln('</p>');
20710449332Schris
20810449332Schris        ptln('</form>');
20910449332Schris        ptln('</div>');
21010449332Schris    }
21110449332Schris
21210449332Schris    /**
213253d4b48SGerrit Uitslag     * @param bool $prompts
214253d4b48SGerrit Uitslag     */
21561e35c35SAndreas Gohr    public function setupLocale($prompts = false) {
21689d74a2fSchris
21789d74a2fSchris        parent::setupLocale();
21889d74a2fSchris        if(!$prompts || $this->_localised_prompts) return;
21989d74a2fSchris
22089d74a2fSchris        $this->_setup_localised_plugin_prompts();
22189d74a2fSchris        $this->_localised_prompts = true;
22289d74a2fSchris
22389d74a2fSchris    }
22489d74a2fSchris
225253d4b48SGerrit Uitslag    /**
226253d4b48SGerrit Uitslag     * @return bool
227*077c27b2SAndreas Gohr     * @fixme this should be done by the loader
228253d4b48SGerrit Uitslag     */
22961e35c35SAndreas Gohr    protected function _setup_localised_plugin_prompts() {
23089d74a2fSchris        global $conf;
23189d74a2fSchris
232746855cfSBen Coburn        $langfile = '/lang/' . $conf['lang'] . '/settings.php';
23389d74a2fSchris        $enlangfile = '/lang/en/settings.php';
23489d74a2fSchris
23589d74a2fSchris        if($dh = opendir(DOKU_PLUGIN)) {
23689d74a2fSchris            while(false !== ($plugin = readdir($dh))) {
23789d74a2fSchris                if($plugin == '.' || $plugin == '..' || $plugin == 'tmp' || $plugin == 'config') continue;
23889d74a2fSchris                if(is_file(DOKU_PLUGIN . $plugin)) continue;
23989d74a2fSchris
24079e79377SAndreas Gohr                if(file_exists(DOKU_PLUGIN . $plugin . $enlangfile)) {
241f1f77134SEsther Brunner                    $lang = array();
24289d74a2fSchris                    @include(DOKU_PLUGIN . $plugin . $enlangfile);
24389d74a2fSchris                    if($conf['lang'] != 'en') @include(DOKU_PLUGIN . $plugin . $langfile);
244f1f77134SEsther Brunner                    foreach($lang as $key => $value) {
245c6639e6aSAndreas Gohr                        $this->lang['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . $key] = $value;
246f1f77134SEsther Brunner                    }
24789d74a2fSchris                }
2484fa2dffcSBen Coburn
2494fa2dffcSBen Coburn                // fill in the plugin name if missing (should exist for plugins with settings)
250c6639e6aSAndreas Gohr                if(!isset($this->lang['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . 'plugin_settings_name'])) {
251c6639e6aSAndreas Gohr                    $this->lang['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . 'plugin_settings_name'] =
252cd3ed83cSMatthias Schulte                        ucwords(str_replace('_', ' ', $plugin));
2534fa2dffcSBen Coburn                }
25489d74a2fSchris            }
25589d74a2fSchris            closedir($dh);
25689d74a2fSchris        }
25789d74a2fSchris
2584a778400SEsther Brunner        // the same for the active template
2594a778400SEsther Brunner        $tpl = $conf['template'];
2604a778400SEsther Brunner
26179e79377SAndreas Gohr        if(file_exists(tpl_incdir() . $enlangfile)) {
2624a778400SEsther Brunner            $lang = array();
263bc9d46afSAndreas Gohr            @include(tpl_incdir() . $enlangfile);
264bc9d46afSAndreas Gohr            if($conf['lang'] != 'en') @include(tpl_incdir() . $langfile);
2654a778400SEsther Brunner            foreach($lang as $key => $value) {
266c6639e6aSAndreas Gohr                $this->lang['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . $key] = $value;
2674a778400SEsther Brunner            }
2684a778400SEsther Brunner        }
2694a778400SEsther Brunner
2704fa2dffcSBen Coburn        // fill in the template name if missing (should exist for templates with settings)
271*077c27b2SAndreas Gohr        if(!isset($this->lang['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . 'tpl_settings_name'])) {
272*077c27b2SAndreas Gohr            $this->lang['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . 'tpl_settings_name'] =
273cd3ed83cSMatthias Schulte                ucwords(str_replace('_', ' ', $tpl));
2744fa2dffcSBen Coburn        }
2754fa2dffcSBen Coburn
27689d74a2fSchris        return true;
27789d74a2fSchris    }
27889d74a2fSchris
2794fa2dffcSBen Coburn    /**
2804fa2dffcSBen Coburn     * Generates a two-level table of contents for the config plugin.
2814fa2dffcSBen Coburn     *
2824fa2dffcSBen Coburn     * @author Ben Coburn <btcoburn@silicodon.net>
283253d4b48SGerrit Uitslag     *
284253d4b48SGerrit Uitslag     * @return array
2854fa2dffcSBen Coburn     */
28661e35c35SAndreas Gohr    public function getTOC() {
287b8595a66SAndreas Gohr        $this->setupLocale(true);
288b8595a66SAndreas Gohr
289685bdd2eSBen Coburn        $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
290685bdd2eSBen Coburn
2914fa2dffcSBen Coburn        // gather toc data
2924fa2dffcSBen Coburn        $toc = array('conf' => array(), 'plugin' => array(), 'template' => null);
293*077c27b2SAndreas Gohr        foreach($this->configuration->getSettings() as $setting) {
2944fa2dffcSBen Coburn            if(is_a($setting, 'setting_fieldset')) {
295*077c27b2SAndreas Gohr                // FIXME as above this should go into Setting class
296*077c27b2SAndreas Gohr                if(substr($setting->getKey(), 0, 10) == 'plugin' . Configuration::KEYMARKER) {
2974fa2dffcSBen Coburn                    $toc['plugin'][] = $setting;
298*077c27b2SAndreas Gohr                } else if(substr($setting->getKey(), 0, 7) == 'tpl' . Configuration::KEYMARKER) {
2994fa2dffcSBen Coburn                    $toc['template'] = $setting;
3004fa2dffcSBen Coburn                } else {
3014fa2dffcSBen Coburn                    $toc['conf'][] = $setting;
3024fa2dffcSBen Coburn                }
3034fa2dffcSBen Coburn            }
3044fa2dffcSBen Coburn        }
3054fa2dffcSBen Coburn
306e1b31a95SBen Coburn        // build toc
307b8595a66SAndreas Gohr        $t = array();
308b8595a66SAndreas Gohr
309cbfba956SMichael Hamann        $check = false;
310cbfba956SMichael Hamann        $title = $this->getLang('_configuration_manager');
311cbfba956SMichael Hamann        $t[] = html_mktocitem(sectionID($title, $check), $title, 1);
312b8595a66SAndreas Gohr        $t[] = html_mktocitem('dokuwiki_settings', $this->getLang('_header_dokuwiki'), 1);
313253d4b48SGerrit Uitslag        /** @var setting $setting */
314e1b31a95SBen Coburn        foreach($toc['conf'] as $setting) {
315e1b31a95SBen Coburn            $name = $setting->prompt($this);
316*077c27b2SAndreas Gohr            $t[] = html_mktocitem($setting->getKey(), $name, 2);
317e1b31a95SBen Coburn        }
318e1b31a95SBen Coburn        if(!empty($toc['plugin'])) {
319b8595a66SAndreas Gohr            $t[] = html_mktocitem('plugin_settings', $this->getLang('_header_plugin'), 1);
320e1b31a95SBen Coburn        }
321e1b31a95SBen Coburn        foreach($toc['plugin'] as $setting) {
322e1b31a95SBen Coburn            $name = $setting->prompt($this);
323*077c27b2SAndreas Gohr            $t[] = html_mktocitem($setting->getKey(), $name, 2);
324e1b31a95SBen Coburn        }
325e1b31a95SBen Coburn        if(isset($toc['template'])) {
326b8595a66SAndreas Gohr            $t[] = html_mktocitem('template_settings', $this->getLang('_header_template'), 1);
327e1b31a95SBen Coburn            $setting = $toc['template'];
328e1b31a95SBen Coburn            $name = $setting->prompt($this);
329*077c27b2SAndreas Gohr            $t[] = html_mktocitem($setting->getKey(), $name, 2);
330e1b31a95SBen Coburn        }
331*077c27b2SAndreas Gohr        if(count($this->configuration->getUndefined()) && $allow_debug) {
332b8595a66SAndreas Gohr            $t[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1);
333e1b31a95SBen Coburn        }
334e1b31a95SBen Coburn
335b8595a66SAndreas Gohr        return $t;
3364fa2dffcSBen Coburn    }
3374fa2dffcSBen Coburn
338253d4b48SGerrit Uitslag    /**
339253d4b48SGerrit Uitslag     * @param string $id
340253d4b48SGerrit Uitslag     * @param string $text
341253d4b48SGerrit Uitslag     */
34261e35c35SAndreas Gohr    protected function _print_h1($id, $text) {
34363e967bdSAnika Henke        ptln('<h1 id="' . $id . '">' . $text . '</h1>');
3444fa2dffcSBen Coburn    }
3454fa2dffcSBen Coburn
34661e35c35SAndreas Gohr    /**
34761e35c35SAndreas Gohr     * Adds a translation to this plugin's language array
34861e35c35SAndreas Gohr     *
34961e35c35SAndreas Gohr     * @param string $key
35061e35c35SAndreas Gohr     * @param string $value
35161e35c35SAndreas Gohr     */
35261e35c35SAndreas Gohr    public function addLang($key, $value) {
35361e35c35SAndreas Gohr        if(!$this->localised) $this->setupLocale();
35461e35c35SAndreas Gohr        $this->lang[$key] = $value;
35561e35c35SAndreas Gohr    }
35610449332Schris}
357