user(); // * Use rate limiter to prevent brute force sticker code if (RateLimiter::tooManyAttempts("participate:{$customer->id}", $perMinute = 5)) { return false; } RateLimiter::hit("participate:{$customer->id}"); return Gate::check('participate', Participation::class); } /** * Prepare the data for validation. * * @return void */ protected function prepareForValidation(): void { try { $this->merge([ 'unique_code' => Code::query()->where('id', Code::serialToInt( Str::upper(\strval($this->input('unique_code'))) ))->first() ?? false, ]); } catch (SerialCasterException) { // * Provoquer l'affichage code incorrect. $this->merge([ 'unique_code' => false, ]); } finally { $this->merge([ 'ean_code' => (string)$this->string('ean_code')->padLeft(13, '0'), 'game_rules' => $this->boolean('game_rules') ]); } /** @var \App\Models\Settings */ $settings = app(Settings::class); // ? Does the game use EAN Codes ? if ($settings->use_ean_codes) { /** * * Check si les codes ean sont utilisés, auquel cas * * on test celui envoyé pour savoir s'il est correct. * Modif demande vincent : * Tester code ean existe avec 13, puis 8 puis 7 chars * Si le code EAN est trouvé dans la liste, alors on prend l'objet correspondant, * sinon on prend le premier objet qui contient les 7 1er chiffres (cas des EAN pds) * * Dans la base chaque code ean doit être rentré dans sa valeur absolue * càd que les code ean 8 sont de longueur 8, 7 de longueur7 et 13 de longueur 13. */ $this->merge([ // * Union pour faire des recherches séparée en une seule requête. // ! ean_code is already str_padded to 13 'product' => Product::query()->where('ean_code', $this->post('ean_code')) ->union(Product::query()->where('ean_code', Str::limit($this->post('ean_code'), 8, ''))) ->union(Product::query()->where('ean_code', Str::limit($this->post('ean_code'), 7, ''))) ->first() ]); } //end if } /** * Get the validation rules that apply to the request. * * @return array */ public function rules(): array { /** @var \App\Models\Settings */ $settings = app(Settings::class); $rules = [ 'game_rules' => 'required|boolean|accepted', 'unique_code' => [ 'required', // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed function (string $attribute, $value, callable $fail) { // ? Le Code unique est resolved ? if ($value === false or !\is_object($value) or \get_class($value) !== Code::class) { $fail(trans('Code unique incorrect, veuillez réessayer.')); return; } /** @var \App\Models\Customer */ $customer = auth('frontend')->user(); /** @var \App\Models\Code $value */ // * Check si l'utilisateur n'a pas déjà utilisé ce code. $query = Participation::query() ->whereHas('code', fn (Builder $q) => $q->where('id', $value->id)) ->whereHas('customer', fn (Builder $q) => $q->where('id', $customer->id)); // ! Une seule participation avec un code donné par joueur if ($query->exists()) { $fail(trans('Vous avez déjà utilisé ce code unique.')); return; } // * Gestion du nombre d'utilisation d'un code. // ? Le code unique à été trop utilisé ? if ($value->has_been_used_too_many_times) { // * Ne pas laisser d'indices, message générique $fail(trans('Code unique incorrect, veuillez réessayer.')); return; } } ] ]; // ? Does the game use EAN Codes ? if ($settings->use_ean_codes) { $rules = \array_merge($rules, ['ean_code' => [ 'required', // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed function ($attribute, $value, $fail) { // phpcs:enable /** @var \App\Models\Produt|mixed */ $product = $this->input('product'); if ( empty($product) or !is_object($product) or !($product instanceof Model) or !$product->exists ) { $fail(trans('Le code barre entré est incorrect, veuillez réessayer.')); } } ]]); } return $rules; } /** * Get custom attributes for validator errors. * * @return array */ public function attributes(): array { return [ 'unique_code' => \trans('validation.custom.unique_code'), 'ean_code' => \trans('validation.custom.ean_code'), 'game_rules' => \trans('validation.custom.game_rules'), ]; } }