Passed
Push — master ( fa9158...36c463 )
by Carlos
02:09
created

Versionable::getVersionStrategy()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
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
    // You can add these properties to you versionable model
20
    //protected $versionable = [];
21
    //protected $dontVersionable = ['*'];
22
23 5
    public static function bootVersionable()
24
    {
25
        static::saved(function (Model $model) {
26 5
            self::createVersionForModel($model);
27 5
        });
28
29
        static::deleted(function (Model $model) {
30
            if ($model->forceDeleting) {
31
                $model->removeAllVersions();
32
            } else {
33
                self::createVersionForModel($model);
34
            }
35 5
        });
36 5
    }
37
38 5
    private static function createVersionForModel(Model $model): void
39
    {
40 5
        if ($model->shouldVersioning()) {
41 5
            Version::createForModel($model);
42 5
            $model->removeOldVersions($model->getKeepVersionsCount());
43
        }
44 5
    }
45
46
    /**
47
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
48
     */
49 5
    public function versions(): MorphMany
50
    {
51 5
        return $this->morphMany(\config('versionable.version_model'), 'versionable')->latest('id');
0 ignored issues
show
Bug introduced by
It seems like morphMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
52
    }
53
54
    /**
55
     * @return \Illuminate\Database\Eloquent\Relations\MorphOne
56
     */
57 3
    public function lastVersion(): MorphOne
58
    {
59 3
        return $this->morphOne(\config('versionable.version_model'), 'versionable')->latest('id');
0 ignored issues
show
Bug introduced by
It seems like morphOne() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
60
    }
61
62
    /**
63
     * @param int $id
64
     *
65
     * @return \Illuminate\Database\Eloquent\Model|null
66
     */
67 1
    public function getVersion($id)
68
    {
69 1
        return $this->versions()->find($id);
70
    }
71
72
    /**
73
     * @param int $id
74
     *
75
     * @return mixed
76
     */
77 1
    public function revertToVersion($id)
78
    {
79 1
        return $this->versions()->findOrFail($id)->revert();
80
    }
81
82
    /**
83
     * @param int $keep
84
     */
85 5
    public function removeOldVersions(int $keep): void
86
    {
87 5
        if ($keep <= 0) {
88 4
            return;
89
        }
90
91 1
        $this->versions()->skip($keep)->take($keep)->get()->each->delete();
92 1
    }
93
94 1
    public function removeAllVersions()
95
    {
96 1
        $this->versions->each->delete();
0 ignored issues
show
Bug introduced by
The property versions does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
97 1
    }
98
99
    /**
100
     * @return bool
101
     */
102 5
    public function shouldVersioning(): bool
103
    {
104 5
        return !empty($this->getVersionableAttributes());
105
    }
106
107
    /**
108
     * @return array
109
     */
110 5
    public function getVersionableAttributes(): array
111
    {
112 5
        $changes = $this->getDirty();
0 ignored issues
show
Bug introduced by
It seems like getDirty() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
113
114 5
        if (empty($changes)) {
115
            return [];
116
        }
117
118 5
        switch ($this->getVersionStrategy()) {
119 5
            case VersionStrategy::DIFF:
120 5
                $contents = $changes;
121 5
                break;
122 1
            case VersionStrategy::SNAPSHOT:
123 1
                $contents = $this->attributesToArray();
0 ignored issues
show
Bug introduced by
It seems like attributesToArray() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
124 1
                break;
125
            default:
126
                $contents = $changes;
127
        }
128
129 5
        return $this->versionableFromArray($contents);
130
    }
131
132
    /**
133
     * @param array $attributes
134
     *
135
     * @return $this
136
     *
137
     * @throws \Exception
138
     */
139
    public function setVersionable(array $attributes)
140
    {
141
        if (!\property_exists($this, 'versionable')) {
142
            throw new \Exception('Property $versionable not exist.');
143
        }
144
145
        $this->versionable = $attributes;
0 ignored issues
show
Bug introduced by
The property versionable does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
146
147
        return $this;
148
    }
149
150
    /**
151
     * @param array $attributes
152
     *
153
     * @return $this
154
     *
155
     * @throws \Exception
156
     */
157
    public function setDontVersionable(array $attributes)
158
    {
159
        if (!\property_exists($this, 'dontVersionable')) {
160
            throw new \Exception('Property $dontVersionable not exist.');
161
        }
162
163
        $this->dontVersionable = $attributes;
0 ignored issues
show
Bug introduced by
The property dontVersionable does not seem to exist. Did you mean versionable?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
164
165
        return $this;
166
    }
167
168
    /**
169
     * @return array
170
     */
171 5
    public function getVersionable(): array
172
    {
173 5
        return \property_exists($this, 'versionable') ? $this->versionable : [];
174
    }
175
176
    /**
177
     * @return array
178
     */
179
    public function getDontVersionable(): array
180
    {
181
        return \property_exists($this, 'dontVersionable') ? $this->dontVersionable : [];
0 ignored issues
show
Bug introduced by
The property dontVersionable does not seem to exist. Did you mean versionable?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
182
    }
183
184
    /**
185
     * @return string
186
     */
187 5
    public function getVersionStrategy()
188
    {
189 5
        return \property_exists($this, 'versionStrategy') ? $this->versionStrategy : VersionStrategy::DIFF;
0 ignored issues
show
Bug introduced by
The property versionStrategy does not seem to exist. Did you mean versions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
190
    }
191
192
    /**
193
     * @param string $strategy
194
     *
195
     * @return $this
196
     *
197
     * @throws \Exception
198
     */
199 1
    public function setVersionStrategy(string $strategy)
200
    {
201 1
        if (!\property_exists($this, 'versionStrategy')) {
202
            throw new \Exception('Property $versionStrategy not exist.');
203
        }
204
205 1
        $this->versionStrategy = $strategy;
0 ignored issues
show
Bug introduced by
The property versionStrategy does not seem to exist. Did you mean versions?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
206
207 1
        return $this;
208
    }
209
210
    /**
211
     * @return string
212
     */
213 5
    public function getVersionModel(): string
214
    {
215 5
        return config('versionable.version_model');
216
    }
217
218
    /**
219
     * @return string
220
     */
221 5
    public function getKeepVersionsCount(): string
222
    {
223 5
        return config('versionable.keep_versions', 0);
224
    }
225
226
    /**
227
     * Get the versionable attributes of a given array.
228
     *
229
     * @param array $attributes
230
     *
231
     * @return array
232
     */
233 5
    public function versionableFromArray(array $attributes): array
234
    {
235 5
        if (count($this->getVersionable()) > 0) {
236 5
            return \array_intersect_key($attributes, array_flip($this->getVersionable()));
237
        }
238
239
        if (count($this->getDontVersionable()) > 0) {
240
            return \array_diff_key($attributes, array_flip($this->getDontVersionable()));
241
        }
242
243
        return $attributes;
244
    }
245
}
246