Skip to content

Commit 1f8a3f0

Browse files
authored
Merge pull request #7085 from kenjis/fix-Validtaion-is_unique
fix: TypeError in Validation is_unique/is_not_unique
2 parents c58f45d + 76c8997 commit 1f8a3f0

4 files changed

Lines changed: 104 additions & 187 deletions

File tree

system/Validation/Rules.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ public function greater_than_equal_to(?string $str, string $min): bool
8686
public function is_not_unique(?string $str, string $field, array $data): bool
8787
{
8888
// Grab any data for exclusion of a single row.
89-
[$field, $whereField, $whereValue] = array_pad(explode(',', $field), 3, null);
89+
[$field, $whereField, $whereValue] = array_pad(
90+
explode(',', $field),
91+
3,
92+
null
93+
);
9094

9195
// Break the table and field apart
9296
sscanf($field, '%[^.].%[^.]', $table, $field);
@@ -97,7 +101,10 @@ public function is_not_unique(?string $str, string $field, array $data): bool
97101
->where($field, $str)
98102
->limit(1);
99103

100-
if (! empty($whereField) && ! empty($whereValue) && ! preg_match('/^\{(\w+)\}$/', $whereValue)) {
104+
if (
105+
! empty($whereField) && ! empty($whereValue)
106+
&& ! preg_match('/^\{(\w+)\}$/', $whereValue)
107+
) {
101108
$row = $row->where($whereField, $whereValue);
102109
}
103110

@@ -125,7 +132,11 @@ public function in_list(?string $value, string $list): bool
125132
*/
126133
public function is_unique(?string $str, string $field, array $data): bool
127134
{
128-
[$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null);
135+
[$field, $ignoreField, $ignoreValue] = array_pad(
136+
explode(',', $field),
137+
3,
138+
null
139+
);
129140

130141
sscanf($field, '%[^.].%[^.]', $table, $field);
131142

@@ -135,7 +146,10 @@ public function is_unique(?string $str, string $field, array $data): bool
135146
->where($field, $str)
136147
->limit(1);
137148

138-
if (! empty($ignoreField) && ! empty($ignoreValue) && ! preg_match('/^\{(\w+)\}$/', $ignoreValue)) {
149+
if (
150+
! empty($ignoreField) && ! empty($ignoreValue)
151+
&& ! preg_match('/^\{(\w+)\}$/', $ignoreValue)
152+
) {
139153
$row = $row->where("{$ignoreField} !=", $ignoreValue);
140154
}
141155

system/Validation/StrictRules/Rules.php

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,34 @@ public function greater_than_equal_to($str, string $min): bool
117117
*/
118118
public function is_not_unique($str, string $field, array $data): bool
119119
{
120-
return $this->nonStrictRules->is_not_unique($str, $field, $data);
120+
if (is_object($str) || is_array($str)) {
121+
return false;
122+
}
123+
124+
// Grab any data for exclusion of a single row.
125+
[$field, $whereField, $whereValue] = array_pad(
126+
explode(',', $field),
127+
3,
128+
null
129+
);
130+
131+
// Break the table and field apart
132+
sscanf($field, '%[^.].%[^.]', $table, $field);
133+
134+
$row = Database::connect($data['DBGroup'] ?? null)
135+
->table($table)
136+
->select('1')
137+
->where($field, $str)
138+
->limit(1);
139+
140+
if (
141+
! empty($whereField) && ! empty($whereValue)
142+
&& ! preg_match('/^\{(\w+)\}$/', $whereValue)
143+
) {
144+
$row = $row->where($whereField, $whereValue);
145+
}
146+
147+
return $row->get()->getRow() !== null;
121148
}
122149

123150
/**
@@ -151,7 +178,32 @@ public function in_list($value, string $list): bool
151178
*/
152179
public function is_unique($str, string $field, array $data): bool
153180
{
154-
return $this->nonStrictRules->is_unique($str, $field, $data);
181+
if (is_object($str) || is_array($str)) {
182+
return false;
183+
}
184+
185+
[$field, $ignoreField, $ignoreValue] = array_pad(
186+
explode(',', $field),
187+
3,
188+
null
189+
);
190+
191+
sscanf($field, '%[^.].%[^.]', $table, $field);
192+
193+
$row = Database::connect($data['DBGroup'] ?? null)
194+
->table($table)
195+
->select('1')
196+
->where($field, $str)
197+
->limit(1);
198+
199+
if (
200+
! empty($ignoreField) && ! empty($ignoreValue)
201+
&& ! preg_match('/^\{(\w+)\}$/', $ignoreValue)
202+
) {
203+
$row = $row->where("{$ignoreField} !=", $ignoreValue);
204+
}
205+
206+
return $row->get()->getRow() === null;
155207
}
156208

157209
/**

tests/system/Validation/DatabaseRelatedRulesTest.php

Lines changed: 5 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,17 @@
1111

1212
namespace CodeIgniter\Validation;
1313

14-
use CodeIgniter\Test\CIUnitTestCase;
15-
use CodeIgniter\Test\DatabaseTestTrait;
16-
use Config\Database;
17-
use Config\Services;
14+
use CodeIgniter\Validation\StrictRules\DatabaseRelatedRulesTest as StrictDatabaseRelatedRulesTest;
1815
use Tests\Support\Validation\TestRules;
1916

2017
/**
2118
* @internal
2219
*
2320
* @group DatabaseLive
2421
*/
25-
final class DatabaseRelatedRulesTest extends CIUnitTestCase
22+
final class DatabaseRelatedRulesTest extends StrictDatabaseRelatedRulesTest
2623
{
27-
use DatabaseTestTrait;
28-
29-
private Validation $validation;
30-
private array $config = [
24+
protected array $config = [
3125
'ruleSets' => [
3226
Rules::class,
3327
FormatRules::class,
@@ -45,173 +39,8 @@ final class DatabaseRelatedRulesTest extends CIUnitTestCase
4539
],
4640
];
4741

48-
protected function setUp(): void
49-
{
50-
parent::setUp();
51-
$this->validation = new Validation((object) $this->config, Services::renderer());
52-
$this->validation->reset();
53-
}
54-
55-
public function testIsUniqueFalse(): void
56-
{
57-
Database::connect()
58-
->table('user')
59-
->insert([
60-
'name' => 'Derek Travis',
61-
'email' => 'derek@world.com',
62-
'country' => 'Elbonia',
63-
]);
64-
65-
$data = ['email' => 'derek@world.com'];
66-
$this->validation->setRules(['email' => 'is_unique[user.email]']);
67-
$this->assertFalse($this->validation->run($data));
68-
}
69-
70-
public function testIsUniqueTrue(): void
71-
{
72-
$data = ['email' => 'derek@world.co.uk'];
73-
$this->validation->setRules(['email' => 'is_unique[user.email]']);
74-
$this->assertTrue($this->validation->run($data));
75-
}
76-
77-
public function testIsUniqueIgnoresParams(): void
78-
{
79-
$db = Database::connect();
80-
$db
81-
->table('user')
82-
->insert([
83-
'name' => 'Developer A',
84-
'email' => 'deva@example.com',
85-
'country' => 'Elbonia',
86-
]);
87-
$row = $db->table('user')
88-
->limit(1)
89-
->get()
90-
->getRow();
91-
92-
$data = ['email' => 'derek@world.co.uk'];
93-
$this->validation->setRules(['email' => "is_unique[user.email,id,{$row->id}]"]);
94-
$this->assertTrue($this->validation->run($data));
95-
}
96-
97-
public function testIsUniqueIgnoresParamsPlaceholders(): void
98-
{
99-
$this->hasInDatabase('user', [
100-
'name' => 'Derek',
101-
'email' => 'derek@world.co.uk',
102-
'country' => 'GB',
103-
]);
104-
105-
$row = Database::connect()
106-
->table('user')
107-
->limit(1)
108-
->get()
109-
->getRow();
110-
111-
$data = [
112-
'id' => $row->id,
113-
'email' => 'derek@world.co.uk',
114-
];
115-
116-
$this->validation->setRules(['email' => 'is_unique[user.email,id,{id}]']);
117-
$this->assertTrue($this->validation->run($data));
118-
}
119-
120-
public function testIsUniqueByManualRun(): void
121-
{
122-
Database::connect()
123-
->table('user')
124-
->insert([
125-
'name' => 'Developer A',
126-
'email' => 'deva@example.com',
127-
'country' => 'Elbonia',
128-
]);
129-
130-
$this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', []));
131-
}
132-
133-
public function testIsNotUniqueFalse(): void
134-
{
135-
Database::connect()
136-
->table('user')
137-
->insert([
138-
'name' => 'Derek Travis',
139-
'email' => 'derek@world.com',
140-
'country' => 'Elbonia',
141-
]);
142-
143-
$data = ['email' => 'derek1@world.com'];
144-
$this->validation->setRules(['email' => 'is_not_unique[user.email]']);
145-
$this->assertFalse($this->validation->run($data));
146-
}
147-
148-
public function testIsNotUniqueTrue(): void
149-
{
150-
Database::connect()
151-
->table('user')
152-
->insert([
153-
'name' => 'Derek Travis',
154-
'email' => 'derek@world.com',
155-
'country' => 'Elbonia',
156-
]);
157-
158-
$data = ['email' => 'derek@world.com'];
159-
$this->validation->setRules(['email' => 'is_not_unique[user.email]']);
160-
$this->assertTrue($this->validation->run($data));
161-
}
162-
163-
public function testIsNotUniqueIgnoresParams(): void
42+
protected function createRules()
16443
{
165-
$db = Database::connect();
166-
$db->table('user')
167-
->insert([
168-
'name' => 'Developer A',
169-
'email' => 'deva@example.com',
170-
'country' => 'Elbonia',
171-
]);
172-
173-
$row = $db->table('user')
174-
->limit(1)
175-
->get()
176-
->getRow();
177-
178-
$data = ['email' => 'derek@world.co.uk'];
179-
$this->validation->setRules(['email' => "is_not_unique[user.email,id,{$row->id}]"]);
180-
$this->assertFalse($this->validation->run($data));
181-
}
182-
183-
public function testIsNotUniqueIgnoresParamsPlaceholders(): void
184-
{
185-
$this->hasInDatabase('user', [
186-
'name' => 'Derek',
187-
'email' => 'derek@world.co.uk',
188-
'country' => 'GB',
189-
]);
190-
191-
$row = Database::connect()
192-
->table('user')
193-
->limit(1)
194-
->get()
195-
->getRow();
196-
197-
$data = [
198-
'id' => $row->id,
199-
'email' => 'derek@world.co.uk',
200-
];
201-
$this->validation->setRules(['email' => 'is_not_unique[user.email,id,{id}]']);
202-
$this->assertTrue($this->validation->run($data));
203-
}
204-
205-
public function testIsNotUniqueByManualRun(): void
206-
{
207-
Database::connect()
208-
->table('user')
209-
->insert([
210-
'name' => 'Developer A',
211-
'email' => 'deva@example.com',
212-
'country' => 'Elbonia',
213-
]);
214-
215-
$this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', []));
44+
return new Rules();
21645
}
21746
}

tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@
2121
/**
2222
* @internal
2323
*
24+
* @no-final
25+
*
2426
* @group DatabaseLive
2527
*/
26-
final class DatabaseRelatedRulesTest extends CIUnitTestCase
28+
class DatabaseRelatedRulesTest extends CIUnitTestCase
2729
{
2830
use DatabaseTestTrait;
2931

30-
private Validation $validation;
31-
private array $config = [
32+
protected Validation $validation;
33+
protected array $config = [
3234
'ruleSets' => [
3335
Rules::class,
3436
FormatRules::class,
@@ -53,6 +55,11 @@ protected function setUp(): void
5355
$this->validation->reset();
5456
}
5557

58+
protected function createRules()
59+
{
60+
return new Rules();
61+
}
62+
5663
public function testIsUniqueFalse(): void
5764
{
5865
Database::connect()
@@ -128,7 +135,22 @@ public function testIsUniqueByManualRun(): void
128135
'country' => 'Elbonia',
129136
]);
130137

131-
$this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', []));
138+
$this->assertFalse($this->createRules()->is_unique('deva@example.com', 'user.email,id,{id}', []));
139+
}
140+
141+
public function testIsUniqueIntValueByManualRun(): void
142+
{
143+
Database::connect()
144+
->table('user')
145+
->insert([
146+
'name' => 'Developer A',
147+
'email' => 'deva@example.com',
148+
'country' => 'Elbonia',
149+
]);
150+
151+
$result = $this->createRules()->is_unique(1, 'user.id', []);
152+
153+
$this->assertFalse($result);
132154
}
133155

134156
public function testIsNotUniqueFalse(): void
@@ -213,6 +235,6 @@ public function testIsNotUniqueByManualRun(): void
213235
'country' => 'Elbonia',
214236
]);
215237

216-
$this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', []));
238+
$this->assertTrue($this->createRules()->is_not_unique('deva@example.com', 'user.email,id,{id}', []));
217239
}
218240
}

0 commit comments

Comments
 (0)