Skip to content

Commit

Permalink
working demo
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Sep 1, 2022
1 parent ca0251d commit c2c606b
Showing 1 changed file with 127 additions and 6 deletions.
133 changes: 127 additions & 6 deletions tests/RandomTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ protected function init(): void
}
class Model_Item extends Model
{
use ModelSoftDeleteTrait;

public $table = 'item';

protected function init(): void
Expand All @@ -36,6 +38,8 @@ protected function init(): void
$this->addField('name');
$this->hasOne('parent_item_id', ['model' => [self::class]])
->addTitle();

$this->initSoftDelete();
}
}
class Model_Item2 extends Model
Expand Down Expand Up @@ -71,6 +75,83 @@ protected function init(): void
}
}

trait ModelSoftDeleteTrait
{
protected function initSoftDelete(): void
{
$this->addField('is_deleted', ['type' => 'boolean', 'nullable' => false, 'default' => false]);
$this->addCondition('is_deleted', false);
$this->onHook(Model::HOOK_BEFORE_DELETE, function (Model $entity) {
$softDeleteController = new ControllerSoftDelete();
$softDeleteController->softDelete($entity);

$entity->hook(Model::HOOK_AFTER_DELETE);
$entity->breakHook(false); // this will cancel original Model::delete()
});
}
}

class ControllerSoftDelete
{
protected function init(): void
{
// example broken for clone "Object cannot be cloned with hook bound to a different object than this"
// TODO remove this code from docs, hard to fix, controller is not meant to be added this way to model
throw new \Error();
}

/**
* @return mixed
*/
public function invokeCallbackWithoutUndeletedCondition(Model $model, \Closure $callback)
{
$model->getField('is_deleted'); // assert field exists

$scopeElementsOrig = $model->scope()->elements;
try {
foreach ($model->scope()->elements as $k => $v) {
if ($v instanceof Model\Scope\Condition && $v->key === 'is_deleted' && $v->operator === '=' && $v->value === false) {
unset($model->scope()->elements[$k]);
}
}

return $callback();
} finally {
$model->scope()->elements = $scopeElementsOrig;
}
}

public function softDelete(Model $entity): void
{
$entity->assertIsLoaded();

$this->invokeCallbackWithoutUndeletedCondition($entity->getModel(), function () use ($entity): void {
if ($entity->hook('beforeSoftDelete') === false) {
return;
}

$entity->saveAndUnload(['is_deleted' => true]);

$entity->hook('afterSoftDelete');
});
}

public function restore(Model $entity): void
{
$entity->assertIsLoaded();

$this->invokeCallbackWithoutUndeletedCondition($entity->getModel(), function () use ($entity): void {
if ($entity->hook('beforeRestore') === false) {
return;
}

$entity->saveAndUnload(['is_deleted' => false]);

$entity->hook('afterRestore');
});
}
}

class RandomTest extends TestCase
{
public function testRate(): void
Expand All @@ -87,6 +168,46 @@ public function testRate(): void
static::assertSame(2, $m->executeCountQuery());
}

public function testSoftDelete(): void
{
$m = new Model_Item($this->db);
$this->createMigrator($m)->dropIfExists()->create();

$m->insert(['name' => 'John']);
$m->insert(['name' => 'Michael']);

$softDeleteController = new ControllerSoftDelete();

$entity = $m->loadBy('name', 'Michael');
$softDeleteController->softDelete($entity);
static::assertEquals([
'item' => [
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => null, 'is_deleted' => '0'],
2 => ['id' => 2, 'name' => 'Michael', 'parent_item_id' => null, 'is_deleted' => '1'],
],
], $this->getDb());

$entity = $softDeleteController->invokeCallbackWithoutUndeletedCondition($m, function () use ($m) {
return $m->loadBy('name', 'Michael');
});
$softDeleteController->restore($entity);
static::assertEquals([
'item' => [
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => null, 'is_deleted' => '0'],
2 => ['id' => 2, 'name' => 'Michael', 'parent_item_id' => null, 'is_deleted' => '0'],
],
], $this->getDb());

$entity = $m->loadBy('name', 'Michael');
$entity->delete();
static::assertEquals([
'item' => [
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => null, 'is_deleted' => '0'],
2 => ['id' => 2, 'name' => 'Michael', 'parent_item_id' => null, 'is_deleted' => '1'],
],
], $this->getDb());
}

public function testTitleImport(): void
{
$this->setDb([
Expand Down Expand Up @@ -205,16 +326,16 @@ public function testSameTable(): void
{
$this->setDb([
'item' => [
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => 1],
2 => ['id' => 2, 'name' => 'Sue', 'parent_item_id' => 1],
3 => ['id' => 3, 'name' => 'Smith', 'parent_item_id' => 2],
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => 1, 'is_deleted' => false],
2 => ['id' => 2, 'name' => 'Sue', 'parent_item_id' => 1, 'is_deleted' => false],
3 => ['id' => 3, 'name' => 'Smith', 'parent_item_id' => 2, 'is_deleted' => false],
],
]);

$m = new Model_Item($this->db, ['table' => 'item']);

static::assertSame(
['id' => 3, 'name' => 'Smith', 'parent_item_id' => 2, 'parent_item' => 'Sue'],
['id' => 3, 'name' => 'Smith', 'parent_item_id' => 2, 'parent_item' => 'Sue', 'is_deleted' => false],
$m->load(3)->get()
);
}
Expand Down Expand Up @@ -348,8 +469,8 @@ public function testGetTitle(): void
{
$this->setDb([
'item' => [
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => 1],
2 => ['id' => 2, 'name' => 'Sue', 'parent_item_id' => 1],
1 => ['id' => 1, 'name' => 'John', 'parent_item_id' => 1, 'is_deleted' => false],
2 => ['id' => 2, 'name' => 'Sue', 'parent_item_id' => 1, 'is_deleted' => false],
],
]);

Expand Down

0 comments on commit c2c606b

Please sign in to comment.