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 Setup Failed
Pull Request — master (#4161)
by
unknown
15:22
created

Input::getRelationDetailsFromInput()   C

Complexity

Conditions 16
Paths 122

Size

Total Lines 77
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 16
eloc 37
nc 122
nop 3
dl 0
loc 77
rs 5.3833
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
8
trait Input
9
{
10
    /**
11
     * ---------------
12
     * PRIVATE METHODS
13
     * ---------------.
14
     */
15
16
    /**
17
     * Returns the direct inputs parsed for model and relationship creation.
18
     *
19
     * @param  array  $inputs
20
     * @param  null|array  $relationDetails
21
     * @param  bool|string  $relationMethod
22
     * @return array
23
     */
24
    private function splitInputIntoDirectAndRelations($inputs, $relationDetails = null, $relationMethod = false)
25
    {
26
        $crudFields = $relationDetails['crudFields'] ?? [];
27
        $model = $relationDetails['model'] ?? false;
28
29
        $directInputs = $this->getDirectInputsFromInput($inputs, $model, $crudFields, $relationMethod);
30
        $relationInputs = $this->getRelationDetailsFromInput($inputs, $crudFields, $relationMethod);
31
32
        return [$directInputs, $relationInputs];
33
    }
34
35
    /**
36
     * Returns the attributes with relationships stripped out from the input.
37
     * BelongsTo relations are ensured to have the correct foreign key set.
38
     * ALL other relations are stripped from the input.
39
     *
40
     * @param  array  $input  - the input array
41
     * @param  mixed  $model  - the model of what we want to get the attributtes for
42
     * @param  array  $fields  - the fields used in this relation
43
     * @param  mixed  $relationMethod  - the relation method
44
     * @return array
45
     */
46
    private function getDirectInputsFromInput($input, $model = false, $fields = [], $relationMethod = false)
47
    {
48
        $model = $model ? (is_string($model) ? app($model) : $model) : $this->model;
49
50
        $input = $this->decodeJsonCastedAttributes($input, $model);
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

50
        /** @scrutinizer ignore-call */ 
51
        $input = $this->decodeJsonCastedAttributes($input, $model);
Loading history...
51
        $input = $this->compactFakeFields($input, $model, $fields);
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

51
        /** @scrutinizer ignore-call */ 
52
        $input = $this->compactFakeFields($input, $model, $fields);
Loading history...
52
        $input = $this->excludeRelationFieldsExceptBelongsTo($input, $fields, $relationMethod);
53
        $input = $this->changeBelongsToNamesFromRelationshipToForeignKey($input, $fields);
0 ignored issues
show
Bug introduced by
It seems like changeBelongsToNamesFromRelationshipToForeignKey() 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

53
        /** @scrutinizer ignore-call */ 
54
        $input = $this->changeBelongsToNamesFromRelationshipToForeignKey($input, $fields);
Loading history...
54
55
        return $input;
56
    }
57
58
    /**
59
     * Get a relation data array from the form data. For each relation defined in the fields
60
     * through the entity attribute, and set some relation details.
61
     *
62
     * We traverse this relation array later to create the relations, for example:
63
     * - Current model HasOne Address
64
     * - Address (line_1, country_id) BelongsTo Country through country_id in Address Model
65
     *
66
     * So when editing current model crud user have two fields
67
     * - address.line_1
68
     * - address.country
69
     * (we infer country_id from relation)
70
     *
71
     * Those will be nested accordingly in this relation array, so address relation
72
     * will have a nested relation with country.
73
     *
74
     * @param  array  $input  The form input.
75
     * @param  array  $crudFields  - present when getting the relation details for other relations.
76
     * @param  mixed  $relationMethod
77
     * @return array The formatted relation details.
78
     */
79
    private function getRelationDetailsFromInput($input, $crudFields = [], $relationMethod = false)
80
    {
81
        // main entity
82
        if (empty($crudFields)) {
83
            $relationFields = $this->getRelationFields();
0 ignored issues
show
Bug introduced by
It seems like getRelationFields() 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
            $relationFields = $this->getRelationFields();
Loading history...
84
        } else {
85
            // relations sends the fields that represent them so we can parse the input accordingly.
86
            $relationFields = $crudFields;
87
88
            foreach ($crudFields as $key => $crudField) {
89
                if (isset($crudField['subfields'])) {
90
                    foreach ($crudField['subfields'] as $crudSubField) {
91
                        if (isset($crudSubField['relation_type'])) {
92
                            $relationFields[] = $crudSubField;
93
                        }
94
                    }
95
                }
96
            }
97
        }
98
99
        //remove fields that are not in the submitted form input
100
        $relationFields = array_filter($relationFields, function ($field) use ($input) {
101
            return Arr::has($input, $field['name']) || isset($input[$field['name']]) || Arr::has($input, Str::afterLast($field['name'], '.'));
102
        });
103
104
        $relationDetails = [];
105
106
        foreach ($relationFields as $field) {
107
            // if relationMethod is set we strip it out of the fieldName that we use to create the relations array
108
            $fieldName = $relationMethod ? Str::after($field['name'], $relationMethod.'.') : $field['name'];
109
110
            $key = Str::before($this->getOnlyRelationEntity(['entity' => $fieldName]), '.');
0 ignored issues
show
Bug introduced by
It seems like getOnlyRelationEntity() 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

110
            $key = Str::before($this->/** @scrutinizer ignore-call */ getOnlyRelationEntity(['entity' => $fieldName]), '.');
Loading history...
111
112
            // if the field entity contains the attribute we want to add that attribute in the correct relation key.
113
            // eg: adress.street, we want to add `street` as an attribute in `address` relation, `street` is not
114
            // a relation of `address`
115
            if ($this->getOnlyRelationEntity($field) !== $field['entity']) {
116
                if (Str::before($field['entity'], '.') === $relationMethod) {
117
                    $key = Str::before($this->getOnlyRelationEntity($field), '.');
118
                }
119
            }
120
121
            $attributeName = (string) Str::of($field['name'])->afterLast('.');
122
123
            switch ($field['relation_type']) {
124
                case 'BelongsTo':
125
                    // when it's a nested belongsTo relation we want to make sure
126
                    // the key used to store the values is the main relation key
127
                    $key = Str::beforeLast($this->getOnlyRelationEntity($field), '.');
128
129
                break;
130
            }
131
132
            // we don't need to re-setup this relation method values, we just want the relations
133
            if ($key === $relationMethod) {
134
                continue;
135
            }
136
137
            $fieldDetails = Arr::get($relationDetails, $key, []);
138
139
            $fieldDetails['values'][$attributeName] = Arr::get($input, $fieldName);
140
            $fieldDetails['model'] = $fieldDetails['model'] ?? $field['model'];
141
            $fieldDetails['relation_type'] = $fieldDetails['relation_type'] ?? $field['relation_type'];
142
            $fieldDetails['crudFields'][] = $field;
143
            $fieldDetails['entity'] = $this->getOnlyRelationEntity($field);
144
145
            if (isset($field['fallback_id'])) {
146
                $fieldDetails['fallback_id'] = $field['fallback_id'];
147
            }
148
            if (isset($field['force_delete'])) {
149
                $fieldDetails['force_delete'] = $field['force_delete'];
150
            }
151
152
            Arr::set($relationDetails, $key, $fieldDetails);
153
        }
154
155
        return $relationDetails;
156
    }
157
158
    /**
159
     * Return the input without relations except BelongsTo that we are going to properly match
160
     * with the relation foreign_key in a later stage of the saving process.
161
     *
162
     * @param  array  $fields
163
     * @param  mixed  $relationMethod
164
     * @return array
165
     */
166
    private function excludeRelationFieldsExceptBelongsTo($input, $fields, $relationMethod)
167
    {
168
        // when fields are empty we are in the main entity, we get the regular crud relation fields
169
        if (empty($fields)) {
170
            $fields = $this->getRelationFields();
171
        }
172
173
        $excludedFields = [];
174
        foreach ($fields as $field) {
175
            $nameToExclude = $relationMethod ? Str::after($field['name'], $relationMethod.'.') : $field['name'];
176
177
            // when using dot notation if relationMethod is not set we are sure we want to exclude those relations.
178
            if ($this->getOnlyRelationEntity($field) !== $field['entity']) {
179
                if (! $relationMethod) {
180
                    $excludedFields[] = $nameToExclude;
181
                }
182
                continue;
183
            }
184
185
            if (isset($field['relation_type']) && $field['relation_type'] !== 'BelongsTo') {
186
                $excludedFields[] = $nameToExclude;
187
                continue;
188
            }
189
        }
190
191
        return Arr::where($input, function ($item, $key) use ($excludedFields) {
192
            return ! in_array($key, $excludedFields);
193
        });
194
    }
195
}
196