Passed
Push — master ( c7d5a7...591597 )
by Lorenzo
17:22
created

Versionable::restoreThrashedVersion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * CalamandreiLorenzo\LaravelVersionable
4
 *
5
 * This file is part of the overtrue/laravel-versionable.
6
 * ------------------------------------------------------
7
 * (c) overtrue <[email protected]>
8
 * This source file is subject to the MIT license that is bundled.
9
 */
10
11
namespace CalamandreiLorenzo\LaravelVersionable;
12
13
use CalamandreiLorenzo\LaravelVersionable\Exceptions\MissingVersionableProperty;
14
use Exception;
15
use Illuminate\Database\Eloquent\Model;
16
use Illuminate\Database\Eloquent\Relations\MorphMany;
17
use Illuminate\Database\Eloquent\Relations\MorphOne;
18
use Illuminate\Support\Collection;
19
use function array_diff_key;
20
use function array_intersect_key;
21
use function array_keys;
22
use function config;
23
use function property_exists;
24
use function optional;
25
26
/**
27
 * Trait Versionable
28
 * @package CalamandreiLorenzo\LaravelVersionable
29
 * @author 安正超 - overtrue
30
 * @github https://github.com/overtrue
31
 * @property-read Collection|Version[] versions
32
 * @property-read Version lastVersion
33
 */
34
trait Versionable
35
{
36
    /**
37
     * @var bool $versioning
38
     */
39
    protected static bool $versioning = true;
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...
40
41
    /**
42
     * @var bool $forceDeleteVersion
43
     */
44
    protected bool $forceDeleteVersion = false;
45
46
    // You can add these properties to you versionable model
47
    //protected $versionable = [];
48
    //protected $dontVersionable = ['*'];
49
50
    /**
51
     * bootVersionable
52
     * @noinspection PhpUnused
53
     * @noinspection UnknownInspectionInspection
54
     */
55 8
    public static function bootVersionable(): void
56
    {
57
        static::saved(static function (Model $model) {
58 8
            self::createVersionForModel($model);
59 8
        });
60
61
        static::deleted(static function (Model $model) {
62
            if (property_exists($model, 'forceDeleting') && $model->forceDeleting) {
63
                /**
64
                 * @var Versionable|Model $model
65
                 */
66
                $model->forceRemoveAllVersions();
67
            } else {
68
                self::createVersionForModel($model);
69
            }
70 8
        });
71 8
    }
72
73
    /**
74
     * createVersionForModel
75
     * @param Versionable|Model $model
76
     * @throws Exceptions\NotVersionableModel
77
     */
78 8
    private static function createVersionForModel(Model $model): void
79
    {
80 8
        if (self::$versioning && $model->shouldVersioning()) {
81 8
            Version::createForModel($model);
82 8
            $model->removeOldVersions($model->getKeepVersionsCount());
83
        }
84 8
    }
85
86
    /**
87
     * versions
88
     * @return MorphMany
89
     */
90 8
    public function versions(): MorphMany
91
    {
92 8
        return $this->morphMany(
93 8
            config('versionable.version_model'),
94 8
            'versionable'
95 8
        )->latest('version_number');
96
    }
97
98
99
    /**
100
     * lastVersion
101
     * @return MorphOne
102
     */
103 6
    public function lastVersion(): MorphOne
104
    {
105 6
        return $this->morphOne(
106 6
            config('versionable.version_model'),
107 6
            'versionable'
108 6
        )->latest('version_number');
109
    }
110
111
    /**
112
     * getVersion
113
     * @param $id
114
     * @return Model|null
115
     */
116
    public function getVersion($id): ?Model
117
    {
118
        return $this->versions()->find($id);
119
    }
120
121
    /**
122
     * getVersion
123
     * @param int $id
124
     * @return Model|null
125
     */
126 1
    public function getVersionByVersionNumber(int $id): ?Model
127
    {
128 1
        return $this->versions()->where('version_number', $id)->first();
129
    }
130
131
    /**
132
     * getThrashedVersions
133
     * @return mixed
134
     */
135 1
    public function getThrashedVersions()
136
    {
137
        /** @noinspection PhpUndefinedMethodInspection */
138 1
        return $this->versions()->onlyTrashed()->get();
139
    }
140
141
    /**
142
     * restoreThrashedVersion
143
     * @param $id
144
     * @return mixed
145
     */
146 1
    public function restoreThrashedVersion($id)
147
    {
148
        /** @noinspection PhpUndefinedMethodInspection */
149 1
        return $this->versions()->onlyTrashed()->whereId($id)->restore();
150
    }
151
152
    /**
153
     * revertToVersion
154
     * @param $id
155
     * @return mixed
156
     */
157
    public function revertToVersion($id)
158
    {
159
        return optional($this->versions()->findOrFail($id))->revert();
160
    }
161
162
    /**
163
     * revertToVersionNumber
164
     * @param int $id
165
     * @return mixed
166
     */
167 1
    public function revertToVersionNumber(int $id)
168
    {
169 1
        return optional(
170 1
            $this->versions()->where('version_number', $id)->firstOrFail()
171 1
        )->revert();
172
    }
173
174
    /**
175
     * removeOldVersions
176
     * @param int $keep
177
     */
178 8
    public function removeOldVersions(int $keep): void
179
    {
180 8
        if ($keep <= 0) {
181 7
            return;
182
        }
183
184
        /** @noinspection PhpUndefinedMethodInspection */
185 1
        $this->versions()->skip($keep)->take(PHP_INT_MAX)->get()->each->delete();
186 1
    }
187
188
    /**
189
     * removeVersions
190
     * @param array $ids
191
     * @return mixed
192
     */
193
    public function removeVersions(array $ids)
194
    {
195
        if ($this->forceDeleteVersion) {
196
            return $this->forceRemoveVersions($ids);
197
        }
198
199
        return $this->versions()->find($ids)->each->delete();
200
    }
201
202
    /**
203
     * removeVersion
204
     * @param $id
205
     * @return bool|mixed|null
206
     * @throws Exception
207
     */
208 2
    public function removeVersion($id)
209
    {
210 2
        if ($this->forceDeleteVersion) {
211 1
            return $this->forceRemoveVersion($id);
212
        }
213
214 1
        return optional($this->versions()->findOrFail($id))->delete();
215
    }
216
217
    /**
218
     * removeAllVersions
219
     */
220 1
    public function removeAllVersions(): void
221
    {
222 1
        if ($this->forceDeleteVersion) {
223
            $this->forceRemoveAllVersions();
224
        }
225
226
        /** @noinspection PhpUndefinedMethodInspection */
227 1
        $this->versions->each->delete();
228 1
    }
229
230
    /**
231
     * forceRemoveVersion
232
     * @param $id
233
     * @return mixed
234
     */
235 1
    public function forceRemoveVersion($id)
236
    {
237 1
        return optional($this->versions()->findOrFail($id))->forceDelete();
238
    }
239
240
    /**
241
     * forceRemoveVersions
242
     * @param array $ids
243
     * @return mixed
244
     */
245
    public function forceRemoveVersions(array $ids)
246
    {
247
        return $this->versions()->find($ids)->each->forceDelete();
248
    }
249
250
    /**
251
     * forceRemoveAllVersions
252
     */
253
    public function forceRemoveAllVersions(): void
254
    {
255
        /** @noinspection PhpUndefinedMethodInspection */
256
        $this->versions->each->forceDelete();
257
    }
258
259
    /**
260
     * shouldVersioning
261
     * @return bool
262
     */
263 8
    public function shouldVersioning(): bool
264
    {
265 8
        return !empty($this->getVersionableAttributes());
266
    }
267
268
    /**
269
     * getVersionableAttributes
270
     * @return array
271
     */
272 8
    public function getVersionableAttributes(): array
273
    {
274 8
        $changes = $this->getDirty();
275
276 8
        if (empty($changes)) {
277
            return [];
278
        }
279
280 8
        $contents = $this->attributesToArray();
281
282 8
        if ($this->getVersionStrategy() === VersionStrategy::DIFF) {
283 8
            $contents = $this->only(array_keys($changes));
284
        }
285
286 8
        return $this->versionableFromArray($contents);
287
    }
288
289
    /**
290
     * setVersionable
291
     * @param array $attributes
292
     * @return $this
293
     * @throws Exception
294
     */
295
    public function setVersionable(array $attributes): self
296
    {
297
        if (!property_exists($this, 'versionable')) {
298
            throw new MissingVersionableProperty('Property $versionable not exist.');
299
        }
300
        $this->versionable = $attributes;
301
        return $this;
302
    }
303
304
    /**
305
     * setDontVersionable
306
     * @param array $attributes
307
     * @return $this
308
     * @throws Exception
309
     */
310
    public function setDontVersionable(array $attributes): self
311
    {
312
        if (!property_exists($this, 'dontVersionable')) {
313
            throw new MissingVersionableProperty('Property $dontVersionable not exist.');
314
        }
315
        $this->dontVersionable = $attributes;
316
        return $this;
317
    }
318
319
    /**
320
     * getVersionable
321
     * @return array
322
     */
323 8
    public function getVersionable(): array
324
    {
325 8
        return property_exists($this, 'versionable') ? $this->versionable : [];
326
    }
327
328
    /**
329
     * getDontVersionable
330
     * @return array
331
     */
332
    public function getDontVersionable(): array
333
    {
334
        return property_exists($this, 'dontVersionable') ? $this->dontVersionable : [];
335
    }
336
337
    /**
338
     * getVersionStrategy
339
     * @return string
340
     */
341 8
    public function getVersionStrategy(): string
342
    {
343 8
        return property_exists($this, 'versionStrategy') ? $this->versionStrategy : VersionStrategy::DIFF;
344
    }
345
346
    /**
347
     * setVersionStrategy
348
     * @param string $strategy
349
     * @return $this
350
     * @throws Exception
351
     */
352 1
    public function setVersionStrategy(string $strategy): self
353
    {
354 1
        if (!property_exists($this, 'versionStrategy')) {
355
            throw new MissingVersionableProperty('Property $versionStrategy not exist.');
356
        }
357 1
        $this->versionStrategy = $strategy;
358 1
        return $this;
359
    }
360
361
    /**
362
     * getVersionModel
363
     * @return mixed
364
     */
365 8
    public function getVersionModel(): string
366
    {
367 8
        return config('versionable.version_model');
368
    }
369
370
    /**
371
     * getKeepVersionsCount
372
     * @return string
373
     */
374 8
    public function getKeepVersionsCount(): string
375
    {
376 8
        return config('versionable.keep_versions', 0);
377
    }
378
379
    /**
380
     * versionableFromArray
381
     * Get the versionable attributes of a given array.
382
     * @param array $attributes
383
     * @return array
384
     */
385 8
    public function versionableFromArray(array $attributes): array
386
    {
387 8
        if (count($this->getVersionable()) > 0) {
388 8
            return array_intersect_key($attributes, array_flip($this->getVersionable()));
389
        }
390
391
        if (count($this->getDontVersionable()) > 0) {
392
            return array_diff_key($attributes, array_flip($this->getDontVersionable()));
393
        }
394
395
        return $attributes;
396
    }
397
398
    /**
399
     * withoutVersion
400
     * @param callable $callback
401
     */
402 1
    public static function withoutVersion(callable $callback): void
403
    {
404 1
        self::$versioning = false;
405 1
        $callback();
406 1
        self::$versioning = true;
407 1
    }
408
409
    /**
410
     * enableForceDeleteVersion
411
     */
412 1
    public function enableForceDeleteVersion(): void
413
    {
414 1
        $this->forceDeleteVersion = true;
415 1
    }
416
417
    /**
418
     * disableForceDeleteVersion
419
     */
420
    public function disableForceDeleteVersion(): void
421
    {
422
        $this->forceDeleteVersion = false;
423
    }
424
}
425