diff --git a/README.md b/README.md index 731c815..145b449 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ The full list of validation rules are listed below, after the next section. ## Validator +To validate an array of values + ```php $validator = new Validator(); @@ -48,7 +50,6 @@ Rule options: - on: default:null. set to create or update to run the rule only on those, works with second argument of `validate` - allowEmpty: default:false validation will be pass on empty values - stopOnFail: default:false wether to continue if validation fails -- present: default:false the field (key) must be present (but can be empty) You can also use custom validation rules using @@ -68,6 +69,15 @@ $validator->add('status', 'uniqueRuleName', [ ]); ``` + +The `Validator` uses the `Validation` rules and has 3 additional validation rules built in, `required`, `optional`, and `present`. + +These rules should be called first, and for `required` and `present`, if they fail no further validation rules will run. + +- required: this means the key must be `present` and the value is `notEmpty` +- optional: this means that data is optional, if the value is `empty` then it will not run any more validation rules. +- present: this means that the data array must have the key present, its irrelevant if the value is empty or not. + ## Validation Rules ### accepted @@ -410,6 +420,20 @@ Validates a value is not empty and has anything other than whitespaces. Validation::notBlank('foo'); ``` +### notEmpty + +Validates a value is not empty, a value is empty + +- `null` +- empty string `''` +- an empty array +- empty file upload + +```php +Validation::notEmpty('foo'); +``` + + ### notIn Validates a value is not in an array of values. diff --git a/src/Validator.php b/src/Validator.php index e6e7d8c..0199cb9 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -72,6 +72,24 @@ class Validator 'url' => 'Invalid URL', ]; + /** + * Array of Objects or Classes with static methods + * + * @var array + */ + private $providers = []; + + /** + * @param array $options + */ + public function __construct(array $options = []) + { + $options += [ + 'providers' => [Validation::class] + ]; + $this->providers = $options['providers']; + } + /** * Adds a validation rule, if you provide just a string, then the rule will be created with the same name as * the rule. @@ -122,7 +140,6 @@ class Validator * - on: default:null. set to create or update to run the rule only on those * - allowEmpty: default:false validation will be pass on empty values * - stopOnFail: default:false wether to continue if validation fails - * - present: default:false the field (key) must be present (but can be empty) * * @return \Origin\Validation\Validator */ @@ -151,7 +168,6 @@ public function add(string $field, $name, array $options = []) 'rule' => $name, 'message' => null, 'on' => null, - 'present' => false, 'allowEmpty' => false, 'stopOnFail' => false ]; @@ -260,17 +276,15 @@ public function validate(array $data, bool $isNewRecord = true): array continue; } - # Check Options (present & allowEmpty) - if ($validationRule['present'] === true && ! $present) { - $errors[$field][] = $this->messageMap['present']; - if ($validationRule['stopOnFail']) { - break; - } + if ($validationRule['allowEmpty'] === true && $isEmpty) { continue; } - if ($validationRule['allowEmpty'] === true && $isEmpty) { - continue; + if ($validationRule['rule'] === 'confirm') { + $otherField = $data[$field .'_confirm'] ?? null; + $validationRule['rule'] = function ($value) use ($otherField) { + return $value == $otherField; + }; } # Carry out validation @@ -318,11 +332,18 @@ protected function isValid($value, array $validationRule): bool $args = array_merge([$value], $validationRule['rule']); } - // Check validation class - if (is_string($rule) && method_exists(Validation::class, $rule)) { - return forward_static_call([Validation::class, $rule], ...$args); + if (is_string($rule)) { + foreach ($this->providers as $provider) { + // run on classes e.g. Validation::class + if (is_string($provider) && method_exists($provider, $rule)) { + return forward_static_call([$provider, $rule], ...$args); + } + if (is_object($provider) && method_exists($provider, $rule)) { + return call_user_func_array([$provider,$rule], $args); + } + } } - + throw new InvalidArgumentException('Invalid validation rule'); } diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 680ed0f..e77287f 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -44,7 +44,6 @@ public function testAdd() 'rule' => 'notEmpty', 'message' => 'This field cannot be empty', 'on' => null, - 'present' => false, 'allowEmpty' => false, 'stopOnFail' => false ]; @@ -56,7 +55,6 @@ public function testAdd() 'rule' => 'notEmpty', 'message' => 'Need input', 'on' => null, - 'present' => false, 'allowEmpty' => false, 'stopOnFail' => false ]; @@ -71,7 +69,6 @@ public function testAdd() 'rule' => 'required', 'message' => 'This field is required', 'on' => null, - 'present' => false, 'allowEmpty' => false, 'stopOnFail' => false ]; @@ -82,7 +79,6 @@ public function testAdd() 'rule' => 'email', 'message' => 'Bad email address', 'on' => null, - 'present' => false, 'allowEmpty' => false, 'stopOnFail' => false ]; @@ -184,7 +180,6 @@ public function testRules() 'rule' => 'notEmpty', 'message' => 'This field cannot be empty', 'on' => null, - 'present' => false, 'allowEmpty' => false, 'stopOnFail' => false ]; @@ -268,37 +263,6 @@ public function testValidatePresent() $this->assertEmpty($validator->validate(['email' => 'phpunit@originphp.com'])); } - public function testValidatePresentOption() - { - $validator = new Validator(); - $validator->add('email', [ - 'email' => [ - 'rule' => 'email', - 'present' => true - ] - ]); - $errors = $validator->validate(['name' => 'foo']); - - $this->assertArrayHasKey('email', $errors); - $this->assertEquals('This field is must be present', $errors['email'][0]); - - $validator = new Validator(); - $validator->add('email', [ - 'notEmpty' => [ - 'rule' => 'notEmpty', - 'present' => true, - 'stopOnFail' => true, - ], - 'email' => [ - 'rule' => 'email' - ] - ]); - $errors = $validator->validate(['foo' => 'bar']); - $this->assertArrayHasKey('email', $errors); - $this->assertEquals('This field is must be present', $errors['email'][0]); - $this->assertCount(1, $errors['email']); - } - public function testValidateAllowEmptyOption() { $validator = new Validator(); @@ -323,6 +287,20 @@ public function testValidateMultipleFailures() $this->assertCount(2, $errors['email']); } + public function testValidateConfirm() + { + $validator = new Validator(); + $validator->add('password', [ + 'confirm' + ]); + $errors = $validator->validate(['password'=>'foo']); + $this->assertNotEmpty($errors); + $errors = $validator->validate(['password'=>'foo','password_confirm'=>'bar']); + $this->assertNotEmpty($errors); + $errors = $validator->validate(['password'=>'foo','password_confirm'=>'foo']); + $this->assertEmpty($errors); + } + /** * @depends testValidateMultipleFailures */