diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 40a5955b157d..93b86ea6b1dd 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -86,7 +86,11 @@ public function greater_than_equal_to(?string $str, string $min): bool public function is_not_unique(?string $str, string $field, array $data): bool { // Grab any data for exclusion of a single row. - [$field, $whereField, $whereValue] = array_pad(explode(',', $field), 3, null); + [$field, $whereField, $whereValue] = array_pad( + explode(',', $field), + 3, + null + ); // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); @@ -97,7 +101,10 @@ public function is_not_unique(?string $str, string $field, array $data): bool ->where($field, $str) ->limit(1); - if (! empty($whereField) && ! empty($whereValue) && ! preg_match('/^\{(\w+)\}$/', $whereValue)) { + if ( + ! empty($whereField) && ! empty($whereValue) + && ! preg_match('/^\{(\w+)\}$/', $whereValue) + ) { $row = $row->where($whereField, $whereValue); } @@ -125,7 +132,11 @@ public function in_list(?string $value, string $list): bool */ public function is_unique(?string $str, string $field, array $data): bool { - [$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null); + [$field, $ignoreField, $ignoreValue] = array_pad( + explode(',', $field), + 3, + null + ); sscanf($field, '%[^.].%[^.]', $table, $field); @@ -135,7 +146,10 @@ public function is_unique(?string $str, string $field, array $data): bool ->where($field, $str) ->limit(1); - if (! empty($ignoreField) && ! empty($ignoreValue) && ! preg_match('/^\{(\w+)\}$/', $ignoreValue)) { + if ( + ! empty($ignoreField) && ! empty($ignoreValue) + && ! preg_match('/^\{(\w+)\}$/', $ignoreValue) + ) { $row = $row->where("{$ignoreField} !=", $ignoreValue); } diff --git a/system/Validation/StrictRules/Rules.php b/system/Validation/StrictRules/Rules.php index 47dbee9b5ae7..05d9e96a305b 100644 --- a/system/Validation/StrictRules/Rules.php +++ b/system/Validation/StrictRules/Rules.php @@ -117,7 +117,34 @@ public function greater_than_equal_to($str, string $min): bool */ public function is_not_unique($str, string $field, array $data): bool { - return $this->nonStrictRules->is_not_unique($str, $field, $data); + if (is_object($str) || is_array($str)) { + return false; + } + + // Grab any data for exclusion of a single row. + [$field, $whereField, $whereValue] = array_pad( + explode(',', $field), + 3, + null + ); + + // Break the table and field apart + sscanf($field, '%[^.].%[^.]', $table, $field); + + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) + ->select('1') + ->where($field, $str) + ->limit(1); + + if ( + ! empty($whereField) && ! empty($whereValue) + && ! preg_match('/^\{(\w+)\}$/', $whereValue) + ) { + $row = $row->where($whereField, $whereValue); + } + + return $row->get()->getRow() !== null; } /** @@ -151,7 +178,32 @@ public function in_list($value, string $list): bool */ public function is_unique($str, string $field, array $data): bool { - return $this->nonStrictRules->is_unique($str, $field, $data); + if (is_object($str) || is_array($str)) { + return false; + } + + [$field, $ignoreField, $ignoreValue] = array_pad( + explode(',', $field), + 3, + null + ); + + sscanf($field, '%[^.].%[^.]', $table, $field); + + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) + ->select('1') + ->where($field, $str) + ->limit(1); + + if ( + ! empty($ignoreField) && ! empty($ignoreValue) + && ! preg_match('/^\{(\w+)\}$/', $ignoreValue) + ) { + $row = $row->where("{$ignoreField} !=", $ignoreValue); + } + + return $row->get()->getRow() === null; } /** diff --git a/tests/system/Validation/DatabaseRelatedRulesTest.php b/tests/system/Validation/DatabaseRelatedRulesTest.php index 42881bab444e..e9abd11f83aa 100644 --- a/tests/system/Validation/DatabaseRelatedRulesTest.php +++ b/tests/system/Validation/DatabaseRelatedRulesTest.php @@ -11,10 +11,7 @@ namespace CodeIgniter\Validation; -use CodeIgniter\Test\CIUnitTestCase; -use CodeIgniter\Test\DatabaseTestTrait; -use Config\Database; -use Config\Services; +use CodeIgniter\Validation\StrictRules\DatabaseRelatedRulesTest as StrictDatabaseRelatedRulesTest; use Tests\Support\Validation\TestRules; /** @@ -22,12 +19,9 @@ * * @group DatabaseLive */ -final class DatabaseRelatedRulesTest extends CIUnitTestCase +final class DatabaseRelatedRulesTest extends StrictDatabaseRelatedRulesTest { - use DatabaseTestTrait; - - private Validation $validation; - private array $config = [ + protected array $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -45,173 +39,8 @@ final class DatabaseRelatedRulesTest extends CIUnitTestCase ], ]; - protected function setUp(): void - { - parent::setUp(); - $this->validation = new Validation((object) $this->config, Services::renderer()); - $this->validation->reset(); - } - - public function testIsUniqueFalse(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = ['email' => 'derek@world.com']; - $this->validation->setRules(['email' => 'is_unique[user.email]']); - $this->assertFalse($this->validation->run($data)); - } - - public function testIsUniqueTrue(): void - { - $data = ['email' => 'derek@world.co.uk']; - $this->validation->setRules(['email' => 'is_unique[user.email]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsUniqueIgnoresParams(): void - { - $db = Database::connect(); - $db - ->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = ['email' => 'derek@world.co.uk']; - $this->validation->setRules(['email' => "is_unique[user.email,id,{$row->id}]"]); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsUniqueIgnoresParamsPlaceholders(): void - { - $this->hasInDatabase('user', [ - 'name' => 'Derek', - 'email' => 'derek@world.co.uk', - 'country' => 'GB', - ]); - - $row = Database::connect() - ->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'id' => $row->id, - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules(['email' => 'is_unique[user.email,id,{id}]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsUniqueByManualRun(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', [])); - } - - public function testIsNotUniqueFalse(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = ['email' => 'derek1@world.com']; - $this->validation->setRules(['email' => 'is_not_unique[user.email]']); - $this->assertFalse($this->validation->run($data)); - } - - public function testIsNotUniqueTrue(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = ['email' => 'derek@world.com']; - $this->validation->setRules(['email' => 'is_not_unique[user.email]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsNotUniqueIgnoresParams(): void + protected function createRules() { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = ['email' => 'derek@world.co.uk']; - $this->validation->setRules(['email' => "is_not_unique[user.email,id,{$row->id}]"]); - $this->assertFalse($this->validation->run($data)); - } - - public function testIsNotUniqueIgnoresParamsPlaceholders(): void - { - $this->hasInDatabase('user', [ - 'name' => 'Derek', - 'email' => 'derek@world.co.uk', - 'country' => 'GB', - ]); - - $row = Database::connect() - ->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'id' => $row->id, - 'email' => 'derek@world.co.uk', - ]; - $this->validation->setRules(['email' => 'is_not_unique[user.email,id,{id}]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsNotUniqueByManualRun(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); + return new Rules(); } } diff --git a/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php b/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php index 79c9c7d39e9f..9b56dc3e3205 100644 --- a/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php +++ b/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php @@ -21,14 +21,16 @@ /** * @internal * + * @no-final + * * @group DatabaseLive */ -final class DatabaseRelatedRulesTest extends CIUnitTestCase +class DatabaseRelatedRulesTest extends CIUnitTestCase { use DatabaseTestTrait; - private Validation $validation; - private array $config = [ + protected Validation $validation; + protected array $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -53,6 +55,11 @@ protected function setUp(): void $this->validation->reset(); } + protected function createRules() + { + return new Rules(); + } + public function testIsUniqueFalse(): void { Database::connect() @@ -128,7 +135,22 @@ public function testIsUniqueByManualRun(): void 'country' => 'Elbonia', ]); - $this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', [])); + $this->assertFalse($this->createRules()->is_unique('deva@example.com', 'user.email,id,{id}', [])); + } + + public function testIsUniqueIntValueByManualRun(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Developer A', + 'email' => 'deva@example.com', + 'country' => 'Elbonia', + ]); + + $result = $this->createRules()->is_unique(1, 'user.id', []); + + $this->assertFalse($result); } public function testIsNotUniqueFalse(): void @@ -213,6 +235,6 @@ public function testIsNotUniqueByManualRun(): void 'country' => 'Elbonia', ]); - $this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); + $this->assertTrue($this->createRules()->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); } }