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 — main (#5440)
by Pedro
25:59 queued 10:50
created

BackpackCustomRule::validateFileRules()   C

Complexity

Conditions 14
Paths 64

Size

Total Lines 39
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 14
eloc 23
c 1
b 1
f 0
nc 64
nop 2
dl 0
loc 39
rs 6.2666

How to fix   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\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
143
        return $validator->errors()->messages()[$attribute] ?? [];
144
    }
145
146
    protected function getValidationAttributeString(string $attribute)
147
    {
148
        return Str::substrCount($attribute, '.') > 1 ?
149
                Str::before($attribute, '.').'.*.'.Str::afterLast($attribute, '.') :
150
                $attribute;
151
    }
152
153
    protected function validateOnSubmit(string $attribute, mixed $value): array
154
    {
155
        return $this->validateRules($attribute, $value);
156
    }
157
158
    protected function validateFieldAndFile(string $attribute, null|array $data = null, array|null $customRules = null): array
159
    {
160
        $fieldErrors = $this->validateFieldRules($attribute, $data, $customRules);
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
174
        $data = $this->prepareValidatorData($data, $attribute);
175
176
        return $this->validateAndGetErrors($validationRuleAttribute, $data, $customRules ?? $this->getFieldRules());
177
    }
178
179
    protected function prepareValidatorData(array|UploadedFile $data, string $attribute): array
180
    {
181
        if ($this->validatesArrays() && is_array($data)) {
182
            return Arr::has($data, $attribute) ? $data : [$attribute => Arr::get($data, $attribute)];
183
        }
184
185
        return [$attribute => $data];
186
    }
187
188
    protected function validateFileRules(string $attribute, mixed $data): array
189
    {
190
        $data = $data ?? $this->data;
191
        $items = is_array($data) && array_key_exists($attribute, $data) ? $data[$attribute] : $data;
192
        $items = is_array($items) ? $items : [$items];
193
        $errors = [];
194
        // we validate each file individually to avoid returning messages like: `field.0` is not a pdf.
195
        foreach ($items as $sentFiles) {
196
            if (! is_array($sentFiles)) {
197
                try {
198
                    if (is_file($sentFiles)) {
199
                        $errors[] = $this->validateAndGetErrors($attribute, [$attribute => $sentFiles], $this->getFileRules());
200
                    }
201
                    continue;
202
                } catch(\Exception) {
203
                    $errors[] = 'Unknown datatype, aborting upload process.';
204
                    break;
205
                }
206
            }
207
208
            if (is_multidimensional_array($sentFiles)) {
209
                foreach ($sentFiles as $key => $value) {
210
                    foreach ($value[$attribute] as $file) {
211
                        if (is_file($file)) {
212
                            $errors[] = $this->validateAndGetErrors($attribute, [$attribute => $file], $this->getFileRules());
213
                        }
214
                    }
215
                }
216
                continue;
217
            }
218
219
            foreach ($sentFiles as $key => $value) {
220
                if (is_file($value)) {
221
                    $errors[] = $this->validateAndGetErrors($attribute, [$attribute => $value], $this->getFileRules());
222
                }
223
            }
224
        }
225
226
        return array_unique(array_merge(...$errors));
227
    }
228
229
    public function validateRules(string $attribute, mixed $value): array
230
    {
231
        return $this->validateFieldAndFile($attribute, $value);
232
    }
233
}
234