PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
← All changes | app/Modules/Form/FormHandler.php +538 -109 3.6.626.2.14 View file →
@@ -1,38 +1,48 @@
1 1 <?php
2 2
3 3 namespace FluentForm\App\Modules\Form;
4 4
5 -use FluentForm\App\Databases\Migrations\FormSubmissionDetails;
5 +use FluentForm\Database\Migrations\SubmissionDetails;
6 6 use FluentForm\App\Helpers\Helper;
7 7 use FluentForm\App\Modules\Activator;
8 -use FluentForm\App\Modules\Entries\Entries;
9 8 use FluentForm\App\Modules\ReCaptcha\ReCaptcha;
9 +use FluentForm\App\Modules\HCaptcha\HCaptcha;
10 +use FluentForm\App\Modules\Turnstile\Turnstile;
10 11 use FluentForm\App\Services\Browser\Browser;
11 12 use FluentForm\App\Services\FormBuilder\ShortCodeParser;
13 +use FluentForm\App\Services\Submission\SubmissionService;
12 14 use FluentForm\Framework\Foundation\Application;
13 15 use FluentForm\Framework\Helpers\ArrayHelper as Arr;
14 16 use FluentForm\Framework\Helpers\ArrayHelper;
15 17
18 +/* @deprecated Use class \FluentForm\App\Http\Controllers\SubmissionHandlerController */
19 +
16 20 class FormHandler
17 21 {
18 22 /**
23 + * App instance
24 + *
19 25 * @var \FluentForm\Framework\Foundation\Application
20 26 */
21 27 protected $app;
22 28
23 29 /**
30 + * Request object
31 + *
24 32 * @var \FluentForm\Framework\Request\Request
25 33 */
26 34 protected $request;
27 35
28 36 /**
37 + * Form Data
38 + *
29 39 * @var array $formData
30 40 */
31 41 protected $formData;
32 42
33 43 /**
34 - * The fluent form object.
44 + * The Fluent Forms object.
35 45 *
36 46 * @var \stdClass
37 47 */
38 48 protected $form;
@@ -51,8 +61,9 @@
51 61 /**
52 62 * Set the form using it's ID.
53 63 *
54 64 * @param $formId
65 + *
55 66 * @return $this
56 67 */
57 68 public function setForm($formId)
58 69 {
@@ -67,9 +78,9 @@
67 78 {
68 79 // Parse the url encoded data from the request object.
69 80 parse_str($this->app->request->get('data'), $data);
70 81
71 - $data['_wp_http_referer'] = urldecode( $data['_wp_http_referer']);
82 + $data['_wp_http_referer'] = urldecode($data['_wp_http_referer']);
72 83
73 84 // Merge it back again to the request object.
74 85 $this->app->request->merge(['data' => $data]);
75 86
@@ -76,8 +87,15 @@
76 87 $formId = intval($this->app->request->get('form_id'));
77 88
78 89 $this->setForm($formId);
79 90
91 + if (!$this->form) {
92 + wp_send_json([
93 + 'errors' => [],
94 + 'message' => 'Sorry, No corresponding form found',
95 + ], 423);
96 + }
97 +
80 98 // Parse the form and get the flat inputs with validations.
81 99 $fields = FormFieldsParser::getInputs($this->form, ['rules', 'raw']);
82 100
83 101 // Sanitize the data properly.
@@ -88,26 +106,64 @@
88 106
89 107 // Prepare the data to be inserted to the DB.
90 108 $insertData = $this->prepareInsertData();
91 109
92 - if ($this->isSpam($this->formData, $this->form)) {
110 + if ($this->isAkismetSpam($this->formData, $this->form)) {
93 111 $insertData['status'] = 'spam';
94 112 $this->handleSpamError();
95 113 }
96 114
97 - do_action('fluentform_before_insert_submission', $insertData, $data, $this->form);
115 + do_action_deprecated(
116 + 'fluentform_before_insert_submission',
117 + [
118 + $insertData,
119 + $data,
120 + $this->form
121 + ],
122 + FLUENTFORM_FRAMEWORK_UPGRADE,
123 + 'fluentform/before_insert_submission',
124 + 'Use fluentform/before_insert_submission instead of fluentform_before_insert_submission.'
125 + );
98 126
127 + do_action('fluentform/before_insert_submission', $insertData, $data, $this->form);
128 +
99 129 if ($this->form->has_payment) {
100 - do_action('fluentform_before_insert_payment_form', $insertData, $data, $this->form);
130 + do_action_deprecated(
131 + 'fluentform_before_insert_payment_form',
132 + [
133 + $insertData,
134 + $data,
135 + $this->form
136 + ],
137 + FLUENTFORM_FRAMEWORK_UPGRADE,
138 + 'fluentform/before_insert_payment_form',
139 + 'Use fluentform/before_insert_payment_form instead of fluentform_before_insert_payment_form.'
140 + );
141 +
142 + do_action('fluentform/before_insert_payment_form', $insertData, $data, $this->form);
101 143 }
102 144
103 - $insertId = wpFluent()->table('fluentform_submissions')->insert($insertData);
145 + $insertId = wpFluent()->table('fluentform_submissions')->insertGetId($insertData);
104 146
147 + do_action('fluentform/notify_on_form_submit', $insertId, $this->formData, $this->form);
148 +
105 149 $uidHash = md5(wp_generate_uuid4() . $insertId);
106 150 Helper::setSubmissionMeta($insertId, '_entry_uid_hash', $uidHash, $formId);
107 151
108 - do_action('fluentform_before_form_actions_processing', $insertId, $this->formData, $this->form);
152 + do_action_deprecated(
153 + 'fluentform_before_form_actions_processing',
154 + [
155 + $insertId,
156 + $this->formData,
157 + $this->form
158 + ],
159 + FLUENTFORM_FRAMEWORK_UPGRADE,
160 + 'fluentform/before_form_actions_processing',
161 + 'Use fluentform/before_form_actions_processing instead of fluentform_before_form_actions_processing.'
162 + );
109 163
164 + do_action('fluentform/before_form_actions_processing', $insertId, $this->formData, $this->form);
165 +
110 166 $result = $this->processFormSubmissionData($insertId, $this->formData, $this->form);
111 167
112 168 wp_send_json_success($result, 200);
113 169 }
@@ -115,13 +171,13 @@
115 171 public function processFormSubmissionData($insertId, $formData, $form)
116 172 {
117 173 if ($insertId) {
118 174 ob_start();
119 - $entries = new Entries();
120 - $entries->recordEntryDetails($insertId, $form->id, $formData);
175 + $submissionService = new SubmissionService();
176 + $submissionService->recordEntryDetails($insertId, $form->id, $formData);
121 177 $isError = ob_get_clean();
122 178 if ($isError) {
123 - FormSubmissionDetails::migrate();
179 + SubmissionDetails::migrate();
124 180 }
125 181 }
126 182
127 183 $returnData = $this->getReturnData($insertId, $form, $formData);
@@ -127,10 +183,16 @@
127 183 $returnData = $this->getReturnData($insertId, $form, $formData);
128 184
129 185 $error = '';
130 186 try {
131 - $this->app->doAction(
132 - 'fluentform_submission_inserted',
187 +
188 + /*
189 + * We will keep this old hook for backward compatability.
190 + */
191 + do_action('fluentform_submission_inserted', $insertId, $formData, $form);
192 +
193 + do_action(
194 + 'fluentform/submission_inserted',
133 195 $insertId,
134 196 $formData,
135 197 $form
136 198 );
@@ -136,14 +198,27 @@
136 198 );
137 199
138 200 Helper::setSubmissionMeta($insertId, 'is_form_action_fired', 'yes');
139 201
140 - $this->app->doAction(
202 + do_action_deprecated(
141 203 'fluentform_submission_inserted_' . $form->type . '_form',
204 + [
205 + $insertId,
206 + $formData,
207 + $form
208 + ],
209 + FLUENTFORM_FRAMEWORK_UPGRADE,
210 + 'fluentform/submission_inserted',
211 + 'Use fluentform/submission_inserted_' . $form->type . '_form' . ' instead of fluentform_submission_inserted_' . $form->type . '_form'
212 + );
213 +
214 + do_action(
215 + 'fluentform/submission_inserted_' . $form->type . '_form',
142 216 $insertId,
143 217 $formData,
144 218 $form
145 219 );
220 +
146 221 } catch (\Exception $e) {
147 222 if (defined('WP_DEBUG') && WP_DEBUG) {
148 223 $error = $e->getMessage();
149 224 }
@@ -148,14 +223,26 @@
148 223 $error = $e->getMessage();
149 224 }
150 225 }
151 226
152 - do_action('fluenform_before_submission_confirmation', $insertId, $formData, $form);
227 + do_action_deprecated(
228 + 'fluentform_before_submission_confirmation',
229 + [
230 + $insertId,
231 + $formData,
232 + $form
233 + ],
234 + FLUENTFORM_FRAMEWORK_UPGRADE,
235 + 'fluentform/before_submission_confirmation',
236 + 'Use fluentform/before_submission_confirmation instead of fluentform_before_submission_confirmation.'
237 + );
153 238
239 + do_action('fluentform/before_submission_confirmation', $insertId, $formData, $form);
240 +
154 241 return [
155 242 'insert_id' => $insertId,
156 - 'result' => $returnData,
157 - 'error' => $error
243 + 'result' => $returnData,
244 + 'error' => $error,
158 245 ];
159 246 }
160 247
161 248 public function getReturnData($insertId, $form, $formData)
@@ -167,45 +254,61 @@
167 254 ->first();
168 255
169 256 $form->settings = $formSettings ? json_decode($formSettings->value, true) : [];
170 257 }
171 -
172 - $confirmation = apply_filters(
258 + $confirmation = $form->settings['confirmation'];
259 + $confirmation = apply_filters_deprecated(
173 260 'fluentform_form_submission_confirmation',
174 - $form->settings['confirmation'],
261 + [
262 + $confirmation,
263 + $formData,
264 + $form
265 + ],
266 + FLUENTFORM_FRAMEWORK_UPGRADE,
267 + 'fluentform/form_submission_confirmation',
268 + 'Use fluentform/form_submission_confirmation instead of fluentform_form_submission_confirmation.'
269 + );
270 +
271 + $confirmation = $this->app->applyFilters(
272 + 'fluentform/form_submission_confirmation',
273 + $confirmation,
175 274 $formData,
176 275 $form
177 276 );
178 277
179 - if ($confirmation['redirectTo'] == 'samePage') {
278 + if ('samePage' == $confirmation['redirectTo']) {
279 +
280 + $confirmation['messageToShow'] = fluentform_sanitize_html($confirmation['messageToShow']);
281 +
282 + $confirmation['messageToShow'] = do_shortcode($confirmation['messageToShow']);
283 +
284 + $confirmation['messageToShow'] = apply_filters('fluentform/submission_message_parse',
285 + $confirmation['messageToShow'], $insertId, $formData, $form);
180 286
181 - $confirmation['messageToShow'] = apply_filters('fluentform_submission_message_parse', $confirmation['messageToShow'], $insertId, $formData, $form);
182 -
183 -
184 287 $message = ShortCodeParser::parse(
185 288 $confirmation['messageToShow'],
186 289 $insertId,
187 290 $formData,
188 - $form
291 + $form,
292 + false,
293 + true
189 294 );
190 295
191 -
192 296 $message = $message ? $message : 'The form has been successfully submitted.';
193 297
194 298 $returnData = [
195 - 'message' => do_shortcode($message),
196 - 'action' => $confirmation['samePageFormBehavior'],
299 + 'message' => $message,
300 + 'action' => $confirmation['samePageFormBehavior'],
197 301 ];
198 -
199 302 } else {
200 303 $redirectUrl = Arr::get($confirmation, 'customUrl');
201 304
202 - if ($confirmation['redirectTo'] == 'customPage') {
305 + if ('customPage' == $confirmation['redirectTo']) {
203 306 $redirectUrl = get_permalink($confirmation['customPage']);
204 307 }
205 308
206 309 if (
207 - (Arr::get($confirmation, 'enable_query_string') == 'yes') &&
310 + ('yes' == Arr::get($confirmation, 'enable_query_string')) &&
208 311 Arr::get($confirmation, 'query_strings')
209 312 ) {
210 313 if (strpos($redirectUrl, '?')) {
211 314 $redirectUrl .= '&' . Arr::get($confirmation, 'query_strings');
@@ -212,10 +315,21 @@
212 315 } else {
213 316 $redirectUrl .= '?' . Arr::get($confirmation, 'query_strings');
214 317 }
215 318 }
319 + $parseUrl = true;
320 + $parseUrl = apply_filters_deprecated(
321 + 'fluentform_will_parse_url_value',
322 + [
323 + $parseUrl,
324 + $form
325 + ],
326 + FLUENTFORM_FRAMEWORK_UPGRADE,
327 + 'fluentform/will_parse_url_value',
328 + 'Use fluentform/will_parse_url_value instead of fluentform_will_parse_url_value.'
329 + );
216 330
217 - $isUrlParser = apply_filters('fluentform_will_parse_url_value', true, $form);
331 + $isUrlParser = apply_filters('fluentform/will_parse_url_value', $parseUrl, $form);
218 332
219 333 $redirectUrl = ShortCodeParser::parse(
220 334 $redirectUrl,
221 335 $insertId,
@@ -222,14 +336,14 @@
222 336 $formData,
223 337 $form,
224 338 $isUrlParser
225 339 );
226 -
227 - if($isUrlParser) {
340 +
341 + if ($isUrlParser) {
228 342 /*
229 343 * For Empty Redirect Value
230 344 */
231 - if(strpos($redirectUrl, '=&') || substr($redirectUrl, -1) == '=') {
345 + if (strpos($redirectUrl, '=&') || '=' == substr($redirectUrl, -1)) {
232 346 $urlArray = explode('?', $redirectUrl);
233 347 $baseUrl = array_shift($urlArray);
234 348
235 349 $query = wp_parse_url($redirectUrl)['query'];
@@ -238,9 +352,9 @@
238 352
239 353 $params = [];
240 354 foreach ($queryParams as $queryParam) {
241 355 $paramArray = explode('=', $queryParam);
242 - if(!empty($paramArray[1])) {
356 + if (!empty($paramArray[1])) {
243 357 $params[$paramArray[0]] = $paramArray[1];
244 358 }
245 359 }
246 360
@@ -251,19 +365,34 @@
251 365 $message = ShortCodeParser::parse(
252 366 ArrayHelper::get($confirmation, 'redirectMessage', ''),
253 367 $insertId,
254 368 $formData,
255 - $form
369 + $form,
370 + false,
371 + true
256 372 );
257 -
373 +
374 + $redirectUrl = wp_sanitize_redirect(urldecode($redirectUrl));
258 375 $returnData = [
259 - 'redirectUrl' => wp_sanitize_redirect($redirectUrl),
260 - 'message' => $message
376 + 'redirectUrl' => esc_url_raw($redirectUrl),
377 + 'message' => $message,
261 378 ];
262 379 }
380 +
381 + $returnData = apply_filters_deprecated(
382 + 'fluentform_submission_confirmation',
383 + [
384 + $returnData,
385 + $form,
386 + $confirmation
387 + ],
388 + FLUENTFORM_FRAMEWORK_UPGRADE,
389 + 'fluentform/submission_confirmation',
390 + 'Use fluentform/submission_confirmation instead of fluentform_submission_confirmation.'
391 + );
263 392
264 393 return $this->app->applyFilters(
265 - 'fluentform_submission_confirmation',
394 + 'fluentform/submission_confirmation',
266 395 $returnData,
267 396 $form,
268 397 $confirmation
269 398 );
@@ -272,29 +401,60 @@
272 401 /**
273 402 * Validate form data.
274 403 *
275 404 * @param $fields
405 + *
276 406 * @return bool
277 407 */
278 408 private function validate(&$fields)
279 409 {
410 + $this->preventMaliciousAttacks();
411 +
280 412 $this->validateRestrictions($fields);
281 413
282 414 $this->validateNonce();
283 415
284 416 $this->validateReCaptcha();
417 + $this->validateHCaptcha();
418 + $this->validateTurnstile();
285 419
286 420 foreach ($fields as $fieldName => $field) {
287 - if(isset($this->formData[$fieldName])) {
421 + if (isset($this->formData[$fieldName])) {
288 422 $element = $field['element'];
289 - $this->formData[$fieldName] = apply_filters('fluentform_input_data_'.$element, $this->formData[$fieldName], $field, $this->formData);
423 +
424 + $this->formData[$fieldName] = apply_filters_deprecated(
425 + 'fluentform_input_data_' . $element,
426 + [
427 + $this->formData[$fieldName],
428 + $field,
429 + $this->formData,
430 + $this->form
431 + ],
432 + FLUENTFORM_FRAMEWORK_UPGRADE,
433 + 'fluentform/input_data_' . $element,
434 + 'Use fluentform/input_data_' . $element . ' instead of fluentform_input_data_' . $element
435 + );
436 +
437 + $this->formData[$fieldName] = $this->app->applyFilters('fluentform/input_data_' . $element,
438 + $this->formData[$fieldName], $field, $this->formData, $this->form);
290 439 }
291 440 }
292 441
293 442 $originalValidations = FormFieldsParser::getValidations($this->form, $this->formData, $fields);
294 -
443 +
444 + $originalValidations = apply_filters_deprecated(
445 + 'fluentform_validations',
446 + [
447 + $originalValidations,
448 + $this->form,
449 + $this->formData
450 + ],
451 + FLUENTFORM_FRAMEWORK_UPGRADE,
452 + 'fluentform/validations',
453 + 'Use fluentform/validations instead of fluentform_validations.'
454 + );
295 455 // Fire an event so that one can hook into it to work with the rules & messages.
296 - $validations = apply_filters('fluentform_validations', $originalValidations, $this->form, $this->formData);
456 + $validations = apply_filters('fluentform/validations', $originalValidations, $this->form, $this->formData);
297 457
298 458 /*
299 459 * Clean talk fix for now
300 460 * They should not hook fluentform_validations and return nothing!
@@ -303,9 +463,9 @@
303 463 if ($originalValidations && (!$validations || !array_filter($validations))) {
304 464 $validations = $originalValidations;
305 465 }
306 466
307 - $validator = \FluentValidator\Validator::make($this->formData, $validations[0], $validations[1]);
467 + $validator = wpFluentForm('validator')->make($this->formData, $validations[0], $validations[1]);
308 468
309 469 $errors = [];
310 470 if ($validator->validate()->fails()) {
311 471 foreach ($validator->errors() as $attribute => $rules) {
@@ -316,10 +476,24 @@
316 476 }
317 477
318 478 $errors[$attribute] = $rules;
319 479 }
480 +
481 + $errors = apply_filters_deprecated(
482 + 'fluentform_validation_error',
483 + [
484 + $errors,
485 + $this->form,
486 + $fields,
487 + $this->formData
488 + ],
489 + FLUENTFORM_FRAMEWORK_UPGRADE,
490 + 'fluentform/validation_error',
491 + 'Use fluentform/validation_error instead of fluentform_validation_error.'
492 + );
320 493 // Fire an event so that one can hook into it to work with the errors.
321 - $errors = $this->app->applyFilters('fluentform_validation_error', $errors, $this->form, $fields, $this->formData);
494 + $errors = $this->app->applyFilters('fluentform/validation_error', $errors, $this->form, $fields,
495 + $this->formData);
322 496 }
323 497
324 498 foreach ($fields as $fieldKey => $field) {
325 499 $field['data_key'] = $fieldKey;
@@ -324,15 +498,31 @@
324 498 foreach ($fields as $fieldKey => $field) {
325 499 $field['data_key'] = $fieldKey;
326 500 $inputName = \FluentForm\Framework\Helpers\ArrayHelper::get($field, 'raw.attributes.name');
327 501 $field['name'] = $inputName;
328 - $error = apply_filters('fluentform_validate_input_item_' . $field['element'], '', $field, $this->formData, $fields, $this->form, $errors);
502 +
503 + $error = apply_filters_deprecated(
504 + 'fluentform_validate_input_item_' . $field['element'],
505 + [
506 + '',
507 + $field,
508 + $this->formData,
509 + $fields,
510 + $this->form,
511 + $errors
512 + ],
513 + FLUENTFORM_FRAMEWORK_UPGRADE,
514 + 'fluentform_validate_input_item_' . $field['element'],
515 + 'Use fluentform/validate_input_item_' . $field['element'] . ' instead of fluentform_validate_input_item_' . $field['element']
516 + );
517 +
518 + $error = apply_filters('fluentform/validate_input_item_' . $field['element'], $error, $field, $this->formData, $fields, $this->form, $errors);
329 519 if ($error) {
330 520 if (empty($errors[$inputName])) {
331 521 $errors[$inputName] = [];
332 522 }
333 523
334 - if(is_string($error)) {
524 + if (is_string($error)) {
335 525 $error = [$error];
336 526 }
337 527
338 528 $errors[$inputName] = array_merge($error, $errors[$inputName]);
@@ -337,17 +527,61 @@
337 527
338 528 $errors[$inputName] = array_merge($error, $errors[$inputName]);
339 529 }
340 530 }
531 +
532 + $errors = apply_filters_deprecated(
533 + 'fluentform_validation_errors',
534 + [
535 + $errors,
536 + $this->formData,
537 + $this->form,
538 + $fields
539 + ],
540 + FLUENTFORM_FRAMEWORK_UPGRADE,
541 + 'fluentform/validation_errors',
542 + 'Use fluentform/validation_errors instead of fluentform_validation_errors.'
543 + );
341 544
342 - $errors = apply_filters('fluentform_validation_errors', $errors, $this->formData, $this->form, $fields);
545 + $errors = apply_filters('fluentform/validation_errors', $errors, $this->formData, $this->form, $fields);
343 546
344 - if(Helper::getFormMeta($this->form->id, '_has_user_registration') == 'yes') {
345 - $errors = apply_filters('fluentform_validation_user_registration_errors', $errors, $this->formData, $this->form, $fields);
547 + if ('yes' == Helper::getFormMeta($this->form->id, '_has_user_registration') && !get_current_user_id()) {
548 + $errors = apply_filters_deprecated(
549 + 'fluentform_validation_user_registration_errors',
550 + [
551 + $errors,
552 + $this->formData,
553 + $this->form,
554 + $fields
555 + ],
556 + FLUENTFORM_FRAMEWORK_UPGRADE,
557 + 'fluentform/validation_user_registration_errors',
558 + 'Use fluentform/validation_user_registration_errors instead of fluentform_validation_user_registration_errors.'
559 + );
560 +
561 + $errors = apply_filters('fluentform/validation_user_registration_errors', $errors, $this->formData,
562 + $this->form, $fields);
346 563 }
347 564
565 + if ('yes' == Helper::getFormMeta($this->form->id, '_has_user_update') && get_current_user_id()) {
566 + $errors = apply_filters_deprecated(
567 + 'fluentform_validation_user_update_errors',
568 + [
569 + $errors,
570 + $this->formData,
571 + $this->form,
572 + $fields
573 + ],
574 + FLUENTFORM_FRAMEWORK_UPGRADE,
575 + 'fluentform/validation_user_update_errors',
576 + 'Use fluentform/validation_user_update_errors instead of fluentform_validation_user_update_errors.'
577 + );
578 +
579 + $errors = apply_filters('fluentform/validation_user_update_errors', $errors, $this->formData, $this->form, $fields);
580 + }
581 +
348 582 if ($errors) {
349 - wp_send_json(['errors' => $errors], 422);
583 + wp_send_json(['errors' => $errors], 423);
350 584 }
351 585
352 586 return true;
353 587 }
@@ -357,19 +591,30 @@
357 591 */
358 592 protected function validateNonce()
359 593 {
360 594 $formId = $this->form->id;
595 + $nonceVerify = false;
596 + /* This filter is deprecated and will be removed soon. */
597 + $nonceVerify = $this->app->applyFilters('fluentform_nonce_verify', $nonceVerify, $formId);
361 598
362 - $shouldVerifyNonce = $this->app->applyFilters('fluentform_nonce_verify', false, $formId);
599 + $shouldVerifyNonce = $this->app->applyFilters('fluentform/nonce_verify', $nonceVerify, $formId);
363 600
364 601 if ($shouldVerifyNonce) {
365 602 $nonce = Arr::get($this->formData, '_fluentform_' . $formId . '_fluentformnonce');
366 603 if (!wp_verify_nonce($nonce, 'fluentform-submit-form')) {
367 - $errors = $this->app->applyFilters('fluentForm_nonce_error', [
368 - '_fluentformnonce' => [
369 - __('Nonce verification failed, please try again.', 'fluentform')
370 - ]
371 - ]);
604 + $nonceMessage = apply_filters_deprecated(
605 + 'fluentForm_nonce_error',
606 + [
607 + '_fluentformnonce' => [
608 + __('Nonce verification failed, please try again.', 'fluentform'),
609 + ],
610 + ],
611 + FLUENTFORM_FRAMEWORK_UPGRADE,
612 + 'fluentform/nonce_error',
613 + 'Use fluentform/nonce_error instead of fluentForm_nonce_error.'
614 + );
615 +
616 + $errors = $this->app->applyFilters('fluentform/nonce_error', $nonceMessage);
372 617 wp_send_json(['errors' => $errors], 422);
373 618 }
374 619 }
375 620 }
@@ -376,33 +621,61 @@
376 621
377 622 protected function handleSpamError()
378 623 {
379 624 $settings = get_option('_fluentform_global_form_settings');
380 - if (!$settings || ArrayHelper::get($settings, 'misc.akismet_validation') != 'validation_failed') {
625 + if (!$settings || 'validation_failed' != ArrayHelper::get($settings, 'misc.akismet_validation')) {
381 626 return;
382 627 }
383 628
384 - $errors = [
385 - '_fluentformakismet' => __('Submission marked as spammed. Please try again', 'fluentform')
629 + $errors = [
630 + '_fluentformakismet' => apply_filters(
631 + 'fluentform/akismet_spam_message',
632 + __('Submission marked as spammed. Please try again', 'fluentform'),
633 + $this->form->id
634 + ),
386 635 ];
387 636
388 637 wp_send_json(['errors' => $errors], 422);
389 638 }
390 639
391 - protected function isSpam($formData, $form)
640 + protected function isAkismetSpam($formData, $form)
392 641 {
393 642 if (!AkismetHandler::isEnabled()) {
394 643 return false;
395 644 }
645 + $isSpamCheck = true;
646 + $isSpamCheck = apply_filters_deprecated(
647 + 'fluentform_akismet_check_spam',
648 + [
649 + true,
650 + $form->id,
651 + $formData
652 + ],
653 + FLUENTFORM_FRAMEWORK_UPGRADE,
654 + 'fluentform/akismet_check_spam',
655 + 'Use fluentform/akismet_check_spam instead of fluentform_akismet_check_spam.'
656 + );
396 657
397 - $isSpamCheck = apply_filters('fluentform_akismet_check_spam', true, $form->id, $formData);
658 + $isSpamCheck = apply_filters('fluentform/akismet_check_spam', $isSpamCheck, $form->id, $formData);
398 659 if (!$isSpamCheck) {
399 660 return false;
400 661 }
401 662 // Let's validate now
402 663 $isSpam = AkismetHandler::isSpamSubmission($formData, $form);
664 +
665 + $isSpam = apply_filters_deprecated(
666 + 'fluentform_akismet_spam_result',
667 + [
668 + $isSpam,
669 + $form->id,
670 + $formData
671 + ],
672 + FLUENTFORM_FRAMEWORK_UPGRADE,
673 + 'fluentform/akismet_spam_result',
674 + 'Use fluentform/akismet_spam_result instead of fluentform_akismet_spam_result.'
675 + );
403 676
404 - return apply_filters('fluentform_akismet_spam_result', $isSpam, $form->id, $formData);
677 + return $this->app->applyFilters('fluentform/akismet_spam_result', $isSpam, $form->id, $formData);
405 678 }
406 679
407 680 /**
408 681 * Validate reCaptcha.
@@ -408,24 +681,107 @@
408 681 * Validate reCaptcha.
409 682 */
410 683 private function validateReCaptcha()
411 684 {
412 - if (FormFieldsParser::hasElement($this->form, 'recaptcha')) {
413 - $isValid = ReCaptcha::validate(Arr::get($this->formData, 'g-recaptcha-response'));
685 + $hasAutoRecaptcha = false;
686 + $hasAutoRecaptcha = apply_filters_deprecated(
687 + 'ff_has_auto_recaptcha',
688 + [
689 + $hasAutoRecaptcha
690 + ],
691 + FLUENTFORM_FRAMEWORK_UPGRADE,
692 + 'fluentform/has_recaptcha',
693 + 'Use fluentform/has_recaptcha instead of ff_has_auto_recaptcha.'
694 + );
695 + $autoInclude = apply_filters('fluentform/has_recaptcha', $hasAutoRecaptcha);
696 + if (FormFieldsParser::hasElement($this->form, 'recaptcha') || $autoInclude) {
697 + $keys = get_option('_fluentform_reCaptcha_details');
698 + $token = Arr::get($this->formData, 'g-recaptcha-response');
699 + $version = 'v2_visible';
700 + if (!empty($keys['api_version'])) {
701 + $version = $keys['api_version'];
702 + }
703 + $isValid = ReCaptcha::validate($token, $keys['secretKey'], $version);
414 704
415 705 if (!$isValid) {
416 - wp_send_json([
417 - 'errors' => [
418 - 'g-recaptcha-response' => [
419 - __('reCaptcha verification failed, please try again.', 'fluentform')
420 - ]
421 - ]
422 - ], 422);
706 + $message = apply_filters(
707 + 'fluentform/recaptcha_failed_message',
708 + __('reCaptcha verification failed, please try again.', 'fluentform'),
709 + $this->form
710 + );
711 + wp_send_json(['errors' => ['g-recaptcha-response' => [$message]]], 422);
423 712 }
424 713 }
425 714 }
426 715
427 716 /**
717 + * Validate hCaptcha.
718 + */
719 + private function validateHCaptcha()
720 + {
721 + $hasAutoHcaptcha = false;
722 +
723 + $hasAutoHcaptcha = apply_filters_deprecated(
724 + 'ff_has_auto_hcaptcha',
725 + [
726 + $hasAutoHcaptcha
727 + ],
728 + FLUENTFORM_FRAMEWORK_UPGRADE,
729 + 'fluentform/has_hcaptcha',
730 + 'Use fluentform/has_hcaptcha instead of ff_has_auto_hcaptcha.'
731 + );
732 + $autoInclude = apply_filters('fluentform/has_hcaptcha', $hasAutoHcaptcha);
733 + FormFieldsParser::resetData();
734 + if (FormFieldsParser::hasElement($this->form, 'hcaptcha') || $autoInclude) {
735 + $keys = get_option('_fluentform_hCaptcha_details');
736 + $token = Arr::get($this->formData, 'h-captcha-response');
737 + $isValid = HCaptcha::validate($token, $keys['secretKey']);
738 +
739 + if (!$isValid) {
740 + $message = apply_filters(
741 + 'fluentform/hcaptcha_failed_message',
742 + __('hCaptcha verification failed, please try again.', 'fluentform'),
743 + $this->form
744 + );
745 + wp_send_json(['errors' => ['h-captcha-response' => [$message]]], 422);
746 + }
747 + }
748 + }
749 +
750 + /**
751 + * Validate turnstile.
752 + */
753 + private function validateTurnstile()
754 + {
755 + $hasAutoTurnsTile = false;
756 + $hasAutoTurnsTile = apply_filters_deprecated(
757 + 'ff_has_auto_turnstile',
758 + [
759 + $hasAutoTurnsTile
760 + ],
761 + FLUENTFORM_FRAMEWORK_UPGRADE,
762 + 'fluentform/has_turnstile',
763 + 'Use fluentform/has_turnstile instead of ff_has_auto_turnstile.'
764 + );
765 + $autoInclude = apply_filters('fluentform/has_turnstile', $hasAutoTurnsTile);
766 + if (FormFieldsParser::hasElement($this->form, 'turnstile') || $autoInclude) {
767 + $keys = get_option('_fluentform_turnstile_details');
768 + $token = Arr::get($this->formData, 'cf-turnstile-response');
769 +
770 + $isValid = Turnstile::validate($token, $keys['secretKey']);
771 +
772 + if (!$isValid) {
773 + $message = apply_filters(
774 + 'fluentform/turnstile_failed_message',
775 + __('Turnstile verification failed, please try again.', 'fluentform'),
776 + $this->form
777 + );
778 + wp_send_json(['errors' => ['cf-turnstile-response' => [$message]]], 422);
779 + }
780 + }
781 + }
782 +
783 + /**
428 784 * Validate form data based on the form restrictions settings.
429 785 *
430 786 * @param $fields
431 787 */
@@ -438,10 +794,10 @@
438 794
439 795 $this->form->settings = $formSettings ? json_decode($formSettings->value, true) : [];
440 796
441 797 $isAllowed = [
442 - 'status' => true,
443 - 'message' => ''
798 + 'status' => true,
799 + 'message' => '',
444 800 ];
445 801
446 802 // This will check the following restriction settings.
447 803 // 1. limitNumberOfEntries
@@ -446,17 +802,21 @@
446 802 // This will check the following restriction settings.
447 803 // 1. limitNumberOfEntries
448 804 // 2. scheduleForm
449 805 // 3. requireLogin
806 +
807 + /* This filter is deprecated and will be removed soon */
450 808 $isAllowed = apply_filters('fluentform_is_form_renderable', $isAllowed, $this->form);
809 +
810 + $isAllowed = apply_filters('fluentform/is_form_renderable', $isAllowed, $this->form);
451 811
452 812 if (!$isAllowed['status']) {
453 813 wp_send_json([
454 814 'errors' => [
455 815 'restricted' => [
456 - $isAllowed['message']
457 - ]
458 - ]
816 + $isAllowed['message'],
817 + ],
818 + ],
459 819 ], 422);
460 820 }
461 821
462 822 // Since we are here, we should now handle if the form should be allowed to submit empty.
@@ -470,9 +830,9 @@
470 830 *
471 831 * @param array $settings
472 832 * @param $fields
473 833 */
474 - private function handleDenyEmptySubmission($settings = [], &$fields)
834 + private function handleDenyEmptySubmission($settings, &$fields)
475 835 {
476 836 // Determine whether empty form submission is allowed or not.
477 837 if (Arr::get($settings, 'enabled')) {
478 838 // confirm this form has no required fields.
@@ -478,9 +838,9 @@
478 838 // confirm this form has no required fields.
479 839 if (!FormFieldsParser::hasRequiredFields($this->form, $fields)) {
480 840 // Filter out the form data which doesn't have values.
481 841 $filteredFormData = array_filter(
482 - // Filter out the other meta fields that aren't actual inputs.
842 + // Filter out the other meta fields that aren't actual inputs.
483 843 array_intersect_key($this->formData, $fields)
484 844 );
485 845
486 846 // TODO: Extract this function into global functions file...
@@ -494,19 +854,18 @@
494 854 return $array;
495 855 };
496 856
497 857 if (!count($arrayFilterRecursive($filteredFormData))) {
858 + $message = Arr::get($settings, 'message');
859 + if (!$message) {
860 + $message = __('Sorry! You can\'t submit an empty form.', 'fluentform');
861 + }
498 862 wp_send_json([
499 863 'errors' => [
500 864 'restricted' => [
501 - __(
502 - !($m = Arr::get($settings, 'message'))
503 - ? 'Sorry! You can\'t submit an empty form.'
504 - : $m,
505 - 'fluentform'
506 - )
507 - ]
508 - ]
865 + $message,
866 + ],
867 + ],
509 868 ], 422);
510 869 }
511 870 }
512 871 }
@@ -515,8 +874,9 @@
515 874 /**
516 875 * Prepare the data to be inserted to the database.
517 876 *
518 877 * @param boolean $formData
878 + *
519 879 * @return array
520 880 */
521 881 public function prepareInsertData($formData = false)
522 882 {
@@ -536,35 +896,67 @@
536 896 if ($previousItem) {
537 897 $serialNumber = $previousItem->serial_number + 1;
538 898 }
539 899
540 - $browser = new Browser;
900 + $browser = new Browser();
541 901
542 - $inputConfigs = FormFieldsParser::getEntryInputs($this->form, array('admin_label', 'raw'));
902 + $inputConfigs = FormFieldsParser::getEntryInputs($this->form, ['admin_label', 'raw']);
903 +
904 + $formData = apply_filters_deprecated(
905 + 'fluentform_insert_response_data',
906 + [
907 + $formData,
908 + $formId,
909 + $inputConfigs
910 + ],
911 + FLUENTFORM_FRAMEWORK_UPGRADE,
912 + 'fluentform/insert_response_data',
913 + 'Use fluentform/insert_response_data instead of fluentform_insert_response_data.'
914 + );
915 + $this->formData = apply_filters('fluentform/insert_response_data', $formData, $formId, $inputConfigs);
543 916
544 - $this->formData = apply_filters('fluentform_insert_response_data', $formData, $formId, $inputConfigs);
917 + $ipAddress = sanitize_text_field($this->app->request->getIp());
918 + $disableIpLogging = false;
919 + $disableIpLogging = apply_filters_deprecated(
920 + 'fluentform_disable_ip_logging',
921 + [
922 + $disableIpLogging,
923 + $formId
924 + ],
925 + FLUENTFORM_FRAMEWORK_UPGRADE,
926 + 'fluentform/disable_ip_logging',
927 + 'Use fluentform/disable_ip_logging instead of fluentform_disable_ip_logging.'
928 + );
545 929
546 - $ipAddress = $this->app->request->getIp();
547 -
548 - if ((defined('FLUENTFROM_DISABLE_IP_LOGGING') && FLUENTFROM_DISABLE_IP_LOGGING) || apply_filters('fluentform_disable_ip_logging', false, $formId)) {
930 + if ((defined('FLUENTFROM_DISABLE_IP_LOGGING') && FLUENTFROM_DISABLE_IP_LOGGING) || apply_filters('fluentform/disable_ip_logging',
931 + $disableIpLogging, $formId)) {
549 932 $ipAddress = false;
550 933 }
551 934
552 935 $response = [
553 - 'form_id' => $formId,
936 + 'form_id' => $formId,
554 937 'serial_number' => $serialNumber,
555 - 'response' => json_encode($this->formData),
556 - 'source_url' => site_url(Arr::get($formData, '_wp_http_referer')),
557 - 'user_id' => get_current_user_id(),
558 - 'browser' => $browser->getBrowser(),
559 - 'device' => $browser->getPlatform(),
560 - 'ip' => $ipAddress,
561 - 'created_at' => current_time('mysql'),
562 - 'updated_at' => current_time('mysql')
938 + 'response' => json_encode($this->formData, JSON_UNESCAPED_UNICODE),
939 + 'source_url' => site_url(Arr::get($formData, '_wp_http_referer')),
940 + 'user_id' => get_current_user_id(),
941 + 'browser' => $browser->getBrowser(),
942 + 'device' => $browser->getPlatform(),
943 + 'ip' => $ipAddress,
944 + 'created_at' => current_time('mysql'),
945 + 'updated_at' => current_time('mysql'),
563 946 ];
947 +
948 + $response = apply_filters_deprecated(
949 + 'fluentform_filter_insert_data',
950 + [
951 + $response
952 + ],
953 + FLUENTFORM_FRAMEWORK_UPGRADE,
954 + 'fluentform/filter_insert_data',
955 + 'Use fluentform/filter_insert_data instead of fluentform_filter_insert_data.'
956 + );
564 957
565 -
566 - return apply_filters('fluentform_filter_insert_data', $response);
958 + return apply_filters('fluentform/filter_insert_data', $response);
567 959 }
568 960
569 961 /**
570 962 * Delegate the validation rules & messages to the
@@ -569,10 +961,11 @@
569 961 /**
570 962 * Delegate the validation rules & messages to the
571 963 * ones that the validation library recognizes.
572 964 *
573 - * @param $rules
574 - * @param $messages
965 + * @param $rules
966 + * @param $messages
967 + *
575 968 * @return array
576 969 */
577 970 protected function delegateValidations($rules, $messages, $search = [], $replace = [])
578 971 {
@@ -591,5 +984,41 @@
591 984
592 985 return [$rules, $messages];
593 986 }
594 987
988 + /**
989 + * Prevents malicious attacks when the submission
990 + * count exceeds in an allowed interval.
991 + */
992 + public function preventMaliciousAttacks()
993 + {
994 + $prevent = apply_filters('fluentform/prevent_malicious_attacks', true, $this->form->id);
995 +
996 + if ($prevent) {
997 + $maxSubmissionCount = apply_filters('fluentform/max_submission_count', 5, $this->form->id);
998 + $minSubmissionInterval = apply_filters('fluentform/min_submission_interval', 30, $this->form->id);
999 +
1000 + $interval = date('Y-m-d H:i:s', strtotime(current_time('mysql')) - $minSubmissionInterval);
1001 +
1002 + $clientIp = sanitize_text_field($this->app->request->getIp());
1003 + $submissionCount = wpFluent()->table('fluentform_submissions')
1004 + ->where('status', '!=', 'trashed')
1005 + ->where('ip', $clientIp ?: '0.0.0.0')
1006 + ->where('created_at', '>=', $interval)
1007 + ->count();
1008 +
1009 + if ($submissionCount >= $maxSubmissionCount) {
1010 + wp_send_json([
1011 + 'errors' => [
1012 + 'restricted' => [
1013 + apply_filters(
1014 + 'fluentform/too_many_requests',
1015 + __('Too Many Requests.', 'fluentform'),
1016 + $this->form->id
1017 + ),
1018 + ],
1019 + ],
1020 + ], 429);
1021 + }
1022 + }
1023 + }
595 1024 }