mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
Fix splitting of string rules (#4957)
This commit is contained in:
parent
6e64994e6c
commit
eeaae2a218
@ -672,21 +672,42 @@ class Validation implements ValidationInterface
|
||||
*/
|
||||
protected function splitRules(string $rules): array
|
||||
{
|
||||
$nonEscapeBracket = '((?<!\\\\)(?:\\\\\\\\)*[\[\]])';
|
||||
$pipeNotInBracket = sprintf(
|
||||
'/\|(?=(?:[^\[\]]*%s[^\[\]]*%s)*(?![^\[\]]*%s))/',
|
||||
$nonEscapeBracket,
|
||||
$nonEscapeBracket,
|
||||
$nonEscapeBracket
|
||||
);
|
||||
if (strpos($rules, '|') === false) {
|
||||
return [$rules];
|
||||
}
|
||||
|
||||
$_rules = preg_split($pipeNotInBracket, $rules);
|
||||
$string = $rules;
|
||||
$rules = [];
|
||||
$length = strlen($string);
|
||||
$cursor = 0;
|
||||
|
||||
return array_unique($_rules);
|
||||
while ($cursor < $length) {
|
||||
$pos = strpos($string, '|', $cursor);
|
||||
|
||||
if ($pos === false) {
|
||||
// we're in the last rule
|
||||
$pos = $length;
|
||||
}
|
||||
|
||||
$rule = substr($string, $cursor, $pos - $cursor);
|
||||
|
||||
while (
|
||||
(substr_count($rule, '[') - substr_count($rule, '\['))
|
||||
!== (substr_count($rule, ']') - substr_count($rule, '\]'))
|
||||
) {
|
||||
// the pipe is inside the brackets causing the closing bracket to
|
||||
// not be included. so, we adjust the rule to include that portion.
|
||||
$pos = strpos($string, '|', $cursor + strlen($rule) + 1) ?: $length;
|
||||
$rule = substr($string, $cursor, $pos - $cursor);
|
||||
}
|
||||
|
||||
$rules[] = $rule;
|
||||
$cursor += strlen($rule) + 1; // +1 to exclude the pipe
|
||||
}
|
||||
|
||||
return array_unique($rules);
|
||||
}
|
||||
|
||||
// Misc
|
||||
|
||||
/**
|
||||
* Resets the class to a blank slate. Should be called whenever
|
||||
* you need to process more than one array.
|
||||
|
@ -984,4 +984,68 @@ final class ValidationTest extends CIUnitTestCase
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideStringRulesCases
|
||||
*
|
||||
* @param string $input
|
||||
* @param array $expected
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @see https://github.com/codeigniter4/CodeIgniter4/issues/4929
|
||||
*/
|
||||
public function testSplittingOfComplexStringRules(string $input, array $expected): void
|
||||
{
|
||||
$splitter = $this->getPrivateMethodInvoker($this->validation, 'splitRules');
|
||||
$this->assertSame($expected, $splitter($input));
|
||||
}
|
||||
|
||||
public function provideStringRulesCases(): iterable
|
||||
{
|
||||
yield [
|
||||
'required',
|
||||
['required'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|numeric',
|
||||
['required', 'numeric'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|max_length[500]|hex',
|
||||
['required', 'max_length[500]', 'hex'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|numeric|regex_match[/[a-zA-Z]+/]',
|
||||
['required', 'numeric', 'regex_match[/[a-zA-Z]+/]'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|max_length[500]|regex_match[/^;"\'{}\[\]^<>=/]',
|
||||
['required', 'max_length[500]', 'regex_match[/^;"\'{}\[\]^<>=/]'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'regex_match[/^;"\'{}\[\]^<>=/]|regex_match[/[^a-z0-9.\|_]+/]',
|
||||
['regex_match[/^;"\'{}\[\]^<>=/]', 'regex_match[/[^a-z0-9.\|_]+/]'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|regex_match[/^(01[2689]|09)[0-9]{8}$/]|numeric',
|
||||
['required', 'regex_match[/^(01[2689]|09)[0-9]{8}$/]', 'numeric'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|regex_match[/^[0-9]{4}[\-\.\[\/][0-9]{2}[\-\.\[\/][0-9]{2}/]|max_length[10]',
|
||||
['required', 'regex_match[/^[0-9]{4}[\-\.\[\/][0-9]{2}[\-\.\[\/][0-9]{2}/]', 'max_length[10]'],
|
||||
];
|
||||
|
||||
yield [
|
||||
'required|regex_match[/^(01|2689|09)[0-9]{8}$/]|numeric',
|
||||
['required', 'regex_match[/^(01|2689|09)[0-9]{8}$/]', 'numeric'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user