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