summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/config/core/Setting
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/lib/plugins/config/core/Setting')
-rw-r--r--platform/www/lib/plugins/config/core/Setting/Setting.php294
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingArray.php105
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingAuthtype.php60
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingCompression.php21
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingDirchoice.php33
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingDisableactions.php23
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingEmail.php58
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingFieldset.php17
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingHidden.php10
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingImConvert.php28
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingLicense.php23
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingMulticheckbox.php163
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingMultichoice.php71
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingNoClass.php12
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingNoDefault.php13
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingNoKnownClass.php11
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingNumeric.php42
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingNumericopt.php25
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingOnoff.php57
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingPassword.php39
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingRegex.php34
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingRenderer.php56
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingSavedir.php26
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingSepchar.php18
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingString.php32
-rw-r--r--platform/www/lib/plugins/config/core/Setting/SettingUndefined.php40
26 files changed, 1311 insertions, 0 deletions
diff --git a/platform/www/lib/plugins/config/core/Setting/Setting.php b/platform/www/lib/plugins/config/core/Setting/Setting.php
new file mode 100644
index 0000000..d64f684
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/Setting.php
@@ -0,0 +1,294 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+use dokuwiki\plugin\config\core\Configuration;
+
+/**
+ * Class Setting
+ */
+class Setting {
+ /** @var string unique identifier of this setting */
+ protected $key = '';
+
+ /** @var mixed the default value of this setting */
+ protected $default = null;
+ /** @var mixed the local value of this setting */
+ protected $local = null;
+ /** @var mixed the protected value of this setting */
+ protected $protected = null;
+
+ /** @var array valid alerts, images matching the alerts are in the plugin's images directory */
+ static protected $validCautions = array('warning', 'danger', 'security');
+
+ protected $pattern = '';
+ protected $error = false; // only used by those classes which error check
+ protected $input = null; // only used by those classes which error check
+ protected $caution = null; // used by any setting to provide an alert along with the setting
+
+ /**
+ * Constructor.
+ *
+ * The given parameters will be set up as class properties
+ *
+ * @see initialize() to set the actual value of the setting
+ *
+ * @param string $key
+ * @param array|null $params array with metadata of setting
+ */
+ public function __construct($key, $params = null) {
+ $this->key = $key;
+
+ if(is_array($params)) {
+ foreach($params as $property => $value) {
+ $property = trim($property, '_'); // we don't use underscores anymore
+ $this->$property = $value;
+ }
+ }
+ }
+
+ /**
+ * Set the current values for the setting $key
+ *
+ * This is used to initialize the setting with the data read form the config files.
+ *
+ * @see update() to set a new value
+ * @param mixed $default default setting value
+ * @param mixed $local local setting value
+ * @param mixed $protected protected setting value
+ */
+ public function initialize($default = null, $local = null, $protected = null) {
+ $this->default = $this->cleanValue($default);
+ $this->local = $this->cleanValue($local);
+ $this->protected = $this->cleanValue($protected);
+ }
+
+ /**
+ * update changed setting with validated user provided value $input
+ * - if changed value fails validation check, save it to $this->input (to allow echoing later)
+ * - if changed value passes validation check, set $this->local to the new value
+ *
+ * @param mixed $input the new value
+ * @return boolean true if changed, false otherwise
+ */
+ public function update($input) {
+ if(is_null($input)) return false;
+ if($this->isProtected()) return false;
+ $input = $this->cleanValue($input);
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ // validate new value
+ if($this->pattern && !preg_match($this->pattern, $input)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+
+ // update local copy of this setting with new value
+ $this->local = $input;
+
+ // setting ready for update
+ return true;
+ }
+
+ /**
+ * Clean a value read from a config before using it internally
+ *
+ * Default implementation returns $value as is. Subclasses can override.
+ * Note: null should always be returned as null!
+ *
+ * This is applied in initialize() and update()
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function cleanValue($value) {
+ return $value;
+ }
+
+ /**
+ * Should this type of config have a default?
+ *
+ * @return bool
+ */
+ public function shouldHaveDefault() {
+ return true;
+ }
+
+ /**
+ * Get this setting's unique key
+ *
+ * @return string
+ */
+ public function getKey() {
+ return $this->key;
+ }
+
+ /**
+ * Get the key of this setting marked up human readable
+ *
+ * @param bool $url link to dokuwiki.org manual?
+ * @return string
+ */
+ public function getPrettyKey($url = true) {
+ $out = str_replace(Configuration::KEYMARKER, "»", $this->key);
+ if($url && !strstr($out, '»')) {//provide no urls for plugins, etc.
+ if($out == 'start') {
+ // exception, because this config name is clashing with our actual start page
+ return '<a href="http://www.dokuwiki.org/config:startpage">' . $out . '</a>';
+ } else {
+ return '<a href="http://www.dokuwiki.org/config:' . $out . '">' . $out . '</a>';
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Returns setting key as an array key separator
+ *
+ * This is used to create form output
+ *
+ * @return string key
+ */
+ public function getArrayKey() {
+ return str_replace(Configuration::KEYMARKER, "']['", $this->key);
+ }
+
+ /**
+ * What type of configuration is this
+ *
+ * Returns one of
+ *
+ * 'plugin' for plugin configuration
+ * 'template' for template configuration
+ * 'dokuwiki' for core configuration
+ *
+ * @return string
+ */
+ public function getType() {
+ if(substr($this->getKey(), 0, 10) == 'plugin' . Configuration::KEYMARKER) {
+ return 'plugin';
+ } else if(substr($this->getKey(), 0, 7) == 'tpl' . Configuration::KEYMARKER) {
+ return 'template';
+ } else {
+ return 'dokuwiki';
+ }
+ }
+
+ /**
+ * Build html for label and input of setting
+ *
+ * @param \admin_plugin_config $plugin object of config plugin
+ * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting
+ * @return string[] with content array(string $label_html, string $input_html)
+ */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ $disable = '';
+
+ if($this->isProtected()) {
+ $value = $this->protected;
+ $disable = 'disabled="disabled"';
+ } else {
+ if($echo && $this->error) {
+ $value = $this->input;
+ } else {
+ $value = is_null($this->local) ? $this->default : $this->local;
+ }
+ }
+
+ $key = htmlspecialchars($this->key);
+ $value = formText($value);
+
+ $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>';
+ $input = '<textarea rows="3" cols="40" id="config___' . $key .
+ '" name="config[' . $key . ']" class="edit" ' . $disable . '>' . $value . '</textarea>';
+ return array($label, $input);
+ }
+
+ /**
+ * Should the current local value be saved?
+ *
+ * @see out() to run when this returns true
+ * @return bool
+ */
+ public function shouldBeSaved() {
+ if($this->isProtected()) return false;
+ if($this->local === null) return false;
+ if($this->default == $this->local) return false;
+ return true;
+ }
+
+ /**
+ * Generate string to save local setting value to file according to $fmt
+ *
+ * @see shouldBeSaved() to check if this should be called
+ * @param string $var name of variable
+ * @param string $fmt save format
+ * @return string
+ */
+ public function out($var, $fmt = 'php') {
+ if($fmt != 'php') return '';
+
+ $tr = array("\\" => '\\\\', "'" => '\\\''); // escape the value
+ $out = '$' . $var . "['" . $this->getArrayKey() . "'] = '" . strtr(cleanText($this->local), $tr) . "';\n";
+
+ return $out;
+ }
+
+ /**
+ * Returns the localized prompt
+ *
+ * @param \admin_plugin_config $plugin object of config plugin
+ * @return string text
+ */
+ public function prompt(\admin_plugin_config $plugin) {
+ $prompt = $plugin->getLang($this->key);
+ if(!$prompt) $prompt = htmlspecialchars(str_replace(array('____', '_'), ' ', $this->key));
+ return $prompt;
+ }
+
+ /**
+ * Is setting protected
+ *
+ * @return bool
+ */
+ public function isProtected() {
+ return !is_null($this->protected);
+ }
+
+ /**
+ * Is setting the default?
+ *
+ * @return bool
+ */
+ public function isDefault() {
+ return !$this->isProtected() && is_null($this->local);
+ }
+
+ /**
+ * Has an error?
+ *
+ * @return bool
+ */
+ public function hasError() {
+ return $this->error;
+ }
+
+ /**
+ * Returns caution
+ *
+ * @return false|string caution string, otherwise false for invalid caution
+ */
+ public function caution() {
+ if(empty($this->caution)) return false;
+ if(!in_array($this->caution, Setting::$validCautions)) {
+ throw new \RuntimeException(
+ 'Invalid caution string (' . $this->caution . ') in metadata for setting "' . $this->key . '"'
+ );
+ }
+ return $this->caution;
+ }
+
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingArray.php b/platform/www/lib/plugins/config/core/Setting/SettingArray.php
new file mode 100644
index 0000000..c48dc76
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingArray.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_array
+ */
+class SettingArray extends Setting {
+
+ /**
+ * Create an array from a string
+ *
+ * @param string $string
+ * @return array
+ */
+ protected function fromString($string) {
+ $array = explode(',', $string);
+ $array = array_map('trim', $array);
+ $array = array_filter($array);
+ $array = array_unique($array);
+ return $array;
+ }
+
+ /**
+ * Create a string from an array
+ *
+ * @param array $array
+ * @return string
+ */
+ protected function fromArray($array) {
+ return join(', ', (array) $array);
+ }
+
+ /**
+ * update setting with user provided value $input
+ * if value fails error check, save it
+ *
+ * @param string $input
+ * @return bool true if changed, false otherwise (incl. on error)
+ */
+ public function update($input) {
+ if(is_null($input)) return false;
+ if($this->isProtected()) return false;
+
+ $input = $this->fromString($input);
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ foreach($input as $item) {
+ if($this->pattern && !preg_match($this->pattern, $item)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+ }
+
+ $this->local = $input;
+ return true;
+ }
+
+ /**
+ * Escaping
+ *
+ * @param string $string
+ * @return string
+ */
+ protected function escape($string) {
+ $tr = array("\\" => '\\\\', "'" => '\\\'');
+ return "'" . strtr(cleanText($string), $tr) . "'";
+ }
+
+ /** @inheritdoc */
+ public function out($var, $fmt = 'php') {
+ if($fmt != 'php') return '';
+
+ $vals = array_map(array($this, 'escape'), $this->local);
+ $out = '$' . $var . "['" . $this->getArrayKey() . "'] = array(" . join(', ', $vals) . ");\n";
+ return $out;
+ }
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ $disable = '';
+
+ if($this->isProtected()) {
+ $value = $this->protected;
+ $disable = 'disabled="disabled"';
+ } else {
+ if($echo && $this->error) {
+ $value = $this->input;
+ } else {
+ $value = is_null($this->local) ? $this->default : $this->local;
+ }
+ }
+
+ $key = htmlspecialchars($this->key);
+ $value = htmlspecialchars($this->fromArray($value));
+
+ $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>';
+ $input = '<input id="config___' . $key . '" name="config[' . $key .
+ ']" type="text" class="edit" value="' . $value . '" ' . $disable . '/>';
+ return array($label, $input);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingAuthtype.php b/platform/www/lib/plugins/config/core/Setting/SettingAuthtype.php
new file mode 100644
index 0000000..3a6df6f
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingAuthtype.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_authtype
+ */
+class SettingAuthtype extends SettingMultichoice {
+
+ /** @inheritdoc */
+ public function initialize($default = null, $local = null, $protected = null) {
+ /** @var $plugin_controller \dokuwiki\Extension\PluginController */
+ global $plugin_controller;
+
+ // retrieve auth types provided by plugins
+ foreach($plugin_controller->getList('auth') as $plugin) {
+ $this->choices[] = $plugin;
+ }
+
+ parent::initialize($default, $local, $protected);
+ }
+
+ /** @inheritdoc */
+ public function update($input) {
+ /** @var $plugin_controller \dokuwiki\Extension\PluginController */
+ global $plugin_controller;
+
+ // is an update possible/requested?
+ $local = $this->local; // save this, parent::update() may change it
+ if(!parent::update($input)) return false; // nothing changed or an error caught by parent
+ $this->local = $local; // restore original, more error checking to come
+
+ // attempt to load the plugin
+ $auth_plugin = $plugin_controller->load('auth', $input);
+
+ // @TODO: throw an error in plugin controller instead of returning null
+ if(is_null($auth_plugin)) {
+ $this->error = true;
+ msg('Cannot load Auth Plugin "' . $input . '"', -1);
+ return false;
+ }
+
+ // verify proper instantiation (is this really a plugin?) @TODO use instanceof? implement interface?
+ if(is_object($auth_plugin) && !method_exists($auth_plugin, 'getPluginName')) {
+ $this->error = true;
+ msg('Cannot create Auth Plugin "' . $input . '"', -1);
+ return false;
+ }
+
+ // did we change the auth type? logout
+ global $conf;
+ if($conf['authtype'] != $input) {
+ msg('Authentication system changed. Please re-login.');
+ auth_logoff();
+ }
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingCompression.php b/platform/www/lib/plugins/config/core/Setting/SettingCompression.php
new file mode 100644
index 0000000..f97d828
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingCompression.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_compression
+ */
+class SettingCompression extends SettingMultichoice {
+
+ protected $choices = array('0'); // 0 = no compression, always supported
+
+ /** @inheritdoc */
+ public function initialize($default = null, $local = null, $protected = null) {
+
+ // populate _choices with the compression methods supported by this php installation
+ if(function_exists('gzopen')) $this->choices[] = 'gz';
+ if(function_exists('bzopen')) $this->choices[] = 'bz2';
+
+ parent::initialize($default, $local, $protected);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingDirchoice.php b/platform/www/lib/plugins/config/core/Setting/SettingDirchoice.php
new file mode 100644
index 0000000..dfb27f5
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingDirchoice.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_dirchoice
+ */
+class SettingDirchoice extends SettingMultichoice {
+
+ protected $dir = '';
+
+ /** @inheritdoc */
+ public function initialize($default = null, $local = null, $protected = null) {
+
+ // populate $this->_choices with a list of directories
+ $list = array();
+
+ if($dh = @opendir($this->dir)) {
+ while(false !== ($entry = readdir($dh))) {
+ if($entry == '.' || $entry == '..') continue;
+ if($this->pattern && !preg_match($this->pattern, $entry)) continue;
+
+ $file = (is_link($this->dir . $entry)) ? readlink($this->dir . $entry) : $this->dir . $entry;
+ if(is_dir($file)) $list[] = $entry;
+ }
+ closedir($dh);
+ }
+ sort($list);
+ $this->choices = $list;
+
+ parent::initialize($default, $local, $protected);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingDisableactions.php b/platform/www/lib/plugins/config/core/Setting/SettingDisableactions.php
new file mode 100644
index 0000000..2553175
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingDisableactions.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_disableactions
+ */
+class SettingDisableactions extends SettingMulticheckbox {
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ global $lang;
+
+ // make some language adjustments (there must be a better way)
+ // transfer some DokuWiki language strings to the plugin
+ $plugin->addLang($this->key . '_revisions', $lang['btn_revs']);
+ foreach($this->choices as $choice) {
+ if(isset($lang['btn_' . $choice])) $plugin->addLang($this->key . '_' . $choice, $lang['btn_' . $choice]);
+ }
+
+ return parent::html($plugin, $echo);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingEmail.php b/platform/www/lib/plugins/config/core/Setting/SettingEmail.php
new file mode 100644
index 0000000..25a0c0e
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingEmail.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_email
+ */
+class SettingEmail extends SettingString {
+ protected $multiple = false;
+ protected $placeholders = false;
+
+ /** @inheritdoc */
+ public function update($input) {
+ if(is_null($input)) return false;
+ if($this->isProtected()) return false;
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+ if($input === '') {
+ $this->local = $input;
+ return true;
+ }
+ $mail = $input;
+
+ if($this->placeholders) {
+ // replace variables with pseudo values
+ $mail = str_replace('@USER@', 'joe', $mail);
+ $mail = str_replace('@NAME@', 'Joe Schmoe', $mail);
+ $mail = str_replace('@MAIL@', 'joe@example.com', $mail);
+ }
+
+ // multiple mail addresses?
+ if($this->multiple) {
+ $mails = array_filter(array_map('trim', explode(',', $mail)));
+ } else {
+ $mails = array($mail);
+ }
+
+ // check them all
+ foreach($mails as $mail) {
+ // only check the address part
+ if(preg_match('#(.*?)<(.*?)>#', $mail, $matches)) {
+ $addr = $matches[2];
+ } else {
+ $addr = $mail;
+ }
+
+ if(!mail_isvalid($addr)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+ }
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingFieldset.php b/platform/www/lib/plugins/config/core/Setting/SettingFieldset.php
new file mode 100644
index 0000000..4e86189
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingFieldset.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * A do-nothing class used to detect the 'fieldset' type.
+ *
+ * Used to start a new settings "display-group".
+ */
+class SettingFieldset extends Setting {
+
+ /** @inheritdoc */
+ public function shouldHaveDefault() {
+ return false;
+ }
+
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingHidden.php b/platform/www/lib/plugins/config/core/Setting/SettingHidden.php
new file mode 100644
index 0000000..ca8a03e
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingHidden.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_hidden
+ */
+class SettingHidden extends Setting {
+ // Used to explicitly ignore a setting in the configuration manager.
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingImConvert.php b/platform/www/lib/plugins/config/core/Setting/SettingImConvert.php
new file mode 100644
index 0000000..8740d94
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingImConvert.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_im_convert
+ */
+class SettingImConvert extends SettingString {
+
+ /** @inheritdoc */
+ public function update($input) {
+ if($this->isProtected()) return false;
+
+ $input = trim($input);
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ if($input && !file_exists($input)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingLicense.php b/platform/www/lib/plugins/config/core/Setting/SettingLicense.php
new file mode 100644
index 0000000..8dacf8e
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingLicense.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_license
+ */
+class SettingLicense extends SettingMultichoice {
+
+ protected $choices = array(''); // none choosen
+
+ /** @inheritdoc */
+ public function initialize($default = null, $local = null, $protected = null) {
+ global $license;
+
+ foreach($license as $key => $data) {
+ $this->choices[] = $key;
+ $this->lang[$this->key . '_o_' . $key] = $data['name']; // stored in setting
+ }
+
+ parent::initialize($default, $local, $protected);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingMulticheckbox.php b/platform/www/lib/plugins/config/core/Setting/SettingMulticheckbox.php
new file mode 100644
index 0000000..df212cc
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingMulticheckbox.php
@@ -0,0 +1,163 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_multicheckbox
+ */
+class SettingMulticheckbox extends SettingString {
+
+ protected $choices = array();
+ protected $combine = array();
+ protected $other = 'always';
+
+ /** @inheritdoc */
+ public function update($input) {
+ if($this->isProtected()) return false;
+
+ // split any combined values + convert from array to comma separated string
+ $input = ($input) ? $input : array();
+ $input = $this->array2str($input);
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ if($this->pattern && !preg_match($this->pattern, $input)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+
+ $this->local = $input;
+ return true;
+ }
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+
+ $disable = '';
+
+ if($this->isProtected()) {
+ $value = $this->protected;
+ $disable = 'disabled="disabled"';
+ } else {
+ if($echo && $this->error) {
+ $value = $this->input;
+ } else {
+ $value = is_null($this->local) ? $this->default : $this->local;
+ }
+ }
+
+ $key = htmlspecialchars($this->key);
+
+ // convert from comma separated list into array + combine complimentary actions
+ $value = $this->str2array($value);
+ $default = $this->str2array($this->default);
+
+ $input = '';
+ foreach($this->choices as $choice) {
+ $idx = array_search($choice, $value);
+ $idx_default = array_search($choice, $default);
+
+ $checked = ($idx !== false) ? 'checked="checked"' : '';
+
+ // @todo ideally this would be handled using a second class of "default"
+ $class = (($idx !== false) == (false !== $idx_default)) ? " selectiondefault" : "";
+
+ $prompt = ($plugin->getLang($this->key . '_' . $choice) ?
+ $plugin->getLang($this->key . '_' . $choice) : htmlspecialchars($choice));
+
+ $input .= '<div class="selection' . $class . '">' . "\n";
+ $input .= '<label for="config___' . $key . '_' . $choice . '">' . $prompt . "</label>\n";
+ $input .= '<input id="config___' . $key . '_' . $choice . '" name="config[' . $key .
+ '][]" type="checkbox" class="checkbox" value="' . $choice . '" ' . $disable . ' ' . $checked . "/>\n";
+ $input .= "</div>\n";
+
+ // remove this action from the disabledactions array
+ if($idx !== false) unset($value[$idx]);
+ if($idx_default !== false) unset($default[$idx_default]);
+ }
+
+ // handle any remaining values
+ if($this->other != 'never') {
+ $other = join(',', $value);
+ // test equivalent to ($this->_other == 'always' || ($other && $this->_other == 'exists')
+ // use != 'exists' rather than == 'always' to ensure invalid values default to 'always'
+ if($this->other != 'exists' || $other) {
+
+ $class = (
+ (count($default) == count($value)) &&
+ (count($value) == count(array_intersect($value, $default)))
+ ) ?
+ " selectiondefault" : "";
+
+ $input .= '<div class="other' . $class . '">' . "\n";
+ $input .= '<label for="config___' . $key . '_other">' .
+ $plugin->getLang($key . '_other') .
+ "</label>\n";
+ $input .= '<input id="config___' . $key . '_other" name="config[' . $key .
+ '][other]" type="text" class="edit" value="' . htmlspecialchars($other) .
+ '" ' . $disable . " />\n";
+ $input .= "</div>\n";
+ }
+ }
+ $label = '<label>' . $this->prompt($plugin) . '</label>';
+ return array($label, $input);
+ }
+
+ /**
+ * convert comma separated list to an array and combine any complimentary values
+ *
+ * @param string $str
+ * @return array
+ */
+ protected function str2array($str) {
+ $array = explode(',', $str);
+
+ if(!empty($this->combine)) {
+ foreach($this->combine as $key => $combinators) {
+ $idx = array();
+ foreach($combinators as $val) {
+ if(($idx[] = array_search($val, $array)) === false) break;
+ }
+
+ if(count($idx) && $idx[count($idx) - 1] !== false) {
+ foreach($idx as $i) unset($array[$i]);
+ $array[] = $key;
+ }
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * convert array of values + other back to a comma separated list, incl. splitting any combined values
+ *
+ * @param array $input
+ * @return string
+ */
+ protected function array2str($input) {
+
+ // handle other
+ $other = trim($input['other']);
+ $other = !empty($other) ? explode(',', str_replace(' ', '', $input['other'])) : array();
+ unset($input['other']);
+
+ $array = array_unique(array_merge($input, $other));
+
+ // deconstruct any combinations
+ if(!empty($this->combine)) {
+ foreach($this->combine as $key => $combinators) {
+
+ $idx = array_search($key, $array);
+ if($idx !== false) {
+ unset($array[$idx]);
+ $array = array_merge($array, $combinators);
+ }
+ }
+ }
+
+ return join(',', array_unique($array));
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingMultichoice.php b/platform/www/lib/plugins/config/core/Setting/SettingMultichoice.php
new file mode 100644
index 0000000..3a50857
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingMultichoice.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_multichoice
+ */
+class SettingMultichoice extends SettingString {
+ protected $choices = array();
+ public $lang; //some custom language strings are stored in setting
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ $disable = '';
+ $nochoice = '';
+
+ if($this->isProtected()) {
+ $value = $this->protected;
+ $disable = ' disabled="disabled"';
+ } else {
+ $value = is_null($this->local) ? $this->default : $this->local;
+ }
+
+ // ensure current value is included
+ if(!in_array($value, $this->choices)) {
+ $this->choices[] = $value;
+ }
+ // disable if no other choices
+ if(!$this->isProtected() && count($this->choices) <= 1) {
+ $disable = ' disabled="disabled"';
+ $nochoice = $plugin->getLang('nochoice');
+ }
+
+ $key = htmlspecialchars($this->key);
+
+ $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>';
+
+ $input = "<div class=\"input\">\n";
+ $input .= '<select class="edit" id="config___' . $key . '" name="config[' . $key . ']"' . $disable . '>' . "\n";
+ foreach($this->choices as $choice) {
+ $selected = ($value == $choice) ? ' selected="selected"' : '';
+ $option = $plugin->getLang($this->key . '_o_' . $choice);
+ if(!$option && isset($this->lang[$this->key . '_o_' . $choice])) {
+ $option = $this->lang[$this->key . '_o_' . $choice];
+ }
+ if(!$option) $option = $choice;
+
+ $choice = htmlspecialchars($choice);
+ $option = htmlspecialchars($option);
+ $input .= ' <option value="' . $choice . '"' . $selected . ' >' . $option . '</option>' . "\n";
+ }
+ $input .= "</select> $nochoice \n";
+ $input .= "</div>\n";
+
+ return array($label, $input);
+ }
+
+ /** @inheritdoc */
+ public function update($input) {
+ if(is_null($input)) return false;
+ if($this->isProtected()) return false;
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ if(!in_array($input, $this->choices)) return false;
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingNoClass.php b/platform/www/lib/plugins/config/core/Setting/SettingNoClass.php
new file mode 100644
index 0000000..8efff21
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingNoClass.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_no_class
+ * A do-nothing class used to detect settings with a missing setting class.
+ * Used internaly to hide undefined settings, and generate the undefined settings list.
+ */
+class SettingNoClass extends SettingUndefined {
+ protected $errorMessage = '_msg_setting_no_class';
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingNoDefault.php b/platform/www/lib/plugins/config/core/Setting/SettingNoDefault.php
new file mode 100644
index 0000000..07b8412
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingNoDefault.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_no_default
+ *
+ * A do-nothing class used to detect settings with no default value.
+ * Used internaly to hide undefined settings, and generate the undefined settings list.
+ */
+class SettingNoDefault extends SettingUndefined {
+ protected $errorMessage = '_msg_setting_no_default';
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingNoKnownClass.php b/platform/www/lib/plugins/config/core/Setting/SettingNoKnownClass.php
new file mode 100644
index 0000000..3c527e1
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingNoKnownClass.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * A do-nothing class used to detect settings with a missing setting class.
+ * Used internaly to hide undefined settings, and generate the undefined settings list.
+ */
+class SettingNoKnownClass extends SettingUndefined {
+ protected $errorMessage = '_msg_setting_no_known_class';
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingNumeric.php b/platform/www/lib/plugins/config/core/Setting/SettingNumeric.php
new file mode 100644
index 0000000..8a6b179
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingNumeric.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_numeric
+ */
+class SettingNumeric extends SettingString {
+ // This allows for many PHP syntax errors...
+ // var $_pattern = '/^[-+\/*0-9 ]*$/';
+ // much more restrictive, but should eliminate syntax errors.
+ protected $pattern = '/^[-+]? *[0-9]+ *(?:[-+*] *[0-9]+ *)*$/';
+ protected $min = null;
+ protected $max = null;
+
+ /** @inheritdoc */
+ public function update($input) {
+ $local = $this->local;
+ $valid = parent::update($input);
+ if($valid && !(is_null($this->min) && is_null($this->max))) {
+ $numeric_local = (int) eval('return ' . $this->local . ';');
+ if((!is_null($this->min) && $numeric_local < $this->min) ||
+ (!is_null($this->max) && $numeric_local > $this->max)) {
+ $this->error = true;
+ $this->input = $input;
+ $this->local = $local;
+ $valid = false;
+ }
+ }
+ return $valid;
+ }
+
+ /** @inheritdoc */
+ public function out($var, $fmt = 'php') {
+ if($fmt != 'php') return '';
+
+ $local = $this->local === '' ? "''" : $this->local;
+ $out = '$' . $var . "['" . $this->getArrayKey() . "'] = " . $local . ";\n";
+
+ return $out;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingNumericopt.php b/platform/www/lib/plugins/config/core/Setting/SettingNumericopt.php
new file mode 100644
index 0000000..a486e18
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingNumericopt.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_numericopt
+ */
+class SettingNumericopt extends SettingNumeric {
+ // just allow an empty config
+ protected $pattern = '/^(|[-]?[0-9]+(?:[-+*][0-9]+)*)$/';
+
+ /**
+ * @inheritdoc
+ * Empty string is valid for numericopt
+ */
+ public function update($input) {
+ if($input === '') {
+ if($input == $this->local) return false;
+ $this->local = $input;
+ return true;
+ }
+
+ return parent::update($input);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingOnoff.php b/platform/www/lib/plugins/config/core/Setting/SettingOnoff.php
new file mode 100644
index 0000000..780778b
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingOnoff.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_onoff
+ */
+class SettingOnoff extends SettingNumeric {
+
+ /**
+ * We treat the strings 'false' and 'off' as false
+ * @inheritdoc
+ */
+ protected function cleanValue($value) {
+ if($value === null) return null;
+
+ if(is_string($value)) {
+ if(strtolower($value) === 'false') return 0;
+ if(strtolower($value) === 'off') return 0;
+ if(trim($value) === '') return 0;
+ }
+
+ return (int) (bool) $value;
+ }
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ $disable = '';
+
+ if($this->isProtected()) {
+ $value = $this->protected;
+ $disable = ' disabled="disabled"';
+ } else {
+ $value = is_null($this->local) ? $this->default : $this->local;
+ }
+
+ $key = htmlspecialchars($this->key);
+ $checked = ($value) ? ' checked="checked"' : '';
+
+ $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>';
+ $input = '<div class="input"><input id="config___' . $key . '" name="config[' . $key .
+ ']" type="checkbox" class="checkbox" value="1"' . $checked . $disable . '/></div>';
+ return array($label, $input);
+ }
+
+ /** @inheritdoc */
+ public function update($input) {
+ if($this->isProtected()) return false;
+
+ $input = ($input) ? 1 : 0;
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingPassword.php b/platform/www/lib/plugins/config/core/Setting/SettingPassword.php
new file mode 100644
index 0000000..9d9c533
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingPassword.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_password
+ */
+class SettingPassword extends SettingString {
+
+ protected $code = 'plain'; // mechanism to be used to obscure passwords
+
+ /** @inheritdoc */
+ public function update($input) {
+ if($this->isProtected()) return false;
+ if(!$input) return false;
+
+ if($this->pattern && !preg_match($this->pattern, $input)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+
+ $this->local = conf_encodeString($input, $this->code);
+ return true;
+ }
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+
+ $disable = $this->isProtected() ? 'disabled="disabled"' : '';
+
+ $key = htmlspecialchars($this->key);
+
+ $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>';
+ $input = '<input id="config___' . $key . '" name="config[' . $key .
+ ']" autocomplete="off" type="password" class="edit" value="" ' . $disable . ' />';
+ return array($label, $input);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingRegex.php b/platform/www/lib/plugins/config/core/Setting/SettingRegex.php
new file mode 100644
index 0000000..b38f0a5
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingRegex.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_regex
+ */
+class SettingRegex extends SettingString {
+
+ protected $delimiter = '/'; // regex delimiter to be used in testing input
+ protected $pregflags = 'ui'; // regex pattern modifiers to be used in testing input
+
+ /** @inheritdoc */
+ public function update($input) {
+
+ // let parent do basic checks, value, not changed, etc.
+ $local = $this->local;
+ if(!parent::update($input)) return false;
+ $this->local = $local;
+
+ // see if the regex compiles and runs (we don't check for effectiveness)
+ $regex = $this->delimiter . $input . $this->delimiter . $this->pregflags;
+ $lastError = error_get_last();
+ @preg_match($regex, 'testdata');
+ if(preg_last_error() != PREG_NO_ERROR || error_get_last() != $lastError) {
+ $this->input = $input;
+ $this->error = true;
+ return false;
+ }
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingRenderer.php b/platform/www/lib/plugins/config/core/Setting/SettingRenderer.php
new file mode 100644
index 0000000..37ba9c7
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingRenderer.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * additional setting classes specific to these settings
+ *
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_renderer
+ */
+class SettingRenderer extends SettingMultichoice {
+ protected $prompts = array();
+ protected $format = null;
+
+ /** @inheritdoc */
+ public function initialize($default = null, $local = null, $protected = null) {
+ $format = $this->format;
+
+ foreach(plugin_list('renderer') as $plugin) {
+ $renderer = plugin_load('renderer', $plugin);
+ if(method_exists($renderer, 'canRender') && $renderer->canRender($format)) {
+ $this->choices[] = $plugin;
+
+ $info = $renderer->getInfo();
+ $this->prompts[$plugin] = $info['name'];
+ }
+ }
+
+ parent::initialize($default, $local, $protected);
+ }
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+
+ // make some language adjustments (there must be a better way)
+ // transfer some plugin names to the config plugin
+ foreach($this->choices as $choice) {
+ if(!$plugin->getLang($this->key . '_o_' . $choice)) {
+ if(!isset($this->prompts[$choice])) {
+ $plugin->addLang(
+ $this->key . '_o_' . $choice,
+ sprintf($plugin->getLang('renderer__core'), $choice)
+ );
+ } else {
+ $plugin->addLang(
+ $this->key . '_o_' . $choice,
+ sprintf($plugin->getLang('renderer__plugin'), $this->prompts[$choice])
+ );
+ }
+ }
+ }
+ return parent::html($plugin, $echo);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingSavedir.php b/platform/www/lib/plugins/config/core/Setting/SettingSavedir.php
new file mode 100644
index 0000000..43e428d
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingSavedir.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_savedir
+ */
+class SettingSavedir extends SettingString {
+
+ /** @inheritdoc */
+ public function update($input) {
+ if($this->isProtected()) return false;
+
+ $value = is_null($this->local) ? $this->default : $this->local;
+ if($value == $input) return false;
+
+ if(!init_path($input)) {
+ $this->error = true;
+ $this->input = $input;
+ return false;
+ }
+
+ $this->local = $input;
+ return true;
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingSepchar.php b/platform/www/lib/plugins/config/core/Setting/SettingSepchar.php
new file mode 100644
index 0000000..57cd0ae
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingSepchar.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_sepchar
+ */
+class SettingSepchar extends SettingMultichoice {
+
+ /** @inheritdoc */
+ public function __construct($key, $param = null) {
+ $str = '_-.';
+ for($i = 0; $i < strlen($str); $i++) $this->choices[] = $str[$i];
+
+ // call foundation class constructor
+ parent::__construct($key, $param);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingString.php b/platform/www/lib/plugins/config/core/Setting/SettingString.php
new file mode 100644
index 0000000..b819407
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingString.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+/**
+ * Class setting_string
+ */
+class SettingString extends Setting {
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ $disable = '';
+
+ if($this->isProtected()) {
+ $value = $this->protected;
+ $disable = 'disabled="disabled"';
+ } else {
+ if($echo && $this->error) {
+ $value = $this->input;
+ } else {
+ $value = is_null($this->local) ? $this->default : $this->local;
+ }
+ }
+
+ $key = htmlspecialchars($this->key);
+ $value = htmlspecialchars($value);
+
+ $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>';
+ $input = '<input id="config___' . $key . '" name="config[' . $key .
+ ']" type="text" class="edit" value="' . $value . '" ' . $disable . '/>';
+ return array($label, $input);
+ }
+}
diff --git a/platform/www/lib/plugins/config/core/Setting/SettingUndefined.php b/platform/www/lib/plugins/config/core/Setting/SettingUndefined.php
new file mode 100644
index 0000000..fa46a9f
--- /dev/null
+++ b/platform/www/lib/plugins/config/core/Setting/SettingUndefined.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace dokuwiki\plugin\config\core\Setting;
+
+use dokuwiki\plugin\config\core\Configuration;
+
+/**
+ * A do-nothing class used to detect settings with no metadata entry.
+ * Used internaly to hide undefined settings, and generate the undefined settings list.
+ */
+class SettingUndefined extends SettingHidden {
+
+ protected $errorMessage = '_msg_setting_undefined';
+
+ /** @inheritdoc */
+ public function shouldHaveDefault() {
+ return false;
+ }
+
+ /** @inheritdoc */
+ public function html(\admin_plugin_config $plugin, $echo = false) {
+ // determine the name the meta key would be called
+ if(preg_match(
+ '/^(?:plugin|tpl)' . Configuration::KEYMARKER . '.*?' . Configuration::KEYMARKER . '(.*)$/',
+ $this->getKey(),
+ $undefined_setting_match
+ )) {
+ $undefined_setting_key = $undefined_setting_match[1];
+ } else {
+ $undefined_setting_key = $this->getKey();
+ }
+
+ $label = '<span title="$meta[\'' . $undefined_setting_key . '\']">$' .
+ 'conf' . '[\'' . $this->getArrayKey() . '\']</span>';
+ $input = $plugin->getLang($this->errorMessage);
+
+ return array($label, $input);
+ }
+
+}