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
Push — fix-uploaders ( a81c63...ed8c3d )
by Pedro
15:20
created

BackpackCustomRule::field()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 3
eloc 6
c 1
b 1
f 0
nc 3
nop 1
dl 0
loc 12
rs 10
1
<?php
2
3
namespace Backpack\CRUD\app\Library\Validation\Rules;
4
5
use Backpack\CRUD\app\Library\Validation\Rules\Support\ValidateArrayContract;
6
use Closure;
7
use Illuminate\Contracts\Validation\DataAwareRule;
8
use Illuminate\Contracts\Validation\Rule;
9
use Illuminate\Contracts\Validation\ValidationRule;
10
use Illuminate\Contracts\Validation\ValidatorAwareRule;
11
use Illuminate\Http\UploadedFile;
12
use Illuminate\Support\Arr;
13
use Illuminate\Support\Facades\Validator;
14
use Illuminate\Support\Str;
15
16
abstract class BackpackCustomRule implements ValidationRule, DataAwareRule, ValidatorAwareRule
17
{
18
    use Support\HasFiles;
19
20
    /**
21
     * @var \Illuminate\Contracts\Validation\Validator
22
     */
23
    protected $validator;
24
25
    protected array $data;
26
27
    public array $fieldRules = [];
28
29
    public bool $implicit = true;
30
31
    public static function field(string|array|ValidationRule|Rule $rules = []): self
32
    {
33
        $instance = new static();
34
        $instance->fieldRules = self::getRulesAsArray($rules);
35
36
        if ($instance->validatesArrays()) {
37
            if (! in_array('array', $instance->getFieldRules())) {
38
                $instance->fieldRules[] = 'array';
39
            }
40
        }
41
42
        return $instance;
43
    }
44
45
    /**
46
     * Run the validation rule.
47
     *
48
     * @param  string  $attribute
49
     * @param  mixed  $value
50
     * @param  Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
51
     * @return void
52
     */
53
    public function validate(string $attribute, mixed $value, Closure $fail): void
54
    {
55
        $value = $this->ensureValueIsValid($value);
56
57
        if ($value === false) {
58
            $fail('Invalid value for the attribute.')->translate();
59
60
            return;
61
        }
62
63
        $errors = $this->validateOnSubmit($attribute, $value);
64
        foreach ($errors as $error) {
65
            $fail($error)->translate();
66
        }
67
    }
68
69
    /**
70
     * Set the performing validator.
71
     *
72
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
73
     * @return $this
74
     */
75
    public function setValidator($validator)
76
    {
77
        $this->validator = $validator;
78
79
        return $this;
80
    }
81
82
    /**
83
     * Set the data under validation.
84
     *
85
     * @param  array  $data
86
     * @return $this
87
     */
88
    public function setData($data)
89
    {
90
        $this->data = $data;
91
92
        return $this;
93
    }
94
95
    public function getFieldRules(): array
96
    {
97
        return tap($this->fieldRules, function ($rule) {
98
            if (is_a($rule, BackpackCustomRule::class, true)) {
99
                $rule = $rule->getFieldRules();
100
            }
101
102
            return $rule;
103
        });
104
    }
105
106
    protected static function getRulesAsArray($rules)
107
    {
108
        if (is_string($rules)) {
109
            $rules = explode('|', $rules);
110
        }
111
112
        if (! is_array($rules)) {
113
            $rules = [$rules];
114
        }
115
116
        return $rules;
117
    }
118
119
    protected function ensureValueIsValid($value)
120
    {
121
        if ($this->validatesArrays() && ! is_array($value)) {
122
            try {
123
                $value = json_decode($value, true) ?? [];
124
            } catch(\Exception $e) {
125
                return false;
126
            }
127
        }
128
129
        return $value;
130
    }
131
132
    private function validatesArrays(): bool
133
    {
134
        return is_a($this, ValidateArrayContract::class);
135
    }
136
137
    private function validateAndGetErrors(string $attribute, mixed $value, array $rules): array
138
    {
139
        $validator = Validator::make($value, [
140
            $attribute => $rules,
141
        ], $this->validator->customMessages, $this->validator->customAttributes);
0 ignored issues
show
Bug introduced by
Accessing customMessages on the interface Illuminate\Contracts\Validation\Validator suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
Bug introduced by
Accessing customAttributes on the interface Illuminate\Contracts\Validation\Validator suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
142
        return $validator->errors()->messages()[$attribute] ?? (!empty($validator->errors()->messages()) ? current($validator->errors()->messages()) : []);
143
    }
144
145
    protected function getValidationAttributeString(string $attribute)
146
    {
147
        return Str::substrCount($attribute, '.') > 1 ?
148
                Str::before($attribute, '.').'.*.'.Str::afterLast($attribute, '.') :
149
                $attribute;
150
    }
151
152
    protected function validateOnSubmit(string $attribute, mixed $value): array
153
    {
154
        return $this->validateRules($attribute, $value);
155
    }
156
157
    protected function validateFieldAndFile(string $attribute, null|array $data = null, array|null $customRules = null): array
158
    {
159
        $fieldErrors = $this->validateFieldRules($attribute, $data, $customRules);
160
       
161
        $fileErrors = $this->validateFileRules($attribute, $data);
162
163
        return array_merge($fieldErrors, $fileErrors);
164
    }
165
166
    /**
167
     * Implementation.
168
     */
169
    public function validateFieldRules(string $attribute, null|array|UploadedFile $data = null, array|null $customRules = null): array
170
    {
171
        $data = $data ?? $this->data;
172
        $validationRuleAttribute = $this->getValidationAttributeString($attribute);
173
        $data = $this->prepareValidatorData($data, $attribute);
174
        return $this->validateAndGetErrors($validationRuleAttribute, $data, $customRules ?? $this->getFieldRules());
175
    }
176
177
    protected function prepareValidatorData(array|UploadedFile $data, string $attribute): array
178
    {
179
        if ($this->validatesArrays() && is_array($data) && ! Str::contains($attribute, '.')) {
180
            return Arr::has($data, $attribute) ? $data : [$attribute => Arr::get($data, $attribute)];
181
        }
182
183
        if(Str::contains($attribute, '.')) {
184
            $validData = [];
185
            
186
            Arr::set($validData, $attribute, !is_array($data) ? $data : Arr::get($data, $attribute));
187
            return $validData;
188
        }
189
190
        return [$attribute => $data];
191
    }
192
193
    protected function validateFileRules(string $attribute, mixed $data): array
194
    {
195
        $items = $this->prepareValidatorData($data ?? $this->data, $attribute);
196
        $items = is_array($items) ? $items : [$items];
0 ignored issues
show
introduced by
The condition is_array($items) is always true.
Loading history...
197
        $validationRuleAttribute = $this->getValidationAttributeString($attribute);
198
199
        $filesToValidate = array_filter(Arr::get($items, $attribute), function ($item) {
0 ignored issues
show
Bug introduced by
It seems like Illuminate\Support\Arr::get($items, $attribute) can also be of type null; however, parameter $array of array_filter() does only seem to accept array, 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

199
        $filesToValidate = array_filter(/** @scrutinizer ignore-type */ Arr::get($items, $attribute), function ($item) {
Loading history...
200
            return $item instanceof UploadedFile;
201
        });
202
203
        Arr::set($items, $attribute, $filesToValidate);
204
205
        $errors = [];
206
        
207
        foreach ($filesToValidate as $key => $file) {
208
            $fileToValidate = [];
209
            Arr::set($fileToValidate, $attribute, $file);
210
            $errors[] = $this->validateAndGetErrors($validationRuleAttribute, $fileToValidate, $this->getFileRules());
211
        }
212
213
        return array_unique(array_merge(...$errors));
214
    }
215
216
    public function validateRules(string $attribute, mixed $value): array
217
    {
218
        return $this->validateFieldAndFile($attribute, $value);
219
    }
220
}
221