1<?php 2 3namespace dokuwiki\Input; 4 5/** 6 * Encapsulates access to the $_REQUEST array, making sure used parameters are initialized and 7 * have the correct type. 8 * 9 * All function access the $_REQUEST array by default, if you want to access $_POST or $_GET 10 * explicitly use the $post and $get members. 11 * 12 * @author Andreas Gohr <andi@splitbrain.org> 13 */ 14class Input 15{ 16 /** @var Post Access $_POST parameters */ 17 public $post; 18 /** @var Get Access $_GET parameters */ 19 public $get; 20 /** @var Server Access $_SERVER parameters */ 21 public $server; 22 23 protected $access; 24 25 /** 26 * @var Callable 27 */ 28 protected $filter; 29 30 /** 31 * Intilizes the dokuwiki\Input\Input class and it subcomponents 32 */ 33 public function __construct() 34 { 35 $this->access = &$_REQUEST; 36 $this->post = new Post(); 37 $this->get = new Get(); 38 $this->server = new Server(); 39 } 40 41 /** 42 * Apply the set filter to the given value 43 * 44 * @param string $data 45 * @return string 46 */ 47 protected function applyfilter($data) 48 { 49 if (!$this->filter) return $data; 50 return call_user_func($this->filter, $data); 51 } 52 53 /** 54 * Return a filtered copy of the input object 55 * 56 * Expects a callable that accepts one string parameter and returns a filtered string 57 * 58 * @param Callable|string $filter 59 * @return Input 60 */ 61 public function filter($filter = 'stripctl') 62 { 63 $this->filter = $filter; 64 $clone = clone $this; 65 $this->filter = ''; 66 return $clone; 67 } 68 69 /** 70 * Check if a parameter was set 71 * 72 * Basically a wrapper around isset. When called on the $post and $get subclasses, 73 * the parameter is set to $_POST or $_GET and to $_REQUEST 74 * 75 * @see isset 76 * @param string $name Parameter name 77 * @return bool 78 */ 79 public function has($name) 80 { 81 return isset($this->access[$name]); 82 } 83 84 /** 85 * Remove a parameter from the superglobals 86 * 87 * Basically a wrapper around unset. When NOT called on the $post and $get subclasses, 88 * the parameter will also be removed from $_POST or $_GET 89 * 90 * @see isset 91 * @param string $name Parameter name 92 */ 93 public function remove($name) 94 { 95 if (isset($this->access[$name])) { 96 unset($this->access[$name]); 97 } 98 // also remove from sub classes 99 if (isset($this->post) && isset($_POST[$name])) { 100 unset($_POST[$name]); 101 } 102 if (isset($this->get) && isset($_GET[$name])) { 103 unset($_GET[$name]); 104 } 105 } 106 107 /** 108 * Access a request parameter without any type conversion 109 * 110 * @param string $name Parameter name 111 * @param mixed $default Default to return if parameter isn't set 112 * @param bool $nonempty Return $default if parameter is set but empty() 113 * @return mixed 114 */ 115 public function param($name, $default = null, $nonempty = false) 116 { 117 if (!isset($this->access[$name])) return $default; 118 $value = $this->applyfilter($this->access[$name]); 119 if ($nonempty && empty($value)) return $default; 120 return $value; 121 } 122 123 /** 124 * Sets a parameter 125 * 126 * @param string $name Parameter name 127 * @param mixed $value Value to set 128 */ 129 public function set($name, $value) 130 { 131 $this->access[$name] = $value; 132 } 133 134 /** 135 * Get a reference to a request parameter 136 * 137 * This avoids copying data in memory, when the parameter is not set it will be created 138 * and intialized with the given $default value before a reference is returned 139 * 140 * @param string $name Parameter name 141 * @param mixed $default If parameter is not set, initialize with this value 142 * @param bool $nonempty Init with $default if parameter is set but empty() 143 * @return mixed (reference) 144 */ 145 public function &ref($name, $default = '', $nonempty = false) 146 { 147 if (!isset($this->access[$name]) || ($nonempty && empty($this->access[$name]))) { 148 $this->set($name, $default); 149 } 150 151 return $this->access[$name]; 152 } 153 154 /** 155 * Access a request parameter as int 156 * 157 * @param string $name Parameter name 158 * @param int $default Default to return if parameter isn't set or is an array 159 * @param bool $nonempty Return $default if parameter is set but empty() 160 * @return int 161 */ 162 public function int($name, $default = 0, $nonempty = false) 163 { 164 if (!isset($this->access[$name])) return $default; 165 if (is_array($this->access[$name])) return $default; 166 $value = $this->applyfilter($this->access[$name]); 167 if ($value === '') return $default; 168 if ($nonempty && empty($value)) return $default; 169 170 return (int)$value; 171 } 172 173 /** 174 * Access a request parameter as string 175 * 176 * @param string $name Parameter name 177 * @param string $default Default to return if parameter isn't set or is an array 178 * @param bool $nonempty Return $default if parameter is set but empty() 179 * @return string 180 */ 181 public function str($name, $default = '', $nonempty = false) 182 { 183 if (!isset($this->access[$name])) return $default; 184 if (is_array($this->access[$name])) return $default; 185 $value = $this->applyfilter($this->access[$name]); 186 if ($nonempty && empty($value)) return $default; 187 188 return (string)$value; 189 } 190 191 /** 192 * Access a request parameter and make sure it is has a valid value 193 * 194 * Please note that comparisons to the valid values are not done typesafe (request vars 195 * are always strings) however the function will return the correct type from the $valids 196 * array when an match was found. 197 * 198 * @param string $name Parameter name 199 * @param array $valids Array of valid values 200 * @param mixed $default Default to return if parameter isn't set or not valid 201 * @return null|mixed 202 */ 203 public function valid($name, $valids, $default = null) 204 { 205 if (!isset($this->access[$name])) return $default; 206 if (is_array($this->access[$name])) return $default; // we don't allow arrays 207 $value = $this->applyfilter($this->access[$name]); 208 $found = array_search($value, $valids); 209 if ($found !== false) return $valids[$found]; // return the valid value for type safety 210 return $default; 211 } 212 213 /** 214 * Access a request parameter as bool 215 * 216 * Note: $nonempty is here for interface consistency and makes not much sense for booleans 217 * 218 * @param string $name Parameter name 219 * @param mixed $default Default to return if parameter isn't set 220 * @param bool $nonempty Return $default if parameter is set but empty() 221 * @return bool 222 */ 223 public function bool($name, $default = false, $nonempty = false) 224 { 225 if (!isset($this->access[$name])) return $default; 226 if (is_array($this->access[$name])) return $default; 227 $value = $this->applyfilter($this->access[$name]); 228 if ($value === '') return $default; 229 if ($nonempty && empty($value)) return $default; 230 231 return (bool)$value; 232 } 233 234 /** 235 * Access a request parameter as array 236 * 237 * @param string $name Parameter name 238 * @param mixed $default Default to return if parameter isn't set 239 * @param bool $nonempty Return $default if parameter is set but empty() 240 * @return array 241 */ 242 public function arr($name, $default = [], $nonempty = false) 243 { 244 if (!isset($this->access[$name])) return $default; 245 if (!is_array($this->access[$name])) return $default; 246 if ($nonempty && empty($this->access[$name])) return $default; 247 248 return $this->access[$name]; 249 } 250 251 /** 252 * Create a simple key from an array key 253 * 254 * This is useful to access keys where the information is given as an array key or as a single array value. 255 * For example when the information was submitted as the name of a submit button. 256 * 257 * This function directly changes the access array. 258 * 259 * Eg. $_REQUEST['do']['save']='Speichern' becomes $_REQUEST['do'] = 'save' 260 * 261 * This function returns the $INPUT object itself for easy chaining 262 * 263 * @param string $name 264 * @return Input 265 */ 266 public function extract($name) 267 { 268 if (!isset($this->access[$name])) return $this; 269 if (!is_array($this->access[$name])) return $this; 270 $keys = array_keys($this->access[$name]); 271 if (!$keys) { 272 // this was an empty array 273 $this->remove($name); 274 return $this; 275 } 276 // get the first key 277 $value = array_shift($keys); 278 if ($value === 0) { 279 // we had a numeric array, assume the value is not in the key 280 $value = array_shift($this->access[$name]); 281 } 282 283 $this->set($name, $value); 284 return $this; 285 } 286} 287