Passed
Branch dev_2x (3e8772)
by Adrian
01:42
created

SoftDeleteObserver   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 8
eloc 42
c 1
b 0
f 0
dl 0
loc 126
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm\CodeGenerator\Observer\Behaviour;
5
6
use Nette\PhpGenerator\ClassType;
7
use Sirius\Orm\Blueprint\Behaviour\SoftDelete;
8
use Sirius\Orm\Blueprint\Behaviour\Timestamps;
9
use Sirius\Orm\CodeGenerator\Observer\Base;
10
use Sirius\Orm\Query\SoftDeleteTrait;
11
12
class SoftDeleteObserver extends Base
13
{
14
    /**
15
     * @var SoftDelete
16
     */
17
    protected $behaviour;
18
19
    public function with(SoftDelete $behaviour)
20
    {
21
        $clone            = clone($this);
22
        $clone->behaviour = $behaviour;
23
24
        return $clone;
25
    }
26
27
28
    public function observe(string $key, $object)
29
    {
30
        if ($key == $this->behaviour->getMapper()->getName() . '_base_mapper') {
31
            return $this->observeBaseMapperClass($object);
32
        }
33
        if ($key == $this->behaviour->getMapper()->getName() . '_base_query') {
34
            return $this->observeBaseQueryClass($object);
35
        }
36
37
        return $object;
38
    }
39
40
    public function __toString()
41
    {
42
        return sprintf(
43
            'Observer for behaviour %s of mapper %s',
44
            $this->behaviour->getName(),
45
            $this->behaviour->getMapper()->getName()
46
        );
47
    }
48
49
50
51
    public function observeBaseMapperClass(ClassType $class): ClassType
52
    {
53
        /** @scrutinizer ignore-deprecated */ $class->getNamespace()->addUse(\Sirius\Orm\Action\SoftDelete::class, 'SoftDeleteAction');
54
        /** @scrutinizer ignore-deprecated */ $class->getNamespace()->addUse(\Sirius\Orm\Action\Delete::class, 'DeleteAction');
55
        /** @scrutinizer ignore-deprecated */ $class->getNamespace()->addUse(\Sirius\Orm\Action\Update::class, 'UpdateAction');
56
        $class->addProperty('deletedAtColumn', $this->behaviour->getDeletedAtColumn())
57
              ->setVisibility('protected');
58
59
        //
60
        $method = $class->addMethod('newDeleteAction');
61
        $method->addParameter('entity')->setType($this->behaviour->getMapper()->getEntityClass());
62
        $method->addParameter('options');
63
        $method->setBody('
64
$options = array_merge((array) $options, [\'deleted_at_column\' => $this->deletedAtColumn]);         
65
$action = new SoftDeleteAction($this, $entity, $options);
66
67
return $this->behaviours->apply($this, __FUNCTION__, $action);           
68
            ');
69
70
        $method = $class->addMethod('forceDelete');
71
        $method->addParameter('entity')->setType($this->behaviour->getMapper()->getEntityClass());
72
        $method->addParameter('withRelations', false);
73
        $method->setBody('
74
$action = new DeleteAction($this, $entity, [\'relations\' => $withRelations]);
75
76
$this->connectionLocator->lockToWrite(true);
77
$this->getWriteConnection()->beginTransaction();
78
try {
79
    $action->run();
80
    $this->getWriteConnection()->commit();
81
82
    return true;
83
} catch (\Exception $e) {
84
    $this->getWriteConnection()->rollBack();
85
    throw $e;
86
}
87
        ');
88
89
        $method = $class->addMethod('restore')->setReturnType('bool');
90
        $method->addParameter('pk');
91
        $method->setBody('
92
$entity = $this->newQuery()
93
               ->withTrashed()
94
               ->find($pk);
95
96
if ( ! $entity) {
97
    return false;
98
}
99
100
$this->getHydrator()->set($entity, $this->deletedAtColumn, null);
101
$action = new UpdateAction($this, $entity);
102
103
$this->connectionLocator->lockToWrite(true);
104
$this->getWriteConnection()->beginTransaction();
105
try {
106
    $action->run();
107
    $this->getWriteConnection()->commit();
108
109
    return true;
110
} catch (\Exception $e) {
111
    $this->getWriteConnection()->rollBack();
112
    throw $e;
113
}
114
        ');
115
116
        return $class;
117
    }
118
119
    public function observeBaseQueryClass(ClassType $class): ClassType
120
    {
121
        $class->addProperty('deletedAtColumn', $this->behaviour->getDeletedAtColumn())
122
              ->setVisibility('protected');
123
124
        // add guard
125
        if (! $class->hasMethod('init')) {
126
            $class->addMethod('init')
127
                  ->setVisibility(ClassType::VISIBILITY_PROTECTED)
128
                  ->setBody('parent::init();' . PHP_EOL);
129
        }
130
        $init = $class->getMethod('init');
131
        $init->addBody('$this->withoutTrashed();' . PHP_EOL);
132
133
        /** @scrutinizer ignore-deprecated */ $class->getNamespace()->addUse(SoftDeleteTrait::class, null, $traitAlias);
134
135
        $class->addTrait($traitAlias);
136
137
        return $class;
138
    }
139
}
140