admin.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <?php
  2. /**
  3. * Configuration Manager admin plugin
  4. *
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Christopher Smith <chris@jalakai.co.uk>
  7. * @author Ben Coburn <btcoburn@silicodon.net>
  8. */
  9. use dokuwiki\plugin\config\core\Configuration;
  10. use dokuwiki\plugin\config\core\Setting\Setting;
  11. use dokuwiki\plugin\config\core\Setting\SettingFieldset;
  12. use dokuwiki\plugin\config\core\Setting\SettingHidden;
  13. /**
  14. * All DokuWiki plugins to extend the admin function
  15. * need to inherit from this class
  16. */
  17. class admin_plugin_config extends DokuWiki_Admin_Plugin {
  18. const IMGDIR = DOKU_BASE . 'lib/plugins/config/images/';
  19. /** @var Configuration */
  20. protected $configuration;
  21. /** @var bool were there any errors in the submitted data? */
  22. protected $hasErrors = false;
  23. /** @var bool have the settings translations been loaded? */
  24. protected $promptsLocalized = false;
  25. /**
  26. * handle user request
  27. */
  28. public function handle() {
  29. global $ID, $INPUT;
  30. // always initialize the configuration
  31. $this->configuration = new Configuration();
  32. if(!$INPUT->bool('save') || !checkSecurityToken()) {
  33. return;
  34. }
  35. // don't go any further if the configuration is locked
  36. if($this->configuration->isLocked()) return;
  37. // update settings and redirect of successful
  38. $ok = $this->configuration->updateSettings($INPUT->arr('config'));
  39. if($ok) { // no errors
  40. try {
  41. if($this->configuration->hasChanged()) {
  42. $this->configuration->save();
  43. } else {
  44. $this->configuration->touch();
  45. }
  46. msg($this->getLang('updated'), 1);
  47. } catch(Exception $e) {
  48. msg($this->getLang('error'), -1);
  49. }
  50. send_redirect(wl($ID, array('do' => 'admin', 'page' => 'config'), true, '&'));
  51. } else {
  52. $this->hasErrors = true;
  53. }
  54. }
  55. /**
  56. * output appropriate html
  57. */
  58. public function html() {
  59. $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
  60. global $lang;
  61. global $ID;
  62. $this->setupLocale(true);
  63. echo $this->locale_xhtml('intro');
  64. echo '<div id="config__manager">';
  65. if($this->configuration->isLocked()) {
  66. echo '<div class="info">' . $this->getLang('locked') . '</div>';
  67. }
  68. // POST to script() instead of wl($ID) so config manager still works if
  69. // rewrite config is broken. Add $ID as hidden field to remember
  70. // current ID in most cases.
  71. echo '<form id="dw__configform" action="' . script() . '" method="post">';
  72. echo '<div class="no"><input type="hidden" name="id" value="' . $ID . '" /></div>';
  73. formSecurityToken();
  74. $this->printH1('dokuwiki_settings', $this->getLang('_header_dokuwiki'));
  75. $in_fieldset = false;
  76. $first_plugin_fieldset = true;
  77. $first_template_fieldset = true;
  78. foreach($this->configuration->getSettings() as $setting) {
  79. if(is_a($setting, SettingHidden::class)) {
  80. continue;
  81. } else if(is_a($setting, settingFieldset::class)) {
  82. // config setting group
  83. if($in_fieldset) {
  84. echo '</table>';
  85. echo '</div>';
  86. echo '</fieldset>';
  87. } else {
  88. $in_fieldset = true;
  89. }
  90. if($first_plugin_fieldset && $setting->getType() == 'plugin') {
  91. $this->printH1('plugin_settings', $this->getLang('_header_plugin'));
  92. $first_plugin_fieldset = false;
  93. } else if($first_template_fieldset && $setting->getType() == 'template') {
  94. $this->printH1('template_settings', $this->getLang('_header_template'));
  95. $first_template_fieldset = false;
  96. }
  97. echo '<fieldset id="' . $setting->getKey() . '">';
  98. echo '<legend>' . $setting->prompt($this) . '</legend>';
  99. echo '<div class="table">';
  100. echo '<table class="inline">';
  101. } else {
  102. // config settings
  103. list($label, $input) = $setting->html($this, $this->hasErrors);
  104. $class = $setting->isDefault()
  105. ? ' class="default"'
  106. : ($setting->isProtected() ? ' class="protected"' : '');
  107. $error = $setting->hasError()
  108. ? ' class="value error"'
  109. : ' class="value"';
  110. $icon = $setting->caution()
  111. ? '<img src="' . self::IMGDIR . $setting->caution() . '.png" ' .
  112. 'alt="' . $setting->caution() . '" title="' . $this->getLang($setting->caution()) . '" />'
  113. : '';
  114. echo '<tr' . $class . '>';
  115. echo '<td class="label">';
  116. echo '<span class="outkey">' . $setting->getPrettyKey() . '</span>';
  117. echo $icon . $label;
  118. echo '</td>';
  119. echo '<td' . $error . '>' . $input . '</td>';
  120. echo '</tr>';
  121. }
  122. }
  123. echo '</table>';
  124. echo '</div>';
  125. if($in_fieldset) {
  126. echo '</fieldset>';
  127. }
  128. // show undefined settings list
  129. $undefined_settings = $this->configuration->getUndefined();
  130. if($allow_debug && !empty($undefined_settings)) {
  131. /**
  132. * Callback for sorting settings
  133. *
  134. * @param Setting $a
  135. * @param Setting $b
  136. * @return int if $a is lower/equal/higher than $b
  137. */
  138. function settingNaturalComparison($a, $b) {
  139. return strnatcmp($a->getKey(), $b->getKey());
  140. }
  141. usort($undefined_settings, 'settingNaturalComparison');
  142. $this->printH1('undefined_settings', $this->getLang('_header_undefined'));
  143. echo '<fieldset>';
  144. echo '<div class="table">';
  145. echo '<table class="inline">';
  146. foreach($undefined_settings as $setting) {
  147. list($label, $input) = $setting->html($this);
  148. echo '<tr>';
  149. echo '<td class="label">' . $label . '</td>';
  150. echo '<td>' . $input . '</td>';
  151. echo '</tr>';
  152. }
  153. echo '</table>';
  154. echo '</div>';
  155. echo '</fieldset>';
  156. }
  157. // finish up form
  158. echo '<p>';
  159. echo '<input type="hidden" name="do" value="admin" />';
  160. echo '<input type="hidden" name="page" value="config" />';
  161. if(!$this->configuration->isLocked()) {
  162. echo '<input type="hidden" name="save" value="1" />';
  163. echo '<button type="submit" name="submit" accesskey="s">' . $lang['btn_save'] . '</button>';
  164. echo '<button type="reset">' . $lang['btn_reset'] . '</button>';
  165. }
  166. echo '</p>';
  167. echo '</form>';
  168. echo '</div>';
  169. }
  170. /**
  171. * @param bool $prompts
  172. */
  173. public function setupLocale($prompts = false) {
  174. parent::setupLocale();
  175. if(!$prompts || $this->promptsLocalized) return;
  176. $this->lang = array_merge($this->lang, $this->configuration->getLangs());
  177. $this->promptsLocalized = true;
  178. }
  179. /**
  180. * Generates a two-level table of contents for the config plugin.
  181. *
  182. * @author Ben Coburn <btcoburn@silicodon.net>
  183. *
  184. * @return array
  185. */
  186. public function getTOC() {
  187. $this->setupLocale(true);
  188. $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
  189. $toc = array();
  190. $check = false;
  191. // gather settings data into three sub arrays
  192. $labels = ['dokuwiki' => [], 'plugin' => [], 'template' => []];
  193. foreach($this->configuration->getSettings() as $setting) {
  194. if(is_a($setting, SettingFieldset::class)) {
  195. $labels[$setting->getType()][] = $setting;
  196. }
  197. }
  198. // top header
  199. $title = $this->getLang('_configuration_manager');
  200. $toc[] = html_mktocitem(sectionID($title, $check), $title, 1);
  201. // main entries
  202. foreach(['dokuwiki', 'plugin', 'template'] as $section) {
  203. if(empty($labels[$section])) continue; // no entries, skip
  204. // create main header
  205. $toc[] = html_mktocitem(
  206. $section . '_settings',
  207. $this->getLang('_header_' . $section),
  208. 1
  209. );
  210. // create sub headers
  211. foreach($labels[$section] as $setting) {
  212. /** @var SettingFieldset $setting */
  213. $name = $setting->prompt($this);
  214. $toc[] = html_mktocitem($setting->getKey(), $name, 2);
  215. }
  216. }
  217. // undefined settings if allowed
  218. if(count($this->configuration->getUndefined()) && $allow_debug) {
  219. $toc[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1);
  220. }
  221. return $toc;
  222. }
  223. /**
  224. * @param string $id
  225. * @param string $text
  226. */
  227. protected function printH1($id, $text) {
  228. echo '<h1 id="' . $id . '">' . $text . '</h1>';
  229. }
  230. /**
  231. * Adds a translation to this plugin's language array
  232. *
  233. * Used by some settings to set up dynamic translations
  234. *
  235. * @param string $key
  236. * @param string $value
  237. */
  238. public function addLang($key, $value) {
  239. if(!$this->localised) $this->setupLocale();
  240. $this->lang[$key] = $value;
  241. }
  242. }