check(); } /** * Get the validation rules that apply to the request. * * @return array * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh * @phpcs:disable Generic.Metrics.NestingLevel.TooHigh */ public function rules() { // phpcs:enable $rules = []; foreach ($this->{$this->modelName}->data as $iptName => $input) { $input = \json_decode(\json_encode($input), true); switch ($input['inputType']) { case InputType::number->value: $rules = array_merge($rules, [ "data.$iptName.value" => $this->compileValidate('required|numeric', $input) ]); break; case InputType::videoYoutube->value: $rules = array_merge($rules, [ "data.$iptName.value" => $this->compileValidate('regex:%([^"&?\/\s]{11})%i', $input) ]); break; case InputType::videoVimeo->value: $rules = array_merge($rules, [ "data.$iptName.value" => $this->compileValidate('regex:%([0-9]{8,10})%i', $input) ]); break; case InputType::video->value: $rules = array_merge($rules, [ "data.$iptName.value" => $this->compileValidate([ 'regex:%([0-9]{8,10}|[^"&?\/\s]{11})%i' ], $input) ]); break; case InputType::string->value: $rules = array_merge($rules, [ "data.$iptName.value" => $this->compileValidate('required|string|min:3', $input) ]); break; case InputType::text->value: $mergeRules = $this->compileValidate('required|string|min:15', $input); $mergeRules = collect($mergeRules) ->map(function ($rule) { if (\strpos($rule, 'max:') !== false) { $max = \intval(str_replace('max:', '', $rule)); return function ($attribute, $value, $fail) use ($max) { if (\strlen(\strip_tags($value)) > $max) { $fail("$attribute ne doit pas excéder $max caractères"); } }; } return $rule; }); $rules = array_merge($rules, [ "data.$iptName.value" => $mergeRules ]); break; case InputType::image->value: $required = $this->isUpdate() ? 'sometimes' : 'required'; $ipt = $this->data[$iptName]; $max = isset($ipt['dimensionsMax']); $dim = \is_string($input['dimensions']) ? collect(explode( ',', (isset($ipt['dimensionsMax']) and is_string($ipt['dimensionsMax'])) ? $ipt['dimensionsMax'] : $input['dimensions'] ))->mapWithKeys(function ($v) { $v = explode(' ', $v); return [$v[0] => $v[1]]; }) : $input['dimensions']; // * Adapt dimensions $sizes = (object)[ 'minHeight' => $dim['height'], 'maxHeight' => $dim['height'], 'minWith' => $dim['width'], 'maxWith' => $dim['width'], ]; $rules = array_merge($rules, [ "data.$iptName.value" => [ function (string $attribute, $value, callable $fail) use ($sizes) { ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes); } ], $this->compileValidate( implode('|', [ $required, 'image', 'mimes:png,jpg,jpeg', sprintf( 'dimensions:%s=%d,%s=%d', $max ? 'max_height' : 'height', $dim['height'], $max ? 'max_width' : 'width', $dim['width'] ) ]), $input ), "data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input), "data.$iptName.title" => $this->compileValidate("$required|string|min:5", $input) ]); break; case InputType::url->value: $rules = array_merge($rules, [ "data.$iptName.value" => [ 'required', 'url', // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed function ($attribute, $value, $fail) { try { ToolboxHelper::assertNoInternalUrls($attribute, $value); ToolboxHelper::assertNoInternalBoUrls($attribute, $value); } catch (ValidationException $e) { $fail(collect($e->errors())->first()[0]); } } ] ]); break; case InputType::boolean->value: $all = $this->all(); $nested = ToolboxHelper::dotStringToNestedArray( "data.$iptName.value", $this->input("data.$iptName.value") ? true : false ); $all = ToolboxHelper::arrayMergeRecursiveDistinct($all, $nested); $this->merge($all); $rules = array_merge($rules, [ "data.$iptName.value" => 'boolean' ]); break; } //end switch } //end foreach return $rules; } /** * Undocumented function * * @param string|array $inputTypeValidate * @param array $input * @return array */ public function compileValidate(string|array $inputTypeValidate, array $input): array { if (\is_string($inputTypeValidate)) { $inputTypeValidate = explode('|', $inputTypeValidate); } /** @var array|string */ $inputValidate = \collect($input)->get('validate', $input); $inputValidate = \is_string($inputValidate) ? explode('|', $inputValidate) : $inputValidate; foreach ($inputValidate as $validate) { if (!\in_array($validate, $inputTypeValidate)) { $inputTypeValidate[] = $validate; } } $test = \collect($inputTypeValidate)->all(); $test = \collect($inputTypeValidate)->sort(function ($valueA, $valueB) { $valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2; $valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2; return $valueA - $valueB; })->unique()->all(); return \collect($inputTypeValidate)->unique()->sort(function ($valueA, $valueB) { $valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2; $valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2; return $valueA - $valueB; })->all(); } /** * Does the rulle need to come first ? * * @param string $rule * @return boolean */ private function ruleHasToComeFirst(string $rule): bool { $rule = \collect(\explode(':', $rule, 1))->filter()->first(null, ''); return \collect([ 'nullable', 'present', 'required', 'required_if', 'required_unless', 'required_with', 'required_with_all', 'required_without', 'required_without_all', 'required_with_all', 'missing', 'missing_if', 'missing_unless', 'missing_with', 'missing_with_all', ])->first(fn (string $firstRule) => \strpos($rule, $firstRule) === 0) ? true : false; } /** * Is this request an update request ? * * @return boolean */ private function isUpdate(): bool { return $this->isMethod('PUT'); } }