1<?php 2 3namespace dokuwiki\Form; 4 5/** 6 * Class LegacyForm 7 * 8 * Provides a compatibility layer to the old Doku_Form API 9 * 10 * This can be used to work with the modern API on forms provided by old events for 11 * example. When you start new forms, just use Form\Form 12 * 13 * @package dokuwiki\Form 14 */ 15class LegacyForm extends Form 16{ 17 /** 18 * Creates a new modern form from an old legacy Doku_Form 19 * 20 * @param \Doku_Form $oldform 21 */ 22 public function __construct(\Doku_Form $oldform) 23 { 24 parent::__construct($oldform->params); 25 26 $this->hidden = $oldform->_hidden; 27 28 foreach ($oldform->_content as $element) { 29 [$ctl, $attr] = $this->parseLegacyAttr($element); 30 31 if (is_array($element)) { 32 switch ($ctl['elem']) { 33 case 'wikitext': 34 $this->addTextarea('wikitext') 35 ->attrs($attr) 36 ->id('wiki__text') 37 ->val($ctl['text']) 38 ->addClass($ctl['class']); 39 break; 40 case 'textfield': 41 $this->addTextInput($ctl['name'], $ctl['text']) 42 ->attrs($attr) 43 ->id($ctl['id']) 44 ->addClass($ctl['class']); 45 break; 46 case 'passwordfield': 47 $this->addPasswordInput($ctl['name'], $ctl['text']) 48 ->attrs($attr) 49 ->id($ctl['id']) 50 ->addClass($ctl['class']); 51 break; 52 case 'checkboxfield': 53 $this->addCheckbox($ctl['name'], $ctl['text']) 54 ->attrs($attr) 55 ->id($ctl['id']) 56 ->addClass($ctl['class']); 57 break; 58 case 'radiofield': 59 $this->addRadioButton($ctl['name'], $ctl['text']) 60 ->attrs($attr) 61 ->id($ctl['id']) 62 ->addClass($ctl['class']); 63 break; 64 case 'tag': 65 $this->addTag($ctl['tag']) 66 ->attrs($attr) 67 ->attr('name', $ctl['name']) 68 ->id($ctl['id']) 69 ->addClass($ctl['class']); 70 break; 71 case 'opentag': 72 $this->addTagOpen($ctl['tag']) 73 ->attrs($attr) 74 ->attr('name', $ctl['name']) 75 ->id($ctl['id']) 76 ->addClass($ctl['class']); 77 break; 78 case 'closetag': 79 $this->addTagClose($ctl['tag']); 80 break; 81 case 'openfieldset': 82 $this->addFieldsetOpen($ctl['legend']) 83 ->attrs($attr) 84 ->attr('name', $ctl['name']) 85 ->id($ctl['id']) 86 ->addClass($ctl['class']); 87 break; 88 case 'closefieldset': 89 $this->addFieldsetClose(); 90 break; 91 case 'button': 92 case 'field': 93 case 'fieldright': 94 case 'filefield': 95 case 'menufield': 96 case 'listboxfield': 97 throw new \UnexpectedValueException('Unsupported legacy field ' . $ctl['elem']); 98 default: 99 throw new \UnexpectedValueException('Unknown legacy field ' . $ctl['elem']); 100 } 101 } else { 102 $this->addHTML($element); 103 } 104 } 105 106 } 107 108 /** 109 * Parses out what is the elements attributes and what is control info 110 * 111 * @param array $legacy 112 * @return array 113 */ 114 protected function parseLegacyAttr($legacy) 115 { 116 $attributes = []; 117 $control = []; 118 119 foreach ($legacy as $key => $val) { 120 if ($key[0] == '_') { 121 $control[substr($key, 1)] = $val; 122 } elseif ($key == 'name') { 123 $control[$key] = $val; 124 } elseif ($key == 'id') { 125 $control[$key] = $val; 126 } else { 127 $attributes[$key] = $val; 128 } 129 } 130 131 return [$control, $attributes]; 132 } 133 134 /** 135 * Translates our types to the legacy types 136 * 137 * @param string $type 138 * @return string 139 */ 140 protected function legacyType($type) 141 { 142 static $types = [ 143 'text' => 'textfield', 144 'password' => 'passwordfield', 145 'checkbox' => 'checkboxfield', 146 'radio' => 'radiofield', 147 'tagopen' => 'opentag', 148 'tagclose' => 'closetag', 149 'fieldsetopen' => 'openfieldset', 150 'fieldsetclose' => 'closefieldset' 151 ]; 152 return $types[$type] ?? $type; 153 } 154 155 /** 156 * Creates an old legacy form from this modern form's data 157 * 158 * @return \Doku_Form 159 */ 160 public function toLegacy() 161 { 162 $this->balanceFieldsets(); 163 164 $legacy = new \Doku_Form($this->attrs()); 165 $legacy->_hidden = $this->hidden; 166 foreach ($this->elements as $element) { 167 if (is_a($element, 'dokuwiki\Form\HTMLElement')) { 168 $legacy->_content[] = $element->toHTML(); 169 } elseif (is_a($element, 'dokuwiki\Form\InputElement')) { 170 /** @var InputElement $element */ 171 $data = $element->attrs(); 172 $data['_elem'] = $this->legacyType($element->getType()); 173 $label = $element->getLabel(); 174 if ($label instanceof LabelElement) { 175 $data['_class'] = $label->attr('class'); 176 } 177 $legacy->_content[] = $data; 178 } 179 } 180 181 return $legacy; 182 } 183} 184