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 (#5715)
by Cristian
11:33
created

BackpackCustomRule::getRulesAsArray()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 4
nop 1
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Backpack\CRUD\app\Library\Validation\Rules;
4
5
use Backpack\CRUD\app\Library\Validation\Rules\Support\ValidateArrayContract;
6
use Backpack\Pro\Uploads\Validation\ValidGenericAjaxEndpoint;
0 ignored issues
show
Bug introduced by
The type Backpack\Pro\Uploads\Val...alidGenericAjaxEndpoint was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Closure;
8
use Illuminate\Contracts\Validation\DataAwareRule;
9
use Illuminate\Contracts\Validation\Rule;
10
use Illuminate\Contracts\Validation\ValidationRule;
11
use Illuminate\Contracts\Validation\ValidatorAwareRule;
12
use Illuminate\Http\UploadedFile;
13
use Illuminate\Support\Arr;
14
use Illuminate\Support\Facades\Validator;
15
use Illuminate\Support\Str;
16
17
abstract class BackpackCustomRule implements ValidationRule, DataAwareRule, ValidatorAwareRule
18
{
19
    use Support\HasFiles;
20
21
    /**
22
     * @var \Illuminate\Contracts\Validation\Validator
23
     */
24
    protected $validator;
25
26
    protected array $data;
27
28
    public array $fieldRules = [];
29
30
    public bool $implicit = true;
31
32
    public static function field(string|array|ValidationRule|Rule $rules = []): self
33
    {
34
        $instance = new static();
35
        $instance->fieldRules = self::getRulesAsArray($rules);
36
37
        if ($instance->validatesArrays()) {
38
            if (! in_array('array', $instance->getFieldRules())) {
39
                $instance->fieldRules[] = 'array';
40
            }
41
        }
42
43
        return $instance;
44
    }
45
46
    /**
47
     * Run the validation rule.
48
     *
49
     * @param  string  $attribute
50
     * @param  mixed  $value
51
     * @param  Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
52
     * @return void
53
     */
54
    public function validate(string $attribute, mixed $value, Closure $fail): void
55
    {
56
        $value = $this->ensureValueIsValid($value);
57
58
        if ($value === false) {
59
            $fail('Invalid value for the attribute.')->translate();
60
61
            return;
62
        }
63
64
        $errors = $this->validateOnSubmit($attribute, $value);
65
        foreach ($errors as $error) {
66
            $fail($error)->translate();
67
        }
68
    }
69
70
    /**
71
     * Set the performing validator.
72
     *
73
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
74
     * @return $this
75
     */
76
    public function setValidator($validator)
77
    {
78
        $this->validator = $validator;
79
80
        return $this;
81
    }
82
83
    /**
84
     * Set the data under validation.
85
     *
86
     * @param  array  $data
87
     * @return $this
88
     */
89
    public function setData($data)
90
    {
91
        $this->data = $data;
92
93
        return $this;
94
    }
95
96
    public function getFieldRules(): array
97
    {
98
        return tap($this->fieldRules, function ($rule) {
99
            if (is_a($rule, BackpackCustomRule::class, true)) {
100
                $rule = $rule->getFieldRules();
101
            }
102
103
            return $rule;
104
        });
105
    }
106
107
    protected static function getRulesAsArray($rules)
108
    {
109
        if (is_string($rules)) {
110
            $rules = explode('|', $rules);
111
        }
112
113
        if (! is_array($rules)) {
114
            $rules = [$rules];
115
        }
116
117
        return $rules;
118
    }
119
120
    protected function ensureValueIsValid($value)
121
    {
122
        if ($this->validatesArrays() && ! is_array($value)) {
123
            try {
124
                $value = json_decode($value, true) ?? [];
125
            } catch(\Exception $e) {
126
                return false;
127
            }
128
        }
129
130
        return $value;
131
    }
132
133
    private function validatesArrays(): bool
134
    {
135
        return is_a($this, ValidateArrayContract::class);
136
    }
137
138
    private function validateAndGetErrors(string $attribute, mixed $value, array $rules): array
139
    {
140
        $validator = Validator::make($value, [
141
            $attribute => $rules,
142
        ], $this->validator->customMessages, $this->getValidatorCustomAttributes($attribute));
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...
143
144
        return $validator->errors()->messages()[$attribute] ?? (! empty($validator->errors()->messages()) ? current($validator->errors()->messages()) : []);
145
    }
146
147
    private function getValidatorCustomAttributes(string $attribute): array
148
    {
149
        if (! is_a($this, ValidGenericAjaxEndpoint::class) && ! Str::contains($attribute, '.*.')) {
150
            return $this->validator->customAttributes;
0 ignored issues
show
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...
151
        }
152
153
        // generic fallback to `profile picture` from `profile.*.picture`
154
        return [$attribute => Str::replace('.*.', ' ', $attribute)];
155
    }
156
157
    protected function getValidationAttributeString(string $attribute)
158
    {
159
        return Str::substrCount($attribute, '.') > 1 ?
160
                Str::before($attribute, '.').'.*.'.Str::afterLast($attribute, '.') :
161
                $attribute;
162
    }
163
164
    protected function validateOnSubmit(string $attribute, mixed $value): array
165
    {
166
        return $this->validateRules($attribute, $value);
167
    }
168
169
    protected function validateFieldAndFile(string $attribute, null|array $data = null, array|null $customRules = null): array
170
    {
171
        $fieldErrors = $this->validateFieldRules($attribute, $data, $customRules);
172
173
        $fileErrors = $this->validateFileRules($attribute, $data);
174
175
        return array_merge($fieldErrors, $fileErrors);
176
    }
177
178
    /**
179
     * Implementation.
180
     */
181
    public function validateFieldRules(string $attribute, null|array|string|UploadedFile $data = null, array|null $customRules = null): array
182
    {
183
        $data = $data ?? $this->data;
184
        $validationRuleAttribute = $this->getValidationAttributeString($attribute);
185
        $data = $this->prepareValidatorData($data, $attribute);
186
187
        return $this->validateAndGetErrors($validationRuleAttribute, $data, $customRules ?? $this->getFieldRules());
188
    }
189
190
    protected function prepareValidatorData(array|string|UploadedFile $data, string $attribute): array
191
    {
192
        if ($this->validatesArrays() && is_array($data) && ! Str::contains($attribute, '.')) {
193
            return Arr::has($data, $attribute) ? $data : [$attribute => $data];
194
        }
195
196
        if (Str::contains($attribute, '.')) {
197
            $validData = [];
198
199
            Arr::set($validData, $attribute, ! is_array($data) ? $data : Arr::get($data, $attribute));
200
201
            return $validData;
202
        }
203
204
        return [$attribute => is_array($data) ? (Arr::has($data, $attribute) ? Arr::get($data, $attribute) : $data) : $data];
205
    }
206
207
    protected function validateFileRules(string $attribute, mixed $data): array
208
    {
209
        $items = $this->prepareValidatorData($data ?? $this->data, $attribute);
210
        $items = is_array($items) ? $items : [$items];
0 ignored issues
show
introduced by
The condition is_array($items) is always true.
Loading history...
211
        $validationRuleAttribute = $this->getValidationAttributeString($attribute);
212
213
        $filesToValidate = Arr::get($items, $attribute);
214
        $filesToValidate = is_array($filesToValidate) ? array_filter($filesToValidate, function ($item) {
215
            return $item instanceof UploadedFile;
216
        }) : (is_a($filesToValidate, UploadedFile::class, true) ? [$filesToValidate] : []);
217
218
        Arr::set($items, $attribute, $filesToValidate);
219
220
        $errors = [];
221
222
        // validate each file individually
223
        foreach ($filesToValidate as $key => $file) {
224
            $fileToValidate = [];
225
            Arr::set($fileToValidate, $attribute, $file);
226
            $errors[] = $this->validateAndGetErrors($validationRuleAttribute, $fileToValidate, $this->getFileRules());
227
        }
228
229
        return array_unique(array_merge(...$errors));
230
    }
231
232
    public function validateRules(string $attribute, mixed $value): array
233
    {
234
        return $this->validateFieldAndFile($attribute, $value);
235
    }
236
}
237