Variables.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. <?php
  2. /**
  3. * Horde_Variables:: class. Provides OO-way to access form variables.
  4. *
  5. * Copyright 2009-2013 Horde LLC (http://www.horde.org/)
  6. *
  7. * See the enclosed file COPYING for license information (LGPL). If you
  8. * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9. *
  10. * @author Robert E. Coyle <robertecoyle@hotmail.com>
  11. * @author Chuck Hagenbuch <chuck@horde.org>
  12. * @category Horde
  13. * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
  14. * @package Util
  15. */
  16. class Horde_Variables implements Countable, Iterator, ArrayAccess
  17. {
  18. /**
  19. * The list of expected variables.
  20. *
  21. * @var array
  22. */
  23. protected $_expected = [];
  24. /**
  25. * Has the input been sanitized?
  26. *
  27. * @var boolean
  28. */
  29. protected $_sanitized = false;
  30. /**
  31. * Array of form variables.
  32. *
  33. * @var array
  34. */
  35. protected $_vars;
  36. /**
  37. * Returns a Horde_Variables object populated with the form input.
  38. *
  39. * @param string $sanitize Sanitize the input variables?
  40. *
  41. * @return Horde_Variables Variables object.
  42. */
  43. static public function getDefaultVariables($sanitize = false)
  44. {
  45. return new self(null, $sanitize);
  46. }
  47. /**
  48. * Constructor.
  49. *
  50. * @param array $vars The list of form variables (if null, defaults
  51. * to PHP's $_REQUEST value).
  52. * @param string $sanitize Sanitize the input variables?
  53. */
  54. public function __construct($vars = [], $sanitize = false)
  55. {
  56. if (is_null($vars)) {
  57. $request_copy = $_REQUEST;
  58. $vars = Horde_Util::dispelMagicQuotes($request_copy);
  59. }
  60. if (isset($vars['_formvars'])) {
  61. $this->_expected = @unserialize($vars['_formvars']);
  62. unset($vars['_formvars']);
  63. }
  64. $this->_vars = $vars;
  65. if ($sanitize) {
  66. $this->sanitize();
  67. }
  68. }
  69. /**
  70. * Sanitize the form input.
  71. */
  72. public function sanitize()
  73. {
  74. if (!$this->_sanitized) {
  75. foreach (array_keys($this->_vars) as $key) {
  76. $this->$key = $this->filter($key);
  77. }
  78. $this->_sanitized = true;
  79. }
  80. }
  81. /**
  82. * Alias of isset().
  83. *
  84. * @see __isset()
  85. */
  86. public function exists($varname)
  87. {
  88. return isset($this->$varname);
  89. }
  90. /**
  91. * isset() implementation.
  92. *
  93. * @param string $varname The form variable name.
  94. *
  95. * @return boolean Does $varname form variable exist?
  96. */
  97. public function __isset($varname)
  98. {
  99. return count($this->_expected)
  100. ? $this->_getExists($this->_expected, $varname, $value)
  101. : $this->_getExists($this->_vars, $varname, $value);
  102. }
  103. /**
  104. * Implements isset() for ArrayAccess interface.
  105. *
  106. * @see __isset()
  107. */
  108. public function offsetExists($field)
  109. {
  110. return $this->__isset($field);
  111. }
  112. /**
  113. * Returns the value of a given form variable.
  114. *
  115. * @param string $varname The form variable name.
  116. * @param string $default The default form variable value.
  117. *
  118. * @return mixed The form variable, or $default if it doesn't exist.
  119. */
  120. public function get($varname, $default = null)
  121. {
  122. return $this->_getExists($this->_vars, $varname, $value)
  123. ? $value
  124. : $default;
  125. }
  126. /**
  127. * Returns the value of a given form variable.
  128. *
  129. * @param string $varname The form variable name.
  130. *
  131. * @return mixed The form variable, or null if it doesn't exist.
  132. */
  133. public function __get($varname)
  134. {
  135. $this->_getExists($this->_vars, $varname, $value);
  136. return $value;
  137. }
  138. /**
  139. * Implements getter for ArrayAccess interface.
  140. *
  141. * @see __get()
  142. */
  143. public function offsetGet($field)
  144. {
  145. return $this->__get($field);
  146. }
  147. /**
  148. * Given a variable name, returns the value and sets a variable indicating
  149. * whether the value exists in the form data.
  150. *
  151. * @param string $varname The form variable name.
  152. * @param boolean &$exists Reference to variable that will indicate
  153. * whether $varname existed in form data.
  154. *
  155. * @return mixed The form variable, or null if it doesn't exist.
  156. */
  157. public function getExists($varname, &$exists)
  158. {
  159. $exists = $this->_getExists($this->_vars, $varname, $value);
  160. return $value;
  161. }
  162. /**
  163. * Sets the value of a given form variable.
  164. *
  165. * @see __set()
  166. */
  167. public function set($varname, $value)
  168. {
  169. $this->$varname = $value;
  170. }
  171. /**
  172. * Sets the value of a given form variable.
  173. *
  174. * @param string $varname The form variable name.
  175. * @param mixed $value The value to set.
  176. */
  177. public function __set($varname, $value)
  178. {
  179. $keys = [];
  180. if (Horde_Array::getArrayParts($varname, $base, $keys)) {
  181. array_unshift($keys, $base);
  182. $place = &$this->_vars;
  183. $i = count($keys);
  184. while ($i--) {
  185. $key = array_shift($keys);
  186. if (!isset($place[$key])) {
  187. $place[$key] = [];
  188. }
  189. $place = &$place[$key];
  190. }
  191. $place = $value;
  192. } else {
  193. $this->_vars[$varname] = $value;
  194. }
  195. }
  196. /**
  197. * Implements setter for ArrayAccess interface.
  198. *
  199. * @see __set()
  200. */
  201. public function offsetSet($field, $value)
  202. {
  203. $this->__set($field, $value);
  204. }
  205. /**
  206. * Deletes a given form variable.
  207. *
  208. * @see __unset()
  209. */
  210. public function remove($varname)
  211. {
  212. unset($this->$varname);
  213. }
  214. /**
  215. * Deletes a given form variable.
  216. *
  217. * @param string $varname The form variable name.
  218. */
  219. public function __unset($varname)
  220. {
  221. Horde_Array::getArrayParts($varname, $base, $keys);
  222. if (is_null($base)) {
  223. unset($this->_vars[$varname]);
  224. } else {
  225. $ptr = &$this->_vars[$base];
  226. $end = count($keys) - 1;
  227. foreach ($keys as $key => $val) {
  228. if (!isset($ptr[$val])) {
  229. break;
  230. }
  231. if ($end == $key) {
  232. array_splice($ptr, array_search($val, array_keys($ptr)), 1);
  233. } else {
  234. $ptr = &$ptr[$val];
  235. }
  236. }
  237. }
  238. }
  239. /**
  240. * Implements unset() for ArrayAccess interface.
  241. *
  242. * @see __unset()
  243. */
  244. public function offsetUnset($field)
  245. {
  246. $this->__unset($field);
  247. }
  248. /**
  249. * Merges a list of variables into the current form variable list.
  250. *
  251. * @param array $vars Form variables.
  252. */
  253. public function merge($vars)
  254. {
  255. foreach ($vars as $varname => $value) {
  256. $this->$varname = $value;
  257. }
  258. }
  259. /**
  260. * Set $varname to $value ONLY if it's not already present.
  261. *
  262. * @param string $varname The form variable name.
  263. * @param mixed $value The value to set.
  264. *
  265. * @return boolean True if the value was altered.
  266. */
  267. public function add($varname, $value)
  268. {
  269. if ($this->exists($varname)) {
  270. return false;
  271. }
  272. $this->_vars[$varname] = $value;
  273. return true;
  274. }
  275. /**
  276. * Filters a form value so that it can be used in HTML output.
  277. *
  278. * @param string $varname The form variable name.
  279. *
  280. * @return mixed The filtered variable, or null if it doesn't exist.
  281. */
  282. public function filter($varname)
  283. {
  284. $val = $this->$varname;
  285. if (is_null($val) || $this->_sanitized) {
  286. return $val;
  287. }
  288. return is_array($val)
  289. ? filter_var_array($val, FILTER_SANITIZE_STRING)
  290. : filter_var($val, FILTER_SANITIZE_STRING);
  291. }
  292. /* Protected methods. */
  293. /**
  294. * Fetch the requested variable ($varname) into $value, and return
  295. * whether or not the variable was set in $array.
  296. *
  297. * @param array $array The array to search in (usually either
  298. * $this->_vars or $this->_expected).
  299. * @param string $varname The name of the variable to look for.
  300. * @param mixed &$value $varname's value gets assigned to this variable.
  301. *
  302. * @return boolean Whether or not the variable was set (or, if we've
  303. * checked $this->_expected, should have been set).
  304. */
  305. protected function _getExists($array, $varname, &$value)
  306. {
  307. if (Horde_Array::getArrayParts($varname, $base, $keys)) {
  308. if (!isset($array[$base])) {
  309. $value = null;
  310. return false;
  311. }
  312. $searchspace = &$array[$base];
  313. $i = count($keys);
  314. while ($i--) {
  315. $key = array_shift($keys);
  316. if (!isset($searchspace[$key])) {
  317. $value = null;
  318. return false;
  319. }
  320. $searchspace = &$searchspace[$key];
  321. }
  322. $value = $searchspace;
  323. return true;
  324. }
  325. $value = isset($array[$varname])
  326. ? $array[$varname]
  327. : null;
  328. return !is_null($value);
  329. }
  330. /* Countable methods. */
  331. /**
  332. */
  333. public function count()
  334. {
  335. return count($this->_vars);
  336. }
  337. /* Iterator methods. */
  338. public function current()
  339. {
  340. return current($this->_vars);
  341. }
  342. public function key()
  343. {
  344. return key($this->_vars);
  345. }
  346. public function next()
  347. {
  348. next($this->_vars);
  349. }
  350. public function rewind()
  351. {
  352. reset($this->_vars);
  353. }
  354. public function valid()
  355. {
  356. return (key($this->_vars) !== null);
  357. }
  358. }