ldc-legaulois/app/Http/Requests/Bo/BlockPage/UpdateBlockRequest.php
2026-09-25 16:25:31 +02:00

202 lines
6.6 KiB
PHP

<?php
namespace App\Http\Requests\Bo\BlockPage;
use App\Enums\Block\BlockContentTypeEnum;
use App\Enums\BlockTypeEnum;
use App\Http\Requests\Bo\UpdateMiniCrudRequest;
use App\Traits\Requests\HasPicture;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
class UpdateBlockRequest extends UpdateMiniCrudRequest
{
use HasPicture;
protected $modelName = 'block';
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return Gate::check('update', $this->route($this->modelName));
}
/**
* Prepare the data for validation.
*/
protected function prepareForValidation(): void
{
$data = $this->input('data', []);
$block = $this->route('block');
$fields = json_decode(json_encode($block->data), true);
if ($block->type === BlockTypeEnum::redirection) {
$data = $this->processBlockData($data, $fields);
if (isset($data['article_id']['value']) && is_array($data['article_id']['value'])) {
$article = $data['article_id']['value'][0] ?? null;
$data['article_id']['value'] = $article['id'] ?? null;
}
} else {
foreach ($fields as $key => $field) {
if (isset($data[$key])) {
$submitted = $data[$key];
if (is_array($submitted)) {
$fields[$key] = array_merge($field, $submitted);
} else {
$fields[$key]['value'] = $submitted;
}
}
}
$data = $fields;
}
$this->merge(['data' => $data]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$parentRules = parent::rules();
$block = $this->route('block');
$rules = [
'data' => 'present|array',
'data.*' => 'required|array',
];
if ($block->type === BlockTypeEnum::redirection) {
$rules['data.block_type.value'] = ['required', Rule::in(BlockContentTypeEnum::toValues())];
$rules = array_merge($rules, $this->resolveRedirectionRules());
}
return array_merge($parentRules, $rules);
}
public function attributes(): array
{
return [
'data.cta_url.value' => 'redirection',
'data.cta_label.value' => 'du bouton',
'data.block_type.value' => 'type de bloc',
'data.article_id.value' => 'article lié',
'data.title.value' => 'titre',
'data.position.value' => 'position',
'data.picture.value' => 'pictogramme',
'data.picture.alt' => 'pictogramme Alt',
'data.picture.title' => 'pictogramme Title',
];
}
protected function failedValidation(Validator $validator)
{
$errors = collect($validator->errors()->all())->join("\n");
session()->flash('error', 'Liste des erreurs :' . "\n" . $errors);
throw new HttpResponseException(
response()->json([
'message' => 'Erreur de validation.',
'errors' => $validator->errors(),
], 422)
);
}
/**
* Normalize input data and apply showWhen visibility logic for redirection blocks.
*
* @param array $data The raw input data from the request.
* @param array $fields The block field configuration (including showWhen rules).
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
private function processBlockData(array $data, array $fields): array
{
foreach ($data as $key => $item) {
if (! isset($item['value'])) {
$data[$key] = ['value' => $item];
}
}
foreach ($fields as $fieldName => $fieldConfig) {
if (! isset($fieldConfig['showWhen'])) {
continue;
}
$shouldShow = true;
foreach ($fieldConfig['showWhen'] as $dependentField => $allowedValues) {
if (! in_array($data[$dependentField]['value'] ?? null, (array) $allowedValues)) {
$shouldShow = false;
break;
}
}
if (! $shouldShow) {
$data[$fieldName] = ['validate' => 'nullable', 'required' => false, 'value' => null];
} else {
$data[$fieldName]['required'] = true;
unset($data[$fieldName]['validate']);
}
}
return $data;
}
/**
* Resolve validation rules for redirection block fields dynamically.
*
* builds a rules array based on:
* - The block's field config (validate key) as fallback.
* - The field's required flag set during prepareForValidation to either
* enforce "required" or replace it with "nullable".
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
private function resolveRedirectionRules(): array
{
$data = $this->input('data', []);
$parentRules = parent::rules();
$block = $this->route('block');
$config = json_decode(json_encode($block->data), true);
$rules = [];
foreach ($data as $fieldName => $item) {
if ($fieldName === 'block_type' || $fieldName === 'position') {
continue;
}
$isRequired = $item['required'] ?? true;
$baseRules = $parentRules["data.{$fieldName}.value"]
?? $config[$fieldName]['validate']
?? [];
if (is_string($baseRules)) {
$baseRules = explode('|', $baseRules);
}
if (empty($baseRules)) {
continue;
}
if (! $isRequired) {
$baseRules = array_filter($baseRules, fn ($r) => $r !== 'required');
$baseRules[] = 'nullable';
$baseRules = array_values($baseRules);
} else {
if (! in_array('required', $baseRules)) {
array_unshift($baseRules, 'required');
}
}
$rules["data.{$fieldName}.value"] = $baseRules;
}
return $rules;
}
}