Skip to content

Commit e39b480

Browse files
committed
Must confirm delete all in query builder
With the query builder it is easy to delete all entries in a table by forgetting the "where" restriction - now there is a mandatory confirmDeleteAll call if no where restriction is defined, to make deleting all entries explicit.
1 parent b676d07 commit e39b480

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

src/Builder/DeleteEntries.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Squirrel\Queries\Builder;
44

5+
use Squirrel\Queries\DBDebug;
56
use Squirrel\Queries\DBInterface;
7+
use Squirrel\Queries\Exception\DBInvalidOptionException;
68

79
/**
810
* Delete query builder as a fluent object - build query and execute it
@@ -24,6 +26,11 @@ class DeleteEntries
2426
*/
2527
private $where = [];
2628

29+
/**
30+
* @var bool We need to confirmation before we delete all entries
31+
*/
32+
private $deleteAll = false;
33+
2734
public function __construct(DBInterface $db)
2835
{
2936
$this->db = $db;
@@ -41,12 +48,18 @@ public function where(array $whereClauses): self
4148
return $this;
4249
}
4350

51+
public function confirmDeleteAll(): self
52+
{
53+
$this->deleteAll = true;
54+
return $this;
55+
}
56+
4457
/**
4558
* Write changes to database
4659
*/
4760
public function write(): void
4861
{
49-
$this->db->delete($this->table, $this->where);
62+
$this->writeAndReturnAffectedNumber();
5063
}
5164

5265
/**
@@ -56,6 +69,23 @@ public function write(): void
5669
*/
5770
public function writeAndReturnAffectedNumber(): int
5871
{
72+
$this->accidentalDeleteAllCheck();
73+
5974
return $this->db->delete($this->table, $this->where);
6075
}
76+
77+
/**
78+
* Make sure there is no accidental "delete everything" because WHERE restrictions were forgotten
79+
*/
80+
private function accidentalDeleteAllCheck()
81+
{
82+
// Make sure there is no accidental "delete everything"
83+
if (\count($this->where) === 0 && $this->deleteAll !== true) {
84+
throw DBDebug::createException(
85+
DBInvalidOptionException::class,
86+
[self::class],
87+
'No restricting "where" arguments defined for DELETE'
88+
);
89+
}
90+
}
6191
}

tests/Builder/DeleteEntriesTest.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Squirrel\Queries\Builder\DeleteEntries;
66
use Squirrel\Queries\DBInterface;
7+
use Squirrel\Queries\Exception\DBInvalidOptionException;
78

89
class DeleteEntriesTest extends \PHPUnit\Framework\TestCase
910
{
@@ -29,7 +30,9 @@ public function testNoDataGetEntries()
2930
->with('', [])
3031
->andReturn($expectedResult);
3132

32-
$deleteBuilder->write();
33+
$deleteBuilder
34+
->confirmDeleteAll()
35+
->write();
3336

3437
$this->assertTrue(true);
3538
}
@@ -46,7 +49,9 @@ public function testNoDataGetEntriesWithAffected()
4649
->with('', [])
4750
->andReturn($expectedResult);
4851

49-
$results = $deleteBuilder->writeAndReturnAffectedNumber();
52+
$results = $deleteBuilder
53+
->confirmDeleteAll()
54+
->writeAndReturnAffectedNumber();
5055

5156
$this->assertSame($expectedResult, $results);
5257
}
@@ -76,4 +81,21 @@ public function testGetEntries()
7681

7782
$this->assertSame($expectedResult, $results);
7883
}
84+
85+
public function testNoWhereNoConfirmation()
86+
{
87+
$this->expectException(DBInvalidOptionException::class);
88+
89+
$deleteBuilder = new DeleteEntries($this->db);
90+
91+
$expectedResult = 33;
92+
93+
$this->db
94+
->shouldReceive('delete')
95+
->once()
96+
->with('', [])
97+
->andReturn($expectedResult);
98+
99+
$deleteBuilder->write();
100+
}
79101
}

0 commit comments

Comments
 (0)