From fab6425d009f33e7df3bc2cc47432b85e4c97358 Mon Sep 17 00:00:00 2001 From: Viktor Turskyi Date: Tue, 27 Oct 2026 16:34:42 +0200 Subject: [PATCH] like: $ matches only at the end of the value LIVR patterns follow JavaScript, where $ matches only at the end of the value. PCRE also matches it before a trailing newline, so {"like": "^[0-9]{5}$"} accepted "12345\n". The like rule now compiles the pattern with the D (PCRE_DOLLAR_ENDONLY) modifier. --- lib/Validator/LIVR/Rules/Text.php | 3 ++- tests/05-rules_edge_cases.php | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/Validator/LIVR/Rules/Text.php b/lib/Validator/LIVR/Rules/Text.php index ddc2cda..3a48b46 100644 --- a/lib/Validator/LIVR/Rules/Text.php +++ b/lib/Validator/LIVR/Rules/Text.php @@ -164,7 +164,8 @@ public static function lengthBetween($minLength, $maxLength) public static function like($re) { - $re = '/' . $re . '/'; + // D: $ matches only at the end of the value, as in JavaScript, not before a trailing newline + $re = '/' . $re . '/D'; if (func_num_args() == 3) { #Passed regexp flag $flags = func_get_arg(1); diff --git a/tests/05-rules_edge_cases.php b/tests/05-rules_edge_cases.php index 40536b5..257737d 100644 --- a/tests/05-rules_edge_cases.php +++ b/tests/05-rules_edge_cases.php @@ -64,4 +64,23 @@ public function testEmptyListsOfRules() 'Should skip fields without rules' ); } + + public function testLikeMatchesTheEndOfTheValue() + { + $validator = new Validator\LIVR(array( + 'zip1' => array('like' => '^[0-9]{5}$'), + 'zip2' => array('like' => array('^[0-9]{5}$', 'i')), + 'zip3' => array('like' => '^[0-9]{5}$'), + )); + + $this->assertFalse( + $validator->validate(array('zip1' => "12345\n", 'zip2' => "12345\n", 'zip3' => '12345')), + 'Should return false' + ); + $this->assertEquals( + array('zip1' => 'WRONG_FORMAT', 'zip2' => 'WRONG_FORMAT'), + $validator->getErrors(), + 'Should not match $ before a trailing newline' + ); + } }