PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Gallary/modules/forge/libraries/Form_Input.php

https://bitbucket.org/JakePratt/kupcakz.com
PHP | 555 lines | 347 code | 61 blank | 147 comment | 55 complexity | 7fb098644a1b2ff87c3401460502cfd3 MD5 | raw file
  1. <?php defined("SYSPATH") or die("No direct script access.");
  2. /**
  3. * FORGE base input library.
  4. *
  5. * $Id: Form_Input.php 3326 2008-08-09 21:24:30Z Shadowhand $
  6. *
  7. * @package Forge
  8. * @author Kohana Team
  9. * @copyright (c) 2007-2008 Kohana Team
  10. * @license http://kohanaphp.com/license.html
  11. */
  12. class Form_Input_Core {
  13. // Input method
  14. public $method;
  15. // Element data
  16. protected $data = array
  17. (
  18. 'type' => 'text',
  19. 'class' => 'textbox',
  20. 'value' => ''
  21. );
  22. // Protected data keys
  23. protected $protect = array();
  24. // Validation rules, matches, and callbacks
  25. protected $rules = array();
  26. protected $matches = array();
  27. protected $callbacks = array();
  28. // Validation check
  29. protected $is_valid;
  30. // Errors
  31. protected $errors = array();
  32. protected $error_messages = array();
  33. /**
  34. * Sets the input element name.
  35. */
  36. public function __construct($name)
  37. {
  38. $this->data['name'] = $name;
  39. }
  40. /**
  41. * Sets form attributes, or return rules.
  42. */
  43. public function __call($method, $args)
  44. {
  45. if ($method == 'rules')
  46. {
  47. if (empty($args))
  48. return $this->rules;
  49. // Set rules and action
  50. $rules = $args[0];
  51. $action = substr($rules, 0, 1);
  52. if (in_array($action, array('-', '+', '=')))
  53. {
  54. // Remove the action from the rules
  55. $rules = substr($rules, 1);
  56. }
  57. else
  58. {
  59. // Default action is append
  60. $action = '';
  61. }
  62. $this->add_rules(explode('|', $rules), $action);
  63. }
  64. elseif ($method == 'name')
  65. {
  66. // Do nothing. The name should stay static once it is set.
  67. }
  68. else
  69. {
  70. $this->data[$method] = $args[0];
  71. }
  72. return $this;
  73. }
  74. /**
  75. * Returns form attributes.
  76. *
  77. * @param string attribute name
  78. * @return string
  79. */
  80. public function __get($key)
  81. {
  82. if (isset($this->data[$key]))
  83. {
  84. return $this->data[$key];
  85. }
  86. }
  87. /**
  88. * Sets a form element that this element must match the value of.
  89. *
  90. * @chainable
  91. * @param object another Forge input
  92. * @return object
  93. */
  94. public function matches($input)
  95. {
  96. if ( ! in_array($input, $this->matches, TRUE))
  97. {
  98. $this->matches[] = $input;
  99. }
  100. return $this;
  101. }
  102. /**
  103. * Sets a callback method as a rule for this input.
  104. *
  105. * @chainable
  106. * @param callback
  107. * @return object
  108. */
  109. public function callback($callback)
  110. {
  111. if ( ! in_array($callback, $this->callbacks, TRUE))
  112. {
  113. $this->callbacks[] = $callback;
  114. }
  115. return $this;
  116. }
  117. /**
  118. * Sets or returns the input label.
  119. *
  120. * @chainable
  121. * @param string label to set
  122. * @return string|object
  123. */
  124. public function label($val = NULL)
  125. {
  126. if ($val === NULL)
  127. {
  128. if (isset($this->data['name']) AND isset($this->data['label']))
  129. {
  130. return form::label($this->data['name'], $this->data['label']);
  131. }
  132. return FALSE;
  133. }
  134. else
  135. {
  136. $this->data['label'] = ($val === TRUE) ? utf8::ucwords(inflector::humanize($this->name)) : $val;
  137. return $this;
  138. }
  139. }
  140. /**
  141. * Set or return the error message.
  142. *
  143. * @chainable
  144. * @param string error message
  145. * @return strong|object
  146. */
  147. public function message($val = NULL)
  148. {
  149. if ($val === NULL)
  150. {
  151. if (isset($this->data['message']))
  152. return $this->data['message'];
  153. }
  154. else
  155. {
  156. $this->data['message'] = $val;
  157. return $this;
  158. }
  159. }
  160. /**
  161. * Runs validation and returns the element HTML.
  162. *
  163. * @return string
  164. */
  165. public function render()
  166. {
  167. // Make sure validation runs
  168. $this->validate();
  169. return $this->html_element();
  170. }
  171. /**
  172. * Returns the form input HTML.
  173. *
  174. * @return string
  175. */
  176. protected function html_element()
  177. {
  178. $data = $this->data;
  179. unset($data['label']);
  180. unset($data['message']);
  181. return form::input($data);
  182. }
  183. /**
  184. * Replace, remove, or append rules.
  185. *
  186. * @param array rules to change
  187. * @param string action to use: replace, remove, append
  188. */
  189. protected function add_rules( array $rules, $action)
  190. {
  191. if ($action === '=')
  192. {
  193. // Just replace the rules
  194. $this->rules = $rules;
  195. return;
  196. }
  197. foreach ($rules as $rule)
  198. {
  199. if ($action === '-')
  200. {
  201. if (($key = array_search($rule, $this->rules)) !== FALSE)
  202. {
  203. // Remove the rule
  204. unset($this->rules[$key]);
  205. }
  206. }
  207. else
  208. {
  209. if ( ! in_array($rule, $this->rules))
  210. {
  211. if ($action == '+')
  212. {
  213. array_unshift($this->rules, $rule);
  214. }
  215. else
  216. {
  217. $this->rules[] = $rule;
  218. }
  219. }
  220. }
  221. }
  222. }
  223. /**
  224. * Add an error to the input.
  225. *
  226. * @chainable
  227. * @return object
  228. */
  229. public function add_error($key, $val)
  230. {
  231. if ( ! isset($this->errors[$key]))
  232. {
  233. $this->errors[$key] = $val;
  234. }
  235. return $this;
  236. }
  237. /**
  238. * Set or return the error messages.
  239. *
  240. * @chainable
  241. * @param string|array failed validation function, or an array of messages
  242. * @param string error message
  243. * @return object|array
  244. */
  245. public function error_messages($func = NULL, $message = NULL)
  246. {
  247. // Set custom error messages
  248. if ( ! empty($func))
  249. {
  250. if (is_array($func))
  251. {
  252. // Replace all
  253. $this->error_messages = $func;
  254. }
  255. else
  256. {
  257. if (empty($message))
  258. {
  259. // Single error, replaces all others
  260. $this->error_messages = $func;
  261. }
  262. else
  263. {
  264. // Add custom error
  265. $this->error_messages[$func] = $message;
  266. }
  267. }
  268. return $this;
  269. }
  270. // Make sure validation runs
  271. is_null($this->is_valid) and $this->validate();
  272. // Return single error
  273. if ( ! is_array($this->error_messages) AND ! empty($this->errors))
  274. return array($this->error_messages);
  275. $messages = array();
  276. foreach ($this->errors as $func => $args)
  277. {
  278. if (is_string($args))
  279. {
  280. $error = $args;
  281. }
  282. else
  283. {
  284. // Force args to be an array
  285. $args = is_array($args) ? $args : array();
  286. // Add the label or name to the beginning of the args
  287. array_unshift($args, $this->label ? mb_strtolower($this->label) : $this->name);
  288. if (isset($this->error_messages[$func]))
  289. {
  290. // Use custom error message
  291. $error = vsprintf($this->error_messages[$func], $args);
  292. }
  293. else
  294. {
  295. // Get the proper i18n entry, very hacky but it works
  296. switch ($func)
  297. {
  298. case 'valid_url':
  299. case 'valid_email':
  300. case 'valid_ip':
  301. // Fetch an i18n error message
  302. $error = 'validation.'.$func;
  303. break;
  304. case substr($func, 0, 6) === 'valid_':
  305. // Strip 'valid_' from func name
  306. $func = (substr($func, 0, 6) === 'valid_') ? substr($func, 6) : $func;
  307. case 'alpha':
  308. case 'alpha_dash':
  309. case 'digit':
  310. case 'numeric':
  311. // i18n strings have to be inserted into valid_type
  312. $args[] = 'validation.'.$func;
  313. $error = 'validation.valid_type';
  314. break;
  315. default:
  316. $error = 'validation.'.$func;
  317. }
  318. }
  319. }
  320. // Add error to list
  321. $messages[] = $error;
  322. }
  323. return $messages;
  324. }
  325. /**
  326. * Get the global input value.
  327. *
  328. * @return string|bool
  329. */
  330. protected function input_value($name = array())
  331. {
  332. // Get the Input instance
  333. $input = Input::instance();
  334. // Fetch the method for this object
  335. $method = $this->method;
  336. return $input->$method($name, NULL);
  337. }
  338. /**
  339. * Load the value of the input, if form data is present.
  340. *
  341. * @return void
  342. */
  343. protected function load_value()
  344. {
  345. if (is_bool($this->is_valid))
  346. return;
  347. if ($name = $this->name)
  348. {
  349. // Load POSTed value, but only for named inputs
  350. $this->data['value'] = $this->input_value($name);
  351. }
  352. if (is_string($this->data['value']))
  353. {
  354. // Trim string values
  355. $this->data['value'] = trim($this->data['value']);
  356. }
  357. }
  358. /**
  359. * Validate this input based on the set rules.
  360. *
  361. * @return bool
  362. */
  363. public function validate()
  364. {
  365. // Validation has already run
  366. if (is_bool($this->is_valid))
  367. return $this->is_valid;
  368. // No data to validate
  369. if ($this->input_value() == FALSE)
  370. return $this->is_valid = FALSE;
  371. // Load the submitted value
  372. $this->load_value();
  373. // No rules to validate
  374. if (count($this->rules) == 0 AND count($this->matches) == 0 AND count($this->callbacks) == 0)
  375. return $this->is_valid = TRUE;
  376. if ( ! empty($this->rules))
  377. {
  378. foreach ($this->rules as $rule)
  379. {
  380. if (($offset = strpos($rule, '[')) !== FALSE)
  381. {
  382. // Get the args
  383. $args = preg_split('/, ?/', trim(substr($rule, $offset), '[]'));
  384. // Remove the args from the rule
  385. $rule = substr($rule, 0, $offset);
  386. }
  387. if (substr($rule, 0, 6) === 'valid_' AND method_exists('valid', substr($rule, 6)))
  388. {
  389. $func = substr($rule, 6);
  390. if ($this->value AND ! valid::$func($this->value))
  391. {
  392. $this->errors[$rule] = TRUE;
  393. }
  394. }
  395. elseif (method_exists($this, 'rule_'.$rule))
  396. {
  397. // The rule function is always prefixed with rule_
  398. $rule = 'rule_'.$rule;
  399. if (isset($args))
  400. {
  401. // Manually call up to 2 args for speed
  402. switch (count($args))
  403. {
  404. case 1:
  405. $this->$rule($args[0]);
  406. break;
  407. case 2:
  408. $this->$rule($args[0], $args[1]);
  409. break;
  410. default:
  411. call_user_func_array(array($this, $rule), $args);
  412. break;
  413. }
  414. }
  415. else
  416. {
  417. // Just call the rule
  418. $this->$rule();
  419. }
  420. // Prevent args from being re-used
  421. unset($args);
  422. }
  423. else
  424. {
  425. throw new Kohana_Exception('validation.invalid_rule', $rule);
  426. }
  427. // Stop when an error occurs
  428. if ( ! empty($this->errors))
  429. break;
  430. }
  431. }
  432. if ( ! empty($this->matches))
  433. {
  434. foreach ($this->matches as $input)
  435. {
  436. if ($this->value != $input->value)
  437. {
  438. // Field does not match
  439. $this->errors['matches'] = array($input->label ? mb_strtolower($input->label) : $input->name);
  440. break;
  441. }
  442. }
  443. }
  444. if ( ! empty($this->callbacks))
  445. {
  446. foreach ($this->callbacks as $callback)
  447. {
  448. call_user_func($callback, $this);
  449. // Stop when an error occurs
  450. if ( ! empty($this->errors))
  451. break;
  452. }
  453. }
  454. // If there are errors, validation failed
  455. return $this->is_valid = empty($this->errors);
  456. }
  457. /**
  458. * Validate required.
  459. */
  460. protected function rule_required()
  461. {
  462. if ($this->value === '' OR $this->value === NULL)
  463. {
  464. $this->errors['required'] = TRUE;
  465. }
  466. }
  467. /**
  468. * Validate length.
  469. */
  470. protected function rule_length($min, $max = NULL)
  471. {
  472. // Get the length, return if zero
  473. if (($length = mb_strlen($this->value)) === 0)
  474. return;
  475. if ($max == NULL)
  476. {
  477. if ($length != $min)
  478. {
  479. $this->errors['exact_length'] = array($min);
  480. }
  481. }
  482. else
  483. {
  484. if ($length < $min)
  485. {
  486. $this->errors['min_length'] = array($min);
  487. }
  488. elseif ($length > $max)
  489. {
  490. $this->errors['max_length'] = array($max);
  491. }
  492. }
  493. }
  494. } // End Form Input