summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/config/core/Setting/SettingMulticheckbox.php
blob: df212cca02d8eb64b5f36d6ae5ec709a929249fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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));
    }
}