Form.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <?php
  2. /**
  3. * Form helper class. Unless otherwise noted, all generated HTML will be made
  4. * safe using the [HTML::chars] method. This prevents against simple XSS
  5. * attacks that could otherwise be triggered by inserting HTML characters into
  6. * form fields.
  7. *
  8. * @package KO7
  9. * @category Helpers
  10. *
  11. * @copyright (c) 2007-2016 Kohana Team
  12. * @copyright (c) since 2016 Koseven Team
  13. * @license https://koseven.dev/LICENSE
  14. */
  15. class KO7_Form {
  16. /**
  17. * Generates an opening HTML form tag.
  18. *
  19. * // Form will submit back to the current page using POST
  20. * echo Form::open();
  21. *
  22. * // Form will submit to 'search' using GET
  23. * echo Form::open('search', array('method' => 'get'));
  24. *
  25. * // When "file" inputs are present, you must include the "enctype"
  26. * echo Form::open(NULL, array('enctype' => 'multipart/form-data'));
  27. *
  28. * @param mixed $action form action, defaults to the current request URI, or [Request] class to use
  29. * @param array $attributes html attributes
  30. * @return string
  31. * @uses Request
  32. * @uses URL::site
  33. * @uses HTML::attributes
  34. */
  35. public static function open($action = NULL, array $attributes = NULL)
  36. {
  37. if ($action instanceof Request)
  38. {
  39. // Use the current URI
  40. $action = $action->uri();
  41. }
  42. if ( ! $action)
  43. {
  44. // Allow empty form actions (submits back to the current url).
  45. $action = '';
  46. }
  47. elseif (strpos($action, '://') === FALSE AND strncmp($action, '//', 2))
  48. {
  49. // Make the URI absolute
  50. $action = URL::site($action);
  51. }
  52. // Add the form action to the attributes
  53. $attributes['action'] = $action;
  54. // Only accept the default character set
  55. $attributes['accept-charset'] = KO7::$charset;
  56. if ( ! isset($attributes['method']))
  57. {
  58. // Use POST method
  59. $attributes['method'] = 'post';
  60. }
  61. return '<form'.HTML::attributes($attributes).'>';
  62. }
  63. /**
  64. * Creates the closing form tag.
  65. *
  66. * echo Form::close();
  67. *
  68. * @return string
  69. */
  70. public static function close()
  71. {
  72. return '</form>';
  73. }
  74. /**
  75. * Creates a form input. If no type is specified, a "text" type input will
  76. * be returned.
  77. *
  78. * echo Form::input('username', $username);
  79. *
  80. * @param string $name input name
  81. * @param string $value input value
  82. * @param array $attributes html attributes
  83. * @return string
  84. * @uses HTML::attributes
  85. */
  86. public static function input($name, $value = NULL, array $attributes = NULL)
  87. {
  88. // Set the input name
  89. $attributes['name'] = $name;
  90. // Set the input value
  91. $attributes['value'] = $value;
  92. if ( ! isset($attributes['type']))
  93. {
  94. // Default type is text
  95. $attributes['type'] = 'text';
  96. }
  97. return '<input'.HTML::attributes($attributes).' />';
  98. }
  99. /**
  100. * Creates a hidden form input.
  101. *
  102. * echo Form::hidden('csrf', $token);
  103. *
  104. * @param string $name input name
  105. * @param string $value input value
  106. * @param array $attributes html attributes
  107. * @return string
  108. * @uses Form::input
  109. */
  110. public static function hidden($name, $value = NULL, array $attributes = NULL)
  111. {
  112. $attributes['type'] = 'hidden';
  113. return Form::input($name, $value, $attributes);
  114. }
  115. /**
  116. * Creates a password form input.
  117. *
  118. * echo Form::password('password');
  119. *
  120. * @param string $name input name
  121. * @param string $value input value
  122. * @param array $attributes html attributes
  123. * @return string
  124. * @uses Form::input
  125. */
  126. public static function password($name, $value = NULL, array $attributes = NULL)
  127. {
  128. $attributes['type'] = 'password';
  129. return Form::input($name, $value, $attributes);
  130. }
  131. /**
  132. * Creates a file upload form input. No input value can be specified.
  133. *
  134. * echo Form::file('image');
  135. *
  136. * @param string $name input name
  137. * @param array $attributes html attributes
  138. * @return string
  139. * @uses Form::input
  140. */
  141. public static function file($name, array $attributes = NULL)
  142. {
  143. $attributes['type'] = 'file';
  144. return Form::input($name, NULL, $attributes);
  145. }
  146. /**
  147. * Creates a checkbox form input.
  148. *
  149. * echo Form::checkbox('remember_me', 1, (bool) $remember);
  150. *
  151. * @param string $name input name
  152. * @param string $value input value
  153. * @param boolean $checked checked status
  154. * @param array $attributes html attributes
  155. * @return string
  156. * @uses Form::input
  157. */
  158. public static function checkbox($name, $value = NULL, $checked = FALSE, array $attributes = NULL)
  159. {
  160. $attributes['type'] = 'checkbox';
  161. if ($checked === TRUE)
  162. {
  163. // Make the checkbox active
  164. $attributes[] = 'checked';
  165. }
  166. return Form::input($name, $value, $attributes);
  167. }
  168. /**
  169. * Creates a radio form input.
  170. *
  171. * echo Form::radio('like_cats', 1, $cats);
  172. * echo Form::radio('like_cats', 0, ! $cats);
  173. *
  174. * @param string $name input name
  175. * @param string $value input value
  176. * @param boolean $checked checked status
  177. * @param array $attributes html attributes
  178. * @return string
  179. * @uses Form::input
  180. */
  181. public static function radio($name, $value = NULL, $checked = FALSE, array $attributes = NULL)
  182. {
  183. $attributes['type'] = 'radio';
  184. if ($checked === TRUE)
  185. {
  186. // Make the radio active
  187. $attributes[] = 'checked';
  188. }
  189. return Form::input($name, $value, $attributes);
  190. }
  191. /**
  192. * Creates a textarea form input.
  193. *
  194. * echo Form::textarea('about', $about);
  195. *
  196. * @param string $name textarea name
  197. * @param string $body textarea body
  198. * @param array $attributes html attributes
  199. * @param boolean $double_encode encode existing HTML characters
  200. * @return string
  201. * @uses HTML::attributes
  202. * @uses HTML::chars
  203. */
  204. public static function textarea($name, $body = '', array $attributes = NULL, $double_encode = TRUE)
  205. {
  206. // Set the input name
  207. $attributes['name'] = $name;
  208. // Add default rows and cols attributes (required)
  209. $attributes += ['rows' => 10, 'cols' => 50];
  210. return '<textarea'.HTML::attributes($attributes).'>'.HTML::chars($body, $double_encode).'</textarea>';
  211. }
  212. /**
  213. * Creates a select form input.
  214. *
  215. * echo Form::select('country', $countries, $country);
  216. *
  217. * [!!] Support for multiple selected options was added in v3.0.7.
  218. *
  219. * @param string $name input name
  220. * @param array $options available options
  221. * @param mixed $selected selected option string, or an array of selected options
  222. * @param array $attributes html attributes
  223. * @return string
  224. * @uses HTML::attributes
  225. */
  226. public static function select($name, array $options = NULL, $selected = NULL, array $attributes = NULL)
  227. {
  228. // Set the input name
  229. $attributes['name'] = $name;
  230. if (is_array($selected))
  231. {
  232. // This is a multi-select, god save us!
  233. $attributes[] = 'multiple';
  234. }
  235. if ( ! is_array($selected))
  236. {
  237. if ($selected === NULL)
  238. {
  239. // Use an empty array
  240. $selected = [];
  241. }
  242. else
  243. {
  244. // Convert the selected options to an array
  245. $selected = [ (string) $selected];
  246. }
  247. }
  248. if (empty($options))
  249. {
  250. // There are no options
  251. $options = '';
  252. }
  253. else
  254. {
  255. foreach ($options as $value => $name)
  256. {
  257. if (is_array($name))
  258. {
  259. // Create a new optgroup
  260. $group = ['label' => $value];
  261. // Create a new list of options
  262. $_options = [];
  263. foreach ($name as $_value => $_name)
  264. {
  265. // Force value to be string
  266. $_value = (string) $_value;
  267. // Create a new attribute set for this option
  268. $option = ['value' => $_value];
  269. if (in_array($_value, $selected))
  270. {
  271. // This option is selected
  272. $option[] = 'selected';
  273. }
  274. // Change the option to the HTML string
  275. $_options[] = '<option'.HTML::attributes($option).'>'.HTML::chars($_name, FALSE).'</option>';
  276. }
  277. // Compile the options into a string
  278. $_options = "\n".implode("\n", $_options)."\n";
  279. $options[$value] = '<optgroup'.HTML::attributes($group).'>'.$_options.'</optgroup>';
  280. }
  281. else
  282. {
  283. // Force value to be string
  284. $value = (string) $value;
  285. // Create a new attribute set for this option
  286. $option = ['value' => $value];
  287. if (in_array($value, $selected))
  288. {
  289. // This option is selected
  290. $option[] = 'selected';
  291. }
  292. // Change the option to the HTML string
  293. $options[$value] = '<option'.HTML::attributes($option).'>'.HTML::chars($name, FALSE).'</option>';
  294. }
  295. }
  296. // Compile the options into a single string
  297. $options = "\n".implode("\n", $options)."\n";
  298. }
  299. return '<select'.HTML::attributes($attributes).'>'.$options.'</select>';
  300. }
  301. /**
  302. * Creates a submit form input.
  303. *
  304. * echo Form::submit(NULL, 'Login');
  305. *
  306. * @param string $name input name
  307. * @param string $value input value
  308. * @param array $attributes html attributes
  309. * @return string
  310. * @uses Form::input
  311. */
  312. public static function submit($name, $value, array $attributes = NULL)
  313. {
  314. $attributes['type'] = 'submit';
  315. return Form::input($name, $value, $attributes);
  316. }
  317. /**
  318. * Creates a image form input.
  319. *
  320. * echo Form::image(NULL, NULL, array('src' => 'media/img/login.png'));
  321. *
  322. * @param string $name input name
  323. * @param string $value input value
  324. * @param array $attributes html attributes
  325. * @param boolean $index add index file to URL?
  326. * @return string
  327. * @uses Form::input
  328. */
  329. public static function image($name, $value, array $attributes = NULL, $index = FALSE)
  330. {
  331. if ( ! empty($attributes['src']))
  332. {
  333. if (strpos($attributes['src'], '://') === FALSE AND strncmp($attributes['src'], '//', 2))
  334. {
  335. // Add the base URL
  336. $attributes['src'] = URL::base($index).$attributes['src'];
  337. }
  338. }
  339. $attributes['type'] = 'image';
  340. return Form::input($name, $value, $attributes);
  341. }
  342. /**
  343. * Creates a button form input. Note that the body of a button is NOT escaped,
  344. * to allow images and other HTML to be used.
  345. *
  346. * echo Form::button('save', 'Save Profile', array('type' => 'submit'));
  347. *
  348. * @param string $name input name
  349. * @param string $body input value
  350. * @param array $attributes html attributes
  351. * @return string
  352. * @uses HTML::attributes
  353. */
  354. public static function button($name, $body, array $attributes = NULL)
  355. {
  356. // Set the input name
  357. $attributes['name'] = $name;
  358. return '<button'.HTML::attributes($attributes).'>'.$body.'</button>';
  359. }
  360. /**
  361. * Creates a form label. Label text is not automatically translated.
  362. *
  363. * echo Form::label('username', 'Username');
  364. *
  365. * @param string $input target input
  366. * @param string $text label text
  367. * @param array $attributes html attributes
  368. * @return string
  369. * @uses HTML::attributes
  370. */
  371. public static function label($input, $text = NULL, array $attributes = NULL)
  372. {
  373. if ($text === NULL)
  374. {
  375. // Use the input name as the text
  376. $text = ucwords(preg_replace('/[\W_]+/', ' ', $input));
  377. }
  378. // Set the label target
  379. $attributes['for'] = $input;
  380. return '<label'.HTML::attributes($attributes).'>'.$text.'</label>';
  381. }
  382. }