Passed
Push — master ( d8e957...a3e243 )
by Maksim
03:45
created

HasCompositePrimaryKey::scopeApplyIds()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 17
rs 9.6111
c 0
b 0
f 0
cc 5
nc 6
nop 3
1
<?php
2
3
namespace MaksimM\CompositePrimaryKeys\Http\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Support\Arr;
7
use MaksimM\CompositePrimaryKeys\Eloquent\CompositeKeyQueryBuilder;
8
use MaksimM\CompositePrimaryKeys\Exceptions\MissingPrimaryKeyValueException;
9
use MaksimM\CompositePrimaryKeys\Exceptions\WrongKeyException;
10
use MaksimM\CompositePrimaryKeys\Scopes\CompositeKeyScope;
11
12
trait HasCompositePrimaryKey
13
{
14
    use NormalizedKeysParser, PrimaryKeyInformation, CompositeRelationships;
15
16
    /**
17
     * Destroy the models for the given IDs.
18
     *
19
     * @param array|int $ids
20
     *
21
     * @return int
22
     */
23
    public static function destroy($ids)
24
    {
25
        // We'll initialize a count here so we will return the total number of deletes
26
        // for the operation. The developers can then check this number as a boolean
27
        // type value or get this total count of records deleted for logging, etc.
28
        $count = 0;
29
30
        $ids = is_array($ids) ? $ids : func_get_args();
31
32
        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

32
        foreach ((new static())->/** @scrutinizer ignore-call */ applyIds($ids)->get() as $model) {
Loading history...
33
            if ($model->delete()) {
34
                $count++;
35
            }
36
        }
37
38
        return $count;
39
    }
40
41
    /**
42
     * Convert the object into something JSON serializable.
43
     *
44
     * @return array
45
     */
46
    public function jsonSerialize()
47
    {
48
        $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

48
        /** @scrutinizer ignore-call */ 
49
        $attributes = $this->toArray();
Loading history...
49
        foreach ($attributes as $key => $value) {
50
            if (in_array($key, $this->getBinaryColumns())) {
51
                $attributes[$key] = strtoupper(bin2hex($value));
52
            }
53
        }
54
55
        // append virtual row id
56
        if (count($this->getRawKeyName()) > 1) {
57
            $attributes[$this->getNormalizedKeyName()] = $this->getNormalizedKey();
58
        }
59
60
        return $attributes;
61
    }
62
63
    /**
64
     * Get the primary key for the model.
65
     *
66
     * @return array
67
     */
68
    public function getRawKeyName()
69
    {
70
        return $this->hasCompositeIndex() ? $this->primaryKey : [$this->primaryKey];
71
    }
72
73
    /**
74
     * Get the value of the model's primary key.
75
     *
76
     * @return mixed
77
     */
78
    public function getRawKey()
79
    {
80
        $attributes = [];
81
82
        foreach ($this->getRawKeyName() as $key) {
83
            $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

83
            /** @scrutinizer ignore-call */ 
84
            $attributes[$key] = $this->getAttribute($key);
Loading history...
84
        }
85
86
        return $attributes;
87
    }
88
89
    /**
90
     * Get the value indicating whether the IDs are incrementing.
91
     *
92
     * @return bool
93
     */
94
    public function getIncrementing()
95
    {
96
        return false;
97
    }
98
99
    /**
100
     * Get the primary key for the model.
101
     *
102
     * @return string
103
     */
104
    public function getKeyName()
105
    {
106
        return $this->getNormalizedKeyName();
107
    }
108
109
    /**
110
     * Get virtual string key, required for proper collection support.
111
     *
112
     * @return mixed
113
     */
114
    public function getKey()
115
    {
116
        return $this->getNormalizedKey();
117
    }
118
119
    /**
120
     * @param \Illuminate\Database\Query\Builder $query
121
     * @param array|string                       $ids
122
     * @param bool                               $inverse
123
     *
124
     * @throws MissingPrimaryKeyValueException
125
     * @throws WrongKeyException
126
     */
127
    public function scopeApplyIds($query, $ids, $inverse = false)
128
    {
129
        $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...
130
131
        if (!is_array($ids) || Arr::isAssoc($ids)) {
132
            $ids = [$ids];
133
        }
134
135
        if ($this->hasCompositeIndex()) {
136
137
            (new CompositeKeyScope($keys, $ids, $inverse, $this->getBinaryColumns()))->apply($query);
138
139
        } else {
140
            if ($inverse) {
141
                $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

141
                $query->whereNotIn($this->/** @scrutinizer ignore-call */ qualifyColumn($keys[0]), $ids);
Loading history...
142
            } else {
143
                $query->whereIn($this->qualifyColumn($keys[0]), $ids);
144
            }
145
        }
146
    }
147
148
149
150
    /**
151
     * Get a new query to restore one or more models by their queueable IDs.
152
     *
153
     * @param array|int $ids
154
     *
155
     * @throws MissingPrimaryKeyValueException
156
     * @throws WrongKeyException
157
     *
158
     * @return \Illuminate\Database\Eloquent\Builder
159
     */
160
    public function newQueryForRestoration($ids)
161
    {
162
        if (!is_array($ids)) {
163
            $ids = [$ids];
164
        }
165
166
        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

166
        return $this->/** @scrutinizer ignore-call */ newQueryWithoutScopes()->applyIds(
Loading history...
167
            array_map(
168
                function ($normalizedKey) {
169
                    return $this->parseNormalizedKey($normalizedKey);
170
                },
171
                $ids
172
            )
173
        );
174
    }
175
176
    /**
177
     * @param \Illuminate\Database\Query\Builder $query
178
     *
179
     * @return \Illuminate\Database\Eloquent\Builder|static
180
     */
181
    public function newEloquentBuilder($query)
182
    {
183
        return new CompositeKeyQueryBuilder($query);
184
    }
185
186
    public function getBinaryColumns()
187
    {
188
        return $this->binaryColumns ?? [];
189
    }
190
191
    /**
192
     * Get the primary key value for a save query.
193
     *
194
     * @return mixed
195
     */
196
    protected function getKeyForSaveQuery()
197
    {
198
        $originalKeys = array_intersect_key($this->original, array_flip($this->getRawKeyName()));
199
200
        return array_merge($this->getRawKey(), $originalKeys);
201
    }
202
203
    /**
204
     * Set the keys for a save update query.
205
     *
206
     * @param \Illuminate\Database\Eloquent\Builder $query
207
     *
208
     * @throws MissingPrimaryKeyValueException
209
     *
210
     * @return \Illuminate\Database\Eloquent\Builder
211
     */
212
    protected function setKeysForSaveQuery(Builder $query)
213
    {
214
        foreach ($this->getRawKeyName() as $key) {
215
            if (isset($this->{$key})) {
216
                $query->where($key, '=', $this->{$key});
217
            } else {
218
                throw new MissingPrimaryKeyValueException($key, 'Missing value for key '.$key);
219
            }
220
        }
221
222
        return $query;
223
    }
224
225
    /**
226
     * Run the increment or decrement method on the model.
227
     *
228
     * @param string    $column
229
     * @param float|int $amount
230
     * @param array     $extra
231
     * @param string    $method
232
     *
233
     * @return int
234
     */
235
    protected function incrementOrDecrement($column, $amount, $extra, $method)
236
    {
237
        $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

237
        /** @scrutinizer ignore-call */ 
238
        $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...
238
239
        if (!$this->exists) {
240
            return $query->{$method}($column, $amount, $extra);
241
        }
242
243
        $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

243
        $this->/** @scrutinizer ignore-call */ 
244
               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...
244
245
        foreach ($this->getRawKeyName() as $key) {
246
            $query->where($key, $this->getAttribute($key));
247
        }
248
249
        return $query->{$method}($column, $amount, $extra);
250
    }
251
252
    /**
253
     * Retrieve the model for a bound value.
254
     *
255
     * @param mixed $value
256
     *
257
     * @return \Illuminate\Database\Eloquent\Model|null
258
     */
259
    public function resolveRouteBinding($value)
260
    {
261
        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

261
        if ($this->hasCompositeIndex() && $this->/** @scrutinizer ignore-call */ getRouteKeyName() == $this->getKeyName()) {
Loading history...
262
            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

262
            return $this->/** @scrutinizer ignore-call */ whereKey($value)->first();
Loading history...
263
        } else {
264
            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

264
            return $this->/** @scrutinizer ignore-call */ where($this->getRouteKeyName(), $value)->first();
Loading history...
265
        }
266
    }
267
}
268