Passed
Pull Request — master (#5)
by Maksim
04:51 queued 01:17
created

HasCompositePrimaryKey::hasGetMutator()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 3
nc 2
nop 1
1
<?php
2
3
namespace MaksimM\CompositePrimaryKeys\Http\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Arr;
8
use MaksimM\CompositePrimaryKeys\Eloquent\CompositeKeyQueryBuilder;
9
use MaksimM\CompositePrimaryKeys\Exceptions\MissingPrimaryKeyValueException;
10
use MaksimM\CompositePrimaryKeys\Exceptions\WrongKeyException;
11
use MaksimM\CompositePrimaryKeys\Scopes\CompositeKeyScope;
12
13
trait HasCompositePrimaryKey
14
{
15
    use NormalizedKeysParser, PrimaryKeyInformation, CompositeRelationships;
16
17
    protected $hexBinaryColumns = false;
18
19
    /**
20
     * Destroy the models for the given IDs.
21
     *
22
     * @param array|int $ids
23
     *
24
     * @return int
25
     */
26
    public static function destroy($ids)
27
    {
28
        // We'll initialize a count here so we will return the total number of deletes
29
        // for the operation. The developers can then check this number as a boolean
30
        // type value or get this total count of records deleted for logging, etc.
31
        $count = 0;
32
33
        $ids = is_array($ids) ? $ids : func_get_args();
34
35
        foreach ((new static())->applyIds($ids)->get() as $model) {
0 ignored issues
show
Bug introduced by
It seems like applyIds() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

35
        foreach ((new static())->/** @scrutinizer ignore-call */ applyIds($ids)->get() as $model) {
Loading history...
36
            if ($model->delete()) {
37
                $count++;
38
            }
39
        }
40
41
        return $count;
42
    }
43
44
    /**
45
     * Convert the object into something JSON serializable.
46
     *
47
     * @return array
48
     */
49
    public function jsonSerialize()
50
    {
51
        $attributes = $this->toArray();
0 ignored issues
show
Bug introduced by
It seems like toArray() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
        /** @scrutinizer ignore-call */ 
52
        $attributes = $this->toArray();
Loading history...
52
        foreach ($attributes as $key => $value) {
53
            if (in_array($key, $this->getBinaryColumns())) {
54
                $attributes[$key] = strtoupper(bin2hex($value));
55
            }
56
        }
57
58
        // append virtual row id
59
        if (count($this->getRawKeyName()) > 1) {
60
            $attributes[$this->getNormalizedKeyName()] = $this->getNormalizedKey();
61
        }
62
63
        return $attributes;
64
    }
65
66
    /**
67
     * Get the primary key for the model.
68
     *
69
     * @return array
70
     */
71
    public function getRawKeyName()
72
    {
73
        return $this->hasCompositeIndex() ? $this->primaryKey : [$this->primaryKey];
74
    }
75
76
    /**
77
     * Get the value of the model's primary key.
78
     *
79
     * @return mixed
80
     */
81
    public function getRawKey()
82
    {
83
        $attributes = [];
84
85
        foreach ($this->getRawKeyName() as $key) {
86
            $attributes[$key] = $this->getAttribute($key);
0 ignored issues
show
Bug introduced by
It seems like getAttribute() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
            /** @scrutinizer ignore-call */ 
87
            $attributes[$key] = $this->getAttribute($key);
Loading history...
87
        }
88
89
        return $attributes;
90
    }
91
92
    /**
93
     * Get the value indicating whether the IDs are incrementing.
94
     *
95
     * @return bool
96
     */
97
    public function getIncrementing()
98
    {
99
        return false;
100
    }
101
102
    /**
103
     * Get the primary key for the model.
104
     *
105
     * @return string
106
     */
107
    public function getKeyName()
108
    {
109
        return $this->getNormalizedKeyName();
110
    }
111
112
    /**
113
     * Get virtual string key, required for proper collection support.
114
     *
115
     * @return mixed
116
     */
117
    public function getKey()
118
    {
119
        return $this->getNormalizedKey();
120
    }
121
122
    /**
123
     * @param \Illuminate\Database\Query\Builder $query
124
     * @param array|string                       $ids
125
     * @param bool                               $inverse
126
     *
127
     * @throws MissingPrimaryKeyValueException
128
     * @throws WrongKeyException
129
     */
130
    public function scopeApplyIds($query, $ids, $inverse = false)
131
    {
132
        $keys = ($instance = new static())->getRawKeyName();
0 ignored issues
show
Unused Code introduced by
The assignment to $instance is dead and can be removed.
Loading history...
133
134
        if (!is_array($ids) || Arr::isAssoc($ids)) {
135
            $ids = [$ids];
136
        }
137
138
        if ($this->hasCompositeIndex()) {
139
            (new CompositeKeyScope($keys, $ids, $inverse, $this->getBinaryColumns()))->apply($query);
140
        } else {
141
            //remap hex ID to binary ID even if index is not composite
142
            if ($this->shouldProcessBinaryAttribute($keys[0])) {
143
                $ids = array_map(function ($hex) {
144
                    return hex2bin($hex);
145
                }, $ids);
146
            }
147
            if ($inverse) {
148
                $query->whereNotIn($this->qualifyColumn($keys[0]), $ids);
0 ignored issues
show
Bug introduced by
It seems like qualifyColumn() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

148
                $query->whereNotIn($this->/** @scrutinizer ignore-call */ qualifyColumn($keys[0]), $ids);
Loading history...
149
            } else {
150
                $query->whereIn($this->qualifyColumn($keys[0]), $ids);
151
            }
152
        }
153
    }
154
155
    /**
156
     * Get a new query to restore one or more models by their queueable IDs.
157
     *
158
     * @param array|int $ids
159
     *
160
     *@throws WrongKeyException
161
     * @throws MissingPrimaryKeyValueException
162
     *
163
     * @return Builder
164
     */
165
    public function newQueryForRestoration($ids)
166
    {
167
        if (!is_array($ids)) {
168
            $ids = [$ids];
169
        }
170
171
        return $this->newQueryWithoutScopes()->applyIds(
0 ignored issues
show
Bug introduced by
It seems like newQueryWithoutScopes() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

171
        return $this->/** @scrutinizer ignore-call */ newQueryWithoutScopes()->applyIds(
Loading history...
172
            array_map(
173
                function ($normalizedKey) {
174
                    return $this->parseNormalizedKey($normalizedKey);
175
                },
176
                $ids
177
            )
178
        );
179
    }
180
181
    /**
182
     * @param \Illuminate\Database\Query\Builder $query
183
     *
184
     * @return Builder|static
185
     */
186
    public function newEloquentBuilder($query)
187
    {
188
        return new CompositeKeyQueryBuilder($query);
189
    }
190
191
    public function hexBinaryColumns()
192
    {
193
        return $this->hexBinaryColumns;
194
    }
195
196
    public function getBinaryColumns()
197
    {
198
        return $this->binaryColumns ?? [];
199
    }
200
201
    /**
202
     * Get the primary key value for a save query.
203
     *
204
     * @return mixed
205
     */
206
    protected function getKeyForSaveQuery()
207
    {
208
        $originalKeys = array_intersect_key($this->original, array_flip($this->getRawKeyName()));
209
210
        return array_merge($this->getRawKey(), $originalKeys);
211
    }
212
213
    /**
214
     * Set the keys for a save update query.
215
     *
216
     * @param Builder $query
217
     *
218
     *@throws MissingPrimaryKeyValueException
219
     *
220
     * @return Builder
221
     */
222
    protected function setKeysForSaveQuery(Builder $query)
223
    {
224
        foreach ($this->getRawKeyName() as $key) {
225
            if (isset($this->{$key})) {
226
                $query->where($key, '=', $this->getAttributeFromArray($key));
0 ignored issues
show
Bug introduced by
It seems like getAttributeFromArray() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

226
                $query->where($key, '=', $this->/** @scrutinizer ignore-call */ getAttributeFromArray($key));
Loading history...
227
            } else {
228
                throw new MissingPrimaryKeyValueException($key, 'Missing value for key '.$key);
229
            }
230
        }
231
232
        return $query;
233
    }
234
235
    /**
236
     * Run the increment or decrement method on the model.
237
     *
238
     * @param string    $column
239
     * @param float|int $amount
240
     * @param array     $extra
241
     * @param string    $method
242
     *
243
     * @return int
244
     */
245
    protected function incrementOrDecrement($column, $amount, $extra, $method)
246
    {
247
        $query = $this->newQuery();
0 ignored issues
show
Bug introduced by
The method newQuery() does not exist on MaksimM\CompositePrimary...\HasCompositePrimaryKey. Did you maybe mean newQueryForRestoration()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
        /** @scrutinizer ignore-call */ 
248
        $query = $this->newQuery();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
248
249
        if (!$this->exists) {
250
            return $query->{$method}($column, $amount, $extra);
251
        }
252
253
        $this->incrementOrDecrementAttributeValue($column, $amount, $extra, $method);
0 ignored issues
show
Bug introduced by
The method incrementOrDecrementAttributeValue() does not exist on MaksimM\CompositePrimary...\HasCompositePrimaryKey. Did you maybe mean incrementOrDecrement()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

253
        $this->/** @scrutinizer ignore-call */ 
254
               incrementOrDecrementAttributeValue($column, $amount, $extra, $method);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
254
255
        foreach ($this->getRawKeyName() as $key) {
256
            $query->where($key, $this->getAttribute($key));
257
        }
258
259
        return $query->{$method}($column, $amount, $extra);
260
    }
261
262
    /**
263
     * Retrieve the model for a bound value.
264
     *
265
     * @param mixed $value
266
     *
267
     * @return Model|null
268
     */
269
    public function resolveRouteBinding($value)
270
    {
271
        if ($this->hasCompositeIndex() && $this->getRouteKeyName() == $this->getKeyName()) {
0 ignored issues
show
Bug introduced by
It seems like getRouteKeyName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

271
        if ($this->hasCompositeIndex() && $this->/** @scrutinizer ignore-call */ getRouteKeyName() == $this->getKeyName()) {
Loading history...
272
            return $this->whereKey($value)->first();
0 ignored issues
show
Bug introduced by
It seems like whereKey() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

272
            return $this->/** @scrutinizer ignore-call */ whereKey($value)->first();
Loading history...
273
        } else {
274
            return $this->where($this->getRouteKeyName(), $value)->first();
0 ignored issues
show
Bug introduced by
It seems like where() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

274
            return $this->/** @scrutinizer ignore-call */ where($this->getRouteKeyName(), $value)->first();
Loading history...
275
        }
276
    }
277
278
    private function shouldProcessBinaryAttribute($key)
279
    {
280
        return $this->hexBinaryColumns() && in_array($key, $this->getBinaryColumns());
281
    }
282
283
    public function hasGetMutator($key)
284
    {
285
        if ($this->shouldProcessBinaryAttribute($key) && isset($this->{$key})) {
286
            return true;
287
        }
288
289
        return parent::hasGetMutator($key);
290
    }
291
292
    public function mutateAttribute($key, $value)
293
    {
294
        if ($this->shouldProcessBinaryAttribute($key)) {
295
            return strtoupper(bin2hex($value));
296
        }
297
298
        return parent::mutateAttribute($key, $value);
299
    }
300
301
    public function hasSetMutator($key)
302
    {
303
        if ($this->shouldProcessBinaryAttribute($key)) {
304
            return true;
305
        }
306
307
        return parent::hasSetMutator($key);
308
    }
309
310
    public function setMutatedAttributeValue($key, $value)
311
    {
312
        if ($this->shouldProcessBinaryAttribute($key)) {
313
            $value = hex2bin($value);
314
            $this->attributes[$key] = $value;
0 ignored issues
show
Bug Best Practice introduced by
The property attributes does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
315
316
            return $value;
317
        }
318
319
        return parent::setMutatedAttributeValue($key, $value);
320
    }
321
}
322