PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.5
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
← All changes | backend/src/Controllers/Form/FormSubmissionController.php +32 -147 1.1.1 → 1.5 View file →
@@ -10,22 +10,13 @@
10 10 use IvyForms\Common\Exceptions\ForbiddenException;
11 11 use IvyForms\Common\Exceptions\InvalidArgumentException;
12 12 use IvyForms\Common\Exceptions\NotFoundException;
13 13 use IvyForms\Common\Exceptions\ValidationException;
14 -use IvyForms\Common\Helpers\EntryHelper;
15 14 use IvyForms\Common\Sanitizer\Sanitizer;
16 15 use IvyForms\Controllers\Controller;
17 -use IvyForms\Factory\Entry\EntryFactory;
18 -use IvyForms\Services\Confirmation\ConfirmationService;
19 -use IvyForms\Services\Entry\EntryService;
20 -use IvyForms\Services\Field\FieldDuplicateValidationService;
21 -use IvyForms\Services\Field\FieldService;
22 -use IvyForms\Services\Field\FieldType;
23 -use IvyForms\Services\Form\FormService;
24 -use IvyForms\Services\Mailer\MailerService;
25 -use IvyForms\Services\Notification\NotificationService;
26 -use IvyForms\Services\Placeholder\PlaceholderService;
27 -use IvyForms\Services\Security\SecurityService;
16 +use IvyForms\Infrastructure\WP\REST\SubmissionMultipartReader;
17 +use IvyForms\Services\Submission\FormSubmissionService;
18 +use IvyForms\Services\Submission\SubmissionPayloadParser;
28 19 use IvyForms\Services\Translations\BackendStrings;
29 20 use WP_REST_Request;
30 21 use WP_REST_Response;
31 22
@@ -35,35 +26,13 @@
35 26 * @package IvyForms\Controllers\Form
36 27 */
37 28 class FormSubmissionController extends Controller
38 29 {
39 - private FormService $formService;
40 - private FieldService $fieldService;
41 - private FieldDuplicateValidationService $fieldDuplicateValidationService;
42 - private NotificationService $notificationService;
43 - private MailerService $mailerService;
44 - private EntryService $entryService;
45 - private SecurityService $securityService;
46 - private ConfirmationService $confirmationService;
30 + private FormSubmissionService $formSubmissionService;
47 31
48 - public function __construct(
49 - FormService $formService,
50 - FieldService $fieldService,
51 - FieldDuplicateValidationService $fieldDuplicateValidationService,
52 - NotificationService $notificationService,
53 - MailerService $mailerService,
54 - EntryService $entryService,
55 - SecurityService $securityService,
56 - ConfirmationService $confirmationService
57 - ) {
58 - $this->formService = $formService;
59 - $this->fieldService = $fieldService;
60 - $this->fieldDuplicateValidationService = $fieldDuplicateValidationService;
61 - $this->notificationService = $notificationService;
62 - $this->mailerService = $mailerService;
63 - $this->entryService = $entryService;
64 - $this->securityService = $securityService;
65 - $this->confirmationService = $confirmationService;
32 + public function __construct(FormSubmissionService $formSubmissionService)
33 + {
34 + $this->formSubmissionService = $formSubmissionService;
66 35 }
67 36
68 37 /**
69 38 * @param WP_REST_Request $data
@@ -72,129 +41,45 @@
72 41 *
73 42 * @throws InvalidArgumentException|NotFoundException|ForbiddenException
74 43 * @throws ValidationException
75 44 */
76 - public function handle(WP_REST_Request $data): WP_REST_Response
45 + protected function handle(WP_REST_Request $data): WP_REST_Response
77 46 {
78 47 Sanitizer::verifyNonce($data->get_header('X-WP-Nonce'));
79 48
80 - if (empty($data->get_params())) {
81 - throw new InvalidArgumentException(
82 - BackendStrings::getExceptionStrings()['invalid_request_data']
83 - );
84 - }
49 + $params = SubmissionPayloadParser::parseRequestPayload($data);
50 + $formId = Sanitizer::sanitizeId((int) ($params['formId'] ?? 0));
51 + Sanitizer::verifySubmissionNonce(isset($params['nonce']) ? (string) $params['nonce'] : null, $formId);
85 52
86 - $formId = Sanitizer::sanitizeId($data->get_param('formId'));
87 - Sanitizer::verifySubmissionNonce($data->get_param('nonce'), $formId);
53 + $uploadedFiles = SubmissionMultipartReader::resolveUploadedFiles($data);
54 + $result = $this->formSubmissionService->processSubmission($params, $uploadedFiles);
88 55
89 - if ($formId <= 0) {
90 - throw new InvalidArgumentException(
91 - BackendStrings::getExceptionStrings()['invalid_form_id']
92 - );
56 + if (!empty($result['requires_action'])) {
57 + return new WP_REST_Response([
58 + 'message' => BackendStrings::getCommonStrings()['ok'],
59 + 'data' => [
60 + 'success' => false,
61 + 'requires_action' => true,
62 + 'client_secret' => $result['client_secret'] ?? null,
63 + 'payment_intent_id' => $result['payment_intent_id'] ?? null,
64 + 'payment_method' => $result['payment_method'] ?? 'stripe',
65 + ],
66 + ], 200);
93 67 }
94 68
95 - $form = $this->formService->getFormById($formId);
96 - $formFields = $this->fieldService->getAllFields($form->getId());
97 -
98 - $this->fieldService->validateFieldsType($formFields);
99 -
100 - // Build fieldLabels mapping for placeholders
101 - $fieldLabels = PlaceholderService::buildFieldLabels($formFields);
102 -
103 - // Validate CAPTCHA if present using SecurityService (automatically determines provider and validates)
104 - $this->securityService->validateFormSubmission($data->get_params(), $formFields);
105 -
106 - // Sanitize form submission data based on field types
107 - $submissionData = Sanitizer::sanitizeFormSubmissionData($data->get_params(), $formFields);
108 -
109 - [$isDuplicate, $duplicateErrors] = $this->fieldDuplicateValidationService->checkDuplicateFieldValues(
110 - $formFields,
111 - $submissionData,
112 - $formId
113 - );
114 - if ($isDuplicate) {
69 + if (!empty($result['payment_error'])) {
115 70 return new WP_REST_Response([
116 - 'data' => [
117 - 'success' => null,
118 - 'entry' => ['stored' => false],
119 - 'confirmation' => null,
120 - 'is_duplicate' => true,
121 - 'duplicate_errors' => $duplicateErrors,
71 + 'message' => (string) (
72 + $result['message'] ?? BackendStrings::getPaymentStrings()['payment_failed']
73 + ),
74 + 'data' => [
75 + 'success' => false,
76 + 'payment_error' => true,
122 77 ],
123 78 ], 200);
124 79 }
125 80
126 - $entryId = null;
127 - $entry = [
128 - 'stored' => false
129 - ];
130 - /**
131 - * Allow to hook before form submission for integrations
132 - * @since 0.1.0
133 - *
134 - * Arguments:
135 - * - int $formId The ID of the form being submitted
136 - * - array $submissionData The form submission data (field values)
137 - * - array $formFields The form field definitions
138 - */
139 - do_action('ivyforms/form/before_submission', $formId, $submissionData, $formFields);
140 -
141 - if ($form->isStoreEntries()) {
142 - $entryData = EntryHelper::buildEntryData($formId);
143 - $entryObj = EntryFactory::create($entryData);
144 - $entryId = $this->entryService->getEntryManager()->createEntry($entryObj);
145 - $this->entryService->getEntryFieldManager()->addEntryFields($formFields, $entryId, $submissionData);
146 - $entry = [
147 - 'stored' => true,
148 - 'id' => $entryId,
149 - ];
150 - }
151 -
152 - // Build field and general entry data for placeholders
153 - $fieldData = PlaceholderService::buildFieldData($formFields, $submissionData);
154 - $generalData = PlaceholderService::buildGeneralData($entryId ?? 0, $submissionData);
155 -
156 - // Use NotificationService for notifications
157 - // Note: Notification messages are sanitized inside processNotifications() method
158 - // to allow signature images with data: URIs (using Sanitizer::sanitizeHtmlContent)
159 - $notificationsResult = $this->notificationService->processNotifications(
160 - $formId,
161 - $submissionData,
162 - $formFields,
163 - $fieldData,
164 - $generalData,
165 - $this->mailerService,
166 - $fieldLabels
167 - );
168 - // Use ConfirmationService for confirmations
169 - $confirmationMessage = $this->confirmationService->processConfirmations(
170 - $formId,
171 - $fieldData,
172 - $generalData,
173 - $fieldLabels
174 - );
175 -
176 - // Sanitize confirmation message HTML to preserve colors and formatting
177 - $safeConfirmationMessage = Sanitizer::sanitizeEditorContent($confirmationMessage);
178 -
179 - /**
180 - * Allow to hook after form submission for integrations
181 - * @since 0.1.0
182 - *
183 - * Arguments:
184 - * - int $formId The ID of the form being submitted
185 - * - array $submissionData The form submission data (field values)
186 - * - array $formFields The form field definitions
187 - * - int|null $entryId The entry ID if entry storage is enabled
188 - */
189 - do_action('ivyforms/form/after_submission', $formId, $submissionData, $formFields, $entryId);
190 -
191 81 return new WP_REST_Response([
192 - 'message' => BackendStrings::getCommonStrings()['ok'],
193 - 'data' => [
194 - 'success' => $notificationsResult,
195 - 'entry' => $entry,
196 - 'confirmation' => $safeConfirmationMessage,
197 - ],
82 + 'data' => $result,
198 83 ], 200);
199 84 }
200 85 }