> */ public function rules(): array { $rules = [ 'salutation' => ['required', 'in:mr,ms'], 'first_name' => ['required', 'string', new PersonName], 'last_name' => ['required', 'string', new PersonName], 'email' => ['required', 'email', 'max:255'], 'phone' => ['nullable', 'string', 'max:30', 'regex:'.self::PHONE_PATTERN], 'message' => ['required', 'string', 'max:3000', $this->maxLinksRule()], 'accepted_data_protection' => ['accepted'], 'cf-turnstile-response' => ['required', new TurnstileToken($this->ip())], ]; if ($this->asksForSalesPartnership()) { $rules['sales_partnership'] = ['required', 'in:JA,NEIN']; $rules['sales_partnership_message'] = ['required_if:sales_partnership,JA', 'nullable', 'string', 'max:3000', $this->maxLinksRule()]; } return $rules; } /** * @return array */ public function messages(): array { return [ 'phone.regex' => __('contact.phone_invalid'), 'cf-turnstile-response.required' => __('form_protection.captcha_failed'), ]; } /** * Abfrage zur Vertriebspartnerschaft nur auf der Hauptseite und im Firmen-Shop. */ public function asksForSalesPartnership(): bool { $userShop = Util::getUserShop(); return ! $userShop || $userShop->id === 22; } protected function failedValidation(Validator $validator): void { FormSpamGuard::log($this, 'contact', 'validation', ['fields' => array_keys($validator->failed())]); parent::failedValidation($validator); } private function maxLinksRule(): Closure { return function (string $attribute, mixed $value, Closure $fail): void { if (preg_match_all('~https?://|www\.~i', (string) $value) > self::MAX_LINKS) { $fail(__('contact.too_many_links')); } }; } }