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