SettingMulticheckbox.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. namespace dokuwiki\plugin\config\core\Setting;
  3. /**
  4. * Class setting_multicheckbox
  5. */
  6. class SettingMulticheckbox extends SettingString {
  7. protected $choices = array();
  8. protected $combine = array();
  9. protected $other = 'always';
  10. /** @inheritdoc */
  11. public function update($input) {
  12. if($this->isProtected()) return false;
  13. // split any combined values + convert from array to comma separated string
  14. $input = ($input) ? $input : array();
  15. $input = $this->array2str($input);
  16. $value = is_null($this->local) ? $this->default : $this->local;
  17. if($value == $input) return false;
  18. if($this->pattern && !preg_match($this->pattern, $input)) {
  19. $this->error = true;
  20. $this->input = $input;
  21. return false;
  22. }
  23. $this->local = $input;
  24. return true;
  25. }
  26. /** @inheritdoc */
  27. public function html(\admin_plugin_config $plugin, $echo = false) {
  28. $disable = '';
  29. if($this->isProtected()) {
  30. $value = $this->protected;
  31. $disable = 'disabled="disabled"';
  32. } else {
  33. if($echo && $this->error) {
  34. $value = $this->input;
  35. } else {
  36. $value = is_null($this->local) ? $this->default : $this->local;
  37. }
  38. }
  39. $key = htmlspecialchars($this->key);
  40. // convert from comma separated list into array + combine complimentary actions
  41. $value = $this->str2array($value);
  42. $default = $this->str2array($this->default);
  43. $input = '';
  44. foreach($this->choices as $choice) {
  45. $idx = array_search($choice, $value);
  46. $idx_default = array_search($choice, $default);
  47. $checked = ($idx !== false) ? 'checked="checked"' : '';
  48. // @todo ideally this would be handled using a second class of "default"
  49. $class = (($idx !== false) == (false !== $idx_default)) ? " selectiondefault" : "";
  50. $prompt = ($plugin->getLang($this->key . '_' . $choice) ?
  51. $plugin->getLang($this->key . '_' . $choice) : htmlspecialchars($choice));
  52. $input .= '<div class="selection' . $class . '">' . "\n";
  53. $input .= '<label for="config___' . $key . '_' . $choice . '">' . $prompt . "</label>\n";
  54. $input .= '<input id="config___' . $key . '_' . $choice . '" name="config[' . $key .
  55. '][]" type="checkbox" class="checkbox" value="' . $choice . '" ' . $disable . ' ' . $checked . "/>\n";
  56. $input .= "</div>\n";
  57. // remove this action from the disabledactions array
  58. if($idx !== false) unset($value[$idx]);
  59. if($idx_default !== false) unset($default[$idx_default]);
  60. }
  61. // handle any remaining values
  62. if($this->other != 'never') {
  63. $other = join(',', $value);
  64. // test equivalent to ($this->_other == 'always' || ($other && $this->_other == 'exists')
  65. // use != 'exists' rather than == 'always' to ensure invalid values default to 'always'
  66. if($this->other != 'exists' || $other) {
  67. $class = (
  68. (count($default) == count($value)) &&
  69. (count($value) == count(array_intersect($value, $default)))
  70. ) ?
  71. " selectiondefault" : "";
  72. $input .= '<div class="other' . $class . '">' . "\n";
  73. $input .= '<label for="config___' . $key . '_other">' .
  74. $plugin->getLang($key . '_other') .
  75. "</label>\n";
  76. $input .= '<input id="config___' . $key . '_other" name="config[' . $key .
  77. '][other]" type="text" class="edit" value="' . htmlspecialchars($other) .
  78. '" ' . $disable . " />\n";
  79. $input .= "</div>\n";
  80. }
  81. }
  82. $label = '<label>' . $this->prompt($plugin) . '</label>';
  83. return array($label, $input);
  84. }
  85. /**
  86. * convert comma separated list to an array and combine any complimentary values
  87. *
  88. * @param string $str
  89. * @return array
  90. */
  91. protected function str2array($str) {
  92. $array = explode(',', $str);
  93. if(!empty($this->combine)) {
  94. foreach($this->combine as $key => $combinators) {
  95. $idx = array();
  96. foreach($combinators as $val) {
  97. if(($idx[] = array_search($val, $array)) === false) break;
  98. }
  99. if(count($idx) && $idx[count($idx) - 1] !== false) {
  100. foreach($idx as $i) unset($array[$i]);
  101. $array[] = $key;
  102. }
  103. }
  104. }
  105. return $array;
  106. }
  107. /**
  108. * convert array of values + other back to a comma separated list, incl. splitting any combined values
  109. *
  110. * @param array $input
  111. * @return string
  112. */
  113. protected function array2str($input) {
  114. // handle other
  115. $other = trim($input['other']);
  116. $other = !empty($other) ? explode(',', str_replace(' ', '', $input['other'])) : array();
  117. unset($input['other']);
  118. $array = array_unique(array_merge($input, $other));
  119. // deconstruct any combinations
  120. if(!empty($this->combine)) {
  121. foreach($this->combine as $key => $combinators) {
  122. $idx = array_search($key, $array);
  123. if($idx !== false) {
  124. unset($array[$idx]);
  125. $array = array_merge($array, $combinators);
  126. }
  127. }
  128. }
  129. return join(',', array_unique($array));
  130. }
  131. }