Test Setup Failed
Push — master ( 7669e9...96ce6d )
by Carlos
03:17 queued 01:14
created

Versionable::bootVersionable()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.2109

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 5
cts 8
cp 0.625
rs 9.7998
c 0
b 0
f 0
cc 2
nc 1
nop 0
crap 2.2109
1
<?php
2
3
/*
4
 * This file is part of the overtrue/laravel-versionable.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled.
9
 */
10
11
namespace Overtrue\LaravelVersionable;
12
13
use Illuminate\Database\Eloquent\Model;
14
use Illuminate\Database\Eloquent\Relations\MorphMany;
15
use Illuminate\Database\Eloquent\Relations\MorphOne;
16
17
trait Versionable
18
{
19
    static protected $versioning = true;
20
    protected bool $forceDeleteVersion = false;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
21
22
    // You can add these properties to you versionable model
23
    //protected $versionable = [];
24
    //protected $dontVersionable = ['*'];
25 6
26
    public static function bootVersionable()
27
    {
28 6
        static::saved(function (Model $model) {
29 6
            self::createVersionForModel($model);
30
        });
31
32
        static::deleted(function (Model $model) {
33
            if ($model->forceDeleting) {
34
                $model->forceRemoveAllVersions();
35
            } else {
36
                self::createVersionForModel($model);
37 6
            }
38 6
        });
39
    }
40 6
41
    private static function createVersionForModel(Model $model): void
42 6
    {
43 6
        if (self::$versioning && $model->shouldVersioning()) {
44 6
            Version::createForModel($model);
45
            $model->removeOldVersions($model->getKeepVersionsCount());
46 6
        }
47
    }
48
49
    /**
50
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
51 6
     */
52
    public function versions(): MorphMany
53 6
    {
54
        return $this->morphMany(\config('versionable.version_model'), 'versionable')->latest('id');
55
    }
56
57
    /**
58
     * @return \Illuminate\Database\Eloquent\Relations\MorphOne
59 4
     */
60
    public function lastVersion(): MorphOne
61 4
    {
62
        return $this->morphOne(\config('versionable.version_model'), 'versionable')->latest('id');
63
    }
64
65
    /**
66
     * @param int $id
67
     *
68
     * @return \Illuminate\Database\Eloquent\Model|null
69 1
     */
70
    public function getVersion(int $id)
71 1
    {
72
        return $this->versions()->find($id);
73
    }
74
75
    public function getThrashedVersions()
76
    {
77
        return $this->versions()->onlyTrashed()->get();
78
    }
79 1
80
    public function restoreThrashedVersion(int $id)
81 1
    {
82
        return $this->versions()->onlyTrashed()->whereId($id)->restore();
83
    }
84
85
    /**
86
     * @param int $id
87 6
     *
88
     * @return mixed
89 6
     */
90 5
    public function revertToVersion(int $id)
91
    {
92
        return $this->versions()->findOrFail($id)->revert();
93 1
    }
94 1
95
    /**
96 1
     * @param int $keep
97
     */
98 1
    public function removeOldVersions(int $keep): void
99 1
    {
100
        if ($keep <= 0) {
101
            return;
102
        }
103
104 6
        $this->versions()->skip($keep)->take(PHP_INT_MAX)->get()->each->delete();
105
    }
106 6
107
    public function removeVersions(array $ids)
108
    {
109
        if ($this->forceDeleteVersion) {
110
            return $this->forceRemoveVersions($ids);
111
        }
112 6
113
        return $this->versions()->find($ids)->each->delete();
114 6
    }
115
116 6
    public function removeVersion(int $id)
117
    {
118
        if ($this->forceDeleteVersion) {
119
            return $this->forceRemoveVersion($id);
120 6
        }
121 6
122 6
        return $this->versions()->findOrFail($id)->delete();
123 6
    }
124 1
125 1
    public function removeAllVersions()
126 1
    {
127
        if ($this->forceDeleteVersion) {
128
            $this->forceRemoveAllVersions();
129
        }
130
131 6
        $this->versions->each->delete();
132
    }
133
134
    public function forceRemoveVersion(int $id)
135
    {
136
        return $this->versions()->findOrFail($id)->forceDelete();
137
    }
138
139
    public function forceRemoveVersions(array $ids)
140
    {
141
        return $this->versions()->find($ids)->each->forceDelete();
142
    }
143
144
    public function forceRemoveAllVersions()
145
    {
146
        $this->versions->each->forceDelete();
147
    }
148
149
    /**
150
     * @return bool
151
     */
152
    public function shouldVersioning(): bool
153
    {
154
        return !empty($this->getVersionableAttributes());
155
    }
156
157
    /**
158
     * @return array
159
     */
160
    public function getVersionableAttributes(): array
161
    {
162
        $changes = $this->getDirty();
163
164
        if (empty($changes)) {
165
            return [];
166
        }
167
168
        switch ($this->getVersionStrategy()) {
169
            case VersionStrategy::DIFF:
170
                $contents = $changes;
171
                break;
172
            case VersionStrategy::SNAPSHOT:
173 6
                $contents = $this->attributesToArray();
174
                break;
175 6
            default:
176
                $contents = $changes;
177
        }
178
179
        return $this->versionableFromArray($contents);
180
    }
181
182
    /**
183
     * @param array $attributes
184
     *
185
     * @return $this
186
     *
187
     * @throws \Exception
188
     */
189 6
    public function setVersionable(array $attributes)
190
    {
191 6
        if (!\property_exists($this, 'versionable')) {
192
            throw new \Exception('Property $versionable not exist.');
193
        }
194
195
        $this->versionable = $attributes;
196
197
        return $this;
198
    }
199
200
    /**
201 1
     * @param array $attributes
202
     *
203 1
     * @return $this
204
     *
205
     * @throws \Exception
206
     */
207 1
    public function setDontVersionable(array $attributes)
208
    {
209 1
        if (!\property_exists($this, 'dontVersionable')) {
210
            throw new \Exception('Property $dontVersionable not exist.');
211
        }
212
213
        $this->dontVersionable = $attributes;
214
215 6
        return $this;
216
    }
217 6
218
    /**
219
     * @return array
220
     */
221
    public function getVersionable(): array
222
    {
223 6
        return \property_exists($this, 'versionable') ? $this->versionable : [];
224
    }
225 6
226
    /**
227
     * @return array
228
     */
229
    public function getDontVersionable(): array
230
    {
231
        return \property_exists($this, 'dontVersionable') ? $this->dontVersionable : [];
232
    }
233
234
    /**
235 6
     * @return string
236
     */
237 6
    public function getVersionStrategy()
238 6
    {
239
        return \property_exists($this, 'versionStrategy') ? $this->versionStrategy : VersionStrategy::DIFF;
240
    }
241
242
    /**
243
     * @param string $strategy
244
     *
245
     * @return $this
246
     *
247
     * @throws \Exception
248
     */
249
    public function setVersionStrategy(string $strategy)
250
    {
251 1
        if (!\property_exists($this, 'versionStrategy')) {
252
            throw new \Exception('Property $versionStrategy not exist.');
253 1
        }
254
255 1
        $this->versionStrategy = $strategy;
256
257 1
        return $this;
258 1
    }
259
260
    /**
261
     * @return string
262
     */
263
    public function getVersionModel(): string
264
    {
265
        return config('versionable.version_model');
266
    }
267
268
    /**
269
     * @return string
270
     */
271
    public function getKeepVersionsCount(): string
272
    {
273
        return config('versionable.keep_versions', 0);
274
    }
275
276
    /**
277
     * Get the versionable attributes of a given array.
278
     *
279
     * @param array $attributes
280
     *
281
     * @return array
282
     */
283
    public function versionableFromArray(array $attributes): array
284
    {
285
        if (count($this->getVersionable()) > 0) {
286
            return \array_intersect_key($attributes, array_flip($this->getVersionable()));
287
        }
288
289
        if (count($this->getDontVersionable()) > 0) {
290
            return \array_diff_key($attributes, array_flip($this->getDontVersionable()));
291
        }
292
293
        return $attributes;
294
    }
295
296
    /**
297
     * @param callable $callback
298
     */
299
    public static function withoutVersion(callable $callback)
300
    {
301
        self::$versioning = false;
302
303
        \call_user_func($callback);
304
305
        self::$versioning = true;
306
    }
307
}
308