xref: /dokuwiki/lib/plugins/config/core/Setting/SettingMulticheckbox.php (revision d4f83172d9533c4d84f450fe22ef630816b21d75)
10a5b05ebSAndreas Gohr<?php
20a5b05ebSAndreas Gohr
30a5b05ebSAndreas Gohrnamespace dokuwiki\plugin\config\core\Setting;
40a5b05ebSAndreas Gohr
50a5b05ebSAndreas Gohr/**
60a5b05ebSAndreas Gohr * Class setting_multicheckbox
70a5b05ebSAndreas Gohr */
88c7c53b0SAndreas Gohrclass SettingMulticheckbox extends SettingString
98c7c53b0SAndreas Gohr{
10467c1427SAndreas Gohr    protected $choices = [];
11467c1427SAndreas Gohr    protected $combine = [];
120a5b05ebSAndreas Gohr    protected $other = 'always';
130a5b05ebSAndreas Gohr
140a5b05ebSAndreas Gohr    /** @inheritdoc */
15*d868eb89SAndreas Gohr    public function update($input)
16*d868eb89SAndreas Gohr    {
170a5b05ebSAndreas Gohr        if ($this->isProtected()) return false;
180a5b05ebSAndreas Gohr
190a5b05ebSAndreas Gohr        // split any combined values + convert from array to comma separated string
20467c1427SAndreas Gohr        $input = $input ?: [];
210a5b05ebSAndreas Gohr        $input = $this->array2str($input);
220a5b05ebSAndreas Gohr
230a5b05ebSAndreas Gohr        $value = is_null($this->local) ? $this->default : $this->local;
240a5b05ebSAndreas Gohr        if ($value == $input) return false;
250a5b05ebSAndreas Gohr
260a5b05ebSAndreas Gohr        if ($this->pattern && !preg_match($this->pattern, $input)) {
270a5b05ebSAndreas Gohr            $this->error = true;
280a5b05ebSAndreas Gohr            $this->input = $input;
290a5b05ebSAndreas Gohr            return false;
300a5b05ebSAndreas Gohr        }
310a5b05ebSAndreas Gohr
320a5b05ebSAndreas Gohr        $this->local = $input;
330a5b05ebSAndreas Gohr        return true;
340a5b05ebSAndreas Gohr    }
350a5b05ebSAndreas Gohr
360a5b05ebSAndreas Gohr    /** @inheritdoc */
37*d868eb89SAndreas Gohr    public function html(\admin_plugin_config $plugin, $echo = false)
38*d868eb89SAndreas Gohr    {
390a5b05ebSAndreas Gohr
400a5b05ebSAndreas Gohr        $disable = '';
410a5b05ebSAndreas Gohr
420a5b05ebSAndreas Gohr        if ($this->isProtected()) {
430a5b05ebSAndreas Gohr            $value = $this->protected;
440a5b05ebSAndreas Gohr            $disable = 'disabled="disabled"';
45467c1427SAndreas Gohr        } elseif ($echo && $this->error) {
460a5b05ebSAndreas Gohr            $value = $this->input;
470a5b05ebSAndreas Gohr        } else {
480a5b05ebSAndreas Gohr            $value = is_null($this->local) ? $this->default : $this->local;
490a5b05ebSAndreas Gohr        }
500a5b05ebSAndreas Gohr
510a5b05ebSAndreas Gohr        $key = htmlspecialchars($this->key);
520a5b05ebSAndreas Gohr
530a5b05ebSAndreas Gohr        // convert from comma separated list into array + combine complimentary actions
540a5b05ebSAndreas Gohr        $value = $this->str2array($value);
550a5b05ebSAndreas Gohr        $default = $this->str2array($this->default);
560a5b05ebSAndreas Gohr
570a5b05ebSAndreas Gohr        $input = '';
580a5b05ebSAndreas Gohr        foreach ($this->choices as $choice) {
590a5b05ebSAndreas Gohr            $idx = array_search($choice, $value);
600a5b05ebSAndreas Gohr            $idx_default = array_search($choice, $default);
610a5b05ebSAndreas Gohr
620a5b05ebSAndreas Gohr            $checked = ($idx !== false) ? 'checked="checked"' : '';
630a5b05ebSAndreas Gohr
640a5b05ebSAndreas Gohr            // @todo ideally this would be handled using a second class of "default"
65467c1427SAndreas Gohr            $class = (($idx !== false) === (false !== $idx_default)) ? " selectiondefault" : "";
660a5b05ebSAndreas Gohr
67467c1427SAndreas Gohr            $prompt = ($plugin->getLang($this->key . '_' . $choice) ?: htmlspecialchars($choice));
680a5b05ebSAndreas Gohr
690a5b05ebSAndreas Gohr            $input .= '<div class="selection' . $class . '">' . "\n";
700a5b05ebSAndreas Gohr            $input .= '<label for="config___' . $key . '_' . $choice . '">' . $prompt . "</label>\n";
710a5b05ebSAndreas Gohr            $input .= '<input id="config___' . $key . '_' . $choice . '" name="config[' . $key .
720a5b05ebSAndreas Gohr                '][]" type="checkbox" class="checkbox" value="' . $choice . '" ' . $disable . ' ' . $checked . "/>\n";
730a5b05ebSAndreas Gohr            $input .= "</div>\n";
740a5b05ebSAndreas Gohr
750a5b05ebSAndreas Gohr            // remove this action from the disabledactions array
760a5b05ebSAndreas Gohr            if ($idx !== false) unset($value[$idx]);
770a5b05ebSAndreas Gohr            if ($idx_default !== false) unset($default[$idx_default]);
780a5b05ebSAndreas Gohr        }
790a5b05ebSAndreas Gohr
800a5b05ebSAndreas Gohr        // handle any remaining values
810a5b05ebSAndreas Gohr        if ($this->other != 'never') {
82467c1427SAndreas Gohr            $other = implode(',', $value);
830a5b05ebSAndreas Gohr            // test equivalent to ($this->_other == 'always' || ($other && $this->_other == 'exists')
840a5b05ebSAndreas Gohr            // use != 'exists' rather than == 'always' to ensure invalid values default to 'always'
850a5b05ebSAndreas Gohr            if ($this->other != 'exists' || $other) {
860a5b05ebSAndreas Gohr                $class = (
87467c1427SAndreas Gohr                    (count($default) === count($value)) &&
88467c1427SAndreas Gohr                    (count($value) === count(array_intersect($value, $default)))
890a5b05ebSAndreas Gohr                ) ?
900a5b05ebSAndreas Gohr                    " selectiondefault" : "";
910a5b05ebSAndreas Gohr
920a5b05ebSAndreas Gohr                $input .= '<div class="other' . $class . '">' . "\n";
930a5b05ebSAndreas Gohr                $input .= '<label for="config___' . $key . '_other">' .
940a5b05ebSAndreas Gohr                    $plugin->getLang($key . '_other') .
950a5b05ebSAndreas Gohr                    "</label>\n";
960a5b05ebSAndreas Gohr                $input .= '<input id="config___' . $key . '_other" name="config[' . $key .
970a5b05ebSAndreas Gohr                    '][other]" type="text" class="edit" value="' . htmlspecialchars($other) .
980a5b05ebSAndreas Gohr                    '" ' . $disable . " />\n";
990a5b05ebSAndreas Gohr                $input .= "</div>\n";
1000a5b05ebSAndreas Gohr            }
1010a5b05ebSAndreas Gohr        }
1020a5b05ebSAndreas Gohr        $label = '<label>' . $this->prompt($plugin) . '</label>';
103467c1427SAndreas Gohr        return [$label, $input];
1040a5b05ebSAndreas Gohr    }
1050a5b05ebSAndreas Gohr
1060a5b05ebSAndreas Gohr    /**
1070a5b05ebSAndreas Gohr     * convert comma separated list to an array and combine any complimentary values
1080a5b05ebSAndreas Gohr     *
1090a5b05ebSAndreas Gohr     * @param string $str
1100a5b05ebSAndreas Gohr     * @return array
1110a5b05ebSAndreas Gohr     */
112*d868eb89SAndreas Gohr    protected function str2array($str)
113*d868eb89SAndreas Gohr    {
1140a5b05ebSAndreas Gohr        $array = explode(',', $str);
1150a5b05ebSAndreas Gohr
1160a5b05ebSAndreas Gohr        if (!empty($this->combine)) {
1170a5b05ebSAndreas Gohr            foreach ($this->combine as $key => $combinators) {
118467c1427SAndreas Gohr                $idx = [];
1190a5b05ebSAndreas Gohr                foreach ($combinators as $val) {
1200a5b05ebSAndreas Gohr                    if (($idx[] = array_search($val, $array)) === false) break;
1210a5b05ebSAndreas Gohr                }
1220a5b05ebSAndreas Gohr
1230a5b05ebSAndreas Gohr                if (count($idx) && $idx[count($idx) - 1] !== false) {
1240a5b05ebSAndreas Gohr                    foreach ($idx as $i) unset($array[$i]);
1250a5b05ebSAndreas Gohr                    $array[] = $key;
1260a5b05ebSAndreas Gohr                }
1270a5b05ebSAndreas Gohr            }
1280a5b05ebSAndreas Gohr        }
1290a5b05ebSAndreas Gohr
1300a5b05ebSAndreas Gohr        return $array;
1310a5b05ebSAndreas Gohr    }
1320a5b05ebSAndreas Gohr
1330a5b05ebSAndreas Gohr    /**
1340a5b05ebSAndreas Gohr     * convert array of values + other back to a comma separated list, incl. splitting any combined values
1350a5b05ebSAndreas Gohr     *
1360a5b05ebSAndreas Gohr     * @param array $input
1370a5b05ebSAndreas Gohr     * @return string
1380a5b05ebSAndreas Gohr     */
139*d868eb89SAndreas Gohr    protected function array2str($input)
140*d868eb89SAndreas Gohr    {
1410a5b05ebSAndreas Gohr
1420a5b05ebSAndreas Gohr        // handle other
1430a5b05ebSAndreas Gohr        $other = trim($input['other']);
144467c1427SAndreas Gohr        $other = empty($other) ? [] : explode(',', str_replace(' ', '', $input['other']));
1450a5b05ebSAndreas Gohr        unset($input['other']);
1460a5b05ebSAndreas Gohr
1470a5b05ebSAndreas Gohr        $array = array_unique(array_merge($input, $other));
1480a5b05ebSAndreas Gohr
1490a5b05ebSAndreas Gohr        // deconstruct any combinations
1500a5b05ebSAndreas Gohr        if (!empty($this->combine)) {
1510a5b05ebSAndreas Gohr            foreach ($this->combine as $key => $combinators) {
1520a5b05ebSAndreas Gohr                $idx = array_search($key, $array);
1530a5b05ebSAndreas Gohr                if ($idx !== false) {
1540a5b05ebSAndreas Gohr                    unset($array[$idx]);
1550a5b05ebSAndreas Gohr                    $array = array_merge($array, $combinators);
1560a5b05ebSAndreas Gohr                }
1570a5b05ebSAndreas Gohr            }
1580a5b05ebSAndreas Gohr        }
1590a5b05ebSAndreas Gohr
160467c1427SAndreas Gohr        return implode(',', array_unique($array));
1610a5b05ebSAndreas Gohr    }
1620a5b05ebSAndreas Gohr}
163