Test Failed
Push — master ( b1cf76...d8fe36 )
by Julien
08:28
created

SoftDelete::isDeleted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 10
cc 1
nc 1
nop 2
crap 2
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Model\Traits;
13
14
use Zemit\Mvc\Model\Behavior\SoftDelete as SoftDeleteBehavior;
15
use Zemit\Mvc\Model\Traits\Abstracts\AbstractBehavior;
16
use Zemit\Mvc\Model\Traits\Abstracts\AbstractEntity;
17
use Zemit\Mvc\Model\Traits\Abstracts\AbstractEventsManager;
18
use Zemit\Mvc\Model\Traits\Abstracts\AbstractModelsManager;
19
use Zemit\Mvc\Model\Traits\Abstracts\AbstractOptions;
20
use Zemit\Mvc\Model\Traits\Abstracts\AbstractSave;
21
22
/**
23
 * This trait provides soft delete functionality to a model class.
24
 * It allows you to mark a record as deleted without actually deleting it from the database.
25
 * When a record is marked as deleted, it won't be retrieved in queries unless explicitly requested.
26
 */
27
trait SoftDelete
28
{
29
    use AbstractBehavior;
30
    use AbstractEntity;
31
    use AbstractModelsManager;
32
    use AbstractEventsManager;
33
    use AbstractOptions;
34
    use AbstractSave;
35
    
36
    protected $skipped = false;
37
    
38
    /**
39
     * Initializing SoftDelete
40
     */
41 56
    public function initializeSoftDelete(?array $options = null): void
42
    {
43 56
        $options ??= $this->getOptionsManager()->get('softDelete') ?? [];
44
        
45 56
        $options['field'] ??= 'deleted';
46 56
        $options['value'] ??= 1;
47
        
48 56
        $this->setSoftDeleteBehavior(new SoftDeleteBehavior($options));
49
    }
50
    
51
    /**
52
     * Set the SoftDeleteBehavior variable
53
     * Attach the SoftDelete behavior class
54
     */
55 56
    public function setSoftDeleteBehavior(SoftDeleteBehavior $softDeleteBehavior): void
56
    {
57 56
        $this->setBehavior('softDelete', $softDeleteBehavior);
58
    }
59
    
60
    /**
61
     * Return the soft delete behavior instance
62
     */
63
    public function getSoftDeleteBehavior(): SoftDeleteBehavior
64
    {
65
        $behavior = $this->getBehavior('softDelete');
66
        assert($behavior instanceof SoftDeleteBehavior);
67
        return $behavior;
68
    }
69
    
70
    /**
71
     * Disable the soft delete for the current instance
72
     * Note: Zemit SoftDelete behavior must be attached
73
     */
74
    public function disableSoftDelete(): void
75
    {
76
        $this->getSoftDeleteBehavior()->disable();
77
    }
78
    
79
    /**
80
     * Enable the soft delete for the current instance
81
     * Note: Zemit SoftDelete behavior must be attached
82
     */
83
    public function enableSoftDelete(): void
84
    {
85
        $this->getSoftDeleteBehavior()->enable();
86
    }
87
    
88
    /**
89
     * Helper method to check if the row is soft deleted
90
     */
91
    public function isDeleted(?string $field = null, ?int $deletedValue = null): bool
92
    {
93
        $field ??= $this->getSoftDeleteBehavior()->getField();
94
        $deletedValue ??= $this->getSoftDeleteBehavior()->getValue();
95
        return $this->readAttribute($field) === $deletedValue;
96
    }
97
    
98
    /**
99
     * Restore a previously Soft-deleted entry and fire events
100
     * Events:
101
     * - beforeRestore
102
     * - notRestored
103
     * - afterRestore
104
     *
105
     * @todo add a check from orm.events setup state
106
     */
107
    public function restore(?string $field = null, ?int $notDeletedValue = null): bool
108
    {
109
        $ormEvents = (bool)ini_get('phalcon.orm.events');
110
        
111
        if ($ormEvents) {
112
            $this->skipped = false;
113
            
114
            // fire event, allowing to stop options or skip the current operation
115
            if ($this->fireEventCancel('beforeRestore') === false) {
116
                return false;
117
            }
118
            
119
            /**
120
             * Can be modified by the previous event
121
             * @psalm-suppress TypeDoesNotContainType
122
             * @phpstan-ignore-next-line
123
             */
124
            if ($this->skipped) {
125
                return true;
126
            }
127
        }
128
        
129
        $field ??= $this->getSoftDeleteBehavior()->getField();
130
        $notDeletedValue ??= 0;
131
        
132
        // restore (unset soft delete value and save)
133
        $this->writeAttribute($field, $notDeletedValue);
134
        $save = $this->save();
135
        
136
        // check if the entity is restored
137
        $value = $this->readAttribute($field);
138
        $restored = $save && $value === $notDeletedValue;
139
        
140
        // fire events
141
        if ($ormEvents) {
142
            if (!$restored) {
143
                $this->fireEvent('notRestored');
144
            }
145
            else {
146
                $this->fireEvent('afterRestore');
147
            }
148
        }
149
        
150
        return $restored;
151
    }
152
}
153