Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Test Failed
Pull Request — master (#3410)
by
unknown
11:02
created

Update   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Importance

Changes 9
Bugs 3 Features 0
Metric Value
eloc 83
c 9
b 3
f 0
dl 0
loc 187
rs 9.68
wmc 34

4 Methods

Rating   Name   Duplication   Size   Complexity  
B getUpdateFields() 0 29 7
A update() 0 18 1
C getModelAttributeValue() 0 56 16
B getManyRelationAttributeValue() 0 37 10
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
6
use Illuminate\Database\Eloquent\Relations\HasMany;
7
use Illuminate\Database\Eloquent\Relations\HasOne;
8
use Illuminate\Database\Eloquent\Relations\MorphMany;
9
use Illuminate\Database\Eloquent\Relations\MorphOne;
10
use Illuminate\Database\Eloquent\Relations\MorphToMany;
11
use Illuminate\Support\Arr;
12
13
trait Update
14
{
15
    /*
16
    |--------------------------------------------------------------------------
17
    |                                   UPDATE
18
    |--------------------------------------------------------------------------
19
    */
20
21
    /**
22
     * Update a row in the database.
23
     *
24
     * @param int   $id   The entity's id
25
     * @param array $data All inputs to be updated.
26
     *
27
     * @return object
28
     */
29
    public function update($id, $data)
30
    {
31
        $data = $this->decodeJsonCastedAttributes($data);
0 ignored issues
show
Bug introduced by
It seems like decodeJsonCastedAttributes() 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

31
        /** @scrutinizer ignore-call */ 
32
        $data = $this->decodeJsonCastedAttributes($data);
Loading history...
32
        $data = $this->compactFakeFields($data);
0 ignored issues
show
Bug introduced by
It seems like compactFakeFields() 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
        /** @scrutinizer ignore-call */ 
33
        $data = $this->compactFakeFields($data);
Loading history...
33
        $item = $this->model->findOrFail($id);
34
35
        // omit the n-n relationships when updating the eloquent item
36
        $nn_relationships = Arr::pluck($this->getRelationFieldsWithPivot(), 'name');
0 ignored issues
show
Bug introduced by
It seems like getRelationFieldsWithPivot() 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

36
        $nn_relationships = Arr::pluck($this->/** @scrutinizer ignore-call */ getRelationFieldsWithPivot(), 'name');
Loading history...
37
38
        // handle BelongsTo 1:1 relations
39
        $item = $this->associateOrDissociateBelongsToRelations($item, $data);
0 ignored issues
show
Bug introduced by
It seems like associateOrDissociateBelongsToRelations() 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

39
        /** @scrutinizer ignore-call */ 
40
        $item = $this->associateOrDissociateBelongsToRelations($item, $data);
Loading history...
40
41
        $item->fill(Arr::except($data, $nn_relationships));
42
        $item->save();
43
44
        $this->createRelations($item, $data);
0 ignored issues
show
Bug introduced by
It seems like createRelations() 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

44
        $this->/** @scrutinizer ignore-call */ 
45
               createRelations($item, $data);
Loading history...
45
46
        return $item;
47
    }
48
49
    /**
50
     * Get all fields needed for the EDIT ENTRY form.
51
     *
52
     * @param int $id The id of the entry that is being edited.
53
     *
54
     * @return array The fields with attributes, fake attributes and values.
55
     */
56
    public function getUpdateFields($id = false)
57
    {
58
        $fields = $this->fields();
0 ignored issues
show
Bug introduced by
It seems like fields() 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

58
        /** @scrutinizer ignore-call */ 
59
        $fields = $this->fields();
Loading history...
59
        $entry = ($id != false) ? $this->getEntry($id) : $this->getCurrentEntry();
0 ignored issues
show
Bug introduced by
It seems like getEntry() 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

59
        $entry = ($id != false) ? $this->/** @scrutinizer ignore-call */ getEntry($id) : $this->getCurrentEntry();
Loading history...
Bug Best Practice introduced by
It seems like you are loosely comparing $id of type false|integer against false; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
Bug introduced by
It seems like getCurrentEntry() 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

59
        $entry = ($id != false) ? $this->getEntry($id) : $this->/** @scrutinizer ignore-call */ getCurrentEntry();
Loading history...
60
61
        foreach ($fields as &$field) {
62
            // set the value
63
            if (! isset($field['value'])) {
64
                if (isset($field['subfields'])) {
65
                    $field['value'] = [];
66
                    foreach ($field['subfields'] as $subfield) {
67
                        $field['value'][] = $entry->{$subfield['name']};
68
                    }
69
                } else {
70
                    $field['value'] = $this->getModelAttributeValue($entry, $field);
71
                }
72
            }
73
        }
74
75
        // always have a hidden input for the entry id
76
        if (! array_key_exists('id', $fields)) {
77
            $fields['id'] = [
78
                'name'  => $entry->getKeyName(),
79
                'value' => $entry->getKey(),
80
                'type'  => 'hidden',
81
            ];
82
        }
83
84
        return $fields;
85
    }
86
87
    /**
88
     * Get the value of the 'name' attribute from the declared relation model in the given field.
89
     *
90
     * @param \Illuminate\Database\Eloquent\Model $model The current CRUD model.
91
     * @param array                               $field The CRUD field array.
92
     *
93
     * @return mixed The value of the 'name' attribute from the relation model.
94
     */
95
    private function getModelAttributeValue($model, $field)
96
    {
97
        if (isset($field['entity']) && $field['entity'] !== false) {
98
            $relational_entity = $this->parseRelationFieldNamesFromHtml([$field])[0]['name'];
0 ignored issues
show
Bug introduced by
It seems like parseRelationFieldNamesFromHtml() 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

98
            $relational_entity = $this->/** @scrutinizer ignore-call */ parseRelationFieldNamesFromHtml([$field])[0]['name'];
Loading history...
99
100
            $relation_array = explode('.', $relational_entity);
101
102
            $relatedModel = array_reduce(array_splice($relation_array, 0, -1), function ($obj, $method) {
103
                return $obj->{$method} ? $obj->{$method} : $obj;
104
            }, $model);
105
106
            $relationMethod = Arr::last($relation_array);
107
            if (method_exists($relatedModel, $relationMethod)) {
108
                $relation = $relatedModel->{$relationMethod}();
109
                $relation_type = get_class($relation);
110
111
                switch ($relation_type) {
112
                    case HasOne::class:
113
                    case MorphOne::class:
114
                        return $relatedModel->{$relationMethod}->{Arr::last(explode('.', $relational_entity))};
115
116
                    case HasMany::class:
117
                    case MorphMany::class:
118
119
                        $attribute_value = $this->getManyRelationAttributeValue($relatedModel, $relationMethod, $field, $relation_type);
120
                        // we only want to return the json_encoded values here
121
                        if (is_string($attribute_value)) {
122
                            return $attribute_value;
123
                        }
124
125
                    break;
126
                    case BelongsToMany::class:
127
                    case MorphToMany::class:
128
                        $attribute_value = $this->getManyRelationAttributeValue($relatedModel, $relationMethod, $field, $relation_type);
129
                        // we only want to return the json_encoded values here
130
                        if (is_string($attribute_value)) {
131
                            return $attribute_value;
132
                        }
133
                    break;
134
                }
135
            }
136
137
            return $relatedModel->{$relationMethod};
138
        }
139
140
        if (is_string($field['name'])) {
141
            return $model->{$field['name']};
142
        }
143
144
        if (is_array($field['name'])) {
145
            $result = [];
146
            foreach ($field['name'] as $key => $value) {
147
                $result = $model->{$value};
148
            }
149
150
            return $result;
151
        }
152
    }
153
154
    /**
155
     * Returns the json encoded pivot fields from supported relations.
156
     *
157
     * @param \Illuminate\Database\Eloquent\Model $model
158
     * @param string $relation_method
159
     * @param array $field
160
     * @param string $relation_type
161
     * @return bool|string
162
     */
163
    private function getManyRelationAttributeValue($model, $relation_method, $field, $relation_type)
164
    {
165
        if (! isset($field['pivotFields']) || ! is_array($field['pivotFields'])) {
166
            return false;
167
        }
168
169
        $pivot_fields = Arr::where($field['pivotFields'], function ($item) use ($field) {
170
            return $field['name'] != $item['name'];
171
        });
172
        $related_models = $model->{$relation_method};
173
        $return = [];
174
        // for any given model, we grab the attributes that belong to our pivot table.
175
        foreach ($related_models as $related_model) {
176
            $item = [];
177
            switch ($relation_type) {
178
                case HasMany::class:
179
                case MorphMany::class:
180
                        // for any given related model, we get the value from pivot fields
181
                        foreach ($pivot_fields as $pivot_field) {
182
                            $item[$pivot_field['name']] = $related_model->{$pivot_field['name']};
183
                        }
184
                        $item[$related_model->getKeyName()] = $related_model->getKey();
185
                        $return[] = $item;
186
            break;
187
            case BelongsToMany::class:
188
            case MorphToMany::class:
189
190
                    $item[$field['name']] = $related_model->getKey();
191
                    //for any given related model, we get the pivot fields.
192
                    foreach ($pivot_fields as $pivot_field) {
193
                        $item[$pivot_field['name']] = $related_model->pivot->{$pivot_field['name']};
194
                    }
195
                    $return[] = $item;
196
            }
197
        }
198
        // we return the json encoded result as expected by repeatable field.
199
        return json_encode($return);
200
    }
201
}
202