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