Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 144
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateMiniCrudRequest
0.00% covered (danger)
0.00%
0 / 144
0.00% covered (danger)
0.00%
0 / 5
1190
0.00% covered (danger)
0.00%
0 / 1
 authorize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 rules
0.00% covered (danger)
0.00%
0 / 116
0.00% covered (danger)
0.00%
0 / 1
462
 compileValidate
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
90
 ruleHasToComeFirst
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 isUpdate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Requests\Bo;
4
5use App\Enums\InputType;
6use App\Lib\Helpers\ToolboxHelper;
7use Illuminate\Foundation\Http\FormRequest;
8use Illuminate\Validation\ValidationException;
9
10abstract class UpdateMiniCrudRequest extends FormRequest
11{
12    /**
13     * The model parameter name
14     *
15     * @var string
16     */
17    protected $modelName = null;
18
19    /**
20     * Determine if the user is authorized to make this request.
21     *
22     * @return boolean
23     */
24    public function authorize()
25    {
26        return auth('backend')->check();
27    }
28
29    /**
30     * Get the validation rules that apply to the request.
31     *
32     * @return array
33     * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
34     * @phpcs:disable Generic.Metrics.NestingLevel.TooHigh
35     */
36    public function rules()
37    {
38        // phpcs:enable
39        $rules = [];
40        foreach ($this->{$this->modelName}->data as $iptName => $input) {
41            $input = \json_decode(\json_encode($input), true);
42            switch ($input['inputType']) {
43                case InputType::number->value:
44                    $rules = array_merge($rules, [
45                        "data.$iptName.value" => $this->compileValidate('required|numeric', $input)
46                    ]);
47                    break;
48                case InputType::videoYoutube->value:
49                    $rules = array_merge($rules, [
50                        "data.$iptName.value" => $this->compileValidate('regex:%([^"&?\/\s]{11})%i', $input)
51                    ]);
52                    break;
53                case InputType::videoVimeo->value:
54                    $rules = array_merge($rules, [
55                        "data.$iptName.value" => $this->compileValidate('regex:%([0-9]{8,10})%i', $input)
56                    ]);
57                    break;
58                case InputType::video->value:
59                    $rules = array_merge($rules, [
60                        "data.$iptName.value" => $this->compileValidate([
61                            'regex:%([0-9]{8,10}|[^"&?\/\s]{11})%i'
62                        ], $input)
63                    ]);
64                    break;
65                case InputType::string->value:
66                    $rules = array_merge($rules, [
67                        "data.$iptName.value" => $this->compileValidate('required|string|min:3', $input)
68                    ]);
69                    break;
70                case InputType::text->value:
71                    $mergeRules = $this->compileValidate('required|string|min:15', $input);
72                    $mergeRules = collect($mergeRules)
73                        ->map(function ($rule) {
74                            if (\strpos($rule, 'max:') !== false) {
75                                $max = \intval(str_replace('max:', '', $rule));
76                                return function ($attribute, $value, $fail) use ($max) {
77                                    if (\strlen(\strip_tags($value)) > $max) {
78                                        $fail("$attribute ne doit pas excĂ©der $max caractères");
79                                    }
80                                };
81                            }
82                            return $rule;
83                        });
84                    $rules      = array_merge($rules, [
85                        "data.$iptName.value" => $mergeRules
86                    ]);
87                    break;
88                case InputType::image->value:
89                    $required = $this->isUpdate() ? 'sometimes' : 'required';
90
91                    $ipt = $this->data[$iptName];
92                    $max = isset($ipt['dimensionsMax']);
93                    $dim = \is_string($input['dimensions']) ? collect(explode(
94                        ',',
95                        (isset($ipt['dimensionsMax']) and is_string($ipt['dimensionsMax'])) ?
96                            $ipt['dimensionsMax'] : $input['dimensions']
97                    ))->mapWithKeys(function ($v) {
98                        $v = explode(' ', $v);
99                        return [$v[0] => $v[1]];
100                    }) : $input['dimensions'];
101
102                    // * Adapt dimensions
103                    $sizes = (object)[
104                        'minHeight' => $dim['height'],
105                        'maxHeight' => $dim['height'],
106                        'minWith' => $dim['width'],
107                        'maxWith' => $dim['width'],
108                    ];
109                    $rules = array_merge($rules, [
110                        "data.$iptName.value" => [
111                            function (string $attribute, $value, callable $fail) use ($sizes) {
112                                return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
113                            }
114                        ],
115                        $this->compileValidate(
116                            implode('|', [
117                                $required,
118                                'image',
119                                'mimes:png,jpg,jpeg',
120                                sprintf(
121                                    'dimensions:%s=%d,%s=%d',
122                                    $max ? 'max_height' : 'height',
123                                    $dim['height'],
124                                    $max ? 'max_width' : 'width',
125                                    $dim['width']
126                                )
127                            ]),
128                            $input
129                        ),
130                        "data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input),
131                        "data.$iptName.title" => $this->compileValidate("$required|string|min:5", $input)
132                    ]);
133                    break;
134                case InputType::url->value:
135                    $rules = array_merge($rules, [
136                        "data.$iptName.value" => [
137                            'required', 'url',
138                            // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
139                            function ($attribute, $value, $fail) {
140                                try {
141                                    ToolboxHelper::assertNoInternalUrls($attribute, $value);
142                                    ToolboxHelper::assertNoInternalBoUrls($attribute, $value);
143                                } catch (ValidationException $e) {
144                                    $fail(collect($e->errors())->first()[0]);
145                                }
146                            }
147                        ]
148                    ]);
149                    break;
150                case InputType::boolean->value:
151                    $all    = $this->all();
152                    $nested = ToolboxHelper::dotStringToNestedArray(
153                        "data.$iptName.value",
154                        $this->input("data.$iptName.value") ? true : false
155                    );
156                    $all    = ToolboxHelper::arrayMergeRecursiveDistinct($all, $nested);
157                    $this->merge($all);
158                    $rules = array_merge($rules, [
159                        "data.$iptName.value" => 'boolean'
160                    ]);
161                    break;
162            } //end switch
163        } //end foreach
164        return $rules;
165    }
166
167    /**
168     * Undocumented function
169     *
170     * @param string|array $inputTypeValidate
171     * @param array        $input
172     * @return array
173     */
174    public function compileValidate(string|array $inputTypeValidate, array $input): array
175    {
176        if (\is_string($inputTypeValidate)) {
177            $inputTypeValidate = explode('|', $inputTypeValidate);
178        }
179        /** @var array|string */
180        $inputValidate = \collect($input)->get('validate', $input);
181        $inputValidate = \is_string($inputValidate) ? explode('|', $inputValidate) : $inputValidate;
182        foreach ($inputValidate as $validate) {
183            if (!\in_array($validate, $inputTypeValidate)) {
184                $inputTypeValidate[] = $validate;
185            }
186        }
187
188        $test = \collect($inputTypeValidate)->all();
189        $test = \collect($inputTypeValidate)->sort(function ($valueA, $valueB) {
190            $valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2;
191            $valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2;
192            return $valueA - $valueB;
193        })->unique()->all();
194
195        return \collect($inputTypeValidate)->unique()->sort(function ($valueA, $valueB) {
196            $valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2;
197            $valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2;
198            return $valueA - $valueB;
199        })->all();
200    }
201
202    /**
203     * Does the rulle need to come first ?
204     *
205     * @param string $rule
206     * @return boolean
207     */
208    private function ruleHasToComeFirst(string $rule): bool
209    {
210        $rule = \collect(\explode(':', $rule, 1))->filter()->first(null, '');
211        return \collect([
212            'nullable', 'present', 'required', 'required_if',
213            'required_unless', 'required_with', 'required_with_all',
214            'required_without', 'required_without_all', 'required_with_all',
215            'missing', 'missing_if', 'missing_unless',
216            'missing_with', 'missing_with_all',
217        ])->first(fn (string $firstRule) =>  \strpos($rule, $firstRule) === 0) ? true : false;
218    }
219
220    /**
221     * Is this request an update request ?
222     *
223     * @return boolean
224     */
225    private function isUpdate(): bool
226    {
227        return $this->isMethod('PUT');
228    }
229}