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 — main (#4854)
by Pedro
30:01 queued 14:59
created

BaseCollection::buildAttributes()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 18
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 31
rs 9.6666
1
<?php
2
3
namespace Backpack\CRUD\app\Library\Components;
4
5
use Backpack\CRUD\app\Library\Components\Attributes\BaseAttribute;
6
use Backpack\CRUD\app\Library\Components\Interfaces\SmartAttributeInterface;
7
use Backpack\CRUD\app\Library\Components\Interfaces\SmartCollectionInterface;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Facades\Validator;
10
11
class BaseCollection implements SmartCollectionInterface
12
{
13
    private Collection $attributes;
14
15
    public function __construct(array|string $initAttributes,
16
                                private array $componentAttributes = [],
17
                                private array $rules = [],
18
                                private array $defaults = [],
19
                                private array $blockedAttributes = []
20
                            ) {
21
        $item = $this->getItemByName($initAttributes['name'] ?? $initAttributes);
0 ignored issues
show
Bug introduced by
It seems like $initAttributes['name'] ?? $initAttributes can also be of type array; however, parameter $name of Backpack\CRUD\app\Librar...ection::getItemByName() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

21
        $item = $this->getItemByName(/** @scrutinizer ignore-type */ $initAttributes['name'] ?? $initAttributes);
Loading history...
22
        if ($item) {
23
            $this->buildAttributes((array) $item, $componentAttributes, $rules, $defaults);
0 ignored issues
show
Unused Code introduced by
The call to Backpack\CRUD\app\Librar...tion::buildAttributes() has too many arguments starting with $componentAttributes. ( Ignorable by Annotation )

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

23
            $this->/** @scrutinizer ignore-call */ 
24
                   buildAttributes((array) $item, $componentAttributes, $rules, $defaults);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
24
        } else {
25
            $this->addCollectionItem($initAttributes, $componentAttributes);
0 ignored issues
show
Unused Code introduced by
The call to Backpack\CRUD\app\Librar...on::addCollectionItem() has too many arguments starting with $componentAttributes. ( Ignorable by Annotation )

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

25
            $this->/** @scrutinizer ignore-call */ 
26
                   addCollectionItem($initAttributes, $componentAttributes);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
26
        }
27
    }
28
29
    private function buildAttributes(array|string $attributes)
30
    {
31
        if (is_string($attributes)) {
0 ignored issues
show
introduced by
The condition is_string($attributes) is always false.
Loading history...
32
            $attributes = ['name' => $attributes];
33
        }
34
35
        $rules = $this->rules;
36
        $defaults = $this->defaults;
37
38
        $attributeNames = collect($this->componentAttributes)->mapWithKeys(function ($attribute) {
0 ignored issues
show
Bug introduced by
$this->componentAttributes of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

38
        $attributeNames = collect(/** @scrutinizer ignore-type */ $this->componentAttributes)->mapWithKeys(function ($attribute) {
Loading history...
39
            return [$attribute::getAttributeName() => $attribute];
40
        })->toArray();
41
42
        $attributeRules = collect($rules)->mapWithKeys(function ($rule) {
43
            if (is_a($rule, SmartAttributeInterface::class, true)) {
44
                return [$rule::getAttributeName() => $rule::getValidationRules($this)];
45
            }
46
47
            return [$rule::getAttributeName() => $rule];
48
        })->toArray();
49
50
        $this->attributes = collect($attributes)->mapWithKeys(function ($value, $key) use ($attributeNames, $attributeRules, $defaults) {
51
            if (isset($attributeNames[$key])) {
52
                return [$key => $attributeNames[$key]::make($key, $value, $attributeNames[$key]::getValidationRules($this))];
53
            }
54
55
            return [$key => new BaseAttribute($key, $value, $attributeRules[$key] ?? [], $defaults)];
56
        });
57
58
        $this->setAttributeDefaults();
59
        $this->validate();
60
    }
61
62
    public function addCollectionItem($attributes)
63
    {
64
        $this->buildAttributes($attributes);
65
        $collection = $this->getCollection();
66
        $collection[$this->getAttributeValue('name')] = $this->toArray();
67
        $this->saveCollection($collection);
68
    }
69
70
    public function getItems(): Collection
71
    {
72
        return collect($this->getCollection());
73
    }
74
75
    public function getAttributes(): Collection
76
    {
77
        return $this->attributes;
78
    }
79
80
    public function getItemByName(string $name)
81
    {
82
        return $this->getItems()->first(function ($item, $key) use ($name) {
83
            return $key === $name;
84
        });
85
    }
86
87
    public function hasAttribute(string $attribute): bool
88
    {
89
        return $this->attributes->has($attribute);
90
    }
91
92
    public function getAttributeValue($attribute, $default = null)
93
    {
94
        return $this->attributes->has($attribute) ? $this->attributes->get($attribute, $default)->value() : $default;
95
    }
96
97
    public function validate()
98
    {
99
        $attributes = $this->toArray();
100
101
        $rules = $this->getValidationRules();
102
103
        $validator = Validator::make($attributes, $rules)->stopOnFirstFailure();
104
105
        if ($validator->fails()) {
106
            throw new \Exception($validator->errors()->first());
107
        }
108
    }
109
110
    private function getValidationRules()
111
    {
112
        $rules = [];
113
        foreach ($this->attributes as $attribute) {
114
            $rules[$attribute->name()] = $attribute->rules();
115
        }
116
117
        return $rules;
118
    }
119
120
    public function setAttribute($attribute, $value)
121
    {
122
        $item = $this->hasAttribute($attribute) ? $this->attributes->get($attribute)->setValue($value) : new BaseAttribute($attribute, $value);
123
        $this->updateItem($item);
124
    }
125
126
    private function updateItem(SmartAttributeInterface $item)
127
    {
128
        $this->attributes[$item->name()] = $item;
129
        $collection = $this->getCollection();
130
        $collection[$this->getAttributeValue('name')] = $this->toArray();
131
        $this->saveCollection($collection);
132
    }
133
134
    public function deleteItem(string $name)
135
    {
136
        $this->attributes->forget($name);
137
        $collection = $this->getCollection();
138
        $collection->forget($name);
139
        $this->saveCollection($collection);
140
    }
141
142
    public function toCollection(): Collection
143
    {
144
        return $this->attributes->mapWithKeys(function ($item, $key) {
145
            return [$key => $item->value()];
146
        });
147
    }
148
149
    public function toArray(): array
150
    {
151
        return $this->toCollection()->toArray();
152
    }
153
154
    private function setAttributeDefaults()
155
    {
156
        foreach ($this->componentAttributes as $attribute) {
157
            if (! $this->hasAttribute($attribute::getAttributeName())) {
158
                $this->attributes[$attribute::getAttributeName()] = $attribute::make($attribute::getAttributeName(), $attribute::getDefault($this), $attribute::getValidationRules($this));
159
            }
160
        }
161
    }
162
163
    public static function attributes(): array
164
    {
165
        return [];
166
    }
167
168
    public function getCollection()
169
    {
170
        return collect();
171
    }
172
173
    public function saveCollection($collection)
174
    {
175
        return [];
176
    }
177
}
178