├── README.md
├── README.txt
├── Validator.php
├── Validator
└── Exception.php
└── tests
├── ValidatorTest.php
└── phpunit.xml
/README.md:
--------------------------------------------------------------------------------
1 | # A PHP 5.3 Class for Easy Form Validation
2 |
3 | This class follows Zend Framework naming conventions for easy drop-in as a substitute to Zend_Validation.
4 | If you opt out of using the bulky Zend_Form on your projects, you might choose to use this for quick and painless
5 | form validation.
6 |
7 | ## A Quick Example
8 |
9 | The example below shows how to throw validation exceptions with the custom
10 | exception. You can then retrieve the error messages from the calling method.
11 | It is not good practice to validate your data in your controller, this should
12 | be handled in your Model. This is just a quick example.
13 |
14 | ```php
15 | _validate($_POST);
31 |
32 | // validation passed because no exception was thrown
33 | // ... to something with the $validData ...
34 |
35 | } catch (Validator_Exception $e) {
36 | // retrieve the overall error message to display
37 | $message = $e->getMessage();
38 |
39 | // retrieve all of the errors
40 | $errors = $e->getErrors();
41 |
42 | // the below code is specific to ZF
43 | $this->_helper->FlashMessenger(array('error' => $message));
44 | $this->_helper->layout->getView()->errors = $errors;
45 | }
46 | }
47 |
48 | /**
49 | * Your user-defined validation handling. The exception section is
50 | * very important and should always be used.
51 | *
52 | * @access private
53 | * @param array $post
54 | * @return mixed
55 | */
56 | private function _validate(array $post = array())
57 | {
58 | $validator = new Validator($post);
59 | $validator
60 | ->required('You must supply a name.')
61 | ->validate('name', 'Name');
62 | $validator
63 | ->required('You must supply an email address.')
64 | ->email('You must supply a valid email address')
65 | ->validate('email', 'Email');
66 |
67 | // check for errors
68 | if ($validator->hasErrors()) {
69 | throw new Validator_Exception(
70 | 'There were errors in your form.',
71 | $validator->getAllErrors()
72 | );
73 | }
74 |
75 | return $validator->getValidData();
76 | }
77 |
78 | }
79 | ```
80 |
81 | ## Available Validation Methods
82 |
83 | * required($message = null) - The field value is required.
84 | * email($message = null) - The field value must be a valid email address string.
85 | * float($message = null) - The field value must be a float.
86 | * integer($message = null) - The field value must be an integer.
87 | * digits($message = null) - The field value must be a digit (integer with no upper bounds).
88 | * min($limit, $include = TRUE, $message = null) - The field value must be greater than $limit (numeric). $include defines if the value can be equal to the limit.
89 | * max($limit, $include = TRUE, $message = null) - The field value must be less than $limit (numeric). $include defines if the value can be equal to the limit.
90 | * between($min, $max, $include = TRUE, $message = null) - The field value must be between $min and $max (numeric). $include defines if the value can be equal to $min and $max.
91 | * minLength($length, $message = null) - The field value must be greater than or equal to $length characters.
92 | * maxLength($length, $message = null) - The field value must be less than or equal to $length characters.
93 | * length($length, $message = null) - The field must be $length characters long.
94 | * matches($field, $label, $message = null) - One field matches another one (i.e. password matching)
95 | * notMatches($field, $label, $message = null) - The field value must not match the value of $field.
96 | * startsWith($sub, $message = null) - The field must start with $sub as a string.
97 | * notStartsWith($sub, $message = null) - The field must not start with $sub as a string.
98 | * endsWith($sub, $message = null) - THe field must end with $sub as a string.
99 | * notEndsWith($sub, $message = null) - The field must not end with $sub as a string.
100 | * ip($message = null) - The field value is a valid IP, determined using filter_var.
101 | * url($message = null) - The field value is a valid URL, determined using filter_var.
102 | * date($message = null) - The field value is a valid date, can be of any format accepted by DateTime()
103 | * minDate($date, $format, $message = null) - The date must be greater than $date. $format must be of a format on the page http://php.net/manual/en/datetime.createfromformat.php
104 | * maxDate($date, $format, $message = null) - The date must be less than $date. $format must be of a format on the page http://php.net/manual/en/datetime.createfromformat.php
105 | * ccnum($message = null) - The field value must be a valid credit card number.
106 | * oneOf($allowed, $message = null) - The field value must be one of the $allowed values. $allowed can be either an array or a comma-separated list of values. If comma separated, do not include spaces unless intended for matching.
107 | * callback($callback, $message = '', $params = array()) - Define your own custom callback validation function. $callback must pass an is_callable() check. $params can be any value, or an array if multiple parameters must be passed.
108 |
109 | ### Callback Examples
110 |
111 | Callback functions can be passed as strings or closures.
112 |
113 | // numeric example
114 | $validadator
115 | ->callback('is_numeric', 'Field is not numeric.')
116 | ->validate('number_field');
117 |
118 | // closure example
119 | $validator
120 | ->callback(function($val) {
121 | return $val < -1 || $val > 1;
122 | }, 'Number must be less than -1 or greater than 1.')
123 | ->validate('number_field_2');
124 |
125 | ## Validating Arrays and Array Indices
126 |
127 | This validation class has been extended to allow for validation of arrays as well as nested indices of a multi-dimensional array.
128 |
129 | ### Validating Specific Indices
130 |
131 | To validate specific indices of an array, use dot notation, i.e.
132 |
133 | ```php
134 | required('The nested field is required.')
141 | ->validate('field.nested');
142 |
143 | // ensure we have the first two numeric indices of $_POST['links'][]
144 | $validator
145 | ->required('This field is required')
146 | ->validate('links.0');
147 | $validator
148 | ->required('This field is required')
149 | ->validate('links.1');
150 | ```
151 |
152 | # Available Pre-Validation Filtering
153 |
154 | You can apply pre-validation filters to your data (i.e. trim, strip_tags, htmlentities). These filters can also
155 | be custom defined so long as they pass an is_callable()
check.
156 |
157 | * filter($callback)
158 |
159 | ### Filter Examples
160 |
161 | ```php
162 | // standard php filter for valid user ids.
163 | $validator
164 | ->filter('intval')
165 | ->min(1)
166 | ->validate('user_id');
167 |
168 | // custom filter
169 | $validator
170 | ->filter(function($val) {
171 | // bogus formatting of the field
172 | $val = rtrim($val, '/');
173 | $val .= '_custom_formatted';
174 | return $val;
175 | })
176 | ->validate('field_to_be_formatted');
177 | ```
178 |
179 | # Credits
180 |
181 | * Modifications by Corey Ballou, Chris Gutierrez, and Robert Fruchtman.
182 | * Forked from Tasos Bekos which was based on the initial work of "Bretticus".
183 | * See http://brettic.us/2010/06/18/form-validation-class-using-php-5-3/ for the original.
184 |
185 | # License
186 |
187 | Copyright (c) 2012 http://github.com/bekos, http://github.com/blackbe.lt
188 |
189 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
190 |
191 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
192 |
193 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
194 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | # A PHP 5.3 Class for Easy Form Validation
2 |
3 | ## Available Pre-Validation Filtering
4 |
5 | You can apply pre-validation filters to your data (i.e. trim, strip_tags, htmlentities). These filters can also
6 | be custom defined so long as they pass an is_callable()
check.
7 |
8 | * filter($callback)
9 |
10 | ## Filter Examples
11 |
12 |
13 | // standard php filter for valid user ids.
14 | $validator
15 | ->filter('intval')
16 | ->min(1)
17 | ->validate('user_id');
18 |
19 | // custom filter
20 | $validator
21 | ->filter(function($val) {
22 | // bogus formatting of the field
23 | $val = rtrim($val, '/');
24 | $val .= '_custom_formatted';
25 | return $val;
26 | })
27 | ->validate('field_to_be_formatted');
28 |
29 |
30 | ## Available Validation Methods
31 |
32 | * required($message = null) - The field value is required.
33 | * email($message = null) - The field value must be a valid email address string.
34 | * float($message = null) - The field value must be a float.
35 | * integer($message = null) - The field value must be an integer.
36 | * digits($message = null) - The field value must be a digit (integer with no upper bounds).
37 | * min($limit, $include = TRUE, $message = null) - The field value must be greater than $limit (numeric). $include defines if the value can be equal to the limit.
38 | * max($limit, $include = TRUE, $message = null) - The field value must be less than $limit (numeric). $include defines if the value can be equal to the limit.
39 | * between($min, $max, $include = TRUE, $message = null) - The field value must be between $min and $max (numeric). $include defines if the value can be equal to $min and $max.
40 | * minLength($length, $message = null) - The field value must be greater than or equal to $length characters.
41 | * maxLength($length, $message = null) - The field value must be less than or equal to $length characters.
42 | * length($length, $message = null) - The field must be $length characters long.
43 | * matches($field, $label, $message = null) - One field matches another one (i.e. password matching)
44 | * notMatches($field, $label, $message = null) - The field value must not match the value of $field.
45 | * startsWith($sub, $message = null) - The field must start with $sub as a string.
46 | * notStartsWith($sub, $message = null) - The field must not start with $sub as a string.
47 | * endsWith($sub, $message = null) - THe field must end with $sub as a string.
48 | * notEndsWith($sub, $message = null) - The field must not end with $sub as a string.
49 | * ip($message = null) - The field value is a valid IP, determined using filter_var.
50 | * url($message = null) - The field value is a valid URL, determined using filter_var.
51 | * date($message = null) - The field value is a valid date, can be of any format accepted by DateTime()
52 | * minDate($date, $format, $message = null) - The date must be greater than $date. $format must be of a format on the page http://php.net/manual/en/datetime.createfromformat.php
53 | * maxDate($date, $format, $message = null) - The date must be less than $date. $format must be of a format on the page http://php.net/manual/en/datetime.createfromformat.php
54 | * ccnum($message = null) - The field value must be a valid credit card number.
55 | * oneOf($allowed, $message = null) - The field value must be one of the $allowed values. $allowed can be either an array or a comma-separated list of values. If comma separated, do not include spaces unless intended for matching.
56 | * callback($callback, $message = '', $params = null) - Define your own custom callback validation function. $callback must pass an is_callable() check. $params can be any value, or an array if multiple parameters must be passed.
57 |
58 | ### Callback Examples
59 |
60 | Callback functions can be passed as strings or closures.
61 |
62 |
63 | // numeric example
64 | $validadator
65 | ->callback('is_numeric', 'Field is not numeric.')
66 | ->validate('number_field');
67 |
68 | // closure example
69 | $validator
70 | ->callback(function($val) {
71 | return $val < -1 || $val > 1;
72 | }, 'Number must be less than -1 or greater than 1.')
73 | ->validate('number_field_2');
74 |
75 |
76 | ## Validating Arrays and Array Indices
77 |
78 | This validation class has been extended to allow for validation of arrays as well as nested indices of a multi-dimensional array.
79 |
80 | ### Validating Specific Indices
81 |
82 | To validate specific indices of an array, use dot notation, i.e.
83 |
84 |
85 | // load the validator
86 | $validator = new Blackbelt_Validator($_POST);
87 |
88 | // ensure $_POST['field']['nested'] exists
89 | $validator
90 | ->required('The nested field is required.')
91 | ->validate('field.nested');
92 |
93 | // ensure we have the first two numeric indices of $_POST['links'][]
94 | $validator
95 | ->required('This field is required')
96 | ->validate('links.0');
97 | $validator
98 | ->required('This field is required')
99 | ->validate('links.1');
100 |
101 |
102 | ## Credits
103 |
104 | * Modifications by Corey Ballou, Chris Gutierrez, and Robert Fruchtman.
105 | * Forked from Tasos Bekos which was based on the initial work of "Bretticus".
106 | * See http://brettic.us/2010/06/18/form-validation-class-using-php-5-3/ for the original.
107 |
--------------------------------------------------------------------------------
/Validator.php:
--------------------------------------------------------------------------------
1 |
7 | * @author Chris Gutierrez
8 | * @author Corey Ballou
9 | * @see https://github.com/blackbelt/php-validation
10 | * @see Based on idea: http://brettic.us/2010/06/18/form-validation-class-using-php-5-3/
11 | */
12 | class Validator {
13 |
14 | protected $messages = array();
15 | protected $errors = array();
16 | protected $rules = array();
17 | protected $fields = array();
18 | protected $functions = array();
19 | protected $arguments = array();
20 | protected $filters = array();
21 | protected $data = null;
22 | protected $validData = array();
23 |
24 | /**
25 | * Constructor.
26 | * Define values to validate.
27 | *
28 | * @param array $data
29 | */
30 | function __construct(array $data = null) {
31 | if (!empty($data)) $this->setData($data);
32 | }
33 |
34 | /**
35 | * set the data to be validated
36 | *
37 | * @access public
38 | * @param mixed $data
39 | * @return FormValidator
40 | */
41 | public function setData(array $data) {
42 | $this->data = $data;
43 | return $this;
44 | }
45 |
46 | // ----------------- ADD NEW RULE FUNCTIONS BELOW THIS LINE ----------------
47 |
48 | /**
49 | * Field, if completed, has to be a valid email address.
50 | *
51 | * @param string $message
52 | * @return FormValidator
53 | */
54 | public function email($message = null) {
55 | $this->setRule(__FUNCTION__, function($email) {
56 | if (strlen($email) == 0) return true;
57 | $isValid = true;
58 | $atIndex = strrpos($email, '@');
59 | if (is_bool($atIndex) && !$atIndex) {
60 | $isValid = false;
61 | } else {
62 | $domain = substr($email, $atIndex+1);
63 | $local = substr($email, 0, $atIndex);
64 | $localLen = strlen($local);
65 | $domainLen = strlen($domain);
66 | if ($localLen < 1 || $localLen > 64) {
67 | $isValid = false;
68 | } else if ($domainLen < 1 || $domainLen > 255) {
69 | // domain part length exceeded
70 | $isValid = false;
71 | } else if ($local[0] == '.' || $local[$localLen-1] == '.') {
72 | // local part starts or ends with '.'
73 | $isValid = false;
74 | } else if (preg_match('/\\.\\./', $local)) {
75 | // local part has two consecutive dots
76 | $isValid = false;
77 | } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
78 | // character not valid in domain part
79 | $isValid = false;
80 | } else if (preg_match('/\\.\\./', $domain)) {
81 | // domain part has two consecutive dots
82 | $isValid = false;
83 | } else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) {
84 | // character not valid in local part unless
85 | // local part is quoted
86 | if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) {
87 | $isValid = false;
88 | }
89 | }
90 | // check DNS
91 | if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
92 | $isValid = false;
93 | }
94 | }
95 | return $isValid;
96 | }, $message);
97 | return $this;
98 | }
99 |
100 | /**
101 | * Field must be filled in.
102 | *
103 | * @param string $message
104 | * @return FormValidator
105 | */
106 | public function required($message = null) {
107 | $this->setRule(__FUNCTION__, function($val) {
108 | if (is_scalar($val)) {
109 | $val = trim($val);
110 | }
111 | return !empty($val);
112 | }, $message);
113 | return $this;
114 | }
115 |
116 | /**
117 | * Field must contain a valid float value.
118 | *
119 | * @param string $message
120 | * @return FormValidator
121 | */
122 | public function float($message = null) {
123 | $this->setRule(__FUNCTION__, function($val) {
124 | return !(filter_var($val, FILTER_VALIDATE_FLOAT) === FALSE);
125 | }, $message);
126 | return $this;
127 | }
128 |
129 | /**
130 | * Field must contain a valid integer value.
131 | *
132 | * @param string $message
133 | * @return FormValidator
134 | */
135 | public function integer($message = null) {
136 | $this->setRule(__FUNCTION__, function($val) {
137 | return !(filter_var($val, FILTER_VALIDATE_INT) === FALSE);
138 | }, $message);
139 | return $this;
140 | }
141 |
142 | /**
143 | * Every character in field, if completed, must be a digit.
144 | * This is just like integer(), except there is no upper limit.
145 | *
146 | * @param string $message
147 | * @return FormValidator
148 | */
149 | public function digits($message = null) {
150 | $this->setRule(__FUNCTION__, function($val) {
151 | return (strlen($val) === 0 || ctype_digit((string) $val));
152 | }, $message);
153 | return $this;
154 | }
155 |
156 | /**
157 | * Field must be a number greater than [or equal to] X.
158 | *
159 | * @param numeric $limit
160 | * @param bool $include Whether to include limit value.
161 | * @param string $message
162 | * @return FormValidator
163 | */
164 | public function min($limit, $include = TRUE, $message = null) {
165 | $this->setRule(__FUNCTION__, function($val, $args) {
166 | if (strlen($val) === 0) {
167 | return TRUE;
168 | }
169 |
170 | $val = (float) $val;
171 | $limit = (float) $args[0];
172 | $inc = (bool) $args[1];
173 |
174 | return ($val > $limit || ($inc === TRUE && $val === $limit));
175 | }, $message, array($limit, $include));
176 | return $this;
177 | }
178 |
179 | /**
180 | * Field must be a number greater than [or equal to] X.
181 | *
182 | * @param numeric $limit
183 | * @param bool $include Whether to include limit value.
184 | * @param string $message
185 | * @return FormValidator
186 | */
187 | public function max($limit, $include = TRUE, $message = null) {
188 | $this->setRule(__FUNCTION__, function($val, $args) {
189 | if (strlen($val) === 0) {
190 | return TRUE;
191 | }
192 |
193 | $val = (float) $val;
194 | $limit = (float) $args[0];
195 | $inc = (bool) $args[1];
196 |
197 | return ($val < $limit || ($inc === TRUE && $val === $limit));
198 | }, $message, array($limit, $include));
199 | return $this;
200 | }
201 |
202 | /**
203 | * Field must be a number between X and Y.
204 | *
205 | * @param numeric $min
206 | * @param numeric $max
207 | * @param bool $include Whether to include limit value.
208 | * @param string $message
209 | * @return FormValidator
210 | */
211 | public function between($min, $max, $include = TRUE, $message = null) {
212 | $message = $this->_getDefaultMessage(__FUNCTION__, array($min, $max, $include));
213 |
214 | $this->min($min, $include, $message)->max($max, $include, $message);
215 | return $this;
216 | }
217 |
218 | /**
219 | * Field has to be greater than or equal to X characters long.
220 | *
221 | * @param int $len
222 | * @param string $message
223 | * @return FormValidator
224 | */
225 | public function minlength($len, $message = null) {
226 | $this->setRule(__FUNCTION__, function($val, $args) {
227 | return !(strlen(trim($val)) < $args[0]);
228 | }, $message, array($len));
229 | return $this;
230 | }
231 |
232 | /**
233 | * Field has to be less than or equal to X characters long.
234 | *
235 | * @param int $len
236 | * @param string $message
237 | * @return FormValidator
238 | */
239 | public function maxlength($len, $message = null) {
240 | $this->setRule(__FUNCTION__, function($val, $args) {
241 | return !(strlen(trim($val)) > $args[0]);
242 | }, $message, array($len));
243 | return $this;
244 | }
245 |
246 | /**
247 | * Field has to be between minlength and maxlength characters long.
248 | *
249 | * @param int $minlength
250 | * @param int $maxlength
251 | * @
252 | */
253 | public function betweenlength($minlength, $maxlength, $message = null) {
254 | $message = empty($message) ? self::getDefaultMessage(__FUNCTION__, array($minlength, $maxlength)) : NULL;
255 |
256 | $this->minlength($minlength, $message)->max($maxlength, $message);
257 | return $this;
258 | }
259 |
260 | /**
261 | * Field has to be X characters long.
262 | *
263 | * @param int $len
264 | * @param string $message
265 | * @return FormValidator
266 | */
267 | public function length($len, $message = null) {
268 | $this->setRule(__FUNCTION__, function($val, $args) {
269 | return (strlen(trim($val)) == $args[0]);
270 | }, $message, array($len));
271 | return $this;
272 | }
273 |
274 | /**
275 | * Field is the same as another one (password comparison etc).
276 | *
277 | * @param string $field
278 | * @param string $label
279 | * @param string $message
280 | * @return FormValidator
281 | */
282 | public function matches($field, $label, $message = null) {
283 | $this->setRule(__FUNCTION__, function($val, $args) {
284 | return ((string) $args[0] == (string) $val);
285 | }, $message, array($this->_getVal($field), $label));
286 | return $this;
287 | }
288 |
289 | /**
290 | * Field is different from another one.
291 | *
292 | * @param string $field
293 | * @param string $label
294 | * @param string $message
295 | * @return FormValidator
296 | */
297 | public function notmatches($field, $label, $message = null) {
298 | $this->setRule(__FUNCTION__, function($val, $args) {
299 | return ((string) $args[0] != (string) $val);
300 | }, $message, array($this->_getVal($field), $label));
301 | return $this;
302 | }
303 |
304 | /**
305 | * Field must start with a specific substring.
306 | *
307 | * @param string $sub
308 | * @param string $message
309 | * @return FormValidator
310 | */
311 | public function startsWith($sub, $message = null) {
312 | $this->setRule(__FUNCTION__, function($val, $args) {
313 | $sub = $args[0];
314 | return (strlen($val) === 0 || substr($val, 0, strlen($sub)) === $sub);
315 | }, $message, array($sub));
316 | return $this;
317 | }
318 |
319 | /**
320 | * Field must NOT start with a specific substring.
321 | *
322 | * @param string $sub
323 | * @param string $message
324 | * @return FormValidator
325 | */
326 | public function notstartsWith($sub, $message = null) {
327 | $this->setRule(__FUNCTION__, function($val, $args) {
328 | $sub = $args[0];
329 | return (strlen($val) === 0 || substr($val, 0, strlen($sub)) !== $sub);
330 | }, $message, array($sub));
331 | return $this;
332 | }
333 |
334 | /**
335 | * Field must end with a specific substring.
336 | *
337 | * @param string $sub
338 | * @param string $message
339 | * @return FormValidator
340 | */
341 | public function endsWith($sub, $message = null) {
342 | $this->setRule(__FUNCTION__, function($val, $args) {
343 | $sub = $args[0];
344 | return (strlen($val) === 0 || substr($val, -strlen($sub)) === $sub);
345 | }, $message, array($sub));
346 | return $this;
347 | }
348 |
349 | /**
350 | * Field must not end with a specific substring.
351 | *
352 | * @param string $sub
353 | * @param string $message
354 | * @return FormValidator
355 | */
356 | public function notendsWith($sub, $message = null) {
357 | $this->setRule(__FUNCTION__, function($val, $args) {
358 | $sub = $args[0];
359 | return (strlen($val) === 0 || substr($val, -strlen($sub)) !== $sub);
360 | }, $message, array($sub));
361 | return $this;
362 | }
363 |
364 | /**
365 | * Field has to be valid IP address.
366 | *
367 | * @param string $message
368 | * @return FormValidator
369 | */
370 | public function ip($message = null) {
371 | $this->setRule(__FUNCTION__, function($val) {
372 | return (strlen(trim($val)) === 0 || filter_var($val, FILTER_VALIDATE_IP) !== FALSE);
373 | }, $message);
374 | return $this;
375 | }
376 |
377 | /**
378 | * Field has to be valid internet address.
379 | *
380 | * @param string $message
381 | * @return FormValidator
382 | */
383 | public function url($message = null) {
384 | $this->setRule(__FUNCTION__, function($val) {
385 | return (strlen(trim($val)) === 0 || filter_var($val, FILTER_VALIDATE_URL) !== FALSE);
386 | }, $message);
387 | return $this;
388 | }
389 |
390 | /**
391 | * Date format.
392 | *
393 | * @return string
394 | */
395 | protected function _getDefaultDateFormat() {
396 | return 'd/m/Y';
397 | }
398 |
399 | /**
400 | * Field has to be a valid date.
401 | *
402 | * @param string $message
403 | * @return FormValidator
404 | */
405 | public function date($message = null) {
406 | $this->setRule(__FUNCTION__, function($val, $args) {
407 |
408 | if (strlen(trim($val)) === 0) {
409 | return TRUE;
410 | }
411 |
412 | try {
413 | $dt = new DateTime($val, new DateTimeZone("UTC"));
414 | return true;
415 | } catch(Exception $e) {
416 | return false;
417 | }
418 |
419 | }, $message, array($format, $separator));
420 | return $this;
421 | }
422 |
423 | /**
424 | * Field has to be a date later than or equal to X.
425 | *
426 | * @param string|int $date Limit date
427 | * @param string $format Date format
428 | * @param string $message
429 | * @return FormValidator
430 | */
431 | public function minDate($date = 0, $format = null, $message = null) {
432 | if (empty($format)) {
433 | $format = $this->_getDefaultDateFormat();
434 | }
435 | if (is_numeric($date)) {
436 | $date = new DateTime($date . ' days'); // Days difference from today
437 | } else {
438 | $fieldValue = $this->_getVal($date);
439 | $date = ($fieldValue == FALSE) ? $date : $fieldValue;
440 |
441 | $date = DateTime::createFromFormat($format, $date);
442 | }
443 |
444 | $this->setRule(__FUNCTION__, function($val, $args) {
445 | $format = $args[1];
446 | $limitDate = $args[0];
447 |
448 | return ($limitDate > DateTime::createFromFormat($format, $val)) ? FALSE : TRUE;
449 | }, $message, array($date, $format));
450 | return $this;
451 | }
452 |
453 | /**
454 | * Field has to be a date later than or equal to X.
455 | *
456 | * @param string|integer $date Limit date.
457 | * @param string $format Date format.
458 | * @param string $message
459 | * @return FormValidator
460 | */
461 | public function maxDate($date = 0, $format = null, $message = null) {
462 | if (empty($format)) {
463 | $format = $this->_getDefaultDateFormat();
464 | }
465 | if (is_numeric($date)) {
466 | $date = new DateTime($date . ' days'); // Days difference from today
467 | } else {
468 | $fieldValue = $this->_getVal($date);
469 | $date = ($fieldValue == FALSE) ? $date : $fieldValue;
470 |
471 | $date = DateTime::createFromFormat($format, $date);
472 | }
473 |
474 | $this->setRule(__FUNCTION__, function($val, $args) {
475 | $format = $args[1];
476 | $limitDate = $args[0];
477 |
478 | return !($limitDate < DateTime::createFromFormat($format, $val));
479 | }, $message, array($date, $format));
480 | return $this;
481 | }
482 |
483 | /**
484 | * Field has to be a valid credit card number format.
485 | *
486 | * @see https://github.com/funkatron/inspekt/blob/master/Inspekt.php
487 | * @param string $message
488 | * @return FormValidator
489 | */
490 | public function ccnum($message = null) {
491 | $this->setRule(__FUNCTION__, function($value) {
492 | $value = str_replace(' ', '', $value);
493 | $length = strlen($value);
494 |
495 | if ($length < 13 || $length > 19) {
496 | return FALSE;
497 | }
498 |
499 | $sum = 0;
500 | $weight = 2;
501 |
502 | for ($i = $length - 2; $i >= 0; $i--) {
503 | $digit = $weight * $value[$i];
504 | $sum += floor($digit / 10) + $digit % 10;
505 | $weight = $weight % 2 + 1;
506 | }
507 |
508 | $mod = (10 - $sum % 10) % 10;
509 |
510 | return ($mod == $value[$length - 1]);
511 | }, $message);
512 | return $this;
513 | }
514 |
515 | /**
516 | * Field has to be one of the allowed ones.
517 | *
518 | * @param string|array $allowed Allowed values.
519 | * @param string $message
520 | * @return FormValidator
521 | */
522 | public function oneOf($allowed, $message = null) {
523 | if (is_string($allowed)) {
524 | $allowed = explode(',', $allowed);
525 | }
526 |
527 | $this->setRule(__FUNCTION__, function($val, $args) {
528 | return in_array($val, $args[0]);
529 | }, $message, array($allowed));
530 | return $this;
531 | }
532 |
533 | // --------------- END [ADD NEW RULE FUNCTIONS ABOVE THIS LINE] ------------
534 |
535 | /**
536 | * callback
537 | * @param string $name
538 | * @param mixed $function
539 | * @param string $message
540 | * @param mixed $params
541 | * @return FormValidator
542 | */
543 | public function callback($callback, $message = '', $params = array()) {
544 | if (is_callable($callback)) {
545 |
546 | // If an array is callable, it is a method
547 | if (is_array($callback)) {
548 | $func = new ReflectionMethod($callback[0], $callback[1]);
549 | } else {
550 | $func = new ReflectionFunction($callback);
551 | }
552 |
553 | if (!empty($func)) {
554 | // needs a unique name to avoild collisions in the rules array
555 | $name = 'callback_' . sha1(uniqid());
556 | $this->setRule($name, function($value) use ($func, $params, $callback) {
557 | // Creates merged arguments array with validation target as first argument
558 | $args = array_merge(array($value), (is_array($params) ? $params : array($params)));
559 | if (is_array($callback)) {
560 | // If callback is a method, the object must be the first argument
561 | return $func->invokeArgs($callback[0], $args);
562 | } else {
563 | return $func->invokeArgs($args);
564 | }
565 | }, $message, $params);
566 | }
567 |
568 | } else {
569 | throw new Exception(sprintf('%s is not callable.', $function));
570 | }
571 |
572 | return $this;
573 | }
574 |
575 | // ------------------ PRE VALIDATION FILTERING -------------------
576 | /**
577 | * add a filter callback for the data
578 | *
579 | * @param mixed $callback
580 | * @return FormValidator
581 | */
582 | public function filter($callback) {
583 | if(is_callable($callback)) {
584 | $this->filters[] = $callback;
585 | }
586 |
587 | return $this;
588 | }
589 |
590 | /**
591 | * applies filters based on a data key
592 | *
593 | * @access protected
594 | * @param string $key
595 | * @return void
596 | */
597 | protected function _applyFilters($key) {
598 | $this->_applyFilter($this->data[$key]);
599 | }
600 |
601 | /**
602 | * recursively apply filters to a value
603 | *
604 | * @access protected
605 | * @param mixed $val reference
606 | * @return void
607 | */
608 | protected function _applyFilter(&$val) {
609 | if (is_array($val)) {
610 | foreach($val as $key => &$item) {
611 | $this->_applyFilter($item);
612 | }
613 | } else {
614 | foreach($this->filters as $filter) {
615 | $val = $filter($val);
616 | }
617 | }
618 | }
619 |
620 | /**
621 | * validate
622 | * @param string $key
623 | * @param string $label
624 | * @return bool
625 | */
626 | public function validate($key, $recursive = false, $label = '') {
627 | // set up field name for error message
628 | $this->fields[$key] = (empty($label)) ? 'Field with the name of "' . $key . '"' : $label;
629 |
630 | // apply filters to the data
631 | $this->_applyFilters($key);
632 |
633 | $val = $this->_getVal($key);
634 |
635 | // validate the piece of data
636 | $this->_validate($key, $val, $recursive);
637 |
638 | // reset rules
639 | $this->rules = array();
640 | $this->filters = array();
641 | return $val;
642 | }
643 |
644 | /**
645 | * recursively validates a value
646 | *
647 | * @access protected
648 | * @param string $key
649 | * @param mixed $val
650 | * @return bool
651 | */
652 | protected function _validate($key, $val, $recursive = false)
653 | {
654 | if ($recursive && is_array($val)) {
655 | // run validations on each element of the array
656 | foreach($val as $index => $item) {
657 | if (!$this->_validate($key, $item, $recursive)) {
658 | // halt validation for this value.
659 | return FALSE;
660 | }
661 | }
662 | return TRUE;
663 |
664 | } else {
665 |
666 | // try each rule function
667 | foreach ($this->rules as $rule => $is_true) {
668 | if ($is_true) {
669 | $function = $this->functions[$rule];
670 | $args = $this->arguments[$rule]; // Arguments of rule
671 |
672 | $valid = (empty($args)) ? $function($val) : $function($val, $args);
673 |
674 | if ($valid === FALSE) {
675 | $this->registerError($rule, $key);
676 |
677 | $this->rules = array(); // reset rules
678 | $this->filters = array();
679 | return FALSE;
680 | }
681 | }
682 | }
683 |
684 | $this->validData[$key] = $val;
685 | return TRUE;
686 | }
687 | }
688 |
689 | /**
690 | * Whether errors have been found.
691 | *
692 | * @return bool
693 | */
694 | public function hasErrors() {
695 | return (count($this->errors) > 0);
696 | }
697 |
698 | /**
699 | * Get specific error.
700 | *
701 | * @param string $field
702 | * @return string
703 | */
704 | public function getError($field) {
705 | return $this->errors[$field];
706 | }
707 |
708 | /**
709 | * Get all errors.
710 | *
711 | * @return array
712 | */
713 | public function getAllErrors($keys = true) {
714 | return ($keys == true) ? $this->errors : array_values($this->errors);
715 | }
716 |
717 | public function getValidData()
718 | {
719 | return $this->validData;
720 | }
721 |
722 | /**
723 | * _getVal with added support for retrieving values from numeric and
724 | * associative multi-dimensional arrays. When doing so, use DOT notation
725 | * to indicate a break in keys, i.e.:
726 | *
727 | * key = "one.two.three"
728 | *
729 | * would search the array:
730 | *
731 | * array('one' => array(
732 | * 'two' => array(
733 | * 'three' => 'RETURN THIS'
734 | * )
735 | * );
736 | *
737 | * @param string $key
738 | * @return mixed
739 | */
740 | protected function _getVal($key) {
741 | // handle multi-dimensional arrays
742 | if (strpos($key, '.') !== FALSE) {
743 | $arrData = NULL;
744 | $keys = explode('.', $key);
745 | $keyLen = count($keys);
746 | for ($i = 0; $i < $keyLen; ++$i) {
747 | if (trim($keys[$i]) == '') {
748 | return false;
749 | } else {
750 | if (is_null($arrData)) {
751 | if (!isset($this->data[$keys[$i]])) {
752 | return false;
753 | }
754 | $arrData = $this->data[$keys[$i]];
755 | } else {
756 | if (!isset($arrData[$keys[$i]])) {
757 | return false;
758 | }
759 | $arrData = $arrData[$keys[$i]];
760 | }
761 | }
762 | }
763 | return $arrData;
764 | } else {
765 | return (isset($this->data[$key])) ? $this->data[$key] : FALSE;
766 | }
767 | }
768 |
769 | /**
770 | * Register error.
771 | *
772 | * @param string $rule
773 | * @param string $key
774 | * @param string $message
775 | */
776 | protected function registerError($rule, $key, $message = null) {
777 | if (empty($message)) {
778 | $message = $this->messages[$rule];
779 | }
780 |
781 | $this->errors[$key] = sprintf($message, $this->fields[$key]);
782 | }
783 |
784 | /**
785 | * Set rule.
786 | *
787 | * @param string $rule
788 | * @param closure $function
789 | * @param string $message
790 | * @param array $args
791 | */
792 | public function setRule($rule, $function, $message = '', $args = array()) {
793 | if (!array_key_exists($rule, $this->rules)) {
794 | $this->rules[$rule] = TRUE;
795 | if (!array_key_exists($rule, $this->functions)) {
796 | if (!is_callable($function)) {
797 | die('Invalid function for rule: ' . $rule);
798 | }
799 | $this->functions[$rule] = $function;
800 | }
801 | $this->arguments[$rule] = $args; // Specific arguments for rule
802 |
803 | $this->messages[$rule] = (empty($message)) ? $this->_getDefaultMessage($rule, $args) : $message;
804 | }
805 | }
806 |
807 | /**
808 | * Get default error message.
809 | *
810 | * @param string $key
811 | * @param array $args
812 | * @return string
813 | */
814 | protected function _getDefaultMessage($rule, $args = null) {
815 |
816 | switch ($rule) {
817 | case 'email':
818 | $message = '%s is an invalid email address.';
819 | break;
820 |
821 | case 'ip':
822 | $message = '%s is an invalid IP address.';
823 | break;
824 |
825 | case 'url':
826 | $message = '%s is an invalid url.';
827 | break;
828 |
829 | case 'required':
830 | $message = '%s is required.';
831 | break;
832 |
833 | case 'float':
834 | $message = '%s must consist of numbers only.';
835 | break;
836 |
837 | case 'integer':
838 | $message = '%s must consist of integer value.';
839 | break;
840 |
841 | case 'digits':
842 | $message = '%s must consist only of digits.';
843 | break;
844 |
845 | case 'min':
846 | $message = '%s must be greater than ';
847 | if ($args[1] == TRUE) {
848 | $message .= 'or equal to ';
849 | }
850 | $message .= $args[0] . '.';
851 | break;
852 |
853 | case 'max':
854 | $message = '%s must be less than ';
855 | if ($args[1] == TRUE) {
856 | $message .= 'or equal to ';
857 | }
858 | $message .= $args[0] . '.';
859 | break;
860 |
861 | case 'between':
862 | $message = '%s must be between ' . $args[0] . ' and ' . $args[1] . '.';
863 | if ($args[2] == FALSE) {
864 | $message .= '(Without limits)';
865 | }
866 | break;
867 |
868 | case 'minlength':
869 | $message = '%s must be at least ' . $args[0] . ' characters or longer.';
870 | break;
871 |
872 | case 'maxlength':
873 | $message = '%s must be no longer than ' . $args[0] . ' characters.';
874 | break;
875 |
876 | case 'length':
877 | $message = '%s must be exactly ' . $args[0] . ' characters in length.';
878 | break;
879 |
880 | case 'matches':
881 | $message = '%s must match ' . $args[1] . '.';
882 | break;
883 |
884 | case 'notmatches':
885 | $message = '%s must not match ' . $args[1] . '.';
886 | break;
887 |
888 | case 'startsWith':
889 | $message = '%s must start with "' . $args[0] . '".';
890 | break;
891 |
892 | case 'notstartsWith':
893 | $message = '%s must not start with "' . $args[0] . '".';
894 | break;
895 |
896 | case 'endsWith':
897 | $message = '%s must end with "' . $args[0] . '".';
898 | break;
899 |
900 | case 'notendsWith':
901 | $message = '%s must not end with "' . $args[0] . '".';
902 | break;
903 |
904 | case 'date':
905 | $message = '%s is not valid date.';
906 | break;
907 |
908 | case 'mindate':
909 | $message = '%s must be later than ' . $args[0]->format($args[1]) . '.';
910 | break;
911 |
912 | case 'maxdate':
913 | $message = '%s must be before ' . $args[0]->format($args[1]) . '.';
914 | break;
915 |
916 | case 'oneof':
917 | $message = '%s must be one of ' . implode(', ', $args[0]) . '.';
918 | break;
919 |
920 | case 'ccnum':
921 | $message = '%s must be a valid credit card number.';
922 | break;
923 |
924 | default:
925 | $message = '%s has an error.';
926 | break;
927 | }
928 |
929 | return $message;
930 | }
931 |
932 | }
933 |
--------------------------------------------------------------------------------
/Validator/Exception.php:
--------------------------------------------------------------------------------
1 | _errors = $errors;
9 | }
10 |
11 | public function getErrors() {
12 | return $this->_errors;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/ValidatorTest.php:
--------------------------------------------------------------------------------
1 | _validator = new Validator();
12 | }
13 |
14 | /**
15 | * test filter with string 'trim' as the callbacl
16 | */
17 | public function testFilterTrimCallback()
18 | {
19 | $validator = $this->_validator;
20 |
21 | $data = array(
22 | 'email' => ' test@emailwithwhitespace.com ',
23 | );
24 |
25 | $validator->setData($data);
26 | $email = $validator->filter('trim')->validate('email');
27 |
28 | $this->assertEquals(strlen($email), 28);
29 | }
30 |
31 | /**
32 | * test the FormValidator email rule
33 | */
34 | public function testValidateEmail()
35 | {
36 | $validator = $this->_validator;
37 |
38 | $data = array(
39 | 'email' => 'test@test.com',
40 | );
41 |
42 | $validator->email()->validate('email');
43 |
44 | $this->assertFalse($validator->hasErrors());
45 | }
46 |
47 | /**
48 | * test the FormValidator email rule on an array of emails
49 | */
50 | public function testValidateEmailArray()
51 | {
52 | $validator = $this->_validator;
53 |
54 | $data = array(
55 | 'emails' => array(
56 | 'test@test.com',
57 | 'test2@test.com',
58 | 'test3@test.com'
59 | )
60 | );
61 |
62 | $validator->setData($data);
63 | $validator->email()->validate('emails', true);
64 | $this->assertFalse($validator->hasErrors());
65 | }
66 |
67 | /**
68 | * test the Validator
69 | */
70 | public function testInvalidEmailArray()
71 | {
72 | $validator = $this->_validator;
73 |
74 | $data = array(
75 | 'emails' => array(
76 | 'test@test.com',
77 | 'test2@test.com',
78 | 'testtest.com'
79 | )
80 | );
81 |
82 | $validator->setData($data)
83 | ->email()
84 | ->validate('emails', true);
85 |
86 | $this->assertTrue($validator->hasErrors());
87 | }
88 |
89 | /**
90 | * test the required rule with value present
91 | */
92 | public function testValidateRequired()
93 | {
94 | $validator = $this->_validator;
95 |
96 | $data = array(
97 | 'name' => 'Test Name'
98 | );
99 |
100 | $validator->setData($data)
101 | ->required()
102 | ->validate('name');
103 |
104 | $this->assertFalse($validator->hasErrors());
105 | }
106 |
107 | /**
108 | * test the required rule without value present
109 | */
110 | public function testValidateRequiredEmptyVal()
111 | {
112 | $validator = $this->_validator;
113 |
114 | $data = array(
115 | 'name' => ''
116 | );
117 |
118 | $validator->setData($data)
119 | ->required()
120 | ->validate('name');
121 |
122 | $this->assertTrue($validator->hasErrors());
123 | }
124 |
125 | public function testValidateRequiredWithArray()
126 | {
127 | $validator = $this->_validator;
128 |
129 | $data = array(
130 | 'names' => array('Test Name', 'Another Name', 'And Another Name')
131 | );
132 |
133 | $validator->setData($data)
134 | ->required()
135 | ->validate('names');
136 |
137 | $this->assertFalse($validator->hasErrors());
138 | }
139 |
140 | /**
141 | * test the required rule without value present
142 | */
143 | public function testValidateRequiredWithArrayEmptyElement()
144 | {
145 | $validator = $this->_validator;
146 |
147 | $data = array(
148 | 'names' => array('Test Name', '', 'And Another Name')
149 | );
150 |
151 | $validator->setData($data)
152 | ->required()
153 | ->validate('names', true);
154 |
155 | $this->assertTrue($validator->hasErrors());
156 | }
157 |
158 | /**
159 | * test the float rule
160 | */
161 | public function testValidateFloat()
162 | {
163 | $validator = $this->_validator;
164 |
165 | $data = array(
166 | 'float' => 2.5
167 | );
168 |
169 | $validator->setData($data)
170 | ->float()
171 | ->validate('float');
172 |
173 | $this->assertFalse($validator->hasErrors());
174 |
175 | $data['float'] = 'test';
176 |
177 | $validator->setData($data)
178 | ->float()
179 | ->validate('float');
180 |
181 | $this->assertTrue($validator->hasErrors());
182 | }
183 |
184 | /**
185 | * test the integer rule
186 | */
187 | public function testValidateInteger()
188 | {
189 | $validator = $this->_validator;
190 |
191 | $data = array(
192 | 'integer' => 20
193 | );
194 |
195 | $validator->setData($data)
196 | ->integer()
197 | ->validate('integer');
198 |
199 | $this->assertFalse($validator->hasErrors());
200 |
201 | $data['integer'] = 'test';
202 |
203 | $validator->setData($data)
204 | ->integer()
205 | ->validate('integer');
206 |
207 | $this->assertTrue($validator->hasErrors());
208 | }
209 |
210 | /**
211 | * test the digits rule
212 | */
213 | public function testValidateDigits()
214 | {
215 | $validator = $this->_validator;
216 |
217 | $data = array(
218 | 'digits' => 20
219 | );
220 |
221 | $validator->setData($data)
222 | ->digits()
223 | ->validate('digits');
224 |
225 | $this->assertFalse($validator->hasErrors());
226 |
227 | $data['digits'] = 'test';
228 |
229 | $validator->setData($data)
230 | ->digits()
231 | ->validate('digits');
232 |
233 | $this->assertTrue($validator->hasErrors());
234 | }
235 |
236 | /**
237 | * test the min rule
238 | */
239 | public function testValidateMin()
240 | {
241 | $validator = $this->_validator;
242 |
243 | $data = array(
244 | 'min' => 35
245 | );
246 |
247 | $validator->setData($data)
248 | ->min(30)
249 | ->validate('min');
250 |
251 | $this->assertFalse($validator->hasErrors());
252 |
253 | $validator->setData($data)
254 | ->min(40)
255 | ->validate('min');
256 |
257 | $this->assertTrue($validator->hasErrors());
258 | }
259 |
260 | /**
261 | * test the max rule
262 | */
263 | public function testValidateMax()
264 | {
265 | $validator = $this->_validator;
266 |
267 | $data = array(
268 | 'max' => 29
269 | );
270 |
271 | $validator->setData($data)
272 | ->max(30)
273 | ->validate('max');
274 |
275 | $this->assertFalse($validator->hasErrors());
276 |
277 | $validator->setData($data)
278 | ->max(20)
279 | ->validate('max');
280 |
281 | $this->assertTrue($validator->hasErrors());
282 | }
283 |
284 | /**
285 | * test the between rule
286 | */
287 | public function testValidateBetween()
288 | {
289 | $validator = $this->_validator;
290 |
291 | $data = array(
292 | 'between' => 35
293 | );
294 |
295 | $validator->setData($data)
296 | ->between(30, 40)
297 | ->validate('between');
298 |
299 | $this->assertFalse($validator->hasErrors());
300 |
301 | $validator->setData($data)
302 | ->between(40, 50)
303 | ->validate('between');
304 |
305 | $this->assertTrue($validator->hasErrors());
306 | }
307 |
308 | /**
309 | * test the minLength rule
310 | */
311 | public function testValidateMinLength()
312 | {
313 | $validator = $this->_validator;
314 |
315 | $data = array(
316 | 'minlength' => 'this is a string'
317 | );
318 |
319 | $validator->setData($data)
320 | ->minlength(10)
321 | ->validate('minlength');
322 |
323 | $this->assertFalse($validator->hasErrors());
324 |
325 | $validator->setData($data)
326 | ->minlength(60)
327 | ->validate('minlength');
328 |
329 | $this->assertTrue($validator->hasErrors());
330 | }
331 |
332 | /**
333 | * test the minLength rule
334 | */
335 | public function testValidateMaxLength()
336 | {
337 | $validator = $this->_validator;
338 |
339 | $data = array(
340 | 'maxlength' => 'this is a string'
341 | );
342 |
343 | $validator->setData($data)
344 | ->maxlength(20)
345 | ->validate('maxlength');
346 |
347 | $this->assertFalse($validator->hasErrors());
348 |
349 | $validator->setData($data)
350 | ->maxlength(5)
351 | ->validate('maxlength');
352 |
353 | $this->assertTrue($validator->hasErrors());
354 | }
355 |
356 | /**
357 | * test the minLength rule
358 | */
359 | public function testValidateLength()
360 | {
361 | $validator = $this->_validator;
362 |
363 | $data = array(
364 | 'length' => 'this is a string'
365 | );
366 |
367 | $validator->setData($data)
368 | ->length(16)
369 | ->validate('length');
370 |
371 | $this->assertFalse($validator->hasErrors());
372 |
373 | $validator->setData($data)
374 | ->length(5)
375 | ->validate('length');
376 |
377 | $this->assertTrue($validator->hasErrors());
378 | }
379 |
380 | /**
381 | * test the matches rule
382 | */
383 | public function testValidateMatches()
384 | {
385 | $validator = $this->_validator;
386 |
387 | $data = array(
388 | 'password' => 'testpass',
389 | 'password_confirm' => 'testpass'
390 | );
391 |
392 | $validator->setData($data)
393 | ->matches('password_confirm', 'Password Confirmation')
394 | ->validate('password');
395 |
396 | $this->assertFalse($validator->hasErrors());
397 |
398 | $data['password_confirm'] = 'Oh Noes I forgot what I types!';
399 |
400 | $validator->setData($data)
401 | ->matches('password_confirmaton', 'Password Confirmation')
402 | ->validate('password');
403 |
404 | $this->assertTrue($validator->hasErrors());
405 | }
406 |
407 | /**
408 | * test the notmatches rule
409 | */
410 | public function testValidateNotMatches()
411 | {
412 | $validator = $this->_validator;
413 |
414 | $data = array(
415 | 'password' => 'test',
416 | 'password_confirm' => 'another test'
417 | );
418 |
419 | $validator->setData($data)
420 | ->notmatches('password_confirm', 'Password Confirmation')
421 | ->validate('password');
422 |
423 | $this->assertFalse($validator->hasErrors());
424 |
425 | $data['password_confirm'] = 'test';
426 |
427 | $validator->setData($data)
428 | ->notmatches('password_confirm', 'Password Confirmation')
429 | ->validate('password');
430 |
431 | $this->assertTrue($validator->hasErrors());
432 | }
433 |
434 | /**
435 | * test the date rule
436 | */
437 | public function testValidateDate()
438 | {
439 | $validator = $this->_validator;
440 |
441 | $data = array(
442 | 'date' => '10/20/2010',
443 | );
444 |
445 | $validator->setData($data)
446 | ->date('m/d/Y')
447 | ->validate('date');
448 |
449 | $this->assertFalse($validator->hasErrors());
450 |
451 | $data['date'] = 'test';
452 |
453 | $validator->setData($data)
454 | ->date('m/d/Y')
455 | ->validate('date');
456 |
457 | $this->assertTrue($validator->hasErrors());
458 | }
459 |
460 | public function testValidateCallback()
461 | {
462 | $validator = $this->_validator;
463 |
464 | $data = array(
465 | 'test' => 'test'
466 | );
467 |
468 | $validator
469 | ->setData($data)
470 | ->callback(function($val) {
471 | return true;
472 | })
473 | ->validate('test');
474 | }
475 |
476 | public function testValidateFiles()
477 | {
478 |
479 | }
480 | }
--------------------------------------------------------------------------------
/tests/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ./
4 |
5 |
--------------------------------------------------------------------------------