174 lines
6.9 KiB
PHP
174 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Requests\Fo;
|
|
|
|
use App\Enums\CodeType;
|
|
use App\Models\Code;
|
|
use App\Models\Participation;
|
|
use App\Models\Product;
|
|
use App\Models\Settings;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Foundation\Http\FormRequest;
|
|
use Illuminate\Support\Facades\Gate;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Illuminate\Support\Str;
|
|
use Kwaadpepper\Serial\Exceptions\SerialCasterException;
|
|
|
|
class ParticipateRequest extends FormRequest
|
|
{
|
|
/**
|
|
* Determine if the user is authorized to make this request.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function authorize(): bool
|
|
{
|
|
/** @var \App\Models\Customer */
|
|
$customer = auth('frontend')->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
|
|
{
|
|
/** @var \App\Models\Settings */
|
|
$settings = app(Settings::class);
|
|
if ($settings->code_type->equals(CodeType::unique) || $settings->code_type->equals(CodeType::both)) {
|
|
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([
|
|
'game_rules' => $this->boolean('game_rules'),
|
|
]);
|
|
}
|
|
}
|
|
if ($settings->code_type->equals(CodeType::ean) || $settings->code_type->equals(CodeType::both)) {
|
|
/**
|
|
* * 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([
|
|
'ean_code' => (string) $this->string('ean_code')->padLeft(13, '0'),
|
|
// * 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(),
|
|
'game_rules' => $this->boolean('game_rules'),
|
|
]);
|
|
} //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',
|
|
];
|
|
|
|
// ? Does the game use unique Codes ?
|
|
if ($settings->code_type->equals(CodeType::unique) || $settings->code_type->equals(CodeType::both)) {
|
|
$rules = \array_merge($rules, ['unique_code' => [
|
|
'required',
|
|
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
|
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('front.messages.unique_code_invalid'));
|
|
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('front.messages.unique_code_already_used'));
|
|
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('front.messages.unique_code_invalid'));
|
|
return;
|
|
}
|
|
}
|
|
]]);
|
|
} //end if
|
|
|
|
// ? Does the game use EAN Codes ?
|
|
if ($settings->code_type->equals(CodeType::ean) || $settings->code_type->equals(CodeType::both)) {
|
|
$rules = \array_merge($rules, ['ean_code' => [
|
|
'required',
|
|
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
|
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('front.messages.barcode_invalid'));
|
|
}
|
|
}
|
|
]]);
|
|
}
|
|
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'),
|
|
];
|
|
}
|
|
}
|