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 } 102 } else { 103 $this->addHTML($element); 104 } 105 } 106 107 } 108 109 /** 110 * Parses out what is the elements attributes and what is control info 111 * 112 * @param array $legacy 113 * @return array 114 */ 115 protected function parseLegacyAttr($legacy) 116 { 117 $attributes = []; 118 $control = []; 119 120 foreach ($legacy as $key => $val) { 121 if ($key[0] == '_') { 122 $control[substr($key, 1)] = $val; 123 } elseif($key == 'name') { 124 $control[$key] = $val; 125 } elseif($key == 'id') { 126 $control[$key] = $val; 127 } else { 128 $attributes[$key] = $val; 129 } 130 } 131 132 return [$control, $attributes]; 133 } 134 135 /** 136 * Translates our types to the legacy types 137 * 138 * @param string $type 139 * @return string 140 */ 141 protected function legacyType($type) 142 { 143 static $types = [ 144 'text' => 'textfield', 145 'password' => 'passwordfield', 146 'checkbox' => 'checkboxfield', 147 'radio' => 'radiofield', 148 'tagopen' => 'opentag', 149 'tagclose' => 'closetag', 150 'fieldsetopen' => 'openfieldset', 151 'fieldsetclose' => 'closefieldset' 152 ]; 153 return $types[$type] ?? $type; 154 } 155 156 /** 157 * Creates an old legacy form from this modern form's data 158 * 159 * @return \Doku_Form 160 */ 161 public function toLegacy() 162 { 163 $this->balanceFieldsets(); 164 165 $legacy = new \Doku_Form($this->attrs()); 166 $legacy->_hidden = $this->hidden; 167 foreach ($this->elements as $element) { 168 if (is_a($element, 'dokuwiki\Form\HTMLElement')) { 169 $legacy->_content[] = $element->toHTML(); 170 } elseif (is_a($element, 'dokuwiki\Form\InputElement')) { 171 /** @var InputElement $element */ 172 $data = $element->attrs(); 173 $data['_elem'] = $this->legacyType($element->getType()); 174 $label = $element->getLabel(); 175 if ($label instanceof LabelElement) { 176 $data['_class'] = $label->attr('class'); 177 } 178 $legacy->_content[] = $data; 179 } 180 } 181 182 return $legacy; 183 } 184} 185