validator.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. <?php namespace Laravel; use Closure;
  2. class Validator {
  3. /**
  4. * The array being validated.
  5. *
  6. * @var array
  7. */
  8. public $attributes;
  9. /**
  10. * The post-validation error messages.
  11. *
  12. * @var Messages
  13. */
  14. public $errors;
  15. /**
  16. * The validation rules.
  17. *
  18. * @var array
  19. */
  20. protected $rules = array();
  21. /**
  22. * The validation messages.
  23. *
  24. * @var array
  25. */
  26. protected $messages = array();
  27. /**
  28. * The database connection that should be used by the validator.
  29. *
  30. * @var Database\Connection
  31. */
  32. protected $db;
  33. /**
  34. * The bundle for which the validation is being run.
  35. *
  36. * @var string
  37. */
  38. protected $bundle = DEFAULT_BUNDLE;
  39. /**
  40. * The language that should be used when retrieving error messages.
  41. *
  42. * @var string
  43. */
  44. protected $language;
  45. /**
  46. * The size related validation rules.
  47. *
  48. * @var array
  49. */
  50. protected $size_rules = array('size', 'between', 'min', 'max');
  51. /**
  52. * The numeric related validation rules.
  53. *
  54. * @var array
  55. */
  56. protected $numeric_rules = array('numeric', 'integer');
  57. /**
  58. * The registered custom validators.
  59. *
  60. * @var array
  61. */
  62. protected static $validators = array();
  63. /**
  64. * Create a new validator instance.
  65. *
  66. * @param mixed $attributes
  67. * @param array $rules
  68. * @param array $messages
  69. * @return void
  70. */
  71. public function __construct($attributes, $rules, $messages = array())
  72. {
  73. foreach ($rules as $key => &$rule)
  74. {
  75. $rule = (is_string($rule)) ? explode('|', $rule) : $rule;
  76. }
  77. $this->rules = $rules;
  78. $this->messages = $messages;
  79. $this->attributes = (is_object($attributes)) ? get_object_vars($attributes) : $attributes;
  80. }
  81. /**
  82. * Create a new validator instance.
  83. *
  84. * @param array $attributes
  85. * @param array $rules
  86. * @param array $messages
  87. * @return Validator
  88. */
  89. public static function make($attributes, $rules, $messages = array())
  90. {
  91. return new static($attributes, $rules, $messages);
  92. }
  93. /**
  94. * Register a custom validator.
  95. *
  96. * @param string $name
  97. * @param Closure $validator
  98. * @return void
  99. */
  100. public static function register($name, $validator)
  101. {
  102. static::$validators[$name] = $validator;
  103. }
  104. /**
  105. * Validate the target array using the specified validation rules.
  106. *
  107. * @return bool
  108. */
  109. public function passes()
  110. {
  111. return $this->valid();
  112. }
  113. /**
  114. * Validate the target array using the specified validation rules.
  115. *
  116. * @return bool
  117. */
  118. public function fails()
  119. {
  120. return $this->invalid();
  121. }
  122. /**
  123. * Validate the target array using the specified validation rules.
  124. *
  125. * @return bool
  126. */
  127. public function invalid()
  128. {
  129. return ! $this->valid();
  130. }
  131. /**
  132. * Validate the target array using the specified validation rules.
  133. *
  134. * @return bool
  135. */
  136. public function valid()
  137. {
  138. $this->errors = new Messages;
  139. foreach ($this->rules as $attribute => $rules)
  140. {
  141. foreach ($rules as $rule) $this->check($attribute, $rule);
  142. }
  143. return count($this->errors->messages) == 0;
  144. }
  145. /**
  146. * Evaluate an attribute against a validation rule.
  147. *
  148. * @param string $attribute
  149. * @param string $rule
  150. * @return void
  151. */
  152. protected function check($attribute, $rule)
  153. {
  154. list($rule, $parameters) = $this->parse($rule);
  155. $value = array_get($this->attributes, $attribute);
  156. // Before running the validator, we need to verify that the attribute and rule
  157. // combination is actually validatable. Only the "accepted" rule implies that
  158. // the attribute is "required", so if the attribute does not exist, the other
  159. // rules will not be run for the attribute.
  160. $validatable = $this->validatable($rule, $attribute, $value);
  161. if ($validatable and ! $this->{'validate_'.$rule}($attribute, $value, $parameters, $this))
  162. {
  163. $this->error($attribute, $rule, $parameters);
  164. }
  165. }
  166. /**
  167. * Determine if an attribute is validatable.
  168. *
  169. * To be considered validatable, the attribute must either exist, or the rule
  170. * being checked must implicitly validate "required", such as the "required"
  171. * rule or the "accepted" rule.
  172. *
  173. * @param string $rule
  174. * @param string $attribute
  175. * @param mixed $value
  176. * @return bool
  177. */
  178. protected function validatable($rule, $attribute, $value)
  179. {
  180. return $this->validate_required($attribute, $value) or $this->implicit($rule);
  181. }
  182. /**
  183. * Determine if a given rule implies that the attribute is required.
  184. *
  185. * @param string $rule
  186. * @return bool
  187. */
  188. protected function implicit($rule)
  189. {
  190. return $rule == 'required' or $rule == 'accepted' or $rule == 'required_with';
  191. }
  192. /**
  193. * Add an error message to the validator's collection of messages.
  194. *
  195. * @param string $attribute
  196. * @param string $rule
  197. * @param array $parameters
  198. * @return void
  199. */
  200. protected function error($attribute, $rule, $parameters)
  201. {
  202. $message = $this->replace($this->message($attribute, $rule), $attribute, $rule, $parameters);
  203. $this->errors->add($attribute, $message);
  204. }
  205. /**
  206. * Validate that a required attribute exists in the attributes array.
  207. *
  208. * @param string $attribute
  209. * @param mixed $value
  210. * @return bool
  211. */
  212. protected function validate_required($attribute, $value)
  213. {
  214. if (is_null($value))
  215. {
  216. return false;
  217. }
  218. elseif (is_string($value) and trim($value) === '')
  219. {
  220. return false;
  221. }
  222. elseif ( ! is_null(Input::file($attribute)) and is_array($value) and $value['tmp_name'] == '')
  223. {
  224. return false;
  225. }
  226. return true;
  227. }
  228. /**
  229. * Validate that an attribute exists in the attributes array, if another
  230. * attribute exists in the attributes array.
  231. *
  232. * @param string $attribute
  233. * @param mixed $value
  234. * @param array $parameters
  235. * @return bool
  236. */
  237. protected function validate_required_with($attribute, $value, $parameters)
  238. {
  239. $other = $parameters[0];
  240. $other_value = array_get($this->attributes, $other);
  241. if ($this->validate_required($other, $other_value))
  242. {
  243. return $this->validate_required($attribute, $value);
  244. }
  245. return true;
  246. }
  247. /**
  248. * Validate that an attribute has a matching confirmation attribute.
  249. *
  250. * @param string $attribute
  251. * @param mixed $value
  252. * @return bool
  253. */
  254. protected function validate_confirmed($attribute, $value)
  255. {
  256. return $this->validate_same($attribute, $value, array($attribute.'_confirmation'));
  257. }
  258. /**
  259. * Validate that an attribute was "accepted".
  260. *
  261. * This validation rule implies the attribute is "required".
  262. *
  263. * @param string $attribute
  264. * @param mixed $value
  265. * @return bool
  266. */
  267. protected function validate_accepted($attribute, $value)
  268. {
  269. return $this->validate_required($attribute, $value) and ($value == 'yes' or $value == '1' or $value == 'on');
  270. }
  271. /**
  272. * Validate that an attribute is the same as another attribute.
  273. *
  274. * @param string $attribute
  275. * @param mixed $value
  276. * @param array $parameters
  277. * @return bool
  278. */
  279. protected function validate_same($attribute, $value, $parameters)
  280. {
  281. $other = $parameters[0];
  282. return array_key_exists($other, $this->attributes) and $value == $this->attributes[$other];
  283. }
  284. /**
  285. * Validate that an attribute is different from another attribute.
  286. *
  287. * @param string $attribute
  288. * @param mixed $value
  289. * @param array $parameters
  290. * @return bool
  291. */
  292. protected function validate_different($attribute, $value, $parameters)
  293. {
  294. $other = $parameters[0];
  295. return array_key_exists($other, $this->attributes) and $value != $this->attributes[$other];
  296. }
  297. /**
  298. * Validate that an attribute is numeric.
  299. *
  300. * @param string $attribute
  301. * @param mixed $value
  302. * @return bool
  303. */
  304. protected function validate_numeric($attribute, $value)
  305. {
  306. return is_numeric($value);
  307. }
  308. /**
  309. * Validate that an attribute is an integer.
  310. *
  311. * @param string $attribute
  312. * @param mixed $value
  313. * @return bool
  314. */
  315. protected function validate_integer($attribute, $value)
  316. {
  317. return filter_var($value, FILTER_VALIDATE_INT) !== false;
  318. }
  319. /**
  320. * Validate the size of an attribute.
  321. *
  322. * @param string $attribute
  323. * @param mixed $value
  324. * @param array $parameters
  325. * @return bool
  326. */
  327. protected function validate_size($attribute, $value, $parameters)
  328. {
  329. return $this->size($attribute, $value) == $parameters[0];
  330. }
  331. /**
  332. * Validate the size of an attribute is between a set of values.
  333. *
  334. * @param string $attribute
  335. * @param mixed $value
  336. * @param array $parameters
  337. * @return bool
  338. */
  339. protected function validate_between($attribute, $value, $parameters)
  340. {
  341. $size = $this->size($attribute, $value);
  342. return $size >= $parameters[0] and $size <= $parameters[1];
  343. }
  344. /**
  345. * Validate the size of an attribute is greater than a minimum value.
  346. *
  347. * @param string $attribute
  348. * @param mixed $value
  349. * @param array $parameters
  350. * @return bool
  351. */
  352. protected function validate_min($attribute, $value, $parameters)
  353. {
  354. return $this->size($attribute, $value) >= $parameters[0];
  355. }
  356. /**
  357. * Validate the size of an attribute is less than a maximum value.
  358. *
  359. * @param string $attribute
  360. * @param mixed $value
  361. * @param array $parameters
  362. * @return bool
  363. */
  364. protected function validate_max($attribute, $value, $parameters)
  365. {
  366. return $this->size($attribute, $value) <= $parameters[0];
  367. }
  368. /**
  369. * Get the size of an attribute.
  370. *
  371. * @param string $attribute
  372. * @param mixed $value
  373. * @return mixed
  374. */
  375. protected function size($attribute, $value)
  376. {
  377. // This method will determine if the attribute is a number, string, or file and
  378. // return the proper size accordingly. If it is a number, the number itself is
  379. // the size; if it is a file, the kilobytes is the size; if it is a
  380. // string, the length is the size.
  381. if (is_numeric($value) and $this->has_rule($attribute, $this->numeric_rules))
  382. {
  383. return $this->attributes[$attribute];
  384. }
  385. elseif (array_key_exists($attribute, Input::file()))
  386. {
  387. return $value['size'] / 1024;
  388. }
  389. else
  390. {
  391. return Str::length(trim($value));
  392. }
  393. }
  394. /**
  395. * Validate an attribute is contained within a list of values.
  396. *
  397. * @param string $attribute
  398. * @param mixed $value
  399. * @param array $parameters
  400. * @return bool
  401. */
  402. protected function validate_in($attribute, $value, $parameters)
  403. {
  404. return in_array($value, $parameters);
  405. }
  406. /**
  407. * Validate an attribute is not contained within a list of values.
  408. *
  409. * @param string $attribute
  410. * @param mixed $value
  411. * @param array $parameters
  412. * @return bool
  413. */
  414. protected function validate_not_in($attribute, $value, $parameters)
  415. {
  416. return ! in_array($value, $parameters);
  417. }
  418. /**
  419. * Validate the uniqueness of an attribute value on a given database table.
  420. *
  421. * If a database column is not specified, the attribute will be used.
  422. *
  423. * @param string $attribute
  424. * @param mixed $value
  425. * @param array $parameters
  426. * @return bool
  427. */
  428. protected function validate_unique($attribute, $value, $parameters)
  429. {
  430. // We allow the table column to be specified just in case the column does
  431. // not have the same name as the attribute. It must be within the second
  432. // parameter position, right after the database table name.
  433. if (isset($parameters[1]))
  434. {
  435. $attribute = $parameters[1];
  436. }
  437. $query = $this->db()->table($parameters[0])->where($attribute, '=', $value);
  438. // We also allow an ID to be specified that will not be included in the
  439. // uniqueness check. This makes updating columns easier since it is
  440. // fine for the given ID to exist in the table.
  441. if (isset($parameters[2]))
  442. {
  443. $id = (isset($parameters[3])) ? $parameters[3] : 'id';
  444. $query->where($id, '<>', $parameters[2]);
  445. }
  446. return $query->count() == 0;
  447. }
  448. /**
  449. * Validate the existence of an attribute value in a database table.
  450. *
  451. * @param string $attribute
  452. * @param mixed $value
  453. * @param array $parameters
  454. * @return bool
  455. */
  456. protected function validate_exists($attribute, $value, $parameters)
  457. {
  458. if (isset($parameters[1])) $attribute = $parameters[1];
  459. // Grab the number of elements we are looking for. If the given value is
  460. // in array, we'll count all of the values in the array, otherwise we
  461. // can just make sure the count is greater or equal to one.
  462. $count = (is_array($value)) ? count($value) : 1;
  463. $query = $this->db()->table($parameters[0]);
  464. // If the given value is an array, we will check for the existence of
  465. // all the values in the database, otherwise we'll check for the
  466. // presence of the single given value in the database.
  467. if (is_array($value))
  468. {
  469. $query = $query->where_in($attribute, $value);
  470. }
  471. else
  472. {
  473. $query = $query->where($attribute, '=', $value);
  474. }
  475. return $query->count() >= $count;
  476. }
  477. /**
  478. * Validate that an attribute is a valid IP.
  479. *
  480. * @param string $attribute
  481. * @param mixed $value
  482. * @return bool
  483. */
  484. protected function validate_ip($attribute, $value)
  485. {
  486. return filter_var($value, FILTER_VALIDATE_IP) !== false;
  487. }
  488. /**
  489. * Validate that an attribute is a valid e-mail address.
  490. *
  491. * @param string $attribute
  492. * @param mixed $value
  493. * @return bool
  494. */
  495. protected function validate_email($attribute, $value)
  496. {
  497. return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
  498. }
  499. /**
  500. * Validate that an attribute is a valid URL.
  501. *
  502. * @param string $attribute
  503. * @param mixed $value
  504. * @return bool
  505. */
  506. protected function validate_url($attribute, $value)
  507. {
  508. return filter_var($value, FILTER_VALIDATE_URL) !== false;
  509. }
  510. /**
  511. * Validate that an attribute is an active URL.
  512. *
  513. * @param string $attribute
  514. * @param mixed $value
  515. * @return bool
  516. */
  517. protected function validate_active_url($attribute, $value)
  518. {
  519. $url = str_replace(array('http://', 'https://', 'ftp://'), '', Str::lower($value));
  520. return (trim($url) !== '') ? checkdnsrr($url) : false;
  521. }
  522. /**
  523. * Validate the MIME type of a file is an image MIME type.
  524. *
  525. * @param string $attribute
  526. * @param mixed $value
  527. * @return bool
  528. */
  529. protected function validate_image($attribute, $value)
  530. {
  531. return $this->validate_mimes($attribute, $value, array('jpg', 'png', 'gif', 'bmp'));
  532. }
  533. /**
  534. * Validate that an attribute contains only alphabetic characters.
  535. *
  536. * @param string $attribute
  537. * @param mixed $value
  538. * @return bool
  539. */
  540. protected function validate_alpha($attribute, $value)
  541. {
  542. return preg_match('/^([a-z])+$/i', $value);
  543. }
  544. /**
  545. * Validate that an attribute contains only alpha-numeric characters.
  546. *
  547. * @param string $attribute
  548. * @param mixed $value
  549. * @return bool
  550. */
  551. protected function validate_alpha_num($attribute, $value)
  552. {
  553. return preg_match('/^([a-z0-9])+$/i', $value);
  554. }
  555. /**
  556. * Validate that an attribute contains only alpha-numeric characters, dashes, and underscores.
  557. *
  558. * @param string $attribute
  559. * @param mixed $value
  560. * @return bool
  561. */
  562. protected function validate_alpha_dash($attribute, $value)
  563. {
  564. return preg_match('/^([-a-z0-9_-])+$/i', $value);
  565. }
  566. /**
  567. * Validate that an attribute passes a regular expression check.
  568. *
  569. * @param string $attribute
  570. * @param mixed $value
  571. * @param array $parameters
  572. * @return bool
  573. */
  574. protected function validate_match($attribute, $value, $parameters)
  575. {
  576. return preg_match($parameters[0], $value);
  577. }
  578. /**
  579. * Validate the MIME type of a file upload attribute is in a set of MIME types.
  580. *
  581. * @param string $attribute
  582. * @param array $value
  583. * @param array $parameters
  584. * @return bool
  585. */
  586. protected function validate_mimes($attribute, $value, $parameters)
  587. {
  588. if ( ! is_array($value) or array_get($value, 'tmp_name', '') == '') return true;
  589. foreach ($parameters as $extension)
  590. {
  591. if (File::is($extension, $value['tmp_name']))
  592. {
  593. return true;
  594. }
  595. }
  596. return false;
  597. }
  598. /**
  599. * Validate that an attribute is an array
  600. *
  601. * @param string $attribute
  602. * @param mixed $value
  603. * @return bool
  604. */
  605. protected function validate_array($attribute, $value)
  606. {
  607. return is_array($value);
  608. }
  609. /**
  610. * Validate that an attribute of type array has a specific count
  611. *
  612. * @param string $attribute
  613. * @param mixed $value
  614. * @param array $parameters
  615. * @return bool
  616. */
  617. protected function validate_count($attribute, $value, $parameters)
  618. {
  619. return (is_array($value) && count($value) == $parameters[0]);
  620. }
  621. /**
  622. * Validate that an attribute of type array has a minimum of elements.
  623. *
  624. * @param string $attribute
  625. * @param mixed $value
  626. * @param array $parameters
  627. * @return bool
  628. */
  629. protected function validate_countmin($attribute, $value, $parameters)
  630. {
  631. return (is_array($value) && count($value) >= $parameters[0]);
  632. }
  633. /**
  634. * Validate that an attribute of type array has a maximum of elements.
  635. *
  636. * @param string $attribute
  637. * @param mixed $value
  638. * @param array $parameters
  639. * @return bool
  640. */
  641. protected function validate_countmax($attribute, $value, $parameters)
  642. {
  643. return (is_array($value) && count($value) <= $parameters[0]);
  644. }
  645. /**
  646. * Validate that an attribute of type array has elements between max and min.
  647. *
  648. * @param string $attribute
  649. * @param mixed $value
  650. * @param array $parameters
  651. * @return bool
  652. */
  653. protected function validate_countbetween($attribute, $value, $parameters)
  654. {
  655. return (is_array($value) && count($value) >= $parameters[0] && count($value) <= $parameters[1] );
  656. }
  657. /**
  658. * Validate the date is before a given date.
  659. *
  660. * @param string $attribute
  661. * @param mixed $value
  662. * @param array $parameters
  663. * @return bool
  664. */
  665. protected function validate_before($attribute, $value, $parameters)
  666. {
  667. return (strtotime($value) < strtotime($parameters[0]));
  668. }
  669. /**
  670. * Validate the date is after a given date.
  671. *
  672. * @param string $attribute
  673. * @param mixed $value
  674. * @param array $parameters
  675. * @return bool
  676. */
  677. protected function validate_after($attribute, $value, $parameters)
  678. {
  679. return (strtotime($value) > strtotime($parameters[0]));
  680. }
  681. /**
  682. * Validate the date conforms to a given format.
  683. *
  684. * @param string $attribute
  685. * @param mixed $value
  686. * @param array $parameters
  687. * @return bool
  688. */
  689. protected function validate_date_format($attribute, $value, $parameters)
  690. {
  691. return date_create_from_format($parameters[0], $value) !== false;
  692. }
  693. /**
  694. * Get the proper error message for an attribute and rule.
  695. *
  696. * @param string $attribute
  697. * @param string $rule
  698. * @return string
  699. */
  700. protected function message($attribute, $rule)
  701. {
  702. $bundle = Bundle::prefix($this->bundle);
  703. // First we'll check for developer specified, attribute specific messages.
  704. // These messages take first priority. They allow the fine-grained tuning
  705. // of error messages for each rule.
  706. $custom = $attribute.'_'.$rule;
  707. if (array_key_exists($custom, $this->messages))
  708. {
  709. return $this->messages[$custom];
  710. }
  711. elseif (Lang::has($custom = "{$bundle}validation.custom.{$custom}", $this->language))
  712. {
  713. return Lang::line($custom)->get($this->language);
  714. }
  715. // Next we'll check for developer specified, rule specific error messages.
  716. // These allow the developer to override the error message for an entire
  717. // rule, regardless of the attribute being validated by that rule.
  718. elseif (array_key_exists($rule, $this->messages))
  719. {
  720. return $this->messages[$rule];
  721. }
  722. // If the rule being validated is a "size" rule, we will need to gather
  723. // the specific size message for the type of attribute being validated,
  724. // either a number, file, or string.
  725. elseif (in_array($rule, $this->size_rules))
  726. {
  727. return $this->size_message($bundle, $attribute, $rule);
  728. }
  729. // If no developer specified messages have been set, and no other special
  730. // messages apply to the rule, we will just pull the default validation
  731. // message from the validation language file.
  732. else
  733. {
  734. $line = "{$bundle}validation.{$rule}";
  735. return Lang::line($line)->get($this->language);
  736. }
  737. }
  738. /**
  739. * Get the proper error message for an attribute and size rule.
  740. *
  741. * @param string $bundle
  742. * @param string $attribute
  743. * @param string $rule
  744. * @return string
  745. */
  746. protected function size_message($bundle, $attribute, $rule)
  747. {
  748. // There are three different types of size validations. The attribute
  749. // may be either a number, file, or a string, so we'll check a few
  750. // things to figure out which one it is.
  751. if ($this->has_rule($attribute, $this->numeric_rules))
  752. {
  753. $line = 'numeric';
  754. }
  755. // We assume that attributes present in the $_FILES array are files,
  756. // which makes sense. If the attribute doesn't have numeric rules
  757. // and isn't a file, it's a string.
  758. elseif (array_key_exists($attribute, Input::file()))
  759. {
  760. $line = 'file';
  761. }
  762. else
  763. {
  764. $line = 'string';
  765. }
  766. return Lang::line("{$bundle}validation.{$rule}.{$line}")->get($this->language);
  767. }
  768. /**
  769. * Replace all error message place-holders with actual values.
  770. *
  771. * @param string $message
  772. * @param string $attribute
  773. * @param string $rule
  774. * @param array $parameters
  775. * @return string
  776. */
  777. protected function replace($message, $attribute, $rule, $parameters)
  778. {
  779. $message = str_replace(':attribute', $this->attribute($attribute), $message);
  780. if (method_exists($this, $replacer = 'replace_'.$rule))
  781. {
  782. $message = $this->$replacer($message, $attribute, $rule, $parameters);
  783. }
  784. return $message;
  785. }
  786. /**
  787. * Replace all place-holders for the required_with rule.
  788. *
  789. * @param string $message
  790. * @param string $attribute
  791. * @param string $rule
  792. * @param array $parameters
  793. * @return string
  794. */
  795. protected function replace_required_with($message, $attribute, $rule, $parameters)
  796. {
  797. return str_replace(':field', $this->attribute($parameters[0]), $message);
  798. }
  799. /**
  800. * Replace all place-holders for the between rule.
  801. *
  802. * @param string $message
  803. * @param string $attribute
  804. * @param string $rule
  805. * @param array $parameters
  806. * @return string
  807. */
  808. protected function replace_between($message, $attribute, $rule, $parameters)
  809. {
  810. return str_replace(array(':min', ':max'), $parameters, $message);
  811. }
  812. /**
  813. * Replace all place-holders for the size rule.
  814. *
  815. * @param string $message
  816. * @param string $attribute
  817. * @param string $rule
  818. * @param array $parameters
  819. * @return string
  820. */
  821. protected function replace_size($message, $attribute, $rule, $parameters)
  822. {
  823. return str_replace(':size', $parameters[0], $message);
  824. }
  825. /**
  826. * Replace all place-holders for the min rule.
  827. *
  828. * @param string $message
  829. * @param string $attribute
  830. * @param string $rule
  831. * @param array $parameters
  832. * @return string
  833. */
  834. protected function replace_min($message, $attribute, $rule, $parameters)
  835. {
  836. return str_replace(':min', $parameters[0], $message);
  837. }
  838. /**
  839. * Replace all place-holders for the max rule.
  840. *
  841. * @param string $message
  842. * @param string $attribute
  843. * @param string $rule
  844. * @param array $parameters
  845. * @return string
  846. */
  847. protected function replace_max($message, $attribute, $rule, $parameters)
  848. {
  849. return str_replace(':max', $parameters[0], $message);
  850. }
  851. /**
  852. * Replace all place-holders for the in rule.
  853. *
  854. * @param string $message
  855. * @param string $attribute
  856. * @param string $rule
  857. * @param array $parameters
  858. * @return string
  859. */
  860. protected function replace_in($message, $attribute, $rule, $parameters)
  861. {
  862. return str_replace(':values', implode(', ', $parameters), $message);
  863. }
  864. /**
  865. * Replace all place-holders for the not_in rule.
  866. *
  867. * @param string $message
  868. * @param string $attribute
  869. * @param string $rule
  870. * @param array $parameters
  871. * @return string
  872. */
  873. protected function replace_not_in($message, $attribute, $rule, $parameters)
  874. {
  875. return str_replace(':values', implode(', ', $parameters), $message);
  876. }
  877. /**
  878. * Replace all place-holders for the mimes rule.
  879. *
  880. * @param string $message
  881. * @param string $attribute
  882. * @param string $rule
  883. * @param array $parameters
  884. * @return string
  885. */
  886. protected function replace_mimes($message, $attribute, $rule, $parameters)
  887. {
  888. return str_replace(':values', implode(', ', $parameters), $message);
  889. }
  890. /**
  891. * Replace all place-holders for the same rule.
  892. *
  893. * @param string $message
  894. * @param string $attribute
  895. * @param string $rule
  896. * @param array $parameters
  897. * @return string
  898. */
  899. protected function replace_same($message, $attribute, $rule, $parameters)
  900. {
  901. return str_replace(':other', $this->attribute($parameters[0]), $message);
  902. }
  903. /**
  904. * Replace all place-holders for the different rule.
  905. *
  906. * @param string $message
  907. * @param string $attribute
  908. * @param string $rule
  909. * @param array $parameters
  910. * @return string
  911. */
  912. protected function replace_different($message, $attribute, $rule, $parameters)
  913. {
  914. return str_replace(':other', $this->attribute($parameters[0]), $message);
  915. }
  916. /**
  917. * Replace all place-holders for the before rule.
  918. *
  919. * @param string $message
  920. * @param string $attribute
  921. * @param string $rule
  922. * @param array $parameters
  923. * @return string
  924. */
  925. protected function replace_before($message, $attribute, $rule, $parameters)
  926. {
  927. return str_replace(':date', $parameters[0], $message);
  928. }
  929. /**
  930. * Replace all place-holders for the after rule.
  931. *
  932. * @param string $message
  933. * @param string $attribute
  934. * @param string $rule
  935. * @param array $parameters
  936. * @return string
  937. */
  938. protected function replace_after($message, $attribute, $rule, $parameters)
  939. {
  940. return str_replace(':date', $parameters[0], $message);
  941. }
  942. /**
  943. * Replace all place-holders for the count rule.
  944. *
  945. * @param string $message
  946. * @param string $attribute
  947. * @param string $rule
  948. * @param array $parameters
  949. * @return string
  950. */
  951. protected function replace_count($message, $attribute, $rule, $parameters)
  952. {
  953. return str_replace(':count', $parameters[0], $message);
  954. }
  955. /**
  956. * Replace all place-holders for the countmin rule.
  957. *
  958. * @param string $message
  959. * @param string $attribute
  960. * @param string $rule
  961. * @param array $parameters
  962. * @return string
  963. */
  964. protected function replace_countmin($message, $attribute, $rule, $parameters)
  965. {
  966. return str_replace(':min', $parameters[0], $message);
  967. }
  968. /**
  969. * Replace all place-holders for the countmax rule.
  970. *
  971. * @param string $message
  972. * @param string $attribute
  973. * @param string $rule
  974. * @param array $parameters
  975. * @return string
  976. */
  977. protected function replace_countmax($message, $attribute, $rule, $parameters)
  978. {
  979. return str_replace(':max', $parameters[0], $message);
  980. }
  981. /**
  982. * Replace all place-holders for the between rule.
  983. *
  984. * @param string $message
  985. * @param string $attribute
  986. * @param string $rule
  987. * @param array $parameters
  988. * @return string
  989. */
  990. protected function replace_countbetween($message, $attribute, $rule, $parameters)
  991. {
  992. return str_replace(array(':min', ':max'), $parameters, $message);
  993. }
  994. /**
  995. * Get the displayable name for a given attribute.
  996. *
  997. * @param string $attribute
  998. * @return string
  999. */
  1000. protected function attribute($attribute)
  1001. {
  1002. $bundle = Bundle::prefix($this->bundle);
  1003. // More reader friendly versions of the attribute names may be stored
  1004. // in the validation language file, allowing a more readable version
  1005. // of the attribute name in the message.
  1006. $line = "{$bundle}validation.attributes.{$attribute}";
  1007. if (Lang::has($line, $this->language))
  1008. {
  1009. return Lang::line($line)->get($this->language);
  1010. }
  1011. // If no language line has been specified for the attribute, all of
  1012. // the underscores are removed from the attribute name and that
  1013. // will be used as the attribute name.
  1014. else
  1015. {
  1016. return str_replace('_', ' ', $attribute);
  1017. }
  1018. }
  1019. /**
  1020. * Determine if an attribute has a rule assigned to it.
  1021. *
  1022. * @param string $attribute
  1023. * @param array $rules
  1024. * @return bool
  1025. */
  1026. protected function has_rule($attribute, $rules)
  1027. {
  1028. foreach ($this->rules[$attribute] as $rule)
  1029. {
  1030. list($rule, $parameters) = $this->parse($rule);
  1031. if (in_array($rule, $rules)) return true;
  1032. }
  1033. return false;
  1034. }
  1035. /**
  1036. * Extract the rule name and parameters from a rule.
  1037. *
  1038. * @param string $rule
  1039. * @return array
  1040. */
  1041. protected function parse($rule)
  1042. {
  1043. $parameters = array();
  1044. // The format for specifying validation rules and parameters follows a
  1045. // {rule}:{parameters} formatting convention. For instance, the rule
  1046. // "max:3" specifies that the value may only be 3 characters long.
  1047. if (($colon = strpos($rule, ':')) !== false)
  1048. {
  1049. $parameters = str_getcsv(substr($rule, $colon + 1));
  1050. }
  1051. return array(is_numeric($colon) ? substr($rule, 0, $colon) : $rule, $parameters);
  1052. }
  1053. /**
  1054. * Set the bundle that the validator is running for.
  1055. *
  1056. * The bundle determines which bundle the language lines will be loaded from.
  1057. *
  1058. * @param string $bundle
  1059. * @return Validator
  1060. */
  1061. public function bundle($bundle)
  1062. {
  1063. $this->bundle = $bundle;
  1064. return $this;
  1065. }
  1066. /**
  1067. * Set the language that should be used when retrieving error messages.
  1068. *
  1069. * @param string $language
  1070. * @return Validator
  1071. */
  1072. public function speaks($language)
  1073. {
  1074. $this->language = $language;
  1075. return $this;
  1076. }
  1077. /**
  1078. * Set the database connection that should be used by the validator.
  1079. *
  1080. * @param Database\Connection $connection
  1081. * @return Validator
  1082. */
  1083. public function connection(Database\Connection $connection)
  1084. {
  1085. $this->db = $connection;
  1086. return $this;
  1087. }
  1088. /**
  1089. * Get the database connection for the Validator.
  1090. *
  1091. * @return Database\Connection
  1092. */
  1093. protected function db()
  1094. {
  1095. if ( ! is_null($this->db)) return $this->db;
  1096. return $this->db = Database::connection();
  1097. }
  1098. /**
  1099. * Dynamically handle calls to custom registered validators.
  1100. */
  1101. public function __call($method, $parameters)
  1102. {
  1103. // First we will slice the "validate_" prefix off of the validator since
  1104. // custom validators aren't registered with such a prefix, then we can
  1105. // just call the method with the given parameters.
  1106. if (isset(static::$validators[$method = substr($method, 9)]))
  1107. {
  1108. return call_user_func_array(static::$validators[$method], $parameters);
  1109. }
  1110. throw new \Exception("Method [$method] does not exist.");
  1111. }
  1112. }