From 7a8a6e023d82b4bd1fb0601863cd0bbfe2d5e871 Mon Sep 17 00:00:00 2001 From: F4ilji Date: Tue, 22 Jul 2025 13:00:18 +0500 Subject: [PATCH] refactor ClientWidgetFormController; replace validation logic with SubmitWidgetFormAction for improved maintainability and clarity --- .../Widget/Actions/SubmitWidgetFormAction.php | 44 +++++++ .../Widget/Tasks/FindWidgetFormByIdTask.php | 13 +++ ...nerateWidgetFormValidationMessagesTask.php | 33 ++++++ .../GenerateWidgetFormValidationRulesTask.php | 69 +++++++++++ .../Tasks/StoreWidgetFormResponseTask.php | 16 +++ .../ClientWidgetFormController.php | 110 ++---------------- 6 files changed, 186 insertions(+), 99 deletions(-) create mode 100644 app/Containers/Widget/Actions/SubmitWidgetFormAction.php create mode 100644 app/Containers/Widget/Tasks/FindWidgetFormByIdTask.php create mode 100644 app/Containers/Widget/Tasks/GenerateWidgetFormValidationMessagesTask.php create mode 100644 app/Containers/Widget/Tasks/GenerateWidgetFormValidationRulesTask.php create mode 100644 app/Containers/Widget/Tasks/StoreWidgetFormResponseTask.php diff --git a/app/Containers/Widget/Actions/SubmitWidgetFormAction.php b/app/Containers/Widget/Actions/SubmitWidgetFormAction.php new file mode 100644 index 0000000..95173ea --- /dev/null +++ b/app/Containers/Widget/Actions/SubmitWidgetFormAction.php @@ -0,0 +1,44 @@ +findWidgetFormByIdTask->run($id); + + $rules = $this->generateWidgetFormValidationRulesTask->run($formData['columns'], $formData['id']); + $messages = $this->generateWidgetFormValidationMessagesTask->run($formData['columns']); + + $validator = Validator::make($requestData, $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + + $this->storeWidgetFormResponseTask->run($id, $validator->validated()); + + return [ + 'message' => $formData['send_message'], + 'status' => 'ok' + ]; + } +} diff --git a/app/Containers/Widget/Tasks/FindWidgetFormByIdTask.php b/app/Containers/Widget/Tasks/FindWidgetFormByIdTask.php new file mode 100644 index 0000000..cd37b9f --- /dev/null +++ b/app/Containers/Widget/Tasks/FindWidgetFormByIdTask.php @@ -0,0 +1,13 @@ +mapWithKeys(fn(array $column) => [ + // Ключом будет название поля, значением - массив его правил + $column['data']['name_field'] => $this->resolveRulesForColumn($column, $formId) + ]) + ->all(); + } + + /** + * Определяет и делегирует создание правил в зависимости от типа поля. + */ + private function resolveRulesForColumn(array $column, int $formId): array + { + $type = $column['type'] ?? 'default'; + + return match ($type) { + 'multiple_choice' => ['required', 'array', 'min:1'], + default => $this->buildRulesFromConfig($column, $formId), + }; + } + + /** + * Собирает стандартный набор правил валидации из конфигурации поля. + */ + private function buildRulesFromConfig(array $column, int $formId): array + { + $configRules = $column['data']['rules'] ?? []; + $validationRules = []; + + // Правила, которые просто включаются по флагу true + if (!empty($configRules['required'])) { + $validationRules[] = 'required'; + } + + // Правила, требующие значения (min, max, и т.д.) + foreach (['min', 'max'] as $rule) { + // Используем isset для корректной обработки значения '0' + if (isset($configRules[$rule])) { + $validationRules[] = "{$rule}:{$configRules[$rule]}"; + } + } + + // Сложные правила, требующие инстанцирования объектов + if (!empty($configRules['unique'])) { + $fieldName = $column['data']['name_field']; + $validationRules[] = new UniqueJsonField($formId, $fieldName); + } + + return $validationRules; + } +} diff --git a/app/Containers/Widget/Tasks/StoreWidgetFormResponseTask.php b/app/Containers/Widget/Tasks/StoreWidgetFormResponseTask.php new file mode 100644 index 0000000..69a864b --- /dev/null +++ b/app/Containers/Widget/Tasks/StoreWidgetFormResponseTask.php @@ -0,0 +1,16 @@ + $formId, + 'answers' => $validatedData, + ]); + } +} diff --git a/app/Containers/Widget/UI/API/Controllers/ClientWidgetFormController.php b/app/Containers/Widget/UI/API/Controllers/ClientWidgetFormController.php index ea99ab2..79f82b2 100644 --- a/app/Containers/Widget/UI/API/Controllers/ClientWidgetFormController.php +++ b/app/Containers/Widget/UI/API/Controllers/ClientWidgetFormController.php @@ -2,17 +2,20 @@ namespace App\Containers\Widget\UI\API\Controllers; -use App\Containers\Widget\Data\Rules\UniqueJsonField; +use App\Containers\Widget\Actions\SubmitWidgetFormAction; use App\Containers\Widget\Enums\CustomFormStatus; use App\Containers\Widget\Models\CustomForm; -use App\Containers\Widget\Models\CustomFormResponse; use App\Containers\Widget\UI\API\Transformers\FormResource; use App\Ship\Controllers\Controller; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\ValidationException; class ClientWidgetFormController extends Controller { + public function __construct( + private readonly SubmitWidgetFormAction $submitWidgetFormAction, + ) {} + public function single(string $id) { return new FormResource(CustomForm::query()->where('status', CustomFormStatus::PUBLISHED)->where('form_id', $id)->firstOrFail()); @@ -20,103 +23,12 @@ class ClientWidgetFormController extends Controller public function submit(int $id, Request $request) { - $data = CustomForm::findOrFail($id); - - - $rules = $this->generateValidationRules($data['columns'], $data['id']); - - - $messages = $this->generateValidationMessages($data['columns']); - - - $validateData = Validator::make($request->all(), $rules, $messages); - - - if ($validateData->fails()) { - return response()->json($validateData->errors(), 422); + try { + $result = $this->submitWidgetFormAction->run($id, $request->all()); + } catch (ValidationException $exception) { + return response()->json($exception->errors(), 422); } - $this->storeResponse($id, $validateData->validated()); - - - return response()->json([ - 'message' => $data['send_message'], - 'status' => 'ok' - ]); - } - - private function generateValidationRules(array $columns, int $id): array - { - $rules = []; - - foreach ($columns as $column) { - // Извлекаем информацию о поле - $name = $column['data']['name_field']; - $rulesForField = []; - - // Проверяем, является ли поле массивом (множественный выбор) - if ($column['type'] === 'multiple_choice') { - $rulesForField[] = 'required'; // Обязательно для множественного выбора - $rulesForField[] = 'array'; // Указывает, что это массив - $rulesForField[] = 'min:1'; // Минимум один элемент - $rules[$name] = $rulesForField; // Правила для каждого элемента массива - } else { - // Обработка обычных полей - if (!empty($column['data']['rules']['required'])) { - $rulesForField[] = 'required'; - } - - if (!empty($column['data']['rules']['min'])) { - $rulesForField[] = 'min:' . $column['data']['rules']['min']; - } - - if (!empty($column['data']['rules']['max'])) { - $rulesForField[] = 'max:' . $column['data']['rules']['max']; - } - - if (!empty($column['data']['rules']['unique']) && $column['data']['rules']['unique'] === true) { - $rulesForField[] = new UniqueJsonField($id, $name); - } - - $rules[$name] = $rulesForField; // Добавляем правила для обычного поля - } - } - - return $rules; - } - - private function generateValidationMessages(array $columns): array - { - $messages = []; - - foreach ($columns as $column) { - $name = $column['data']['name_field']; - - if (!empty($column['data']['rules']['required'])) { - $messages[$name . '.required'] = 'Поле обязательно для заполнения.'; - } - - if (!empty($column['data']['rules']['min'])) { - $messages[$name . '.min'] = 'Минимальная длина поля должна быть ' . $column['data']['rules']['min'] . ' символов.'; - } - - if (!empty($column['data']['rules']['max'])) { - $messages[$name . '.max'] = 'Максимальная длина поля должна быть ' . $column['data']['rules']['max'] . ' символов.'; - } - - if (!empty($column['data']['rules']['unique'])) { - $messages[$name . '.max'] = 'Поле должно быть уникальным'; - } - } - - return $messages; - } - - private function storeResponse(int $id, array $validateData): void - { - CustomFormResponse::create([ - 'custom_form_id' => $id, - 'answers' => $validateData, - ]); + return response()->json($result); } }