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