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 0.8.1 → 1.5 View file →
@@ -6,30 +6,17 @@
6 6 */
7 7
8 8 namespace IvyForms\Controllers\Form;
9 9
10 -// phpcs:disable PSR1.Files.SideEffects
11 -if (!defined('ABSPATH')) {
12 - exit; // Exit if accessed directly
13 -}
14 -
15 10 use IvyForms\Common\Exceptions\ForbiddenException;
16 11 use IvyForms\Common\Exceptions\InvalidArgumentException;
17 12 use IvyForms\Common\Exceptions\NotFoundException;
18 13 use IvyForms\Common\Exceptions\ValidationException;
19 -use IvyForms\Common\Helpers\EntryHelper;
20 14 use IvyForms\Common\Sanitizer\Sanitizer;
21 15 use IvyForms\Controllers\Controller;
22 -use IvyForms\Factory\Entry\EntryFactory;
23 -use IvyForms\Services\Confirmation\ConfirmationService;
24 -use IvyForms\Services\Entry\EntryService;
25 -use IvyForms\Services\Field\FieldService;
26 -use IvyForms\Services\Field\FieldType;
27 -use IvyForms\Services\Form\FormService;
28 -use IvyForms\Services\Mailer\MailerService;
29 -use IvyForms\Services\Notification\NotificationService;
30 -use IvyForms\Services\Placeholder\PlaceholderService;
31 -use IvyForms\Services\Security\SecurityService;
16 +use IvyForms\Infrastructure\WP\REST\SubmissionMultipartReader;
17 +use IvyForms\Services\Submission\FormSubmissionService;
18 +use IvyForms\Services\Submission\SubmissionPayloadParser;
32 19 use IvyForms\Services\Translations\BackendStrings;
33 20 use WP_REST_Request;
34 21 use WP_REST_Response;
35 22
@@ -39,32 +26,13 @@
39 26 * @package IvyForms\Controllers\Form
40 27 */
41 28 class FormSubmissionController extends Controller
42 29 {
43 - private FormService $formService;
44 - private FieldService $fieldService;
45 - private NotificationService $notificationService;
46 - private MailerService $mailerService;
47 - private EntryService $entryService;
48 - private SecurityService $securityService;
49 - private ConfirmationService $confirmationService;
30 + private FormSubmissionService $formSubmissionService;
50 31
51 - public function __construct(
52 - FormService $formService,
53 - FieldService $fieldService,
54 - NotificationService $notificationService,
55 - MailerService $mailerService,
56 - EntryService $entryService,
57 - SecurityService $securityService,
58 - ConfirmationService $confirmationService
59 - ) {
60 - $this->formService = $formService;
61 - $this->fieldService = $fieldService;
62 - $this->notificationService = $notificationService;
63 - $this->mailerService = $mailerService;
64 - $this->entryService = $entryService;
65 - $this->securityService = $securityService;
66 - $this->confirmationService = $confirmationService;
32 + public function __construct(FormSubmissionService $formSubmissionService)
33 + {
34 + $this->formSubmissionService = $formSubmissionService;
67 35 }
68 36
69 37 /**
70 38 * @param WP_REST_Request $data
@@ -73,128 +41,45 @@
73 41 *
74 42 * @throws InvalidArgumentException|NotFoundException|ForbiddenException
75 43 * @throws ValidationException
76 44 */
77 - public function handle(WP_REST_Request $data): WP_REST_Response
45 + protected function handle(WP_REST_Request $data): WP_REST_Response
78 46 {
79 47 Sanitizer::verifyNonce($data->get_header('X-WP-Nonce'));
80 48
81 - if (empty($data->get_params())) {
82 - throw new InvalidArgumentException(
83 - BackendStrings::getExceptionStrings()['invalid_request_data']
84 - );
85 - }
49 + $params = SubmissionPayloadParser::parseRequestPayload($data);
50 + $formId = Sanitizer::sanitizeId((int) ($params['formId'] ?? 0));
51 + Sanitizer::verifySubmissionNonce(isset($params['nonce']) ? (string) $params['nonce'] : null, $formId);
86 52
87 - $formId = Sanitizer::sanitizeId($data->get_param('formId'));
88 - Sanitizer::verifySubmissionNonce($data->get_param('nonce'), $formId);
53 + $uploadedFiles = SubmissionMultipartReader::resolveUploadedFiles($data);
54 + $result = $this->formSubmissionService->processSubmission($params, $uploadedFiles);
89 55
90 - if ($formId <= 0) {
91 - throw new InvalidArgumentException(
92 - BackendStrings::getExceptionStrings()['invalid_form_id']
93 - );
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);
94 67 }
95 68
96 - $form = $this->formService->getFormById($formId);
97 - $formFields = $this->fieldService->getAllFields($form->getId());
98 -
99 - $this->fieldService->validateFieldsType($formFields);
100 -
101 - // Build fieldLabels mapping for placeholders
102 - $fieldLabels = PlaceholderService::buildFieldLabels($formFields);
103 -
104 - // Validate CAPTCHA if present using SecurityService (automatically determines provider and validates)
105 - $this->securityService->validateFormSubmission($data->get_params(), $formFields);
106 -
107 - // Sanitize form submission data based on field types
108 - $submissionData = Sanitizer::sanitizeFormSubmissionData($data->get_params(), $formFields);
109 -
110 - [$isDuplicate, $duplicateErrors] = $this->fieldService->checkDuplicateFieldValues(
111 - $formFields,
112 - $submissionData,
113 - $formId
114 - );
115 - if ($isDuplicate) {
69 + if (!empty($result['payment_error'])) {
116 70 return new WP_REST_Response([
117 - 'data' => [
118 - 'success' => null,
119 - 'entry' => ['stored' => false],
120 - 'confirmation' => null,
121 - 'is_duplicate' => true,
122 - 'duplicate_errors' => $duplicateErrors,
71 + 'message' => (string) (
72 + $result['message'] ?? BackendStrings::getPaymentStrings()['payment_failed']
73 + ),
74 + 'data' => [
75 + 'success' => false,
76 + 'payment_error' => true,
123 77 ],
124 78 ], 200);
125 79 }
126 80
127 - $entryId = null;
128 - $entry = [
129 - 'stored' => false
130 - ];
131 - /**
132 - * Allow to hook before form submission for integrations
133 - * @since 0.1.0
134 - *
135 - * Arguments:
136 - * - int $formId The ID of the form being submitted
137 - * - array $submissionData The form submission data (field values)
138 - * - array $formFields The form field definitions
139 - */
140 - do_action('ivyforms/form/before_submission', $formId, $submissionData, $formFields);
141 -
142 - if ($form->isStoreEntries()) {
143 - $entryData = EntryHelper::buildEntryData($formId);
144 - $entryObj = EntryFactory::create($entryData);
145 - $entryId = $this->entryService->getEntryManager()->createEntry($entryObj);
146 - $this->entryService->getEntryFieldManager()->addEntryFields($formFields, $entryId, $submissionData);
147 - $entry = [
148 - 'stored' => true,
149 - 'id' => $entryId,
150 - ];
151 - }
152 -
153 - // Build field and general entry data for placeholders
154 - $fieldData = PlaceholderService::buildFieldData($formFields, $submissionData);
155 - $generalData = PlaceholderService::buildGeneralData($entryId ?? 0, $submissionData);
156 -
157 - // Use NotificationService for notifications
158 - // Note: Notification messages are sanitized inside processNotifications() method
159 - // to allow signature images with data: URIs (using Sanitizer::sanitizeHtmlContent)
160 - $notificationsResult = $this->notificationService->processNotifications(
161 - $formId,
162 - $submissionData,
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 }