*/ private const ALLOWED_COUNTRIES = [ Country::france, Country::belgium, ]; /** @var list */ private const PROFILES = [ 'consommateur', 'eleveur', ]; private ?Country $selectedCountry = null; public function authorize(): bool { // NOTE: Public form return true; } #[\Override] public function prepareForValidation(): void { $countryInput = $this->string('country')->trim()->value(); $matchedCountry = Country::tryFromIso2($countryInput); if ($matchedCountry && in_array($matchedCountry, self::ALLOWED_COUNTRIES, true)) { $this->selectedCountry = $matchedCountry; } } /** * @return array */ public function rules(): array { ToolboxHelper::validateRecaptcha($this); $allowedIso2 = array_map(static fn(Country $c): string => $c->iso2(), self::ALLOWED_COUNTRIES); $postalCodeRule = $this->selectedCountry !== null ? PostalCode::forCountry($this->selectedCountry->iso2()) : 'string'; return [ 'lastName' => ['required', 'string', 'min:3', 'max:50'], 'firstName' => ['required', 'string', 'min:3', 'max:50'], 'email' => ['required', 'string', 'email:strict,rfc,spoof', 'max:255'], 'phone' => ['required', 'phone:' . ($this->selectedCountry?->iso2() ?? implode(',', $allowedIso2))], 'profile' => ['required', 'string', Rule::in(self::PROFILES)], 'company' => ['nullable', 'string', 'min:2', 'max:60'], 'postalCode' => ['nullable', 'required_with:city,country', $postalCodeRule], 'city' => ['nullable', 'required_with:postalCode,country', 'string', 'min:2', 'max:60'], 'country' => ['nullable', 'required_with:city,postalCode', Rule::in($allowedIso2)], 'subject' => ['required', 'string', 'min:3', 'max:100'], 'message' => ['required', 'string', 'min:30', 'max:255'], 'attachment' => ['nullable', 'file', 'max:2048', 'mimes:jpg,jpeg,png', 'extensions:jpg,jpeg,png'], 'acceptsUsage' => ['required', 'accepted'], ]; } /** * @return array */ #[\Override] public function messages(): array { $countryLabels = implode(', ', array_map( static fn(Country $country): string => $country->label('fr'), self::ALLOWED_COUNTRIES )); return [ 'phone.phone' => "Le numéro de téléphone doit être un numéro valide pour : {$countryLabels}.", 'postalCode.postal_code' => "Le code postal doit être valide pour le pays sélectionné ({$countryLabels}).", 'country.in' => "Le pays sélectionné doit être l'un des suivants : {$countryLabels}.", 'acceptsUsage.accepted' => "Vous devez accepter l'utilisation de vos données personnelles.", 'g-recaptcha-response.required' => 'Veuillez valider le reCAPTCHA.', ]; } #[\Override] public function attributes(): array { return [ 'lastName' => 'nom', 'firstName' => 'prénom', 'email' => 'adresse email', 'phone' => 'téléphone', 'profile' => 'profil', 'company' => 'société', 'postalCode' => 'code postal', 'city' => 'ville', 'country' => 'pays', 'subject' => 'sujet', 'message' => 'message', 'attachment' => 'pièce jointe', 'acceptsUsage' => 'conditions d\'utilisation', 'g-recaptcha-response' => 'reCAPTCHA', ]; } protected function rateLimitPrefix(): string { return 'contact'; } protected function rateLimitMaxAttempts(): int { return 3; } protected function rateLimitMessageKey(): string { return 'validation.rate_limit.too_many_attempts'; } public function withValidator(Validator $validator): void { $validator->after(fn(Validator $v) => $this->applyEmailRateLimit($v)); } }