PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.9.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.9.1
V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 2.10.1 2.10.2 All 137 releases
bit-form / includes / Frontend / Form / FrontendFormManager.php

FrontendFormManager.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 2.9.1, at includes/Frontend/Form/FrontendFormManager.php

888 lines 34.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Get set Form,fields
5 */
6
7 namespace BitCode\BitForm\Frontend\Form;
8
9 /**
10 * FrontendFormManager class
11 */
12
13 use BitCode\BitForm\Admin\Form\Helpers;
14 use BitCode\BitForm\Core\Database\FormEntryModel;
15 use BitCode\BitForm\Core\Form\FormManager;
16 use BitCode\BitForm\Core\Form\Validator\FormFieldValidator;
17 use BitCode\BitForm\Core\Integration\IntegrationHandler;
18 use BitCode\BitForm\Core\Messages\SuccessMessageHandler;
19 use BitCode\BitForm\Core\Util\ApiResponse as UtilApiResponse;
20 use BitCode\BitForm\Core\Util\DateTimeHelper;
21 use BitCode\BitForm\Core\Util\HttpHelper;
22 use BitCode\BitForm\Core\Util\IpTool;
23 use BitCode\BitForm\Core\WorkFlow\WorkFlow;
24 use BitCode\BitForm\Core\WorkFlow\WorkFlowHandler;
25 use BitCode\BitForm\Frontend\Form\View\FormViewer;
26 use BitCode\BitFormPro\Admin\FormSettings\FormAbandonment;
27 use WP_Error;
28
29 final class FrontendFormManager extends FormManager
30 {
31 private $_form_identifier;
32 private $_form_token;
33 private $_form_id;
34 private $_work_flows;
35 private $_conf_messages;
36
37 // private $_has_upload = false;
38 public function __construct($form_id, $shortCodeCounter = null)
39 {
40 parent::__construct($form_id);
41 $this->_form_identifier = 'bitforms_' . $form_id;
42 $this->_form_identifier .= !empty(get_post()->ID) ? '_' . get_post()->ID : '';
43 $this->_form_identifier .= !empty($shortCodeCounter) ? "_$shortCodeCounter" : '';
44 $this->_form_token = wp_create_nonce('bitforms_' . $form_id);
45 $this->_form_id = $form_id;
46 }
47
48 public function getFormIdentifier()
49 {
50 return $this->_form_identifier;
51 }
52
53 public function getFormID()
54 {
55 return $this->_form_id;
56 }
57
58 public function getFormToken()
59 {
60 return $this->_form_token;
61 }
62
63 public function isSubmitted()
64 {
65 // return isset($_POST[$this->_form_identifier]) ? true : false;
66 return (isset($_POST['bitforms_id']) && $_POST['bitforms_id'] === $this->_form_identifier) ? true : false;
67 }
68
69 public function getSubmittedFields($submitted_data)
70 {
71 unset($submitted_data[$this->_form_identifier]);
72 // unset($submitted_data['bit-form-submit-btn']);
73 return array_keys($submitted_data);
74 }
75
76 public function formView($fields = null, $hasFile = false, $errorMessages = null, $previousValue = null)
77 {
78 $formContents = $this->getFormContent();
79 $formAtomicClsMap = $this->getAtomicClsMap();
80 if (!empty($fields)) {
81 $formContents->fields = is_string($fields) ? json_decode($fields) : $fields;
82 } else {
83 $workFlowRunHelper = new WorkFlow($this->form_id);
84 $workFlowreturnedOnLoad = $workFlowRunHelper->executeOnLoad(
85 'create',
86 $formContents->fields
87 );
88 $formContents->fields = empty($workFlowreturnedOnLoad['fields']) ? $formContents->fields : $workFlowreturnedOnLoad['fields'];
89 }
90 $formViewer = new FormViewer($this, $formContents, $formAtomicClsMap, $errorMessages, $previousValue);
91 $isRestricted = $this->checkSubmissionRestriction(false);
92 $msg = !empty($isRestricted) ? $isRestricted[0] : '';
93 return $formViewer->getView($hasFile, $msg);
94 }
95
96 private function checkEmptySubmission($data, $file)
97 {
98 $formFields = $this->getFields();
99 foreach ($formFields as $key => $field) {
100 $fieldType = $field['type'];
101 $fileUploadFieldTypes = ['file-up', 'advanced-file-up'];
102 if ('decision-box' === $fieldType) {
103 continue;
104 }
105 $isFileType = in_array($fieldType, $fileUploadFieldTypes);
106 if ($this->isRepeatedField($key)) {
107 $fileData = !empty($file[$key]) ? $file[$key] : [];
108 $dataVal = !empty($data[$key]) ? $data[$key] : [];
109 if (!$this->checkRepeatedFieldEmptySubmission($isFileType, $dataVal, $fileData)) {
110 return false;
111 }
112 continue;
113 }
114 if (!$isFileType && (!empty($data[$key]) || (isset($data[$key]) && is_numeric($data[$key])))) {
115 return false;
116 }
117 if ($isFileType && !empty($file[$key]['name']) && is_string($file[$key]['name'])) {
118 return false;
119 }
120 if ($isFileType && !empty($file[$key]['name'][0])) {
121 return false;
122 }
123 }
124 return true;
125 }
126
127 private function checkRepeatedFieldEmptySubmission($isFileType, $data, $file = [])
128 {
129 if (!$isFileType) {
130 foreach ($data as $value) {
131 if (!empty($value)) {
132 return false;
133 }
134 }
135 }
136 if ($isFileType) {
137 foreach ($file['name'] as $value) {
138 if (!empty($value) && is_string($value)) {
139 return false;
140 }
141 if (is_array($value) && !empty($value[0])) {
142 return false;
143 }
144 }
145 }
146 return true;
147 }
148
149 private function getParams()
150 {
151 $url = parse_url(wp_get_referer());
152 $parameter = [];
153 if (isset($url['query'])) {
154 $queries = explode('&', $url['query']);
155 foreach ($queries as $query) {
156 list($field, $value) = explode('=', $query);
157 $parameter[$field] = $value;
158 }
159 }
160 return $parameter;
161 }
162
163 public function handleSubmission()
164 {
165 $this->fieldNameReplaceOfPost();
166
167 $validated = $this->beforeSubmittedValidate();
168
169 if (true === $validated) {
170 unset($_POST['hidden_fields']);
171
172 $redirectPage = '';
173 $regSuccMsg = '';
174
175 $existAuth = (new IntegrationHandler($this->_form_id))->getAllIntegration('wp_user_auth', 'wp_auth', 1);
176 if (!is_wp_error($existAuth) && count($existAuth) > 0) {
177 $parameter = $this->getParams();
178 $existAuthFilter = has_filter('bf_wp_user_auth');
179
180 if (true === $existAuthFilter) {
181 $result = apply_filters('bf_wp_user_auth', $existAuth[0], $_POST, $parameter);
182
183 if (isset($result['auth_type']) && 'register' === $result['auth_type']) {
184 if (!$result['success']) {
185 return new WP_Error('errors', __($result['message'], 'bit-form'));
186 } elseif (isset($result['success'])) {
187 $redirectPage = $result['redirect_url'];
188 $regSuccMsg = $result['message'];
189 $newNonce = wp_create_nonce('bitforms_' . $this->_form_id);
190 }
191 } else {
192 if (!$result['success']) {
193 return new WP_Error('errors', __($result['message'], 'bit-form'));
194 } else {
195 return $result;
196 }
197 }
198 }
199 }
200
201 $saveResponse = $this->saveFormEntry($_POST);
202 if (is_wp_error($saveResponse)) {
203 return $saveResponse;
204 }
205
206 $entryID = $saveResponse['entry_id'];
207 do_action('bitform_submit_success', $this->_form_id, $entryID, $_POST);
208
209 // check and replace signature field value
210 $formFields = $this->getFields();
211 $uploadPath = BITFORMS_UPLOAD_BASE_URL . "/uploads/{$this->_form_id}/{$entryID}";
212
213 foreach ($formFields as $key => $field) {
214 if ('signature' === $field['type']) {
215 $saveResponse['fields'][$key] = $uploadPath . '/' . $saveResponse['fields'][$key];
216 break;
217 }
218 }
219
220 $captchaV3Settings = $this->getCaptchaV3Settings();
221 if ($captchaV3Settings) {
222 $token = $_POST['g-recaptcha-response'];
223 $integrationHandler = new IntegrationHandler(0);
224 $allFormIntegrations = $integrationHandler->getAllIntegration('app', 'gReCaptchaV3');
225 if (!is_wp_error($allFormIntegrations)) {
226 foreach ($allFormIntegrations as $integration) {
227 if (!is_null($integration->integration_type) && 'gReCaptchaV3' === $integration->integration_type) {
228 $integrationDetails = json_decode($integration->integration_details);
229 $integrationDetails->id = $integration->id;
230 $reCAPTCHA = $integrationDetails;
231 }
232 }
233 }
234 if (!empty($reCAPTCHA->secretKey)) {
235 $gRecaptchaResponse = HttpHelper::post(
236 'https://www.google.com/recaptcha/api/siteverify',
237 ['secret' => $reCAPTCHA->secretKey, 'response' => $token]
238 );
239 if ($captchaV3Settings && !empty($saveResponse['triggerData'])) {
240 $logID = $saveResponse['triggerData']['logID'];
241 $integId = $reCAPTCHA->id;
242 $saveApiResponse = new UtilApiResponse();
243 $saveApiResponse->apiResponse($logID, $integId, ['type_name' => 'ReCaptcha', 'type' => 'v3'], 'success', $gRecaptchaResponse);
244 }
245 }
246 unset($_POST['g-recaptcha-response']);
247 }
248 if (!empty($redirectPage) && empty($saveResponse['redirectPage']) || null === $saveResponse['redirectPage']) {
249 $saveResponse['redirectPage'] = $redirectPage;
250 }
251 if (!empty($regSuccMsg) && isset($saveResponse['dflt_message'])) {
252 $saveResponse['message'] = $regSuccMsg;
253 }
254 $saveResponse = IntegrationHandler::maybeSetCronForIntegration($saveResponse, 'create');
255 $entryId = $saveResponse['entry_id'];
256
257 $responseMsg = is_array($saveResponse) && !empty($saveResponse) ? $saveResponse : __('Form Submitted Successfully', 'bit-form');
258 if (isset($newNonce)) {
259 $responseMsg['new_nonce'] = $newNonce;
260 }
261 $_POST = [];
262 $responseMsg['entry_id'] = $entryId;
263 return $responseMsg;
264 }
265 do_action('bitform_validation_error', $this->_form_id, $validated);
266 return $validated;
267 }
268
269 public function handleUpdateEntry()
270 {
271 $this->fieldNameReplaceOfPost();
272 $validated = $this->beforeSubmittedValidate();
273
274 $entryID = $_REQUEST['entryID'];
275 if (is_null($entryID)) {
276 return new WP_Error('empty_form', __('Entries id is invalid', 'bit-form'));
277 }
278 if (true === $validated) {
279 unset($_POST['hidden_fields'], $_POST['entryID']);
280
281 $redirectPage = '';
282 $regSuccMsg = '';
283
284 $existAuth = (new IntegrationHandler($this->_form_id))->getAllIntegration('wp_user_auth', 'wp_auth', 1);
285 if (!is_wp_error($existAuth) && count($existAuth) > 0) {
286 $parameter = $this->getParams();
287 $existAuthFilter = has_filter('bf_wp_user_auth');
288
289 if (true === $existAuthFilter) {
290 $result = apply_filters('bf_wp_user_auth', $existAuth[0], $_POST, $parameter);
291
292 if (isset($result['auth_type']) && 'register' === $result['auth_type']) {
293 if (!$result['success']) {
294 return new WP_Error('errors', __($result['message'], 'bit-form'));
295 } elseif (isset($result['success'])) {
296 $redirectPage = $result['redirect_url'];
297 $regSuccMsg = $result['message'];
298 $newNonce = wp_create_nonce('bitforms_' . $this->_form_id);
299 }
300 } else {
301 if (!$result['success']) {
302 return new WP_Error('errors', __($result['message'], 'bit-form'));
303 } else {
304 return $result;
305 }
306 }
307 }
308 }
309
310 $updateResponse = $this->updateFormEntry($_POST, $this->getFormID(), $entryID);
311 if (is_wp_error($updateResponse)) {
312 return $updateResponse;
313 }
314
315 do_action('bitform_submit_success', $this->_form_id, $entryID, $_POST);
316
317 $captchaV3Settings = $this->getCaptchaV3Settings();
318 if ($captchaV3Settings) {
319 $token = $_POST['g-recaptcha-response'];
320 $integrationHandler = new IntegrationHandler(0);
321 $allFormIntegrations = $integrationHandler->getAllIntegration('app', 'gReCaptchaV3');
322 if (!is_wp_error($allFormIntegrations)) {
323 foreach ($allFormIntegrations as $integration) {
324 if (!is_null($integration->integration_type) && 'gReCaptchaV3' === $integration->integration_type) {
325 $integrationDetails = json_decode($integration->integration_details);
326 $integrationDetails->id = $integration->id;
327 $reCAPTCHA = $integrationDetails;
328 }
329 }
330 }
331 if (!empty($reCAPTCHA->secretKey)) {
332 $gRecaptchaResponse = HttpHelper::post(
333 'https://www.google.com/recaptcha/api/siteverify',
334 ['secret' => $reCAPTCHA->secretKey, 'response' => $token]
335 );
336 if ($captchaV3Settings && !empty($updateResponse['triggerData'])) {
337 $logID = $updateResponse['triggerData']['logID'];
338 $integId = $reCAPTCHA->id;
339 $saveApiResponse = new UtilApiResponse();
340 $saveApiResponse->apiResponse($logID, $integId, ['type_name' => 'ReCaptcha', 'type' => 'v3'], 'success', $gRecaptchaResponse);
341 }
342 }
343 unset($_POST['g-recaptcha-response']);
344 }
345 if (!empty($redirectPage) && empty($updateResponse['redirectPage']) || null === $updateResponse['redirectPage']) {
346 $updateResponse['redirectPage'] = $redirectPage;
347 }
348 if (!empty($regSuccMsg) && isset($updateResponse['dflt_message'])) {
349 $updateResponse['message'] = $regSuccMsg;
350 }
351 $updateResponse = IntegrationHandler::maybeSetCronForIntegration($updateResponse, 'create');
352 $entryId = $updateResponse['entry_id'];
353
354 $responseMsg = is_array($updateResponse) && !empty($updateResponse) ? $updateResponse : __('Entry Update Successfully', 'bit-form');
355 if (isset($newNonce)) {
356 $responseMsg['new_nonce'] = $newNonce;
357 }
358 $_POST = [];
359 $responseMsg['entry_id'] = $entryId;
360 return $responseMsg;
361 }
362 do_action('bitform_validation_error', $this->_form_id, $validated);
363 return $validated;
364 }
365
366 public function validateFormSubmission($submitted_data)
367 {
368 $hidden_fields = isset($submitted_data['hidden_fields']) ? $submitted_data['hidden_fields'] : '';
369 $submitted_fields = $this->getSubmittedFields($submitted_data);
370 $form_fields = $this->getFields();
371 $form_fields_names = array_keys($form_fields);
372 if ($this->isGCLIDEnabled()) {
373 array_push($form_fields_names, 'GCLID');
374 }
375 foreach ($submitted_fields as $key => $field) {
376 if ('hidden_fields' !== $field && !in_array($field, $form_fields_names) || false !== strpos($hidden_fields, $field)) {
377 unset($submitted_data[$field]);
378 }
379 }
380 return $submitted_data;
381 }
382
383 public function beforeSubmittedValidate()
384 {
385 if ($this->verifySubmissionNonce()) {
386 if ($this->isExist()) {
387 $isRestricted = $this->checkSubmissionRestriction();
388 if ($isRestricted && !empty($isRestricted)) {
389 return new WP_Error('spam_detection', $isRestricted[0]);
390 }
391 if ($this->isTrappedInHoneypot()) {
392 return new WP_Error('spam_detection', __('Token verification failed', 'bit-form'));
393 }
394 $captchaSettings = $this->getCaptchaSettings();
395 $captchaV3Settings = $this->getCaptchaV3Settings();
396 if ($captchaSettings || $captchaV3Settings) {
397 $token = $_POST['g-recaptcha-response'];
398 if (!isset($_POST['g-recaptcha-response'])) {
399 return new WP_Error('spam_detection', __('Please verify reCAPTCHA', 'bit-form'));
400 }
401 $integrationHandler = new IntegrationHandler(0);
402 $allFormIntegrations = $integrationHandler->getAllIntegration('app', $captchaSettings ? 'gReCaptcha' : 'gReCaptchaV3');
403 if (!is_wp_error($allFormIntegrations)) {
404 foreach ($allFormIntegrations as $integration) {
405 if (!is_null($integration->integration_type) && $integration->integration_type === ($captchaSettings ? 'gReCaptcha' : 'gReCaptchaV3')) {
406 $integrationDetails = json_decode($integration->integration_details);
407 $integrationDetails->id = $integration->id;
408 $reCAPTCHA = $integrationDetails;
409 }
410 }
411 }
412 if (!empty($reCAPTCHA->secretKey)) {
413 $gRecaptchaResponse = HttpHelper::post(
414 'https://www.google.com/recaptcha/api/siteverify',
415 ['secret' => $reCAPTCHA->secretKey, 'response' => $token]
416 );
417 $isgReCaptchaVerified = false;
418 if (!is_wp_error($gRecaptchaResponse)) {
419 if (
420 $captchaV3Settings
421 && !empty($gRecaptchaResponse->score)
422 && ((float) $gRecaptchaResponse->score < (float) $captchaV3Settings->score)
423 ) {
424 wp_send_json_error(
425 __(
426 $captchaV3Settings->message,
427 'bit-form'
428 )
429 );
430 }
431
432 $isgReCaptchaVerified = $gRecaptchaResponse->success;
433 }
434 if (!$isgReCaptchaVerified) {
435 return new WP_Error('spam_detection', __('Please verify reCAPTCHA', 'bit-form'));
436 }
437 }
438 }
439
440 /* Implement Turnstile Captcha start */
441 $turnstileSetting = $this->getTurnstileSettings();
442 if ($turnstileSetting) {
443 if (!isset($_POST['cf-turnstile-response'])) {
444 return new WP_Error('spam_detection', __('Please verify Cloudflare Turnstile Captcha', 'bit-form'));
445 }
446 $token = $_POST['cf-turnstile-response'];
447 $turnstileCaptcha = null;
448 $integrationHandler = new IntegrationHandler(0);
449 $turnstileIntegration = $integrationHandler->getAllIntegration('app', 'turnstileCaptcha')[0];
450 if (!is_wp_error($turnstileIntegration && !is_null($turnstileIntegration->integration_type))) {
451 $turnstileCaptcha = json_decode($turnstileIntegration->integration_details);
452 // $integrationDetails->id = $turnstileIntegration->id;
453 // $turnstileCaptcha = $integrationDetails;
454 }
455 if (!is_null($turnstileCaptcha)) {
456 $isTurnstileCaptchaVerified = false;
457 $turnstileRecaptchaResponse = HttpHelper::post(
458 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
459 ['secret' => $turnstileCaptcha->secretKey, 'response' => $token]
460 );
461 if (!is_wp_error($turnstileRecaptchaResponse)) {
462 if (!$turnstileRecaptchaResponse->success) {
463 wp_send_json_error(
464 __(
465 'Cloudflare Turnstile Validation Error: ' . implode(', ', $turnstileRecaptchaResponse->{'error-codes'}),
466 'bit-form'
467 )
468 );
469 }
470
471 $isTurnstileCaptchaVerified = $turnstileRecaptchaResponse->success;
472 }
473 if (!$isTurnstileCaptchaVerified) {
474 return new WP_Error('spam_detection', __('Please verify Cloudflare Turnstile Captcha', 'bit-form'));
475 }
476 }
477 }
478
479 /* Implement Turnstile Captcha end */
480 $existAuth = (new IntegrationHandler($this->_form_id))->getAllIntegration('wp_user_auth', 'wp_auth', 1);
481
482 // check if user is already logged in and form has auth integration
483 do_action('bitform_checked_exist_auth', $this->_form_id, $existAuth);
484 if (!is_wp_error($existAuth) && count($existAuth) > 0 && is_user_logged_in()) {
485 return new WP_Error('auth_error', __('You are already logged in', 'bit-form'));
486 }
487 $validateForm = $this->validateFormSubmission($_POST);
488 $validateFormFiles = $this->validateFormSubmission($_FILES);
489 $validateForm = array_merge($validateForm, $validateFormFiles);
490 $form_fields = $this->getFields();
491 // check if form-current-step is set and form is multi-step
492 $formCurrentStep = isset($_POST['form-current-step']) ? $_POST['form-current-step'] : null;
493 if (!is_null($formCurrentStep)) {
494 $formContents = $this->getFormContent();
495 $layout = $formContents->layout;
496 $stepIndex = (int) $formCurrentStep - 1;
497 $stepLayout = $layout[$stepIndex]->layout->lg;
498 $nestedLayout = $formContents->nestedLayout;
499 $step_fields = [];
500 foreach ($stepLayout as $lay) {
501 $fk = $lay->i;
502 if (isset($nestedLayout->{$fk})) {
503 $nestedLg = $nestedLayout->{$fk}->lg;
504 foreach ($nestedLg as $nestedLay) {
505 $nestedFk = $nestedLay->i;
506 $step_fields[$nestedFk] = $form_fields[$nestedFk];
507 }
508 }
509 $step_fields[$fk] = $form_fields[$fk];
510 }
511 $form_fields = $step_fields;
512 }
513 $formFieldValidator = new FormFieldValidator($form_fields, $_POST, $_FILES);
514 $validUniuqFields = [];
515 $existFilter = has_filter('bf_check_duplicate_entry');
516 if (true === $existFilter) {
517 $validUniuqFields = apply_filters('bf_check_duplicate_entry', $form_fields, $_POST);
518
519 $fieldKeys = array_keys($validUniuqFields);
520 $form_fields_keys = array_keys($form_fields);
521 $uniqueFields = [];
522 foreach ($fieldKeys as $key) {
523 if (in_array($key, $form_fields_keys)) {
524 $uniqueFields[] = $form_fields[$key];
525 }
526 }
527 do_action('bitform_Unique_entry', $uniqueFields, $validUniuqFields, $this->_form_id, $_POST);
528 }
529 $validateField = $formFieldValidator->validate('create', $this->_form_id);
530
531 if ($validateForm && $validateField && 0 === count($validUniuqFields)) {
532 return true;
533 } else {
534 $error = __('Please submit form with valid fields', 'bit-form');
535 if (!$validateForm) {
536 $errorMessages = $error;
537 } elseif (count($formFieldValidator->getMessage()) > 0) {
538 $errorMessages = $formFieldValidator->getMessage();
539 } else {
540 $errorMessages = 0 === count($validUniuqFields) ? $error : $validUniuqFields;
541 }
542 return new WP_Error('validation_error', $errorMessages);
543 }
544 }
545 return new WP_Error('unknown_form', __('Form does not exist', 'bit-form'));
546 } else {
547 return new WP_Error('token_expired', __('Token expired', 'bit-form'));
548 }
549 }
550
551 public function verifySubmissionNonce()
552 {
553 if (!isset($_POST['t_identity']) && !isset($_POST['csrf'])) {
554 return false;
555 }
556 $tIdenty = sanitize_text_field($_POST['t_identity']);
557 $csrf = sanitize_text_field($_POST['csrf']);
558 unset($_POST['t_identity'], $_POST['action'], $_POST['bitforms_id'], $_POST['csrf']);
559 return Helpers::csrfDecrypted($tIdenty, $csrf);
560 }
561
562 public function setViewCount()
563 {
564 if (!current_user_can('manage_options')) {
565 $update_status = $this->formModel->update(
566 [
567 'views' => intval(static::$form[0]->views) + 1
568 ],
569 [
570 'id' => $this->form_id
571 ]
572 );
573 }
574 }
575
576 public function checkSubmissionRestriction($checkedEmptySubmitted = true)
577 {
578 $formContents = $this->getFormContent();
579 $fromRestrictionSetitingsEnabled = empty($formContents->additional->enabled) ? [] : $formContents->additional->enabled;
580 $fromRestrictionSetitings = empty($formContents->additional->settings) ? null : $formContents->additional->settings;
581 if (is_null($formContents->additional->enabled) || is_null($formContents->additional->settings)) {
582 return false;
583 }
584 $restrictionMessage = [];
585 $ipTool = new IpTool();
586 $ipAddress = $ipTool->getIP();
587 foreach ($fromRestrictionSetitingsEnabled as $restrictionKey => $isEnabled) {
588 if ($isEnabled) {
589 if ('entry_limit' === $restrictionKey && isset($fromRestrictionSetitings->{$restrictionKey})) {
590 $formEntry = new FormEntryModel();
591 $countResult = $formEntry->count(
592 [
593 'form_id' => $this->form_id
594 ]
595 );
596 $count = !empty($countResult[0]) && !empty($countResult[0]->count) ? $countResult[0]->count : false;
597 if ($count && $count >= intval($fromRestrictionSetitings->{$restrictionKey})) {
598 $restrictionMessage[] = __('Sorry!! Entry limit exceeded', 'bit-form');
599 }
600 }
601 if ('onePerIp' === $restrictionKey) {
602 $formEntry = new FormEntryModel();
603 $countResult = $formEntry->count(
604 [
605 'form_id' => $this->form_id,
606 'user_ip' => ip2long($ipAddress)
607 ]
608 );
609 $count = !empty($countResult[0]) && !empty($countResult[0]->count) ? $countResult[0]->count : false;
610
611 if ($count && $count > 0) {
612 $restrictionMessage[] = __('Sorry!! You have already submitted', 'bit-form');
613 }
614 }
615 if ('is_login' === $restrictionKey && 0 === get_current_user_id()) {
616 $restrictionMessage[] = __($fromRestrictionSetitings->is_login->message, 'bit-form');
617 }
618 if ($checkedEmptySubmitted && 'empty_submission' === $restrictionKey) {
619 $isEmpty = $this->checkEmptySubmission($_POST, $_FILES);
620 if ($isEmpty) {
621 $restrictionMessage[] = __($fromRestrictionSetitings->empty_submission->message, 'bit-form');
622 }
623 }
624 if ('restrict_form' === $restrictionKey && isset($fromRestrictionSetitings->{$restrictionKey})) {
625 $day = empty($fromRestrictionSetitings->{$restrictionKey}->day) ? null : $fromRestrictionSetitings->{$restrictionKey}->day;
626 $date = empty($fromRestrictionSetitings->{$restrictionKey}->date) ? null : $fromRestrictionSetitings->{$restrictionKey}->date;
627 $time = empty($fromRestrictionSetitings->{$restrictionKey}->time) ? null : $fromRestrictionSetitings->{$restrictionKey}->time;
628
629 $isdayOk = $isdateOk = $istimeOk = true;
630 $dayNotOkMsg = $dateNotOkMsg = $timeNotOkMsg = '';
631 $dateTimeHelper = new DateTimeHelper();
632 if (
633 !empty($day)
634 && is_array($day)
635 && (in_array('Friday', $day)
636 || in_array('Saturday', $day)
637 || in_array('Sunday', $day)
638 || in_array('Monday', $day)
639 || in_array('Tuesday', $day)
640 || in_array('Wednesday', $day)
641 || in_array('Thursday', $day))
642 && (!in_array($dateTimeHelper->getDay('full-name'), $day))
643 ) {
644 $isdayOk = false;
645 $dayMsgVarsFormat = '';
646 foreach ($day as $dayIndex => $dayValue) {
647 if ($dayIndex > 0) {
648 $dayMsgVarsFormat .= ', ';
649 }
650 $dayMsgVarsFormat .= '%s';
651 }
652 $dayNotOkMsg = vsprintf(__("in $dayMsgVarsFormat", 'bit-form'), $day);
653 }
654 if (
655 !empty($day)
656 && is_array($day)
657 && (in_array('Custom', $day))
658 ) {
659 $startDate = empty($date->from) ? '00-00-0000' : $date->from;
660 $endDate = empty($date->to) ? '00-00-0000' : $date->to;
661 $dateFormat = preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $startDate) ? 'Y-m-d' : 'm-d-Y';
662 if (!empty($date->from) && false !== strpos($startDate, 'T')) {
663 $startDate = $dateTimeHelper->getDate($startDate, false, null, $dateFormat);
664 }
665 if (!empty($date->to) && false !== strpos($endDate, 'T')) {
666 $endDate = $dateTimeHelper->getDate($endDate, false, null, $dateFormat);
667 }
668 $currentDate = $dateTimeHelper->getDate(null, null, null, $dateFormat);
669 if (!($currentDate >= $startDate && $currentDate <= $endDate)) {
670 $isdateOk = false;
671 $dateNotOkMsg = sprintf(__('within %s to %s', 'bit-form'), $startDate, $endDate);
672 }
673 }
674
675 if (!empty($time)) {
676 $startTime = empty($time->from) ? '00:00' : $time->from;
677 $endTime = empty($time->to) ? '23:59.999' : $time->to;
678 $currentTime = $dateTimeHelper->getTime(null, null, null, 'H:i');
679 if (!($currentTime >= $startTime && $currentTime <= $endTime)) {
680 $istimeOk = false;
681 $startTime = $dateTimeHelper->getTime($startTime, 'H:i', null);
682 $endTime = $dateTimeHelper->getTime($endTime, 'H:i', null);
683 $isTimeOk = false;
684 $timeNotOkMsg = sprintf(__('%s to %s', 'bit-form'), $startTime, $endTime);
685 }
686 }
687
688 if (!($isdateOk && $isdayOk && $istimeOk)) {
689 if (!$isdayOk) {
690 $restrictionMessage[] = !empty($timeNotOkMsg) ? sprintf(__('Form is available %s From %s', 'bit-form'), $dayNotOkMsg, $timeNotOkMsg) :
691 sprintf(__('Form is available %s', 'bit-form'), $dayNotOkMsg, $timeNotOkMsg);
692 } elseif (!$isdateOk) {
693 $restrictionMessage[] = !empty($timeNotOkMsg) ? sprintf(__('Form is available %s From %s', 'bit-form'), $dateNotOkMsg, $timeNotOkMsg) :
694 sprintf(__('Form is available %s', 'bit-form'), $dateNotOkMsg, $timeNotOkMsg);
695 } elseif (!$istimeOk) {
696 $restrictionMessage[] = sprintf(__('Form is available on %s', 'bit-form'), $timeNotOkMsg);
697 }
698 }
699 }
700 if ('blocked_ip' === $restrictionKey && isset($fromRestrictionSetitings->{$restrictionKey})) {
701 $isIpBlocked = false;
702 foreach ($fromRestrictionSetitings->{$restrictionKey} as $ipIndex => $ipDetails) {
703 if (!empty($ipDetails->status) && $ipDetails->status && !empty($ipDetails->ip) && $ipDetails->ip === $ipAddress) {
704 $isIpBlocked = true;
705 break;
706 }
707 }
708 if ($isIpBlocked) {
709 $restrictionMessage[] = sprintf(__('Sorry!! Your IP address is %s, Blocked from submitting the form', 'bit-form'), $ipAddress);
710 }
711 }
712 if ('private_ip' === $restrictionKey && isset($fromRestrictionSetitings->{$restrictionKey})) {
713 $isIpWhiteListed = false;
714 foreach ($fromRestrictionSetitings->{$restrictionKey} as $ipIndex => $ipDetails) {
715 if (!empty($ipDetails->status) && $ipDetails->status && !empty($ipDetails->ip) && $ipDetails->ip === $ipAddress) {
716 $isIpWhiteListed = true;
717 break;
718 }
719 }
720 if (!$isIpWhiteListed) {
721 $restrictionMessage[] = sprintf(__('Sorry!! Your IP address is %s, Blocked from submitting the form', 'bit-form'), $ipAddress);
722 }
723 }
724 }
725 }
726 return $restrictionMessage;
727 }
728
729 /**
730 * Will check if form is submitted by a bot
731 *
732 * @return Boolean true - if submitted by bot else false
733 */
734 public function isTrappedInHoneypot()
735 {
736 $isHoneyPot = false;
737
738 if (!$this->isHoneypotActive()) {
739 return false;
740 }
741
742 $token = $_POST['b_h_t'];
743 $pattern = '/^([a-zA-Z0-9]*_[a-zA-Z0-9]*){4}$/';
744 $decryptedToken = base64_decode(base64_decode($token));
745
746 preg_match($pattern, $decryptedToken, $validToken);
747
748 if ($validToken) {
749 if (isset($_POST[$token]) && empty($_POST[$token])) {
750 $isHoneyPot = false;
751 } else {
752 $isHoneyPot = true;
753 }
754 } else {
755 $isHoneyPot = true;
756 }
757
758 if (isset($_POST[$token])) {
759 unset($_POST[$token]);
760 }
761 unset($_POST['b_h_t']);
762 return $isHoneyPot;
763 }
764
765 public function isHoneypotActive()
766 {
767 $formContents = $this->getFormContent();
768 $enabled = empty($formContents->additional->enabled) ? null : $formContents->additional->enabled;
769 if (!empty($enabled->honeypot) && $enabled->honeypot) {
770 return true;
771 }
772 return false;
773 }
774
775 public function checkPaymentFields()
776 {
777 $formContents = $this->getFormContent();
778 $fields = $formContents->fields;
779
780 $payments = [];
781 foreach ($fields as $fldData) {
782 if ('paypal' === $fldData->typ && property_exists($fldData, 'payIntegID')) {
783 $payments['paypalKey'] = $this->getClientKey($fldData->payIntegID, 'clientID');
784 } elseif ('razorpay' === $fldData->typ && property_exists($fldData->options, 'payIntegID')) {
785 $payments['razorpayKey'] = $this->getClientKey($fldData->options->payIntegID, 'apiKey');
786 }
787 }
788
789 return $payments;
790 }
791
792 private function getClientKey($integID, $keyName)
793 {
794 $client = '';
795 if (!empty($integID)) {
796 $integrationHandler = new IntegrationHandler(0);
797 $integration = $integrationHandler->getAIntegration($integID, 'app', 'payments');
798 if (!is_wp_error($integration)) {
799 $integration_details = json_decode($integration[0]->integration_details);
800 $client = base64_encode($integration_details->{$keyName});
801 }
802 }
803 return $client;
804 }
805
806 public function getSuccessMessageMarkups()
807 {
808 if (is_null($this->_work_flows)) {
809 $workFlowManager = new WorkFlowHandler($this->form_id);
810 $this->_work_flows = $workFlowManager->getAllworkFlow();
811 }
812
813 $ids = [];
814 foreach ($this->_work_flows as $msgItem) {
815 foreach ($msgItem['conditions'] as $condition) {
816 if (isset($condition->actions->success)) {
817 foreach ($condition->actions->success as $msg) {
818 if ('successMsg' === $msg->type && isset($msg->details->id)) {
819 $idObj = json_decode(stripslashes($msg->details->id));
820 if (is_object($idObj) && !empty($idObj->id)) {
821 array_push($ids, $idObj->id);
822 }
823 }
824 }
825 }
826 if (isset($condition->actions->failure)) {
827 $idObj = json_decode(stripslashes($condition->actions->failure));
828 if (is_object($idObj) && !empty($idObj->id)) {
829 array_push($ids, $idObj->id);
830 }
831 }
832 }
833 }
834 $ids = array_unique($ids);
835 if (is_null($this->_conf_messages)) {
836 $successMsgHandler = new SuccessMessageHandler($this->form_id);
837 $this->_conf_messages = $successMsgHandler->getMessages($ids);
838 }
839
840 $messageMarkups = '';
841 if (is_wp_error($this->_conf_messages)) {
842 return $messageMarkups;
843 }
844
845 foreach ($this->_conf_messages as $msgItem) {
846 $messageMarkups .= $this->messageMarkup($msgItem);
847 }
848
849 return $messageMarkups;
850 }
851
852 public function getFormAbandonmentMessage()
853 {
854 if (class_exists('\BitCode\BitFormPro\Admin\FormSettings\FormAbandonment')) {
855 $formAbandonmentSettings = FormAbandonment::getFormAbandonmentSettings($this->form_id);
856 $msg = '';
857 if (isset($formAbandonmentSettings->showWarningMsg) && $formAbandonmentSettings->showWarningMsg && !empty($formAbandonmentSettings->warningMsg)) {
858 $msg = $formAbandonmentSettings->warningMsg;
859 $msg = '<div class="bf-form-msg active warning">' . wp_kses_post($msg) . '</div>';
860 }
861 return $msg;
862 }
863 }
864
865 private function messageMarkup($msg)
866 {
867 $msgId = $msg->id;
868 $msgConfig = json_decode($msg->message_config);
869 $scrollClass = 'below' === $msgConfig->msgType ? 'scroll' : '';
870
871 return <<<SUCCESSMSG
872 <div role="dialog" aria-hidden="true" data-modal-backdrop="true" class="{$this->getAtomicCls("msg-container-{$msgId}")} deactive {$scrollClass}">
873 <div data-contentid="{$this->getFormIdentifier()}" data-msgid="{$msgId}" role="button" class="{$this->getAtomicCls("msg-background-{$msgId}")} msg-backdrop">
874 <div class="bf-msg-content {$this->getAtomicCls("msg-content-{$msgId}")}">
875 <button data-contentid="{$this->getFormIdentifier()}" data-msgid="{$msgId}" class="{$this->getAtomicCls("close-{$msgId}")} bf-msg-close" type="button">
876 <svg class="{$this->getAtomicCls("close-icn-{$msgId}")}" viewBox="0 0 30 30">
877 <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" x1="4" y1="3.88" x2="26" y2="26.12"></line>
878 <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" x1="26" y1="3.88" x2="4" y2="26.12"></line>
879 </svg>
880 </button>
881 <div class="msg-content"></div>
882 </div>
883 </div>
884 </div>
885 SUCCESSMSG;
886 }
887 }
888