Skip to content

Commit cd6ebfc

Browse files
committed
fix: Not allowed empty PK value for update/delete
1 parent 04a34ed commit cd6ebfc

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

system/BaseModel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,7 @@ public function delete($id = null, bool $purge = false)
11041104
throw new InvalidArgumentException('delete(): argument #1 ($id) should not be boolean.');
11051105
}
11061106

1107-
if (! in_array($id, [null, 0, '0'], true) && (is_numeric($id) || is_string($id))) {
1107+
if (is_numeric($id) || is_string($id)) {
11081108
$id = [$id];
11091109
}
11101110

system/Model.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ protected function doUpdate($id = null, $row = null): bool
443443

444444
$builder = $this->builder();
445445

446-
if (! in_array($id, [null, '', 0, '0', []], true)) {
446+
if ($this->isValidID($id)) {
447447
$builder = $builder->whereIn($this->table . '.' . $this->primaryKey, $id);
448448
}
449449

@@ -461,6 +461,25 @@ protected function doUpdate($id = null, $row = null): bool
461461
return $builder->update();
462462
}
463463

464+
/**
465+
* Make sure that the primary keys are set and non-empty
466+
* for $this->delete() and $this->update().
467+
*
468+
* @param int|list<mixed>|string|null $id
469+
*/
470+
protected function isValidID($id): bool
471+
{
472+
if (is_array($id) && $id !== []) {
473+
foreach ($id as $valueId) {
474+
if (is_array($valueId) || ! $this->isValidID($valueId)) {
475+
return false;
476+
}
477+
}
478+
}
479+
480+
return ! in_array($id, [null, '', 0, '0', []], true);
481+
}
482+
464483
/**
465484
* Compiles an update string and runs the query
466485
* This method works only with dbCalls.
@@ -496,7 +515,7 @@ protected function doDelete($id = null, bool $purge = false)
496515
$set = [];
497516
$builder = $this->builder();
498517

499-
if (! in_array($id, [null, '', 0, '0', []], true)) {
518+
if ($this->isValidID($id)) {
500519
$builder = $builder->whereIn($this->primaryKey, $id);
501520
}
502521

tests/system/Models/DeleteModelTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ public static function emptyPkValues(): iterable
273273
[0],
274274
[null],
275275
['0'],
276+
// @todo Fail only testDontThrowExceptionWhenSoftDeleteConditionIsSetWithEmptyValue()
277+
// [''],
278+
// [[]],
279+
// [[15 => 150, '_id_' => '200', 20 => '0']],
276280
];
277281
}
278282
}

tests/system/Models/UpdateModelTest.php

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,10 +553,14 @@ public function testUpdateWithSetAndEscape(): void
553553
* @param false|null $id
554554
*/
555555
#[DataProvider('provideUpdateThrowDatabaseExceptionWithoutWhereClause')]
556-
public function testUpdateThrowDatabaseExceptionWithoutWhereClause($id, string $exception, string $exceptionMessage): void
556+
public function testUpdateThrowDatabaseExceptionWithoutWhereClause($id, string $exception): void
557557
{
558558
$this->expectException($exception);
559-
$this->expectExceptionMessage($exceptionMessage);
559+
$this->expectExceptionMessage(
560+
$exception === DatabaseException::class
561+
? 'Updates are not allowed unless they contain a "where" or "like" clause.'
562+
: 'update(): argument #1 ($id) should not be boolean.',
563+
);
560564

561565
// $useSoftDeletes = false
562566
$this->createModel(JobModel::class);
@@ -570,12 +574,34 @@ public static function provideUpdateThrowDatabaseExceptionWithoutWhereClause():
570574
[
571575
null,
572576
DatabaseException::class,
573-
'Updates are not allowed unless they contain a "where" or "like" clause.',
574577
],
575578
[
576579
false,
577580
InvalidArgumentException::class,
578-
'update(): argument #1 ($id) should not be boolean.',
581+
],
582+
[
583+
'',
584+
DatabaseException::class,
585+
],
586+
[
587+
0,
588+
DatabaseException::class,
589+
],
590+
[
591+
'0',
592+
DatabaseException::class,
593+
],
594+
[
595+
[],
596+
DatabaseException::class,
597+
],
598+
[
599+
[15 => 150, '_id_' => '200', 20 => '0'],
600+
DatabaseException::class,
601+
],
602+
[
603+
[0 => '150', [1 => 200]],
604+
DatabaseException::class,
579605
],
580606
];
581607
}

0 commit comments

Comments
 (0)