Skip to content

Commit

Permalink
Merge pull request #8122 from kenjis/fix-validation-matches-and-differs
Browse files Browse the repository at this point in the history
fix: validation rule `matches` and `differs`
  • Loading branch information
kenjis authored Nov 7, 2023
2 parents f6fabae + db0ad7e commit eebec16
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 19 deletions.
12 changes: 7 additions & 5 deletions system/Validation/Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ class Rules
/**
* The value does not match another field in $data.
*
* @param array $data Other field/value pairs
* @param string|null $str
* @param array $data Other field/value pairs
*/
public function differs(?string $str, string $field, array $data): bool
public function differs($str, string $field, array $data): bool
{
if (strpos($field, '.') !== false) {
return $str !== dot_array_search($field, $data);
Expand Down Expand Up @@ -177,15 +178,16 @@ public function less_than_equal_to(?string $str, string $max): bool
/**
* Matches the value of another field in $data.
*
* @param array $data Other field/value pairs
* @param string|null $str
* @param array $data Other field/value pairs
*/
public function matches(?string $str, string $field, array $data): bool
public function matches($str, string $field, array $data): bool
{
if (strpos($field, '.') !== false) {
return $str === dot_array_search($field, $data);
}

return array_key_exists($field, $data) && $str === $data[$field];
return isset($data[$field]) && $str === $data[$field];
}

/**
Expand Down
44 changes: 37 additions & 7 deletions system/Validation/StrictRules/Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,26 @@ public function __construct()
* @param array|bool|float|int|object|string|null $str
* @param array $data Other field/value pairs
*/
public function differs($str, string $field, array $data): bool
{
if (! is_string($str)) {
public function differs(
$str,
string $otherField,
array $data,
?string $error = null,
?string $field = null
): bool {
if (strpos($otherField, '.') !== false) {
return $str !== dot_array_search($otherField, $data);
}

if (! array_key_exists($field, $data)) {
return false;
}

return $this->nonStrictRules->differs($str, $field, $data);
if (! array_key_exists($otherField, $data)) {
return false;
}

return $str !== ($data[$otherField] ?? null);
}

/**
Expand Down Expand Up @@ -254,9 +267,26 @@ public function less_than_equal_to($str, string $max): bool
* @param array|bool|float|int|object|string|null $str
* @param array $data Other field/value pairs
*/
public function matches($str, string $field, array $data): bool
{
return $this->nonStrictRules->matches($str, $field, $data);
public function matches(
$str,
string $otherField,
array $data,
?string $error = null,
?string $field = null
): bool {
if (strpos($otherField, '.') !== false) {
return $str === dot_array_search($otherField, $data);
}

if (! array_key_exists($field, $data)) {
return false;
}

if (! array_key_exists($otherField, $data)) {
return false;
}

return $str === ($data[$otherField] ?? null);
}

/**
Expand Down
35 changes: 28 additions & 7 deletions tests/system/Validation/RulesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -290,20 +290,26 @@ public static function providePermitEmpty(): iterable
}

/**
* @dataProvider provideMatchesCases
* @dataProvider provideMatches
*/
public function testMatches(array $data, bool $expected): void
{
$this->validation->setRules(['foo' => 'matches[bar]']);
$this->assertSame($expected, $this->validation->run($data));
}

public static function provideMatchesCases(): iterable
public static function provideMatches(): iterable
{
yield from [
[['foo' => null, 'bar' => null], true],
[['foo' => 'match', 'bar' => 'match'], true],
[['foo' => 'match', 'bar' => 'nope'], false],
'foo bar not exist' => [[], false],
'bar not exist' => [['foo' => null], false],
'foo not exist' => [['bar' => null], false],
'foo bar null' => [['foo' => null, 'bar' => null], false], // Strict Rule: true
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], true],
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], false],
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], true],
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], false],
'foo bar bool match' => [['foo' => true, 'bar' => true], true],
];
}

Expand All @@ -325,12 +331,27 @@ public static function provideMatchesNestedCases(): iterable
}

/**
* @dataProvider provideMatchesCases
* @dataProvider provideDiffers
*/
public function testDiffers(array $data, bool $expected): void
{
$this->validation->setRules(['foo' => 'differs[bar]']);
$this->assertSame(! $expected, $this->validation->run($data));
$this->assertSame($expected, $this->validation->run($data));
}

public static function provideDiffers(): iterable
{
yield from [
'foo bar not exist' => [[], false],
'bar not exist' => [['foo' => null], false],
'foo not exist' => [['bar' => null], false],
'foo bar null' => [['foo' => null, 'bar' => null], false],
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], false],
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], true],
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], false],
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], true],
'foo bar bool match' => [['foo' => true, 'bar' => true], false],
];
}

/**
Expand Down
48 changes: 48 additions & 0 deletions tests/system/Validation/StrictRules/RulesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,52 @@ public static function provideLessEqualThanStrict(): iterable
[true, '0', false],
];
}

/**
* @dataProvider provideMatches
*/
public function testMatches(array $data, bool $expected): void
{
$this->validation->setRules(['foo' => 'matches[bar]']);
$this->assertSame($expected, $this->validation->run($data));
}

public static function provideMatches(): iterable
{
yield from [
'foo bar not exist' => [[], false],
'bar not exist' => [['foo' => null], false],
'foo not exist' => [['bar' => null], false],
'foo bar null' => [['foo' => null, 'bar' => null], true],
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], true],
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], false],
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], true],
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], false],
'foo bar bool match' => [['foo' => true, 'bar' => true], true],
];
}

/**
* @dataProvider provideDiffers
*/
public function testDiffers(array $data, bool $expected): void
{
$this->validation->setRules(['foo' => 'differs[bar]']);
$this->assertSame($expected, $this->validation->run($data));
}

public static function provideDiffers(): iterable
{
yield from [
'foo bar not exist' => [[], false],
'bar not exist' => [['foo' => null], false],
'foo not exist' => [['bar' => null], false],
'foo bar null' => [['foo' => null, 'bar' => null], false],
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], false],
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], true],
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], false],
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], true],
'foo bar bool match' => [['foo' => true, 'bar' => true], false],
];
}
}
6 changes: 6 additions & 0 deletions user_guide_src/source/changelogs/v4.4.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ A validation rule with the wildcard ``*`` now validates only data in correct
dimensions as "dot array syntax".
See :ref:`Upgrading <upgrade-444-validation-with-dot-array-syntax>` for details.

Validation rules matches and differs
====================================

Bugs have been fixed in the case where ``matches`` and ``differs`` in the Strict
and Traditional rules validate data of non-string types.

***************
Message Changes
***************
Expand Down
11 changes: 11 additions & 0 deletions user_guide_src/source/installation/upgrade_444.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ The following code explains details:

If you have code that depends on the bug, fix the the rule key.

Validation rules matches and differs
====================================

Because bugs have been fixed in the case where ``matches`` and ``differs`` in
the Strict and Traditional rules validate data of non-string types, if you are
using these rules and validate non-string data, the validation results might be
changed (fixed).

Note that Traditional Rules should not be used to validate data that is not a
string.

*********************
Breaking Enhancements
*********************
Expand Down

0 comments on commit eebec16

Please sign in to comment.