From 579a61a169e73071cfc3c890b2a9ffe3cf7946cd Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 14:59:45 +0300 Subject: [PATCH 01/49] introduce ValidatorRule and refactor code and add/fix tests --- src/Validator.php | 103 +++++++++++++------------------- src/ValidatorRule.php | 132 ++++++++++++++++++++++++++++++++++++++++++ tests/BasicTest.php | 125 +++++++++++++++++++++++++++++++++++---- 3 files changed, 288 insertions(+), 72 deletions(-) create mode 100644 src/ValidatorRule.php diff --git a/src/Validator.php b/src/Validator.php index 50964ea..7ef7e2d 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -17,61 +17,46 @@ class Validator { use WarnDynamicPropertyTrait; + /** - * Array of rules in following format which is natively supported by Valitron mapFieldsRules(): - * [ - * 'foo' => [ - * ['required'], - * ['integer', 'message'=>'test 1'], - * ], - * 'bar' => [ - * ['email'], - * ['lengthBetween', 4, 10, 'message'=>'test 2'], - * ], - * ];. - * - * @var array, list): bool>>> + * @var list */ public array $rules = []; + public function __construct(Model $model) + { + $model->onHook(Model::HOOK_VALIDATE, \Closure::fromCallable([$this, 'validate'])); + } + /** - * Array of conditional rules in following format: - * [ - * [ - * $conditions, // array of conditions - * $then_rules, // array in $this->rules format which will be used if conditions are met - * $else_rules // array in $this->rules format which will be used if conditions are not met - * ], - * ]. + * Set rules of particular field. + * + * @param array, list): bool>> $rules + * @param array|list> $conditions * - * @var list< - * array{ - * array, - * array, list): bool>>>, - * array, list): bool>>> - * } - * > + * @return $this */ - public array $if_rules = []; - - public function __construct(Model $model) + public function rule(string $field, array $rules, ?string $activateOn = null, array $conditions = []): self { - $model->onHook(Model::HOOK_VALIDATE, \Closure::fromCallable([$this, 'validate'])); + foreach ($rules as $rule) { + $validatorRule = new ValidatorRule($field, $rule); + if ($activateOn !== null) { + $validatorRule->setActivateOnResult($activateOn, $conditions); + } + $this->addValidatorRule($validatorRule); + } + + return $this; } /** * Set one rule. * - * @param array, list): bool>> $rules - * * @return $this */ - public function rule(string $field, array $rules): self + public function addValidatorRule(ValidatorRule $validatorRule): self { - $this->rules[$field] = array_merge( - $this->rules[$field] ?? [], - $rules - ); + $this->rules[] = $validatorRule; return $this; } @@ -79,7 +64,7 @@ public function rule(string $field, array $rules): self /** * Set multiple rules. * - * @param array, list): bool>>> $hash array with field name as key and rules as value + * @param array, list): bool>>> $hash array with field name as key and rules as value * * @return $this */ @@ -95,19 +80,21 @@ public function rules(array $hash): self /** * Set conditional rules. * - * @param array $conditions - * @param array, list): bool>>> $then_hash - * @param array, list): bool>>> $else_hash + * @param array|list> $conditions + * @param array, list): bool>>> $then_hash + * @param array, list): bool>>> $else_hash * * @return $this */ public function if(array $conditions, array $then_hash, array $else_hash = []): self { - $this->if_rules[] = [ - $conditions, - $then_hash, - $else_hash, - ]; + foreach ($then_hash as $field => $rules) { + $this->rule($field, $rules, ValidatorRule::ON_SUCCESS, $conditions); + } + + foreach ($else_hash as $field => $rules) { + $this->rule($field, $rules, ValidatorRule::ON_FAIL, $conditions); + } return $this; } @@ -117,28 +104,20 @@ public function if(array $conditions, array $then_hash, array $else_hash = []): * * @return array array of errors in format: [field_name => error_message] */ - public function validate(Model $model, ?string $intent = null): array + public function validate(Model $model): array { // initialize Validator, set data $v = new \Valitron\Validator($model->get()); - // prepare array of all rules we have to validate - // this should also include respective rules from $this->if_rules. - $all_rules = $this->rules; - - foreach ($this->if_rules as $row) { - [$conditions, $then_hash, $else_hash] = $row; - - $test = true; - foreach ($conditions as $field => $value) { - $test = $test && ($model->get($field) === $value); + $rules = []; + foreach ($this->rules as $rule) { + if ($rule->isActivated($model) === true) { + $rules[$rule->field][] = $rule->getValitronRule(); } - - $all_rules = array_merge_recursive($all_rules, $test ? $then_hash : $else_hash); } // set up Valitron rules - $v->mapFieldsRules($all_rules); + $v->mapFieldsRules($rules); // validate and if errors then format them to fit Atk4 error format if ($v->validate() === true) { diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php new file mode 100644 index 0000000..cedc0ea --- /dev/null +++ b/src/ValidatorRule.php @@ -0,0 +1,132 @@ + + */ + public array $activateConditions = []; + public ?string $activateOn = null; + + /** + * @var list, list): bool> + */ + private array $rule = []; + private ?string $message = null; + + /** + * @param string|array, list): bool> $rule + */ + public function __construct(string $field, $rule) + { + if (is_string($rule)) { + $rule = [$rule]; + } + + $this->field = $field; + + $message = $rule['message'] ?? null; + if (isset($rule['message'])) { + unset($rule['message']); + } + + $this->setRule($rule); + $this->setMessage($message); + } + + /** + * @param array $activationConditions [field_name => value] + */ + public function setActivateOnSuccess(array $activationConditions): void + { + $this->setActivateOnResult(self::ON_SUCCESS, $activationConditions); + } + + /** + * @param array $activationConditions [field_name => value] + */ + public function setActivateOnFail(array $activationConditions): void + { + $this->setActivateOnResult(self::ON_FAIL, $activationConditions); + } + + /** + * @param array $activationConditions [field_name => value] + */ + public function setActivateOnResult(string $activateOn, array $activationConditions): void + { + if ($this->activateOn !== null) { + throw new Exception('Activation condition already set'); + } + + $this->activateOn = $activateOn; + $this->activateConditions = $activationConditions; + } + + public function isActivated(Model $model): bool + { + $this->activateOn ??= self::ON_SUCCESS; + + foreach ($this->activateConditions as $conditionField => $conditionValue) { + if ($this->activateOn === self::ON_SUCCESS && $model->get($conditionField) !== $conditionValue) { + return false; + } + + if ($this->activateOn === self::ON_FAIL && $model->get($conditionField) === $conditionValue) { + return false; + } + } + + return true; + } + + /** + * @param array, list): bool> $rule + */ + private function setRule(array $rule): void + { + $this->rule = $rule; + } + + private function setMessage(?string $message = null): void + { + $this->message = $message; + } + + /** + * @return array, list): bool> + */ + public function getRule(): array + { + return $this->rule; + } + + public function getMessage(): ?string + { + return $this->message; + } + + /** + * @return array, list): bool>> + */ + public function getValitronRule(): array + { + $rule = $this->getRule(); + if ($this->getMessage() !== null) { + $rule['message'] = $this->getMessage(); + } + + return $rule; + } +} diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 6bed442..4d69bc8 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -8,6 +8,7 @@ use Atk4\Data\Schema\TestCase; use Atk4\Validate\Tests\Model\Dummy; use Atk4\Validate\Validator; +use Atk4\Validate\ValidatorRule; class BasicTest extends TestCase { @@ -62,7 +63,7 @@ public function testSimple2(): void $validator->rule('name', ['required', ['lengthMin', 3]]); - $err = $model->createEntity()->set('name', 'a')->validate(); + $err = $model->createEntity()->setNull('name')->validate(); self::assertSame(['name'], array_keys($err)); } @@ -97,10 +98,10 @@ public function testCallback1(): void $model = $this->createModel(); $validator = $this->createValidator($model); - // Age should be odd (nepāra skaitlis) + // Age should be odd number $validator->rule('age', [ [ - static function ($field, $value, $params, $data) { + static function (string $field, $value, array $params, array $data): bool { return $value % 2 !== 0; }, 'message' => 'Age should be odd', @@ -192,7 +193,7 @@ public function testMix(): void 'type' => 'dog', 'age' => 2, ])->validate(); - self::assertSame(['age'], array_keys($err)); // for dogs also age should be at least 3 + self::assertSame(['age'], array_keys($err)); // for dogs age should be at least 3 $err = $model->createEntity()->setMulti([ 'type' => 'dog', @@ -229,18 +230,122 @@ public function testModelHookValidate(): void { $model = $this->createModel(); $validator = $this->createValidator($model); - $validator->rule('name', ['required', ['lengthMin', 3]]); + $validator->rule('name', ['required', ['lengthMin', 3, 'message' => 'Name to short']]); - $entity = $model->createEntity(); - $entity->setMulti([ + $entity = $model->createEntity()->setMulti([ 'name' => 'abcd', 'type' => 'dog', ]); - $err = $entity->validate(); - self::assertSame([], $err); - // will not raise exception for return an empty array in place of null $entity->save(); + + $entity = $model->createEntity()->setMulti([ + 'name' => 'a', + 'type' => 'dog', + ]); + + // will raise exception because name to short + self::expectExceptionMessage('Name to short'); + $entity->save(); + } + + public function testExceptionIfRule(): void + { + $rule = new ValidatorRule('test', ['required']); + $rule->setActivateOnSuccess(['type' => 'dog']); // if type=dog, then check if field "test" is set + + self::expectExceptionMessage('Activation condition already set'); + $rule->setActivateOnFail(['type' => 'dog']); // should not try to set another condition on same rule + } + + public function testComplexRuleset(): void + { + $model = $this->createModel(); + $validator = $this->createValidator($model); + + // everyone should have name set + $rule = new ValidatorRule('name', 'required'); + $validator->addValidatorRule($rule); + + // dogs should have age set + $rule = new ValidatorRule('age', 'required'); + $rule->setActivateOnSuccess(['type' => 'dog']); + $validator->addValidatorRule($rule); + + // dogs should be not older than 20 years + $rule = new ValidatorRule('age', ['max', 20]); + $rule->setActivateOnSuccess(['type' => 'dog']); + $validator->addValidatorRule($rule); + + // others should have name at least 4 chars long + $rule = new ValidatorRule('name', ['lengthMin', 3, 'message' => 'Name to short']); + $rule->setActivateOnFail(['type' => 'dog']); + $validator->addValidatorRule($rule); + + // now testing + $err = $model->createEntity()->setMulti([ + 'type' => 'ball', + ])->validate(); + self::assertSame(['name'], array_keys($err)); // name is required for everyone + + $err = $model->createEntity()->setMulti([ + 'type' => 'dog', + ])->validate(); + self::assertSame(['name', 'age'], array_keys($err)); // name and age is required for dogs + + $err = $model->createEntity()->setMulti([ + 'type' => 'dog', + 'name' => 'AB', + 'age' => 25, + ])->validate(); + self::assertSame(['age'], array_keys($err)); // for dogs age should be no more than 20, but short name is fine + + $err = $model->createEntity()->setMulti([ + 'type' => 'ball', + 'name' => 'AB', + ])->validate(); + self::assertSame(['name'], array_keys($err)); // for others name should be long enough + } + + // exactly the same rules as in previous tests, but defined by using short-hand method + public function testComplexRuleset2(): void + { + $model = $this->createModel(); + $validator = $this->createValidator($model); + + // everyone should have name set + // dogs should have age set and not older than 20 years + // others should have name at least 4 chars long + $validator->if(['type' => 'dog'], [ + 'name' => ['required'], + 'age' => ['required', ['max', 20]], + ], [ + 'name' => ['required', ['lengthMin', 3, 'message' => 'Name to short']], + ]); + + // now testing + $err = $model->createEntity()->setMulti([ + 'type' => 'ball', + ])->validate(); + self::assertSame(['name'], array_keys($err)); // name is required for everyone + + $err = $model->createEntity()->setMulti([ + 'type' => 'dog', + ])->validate(); + self::assertSame(['name', 'age'], array_keys($err)); // name and age is required for dogs + + $err = $model->createEntity()->setMulti([ + 'type' => 'dog', + 'name' => 'AB', + 'age' => 25, + ])->validate(); + self::assertSame(['age'], array_keys($err)); // for dogs age should be no more than 20, but short name is fine + + $err = $model->createEntity()->setMulti([ + 'type' => 'ball', + 'name' => 'AB', + ])->validate(); + self::assertSame(['name'], array_keys($err)); // for others name should be long enough } } From ac38294e0a01fcf7a49d4f7c4ac472b01cfdbbe8 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 15:07:17 +0300 Subject: [PATCH 02/49] add phptype ValidatorCallback --- src/Validator.php | 16 ++++++++++------ src/ValidatorRule.php | 17 ++++++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Validator.php b/src/Validator.php index 7ef7e2d..a40e557 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -13,6 +13,10 @@ * Use https://github.com/vlucas/valitron under the hood. * * $v = new \Atk4\Validate\Validator($model); + * + * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 + * + * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool */ class Validator { @@ -31,8 +35,8 @@ public function __construct(Model $model) /** * Set rules of particular field. * - * @param array, list): bool>> $rules - * @param array|list> $conditions + * @param array> $rules + * @param array|list> $conditions * * @return $this */ @@ -64,7 +68,7 @@ public function addValidatorRule(ValidatorRule $validatorRule): self /** * Set multiple rules. * - * @param array, list): bool>>> $hash array with field name as key and rules as value + * @param array>> $hash array with field name as key and rules as value * * @return $this */ @@ -80,9 +84,9 @@ public function rules(array $hash): self /** * Set conditional rules. * - * @param array|list> $conditions - * @param array, list): bool>>> $then_hash - * @param array, list): bool>>> $else_hash + * @param array|list> $conditions + * @param array>> $then_hash + * @param array>> $else_hash * * @return $this */ diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index cedc0ea..89d0839 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -7,6 +7,13 @@ use Atk4\Data\Exception; use Atk4\Data\Model; +/** + * One validator rule. + * + * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 + * + * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool + */ class ValidatorRule { public const ON_SUCCESS = 'success'; @@ -20,13 +27,13 @@ class ValidatorRule public ?string $activateOn = null; /** - * @var list, list): bool> + * @var list */ private array $rule = []; private ?string $message = null; /** - * @param string|array, list): bool> $rule + * @param string|array $rule */ public function __construct(string $field, $rule) { @@ -92,7 +99,7 @@ public function isActivated(Model $model): bool } /** - * @param array, list): bool> $rule + * @param array $rule */ private function setRule(array $rule): void { @@ -105,7 +112,7 @@ private function setMessage(?string $message = null): void } /** - * @return array, list): bool> + * @return array */ public function getRule(): array { @@ -118,7 +125,7 @@ public function getMessage(): ?string } /** - * @return array, list): bool>> + * @return array> */ public function getValitronRule(): array { From 142e50354eed4674621145f43e62efd50726b2a4 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 16:41:10 +0300 Subject: [PATCH 03/49] set phpstan-type for valitron rules --- src/Validator.php | 16 ++++++++++------ src/ValidatorRule.php | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Validator.php b/src/Validator.php index a40e557..11b251c 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -17,6 +17,10 @@ * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 * * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool + * + * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 + * @phpstan-type ValitronRuleType 'required'|'equals'|'different'|'accepted'|'array'|'numeric'|'integer'|'length'|'lengthBetween'|'lengthMin'|'lengthMax'|'min'|'max'|'between'|'in'|'listContains'|'notIn'|'contains'|'subset'|'containsUnique'|'ip'|'ipv4'|'ipv6'|'email'|'ascii'|'emailDNS'|'url'|'urlActive'|'alpha'|'alphaNum'|'slug'|'regex'|'date'|'dateFormat'|'dateBefore'|'dateAfter'|'boolean'|'creditCard'|'instanceOf'|'requiredWith'|'requiredWithout'|'optional'|'arrayHasKeys' + * @phpstan-type ValitronRule array */ class Validator { @@ -35,8 +39,8 @@ public function __construct(Model $model) /** * Set rules of particular field. * - * @param array> $rules - * @param array|list> $conditions + * @param array $rules + * @param array|list> $conditions * * @return $this */ @@ -68,7 +72,7 @@ public function addValidatorRule(ValidatorRule $validatorRule): self /** * Set multiple rules. * - * @param array>> $hash array with field name as key and rules as value + * @param array> $hash array with field name as key and rules as value * * @return $this */ @@ -84,9 +88,9 @@ public function rules(array $hash): self /** * Set conditional rules. * - * @param array|list> $conditions - * @param array>> $then_hash - * @param array>> $else_hash + * @param array|list> $conditions + * @param array> $then_hash + * @param array> $else_hash * * @return $this */ diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index 89d0839..c9371a9 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -13,6 +13,10 @@ * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 * * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool + * + * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 + * @phpstan-type ValitronRuleType 'required'|'equals'|'different'|'accepted'|'array'|'numeric'|'integer'|'length'|'lengthBetween'|'lengthMin'|'lengthMax'|'min'|'max'|'between'|'in'|'listContains'|'notIn'|'contains'|'subset'|'containsUnique'|'ip'|'ipv4'|'ipv6'|'email'|'ascii'|'emailDNS'|'url'|'urlActive'|'alpha'|'alphaNum'|'slug'|'regex'|'date'|'dateFormat'|'dateBefore'|'dateAfter'|'boolean'|'creditCard'|'instanceOf'|'requiredWith'|'requiredWithout'|'optional'|'arrayHasKeys' + * @phpstan-type ValitronRule array */ class ValidatorRule { @@ -27,17 +31,17 @@ class ValidatorRule public ?string $activateOn = null; /** - * @var list + * @var list */ private array $rule = []; private ?string $message = null; /** - * @param string|array $rule + * @param ValitronRuleType|ValitronRule|ValidatorCallback $rule */ public function __construct(string $field, $rule) { - if (is_string($rule)) { + if (!is_array($rule)) { $rule = [$rule]; } @@ -99,7 +103,7 @@ public function isActivated(Model $model): bool } /** - * @param array $rule + * @param list $rule */ private function setRule(array $rule): void { @@ -112,7 +116,7 @@ private function setMessage(?string $message = null): void } /** - * @return array + * @return list */ public function getRule(): array { @@ -125,7 +129,7 @@ public function getMessage(): ?string } /** - * @return array> + * @return list */ public function getValitronRule(): array { From 94fd3949881f2988d73e51d79cd291409c132f13 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 18:13:32 +0300 Subject: [PATCH 04/49] address review comments --- src/ValidatorRule.php | 4 +- tests/BasicTest.php | 123 ++++++++++++++++++------------------------ 2 files changed, 52 insertions(+), 75 deletions(-) diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index c9371a9..620139e 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -8,9 +8,7 @@ use Atk4\Data\Model; /** - * One validator rule. - * - * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 + * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251. * * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool * diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 4d69bc8..64c5a4e 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -4,6 +4,7 @@ namespace Atk4\Validate\Tests; +use Atk4\Data\Exception; use Atk4\Data\Model; use Atk4\Data\Schema\TestCase; use Atk4\Validate\Tests\Model\Dummy; @@ -101,7 +102,7 @@ public function testCallback1(): void // Age should be odd number $validator->rule('age', [ [ - static function (string $field, $value, array $params, array $data): bool { + static function ($field, $value, $params, $data): bool { return $value % 2 !== 0; }, 'message' => 'Age should be odd', @@ -246,6 +247,7 @@ public function testModelHookValidate(): void ]); // will raise exception because name to short + self::expectException(Exception::class); self::expectExceptionMessage('Name to short'); $entity->save(); } @@ -255,97 +257,74 @@ public function testExceptionIfRule(): void $rule = new ValidatorRule('test', ['required']); $rule->setActivateOnSuccess(['type' => 'dog']); // if type=dog, then check if field "test" is set + self::expectException(Exception::class); self::expectExceptionMessage('Activation condition already set'); $rule->setActivateOnFail(['type' => 'dog']); // should not try to set another condition on same rule } public function testComplexRuleset(): void { - $model = $this->createModel(); - $validator = $this->createValidator($model); + $models = $validators = []; + foreach (['old', 'new'] as $i) { + $models[$i] = $this->createModel(); + $validators[$i] = $this->createValidator($models[$i]); + } + // set rules in old-style + // everyone should have name set + // dogs should have age set and not older than 20 years + // others should have name at least 4 chars long + $validators['old']->if(['type' => 'dog'], [ + 'name' => ['required'], + 'age' => ['required', ['max', 20]], + ], [ + 'name' => ['required', ['lengthMin', 3, 'message' => 'Name to short']], + ]); + + // and set exactly the same rule using new ValidatorRule style // everyone should have name set $rule = new ValidatorRule('name', 'required'); - $validator->addValidatorRule($rule); + $validators['new']->addValidatorRule($rule); // dogs should have age set $rule = new ValidatorRule('age', 'required'); $rule->setActivateOnSuccess(['type' => 'dog']); - $validator->addValidatorRule($rule); + $validators['new']->addValidatorRule($rule); // dogs should be not older than 20 years $rule = new ValidatorRule('age', ['max', 20]); $rule->setActivateOnSuccess(['type' => 'dog']); - $validator->addValidatorRule($rule); + $validators['new']->addValidatorRule($rule); // others should have name at least 4 chars long $rule = new ValidatorRule('name', ['lengthMin', 3, 'message' => 'Name to short']); $rule->setActivateOnFail(['type' => 'dog']); - $validator->addValidatorRule($rule); - - // now testing - $err = $model->createEntity()->setMulti([ - 'type' => 'ball', - ])->validate(); - self::assertSame(['name'], array_keys($err)); // name is required for everyone - - $err = $model->createEntity()->setMulti([ - 'type' => 'dog', - ])->validate(); - self::assertSame(['name', 'age'], array_keys($err)); // name and age is required for dogs - - $err = $model->createEntity()->setMulti([ - 'type' => 'dog', - 'name' => 'AB', - 'age' => 25, - ])->validate(); - self::assertSame(['age'], array_keys($err)); // for dogs age should be no more than 20, but short name is fine - - $err = $model->createEntity()->setMulti([ - 'type' => 'ball', - 'name' => 'AB', - ])->validate(); - self::assertSame(['name'], array_keys($err)); // for others name should be long enough - } - - // exactly the same rules as in previous tests, but defined by using short-hand method - public function testComplexRuleset2(): void - { - $model = $this->createModel(); - $validator = $this->createValidator($model); - - // everyone should have name set - // dogs should have age set and not older than 20 years - // others should have name at least 4 chars long - $validator->if(['type' => 'dog'], [ - 'name' => ['required'], - 'age' => ['required', ['max', 20]], - ], [ - 'name' => ['required', ['lengthMin', 3, 'message' => 'Name to short']], - ]); - - // now testing - $err = $model->createEntity()->setMulti([ - 'type' => 'ball', - ])->validate(); - self::assertSame(['name'], array_keys($err)); // name is required for everyone - - $err = $model->createEntity()->setMulti([ - 'type' => 'dog', - ])->validate(); - self::assertSame(['name', 'age'], array_keys($err)); // name and age is required for dogs - - $err = $model->createEntity()->setMulti([ - 'type' => 'dog', - 'name' => 'AB', - 'age' => 25, - ])->validate(); - self::assertSame(['age'], array_keys($err)); // for dogs age should be no more than 20, but short name is fine - - $err = $model->createEntity()->setMulti([ - 'type' => 'ball', - 'name' => 'AB', - ])->validate(); - self::assertSame(['name'], array_keys($err)); // for others name should be long enough + $validators['new']->addValidatorRule($rule); + + // now testing both + foreach (['old', 'new'] as $i) { + $err = $models[$i]->createEntity()->setMulti([ + 'type' => 'ball', + ])->validate(); + self::assertSame(['name'], array_keys($err)); // name is required for everyone + + $err = $models[$i]->createEntity()->setMulti([ + 'type' => 'dog', + ])->validate(); + self::assertSame(['name', 'age'], array_keys($err)); // name and age is required for dogs + + $err = $models[$i]->createEntity()->setMulti([ + 'type' => 'dog', + 'name' => 'AB', + 'age' => 25, + ])->validate(); + self::assertSame(['age'], array_keys($err)); // for dogs age should be no more than 20, but short name is fine + + $err = $models[$i]->createEntity()->setMulti([ + 'type' => 'ball', + 'name' => 'AB', + ])->validate(); + self::assertSame(['name'], array_keys($err)); // for others name should be long enough + } } } From 627f26ccff14772932a36aaba2e1e165880fa648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sun, 14 Apr 2024 17:20:48 +0200 Subject: [PATCH 05/49] improve doc --- src/Validator.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Validator.php b/src/Validator.php index 11b251c..935790d 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -14,11 +14,10 @@ * * $v = new \Atk4\Validate\Validator($model); * - * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 - * + * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 https://github.com/phpstan/phpstan/issues/10874 * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool * - * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 + * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 https://github.com/phpstan/phpstan/issues/10874 * @phpstan-type ValitronRuleType 'required'|'equals'|'different'|'accepted'|'array'|'numeric'|'integer'|'length'|'lengthBetween'|'lengthMin'|'lengthMax'|'min'|'max'|'between'|'in'|'listContains'|'notIn'|'contains'|'subset'|'containsUnique'|'ip'|'ipv4'|'ipv6'|'email'|'ascii'|'emailDNS'|'url'|'urlActive'|'alpha'|'alphaNum'|'slug'|'regex'|'date'|'dateFormat'|'dateBefore'|'dateAfter'|'boolean'|'creditCard'|'instanceOf'|'requiredWith'|'requiredWithout'|'optional'|'arrayHasKeys' * @phpstan-type ValitronRule array */ From 48ae9aacc3096c50d3fd0605c3c041005f1ee3ca Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 18:57:22 +0300 Subject: [PATCH 06/49] sort validators, rename method to addRule --- src/Validator.php | 11 ++++++----- src/ValidatorRule.php | 4 ++-- tests/BasicTest.php | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Validator.php b/src/Validator.php index 935790d..aab9005 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -15,11 +15,12 @@ * $v = new \Atk4\Validate\Validator($model); * * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 https://github.com/phpstan/phpstan/issues/10874 + * * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool * * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 https://github.com/phpstan/phpstan/issues/10874 - * @phpstan-type ValitronRuleType 'required'|'equals'|'different'|'accepted'|'array'|'numeric'|'integer'|'length'|'lengthBetween'|'lengthMin'|'lengthMax'|'min'|'max'|'between'|'in'|'listContains'|'notIn'|'contains'|'subset'|'containsUnique'|'ip'|'ipv4'|'ipv6'|'email'|'ascii'|'emailDNS'|'url'|'urlActive'|'alpha'|'alphaNum'|'slug'|'regex'|'date'|'dateFormat'|'dateBefore'|'dateAfter'|'boolean'|'creditCard'|'instanceOf'|'requiredWith'|'requiredWithout'|'optional'|'arrayHasKeys' - * @phpstan-type ValitronRule array + * @phpstan-type ValitronRuleType 'accepted'|'alpha'|'alphaNum'|'array'|'arrayHasKeys'|'ascii'|'between'|'boolean'|'contains'|'containsUnique'|'creditCard'|'date'|'dateAfter'|'dateBefore'|'dateFormat'|'different'|'email'|'emailDNS'|'equals'|'in'|'instanceOf'|'integer'|'ip'|'ipv4'|'ipv6'|'length'|'lengthBetween'|'lengthMax'|'lengthMin'|'listContains'|'max'|'min'|'notIn'|'numeric'|'optional'|'regex'|'required'|'requiredWith'|'requiredWithout'|'slug'|'subset'|'url'|'urlActive' + * @phpstan-type ValitronRule array|ValidatorCallback> */ class Validator { @@ -36,7 +37,7 @@ public function __construct(Model $model) } /** - * Set rules of particular field. + * Add rule/rules for given field. * * @param array $rules * @param array|list> $conditions @@ -50,7 +51,7 @@ public function rule(string $field, array $rules, ?string $activateOn = null, ar if ($activateOn !== null) { $validatorRule->setActivateOnResult($activateOn, $conditions); } - $this->addValidatorRule($validatorRule); + $this->addRule($validatorRule); } return $this; @@ -61,7 +62,7 @@ public function rule(string $field, array $rules, ?string $activateOn = null, ar * * @return $this */ - public function addValidatorRule(ValidatorRule $validatorRule): self + public function addRule(ValidatorRule $validatorRule): self { $this->rules[] = $validatorRule; diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index 620139e..671993d 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -13,8 +13,8 @@ * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool * * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 - * @phpstan-type ValitronRuleType 'required'|'equals'|'different'|'accepted'|'array'|'numeric'|'integer'|'length'|'lengthBetween'|'lengthMin'|'lengthMax'|'min'|'max'|'between'|'in'|'listContains'|'notIn'|'contains'|'subset'|'containsUnique'|'ip'|'ipv4'|'ipv6'|'email'|'ascii'|'emailDNS'|'url'|'urlActive'|'alpha'|'alphaNum'|'slug'|'regex'|'date'|'dateFormat'|'dateBefore'|'dateAfter'|'boolean'|'creditCard'|'instanceOf'|'requiredWith'|'requiredWithout'|'optional'|'arrayHasKeys' - * @phpstan-type ValitronRule array + * @phpstan-type ValitronRuleType 'accepted'|'alpha'|'alphaNum'|'array'|'arrayHasKeys'|'ascii'|'between'|'boolean'|'contains'|'containsUnique'|'creditCard'|'date'|'dateAfter'|'dateBefore'|'dateFormat'|'different'|'email'|'emailDNS'|'equals'|'in'|'instanceOf'|'integer'|'ip'|'ipv4'|'ipv6'|'length'|'lengthBetween'|'lengthMax'|'lengthMin'|'listContains'|'max'|'min'|'notIn'|'numeric'|'optional'|'regex'|'required'|'requiredWith'|'requiredWithout'|'slug'|'subset'|'url'|'urlActive' + * @phpstan-type ValitronRule array|ValidatorCallback> */ class ValidatorRule { diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 64c5a4e..470b81d 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -284,22 +284,22 @@ public function testComplexRuleset(): void // and set exactly the same rule using new ValidatorRule style // everyone should have name set $rule = new ValidatorRule('name', 'required'); - $validators['new']->addValidatorRule($rule); + $validators['new']->addRule($rule); // dogs should have age set $rule = new ValidatorRule('age', 'required'); $rule->setActivateOnSuccess(['type' => 'dog']); - $validators['new']->addValidatorRule($rule); + $validators['new']->addRule($rule); // dogs should be not older than 20 years $rule = new ValidatorRule('age', ['max', 20]); $rule->setActivateOnSuccess(['type' => 'dog']); - $validators['new']->addValidatorRule($rule); + $validators['new']->addRule($rule); // others should have name at least 4 chars long $rule = new ValidatorRule('name', ['lengthMin', 3, 'message' => 'Name to short']); $rule->setActivateOnFail(['type' => 'dog']); - $validators['new']->addValidatorRule($rule); + $validators['new']->addRule($rule); // now testing both foreach (['old', 'new'] as $i) { From 96a3eadb2f0fa389d4c9e85e34a8710fc259ce1c Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 19:21:35 +0300 Subject: [PATCH 07/49] add ValidatorCondition typehint and fix it --- src/Validator.php | 7 ++++--- src/ValidatorRule.php | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Validator.php b/src/Validator.php index aab9005..3225800 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -17,6 +17,7 @@ * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251 https://github.com/phpstan/phpstan/issues/10874 * * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool + * @phpstan-type ValidatorCondition array * * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 https://github.com/phpstan/phpstan/issues/10874 * @phpstan-type ValitronRuleType 'accepted'|'alpha'|'alphaNum'|'array'|'arrayHasKeys'|'ascii'|'between'|'boolean'|'contains'|'containsUnique'|'creditCard'|'date'|'dateAfter'|'dateBefore'|'dateFormat'|'different'|'email'|'emailDNS'|'equals'|'in'|'instanceOf'|'integer'|'ip'|'ipv4'|'ipv6'|'length'|'lengthBetween'|'lengthMax'|'lengthMin'|'listContains'|'max'|'min'|'notIn'|'numeric'|'optional'|'regex'|'required'|'requiredWith'|'requiredWithout'|'slug'|'subset'|'url'|'urlActive' @@ -39,8 +40,8 @@ public function __construct(Model $model) /** * Add rule/rules for given field. * - * @param array $rules - * @param array|list> $conditions + * @param array $rules + * @param ValidatorCondition $conditions * * @return $this */ @@ -88,7 +89,7 @@ public function rules(array $hash): self /** * Set conditional rules. * - * @param array|list> $conditions + * @param ValidatorCondition $conditions * @param array> $then_hash * @param array> $else_hash * diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index 671993d..b38e377 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -11,6 +11,7 @@ * https://github.com/vlucas/valitron/blob/v1.4.11/src/Valitron/Validator.php#L1251. * * @phpstan-type ValidatorCallback \Closure(string, mixed, list, list): bool + * @phpstan-type ValidatorCondition array * * https://github.com/vlucas/valitron/blob/master/src/Valitron/Validator.php#L1240 * @phpstan-type ValitronRuleType 'accepted'|'alpha'|'alphaNum'|'array'|'arrayHasKeys'|'ascii'|'between'|'boolean'|'contains'|'containsUnique'|'creditCard'|'date'|'dateAfter'|'dateBefore'|'dateFormat'|'different'|'email'|'emailDNS'|'equals'|'in'|'instanceOf'|'integer'|'ip'|'ipv4'|'ipv6'|'length'|'lengthBetween'|'lengthMax'|'lengthMin'|'listContains'|'max'|'min'|'notIn'|'numeric'|'optional'|'regex'|'required'|'requiredWith'|'requiredWithout'|'slug'|'subset'|'url'|'urlActive' @@ -23,7 +24,7 @@ class ValidatorRule public string $field; /** - * @var array + * @var ValidatorCondition */ public array $activateConditions = []; public ?string $activateOn = null; @@ -55,7 +56,7 @@ public function __construct(string $field, $rule) } /** - * @param array $activationConditions [field_name => value] + * @param ValidatorCondition $activationConditions [field_name => value] */ public function setActivateOnSuccess(array $activationConditions): void { @@ -63,7 +64,7 @@ public function setActivateOnSuccess(array $activationConditions): void } /** - * @param array $activationConditions [field_name => value] + * @param ValidatorCondition $activationConditions [field_name => value] */ public function setActivateOnFail(array $activationConditions): void { @@ -71,7 +72,7 @@ public function setActivateOnFail(array $activationConditions): void } /** - * @param array $activationConditions [field_name => value] + * @param ValidatorCondition $activationConditions [field_name => value] */ public function setActivateOnResult(string $activateOn, array $activationConditions): void { From e57308b2950b4d80fc6f9af94ede456737e62268 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 19:22:40 +0300 Subject: [PATCH 08/49] better user Model compare method --- src/ValidatorRule.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index b38e377..acc3cc4 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -89,11 +89,11 @@ public function isActivated(Model $model): bool $this->activateOn ??= self::ON_SUCCESS; foreach ($this->activateConditions as $conditionField => $conditionValue) { - if ($this->activateOn === self::ON_SUCCESS && $model->get($conditionField) !== $conditionValue) { + if ($this->activateOn === self::ON_SUCCESS && $model->compare($conditionField, $conditionValue) === false) { return false; } - if ($this->activateOn === self::ON_FAIL && $model->get($conditionField) === $conditionValue) { + if ($this->activateOn === self::ON_FAIL && $model->compare($conditionField, $conditionValue) === true) { return false; } } From 5135e37de8d8dd4ef5d0ef83dad0942e55a687d2 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 19:46:31 +0300 Subject: [PATCH 09/49] add tests for complex data type (date) --- tests/BasicTest.php | 51 +++++++++++++++++++++++++++++++++++++++++++ tests/Model/Dummy.php | 1 + 2 files changed, 52 insertions(+) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 470b81d..4f85a4c 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -25,6 +25,7 @@ protected function setUp(): void 'age' => 22, 'type' => 'dog', 'tail_length' => 5, + 'dob' => '2024-01-01', ], ], ]); @@ -327,4 +328,54 @@ public function testComplexRuleset(): void self::assertSame(['name'], array_keys($err)); // for others name should be long enough } } + + /** + * Test complex data type. + */ + public function testComplexDataType(): void + { + $model = $this->createModel(); + $validator = $this->createValidator($model); + + $validator->rule('dob', ['required', ['dateAfter', '2024-01-01']]); + + // date of birth not set + $err = $model->createEntity()->validate(); + self::assertSame(['dob'], array_keys($err)); + + // date of birth is to small + $err = $model->createEntity()->set('dob', new \DateTime('2023-01-01'))->validate(); + self::assertSame(['dob'], array_keys($err)); + + // date of birth is ok + $err = $model->createEntity()->set('dob', new \DateTime('2024-10-01'))->validate(); + self::assertSame([], array_keys($err)); + } + + /** + * Text complex type as condition. + */ + public function testComplexDataTypeCondition(): void + { + $model = $this->createModel(); + $validator = $this->createValidator($model); + + // if date of birth is this date, then type is required + // otherwise name is required + $validator->if(['dob' => new \DateTime('2024-01-01')], [ + 'type' => ['required'], + ], [ + 'name' => ['required'], + ]); + + $err = $model->createEntity()->setMulti([ + 'dob' => new \DateTime('2023-10-10'), + ])->validate(); + self::assertSame(['name'], array_keys($err)); + + $err = $model->createEntity()->setMulti([ + 'dob' => new \DateTime('2024-01-01'), + ])->validate(); + self::assertSame(['type'], array_keys($err)); + } } diff --git a/tests/Model/Dummy.php b/tests/Model/Dummy.php index a07b8b1..adc0314 100644 --- a/tests/Model/Dummy.php +++ b/tests/Model/Dummy.php @@ -19,5 +19,6 @@ protected function init(): void $this->addField('age', ['type' => 'integer']); $this->addField('type', ['required' => true, 'enum' => ['dog', 'ball']]); $this->addField('tail_length', ['type' => 'float']); + $this->addField('dob', ['type' => 'date']); } } From 09cea81f569310532bcc4799d781155b506f0f80 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sun, 14 Apr 2024 19:57:17 +0300 Subject: [PATCH 10/49] test --- tests/BasicTest.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 4f85a4c..9b05d05 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -334,16 +334,21 @@ public function testComplexRuleset(): void */ public function testComplexDataType(): void { + // date of birth not set $model = $this->createModel(); $validator = $this->createValidator($model); - $validator->rule('dob', ['required', ['dateAfter', '2024-01-01']]); + $validator->rule('dob', ['required']); - // date of birth not set $err = $model->createEntity()->validate(); self::assertSame(['dob'], array_keys($err)); // date of birth is to small + $model = $this->createModel(); + $validator = $this->createValidator($model); + + $validator->rule('dob', [['dateAfter', '2024-01-01']]); + $err = $model->createEntity()->set('dob', new \DateTime('2023-01-01'))->validate(); self::assertSame(['dob'], array_keys($err)); From 582c6b999b20597f11eb1a40acf9955ed6ebaf74 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 18:54:36 +0300 Subject: [PATCH 11/49] change test to show how it fails for empty DateTime --- tests/BasicTest.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 9b05d05..7f59504 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -334,21 +334,16 @@ public function testComplexRuleset(): void */ public function testComplexDataType(): void { - // date of birth not set $model = $this->createModel(); $validator = $this->createValidator($model); - $validator->rule('dob', ['required']); + $validator->rule('dob', [['dateAfter', '2024-01-01']]); + // date of birth not set $err = $model->createEntity()->validate(); self::assertSame(['dob'], array_keys($err)); // date of birth is to small - $model = $this->createModel(); - $validator = $this->createValidator($model); - - $validator->rule('dob', [['dateAfter', '2024-01-01']]); - $err = $model->createEntity()->set('dob', new \DateTime('2023-01-01'))->validate(); self::assertSame(['dob'], array_keys($err)); From 521890564811548be9a88d2a78be0e20e865f169 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 19:31:38 +0300 Subject: [PATCH 12/49] show the problem --- tests/BasicTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 7f59504..110d375 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -332,12 +332,12 @@ public function testComplexRuleset(): void /** * Test complex data type. */ - public function testComplexDataType(): void + public function testComplexDataTypeInRule(): void { $model = $this->createModel(); $validator = $this->createValidator($model); - $validator->rule('dob', [['dateAfter', '2024-01-01']]); + $validator->rule('dob', ['required', ['dateAfter', '2024-01-01']]); // date of birth not set $err = $model->createEntity()->validate(); @@ -355,7 +355,7 @@ public function testComplexDataType(): void /** * Text complex type as condition. */ - public function testComplexDataTypeCondition(): void + public function testComplexDataTypeInCondition(): void { $model = $this->createModel(); $validator = $this->createValidator($model); From 2126a958c840a5aa6cd847e62f5b98d16da941be Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 19:46:16 +0300 Subject: [PATCH 13/49] extend Valitron class and fix bugs there --- src/Validator.php | 2 +- src/ValitronValidator.php | 49 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/ValitronValidator.php diff --git a/src/Validator.php b/src/Validator.php index 3225800..0230027 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -116,7 +116,7 @@ public function if(array $conditions, array $then_hash, array $else_hash = []): public function validate(Model $model): array { // initialize Validator, set data - $v = new \Valitron\Validator($model->get()); + $v = new ValitronValidator($model->get()); $rules = []; foreach ($this->rules as $rule) { diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php new file mode 100644 index 0000000..d8730e3 --- /dev/null +++ b/src/ValitronValidator.php @@ -0,0 +1,49 @@ +validateRequired($field, $value, $params)===false) { + return false; + } + + return parent::validateDate($field, $value); + } + + protected function validateDateFormat($field, $value, $params) + { + if ($this->validateRequired($field, $value, $params)===false) { + return false; + } + + return parent::validateDateFormat($field, $value, $params); + } + + protected function validateDateBefore($field, $value, $params) + { + if ($this->validateRequired($field, $value, $params)===false) { + return false; + } + + return parent::validateDateBefore($field, $value, $params); + } + + protected function validateDateAfter($field, $value, $params) + { + if ($this->validateRequired($field, $value, $params)===false) { + return false; + } + + return parent::validateDateAfter($field, $value, $params); + } +} From 4846bfc1eddbb2dd229c77672f6ad58ffaed8f93 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 20:12:58 +0300 Subject: [PATCH 14/49] proper validation --- src/ValitronValidator.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index d8730e3..60b9f91 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -13,7 +13,7 @@ class ValitronValidator extends OriginalValidator { protected function validateDate($field, $value) { - if ($this->validateRequired($field, $value, $params)===false) { + if (is_null($value) || (is_string($value) && trim($value) === '')) { return false; } @@ -22,7 +22,7 @@ protected function validateDate($field, $value) protected function validateDateFormat($field, $value, $params) { - if ($this->validateRequired($field, $value, $params)===false) { + if (is_null($value) || (is_string($value) && trim($value) === '')) { return false; } @@ -31,7 +31,7 @@ protected function validateDateFormat($field, $value, $params) protected function validateDateBefore($field, $value, $params) { - if ($this->validateRequired($field, $value, $params)===false) { + if (is_null($value) || (is_string($value) && trim($value) === '')) { return false; } @@ -40,7 +40,7 @@ protected function validateDateBefore($field, $value, $params) protected function validateDateAfter($field, $value, $params) { - if ($this->validateRequired($field, $value, $params)===false) { + if (is_null($value) || (is_string($value) && trim($value) === '')) { return false; } From b84cc8da783076b8d414113a09517a855bf13649 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 20:29:52 +0300 Subject: [PATCH 15/49] cs fix --- src/ValitronValidator.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index 60b9f91..52440ba 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -13,34 +13,37 @@ class ValitronValidator extends OriginalValidator { protected function validateDate($field, $value) { - if (is_null($value) || (is_string($value) && trim($value) === '')) { + if ($value === null || (is_string($value) && trim($value) === '')) { return false; } return parent::validateDate($field, $value); } + /** @param array $params */ protected function validateDateFormat($field, $value, $params) { - if (is_null($value) || (is_string($value) && trim($value) === '')) { + if ($value === null || (is_string($value) && trim($value) === '')) { return false; } return parent::validateDateFormat($field, $value, $params); } + /** @param array $params */ protected function validateDateBefore($field, $value, $params) { - if (is_null($value) || (is_string($value) && trim($value) === '')) { + if ($value === null || (is_string($value) && trim($value) === '')) { return false; } return parent::validateDateBefore($field, $value, $params); } + /** @param array $params */ protected function validateDateAfter($field, $value, $params) { - if (is_null($value) || (is_string($value) && trim($value) === '')) { + if ($value === null || (is_string($value) && trim($value) === '')) { return false; } From 7db8c3279ce2ecc403fd804246b6a7314fef7f3e Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 20:34:24 +0300 Subject: [PATCH 16/49] add Override attribute --- src/ValitronValidator.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index 52440ba..1717ddc 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -11,6 +11,7 @@ */ class ValitronValidator extends OriginalValidator { + #[\Override] protected function validateDate($field, $value) { if ($value === null || (is_string($value) && trim($value) === '')) { @@ -21,6 +22,7 @@ protected function validateDate($field, $value) } /** @param array $params */ + #[\Override] protected function validateDateFormat($field, $value, $params) { if ($value === null || (is_string($value) && trim($value) === '')) { @@ -31,6 +33,7 @@ protected function validateDateFormat($field, $value, $params) } /** @param array $params */ + #[\Override] protected function validateDateBefore($field, $value, $params) { if ($value === null || (is_string($value) && trim($value) === '')) { @@ -41,6 +44,7 @@ protected function validateDateBefore($field, $value, $params) } /** @param array $params */ + #[\Override] protected function validateDateAfter($field, $value, $params) { if ($value === null || (is_string($value) && trim($value) === '')) { From 8cea4c3e0f64dbcbc64b34740fcf4cc2fd69c505 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 20:56:52 +0300 Subject: [PATCH 17/49] improve tests for coverage and fix dateFormat rule --- src/ValitronValidator.php | 4 ++++ tests/BasicTest.php | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index 1717ddc..ca4329f 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -29,6 +29,10 @@ protected function validateDateFormat($field, $value, $params) return false; } + if ($value instanceof \DateTime) { + return true; + } + return parent::validateDateFormat($field, $value, $params); } diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 110d375..0f1c111 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -337,7 +337,7 @@ public function testComplexDataTypeInRule(): void $model = $this->createModel(); $validator = $this->createValidator($model); - $validator->rule('dob', ['required', ['dateAfter', '2024-01-01']]); + $validator->rule('dob', ['required', 'date', ['dateAfter', '2024-01-01']]); // date of birth not set $err = $model->createEntity()->validate(); @@ -378,4 +378,23 @@ public function testComplexDataTypeInCondition(): void ])->validate(); self::assertSame(['type'], array_keys($err)); } + + /** + * Test DateTime data typefor coverage. + */ + public function testDateTimeForCoverage(): void + { + $model = $this->createModel(); + $validator = $this->createValidator($model); + + $validator->rule('dob', ['required', ['dateFormat', 'DD-MM-YYYY'], ['dateBefore', '20-10-2024']]); + + // date of birth is to big + $err = $model->createEntity()->set('dob', new \DateTime('2025-01-01'))->validate(); + self::assertSame(['dob'], array_keys($err)); + + // date of birth is ok + $err = $model->createEntity()->set('dob', new \DateTime('2024-10-01'))->validate(); + self::assertSame([], array_keys($err)); + } } From c4f38cbf0e583eabd2d75f6605a41b4558e2b0bd Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 21:11:04 +0300 Subject: [PATCH 18/49] better test for dateFormat --- tests/BasicTest.php | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 0f1c111..85dc234 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -384,17 +384,30 @@ public function testComplexDataTypeInCondition(): void */ public function testDateTimeForCoverage(): void { + // test as DateTime field $model = $this->createModel(); $validator = $this->createValidator($model); - - $validator->rule('dob', ['required', ['dateFormat', 'DD-MM-YYYY'], ['dateBefore', '20-10-2024']]); + $validator->rule('dob', ['required', ['dateFormat', 'd-m-Y'], ['dateBefore', '20-10-2024']]); // date of birth is to big - $err = $model->createEntity()->set('dob', new \DateTime('2025-01-01'))->validate(); + $err = $model->createEntity()->set('dob', new \DateTime('2025-10-20'))->validate(); self::assertSame(['dob'], array_keys($err)); // date of birth is ok - $err = $model->createEntity()->set('dob', new \DateTime('2024-10-01'))->validate(); + $err = $model->createEntity()->set('dob', new \DateTime('2024-05-20'))->validate(); + self::assertSame([], array_keys($err)); + + // now test as simple text field + $model = $this->createModel(); + $validator = $this->createValidator($model); + $validator->rule('name', ['required', ['dateFormat', 'd-m-Y'], ['dateBefore', '20-10-2024']]); + + // date of birth is to big + $err = $model->createEntity()->set('name', '20-10-2025')->validate(); + self::assertSame(['name'], array_keys($err)); + + // date of birth is ok + $err = $model->createEntity()->set('name', '20-05-2024')->validate(); self::assertSame([], array_keys($err)); } } From f04f22d097701e1b42fcc6b1e617fa7b10745236 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 21:18:10 +0300 Subject: [PATCH 19/49] add test to improve coverage --- tests/BasicTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 85dc234..ba8bc60 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -402,6 +402,10 @@ public function testDateTimeForCoverage(): void $validator = $this->createValidator($model); $validator->rule('name', ['required', ['dateFormat', 'd-m-Y'], ['dateBefore', '20-10-2024']]); + // date not set + $err = $model->createEntity()->set('name', '20-10-2025')->validate(); + self::assertSame(['name'], array_keys($err)); + // date of birth is to big $err = $model->createEntity()->set('name', '20-10-2025')->validate(); self::assertSame(['name'], array_keys($err)); From f155225c07ed5abddc54a9e6f99ffaad6fd8295f Mon Sep 17 00:00:00 2001 From: DarkSide Date: Mon, 15 Apr 2024 21:19:03 +0300 Subject: [PATCH 20/49] ouch --- tests/BasicTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index ba8bc60..2c02243 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -403,7 +403,7 @@ public function testDateTimeForCoverage(): void $validator->rule('name', ['required', ['dateFormat', 'd-m-Y'], ['dateBefore', '20-10-2024']]); // date not set - $err = $model->createEntity()->set('name', '20-10-2025')->validate(); + $err = $model->createEntity()->validate(); self::assertSame(['name'], array_keys($err)); // date of birth is to big From 68ce5fcf85058d7176f2cd0c5ddb17f280e2be6e Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:40:17 +0300 Subject: [PATCH 21/49] Update src/Validator.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Validator.php b/src/Validator.php index 0230027..214989b 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -120,7 +120,7 @@ public function validate(Model $model): array $rules = []; foreach ($this->rules as $rule) { - if ($rule->isActivated($model) === true) { + if ($rule->isActivated($model)) { $rules[$rule->field][] = $rule->getValitronRule(); } } From 46a028f0316638c6566f8c6285b33fa6bfff8ea1 Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:40:39 +0300 Subject: [PATCH 22/49] Update src/Validator.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Validator.php b/src/Validator.php index 214989b..4695009 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -129,7 +129,7 @@ public function validate(Model $model): array $v->mapFieldsRules($rules); // validate and if errors then format them to fit Atk4 error format - if ($v->validate() === true) { + if ($v->validate()) { return []; } From 73c34858be294782d7da03ba6814652494e6dc3d Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:41:13 +0300 Subject: [PATCH 23/49] Update src/ValidatorRule.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/ValidatorRule.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index acc3cc4..ed060e5 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -21,6 +21,7 @@ class ValidatorRule { public const ON_SUCCESS = 'success'; public const ON_FAIL = 'fail'; + public string $field; /** From 1cac5b999dcbefa04d0312e1def44c64c0721e4b Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:41:39 +0300 Subject: [PATCH 24/49] Update src/ValidatorRule.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/ValidatorRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index ed060e5..321939a 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -90,7 +90,7 @@ public function isActivated(Model $model): bool $this->activateOn ??= self::ON_SUCCESS; foreach ($this->activateConditions as $conditionField => $conditionValue) { - if ($this->activateOn === self::ON_SUCCESS && $model->compare($conditionField, $conditionValue) === false) { + if ($this->activateOn === self::ON_SUCCESS && !$model->compare($conditionField, $conditionValue)) { return false; } From 49594f30b98aded0a71902497b91e8c18b8b15c4 Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:41:50 +0300 Subject: [PATCH 25/49] Update src/ValidatorRule.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/ValidatorRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index 321939a..cd8341e 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -94,7 +94,7 @@ public function isActivated(Model $model): bool return false; } - if ($this->activateOn === self::ON_FAIL && $model->compare($conditionField, $conditionValue) === true) { + if ($this->activateOn === self::ON_FAIL && $model->compare($conditionField, $conditionValue)) { return false; } } From 365d616233e0fe3a0c011772863b69de6e31fa5f Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:42:24 +0300 Subject: [PATCH 26/49] Update tests/BasicTest.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- tests/BasicTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/BasicTest.php b/tests/BasicTest.php index 2c02243..eb8dcc9 100644 --- a/tests/BasicTest.php +++ b/tests/BasicTest.php @@ -329,9 +329,6 @@ public function testComplexRuleset(): void } } - /** - * Test complex data type. - */ public function testComplexDataTypeInRule(): void { $model = $this->createModel(); From 8585e19056fca7fd9b8d53ca1c2778a35184cda6 Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:42:40 +0300 Subject: [PATCH 27/49] Update src/ValitronValidator.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/ValitronValidator.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index ca4329f..b718156 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -21,7 +21,9 @@ protected function validateDate($field, $value) return parent::validateDate($field, $value); } - /** @param array $params */ + /** + * @param array $params + */ #[\Override] protected function validateDateFormat($field, $value, $params) { From ce6c3fa9e216eacc490769ac54b2b1a582a9f7d7 Mon Sep 17 00:00:00 2001 From: Imants Horsts Date: Thu, 18 Apr 2024 13:42:58 +0300 Subject: [PATCH 28/49] Update src/ValitronValidator.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- src/ValitronValidator.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index b718156..f042e84 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -6,9 +6,6 @@ use Valitron\Validator as OriginalValidator; -/** - * Valitron Validation Class with required fixes. - */ class ValitronValidator extends OriginalValidator { #[\Override] From fc779f54431a5be99deb6a065fa1e69b9e53c1a3 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Thu, 18 Apr 2024 13:53:33 +0300 Subject: [PATCH 29/49] address review --- src/Validator.php | 8 ++++---- src/ValidatorRule.php | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Validator.php b/src/Validator.php index 4695009..6b8839c 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -116,7 +116,7 @@ public function if(array $conditions, array $then_hash, array $else_hash = []): public function validate(Model $model): array { // initialize Validator, set data - $v = new ValitronValidator($model->get()); + $validator = new ValitronValidator($model->get()); $rules = []; foreach ($this->rules as $rule) { @@ -126,15 +126,15 @@ public function validate(Model $model): array } // set up Valitron rules - $v->mapFieldsRules($rules); + $validator->mapFieldsRules($rules); // validate and if errors then format them to fit Atk4 error format - if ($v->validate()) { + if ($validator->validate()) { return []; } $errors = []; - foreach ($v->errors() as $key => $e) { + foreach ($validator->errors() as $key => $e) { if (!isset($errors[$key])) { $errors[$key] = array_pop($e); } diff --git a/src/ValidatorRule.php b/src/ValidatorRule.php index cd8341e..ae82852 100644 --- a/src/ValidatorRule.php +++ b/src/ValidatorRule.php @@ -33,8 +33,8 @@ class ValidatorRule /** * @var list */ - private array $rule = []; - private ?string $message = null; + private array $rule; + private ?string $message; /** * @param ValitronRuleType|ValitronRule|ValidatorCallback $rule From fbb007fb981a696b4407bd14db39d786518e296c Mon Sep 17 00:00:00 2001 From: DarkSide Date: Thu, 18 Apr 2024 16:47:31 +0300 Subject: [PATCH 30/49] start adding tests for fixed valitron validator --- tests/ValitronValidatorTest.php | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/ValitronValidatorTest.php diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php new file mode 100644 index 0000000..bda9ee2 --- /dev/null +++ b/tests/ValitronValidatorTest.php @@ -0,0 +1,61 @@ + '2024-10-20', + 'f_bad_string' => 'bad-date', + 'f_null' => null, + 'f_empty_string' => '', + 'f_datetime' => new \Datetime('2024-10-20'), + ]; + $rules = [ + 'f_good_string' => 'date', + 'f_bad_string' => 'date', + 'f_null' => 'date', + 'f_empty_string' => 'date', + 'f_datetime' => 'date', + ]; + + $v = $this->createOriginalValidator($data); + $v->mapFieldsRules($rules); + $ok = $v->validate(); + self::assertFalse($ok); + self::assertSame(['f_bad_string'], array_keys($v->errors())); + //var_dump($v->errors()); + + $v = $this->createFixedValidator($data); + $v->mapFieldsRules($rules); + $ok = $v->validate(); + self::assertFalse($ok); + self::assertSame(['f_bad_string'], array_keys($v->errors())); + + } + +} From 33dd6ada2d32c2d42ae9d567cdacf33cf07841b6 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Thu, 18 Apr 2024 17:50:10 +0300 Subject: [PATCH 31/49] tests --- tests/ValitronValidatorTest.php | 63 ++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index bda9ee2..61a01a6 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -6,6 +6,7 @@ use Atk4\Data\Schema\TestCase; use Atk4\Validate\ValitronValidator as FixedValidator; +use TypeError; use Valitron\Validator as OriginalValidator; class ValitronValidatorTest extends TestCase @@ -16,14 +17,18 @@ protected function setUp(): void parent::setUp(); } - protected function createOriginalValidator(array $data = [], array $fields = []): OriginalValidator + protected function createOriginalValidator(array $data = [], array $rules = []): OriginalValidator { - return new OriginalValidator($data, $fields); + $v = new OriginalValidator($data); + $v->mapFieldsRules($rules); + return $v; } - protected function createFixedValidator(array $data = [], array $fields = []): FixedValidator + protected function createFixedValidator(array $data = [], array $rules = []): FixedValidator { - return new FixedValidator($data, $fields); + $v = new FixedValidator($data); + $v->mapFieldsRules($rules); + return $v; } public function testDate(): void @@ -32,30 +37,56 @@ public function testDate(): void 'f_good_string' => '2024-10-20', 'f_bad_string' => 'bad-date', 'f_null' => null, - 'f_empty_string' => '', + 'f_empty' => '', 'f_datetime' => new \Datetime('2024-10-20'), ]; $rules = [ - 'f_good_string' => 'date', - 'f_bad_string' => 'date', - 'f_null' => 'date', - 'f_empty_string' => 'date', - 'f_datetime' => 'date', + 'f_good_string' => ['date'], + 'f_bad_string' => ['date'], + 'f_null' => ['date'], + 'f_empty' => ['date'], + 'f_datetime' => ['date'], ]; - $v = $this->createOriginalValidator($data); - $v->mapFieldsRules($rules); + $v = $this->createOriginalValidator($data, $rules); $ok = $v->validate(); self::assertFalse($ok); self::assertSame(['f_bad_string'], array_keys($v->errors())); - //var_dump($v->errors()); - $v = $this->createFixedValidator($data); - $v->mapFieldsRules($rules); + $v = $this->createFixedValidator($data, $rules); $ok = $v->validate(); self::assertFalse($ok); self::assertSame(['f_bad_string'], array_keys($v->errors())); - } + public function testDateFormat(): void + { + $data = [ + 'f_good_string' => '20-10-2024', + 'f_bad_string' => 'bad-date', + 'f_null' => null, + 'f_empty' => '', + 'f_datetime' => new \Datetime('2024-10-20'), + ]; + $rules = [ + 'f_good_string' => [['dateFormat', 'd-m-Y']], + 'f_bad_string' => [['dateFormat', 'd-m-Y']], + 'f_null' => [['dateFormat', 'd-m-Y']], + 'f_empty' => [['dateFormat', 'd-m-Y']], + 'f_datetime' => [['dateFormat', 'd-m-Y']], + ]; + + $v = $this->createOriginalValidator($data, $rules); + // There should not be exception, but original class throws + // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given + self::expectException(TypeError::class); + $ok = $v->validate(); + self::assertFalse($ok); + self::assertSame(['f_bad_string'], array_keys($v->errors())); + + $v = $this->createFixedValidator($data, $rules); + $ok = $v->validate(); + self::assertFalse($ok); + self::assertSame(['f_bad_string'], array_keys($v->errors())); + } } From ee3ef0a7b0ec3d8f660e638a0ee05b27df3aeeeb Mon Sep 17 00:00:00 2001 From: DarkSide Date: Thu, 18 Apr 2024 18:19:21 +0300 Subject: [PATCH 32/49] test --- tests/ValitronValidatorTest.php | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 61a01a6..0238acc 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -31,6 +31,16 @@ protected function createFixedValidator(array $data = [], array $rules = []): Fi return $v; } + public function testDate2(): void + { + $v = $this->createOriginalValidator(['d' => null], ['d' => ['required', 'date']]); + $v->validate(); + var_dump($v->errors()); + + + } + + /* public function testDate(): void { $data = [ @@ -89,4 +99,34 @@ public function testDateFormat(): void self::assertFalse($ok); self::assertSame(['f_bad_string'], array_keys($v->errors())); } + + public function testDateBefore(): void + { + $data = [ + 'f_good_string' => '2024-10-20', + 'f_bad_string' => 'bad-date', + 'f_null' => null, + 'f_empty' => '', + 'f_datetime' => new \Datetime('2024-10-20'), + ]; + $rules = [ + 'f_good_string' => [['dateBefore', '2024-10-21']], + 'f_bad_string' => [['dateBefore', '2024-10-21']], + 'f_null' => [['dateBefore', '2024-10-21']], + 'f_empty' => [['dateBefore', '2024-10-21']], + 'f_datetime' => [['dateBefore', '2024-10-21']], + ]; + + $v = $this->createOriginalValidator($data, $rules); + $ok = $v->validate(); +var_dump($v->errors()); + self::assertFalse($ok); + self::assertSame(['f_bad_string'], array_keys($v->errors())); + + $v = $this->createFixedValidator($data, $rules); + $ok = $v->validate(); + self::assertFalse($ok); + self::assertSame(['f_bad_string'], array_keys($v->errors())); + } + */ } From d4eadd798a0ab915894e6abd133d35424a43253c Mon Sep 17 00:00:00 2001 From: DarkSide Date: Thu, 18 Apr 2024 19:10:35 +0300 Subject: [PATCH 33/49] simplify tests --- src/ValitronValidator.php | 16 ++++- tests/ValitronValidatorTest.php | 124 ++++++++++++++------------------ 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index f042e84..f131934 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -35,7 +35,9 @@ protected function validateDateFormat($field, $value, $params) return parent::validateDateFormat($field, $value, $params); } - /** @param array $params */ + /** + * @param array $params + */ #[\Override] protected function validateDateBefore($field, $value, $params) { @@ -43,10 +45,16 @@ protected function validateDateBefore($field, $value, $params) return false; } + if (!isset($params[0]) || $params[0] === null || (is_string($params[0]) && trim($params[0]) === '')) { + return false; + } + return parent::validateDateBefore($field, $value, $params); } - /** @param array $params */ + /** + * @param array $params + */ #[\Override] protected function validateDateAfter($field, $value, $params) { @@ -54,6 +62,10 @@ protected function validateDateAfter($field, $value, $params) return false; } + if (!isset($params[0]) || $params[0] === null || (is_string($params[0]) && trim($params[0]) === '')) { + return false; + } + return parent::validateDateAfter($field, $value, $params); } } diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 0238acc..dea7868 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -31,102 +31,88 @@ protected function createFixedValidator(array $data = [], array $rules = []): Fi return $v; } - public function testDate2(): void + public function testDate(): void { - $v = $this->createOriginalValidator(['d' => null], ['d' => ['required', 'date']]); - $v->validate(); - var_dump($v->errors()); + $data = ['d' => null]; + $rules = ['d' => ['required', 'date']]; + $v = $this->createOriginalValidator($data, $rules); + // this throws depreciation notice starting PHP 8.1 + // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? + + $v = $this->createFixedValidator($data, $rules); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); } - /* - public function testDate(): void + public function testDateFormat(): void { - $data = [ - 'f_good_string' => '2024-10-20', - 'f_bad_string' => 'bad-date', - 'f_null' => null, - 'f_empty' => '', - 'f_datetime' => new \Datetime('2024-10-20'), - ]; - $rules = [ - 'f_good_string' => ['date'], - 'f_bad_string' => ['date'], - 'f_null' => ['date'], - 'f_empty' => ['date'], - 'f_datetime' => ['date'], - ]; + $data = ['d' => null]; + $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; $v = $this->createOriginalValidator($data, $rules); - $ok = $v->validate(); - self::assertFalse($ok); - self::assertSame(['f_bad_string'], array_keys($v->errors())); + + // this throws depreciation notice starting PHP 8.1 + // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated + $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); - $ok = $v->validate(); - self::assertFalse($ok); - self::assertSame(['f_bad_string'], array_keys($v->errors())); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); } - public function testDateFormat(): void + public function testDateFormat2(): void { - $data = [ - 'f_good_string' => '20-10-2024', - 'f_bad_string' => 'bad-date', - 'f_null' => null, - 'f_empty' => '', - 'f_datetime' => new \Datetime('2024-10-20'), - ]; - $rules = [ - 'f_good_string' => [['dateFormat', 'd-m-Y']], - 'f_bad_string' => [['dateFormat', 'd-m-Y']], - 'f_null' => [['dateFormat', 'd-m-Y']], - 'f_empty' => [['dateFormat', 'd-m-Y']], - 'f_datetime' => [['dateFormat', 'd-m-Y']], - ]; + $data = ['d' => new \Datetime()]; + $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; $v = $this->createOriginalValidator($data, $rules); + // There should not be exception, but original class throws // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(TypeError::class); - $ok = $v->validate(); - self::assertFalse($ok); - self::assertSame(['f_bad_string'], array_keys($v->errors())); + $v->validate(); $v = $this->createFixedValidator($data, $rules); - $ok = $v->validate(); - self::assertFalse($ok); - self::assertSame(['f_bad_string'], array_keys($v->errors())); + self::assertTrue($v->validate()); + self::assertSame([], array_keys($v->errors())); } public function testDateBefore(): void { - $data = [ - 'f_good_string' => '2024-10-20', - 'f_bad_string' => 'bad-date', - 'f_null' => null, - 'f_empty' => '', - 'f_datetime' => new \Datetime('2024-10-20'), - ]; - $rules = [ - 'f_good_string' => [['dateBefore', '2024-10-21']], - 'f_bad_string' => [['dateBefore', '2024-10-21']], - 'f_null' => [['dateBefore', '2024-10-21']], - 'f_empty' => [['dateBefore', '2024-10-21']], - 'f_datetime' => [['dateBefore', '2024-10-21']], - ]; + $data = ['d' => null]; + $rules = ['d' => ['required', ['dateBefore', '2029-12-31']]]; + + $v = $this->createOriginalValidator($data, $rules); + + // this throws depreciation notice starting PHP 8.1 + // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? + + $v = $this->createFixedValidator($data, $rules); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); + } + + public function testDateAfter(): void + { + $data = ['d' => null]; + $rules = ['d' => ['required', ['dateAfter', '2023-12-31']]]; $v = $this->createOriginalValidator($data, $rules); - $ok = $v->validate(); -var_dump($v->errors()); - self::assertFalse($ok); - self::assertSame(['f_bad_string'], array_keys($v->errors())); + + // this throws depreciation notice starting PHP 8.1 + // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); - $ok = $v->validate(); - self::assertFalse($ok); - self::assertSame(['f_bad_string'], array_keys($v->errors())); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); } - */ } From f592bb39f4a406b37a261b4d0fd0254d81166379 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Thu, 18 Apr 2024 19:18:24 +0300 Subject: [PATCH 34/49] cs fixes --- src/ValitronValidator.php | 4 ++-- tests/ValitronValidatorTest.php | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/ValitronValidator.php b/src/ValitronValidator.php index f131934..3dd20ab 100644 --- a/src/ValitronValidator.php +++ b/src/ValitronValidator.php @@ -45,7 +45,7 @@ protected function validateDateBefore($field, $value, $params) return false; } - if (!isset($params[0]) || $params[0] === null || (is_string($params[0]) && trim($params[0]) === '')) { + if (!isset($params[0]) || (is_string($params[0]) && trim($params[0]) === '')) { return false; } @@ -62,7 +62,7 @@ protected function validateDateAfter($field, $value, $params) return false; } - if (!isset($params[0]) || $params[0] === null || (is_string($params[0]) && trim($params[0]) === '')) { + if (!isset($params[0]) || (is_string($params[0]) && trim($params[0]) === '')) { return false; } diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index dea7868..0197671 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -17,17 +17,27 @@ protected function setUp(): void parent::setUp(); } - protected function createOriginalValidator(array $data = [], array $rules = []): OriginalValidator + /** + * @param array $data + * @param array $rules + */ + protected function createOriginalValidator(array $data, array $rules): OriginalValidator { $v = new OriginalValidator($data); $v->mapFieldsRules($rules); + return $v; } - protected function createFixedValidator(array $data = [], array $rules = []): FixedValidator + /** + * @param array $data + * @param array $rules + */ + protected function createFixedValidator(array $data, array $rules): FixedValidator { $v = new FixedValidator($data); $v->mapFieldsRules($rules); + return $v; } @@ -67,14 +77,14 @@ public function testDateFormat(): void public function testDateFormat2(): void { - $data = ['d' => new \Datetime()]; + $data = ['d' => new \DateTime()]; $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; $v = $this->createOriginalValidator($data, $rules); // There should not be exception, but original class throws // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given - self::expectException(TypeError::class); + self::expectException(\TypeError::class); $v->validate(); $v = $this->createFixedValidator($data, $rules); From 64b609c6c5162fa1f883ec82cae3b01c3f8f29ec Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 20:06:39 +0300 Subject: [PATCH 35/49] test --- tests/DepTest.php | 27 +++++++++++++++++++++++++++ tests/ValitronValidatorTest.php | 2 ++ 2 files changed, 29 insertions(+) create mode 100644 tests/DepTest.php diff --git a/tests/DepTest.php b/tests/DepTest.php new file mode 100644 index 0000000..4c5fb0f --- /dev/null +++ b/tests/DepTest.php @@ -0,0 +1,27 @@ +validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); From 2ff9e0e4d82d4cbdcbb8088212e1fa30c9dd7b58 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 20:15:43 +0300 Subject: [PATCH 36/49] test --- tests/DepTest.php | 8 ++++++++ tests/ValitronValidatorTest.php | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/DepTest.php b/tests/DepTest.php index 4c5fb0f..2516af7 100644 --- a/tests/DepTest.php +++ b/tests/DepTest.php @@ -24,4 +24,12 @@ public function testB(): void self::expectException(\TypeError::class); $a = date_parse_from_format('Y-m-d', $_ENV['foo'] ?? null); } + + public function testC(): void + { + // this throws depreciation notice starting PHP 8.1 + // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated + self::expectException(\TypeError::class); + $a = date_parse_from_format('Y-m-d', $_ENV['foo'] ?? new \DateTime()); + } } diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index cc02a31..cba8b20 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -50,7 +50,7 @@ public function testDate(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - self::expectUserDeprecationMessage('Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); + //self::expectUserDeprecationMessage('Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); // or use expectUserDeprecationMessageMatches(regex) $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? @@ -86,6 +86,7 @@ public function testDateFormat2(): void // There should not be exception, but original class throws // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given + //self::expectException(\Exception::class); self::expectException(\TypeError::class); $v->validate(); From 65318ba2427bf9a89c1ce8c3bd2e88f8dfd94d4c Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 20:28:53 +0300 Subject: [PATCH 37/49] test --- tests/DepTest.php | 35 --------------------------------- tests/ValitronValidatorTest.php | 4 ++++ 2 files changed, 4 insertions(+), 35 deletions(-) delete mode 100644 tests/DepTest.php diff --git a/tests/DepTest.php b/tests/DepTest.php deleted file mode 100644 index 2516af7..0000000 --- a/tests/DepTest.php +++ /dev/null @@ -1,35 +0,0 @@ -validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); @@ -69,6 +70,7 @@ public function testDateFormat(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated + self::expectException(\TypeError::class); $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); @@ -104,6 +106,7 @@ public function testDateBefore(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + self::expectException(\TypeError::class); $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); @@ -121,6 +124,7 @@ public function testDateAfter(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + self::expectException(\TypeError::class); $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? $v = $this->createFixedValidator($data, $rules); From 624f63dc5d69b7dfaa99b706d96b5fea8396a69b Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 21:37:11 +0300 Subject: [PATCH 38/49] catch warnings --- tests/ValitronValidatorTest.php | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 279e961..dcf907d 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -49,11 +49,16 @@ public function testDate(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - //self::expectUserDeprecationMessage('Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); - // or use expectUserDeprecationMessageMatches(regex) - self::expectException(\TypeError::class); - $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? + set_error_handler( + static function ( $errno, $errstr ) { + restore_error_handler(); + throw new \Exception( $errstr, $errno ); + }, + E_ALL + ); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -61,6 +66,7 @@ public function testDate(): void self::assertSame(2, count($v->errors()['d'])); } + /* public function testDateFormat(): void { $data = ['d' => null]; @@ -71,7 +77,8 @@ public function testDateFormat(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated self::expectException(\TypeError::class); - $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? + + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -90,7 +97,8 @@ public function testDateFormat2(): void // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given //self::expectException(\Exception::class); self::expectException(\TypeError::class); - $v->validate(); + + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertTrue($v->validate()); @@ -107,7 +115,8 @@ public function testDateBefore(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated self::expectException(\TypeError::class); - $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? + + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -125,11 +134,13 @@ public function testDateAfter(): void // this throws depreciation notice starting PHP 8.1 // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated self::expectException(\TypeError::class); - $v->validate(); // @todo why validate fail with assert(isset($trace[1]['file'])) ??? + + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); self::assertSame(['d'], array_keys($v->errors())); self::assertSame(2, count($v->errors()['d'])); } + */ } From ed288c6ac736b924adda3651ed06255b7721dd8f Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 21:43:29 +0300 Subject: [PATCH 39/49] test --- tests/ValitronValidatorTest.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index dcf907d..d2fd7cb 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -41,14 +41,8 @@ protected function createFixedValidator(array $data, array $rules): FixedValidat return $v; } - public function testDate(): void + private static function catchWarningsAsExceptions(): void { - $data = ['d' => null]; - $rules = ['d' => ['required', 'date']]; - - $v = $this->createOriginalValidator($data, $rules); - - // this throws depreciation notice starting PHP 8.1 set_error_handler( static function ( $errno, $errstr ) { restore_error_handler(); @@ -56,6 +50,17 @@ static function ( $errno, $errstr ) { }, E_ALL ); + } + + public function testDate(): void + { + $data = ['d' => null]; + $rules = ['d' => ['required', 'date']]; + + $v = $this->createOriginalValidator($data, $rules); + + // this throws depreciation notice starting PHP 8.1 + self::catchWarningsAsExceptions(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 From d559369d4d7e80987302dc374eca993ff6804510 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 21:52:21 +0300 Subject: [PATCH 40/49] test --- tests/ValitronValidatorTest.php | 52 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index d2fd7cb..a9a2c6f 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -41,14 +41,14 @@ protected function createFixedValidator(array $data, array $rules): FixedValidat return $v; } - private static function catchWarningsAsExceptions(): void + private function throwAsExceptions(int $error_levels = E_ALL): void { set_error_handler( - static function ( $errno, $errstr ) { + static function ($errno, $errstr) { restore_error_handler(); - throw new \Exception( $errstr, $errno ); + throw new \Exception($errstr, $errno); }, - E_ALL + $error_levels ); } @@ -60,10 +60,12 @@ public function testDate(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - self::catchWarningsAsExceptions(); - $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->throwAsExceptions(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + } $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -71,7 +73,6 @@ public function testDate(): void self::assertSame(2, count($v->errors()['d'])); } - /* public function testDateFormat(): void { $data = ['d' => null]; @@ -80,10 +81,12 @@ public function testDateFormat(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated - self::expectException(\TypeError::class); - - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->throwAsExceptions(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + } $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -100,9 +103,7 @@ public function testDateFormat2(): void // There should not be exception, but original class throws // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given - //self::expectException(\Exception::class); self::expectException(\TypeError::class); - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); @@ -118,10 +119,12 @@ public function testDateBefore(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - self::expectException(\TypeError::class); - - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->throwAsExceptions(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + } $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -137,15 +140,16 @@ public function testDateAfter(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - self::expectException(\TypeError::class); - - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + $this->throwAsExceptions(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + } $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); self::assertSame(['d'], array_keys($v->errors())); self::assertSame(2, count($v->errors()['d'])); } - */ } From ddc468e307b93c014a0456ab591b2864345959a4 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 22:05:09 +0300 Subject: [PATCH 41/49] test --- tests/ValitronValidatorTest.php | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index a9a2c6f..c7dea15 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -41,11 +41,12 @@ protected function createFixedValidator(array $data, array $rules): FixedValidat return $v; } - private function throwAsExceptions(int $error_levels = E_ALL): void + private function throwAsExceptions(int $error_levels = \E_ALL): void { set_error_handler( static function ($errno, $errstr) { restore_error_handler(); + throw new \Exception($errstr, $errno); }, $error_levels @@ -60,12 +61,12 @@ public function testDate(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { $this->throwAsExceptions(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 } + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -81,12 +82,12 @@ public function testDateFormat(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { $this->throwAsExceptions(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 } + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -101,9 +102,15 @@ public function testDateFormat2(): void $v = $this->createOriginalValidator($data, $rules); - // There should not be exception, but original class throws - // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given - self::expectException(\TypeError::class); + // this throws warning in PHP 7.4 and TypeError in 8.x + if (version_compare(\PHP_VERSION, '8.0.0', '<')) { + $this->throwAsExceptions(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*expects parameter 2 to be string, object given.*/'); // Warning: date_parse_from_format() expects parameter 2 to be string, object given + } else { + // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given + self::expectException(\TypeError::class); + } $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); @@ -119,12 +126,12 @@ public function testDateBefore(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { $this->throwAsExceptions(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 } + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -140,12 +147,12 @@ public function testDateAfter(): void $v = $this->createOriginalValidator($data, $rules); // this throws depreciation notice starting PHP 8.1 - if (version_compare(PHP_VERSION, '8.1.0', '>=')) { + if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { $this->throwAsExceptions(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 } + $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); From d51a9414aac80b96bc03dd9bd17e26520a636b89 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 22:10:14 +0300 Subject: [PATCH 42/49] remove comments --- tests/ValitronValidatorTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index c7dea15..60ac89f 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -66,7 +66,7 @@ public function testDate(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + $v->validate(); $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -87,7 +87,7 @@ public function testDateFormat(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated } - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + $v->validate(); $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -111,7 +111,7 @@ public function testDateFormat2(): void // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(\TypeError::class); } - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + $v->validate(); $v = $this->createFixedValidator($data, $rules); self::assertTrue($v->validate()); @@ -131,7 +131,7 @@ public function testDateBefore(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + $v->validate(); $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); @@ -152,7 +152,7 @@ public function testDateAfter(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); // @todo PHPUnit bug: https://github.com/sebastianbergmann/phpunit/pull/5822 + $v->validate(); $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); From 2573e6422b40ad93ecc455459407ec8ef65fe029 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 22:31:28 +0300 Subject: [PATCH 43/49] * reorder tests to put expected exceptions last * improve tests coverage --- tests/ValitronValidatorTest.php | 102 +++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 33 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 60ac89f..ecf5a2b 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -11,12 +11,6 @@ class ValitronValidatorTest extends TestCase { - #[\Override] - protected function setUp(): void - { - parent::setUp(); - } - /** * @param array $data * @param array $rules @@ -41,7 +35,7 @@ protected function createFixedValidator(array $data, array $rules): FixedValidat return $v; } - private function throwAsExceptions(int $error_levels = \E_ALL): void + private function throwAsException(int $error_levels = \E_ALL): void { set_error_handler( static function ($errno, $errstr) { @@ -55,56 +49,60 @@ static function ($errno, $errstr) { public function testDate(): void { + // date in data field is null $data = ['d' => null]; $rules = ['d' => ['required', 'date']]; - $v = $this->createOriginalValidator($data, $rules); + $v = $this->createFixedValidator($data, $rules); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); // this throws depreciation notice starting PHP 8.1 + $v = $this->createOriginalValidator($data, $rules); if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsExceptions(); + $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } $v->validate(); - - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); } public function testDateFormat(): void { + // date in data field is null $data = ['d' => null]; $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; - $v = $this->createOriginalValidator($data, $rules); + $v = $this->createFixedValidator($data, $rules); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); // this throws depreciation notice starting PHP 8.1 + $v = $this->createOriginalValidator($data, $rules); if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsExceptions(); + $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated } $v->validate(); - - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); } public function testDateFormat2(): void { + // date in data field is DateTime object $data = ['d' => new \DateTime()]; $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; - $v = $this->createOriginalValidator($data, $rules); + $v = $this->createFixedValidator($data, $rules); + self::assertTrue($v->validate()); + self::assertSame([], array_keys($v->errors())); // this throws warning in PHP 7.4 and TypeError in 8.x + $v = $this->createOriginalValidator($data, $rules); if (version_compare(\PHP_VERSION, '8.0.0', '<')) { - $this->throwAsExceptions(); + $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*expects parameter 2 to be string, object given.*/'); // Warning: date_parse_from_format() expects parameter 2 to be string, object given } else { @@ -112,51 +110,89 @@ public function testDateFormat2(): void self::expectException(\TypeError::class); } $v->validate(); - - $v = $this->createFixedValidator($data, $rules); - self::assertTrue($v->validate()); - self::assertSame([], array_keys($v->errors())); } public function testDateBefore(): void { + // date in data field is null $data = ['d' => null]; $rules = ['d' => ['required', ['dateBefore', '2029-12-31']]]; - $v = $this->createOriginalValidator($data, $rules); + $v = $this->createFixedValidator($data, $rules); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); // this throws depreciation notice starting PHP 8.1 + $v = $this->createOriginalValidator($data, $rules); if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsExceptions(); + $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } $v->validate(); + } + + public function testDateBefore2(): void + { + // date in condition is null + $data = ['d' => '2024-10-20']; + $rules = ['d' => ['required', ['dateBefore', null]]]; $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); + self::assertSame(1, count($v->errors()['d'])); + + // this throws depreciation notice starting PHP 8.1 + $v = $this->createOriginalValidator($data, $rules); + if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { + $this->throwAsException(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + } + $v->validate(); } public function testDateAfter(): void { + // date in data field is null $data = ['d' => null]; $rules = ['d' => ['required', ['dateAfter', '2023-12-31']]]; - $v = $this->createOriginalValidator($data, $rules); + $v = $this->createFixedValidator($data, $rules); + self::assertFalse($v->validate()); + self::assertSame(['d'], array_keys($v->errors())); + self::assertSame(2, count($v->errors()['d'])); // this throws depreciation notice starting PHP 8.1 + $v = $this->createOriginalValidator($data, $rules); if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsExceptions(); + $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } $v->validate(); + } + + public function testDateAfter2(): void + { + // date in condition is null + $data = ['d' => '2024-10-20']; + $rules = ['d' => ['required', ['dateAfter', null]]]; $v = $this->createFixedValidator($data, $rules); self::assertFalse($v->validate()); self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); + self::assertSame(1, count($v->errors()['d'])); + + // this throws depreciation notice starting PHP 8.1 + $v = $this->createOriginalValidator($data, $rules); + if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { + $this->throwAsException(); + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + } + $v->validate(); } } From cfd2a66820a39725769e9e72be1f5a029fb125a2 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 22:40:53 +0300 Subject: [PATCH 44/49] we do not create coverage report with PHP 7.4 --- tests/ValitronValidatorTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index ecf5a2b..ef0b859 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -102,9 +102,11 @@ public function testDateFormat2(): void // this throws warning in PHP 7.4 and TypeError in 8.x $v = $this->createOriginalValidator($data, $rules); if (version_compare(\PHP_VERSION, '8.0.0', '<')) { + // @codeCoverageIgnoreStart $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*expects parameter 2 to be string, object given.*/'); // Warning: date_parse_from_format() expects parameter 2 to be string, object given + // @codeCoverageIgnoreEnd } else { // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(\TypeError::class); From 2fbcf7adf7af71dcef62a5dafd2bcac031abe4ef Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 22:42:51 +0300 Subject: [PATCH 45/49] cs fix --- tests/ValitronValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index ef0b859..45e98f1 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -106,7 +106,7 @@ public function testDateFormat2(): void $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*expects parameter 2 to be string, object given.*/'); // Warning: date_parse_from_format() expects parameter 2 to be string, object given - // @codeCoverageIgnoreEnd + // @codeCoverageIgnoreEnd } else { // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(\TypeError::class); From 85e88c215fe2fde141e8bfebf3bcdf87d9e8dd3c Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 23:05:06 +0300 Subject: [PATCH 46/49] test --- tests/ValitronValidatorTest.php | 73 +++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 45e98f1..4f424f6 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -17,10 +17,10 @@ class ValitronValidatorTest extends TestCase */ protected function createOriginalValidator(array $data, array $rules): OriginalValidator { - $v = new OriginalValidator($data); - $v->mapFieldsRules($rules); + $validator = new OriginalValidator($data); + $validator->mapFieldsRules($rules); - return $v; + return $validator; } /** @@ -29,22 +29,26 @@ protected function createOriginalValidator(array $data, array $rules): OriginalV */ protected function createFixedValidator(array $data, array $rules): FixedValidator { - $v = new FixedValidator($data); - $v->mapFieldsRules($rules); + $validator = new FixedValidator($data); + $validator->mapFieldsRules($rules); - return $v; + return $validator; } - private function throwAsException(int $error_levels = \E_ALL): void + private function executeFxAndThrowErrors(\Closure $fx, int $errorLevels = \E_ALL) { set_error_handler( static function ($errno, $errstr) { - restore_error_handler(); - throw new \Exception($errstr, $errno); }, - $error_levels + $errorLevels ); + + try { + return $fx(); + } finally { + restore_error_handler(); + } } public function testDate(): void @@ -60,12 +64,13 @@ public function testDate(): void // this throws depreciation notice starting PHP 8.1 $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsException(); + if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } public function testDateFormat(): void @@ -81,12 +86,13 @@ public function testDateFormat(): void // this throws depreciation notice starting PHP 8.1 $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsException(); + if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } public function testDateFormat2(): void @@ -101,9 +107,8 @@ public function testDateFormat2(): void // this throws warning in PHP 7.4 and TypeError in 8.x $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.0.0', '<')) { + if (\PHP_VERSION_ID < 80000) { // @codeCoverageIgnoreStart - $this->throwAsException(); $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*expects parameter 2 to be string, object given.*/'); // Warning: date_parse_from_format() expects parameter 2 to be string, object given // @codeCoverageIgnoreEnd @@ -111,7 +116,9 @@ public function testDateFormat2(): void // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(\TypeError::class); } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } public function testDateBefore(): void @@ -127,12 +134,13 @@ public function testDateBefore(): void // this throws depreciation notice starting PHP 8.1 $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsException(); + if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } public function testDateBefore2(): void @@ -148,12 +156,13 @@ public function testDateBefore2(): void // this throws depreciation notice starting PHP 8.1 $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsException(); + if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } public function testDateAfter(): void @@ -169,12 +178,13 @@ public function testDateAfter(): void // this throws depreciation notice starting PHP 8.1 $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsException(); + if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } public function testDateAfter2(): void @@ -190,11 +200,12 @@ public function testDateAfter2(): void // this throws depreciation notice starting PHP 8.1 $v = $this->createOriginalValidator($data, $rules); - if (version_compare(\PHP_VERSION, '8.1.0', '>=')) { - $this->throwAsException(); + if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $v->validate(); + $this->executeFxAndThrowErrors(function() use ($v){ + $v->validate(); + }); } } From 7733fa280136b0e7fce6831da14ec4530a8c6a0f Mon Sep 17 00:00:00 2001 From: DarkSide Date: Fri, 19 Apr 2024 23:56:58 +0300 Subject: [PATCH 47/49] cs fixes --- tests/ValitronValidatorTest.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 4f424f6..ca9354f 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -35,6 +35,9 @@ protected function createFixedValidator(array $data, array $rules): FixedValidat return $validator; } + /** + * @return mixed + */ private function executeFxAndThrowErrors(\Closure $fx, int $errorLevels = \E_ALL) { set_error_handler( @@ -68,7 +71,7 @@ public function testDate(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } @@ -90,7 +93,7 @@ public function testDateFormat(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } @@ -116,7 +119,7 @@ public function testDateFormat2(): void // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(\TypeError::class); } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } @@ -138,7 +141,7 @@ public function testDateBefore(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } @@ -160,7 +163,7 @@ public function testDateBefore2(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } @@ -182,7 +185,7 @@ public function testDateAfter(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } @@ -204,7 +207,7 @@ public function testDateAfter2(): void $this->expectException(\Exception::class); $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated } - $this->executeFxAndThrowErrors(function() use ($v){ + $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); }); } From 9e06c8c266c8f4ff0604037760914e89465405d7 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sat, 20 Apr 2024 00:02:40 +0300 Subject: [PATCH 48/49] check for precise message --- tests/ValitronValidatorTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index ca9354f..18efc8d 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -69,7 +69,7 @@ public function testDate(): void $v = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); @@ -91,7 +91,7 @@ public function testDateFormat(): void $v = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated + $this->expectExceptionMessage('date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated'); } $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); @@ -113,7 +113,7 @@ public function testDateFormat2(): void if (\PHP_VERSION_ID < 80000) { // @codeCoverageIgnoreStart $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*expects parameter 2 to be string, object given.*/'); // Warning: date_parse_from_format() expects parameter 2 to be string, object given + $this->expectExceptionMessage('date_parse_from_format() expects parameter 2 to be string, object given'); // @codeCoverageIgnoreEnd } else { // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given @@ -139,7 +139,7 @@ public function testDateBefore(): void $v = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); @@ -161,7 +161,7 @@ public function testDateBefore2(): void $v = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); @@ -183,7 +183,7 @@ public function testDateAfter(): void $v = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); @@ -205,7 +205,7 @@ public function testDateAfter2(): void $v = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/.*is deprecated/'); // Deprecated: strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated + $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } $this->executeFxAndThrowErrors(static function () use ($v) { $v->validate(); From 35d408236058587b01f44e3697e392edc35d08d9 Mon Sep 17 00:00:00 2001 From: DarkSide Date: Sat, 20 Apr 2024 00:48:09 +0300 Subject: [PATCH 49/49] variable naming --- tests/ValitronValidatorTest.php | 96 ++++++++++++++++----------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/tests/ValitronValidatorTest.php b/tests/ValitronValidatorTest.php index 18efc8d..8c2763e 100644 --- a/tests/ValitronValidatorTest.php +++ b/tests/ValitronValidatorTest.php @@ -60,19 +60,19 @@ public function testDate(): void $data = ['d' => null]; $rules = ['d' => ['required', 'date']]; - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); + $validator = $this->createFixedValidator($data, $rules); + self::assertFalse($validator->validate()); + self::assertSame(['d'], array_keys($validator->errors())); + self::assertSame(2, count($validator->errors()['d'])); // this throws depreciation notice starting PHP 8.1 - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } @@ -82,19 +82,19 @@ public function testDateFormat(): void $data = ['d' => null]; $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); + $validator = $this->createFixedValidator($data, $rules); + self::assertFalse($validator->validate()); + self::assertSame(['d'], array_keys($validator->errors())); + self::assertSame(2, count($validator->errors()['d'])); // this throws depreciation notice starting PHP 8.1 - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessage('date_parse_from_format(): Passing null to parameter #2 ($datetime) of type string is deprecated'); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } @@ -104,12 +104,12 @@ public function testDateFormat2(): void $data = ['d' => new \DateTime()]; $rules = ['d' => ['required', ['dateFormat', 'd-m-Y']]]; - $v = $this->createFixedValidator($data, $rules); - self::assertTrue($v->validate()); - self::assertSame([], array_keys($v->errors())); + $validator = $this->createFixedValidator($data, $rules); + self::assertTrue($validator->validate()); + self::assertSame([], array_keys($validator->errors())); // this throws warning in PHP 7.4 and TypeError in 8.x - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID < 80000) { // @codeCoverageIgnoreStart $this->expectException(\Exception::class); @@ -119,8 +119,8 @@ public function testDateFormat2(): void // TypeError: date_parse_from_format(): Argument #2 ($datetime) must be of type string, DateTime given self::expectException(\TypeError::class); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } @@ -130,19 +130,19 @@ public function testDateBefore(): void $data = ['d' => null]; $rules = ['d' => ['required', ['dateBefore', '2029-12-31']]]; - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); + $validator = $this->createFixedValidator($data, $rules); + self::assertFalse($validator->validate()); + self::assertSame(['d'], array_keys($validator->errors())); + self::assertSame(2, count($validator->errors()['d'])); // this throws depreciation notice starting PHP 8.1 - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } @@ -152,19 +152,19 @@ public function testDateBefore2(): void $data = ['d' => '2024-10-20']; $rules = ['d' => ['required', ['dateBefore', null]]]; - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(1, count($v->errors()['d'])); + $validator = $this->createFixedValidator($data, $rules); + self::assertFalse($validator->validate()); + self::assertSame(['d'], array_keys($validator->errors())); + self::assertSame(1, count($validator->errors()['d'])); // this throws depreciation notice starting PHP 8.1 - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } @@ -174,19 +174,19 @@ public function testDateAfter(): void $data = ['d' => null]; $rules = ['d' => ['required', ['dateAfter', '2023-12-31']]]; - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(2, count($v->errors()['d'])); + $validator = $this->createFixedValidator($data, $rules); + self::assertFalse($validator->validate()); + self::assertSame(['d'], array_keys($validator->errors())); + self::assertSame(2, count($validator->errors()['d'])); // this throws depreciation notice starting PHP 8.1 - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } @@ -196,19 +196,19 @@ public function testDateAfter2(): void $data = ['d' => '2024-10-20']; $rules = ['d' => ['required', ['dateAfter', null]]]; - $v = $this->createFixedValidator($data, $rules); - self::assertFalse($v->validate()); - self::assertSame(['d'], array_keys($v->errors())); - self::assertSame(1, count($v->errors()['d'])); + $validator = $this->createFixedValidator($data, $rules); + self::assertFalse($validator->validate()); + self::assertSame(['d'], array_keys($validator->errors())); + self::assertSame(1, count($validator->errors()['d'])); // this throws depreciation notice starting PHP 8.1 - $v = $this->createOriginalValidator($data, $rules); + $validator = $this->createOriginalValidator($data, $rules); if (\PHP_VERSION_ID >= 80100) { $this->expectException(\Exception::class); $this->expectExceptionMessage('strtotime(): Passing null to parameter #1 ($datetime) of type string is deprecated'); } - $this->executeFxAndThrowErrors(static function () use ($v) { - $v->validate(); + $this->executeFxAndThrowErrors(static function () use ($validator) { + $validator->validate(); }); } }