xref: /plugin/struct/types/AbstractBaseType.php (revision 9e9bee91898d9164e48494e09d8110b0d9ef2e99)
1<?php
2namespace plugin\struct\types;
3
4use dokuwiki\Form\Form;
5
6/**
7 * Class AbstractBaseType
8 *
9 * This class represents a basic type that can be configured to be used in a Schema. It is the main
10 * part of a column definition as defined in meta\Column
11 *
12 * This defines also how the content of the coulmn will be entered and formatted.
13 *
14 * @package plugin\struct\types
15 * @see Column
16 */
17abstract class AbstractBaseType {
18
19    /**
20     * @var array current config
21     */
22    protected $config = array();
23
24    /**
25     * @var string label for the field
26     */
27    protected $label = '';
28
29    /**
30     * @var bool is this a multivalue field?
31     */
32    protected $ismulti = false;
33
34    /**
35     * @var int the type ID
36     */
37    protected $tid = 0;
38
39    /**
40     * AbstractBaseType constructor.
41     * @param array|null $config The configuration, might be null if nothing saved, yet
42     * @param string $label The label for this field (empty for new definitions=
43     * @param bool $ismulti Should this field accept multiple values?
44     * @param int $tid The id of this type if it has been saved, yet
45     */
46    public function __construct($config = null, $label = '', $ismulti = false, $tid = 0) {
47        if(!is_null($config)) $this->config = array_merge($this->config, $config);
48        $this->initTransConfig();
49        $this->label = $label;
50        $this->ismulti = (bool) $ismulti;
51        $this->tid = $tid;
52    }
53
54    /**
55     * Add the translation keys to the configuration
56     *
57     * This checks if a configuration for the translation plugin exists and if so
58     * adds all configured languages to the config array. This ensures all types
59     * can have translatable labels.
60     */
61    protected function initTransConfig() {
62        global $conf;
63        $lang = $conf['lang'];
64        if(isset($conf['plugin']['translation']['translations'])) {
65            $lang .= ' ' . $conf['plugin']['translation']['translations'];
66        }
67        $langs = explode(' ', $lang);
68        $langs = array_map('trim', $langs);
69        $langs = array_filter($langs);
70        $langs = array_unique($langs);
71
72        if(!isset($this->config['translation'])) $this->config['translation'] = array();
73        foreach($langs as $lang) {
74            if(!isset($this->config['translation'][$lang])) $this->config['translation'][$lang] = '';
75        }
76    }
77
78    /**
79     * Returns data as associative array
80     *
81     * @return array
82     */
83    public function getAsEntry() {
84        return array(
85            'config' => json_encode($this->config),
86            'label' => $this->label,
87            'ismulti' => $this->ismulti,
88            'class' => $this->getClass()
89        );
90    }
91
92    /**
93     * The class name of this type (no namespace)
94     * @return string
95     */
96    public function getClass() {
97        return substr(get_class($this), 20);
98    }
99
100    /**
101     * Return the current configuration for this type
102     *
103     * @return array
104     */
105    public function getConfig() {
106        return $this->config;
107    }
108
109    /**
110     * @return boolean
111     */
112    public function isMulti() {
113        return $this->ismulti;
114    }
115
116    /**
117     * @return string
118     */
119    public function getLabel() {
120        return $this->label;
121    }
122
123    /**
124     * Returns the translated label for this type
125     *
126     * Uses the current language as determined by $conf['lang']. Falls back to english
127     * and then to the Schema label
128     *
129     * @return string
130     */
131    public function getTranslatedLabel() {
132        global $conf;
133        $lang = $conf['lang'];
134        if(!blank($this->config['translation'][$lang])) {
135            return $this->config['translation'][$lang];
136        }
137        if(!blank($this->config['translation']['en'])) {
138            return $this->config['translation']['en'];
139        }
140        return $this->label;
141    }
142
143    /**
144     * @return int
145     */
146    public function getTid() {
147        return $this->tid;
148    }
149
150    /**
151     * Split a single value into multiple values
152     *
153     * This function is called on saving data when only a single value instead of an array
154     * was submitted.
155     *
156     * Types implementing their own @see multiValueEditor() will probably want to override this
157     *
158     * @param string $value
159     * @return array
160     */
161    public function splitValues($value) {
162        return array_map('trim', explode(',', $value));
163    }
164
165    /**
166     * Return the editor to edit multiple values
167     *
168     * Types can override this to provide a better alternative than multiple entry fields
169     *
170     * @param string $name the form base name where this has to be stored
171     * @param string[] $values the current values
172     * @return string html
173     */
174    public function multiValueEditor($name, $values) {
175        $html = '';
176        foreach($values as $value) {
177            $html .= $this->valueEditor($name . '[]', $value);
178        }
179        // empty field to add
180        $html .= $this->valueEditor($name . '[]', '');
181
182        return $html;
183    }
184
185    /**
186     * Return the editor to edit a single value
187     *
188     * @param string $name the form name where this has to be stored
189     * @param string $value the current value
190     * @return string html
191     */
192    public function valueEditor($name, $value) {
193        $name = hsc($name);
194        $value = hsc($value);
195        $html = "<input name=\"$name\" value=\"$value\" />";
196        return "$html";
197    }
198
199    /**
200     * Output the stored data
201     *
202     * @param string|int $value the value stored in the database
203     * @param \Doku_Renderer $R the renderer currently used to render the data
204     * @param string $mode The mode the output is rendered in (eg. XHTML)
205     * @return bool true if $mode could be satisfied
206     */
207    public function renderValue($value, \Doku_Renderer $R, $mode) {
208        $R->cdata($value);
209        return true;
210    }
211
212    /**
213     * format and return the data
214     *
215     * @param int[]|string[] $values the values stored in the database
216     * @param \Doku_Renderer $R the renderer currently used to render the data
217     * @param string $mode The mode the output is rendered in (eg. XHTML)
218     * @return bool true if $mode could be satisfied
219     */
220    public function renderMultiValue($values, \Doku_Renderer $R, $mode) {
221        $len = count($values);
222        for($i = 0; $i < $len; $i++) {
223            $this->renderValue($values[$i], $R, $mode);
224            if($i < $len - 1) {
225                $R->cdata(', ');
226            }
227        }
228        return true;
229    }
230
231    /**
232     * This function builds a where clause for this column, comparing
233     * the current value stored in $column with $value. Types can use it to do
234     * clever things with the comparison.
235     *
236     * This default implementation is probably good enough for most basic types
237     *
238     * @param string $column The column name to us in the SQL
239     * @param string $comp The comparator @see Search::$COMPARATORS
240     * @param string $value
241     * @return array Tuple with the SQL and parameter array
242     */
243    public function compare($column, $comp, $value) {
244        if($comp == '~') {
245            $sql = "$column LIKE ?";
246            $opt = array('%' . $value . '%');
247        } else if($comp == '!~') {
248            $sql = "$column NOT LIKE ?";
249            $opt = array('%' . $value . '%');
250        } else {
251            $sql = "$column $comp ?";
252            $opt = array($value);
253        }
254
255        return array($sql, $opt);
256    }
257}
258