Input.php 8.8 KB

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