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

Passed
Pull Request — master (#3796)
by Cristian
12:06
created

guessIfFieldHasMultipleFromRelationType()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 11
nc 8
nop 1
dl 0
loc 14
rs 8.4444
c 0
b 0
f 0
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 Relationships
9
{
10
    /**
11
     * From the field entity we get the relation instance.
12
     *
13
     * @param array $entity
14
     * @return object
15
     */
16
    public function getRelationInstance($field)
17
    {
18
        $entity = $this->getOnlyRelationEntity($field);
19
        $possible_method = Str::before($entity, '.');
20
        $model = $this->model;
21
22
        if (method_exists($model, $possible_method)) {
23
            $parts = explode('.', $entity);
24
            // here we are going to iterate through all relation parts to check
25
            // if the attribute is present in the relation string.
26
            foreach ($parts as $i => $part) {
27
                $relation = $model->$part();
28
                $model = $relation->getRelated();
29
            }
30
31
            return $relation;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $relation seems to be defined by a foreach iteration on line 26. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
32
        }
33
34
        return (new $relation_model())->{$related_method}();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $related_method seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $relation_model does not exist. Did you maybe mean $relation?
Loading history...
35
    }
36
37
    /**
38
     * Check if field is a nested relation.
39
     *
40
     * @param array $field
41
     * @return bool
42
     */
43
    protected function isNestedRelation($field): bool
44
    {
45
        $entity = $this->getOnlyRelationEntity($field);
46
        if (strpos($entity, '.') !== false) {
47
            return true;
48
        }
49
50
        return false;
51
    }
52
53
    public function getOnlyRelationEntity($relation_field)
54
    {
55
        $relation_model = $this->getRelationModel($relation_field['entity'], -1);
0 ignored issues
show
Bug introduced by
The method getRelationModel() does not exist on Backpack\CRUD\app\Librar...el\Traits\Relationships. Did you maybe mean getRelationInstance()? ( Ignorable by Annotation )

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

55
        /** @scrutinizer ignore-call */ 
56
        $relation_model = $this->getRelationModel($relation_field['entity'], -1);

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...
56
        $related_method = Str::afterLast($relation_field['entity'], '.');
57
58
        if (! method_exists($relation_model, $related_method)) {
59
            return Str::beforeLast($relation_field['entity'], '.');
60
        }
61
62
        return $relation_field['entity'];
63
    }
64
65
    /**
66
     * Grabs an relation instance and returns the class name of the related model.
67
     *
68
     * @param array $field
69
     * @return string
70
     */
71
    public function inferFieldModelFromRelationship($field)
72
    {
73
        $relation = $this->getRelationInstance($field);
74
75
        return get_class($relation->getRelated());
76
    }
77
78
    /**
79
     * Return the relation type from a given field: BelongsTo, HasOne ... etc.
80
     *
81
     * @param array $field
82
     * @return string
83
     */
84
    public function inferRelationTypeFromRelationship($field)
85
    {
86
        $relation = $this->getRelationInstance($field);
87
88
        return Arr::last(explode('\\', get_class($relation)));
89
    }
90
91
    /**
92
     * Parse the field name back to the related entity after the form is submited.
93
     * Its called in getAllFieldNames().
94
     *
95
     * @param array $fields
96
     * @return array
97
     */
98
    public function parseRelationFieldNamesFromHtml($fields)
99
    {
100
        foreach ($fields as &$field) {
101
            //we only want to parse fields that has a relation type and their name contains [ ] used in html.
102
            if (isset($field['relation_type']) && preg_match('/[\[\]]/', $field['name']) !== 0) {
103
                $chunks = explode('[', $field['name']);
104
105
                foreach ($chunks as &$chunk) {
106
                    if (strpos($chunk, ']')) {
107
                        $chunk = str_replace(']', '', $chunk);
108
                    }
109
                }
110
                $field['name'] = implode('.', $chunks);
111
            }
112
        }
113
114
        return $fields;
115
    }
116
117
    /**
118
     * Based on relation type returns the default field type.
119
     *
120
     * @param string $relation_type
121
     * @return bool
122
     */
123
    public function inferFieldTypeFromFieldRelation($field)
124
    {
125
        switch ($field['relation_type']) {
126
            case 'BelongsToMany':
127
            case 'HasMany':
128
            case 'HasManyThrough':
129
            case 'MorphMany':
130
            case 'MorphToMany':
131
            case 'BelongsTo':
132
                return 'relationship';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'relationship' returns the type string which is incompatible with the documented return type boolean.
Loading history...
133
134
            default:
135
                return 'text';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'text' returns the type string which is incompatible with the documented return type boolean.
Loading history...
136
        }
137
    }
138
139
    /**
140
     * Based on relation type returns if relation allows multiple entities.
141
     *
142
     * @param string $relation_type
143
     * @return bool
144
     */
145
    public function guessIfFieldHasMultipleFromRelationType($relation_type)
146
    {
147
        switch ($relation_type) {
148
            case 'BelongsToMany':
149
            case 'HasMany':
150
            case 'HasManyThrough':
151
            case 'HasOneOrMany':
152
            case 'MorphMany':
153
            case 'MorphOneOrMany':
154
            case 'MorphToMany':
155
                return true;
156
157
            default:
158
                return false;
159
        }
160
    }
161
162
    /**
163
     * Based on relation type returns if relation has a pivot table.
164
     *
165
     * @param string $relation_type
166
     * @return bool
167
     */
168
    public function guessIfFieldHasPivotFromRelationType($relation_type)
169
    {
170
        switch ($relation_type) {
171
            case 'BelongsToMany':
172
            case 'HasManyThrough':
173
            case 'MorphMany':
174
            case 'MorphOneOrMany':
175
            case 'MorphToMany':
176
                return true;
177
            default:
178
                return false;
179
        }
180
    }
181
182
    /**
183
     * Get the fields for relationships, according to the relation type. It looks only for direct
184
     * relations - it will NOT look through relationships of relationships.
185
     *
186
     * @param string|array $relation_types Eloquent relation class or array of Eloquent relation classes. Eg: BelongsTo
187
     *
188
     * @return array The fields with corresponding relation types.
189
     */
190
    public function getFieldsWithRelationType($relation_types): array
191
    {
192
        $relation_types = (array) $relation_types;
193
194
        return collect($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

194
        return collect($this->/** @scrutinizer ignore-call */ fields())
Loading history...
195
            ->where('model')
196
            ->whereIn('relation_type', $relation_types)
197
            ->filter(function ($item) {
198
                $related_model = get_class($this->model->{Str::before($item['entity'], '.')}()->getRelated());
199
200
                return Str::contains($item['entity'], '.') && $item['model'] !== $related_model ? false : true;
201
            })
202
            ->toArray();
203
    }
204
}
205