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 (#5440)
by Cristian
27:15 queued 12:39
created

BackpackCustomRule::setData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
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
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