1<?php 2namespace dokuwiki\Form; 3 4/** 5 * Class InputElement 6 * 7 * Base class for all input elements. Uses a wrapping label when label 8 * text is given. 9 * 10 * @todo figure out how to make wrapping or related label configurable 11 * @package dokuwiki\Form 12 */ 13class InputElement extends Element { 14 /** 15 * @var Label 16 */ 17 protected $label = null; 18 19 /** 20 * @var bool if the element should reflect posted values 21 */ 22 protected $useInput = true; 23 24 /** 25 * @param string $type The type of this element 26 * @param string $name The name of this form element 27 * @param string $label The label text for this element 28 */ 29 public function __construct($type, $name, $label = '') { 30 parent::__construct($type, array('name' => $name)); 31 $this->attr('name', $name); 32 if($label) $this->label = new Label($label); 33 } 34 35 /** 36 * Returns the label element if there's one set 37 * 38 * @return Label|null 39 */ 40 public function getLabel() { 41 return $this->label; 42 } 43 44 /** 45 * Should the user sent input be used to initialize the input field 46 * 47 * The default is true. Any set values will be overwritten by the INPUT 48 * provided values. 49 * 50 * @param bool $useinput 51 * @return $this 52 */ 53 public function useInput($useinput) { 54 $this->useInput = (bool) $useinput; 55 return $this; 56 } 57 58 /** 59 * Get or set the element's ID 60 * 61 * @param null|string $id 62 * @return string|$this 63 */ 64 public function id($id = null) { 65 if($this->label) $this->label->attr('for', $id); 66 return parent::id($id); 67 } 68 69 /** 70 * Adds a class to the class attribute 71 * 72 * This is the preferred method of setting the element's class 73 * 74 * @param string $class the new class to add 75 * @return $this 76 */ 77 public function addClass($class) { 78 if($this->label) $this->label->addClass($class); 79 return parent::addClass($class); 80 } 81 82 /** 83 * Figures out how to access the value for this field from INPUT data 84 * 85 * The element's name could have been given as a simple string ('foo') 86 * or in array notation ('foo[bar]'). 87 * 88 * Note: this function only handles one level of arrays. If your data 89 * is nested deeper, you should call useInput(false) and set the 90 * correct value yourself 91 * 92 * @return array name and array key (null if not an array) 93 */ 94 protected function getInputName() { 95 $name = $this->attr('name'); 96 parse_str("$name=1", $parsed); 97 98 $name = array_keys($parsed); 99 $name = array_shift($name); 100 101 if(is_array($parsed[$name])) { 102 $key = array_keys($parsed[$name]); 103 $key = array_shift($key); 104 } else { 105 $key = null; 106 } 107 108 return array($name, $key); 109 } 110 111 /** 112 * Handles the useInput flag and set the value attribute accordingly 113 */ 114 protected function prefillInput() { 115 global $INPUT; 116 117 list($name, $key) = $this->getInputName(); 118 if(!$INPUT->has($name)) return; 119 120 if($key === null) { 121 $value = $INPUT->str($name); 122 } else { 123 $value = $INPUT->arr($name); 124 if(isset($value[$key])) { 125 $value = $value[$key]; 126 } else { 127 $value = ''; 128 } 129 } 130 if($value !== '') { 131 $this->val($value); 132 } 133 } 134 135 /** 136 * The HTML representation of this element 137 * 138 * @return string 139 */ 140 protected function mainElementHTML() { 141 if($this->useInput) $this->prefillInput(); 142 return '<input ' . buildAttributes($this->attrs()) . ' />'; 143 } 144 145 /** 146 * The HTML representation of this element wrapped in a label 147 * 148 * @return string 149 */ 150 public function toHTML() { 151 if($this->label) { 152 return '<label ' . buildAttributes($this->label->attrs()) . '>' . DOKU_LF . 153 '<span>' . hsc($this->label->val()) . '</span>' . DOKU_LF . 154 $this->mainElementHTML() . DOKU_LF . 155 '</label>'; 156 } else { 157 return $this->mainElementHTML(); 158 } 159 } 160} 161