validator.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  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 array $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 = $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';
  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 $value['tmp_name'] == '')
  223. {
  224. return false;
  225. }
  226. return true;
  227. }
  228. /**
  229. * Validate that an attribute has a matching confirmation attribute.
  230. *
  231. * @param string $attribute
  232. * @param mixed $value
  233. * @return bool
  234. */
  235. protected function validate_confirmed($attribute, $value)
  236. {
  237. return $this->validate_same($attribute, $value, array($attribute.'_confirmation'));
  238. }
  239. /**
  240. * Validate that an attribute was "accepted".
  241. *
  242. * This validation rule implies the attribute is "required".
  243. *
  244. * @param string $attribute
  245. * @param mixed $value
  246. * @return bool
  247. */
  248. protected function validate_accepted($attribute, $value)
  249. {
  250. return $this->validate_required($attribute, $value) and ($value == 'yes' or $value == '1');
  251. }
  252. /**
  253. * Validate that an attribute is the same as another attribute.
  254. *
  255. * @param string $attribute
  256. * @param mixed $value
  257. * @param array $parameters
  258. * @return bool
  259. */
  260. protected function validate_same($attribute, $value, $parameters)
  261. {
  262. $other = $parameters[0];
  263. return isset($this->attributes[$other]) and $value == $this->attributes[$other];
  264. }
  265. /**
  266. * Validate that an attribute is different from another attribute.
  267. *
  268. * @param string $attribute
  269. * @param mixed $value
  270. * @param array $parameters
  271. * @return bool
  272. */
  273. protected function validate_different($attribute, $value, $parameters)
  274. {
  275. $other = $parameters[0];
  276. return isset($this->attributes[$other]) and $value != $this->attributes[$other];
  277. }
  278. /**
  279. * Validate that an attribute is numeric.
  280. *
  281. * @param string $attribute
  282. * @param mixed $value
  283. * @return bool
  284. */
  285. protected function validate_numeric($attribute, $value)
  286. {
  287. return is_numeric($value);
  288. }
  289. /**
  290. * Validate that an attribute is an integer.
  291. *
  292. * @param string $attribute
  293. * @param mixed $value
  294. * @return bool
  295. */
  296. protected function validate_integer($attribute, $value)
  297. {
  298. return filter_var($value, FILTER_VALIDATE_INT) !== false;
  299. }
  300. /**
  301. * Validate the size of an attribute.
  302. *
  303. * @param string $attribute
  304. * @param mixed $value
  305. * @param array $parameters
  306. * @return bool
  307. */
  308. protected function validate_size($attribute, $value, $parameters)
  309. {
  310. return $this->size($attribute, $value) == $parameters[0];
  311. }
  312. /**
  313. * Validate the size of an attribute is between a set of values.
  314. *
  315. * @param string $attribute
  316. * @param mixed $value
  317. * @param array $parameters
  318. * @return bool
  319. */
  320. protected function validate_between($attribute, $value, $parameters)
  321. {
  322. $size = $this->size($attribute, $value);
  323. return $size >= $parameters[0] and $size <= $parameters[1];
  324. }
  325. /**
  326. * Validate the size of an attribute is greater than a minimum value.
  327. *
  328. * @param string $attribute
  329. * @param mixed $value
  330. * @param array $parameters
  331. * @return bool
  332. */
  333. protected function validate_min($attribute, $value, $parameters)
  334. {
  335. return $this->size($attribute, $value) >= $parameters[0];
  336. }
  337. /**
  338. * Validate the size of an attribute is less than a maximum value.
  339. *
  340. * @param string $attribute
  341. * @param mixed $value
  342. * @param array $parameters
  343. * @return bool
  344. */
  345. protected function validate_max($attribute, $value, $parameters)
  346. {
  347. return $this->size($attribute, $value) <= $parameters[0];
  348. }
  349. /**
  350. * Get the size of an attribute.
  351. *
  352. * @param string $attribute
  353. * @param mixed $value
  354. * @return mixed
  355. */
  356. protected function size($attribute, $value)
  357. {
  358. // This method will determine if the attribute is a number, string, or file and
  359. // return the proper size accordingly. If it is a number, then number itself is
  360. // the size; if it is a file, the size is kilobytes in the size; if it is a
  361. // string, the length is the size.
  362. if (is_numeric($value) and $this->has_rule($attribute, $this->numeric_rules))
  363. {
  364. return $this->attributes[$attribute];
  365. }
  366. elseif (array_key_exists($attribute, Input::file()))
  367. {
  368. return $value['size'] / 1024;
  369. }
  370. else
  371. {
  372. return Str::length(trim($value));
  373. }
  374. }
  375. /**
  376. * Validate an attribute is contained within a list of values.
  377. *
  378. * @param string $attribute
  379. * @param mixed $value
  380. * @param array $parameters
  381. * @return bool
  382. */
  383. protected function validate_in($attribute, $value, $parameters)
  384. {
  385. return in_array($value, $parameters);
  386. }
  387. /**
  388. * Validate an attribute is not contained within a list of values.
  389. *
  390. * @param string $attribute
  391. * @param mixed $value
  392. * @param array $parameters
  393. * @return bool
  394. */
  395. protected function validate_not_in($attribute, $value, $parameters)
  396. {
  397. return ! in_array($value, $parameters);
  398. }
  399. /**
  400. * Validate the uniqueness of an attribute value on a given database table.
  401. *
  402. * If a database column is not specified, the attribute will be used.
  403. *
  404. * @param string $attribute
  405. * @param mixed $value
  406. * @param array $parameters
  407. * @return bool
  408. */
  409. protected function validate_unique($attribute, $value, $parameters)
  410. {
  411. // We allow the table column to be specified just in case the column does
  412. // not have the same name as the attribute. It must be within the second
  413. // parameter position, right after the database table name.
  414. if (isset($parameters[1]))
  415. {
  416. $attribute = $parameters[1];
  417. }
  418. $query = $this->db()->table($parameters[0])->where($attribute, '=', $value);
  419. // We also allow an ID to be specified that will not be included in the
  420. // uniqueness check. This makes updating columns easier since it is
  421. // fine for the given ID to exist in the table.
  422. if (isset($parameters[2]))
  423. {
  424. $id = (isset($parameters[3])) ? $parameters[3] : 'id';
  425. $query->where($id, '<>', $parameters[2]);
  426. }
  427. return $query->count() == 0;
  428. }
  429. /**
  430. * Validate the existence of an attribute value in a database table.
  431. *
  432. * @param string $attribute
  433. * @param mixed $value
  434. * @param array $parameters
  435. * @return bool
  436. */
  437. protected function validate_exists($attribute, $value, $parameters)
  438. {
  439. if (isset($parameters[1])) $attribute = $parameters[1];
  440. // Grab the number of elements we are looking for. If the given value is
  441. // in array, we'll count all of the values in the array, otherwise we
  442. // can just make sure the count is greater or equal to one.
  443. $count = (is_array($value)) ? count($value) : 1;
  444. $query = $this->db()->table($parameters[0]);
  445. // If the given value is an array, we will check for the existence of
  446. // all the values in the database, otherwise we'll check for the
  447. // presence of the single given value in the database.
  448. if (is_array($value))
  449. {
  450. $query = $query->where_in($attribute, $value);
  451. }
  452. else
  453. {
  454. $query = $query->where($attribute, '=', $value);
  455. }
  456. return $query->count() >= $count;
  457. }
  458. /**
  459. * Validate that an attribute is a valid IP.
  460. *
  461. * @param string $attribute
  462. * @param mixed $value
  463. * @return bool
  464. */
  465. protected function validate_ip($attribute, $value)
  466. {
  467. return filter_var($value, FILTER_VALIDATE_IP) !== false;
  468. }
  469. /**
  470. * Validate that an attribute is a valid e-mail address.
  471. *
  472. * @param string $attribute
  473. * @param mixed $value
  474. * @return bool
  475. */
  476. protected function validate_email($attribute, $value)
  477. {
  478. return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
  479. }
  480. /**
  481. * Validate that an attribute is a valid URL.
  482. *
  483. * @param string $attribute
  484. * @param mixed $value
  485. * @return bool
  486. */
  487. protected function validate_url($attribute, $value)
  488. {
  489. return filter_var($value, FILTER_VALIDATE_URL) !== false;
  490. }
  491. /**
  492. * Validate that an attribute is an active URL.
  493. *
  494. * @param string $attribute
  495. * @param mixed $value
  496. * @return bool
  497. */
  498. protected function validate_active_url($attribute, $value)
  499. {
  500. $url = str_replace(array('http://', 'https://', 'ftp://'), '', Str::lower($value));
  501. return checkdnsrr($url);
  502. }
  503. /**
  504. * Validate the MIME type of a file is an image MIME type.
  505. *
  506. * @param string $attribute
  507. * @param mixed $value
  508. * @return bool
  509. */
  510. protected function validate_image($attribute, $value)
  511. {
  512. return $this->validate_mimes($attribute, $value, array('jpg', 'png', 'gif', 'bmp'));
  513. }
  514. /**
  515. * Validate that an attribute contains only alphabetic characters.
  516. *
  517. * @param string $attribute
  518. * @param mixed $value
  519. * @return bool
  520. */
  521. protected function validate_alpha($attribute, $value)
  522. {
  523. return preg_match('/^([a-z])+$/i', $value);
  524. }
  525. /**
  526. * Validate that an attribute contains only alpha-numeric characters.
  527. *
  528. * @param string $attribute
  529. * @param mixed $value
  530. * @return bool
  531. */
  532. protected function validate_alpha_num($attribute, $value)
  533. {
  534. return preg_match('/^([a-z0-9])+$/i', $value);
  535. }
  536. /**
  537. * Validate that an attribute contains only alpha-numeric characters, dashes, and underscores.
  538. *
  539. * @param string $attribute
  540. * @param mixed $value
  541. * @return bool
  542. */
  543. protected function validate_alpha_dash($attribute, $value)
  544. {
  545. return preg_match('/^([-a-z0-9_-])+$/i', $value);
  546. }
  547. /**
  548. * Validate the MIME type of a file upload attribute is in a set of MIME types.
  549. *
  550. * @param string $attribute
  551. * @param array $value
  552. * @param array $parameters
  553. * @return bool
  554. */
  555. protected function validate_mimes($attribute, $value, $parameters)
  556. {
  557. if ( ! is_array($value) or array_get($value, 'tmp_name', '') == '') return true;
  558. foreach ($parameters as $extension)
  559. {
  560. if (File::is($extension, $value['tmp_name']))
  561. {
  562. return true;
  563. }
  564. }
  565. return false;
  566. }
  567. /**
  568. * Get the proper error message for an attribute and rule.
  569. *
  570. * @param string $attribute
  571. * @param string $rule
  572. * @return string
  573. */
  574. protected function message($attribute, $rule)
  575. {
  576. $bundle = Bundle::prefix($this->bundle);
  577. // First we'll check for developer specified, attribute specific messages.
  578. // These messages take first priority. They allow the fine-grained tuning
  579. // of error messages for each rule.
  580. $custom = $attribute.'_'.$rule;
  581. if (array_key_exists($custom, $this->messages))
  582. {
  583. return $this->messages[$custom];
  584. }
  585. elseif (Lang::has($custom = "validation.custom.{$custom}", $this->language))
  586. {
  587. return Lang::line($custom)->get($this->language);
  588. }
  589. // Next we'll check for developer specified, rule specific error messages.
  590. // These allow the developer to override the error message for an entire
  591. // rule, regardless of the attribute being validated by that rule.
  592. elseif (array_key_exists($rule, $this->messages))
  593. {
  594. return $this->messages[$rule];
  595. }
  596. // If the rule being validated is a "size" rule, we will need to gather
  597. // the specific size message for the type of attribute being validated,
  598. // either a number, file, or string.
  599. elseif (in_array($rule, $this->size_rules))
  600. {
  601. return $this->size_message($bundle, $attribute, $rule);
  602. }
  603. // If no developer specified messages have been set, and no other special
  604. // messages apply to the rule, we will just pull the default validation
  605. // message from the validation language file.
  606. else
  607. {
  608. $line = "{$bundle}validation.{$rule}";
  609. return Lang::line($line)->get($this->language);
  610. }
  611. }
  612. /**
  613. * Get the proper error message for an attribute and size rule.
  614. *
  615. * @param string $bundle
  616. * @param string $attribute
  617. * @param string $rule
  618. * @return string
  619. */
  620. protected function size_message($bundle, $attribute, $rule)
  621. {
  622. // There are three different types of size validations. The attribute
  623. // may be either a number, file, or a string, so we'll check a few
  624. // things to figure out which one it is.
  625. if ($this->has_rule($attribute, $this->numeric_rules))
  626. {
  627. $line = 'numeric';
  628. }
  629. // We assume that attributes present in the $_FILES array are files,
  630. // which makes sense. If the attribute doesn't have numeric rules
  631. // and isn't as file, it's a string.
  632. elseif (array_key_exists($attribute, Input::file()))
  633. {
  634. $line = 'file';
  635. }
  636. else
  637. {
  638. $line = 'string';
  639. }
  640. return Lang::line("{$bundle}validation.{$rule}.{$line}")->get($this->language);
  641. }
  642. /**
  643. * Replace all error message place-holders with actual values.
  644. *
  645. * @param string $message
  646. * @param string $attribute
  647. * @param string $rule
  648. * @param array $parameters
  649. * @return string
  650. */
  651. protected function replace($message, $attribute, $rule, $parameters)
  652. {
  653. $message = str_replace(':attribute', $this->attribute($attribute), $message);
  654. if (method_exists($this, $replacer = 'replace_'.$rule))
  655. {
  656. $message = $this->$replacer($message, $attribute, $rule, $parameters);
  657. }
  658. return $message;
  659. }
  660. /**
  661. * Replace all place-holders for the between rule.
  662. *
  663. * @param string $message
  664. * @param string $attribute
  665. * @param string $rule
  666. * @param array $parameters
  667. * @return string
  668. */
  669. protected function replace_between($message, $attribute, $rule, $parameters)
  670. {
  671. return str_replace(array(':min', ':max'), $parameters, $message);
  672. }
  673. /**
  674. * Replace all place-holders for the size rule.
  675. *
  676. * @param string $message
  677. * @param string $attribute
  678. * @param string $rule
  679. * @param array $parameters
  680. * @return string
  681. */
  682. protected function replace_size($message, $attribute, $rule, $parameters)
  683. {
  684. return str_replace(':size', $parameters[0], $message);
  685. }
  686. /**
  687. * Replace all place-holders for the min rule.
  688. *
  689. * @param string $message
  690. * @param string $attribute
  691. * @param string $rule
  692. * @param array $parameters
  693. * @return string
  694. */
  695. protected function replace_min($message, $attribute, $rule, $parameters)
  696. {
  697. return str_replace(':min', $parameters[0], $message);
  698. }
  699. /**
  700. * Replace all place-holders for the max rule.
  701. *
  702. * @param string $message
  703. * @param string $attribute
  704. * @param string $rule
  705. * @param array $parameters
  706. * @return string
  707. */
  708. protected function replace_max($message, $attribute, $rule, $parameters)
  709. {
  710. return str_replace(':max', $parameters[0], $message);
  711. }
  712. /**
  713. * Replace all place-holders for the in rule.
  714. *
  715. * @param string $message
  716. * @param string $attribute
  717. * @param string $rule
  718. * @param array $parameters
  719. * @return string
  720. */
  721. protected function replace_in($message, $attribute, $rule, $parameters)
  722. {
  723. return str_replace(':values', implode(', ', $parameters), $message);
  724. }
  725. /**
  726. * Replace all place-holders for the not_in rule.
  727. *
  728. * @param string $message
  729. * @param string $attribute
  730. * @param string $rule
  731. * @param array $parameters
  732. * @return string
  733. */
  734. protected function replace_not_in($message, $attribute, $rule, $parameters)
  735. {
  736. return str_replace(':values', implode(', ', $parameters), $message);
  737. }
  738. /**
  739. * Replace all place-holders for the not_in rule.
  740. *
  741. * @param string $message
  742. * @param string $attribute
  743. * @param string $rule
  744. * @param array $parameters
  745. * @return string
  746. */
  747. protected function replace_mimes($message, $attribute, $rule, $parameters)
  748. {
  749. return str_replace(':values', implode(', ', $parameters), $message);
  750. }
  751. /**
  752. * Replace all place-holders for the same rule.
  753. *
  754. * @param string $message
  755. * @param string $attribute
  756. * @param string $rule
  757. * @param array $parameters
  758. * @return string
  759. */
  760. protected function replace_same($message, $attribute, $rule, $parameters)
  761. {
  762. return str_replace(':other', $parameters[0], $message);
  763. }
  764. /**
  765. * Replace all place-holders for the different rule.
  766. *
  767. * @param string $message
  768. * @param string $attribute
  769. * @param string $rule
  770. * @param array $parameters
  771. * @return string
  772. */
  773. protected function replace_different($message, $attribute, $rule, $parameters)
  774. {
  775. return str_replace(':other', $parameters[0], $message);
  776. }
  777. /**
  778. * Get the displayable name for a given attribute.
  779. *
  780. * @param string $attribute
  781. * @return string
  782. */
  783. protected function attribute($attribute)
  784. {
  785. $bundle = Bundle::prefix($this->bundle);
  786. // More reader friendly versions of the attribute names may be stored
  787. // in the validation language file, allowing a more readable version
  788. // of the attribute name in the message.
  789. $line = "{$bundle}validation.attributes.{$attribute}";
  790. $display = Lang::line($line)->get($this->language);
  791. // If no language line has been specified for the attribute, all of
  792. // the underscores are removed from the attribute name and that
  793. // will be used as the attribtue name.
  794. if (is_null($display))
  795. {
  796. return str_replace('_', ' ', $attribute);
  797. }
  798. return $display;
  799. }
  800. /**
  801. * Determine if an attribute has a rule assigned to it.
  802. *
  803. * @param string $attribute
  804. * @param array $rules
  805. * @return bool
  806. */
  807. protected function has_rule($attribute, $rules)
  808. {
  809. foreach ($this->rules[$attribute] as $rule)
  810. {
  811. list($rule, $parameters) = $this->parse($rule);
  812. if (in_array($rule, $rules)) return true;
  813. }
  814. return false;
  815. }
  816. /**
  817. * Extract the rule name and parameters from a rule.
  818. *
  819. * @param string $rule
  820. * @return array
  821. */
  822. protected function parse($rule)
  823. {
  824. $parameters = array();
  825. // The format for specifying validation rules and parameters follows a
  826. // {rule}:{parameters} formatting convention. For instance, the rule
  827. // "max:3" specifies that the value may only be 3 characters long.
  828. if (($colon = strpos($rule, ':')) !== false)
  829. {
  830. $parameters = explode(',', substr($rule, $colon + 1));
  831. }
  832. return array(is_numeric($colon) ? substr($rule, 0, $colon) : $rule, $parameters);
  833. }
  834. /**
  835. * Set the bundle that the validator is running for.
  836. *
  837. * The bundle determines which bundle the language lines will be loaded from.
  838. *
  839. * @param string $bundle
  840. * @return Validator
  841. */
  842. public function bundle($bundle)
  843. {
  844. $this->bundle = $bundle;
  845. return $this;
  846. }
  847. /**
  848. * Set the language that should be used when retrieving error messages.
  849. *
  850. * @param string $language
  851. * @return Validator
  852. */
  853. public function speaks($language)
  854. {
  855. $this->language = $language;
  856. return $this;
  857. }
  858. /**
  859. * Set the database connection that should be used by the validator.
  860. *
  861. * @param Database\Connection $connection
  862. * @return Validator
  863. */
  864. public function connection(Database\Connection $connection)
  865. {
  866. $this->db = $connection;
  867. return $this;
  868. }
  869. /**
  870. * Get the database connection for the Validator.
  871. *
  872. * @return Database\Connection
  873. */
  874. protected function db()
  875. {
  876. if ( ! is_null($this->db)) return $this->db;
  877. return $this->db = Database::connection();
  878. }
  879. /**
  880. * Dynamically handle calls to custom registered validators.
  881. */
  882. public function __call($method, $parameters)
  883. {
  884. // First we will slice the "validate_" prefix off of the validator since
  885. // custom validators aren't registered with such a prefix, then we can
  886. // just call the method with the given parameters.
  887. if (isset(static::$validators[$method = substr($method, 9)]))
  888. {
  889. return call_user_func_array(static::$validators[$method], $parameters);
  890. }
  891. throw new \Exception("Method [$method] does not exist.");
  892. }
  893. }