File modules/cms/action/ValueMapping.class.php

Last commit: Wed Oct 14 01:41:42 2026 +0200	Jan Dankert	Saving values with the new object-oriented ui objects.
1 <?php 2 3 namespace cms\action; 4 5 use cms\model\BaseObject; 6 use cms\model\Element; 7 use cms\model\Folder; 8 use cms\model\Project; 9 use cms\model\Value; 10 use DateTime; 11 use logger\Logger; 12 use util\exception\ValidationException; 13 14 /** 15 * UI-Mapping for Values. 16 */ 17 trait ValueMapping 18 { 19 protected function outputValue( $element, $value ) 20 { 21 $output = []; 22 $content = ''; 23 24 switch( $element->typeid) { 25 26 case Element::ELEMENT_TYPE_DATETIME: 27 $output['items'] = $element->getSelectItems(); 28 $output['date']=date('Y-m-d\TH:i' ,$value->date ); 29 break; 30 case Element::ELEMENT_TYPE_DATE: 31 $output['items'] = $element->getSelectItems(); 32 $output['date']=date('Y-m-d',$value->date ); 33 break; 34 case Element::ELEMENT_TYPE_TIME: 35 $output['items'] = $element->getSelectItems(); 36 $output['date']=date('H:i' ,$value->date ); 37 break; 38 case Element::ELEMENT_TYPE_WEEK: 39 $output['items'] = $element->getSelectItems(); 40 $output['date']=date('Y-\WW',$value->date ); 41 break; 42 case Element::ELEMENT_TYPE_MONTH: 43 $output['items'] = $element->getSelectItems(); 44 $output['date']=date('Y-m' ,$value->date ); 45 break; 46 47 case Element::ELEMENT_TYPE_LINK: 48 $project = new Project($this->page->projectid); 49 $output['rootfolderid'] = $project->getRootObjectId(); 50 51 // Ermitteln, welche Objekttypen verlinkt werden d�rfen. 52 $type = $element->subtype; 53 54 if (substr($type, 0, 5) == 'image') 55 $type = 'file'; 56 57 if (!in_array($type, array('file', 'page', 'link', 'folder'))) 58 $types = array('file', 'page', 'link'); // Fallback: Der Link kann auf Seiten,Dateien und Verknüpfungen zeigen 59 else 60 $types = array($type); // gewünschten Typ verwenden 61 62 $oid = $value->linkToObjectId; 63 $name = ''; 64 65 if ($oid) { 66 $o = new BaseObject($oid); 67 $o->load(); 68 $name = $o->filename; 69 } 70 71 $output['objects'] = array(); 72 $output['linkobjectid']= $oid; 73 $content = $oid; 74 $output['linkname']= $name; 75 76 $output['types'] = implode(',', $types); 77 78 break; 79 80 case Element::ELEMENT_TYPE_SELECT: 81 case Element::ELEMENT_TYPE_SELECTS: 82 $output['items'] = $element->getSelectItems(); 83 $content = $value->text; 84 break; 85 86 case Element::ELEMENT_TYPE_INSERT: 87 // Auswahl ueber alle Elementtypen 88 $objects = array(); 89 //Änderung der möglichen Types 90 $types = array('file', 'page', 'link'); 91 $objects[0] = \cms\base\Language::lang('LIST_ENTRY_EMPTY'); // Wert "nicht ausgewählt" 92 93 $project = new Project($this->page->projectid); 94 $folder = new Folder($project->getRootObjectId()); 95 $folder->load(); 96 97 //Auch Dateien dazu 98 foreach ($project->getAllObjectIds($types) as $id) { 99 $f = new Folder($id); 100 $f->load(); 101 102 $objects[$id] = \cms\base\Language::lang($f->getType()) . ': '; 103 $objects[$id] .= implode(' &raquo; ', $f->parentObjectNames(false, true)); 104 } 105 106 foreach ($project->getAllFolders() as $id) { 107 $f = new Folder($id); 108 $f->load(); 109 110 $objects[$id] = \cms\base\Language::lang($f->getType()) . ': '; 111 $objects[$id] .= implode(' &raquo; ', $f->parentObjectNames(false, true)); 112 } 113 114 asort($objects); // Sortieren 115 116 $output['objects'] = $objects; 117 $content = $value->linkToObjectId; 118 119 break; 120 121 case Element::ELEMENT_TYPE_NUMBER: 122 $output['items'] = $element->getSelectItems(); 123 $content = $value->number / pow(10, $element->decimals); 124 break; 125 126 case Element::ELEMENT_TYPE_RANGE: 127 $content = $value->number / pow(10, $element->decimals); 128 break; 129 130 case Element::ELEMENT_TYPE_CHECKBOX: 131 $content = $value->number; 132 break; 133 134 case Element::ELEMENT_TYPE_LONGTEXT: 135 if ($requestFormat = $this->request->getText('format')) 136 // Individual format from request. 137 $format = $requestFormat; 138 elseif ($value->format != null) 139 $format = $value->format; 140 else 141 // There is no saved value. Get the format from the template element. 142 $format = $element->format; 143 144 $output['format'] = $format; 145 $output['editor'] = Element::getAvailableFormats()[$format]; 146 147 $content = $this->linkifyOIDs($value->text); 148 break; 149 150 case Element::ELEMENT_TYPE_TEXT: 151 case Element::ELEMENT_TYPE_DATA: 152 case Element::ELEMENT_TYPE_URL: 153 case Element::ELEMENT_TYPE_TEL: 154 case Element::ELEMENT_TYPE_EMAIL: 155 case Element::ELEMENT_TYPE_PASSWORD: 156 157 $output['items'] = $element->getSelectItems(); 158 $content = $value->text; 159 break; 160 161 case Element::ELEMENT_TYPE_COLOR: 162 163 Logger::debug( 'Farbe aus DB: '.dechex($value->number)); 164 $content = $this->colorNum2hex( $value->number ); 165 break; 166 167 case Element::ELEMENT_TYPE_COORD: 168 $lat = $value->number >> 32; 169 $long = $value->number << 32 >> 32; 170 171 $content = abs($lat).'°'.($lat<0?'S':'N').' '.abs($long).'°'.($long<0?'W':'E'); 172 break; 173 174 default: 175 throw new \InvalidArgumentException("Unsupported element type: ".$element->typeid); 176 177 } 178 $output['value'] = $content; 179 180 return $output; 181 } 182 183 184 protected function parseToValue( Element $element, Value $value, string $input) : void 185 { 186 switch ($element->typeid) { 187 188 case Element::ELEMENT_TYPE_TEXT: 189 case Element::ELEMENT_TYPE_EMAIL: 190 case Element::ELEMENT_TYPE_URL: 191 case Element::ELEMENT_TYPE_TEL: 192 case Element::ELEMENT_TYPE_DATA: 193 case Element::ELEMENT_TYPE_PASSWORD: 194 195 $value->text = $input; 196 break; 197 198 case Element::ELEMENT_TYPE_COLOR: 199 $value->number = $this->colorHex2Num( $input ); 200 break; 201 202 case Element::ELEMENT_TYPE_COORD: 203 204 $inputLatLongList = explode(' ',$input); 205 206 if ( sizeof($inputLatLongList) != 2 ) 207 throw new \InvalidArgumentException(); 208 209 $inputLatLongList = array_map( function ($value) { 210 if (in_array(substr($value,-1,1),['W','S'])) 211 return abs(intval($value))*-1; 212 elseif (in_array(substr($value,-1,1),['E','N'])) 213 return abs(intval($value)); 214 else 215 return intval($value); 216 },$inputLatLongList); 217 218 list($lat,$long) = $inputLatLongList; 219 220 $value->number = $lat << 32 | $long; 221 break; 222 223 case Element::ELEMENT_TYPE_LONGTEXT: 224 $value->text = $this->compactOIDs($input); 225 break; 226 227 case Element::ELEMENT_TYPE_DATETIME: 228 // 'datetime-local': YYY-MM-DDTHH:mm 229 $dateTime = DateTime::createFromFormat("!Y-m-d\TG:i", $input); 230 if ( $dateTime !== false ) 231 $value->date = $dateTime->getTimestamp(); 232 else 233 $value->date = null; 234 break; 235 236 case Element::ELEMENT_TYPE_DATE: 237 // 'date': YYYY-MM-DD 238 $dateTime = DateTime::createFromFormat("!Y-m-d", $input); 239 if ( $dateTime !== false ) 240 $value->date = $dateTime->getTimestamp(); 241 else 242 $value->date = null; 243 break; 244 245 case Element::ELEMENT_TYPE_TIME: 246 $dateTime = DateTime::createFromFormat("!H:i", $input); 247 if ( $dateTime !== false ) 248 $value->date = $dateTime->getTimestamp(); 249 else 250 $value->date = null; 251 break; 252 253 case Element::ELEMENT_TYPE_WEEK: 254 // week format: YYYY-'W'W 255 // unable to parse the week number from a date string :( 256 $weekDate = $input; 257 if ( strlen($weekDate)==8) { 258 $dateTime = (new DateTime)->setTimestamp(0)->setISODate( 259 intval(substr($weekDate, 0, 4)), 260 intval(substr($weekDate, 6, 2)) 261 ); 262 $value->date = $dateTime->getTimestamp(); 263 } 264 else 265 $value->date = null; 266 break; 267 268 case Element::ELEMENT_TYPE_MONTH: 269 $dateTime = DateTime::createFromFormat("!Y-m", $input); 270 if ( $dateTime !== false ) 271 $value->date = $dateTime->getTimestamp(); 272 else 273 $value->date = null; 274 break; 275 276 case Element::ELEMENT_TYPE_SELECT: 277 case Element::ELEMENT_TYPE_SELECTS: 278 $value->text = $input; 279 break; 280 case Element::ELEMENT_TYPE_CHECKBOX: 281 $value->number = $input?1:0; 282 break; 283 case Element::ELEMENT_TYPE_LINK: 284 case Element::ELEMENT_TYPE_INSERT: 285 $value->linkToObjectId = intval($input); 286 break; 287 288 case Element::ELEMENT_TYPE_NUMBER: 289 case Element::ELEMENT_TYPE_RANGE: 290 $value->number = $input * pow(10, $element->decimals); 291 break; 292 default: 293 throw new \LogicException('Unknown element type: ' . $element->getTypeName()); 294 } 295 296 } 297 298 /** 299 * hex2rgb 300 * 301 * @param mixed $hex 302 * 303 * @return int 304 */ 305 protected function colorHex2Num($hex) 306 { 307 $hex = str_replace('#', '', $hex); 308 309 if ( strlen($hex) != 3 && strlen($hex) != 6 ) 310 throw new \InvalidArgumentException("Hex color '".$hex."' is not valid."); 311 312 $hexColors = str_split($hex, strlen($hex)/3); 313 314 // normalize: The short hex notation: "F" becomes "FF". 315 $hexColors = array_map( function($hexColor) { 316 return (strlen($hexColor)==1)?$hexColor.$hexColor:$hexColor; 317 },$hexColors); 318 319 $numColors = array_map( function($hexColor) { 320 return hexdec($hexColor); 321 },$hexColors); 322 323 Logger::debug( 'Farbe-num aus Request: '.print_r($numColors,true)); 324 return array_reduce($numColors,function($num, $numColor) { 325 $num = $num << 8; 326 $num += $numColor; 327 return $num; 328 },0); 329 } 330 331 /** 332 * rgb2hex 333 * 334 * @param mixed $rgb 335 * 336 * @return string 337 */ 338 protected function colorNum2hex($colorAsNum) 339 { 340 $decArr = [ 341 $colorAsNum >> 16 & 0xff, 342 $colorAsNum >> 8 & 0xff, 343 $colorAsNum & 0xff 344 ]; 345 346 return "#" . 347 array_reduce( $decArr, function ($carry,$item) { 348 return $carry.=str_pad(dechex($item), 2, "0", STR_PAD_LEFT); 349 }, ''); 350 } 351 352 353 }
Download modules/cms/action/ValueMapping.class.php
History Wed, 14 Oct 2026 01:41:42 +0200 Jan Dankert Saving values with the new object-oriented ui objects. Tue, 13 Oct 2026 22:52:59 +0200 Jan Dankert New: The UI is now able to send hierarchical form data and the server is converting it into an object. This is a very nice feature, because this enables a better OpenAPI interface. Tue, 14 Jan 2025 01:57:22 +0100 Jan Dankert New: Some new template element types like 'url','email','range','password','date','time', ...; New: datalists for input fields; Refactoring: Cleaner templates and actions for editing values;