Skip to content

Commit eebec16

Browse files
authored
Merge pull request #8122 from kenjis/fix-validation-matches-and-differs
fix: validation rule `matches` and `differs`
2 parents f6fabae + db0ad7e commit eebec16

File tree

6 files changed

+137
-19
lines changed

6 files changed

+137
-19
lines changed

system/Validation/Rules.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ class Rules
2424
/**
2525
* The value does not match another field in $data.
2626
*
27-
* @param array $data Other field/value pairs
27+
* @param string|null $str
28+
* @param array $data Other field/value pairs
2829
*/
29-
public function differs(?string $str, string $field, array $data): bool
30+
public function differs($str, string $field, array $data): bool
3031
{
3132
if (strpos($field, '.') !== false) {
3233
return $str !== dot_array_search($field, $data);
@@ -177,15 +178,16 @@ public function less_than_equal_to(?string $str, string $max): bool
177178
/**
178179
* Matches the value of another field in $data.
179180
*
180-
* @param array $data Other field/value pairs
181+
* @param string|null $str
182+
* @param array $data Other field/value pairs
181183
*/
182-
public function matches(?string $str, string $field, array $data): bool
184+
public function matches($str, string $field, array $data): bool
183185
{
184186
if (strpos($field, '.') !== false) {
185187
return $str === dot_array_search($field, $data);
186188
}
187189

188-
return array_key_exists($field, $data) && $str === $data[$field];
190+
return isset($data[$field]) && $str === $data[$field];
189191
}
190192

191193
/**

system/Validation/StrictRules/Rules.php

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,26 @@ public function __construct()
3636
* @param array|bool|float|int|object|string|null $str
3737
* @param array $data Other field/value pairs
3838
*/
39-
public function differs($str, string $field, array $data): bool
40-
{
41-
if (! is_string($str)) {
39+
public function differs(
40+
$str,
41+
string $otherField,
42+
array $data,
43+
?string $error = null,
44+
?string $field = null
45+
): bool {
46+
if (strpos($otherField, '.') !== false) {
47+
return $str !== dot_array_search($otherField, $data);
48+
}
49+
50+
if (! array_key_exists($field, $data)) {
4251
return false;
4352
}
4453

45-
return $this->nonStrictRules->differs($str, $field, $data);
54+
if (! array_key_exists($otherField, $data)) {
55+
return false;
56+
}
57+
58+
return $str !== ($data[$otherField] ?? null);
4659
}
4760

4861
/**
@@ -254,9 +267,26 @@ public function less_than_equal_to($str, string $max): bool
254267
* @param array|bool|float|int|object|string|null $str
255268
* @param array $data Other field/value pairs
256269
*/
257-
public function matches($str, string $field, array $data): bool
258-
{
259-
return $this->nonStrictRules->matches($str, $field, $data);
270+
public function matches(
271+
$str,
272+
string $otherField,
273+
array $data,
274+
?string $error = null,
275+
?string $field = null
276+
): bool {
277+
if (strpos($otherField, '.') !== false) {
278+
return $str === dot_array_search($otherField, $data);
279+
}
280+
281+
if (! array_key_exists($field, $data)) {
282+
return false;
283+
}
284+
285+
if (! array_key_exists($otherField, $data)) {
286+
return false;
287+
}
288+
289+
return $str === ($data[$otherField] ?? null);
260290
}
261291

262292
/**

tests/system/Validation/RulesTest.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,20 +290,26 @@ public static function providePermitEmpty(): iterable
290290
}
291291

292292
/**
293-
* @dataProvider provideMatchesCases
293+
* @dataProvider provideMatches
294294
*/
295295
public function testMatches(array $data, bool $expected): void
296296
{
297297
$this->validation->setRules(['foo' => 'matches[bar]']);
298298
$this->assertSame($expected, $this->validation->run($data));
299299
}
300300

301-
public static function provideMatchesCases(): iterable
301+
public static function provideMatches(): iterable
302302
{
303303
yield from [
304-
[['foo' => null, 'bar' => null], true],
305-
[['foo' => 'match', 'bar' => 'match'], true],
306-
[['foo' => 'match', 'bar' => 'nope'], false],
304+
'foo bar not exist' => [[], false],
305+
'bar not exist' => [['foo' => null], false],
306+
'foo not exist' => [['bar' => null], false],
307+
'foo bar null' => [['foo' => null, 'bar' => null], false], // Strict Rule: true
308+
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], true],
309+
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], false],
310+
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], true],
311+
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], false],
312+
'foo bar bool match' => [['foo' => true, 'bar' => true], true],
307313
];
308314
}
309315

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

327333
/**
328-
* @dataProvider provideMatchesCases
334+
* @dataProvider provideDiffers
329335
*/
330336
public function testDiffers(array $data, bool $expected): void
331337
{
332338
$this->validation->setRules(['foo' => 'differs[bar]']);
333-
$this->assertSame(! $expected, $this->validation->run($data));
339+
$this->assertSame($expected, $this->validation->run($data));
340+
}
341+
342+
public static function provideDiffers(): iterable
343+
{
344+
yield from [
345+
'foo bar not exist' => [[], false],
346+
'bar not exist' => [['foo' => null], false],
347+
'foo not exist' => [['bar' => null], false],
348+
'foo bar null' => [['foo' => null, 'bar' => null], false],
349+
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], false],
350+
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], true],
351+
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], false],
352+
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], true],
353+
'foo bar bool match' => [['foo' => true, 'bar' => true], false],
354+
];
334355
}
335356

336357
/**

tests/system/Validation/StrictRules/RulesTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,52 @@ public static function provideLessEqualThanStrict(): iterable
198198
[true, '0', false],
199199
];
200200
}
201+
202+
/**
203+
* @dataProvider provideMatches
204+
*/
205+
public function testMatches(array $data, bool $expected): void
206+
{
207+
$this->validation->setRules(['foo' => 'matches[bar]']);
208+
$this->assertSame($expected, $this->validation->run($data));
209+
}
210+
211+
public static function provideMatches(): iterable
212+
{
213+
yield from [
214+
'foo bar not exist' => [[], false],
215+
'bar not exist' => [['foo' => null], false],
216+
'foo not exist' => [['bar' => null], false],
217+
'foo bar null' => [['foo' => null, 'bar' => null], true],
218+
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], true],
219+
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], false],
220+
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], true],
221+
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], false],
222+
'foo bar bool match' => [['foo' => true, 'bar' => true], true],
223+
];
224+
}
225+
226+
/**
227+
* @dataProvider provideDiffers
228+
*/
229+
public function testDiffers(array $data, bool $expected): void
230+
{
231+
$this->validation->setRules(['foo' => 'differs[bar]']);
232+
$this->assertSame($expected, $this->validation->run($data));
233+
}
234+
235+
public static function provideDiffers(): iterable
236+
{
237+
yield from [
238+
'foo bar not exist' => [[], false],
239+
'bar not exist' => [['foo' => null], false],
240+
'foo not exist' => [['bar' => null], false],
241+
'foo bar null' => [['foo' => null, 'bar' => null], false],
242+
'foo bar string match' => [['foo' => 'match', 'bar' => 'match'], false],
243+
'foo bar string not match' => [['foo' => 'match', 'bar' => 'nope'], true],
244+
'foo bar float match' => [['foo' => 1.2, 'bar' => 1.2], false],
245+
'foo bar float not match' => [['foo' => 1.2, 'bar' => 2.3], true],
246+
'foo bar bool match' => [['foo' => true, 'bar' => true], false],
247+
];
248+
}
201249
}

user_guide_src/source/changelogs/v4.4.4.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ A validation rule with the wildcard ``*`` now validates only data in correct
2121
dimensions as "dot array syntax".
2222
See :ref:`Upgrading <upgrade-444-validation-with-dot-array-syntax>` for details.
2323

24+
Validation rules matches and differs
25+
====================================
26+
27+
Bugs have been fixed in the case where ``matches`` and ``differs`` in the Strict
28+
and Traditional rules validate data of non-string types.
29+
2430
***************
2531
Message Changes
2632
***************

user_guide_src/source/installation/upgrade_444.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ The following code explains details:
3939

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

42+
Validation rules matches and differs
43+
====================================
44+
45+
Because bugs have been fixed in the case where ``matches`` and ``differs`` in
46+
the Strict and Traditional rules validate data of non-string types, if you are
47+
using these rules and validate non-string data, the validation results might be
48+
changed (fixed).
49+
50+
Note that Traditional Rules should not be used to validate data that is not a
51+
string.
52+
4253
*********************
4354
Breaking Enhancements
4455
*********************

0 commit comments

Comments
 (0)