PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.21.4
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.21.4
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 / FrontendFormHandler.php

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

782 lines 30.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace BitCode\BitForm\Frontend\Form;
4
5 use BitCode\BitForm\Admin\Form\AdminFormHandler;
6 use BitCode\BitForm\Admin\Form\FrontEndScriptGenerator;
7 use BitCode\BitForm\Admin\Form\Helpers;
8 use BitCode\BitForm\Core\Database\FormEntryMetaModel;
9 use BitCode\BitForm\Core\Database\FormModel;
10 use BitCode\BitForm\Core\Form\FormManager;
11 use BitCode\BitForm\Core\Integration\IntegrationHandler;
12 use BitCode\BitForm\Core\Util\FieldValueHandler;
13 use BitCode\BitForm\Core\Util\FileDownloadProvider;
14 use BitCode\BitForm\Core\Util\FrontendHelpers;
15 use BitCode\BitForm\Core\Util\SmartTags;
16 use BitCode\BitForm\Core\Util\Utilities;
17 use BitCode\BitForm\Core\WorkFlow\WorkFlow;
18 use BitCode\BitFormPro\Admin\FormSettings\FormAbandonment;
19
20 final class FrontendFormHandler
21 {
22 public function __construct()
23 {
24 // before markup load - formids [], posts [1,2]
25 add_action('wp_enqueue_scripts', [$this, 'loadAssets']);
26 // markup loads - formids []
27 add_shortcode('bitform', [$this, 'handleFrontendRenderRequest']);
28 // after markup load - formids [1,35,3]
29 add_action('wp_footer', [$this, 'generateJS']);
30 }
31
32 private function validPassowordResetToken($token, $userID, $formId)
33 {
34 $existResetInteg = (new IntegrationHandler($formId))->getAllIntegration('wp_user_auth', 'wp_auth', 1);
35 if (!is_wp_error($existResetInteg) && count($existResetInteg) > 0) {
36 if ('reset' === $existResetInteg[0]->integration_name) {
37 $user = get_userdata($userID);
38 if ($user) {
39 $validKey = check_password_reset_key($token, $user->user_login);
40 if (is_wp_error($validKey)) {
41 echo "<div id='bf-resp' style='display:grid;justify-content:center;color:#860000;'>This password reset token is invalid.</div>";
42 exit();
43 }
44 } else {
45 echo "<div id='bf-resp' style='display:grid;justify-content:center;color:#860000;'>Invalid User!!</div>";
46 exit();
47 }
48 }
49 }
50 }
51
52 private function getJSFileSrc($postId)
53 {
54 $formUpdateVersion = get_option('bit-form_form_update_version');
55 $formScriptSrc = BITFORMS_UPLOAD_BASE_URL . "/form-scripts/$postId/bitform-js-$postId.js?bfv=$formUpdateVersion";
56
57 return $formScriptSrc;
58 }
59
60 public function generateJs($formID = null, $entryID = null, $formType = null)
61 {
62 // return true;
63 $isFormPreview = get_transient('bitform_form_preview');
64 if ($isFormPreview && !$formID) {
65 delete_transient('bitform_form_preview');
66 return;
67 }
68 $frontendScriptGenObj = new FrontEndScriptGenerator();
69 $isPageBuilder = FrontendHelpers::checkIsPageBuilder($_SERVER);
70 $bfFrontendFormIds = FrontendHelpers::$bfFrontendFormIds;
71 if ($isPageBuilder || empty($bfFrontendFormIds)) {
72 return;
73 }
74 // for unique fields ids in the same form (e.g. multiple forms in the same page)
75 $allFields = [];
76 $formContents = [];
77 $contentIds = [];
78 $formIDs = [];
79 $previewMode = 'classic';
80 $postId = '';
81
82 $formUpdateVersion = get_option('bit-form_form_update_version');
83 if ($formID) {
84 $formIDs[] = $formID;
85 $FrontendFormManager = FrontendFormManager::getInstance($formID, 1);
86 $formInfo = $FrontendFormManager->getFormInfo();
87 $FormIdentifier = esc_js($FrontendFormManager->getFormIdentifier());
88 $formContent = $FrontendFormManager->getFormContentWithValue($this->getValuesFromQueryParams());
89 $formContent->formId = $formID;
90 $formContents[] = $formContent;
91 $workFlowRunType = $entryID ? 'edit' : 'create';
92 $fields = $formContent->fields;
93 if ($entryID) {
94 $fields = $this->setFieldsValue($fields, $formID, $entryID);
95 }
96 $fields = $this->triggerWorkflowOnLoad($formID, 1, $fields, $workFlowRunType);
97 array_push($contentIds, $FormIdentifier);
98
99 foreach ($fields as $fk => $field) {
100 $allFields[$field->typ][] = ['fk' => $fk, 'field' => $field, 'formID' => $formID, 'contentId' => $FormIdentifier];
101 }
102 //Generate JS file for conversational form
103 if (!empty($formInfo->conversationalSettings->enable) && $formInfo->conversationalSettings->enable) {
104 $frontendScriptGenObj->generateJsFile([$formContent], $allFields, [$FormIdentifier], $formID, [$formID], 'conversational');
105 }
106 $previewMode = 'preview';
107 $postId = $formID;
108 } else {
109 global $post;
110 if (!is_object($post) && !isset($post->ID)) {
111 return;
112 }
113 $bfFrontendFormIds = FrontendHelpers::$bfFrontendFormIds;
114 $bfUniqFormIds = FrontendHelpers::getAllUniqFormIdsInPage();
115 $formIDs = $bfUniqFormIds;
116 $regenerateScriptFlag = $this->regenerateScriptChecker($bfUniqFormIds);
117
118 $postId = $post->ID;
119 if (!$regenerateScriptFlag) {
120 $regenerateScriptFlag = $this->deleteUnusedFormPageIds($postId, $bfUniqFormIds);
121 }
122 $isJsGenerating = get_option('bitforms_frontend_js_generating');
123 if (!$regenerateScriptFlag && !$isJsGenerating && !empty($formIDs)) {
124 wp_enqueue_script('bit-form-all-script-test', $this->getJSFileSrc($postId), [], $formUpdateVersion, true);
125 return;
126 }
127 foreach ($bfFrontendFormIds as $index => $formId) {
128 $shortCodeCounter = $index + 1;
129 $FrontendFormManager = FrontendFormManager::getInstance($formId, $shortCodeCounter);
130 $formInfo = $FrontendFormManager->getFormInfo();
131 $FormIdentifier = esc_js($FrontendFormManager->getFormIdentifier());
132 $formContent = $FrontendFormManager->getFormContentWithValue($this->getValuesFromQueryParams());
133 $formContent->formId = $formId;
134 $formContents[] = $formContent;
135 $fields = $this->triggerWorkflowOnLoad($formId, $shortCodeCounter, $formContent->fields);
136 $contentIds[] = $FormIdentifier;
137 $formFields = []; // indivisual form fields array for conversational view
138 foreach ($fields as $fk => $field) {
139 $fieldArr = ['fk' => $fk, 'field' => $field, 'formID' => $formId, 'contentId' => $FormIdentifier];
140 $allFields[$field->typ][] = $fieldArr;
141 $formFields[$field->typ][] = $fieldArr;
142 }
143 //Generate JS file for conversational form
144 if (!empty($formInfo->conversationalSettings->enable) && $formInfo->conversationalSettings->enable) {
145 $frontendScriptGenObj->generateJsFile([$formContent], $formFields, [$FormIdentifier], $formId, [$formId], 'conversational');
146 }
147 }
148 }
149 if (empty($formIDs)) {
150 return;
151 }
152
153 $frontendScriptGenObj->generateJsFile($formContents, $allFields, $contentIds, $postId, $formIDs, $previewMode);
154 wp_enqueue_script('bit-form-all-script-test', $this->getJSFileSrc($postId), [], $formUpdateVersion, true);
155 }
156
157 private function deleteUnusedFormPageIds($postId, $formIDs)
158 {
159 global $post;
160 if (!is_object($post) && !isset($post->ID)) {
161 return;
162 }
163 $postId = $post->ID;
164 $formModel = new FormModel();
165 $forms = $formModel->get(
166 ['id', 'generated_script_page_ids']
167 );
168 $regenerateScriptFlag = false;
169 foreach ($forms as $form) {
170 $formId = $form->id;
171 $generatedScriptPageIdsDecoded = json_decode($form->generated_script_page_ids, true);
172 $generatedScriptPageIds = is_array($generatedScriptPageIdsDecoded) ? array_keys($generatedScriptPageIdsDecoded) : [];
173 if (!empty($generatedScriptPageIds) && !in_array($formId, $formIDs) && in_array($postId, $generatedScriptPageIds)) {
174 unset($generatedScriptPageIdsDecoded[$postId]);
175 if (empty($generatedScriptPageIdsDecoded)) {
176 $generatedScriptPageIdsDecoded = new \stdClass();
177 }
178 $regenerateScriptFlag = true;
179 $formModel->update(['generated_script_page_ids' => wp_json_encode($generatedScriptPageIdsDecoded)], ['id' => $formId]);
180 }
181 }
182 if ($regenerateScriptFlag) {
183 $formUpdateVersion = get_option('bit-form_form_update_version');
184 if (!$formUpdateVersion) {
185 $formUpdateVersion = 1;
186 } else {
187 $formUpdateVersion = (int) $formUpdateVersion + 1;
188 }
189 update_option('bit-form_form_update_version', $formUpdateVersion);
190 }
191 return $regenerateScriptFlag;
192 }
193
194 private function regenerateScriptChecker($formsIds)
195 {
196 global $post;
197 if (!is_a($post, 'WP_Post') && !isset($post->ID)) {
198 return;
199 }
200 $postId = $post->ID;
201 $regenerateScriptFlag = false;
202 $formModel = new FormModel();
203 foreach ($formsIds as $formId) {
204 $formInstance = FormManager::getInstance($formId);
205 if (!$formInstance->isExist()) {
206 continue;
207 }
208 $generatedPages = $formInstance->getFormData('generated_script_page_ids');
209 if (empty($generatedPages)) {
210 $regenerateScriptFlag = true;
211 } elseif (is_object($generatedPages) && (!isset($generatedPages->{$postId}) || (isset($generatedPages->{$postId}) && false === $generatedPages->{$postId}))) {
212 $regenerateScriptFlag = true;
213 }
214 if (!$regenerateScriptFlag) {
215 continue;
216 }
217 if (!is_object($generatedPages)) {
218 $generatedPages = (object) [];
219 }
220 $generatedPages->{$postId} = true;
221 $formModel->update(
222 [
223 'generated_script_page_ids' => \wp_json_encode($generatedPages)
224 ],
225 [
226 'id' => $formId,
227 ]
228 );
229 }
230 return $regenerateScriptFlag;
231 }
232
233 private function addInlineScript($code, $handle = '', $position = 'after')
234 {
235 $scriptHandle = !empty($handle) ? $handle : 'bf-inline-script';
236 if (!wp_script_is($scriptHandle)) {
237 wp_register_script($scriptHandle, '', [], '', true);
238 wp_enqueue_script($scriptHandle);
239 }
240 wp_add_inline_script($scriptHandle, $code, $position);
241 }
242
243 private function addInlineStyle($code, $handle = '')
244 {
245 $styleHandle = !empty($handle) ? $handle : 'bf-inline-style';
246 if (!wp_style_is($styleHandle)) {
247 wp_register_style($styleHandle, '', [], '', true);
248 wp_enqueue_style($styleHandle);
249 }
250 wp_add_inline_style($styleHandle, $code);
251 }
252
253 private function triggerWorkflowOnLoad($formID, $shortCodeCounter, $fields, $workFlowRunType = 'create')
254 {
255 $FrontendFormManager = new FrontendFormManager($formID, $shortCodeCounter);
256 $previousValue = $this->getValuesFromQueryParams();
257 $formContent = $FrontendFormManager->getFormContentWithValue($previousValue);
258 if (!empty($formContent->workFlowExist)) {
259 $workFlowRunHelper = new WorkFlow($formID);
260 if (!empty($formContent->workFlowExist->onload)) {
261 $workFlowreturnedOnLoad = $workFlowRunHelper->executeOnLoad(
262 $workFlowRunType,
263 $fields
264 );
265
266 if (!empty($workFlowreturnedOnLoad['fields'])) {
267 return $workFlowreturnedOnLoad['fields'];
268 }
269 }
270 }
271
272 return $fields;
273 }
274
275 private function executeOnUserInput($formID, $shortCodeCounter, $fields)
276 {
277 $FrontendFormManager = FrontendFormManager::getInstance($formID, $shortCodeCounter);
278 $previousValue = $this->getValuesFromQueryParams();
279 $formContent = $FrontendFormManager->getFormContentWithValue($previousValue);
280 $customCodesExist = strpos(FrontEndScriptGenerator::getCustomCodes($formID)['JavaScript'], 'bfVars');
281 if ($customCodesExist || (!empty($formContent->workFlowExist) && !empty($formContent->workFlowExist->oninput))) {
282 $workFlowRunHelper = new WorkFlow($formID);
283 return $workFlowRunHelper->executeOnUserInput('create', $fields);
284 }
285 }
286
287 private function getValuesFromQueryParams()
288 {
289 $queryParamsValue = [];
290 if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) {
291 $reqField = $_SERVER['QUERY_STRING'];
292 foreach (explode('&', $reqField) as $keyValue) {
293 // $pattern = '/([a-zA-Z0-9])([a-zA-Z])\=+/';
294 $pattern = '/([^.]+)=(.*?)([^.]+)/';
295 $matches = preg_match($pattern, $keyValue, $matchFormat);
296 if ($matches) {
297 list($field, $value) = explode('=', $keyValue, 2);
298
299 if (!trim($value)) {
300 continue;
301 }
302
303 $queryParamsValue[$field][] = sanitize_text_field(urldecode($value));
304 }
305 }
306 }
307
308 return $queryParamsValue;
309 }
310
311 public function handleFrontendRenderRequest($atts)
312 {
313 $formType = isset($atts['type']) ? $atts['type'] : 'classic';
314 $formPreview = isset($atts['form_preview']) ? $atts['form_preview'] : false;
315 if (isset($atts['form_id'])) {
316 $formID = intval($atts['form_id']);
317 }
318 if (isset($atts['entry_id'])) {
319 $entryId = intval($atts['entry_id']);
320 } elseif (isset($_GET['bf_entry_id'])) {
321 $entryId = $_GET['bf_entry_id'];
322 } else {
323 $entryId = false;
324 }
325 if (isset($atts['id'])) {
326 $atts = shortcode_atts(['id' => 0], $atts);
327 $formID = intval($atts['id']);
328 }
329
330 if (!$formID) {
331 return __('Form ID cannot be empty', 'bit-form');
332 }
333
334 if (!$this->isExist($formID)) {
335 return sprintf(__('#%s no. Form doesn\'t exists', 'bit-form'), $formID);
336 }
337
338 // check for abandoned form entry id
339 $isAbandoned = false;
340 if (empty($entryId) && Utilities::isPro() && class_exists('\BitCode\BitFormPro\Admin\FormSettings\FormAbandonment')) {
341 $FormAbandonment = new FormAbandonment($formID);
342 $isAbandoned = $FormAbandonment->checkAbandonedFormEntryId();
343 }
344
345 FrontendHelpers::setBfFrontendFormIds($formID);
346 $bfFrontendFormIds = FrontendHelpers::$bfFrontendFormIds;
347 $shortCodeCounter = count($bfFrontendFormIds);
348 $FrontendFormManager = FrontendFormManager::getInstance($formID, $shortCodeCounter);
349
350 if (!$FrontendFormManager->checkStatus()) {
351 return sprintf(__('#%s no. Form is not active', 'bit-form'), $formID);
352 }
353 ob_start();
354 $this->loadAssets($formID, $formType);
355
356 $font = $FrontendFormManager->getFont();
357
358 if ($font && !$formPreview) {
359 wp_enqueue_style('bf-google-font', $font, '1.0.0', true);
360 }
361
362 if (!empty($_GET['token']) && !empty($_GET['id'])) {
363 $this->validPassowordResetToken($_GET['token'], $_GET['id'], $formID);
364 }
365
366 $previousValue = $this->getValuesFromQueryParams();
367 $errorMessages = []; // delete
368 $FormIdentifier = esc_js($FrontendFormManager->getFormIdentifier());
369 $nonce = $FrontendFormManager->getFormToken();
370 $file = count($FrontendFormManager->getUploadFields()) > 0 ? $FrontendFormManager->getUploadFields() : false;
371
372 $FrontendFormManager->setViewCount();
373
374 $formContent = $FrontendFormManager->getFormContentWithValue($previousValue);
375 $fields = $formContent->fields;
376 $layout = $formContent->layout;
377 $nestedLayout = isset($formContent->nestedLayout) ? $formContent->nestedLayout : (object) [];
378 $buttons = !empty($formContent->buttons) ? $formContent->buttons : '';
379 $additional = $formContent->additional;
380
381 // $workFlowRunType = $entryId ? 'edit' : 'create';
382 if ($entryId && (FrontendHelpers::is_current_user_can_access($formID, 'entryEditAccess'))) {
383 $workFlowRunType = 'edit';
384 $adminFormHandler = new AdminFormHandler();
385 $getEntry = $adminFormHandler->getSingleEntry($formID, $entryId);
386 if (FrontendHelpers::is_current_user_can_access($formID, 'entryEditAccess', '', $getEntry->__user_id)) {
387 $fields = $this->setFieldsValue($fields, $formID, $entryId);
388 } elseif (!$isAbandoned) {
389 $entryId = false;
390 $workFlowRunType = 'create';
391 }
392 } else {
393 $entryId = false;
394 $workFlowRunType = 'create';
395 }
396
397 // if ($entryId) {
398 // $fields = $this->setFieldsValue($fields, $formID, $entryId);
399 // }
400
401 $fields = apply_filters('bitform_filter_before_workflow_onload_fields', $fields, $formID);
402 $fields = $this->triggerWorkflowOnLoad($formID, $shortCodeCounter, $fields, $workFlowRunType);
403 $fields = apply_filters('bitform_filter_after_workflow_onload_fields', $fields, $formID);
404 do_action('bitform_onload_fields', $fields, $formID);
405 $workFlowreturnedOnUserInput = $this->executeOnUserInput($formID, $shortCodeCounter, $fields);
406
407 // test for form before remove
408 $noLabelFieldTypes = ['decision-box', 'gdpr', 'html', 'shortcode', 'button', 'paypal', 'razorpay', 'recaptcha', 'turnstile', 'hcaptcha', 'stripe', 'spacer'];
409 foreach ($fields as $fldKey => $field) {
410 if (!in_array($field->typ, $noLabelFieldTypes) && isset($field->lbl)) {
411 $lblReplaceToBackslash = str_replace('$_bf_$', '\\', $field->lbl);
412 $fields->{$fldKey}->lbl = FieldValueHandler::replaceSmartTagWithValue($lblReplaceToBackslash);
413 }
414 }
415 $fieldsKey = $FrontendFormManager->getFieldsKey();
416
417 $captchaV3Settings = $FrontendFormManager->getCaptchaV3Settings();
418 if ($FrontendFormManager->getCaptchaSettings() || $captchaV3Settings || $FrontendFormManager->getTurnstileSettings() || $FrontendFormManager->isFieldTypeExist('hcaptcha')) {
419 $integrationHandler = new IntegrationHandler(0);
420 $allFormIntegrations = $integrationHandler->getAllIntegration('app');
421 if (!is_wp_error($allFormIntegrations)) {
422 foreach ($allFormIntegrations as $integration) {
423 if (
424 $FrontendFormManager->getCaptchaSettings()
425 && !is_null($integration->integration_type)
426 && 'gReCaptcha' === $integration->integration_type
427 ) {
428 $integrationDetails = json_decode($integration->integration_details);
429 $integrationDetails->id = $integration->id;
430 $reCAPTCHA = $integrationDetails;
431 $reCAPTCHAVersion = 'v2';
432 }
433
434 if (
435 $FrontendFormManager->getTurnstileSettings()
436 && !is_null($integration->integration_type)
437 && 'turnstileCaptcha' === $integration->integration_type
438 ) {
439 $integrationDetails = json_decode($integration->integration_details);
440 $turnstileSiteKey = $integrationDetails->siteKey;
441 }
442
443 if (
444 $FrontendFormManager->isFieldTypeExist('hcaptcha')
445 && !is_null($integration->integration_type)
446 && 'hcaptcha' === $integration->integration_type
447 ) {
448 $integrationDetails = json_decode($integration->integration_details);
449 $hCaptchaSiteKey = $integrationDetails->siteKey;
450 }
451
452 if ($captchaV3Settings) {
453 if (!is_null($integration->integration_type) && 'gReCaptchaV3' === $integration->integration_type) {
454 $integrationDetails = json_decode($integration->integration_details);
455 $integrationDetails->id = $integration->id;
456 $reCAPTCHA = $integrationDetails;
457 $reCAPTCHAVersion = 'v3';
458 }
459 }
460 }
461 }
462 }
463
464 if ($captchaV3Settings && !empty($reCAPTCHA->siteKey)) {
465 // DANGER: no matter what, DONT CHANGE THE SCRIPT ID OF THIS SCRIPT
466 $scriptId = BITFORMS_PREFIX . 'recaptcha';
467 wp_enqueue_script($scriptId, "https://www.google.com/recaptcha/api.js?render={$reCAPTCHA->siteKey}");
468 }
469
470 $configs = [
471 'bf_separator' => BITFORMS_BF_SEPARATOR,
472 ];
473
474 // check if fields has paypal or razorpay
475 $paymentFields = ['paypal', 'razorpay', 'stripe'];
476 $paymentFieldData = [];
477 foreach ($fields as $key => $field) {
478 if (in_array($field->typ, $paymentFields)) {
479 $paymentFieldData[$key] = $field;
480 }
481 }
482
483 if (!empty($paymentFieldData)) {
484 $integrationHandler = new IntegrationHandler(0);
485 foreach ($paymentFieldData as $fldKey => $fldData) {
486 $paymentIntegration = $integrationHandler->getAIntegration($fldData->payIntegID);
487 if (is_wp_error($paymentIntegration)) {
488 continue;
489 }
490 if ('paypal' === $fldData->typ) {
491 $integrationDetails = json_decode($paymentIntegration[0]->integration_details);
492 $clientID = $integrationDetails->clientID;
493 $fields->{$fldKey}->clientId = $clientID;
494 } elseif ('razorpay' === $fldData->typ) {
495 $integrationDetails = json_decode($paymentIntegration[0]->integration_details);
496 $clientID = $integrationDetails->apiKey;
497 $fields->{$fldKey}->clientId = $clientID;
498 } elseif ('stripe' === $fldData->typ) {
499 $integrationDetails = json_decode($paymentIntegration[0]->integration_details);
500 $publishableKey = $integrationDetails->publishableKey;
501 $fields->{$fldKey}->publishableKey = $publishableKey;
502 }
503 }
504 }
505
506 $bitFormFrontArr = [
507 'ajaxURL' => admin_url('admin-ajax.php'),
508 'nonce' => $nonce,
509 'version' => BITFORMS_VERSION,
510 'layout' => $layout,
511 'nestedLayout' => $nestedLayout,
512 'fields' => $fields,
513 'buttons' => $buttons,
514 'fieldsKey' => $fieldsKey,
515 'file' => $file,
516 'configs' => $configs,
517 'formId' => $formID,
518 'appID' => "bitforms_{$formID}",
519 'GCLID' => $FrontendFormManager->isGCLIDEnabled(),
520 'assetUrl' => BITFORMS_ASSET_URI,
521 'onfieldCondition' => !empty($workFlowreturnedOnUserInput['onfield_input_conditions']) ? $workFlowreturnedOnUserInput['onfield_input_conditions'] : false,
522 'smartTags' => SmartTags::smartTags(SmartTags::getPostUserData()),
523 'paymentCallbackUrl' => get_rest_url() . 'bitform/v1/payments/razorpay',
524 'gRecaptchaSiteKey' => !empty($reCAPTCHA->siteKey) ? $reCAPTCHA->siteKey : null,
525 'gRecaptchaVersion' => !empty($reCAPTCHAVersion) ? $reCAPTCHAVersion : null,
526 'turnstileSiteKey' => !empty($turnstileSiteKey) ? $turnstileSiteKey : null,
527 'hCaptchaSiteKey' => !empty($hCaptchaSiteKey) ? $hCaptchaSiteKey : null,
528 ];
529
530 if ($entryId) {
531 $bitFormFrontArr['entryId'] = $entryId;
532 }
533
534 if (isset($additional->enabled->validateFocusLost)) {
535 $bitFormFrontArr['validateFocusLost'] = true;
536 }
537
538 if (!empty($isAbandoned)) {
539 $bitFormFrontArr['oldValues'] = $this->getFieldsValue($formID, $isAbandoned);
540 if (empty($entryId)) {
541 $bitFormFrontArr['entryId'] = $isAbandoned;
542 }
543 }
544
545 $formInfo = $FrontendFormManager->getFormInfo();
546 if (is_array($layout) && count($layout) > 1) {
547 $multiStepSettings = isset($formInfo->multiStepSettings) ? $formInfo->multiStepSettings : null;
548 $newTempSettings = (object) [
549 'validateOnStepChange' => isset($multiStepSettings->validateOnStepChange) ? $multiStepSettings->validateOnStepChange : false,
550 'maintainStepHistory' => isset($multiStepSettings->maintainStepHistory) ? $multiStepSettings->maintainStepHistory : false,
551 'saveProgress' => isset($multiStepSettings->saveProgress) ? $multiStepSettings->saveProgress : false,
552 'showPercentage' => isset($multiStepSettings->progressSettings->showPercentage) ? $multiStepSettings->progressSettings->showPercentage : false,
553 ];
554 $bitFormFrontArr['formInfo'] = (object) [
555 'multiStepSettings' => $newTempSettings
556 ];
557 }
558
559 if (Helpers::property_exists_nested($formInfo, 'conversationalSettings->enable', true)) {
560 if (!isset($bitFormFrontArr['formInfo'])) {
561 $bitFormFrontArr['formInfo'] = new \stdClass();
562 }
563 $bitFormFrontArr['formInfo']->conversationalSettings = $formInfo->conversationalSettings;
564 }
565
566 $formAbandonmentSettings = $FrontendFormManager->getFormAbandonmentSettings();
567 if (Helpers::property_exists_nested($formAbandonmentSettings, 'active', true)) {
568 $bitFormFrontArr['formSettings'] = (object)[
569 'formAbandonment' => $formAbandonmentSettings
570 ];
571 }
572
573 $bitFormsFront = apply_filters(
574 'bitforms_localized_script',
575 $bitFormFrontArr
576 );
577
578 $layout = wp_json_encode($layout);
579 $buttons = wp_json_encode($buttons);
580 $frontArr = wp_json_encode($bitFormFrontArr);
581
582 $bfGlobals = <<<BFGLOBALS
583 if(!window.bf_globals) {
584 window.bf_globals = {}
585 } if(!window.bf_globals.{$FormIdentifier}) {
586 window.bf_globals.{$FormIdentifier} = {}
587 }
588 if(document.getElementById('{$FormIdentifier}')) {
589 window.bf_globals.{$FormIdentifier} = {
590 ...window.bf_globals.{$FormIdentifier},
591 ...{$frontArr}
592 };
593 }
594 BFGLOBALS;
595
596 if ('conversational' === $formType
597 && isset($formContent->formInfo->conversationalSettings->enable)
598 && $formContent->formInfo->conversationalSettings->enable) {
599 $html = $FrontendFormManager->conversationalFormView($fields, $file, $errorMessages);
600 } else {
601 $html = $FrontendFormManager->formView($fields, $file, $errorMessages);
602 }
603
604 // if form preview then return html otherwise echo with output buffer
605 if ($formPreview) {
606 ob_clean();
607 $formViewObject = new \stdClass();
608 $formViewObject->html = $html;
609 $formViewObject->font = $font;
610 $formViewObject->bfGlobals = $bfGlobals;
611 return $formViewObject;
612 }
613 $html .= <<<BFGLOBALSSCRIPT
614 <script id="bit-form-bf-globals-{$FormIdentifier}">{$bfGlobals}</script>
615 BFGLOBALSSCRIPT;
616 echo trim($html);
617 return ob_get_clean();
618 }
619
620 private function isExist($formID)
621 {
622 $formModel = new FormModel();
623 $form = $formModel->get(
624 [
625 'id'
626 ],
627 [
628 'id' => $formID,
629 ]
630 );
631 if (!is_wp_error($form)) {
632 return true;
633 }
634 return false;
635 }
636
637 private function getFieldsValue($formID, $entryID)
638 {
639 $FrontendFormManager = FrontendFormManager::getInstance($formID, 1);
640 $formEntryModel = new FormEntryMetaModel();
641 $metaValues = $formEntryModel->get(
642 [
643 'meta_key',
644 'meta_value'
645 ],
646 [
647 'bitforms_form_entry_id' => $entryID,
648 ]
649 );
650 $formFields = $FrontendFormManager->getFields();
651 $fldsData = (object) [];
652 if (!is_wp_error($metaValues)) {
653 foreach ($metaValues as $metaValue) {
654 $metaKey = $metaValue->meta_key;
655 $metaVal = $metaValue->meta_value;
656 // if meta value is array then convert to string
657 if (preg_match('/^\[.*\]$/', $metaVal)) {
658 $metaVal = json_decode($metaVal);
659 //check is it array of objects
660 if (is_array($metaVal) && is_object($metaVal[0])) {
661 $metaVal = $metaValue->meta_value;
662 } else {
663 $metaVal = implode(BITFORMS_BF_SEPARATOR, $metaVal);
664 }
665 }
666 if (!isset($fldsData->{$metaKey})) {
667 $fldsData->{$metaKey} = '';
668 }
669 $fldsData->{$metaKey} = $metaVal;
670 if (isset($formFields[$metaKey]['type']) && in_array($formFields[$metaKey]['type'], ['file-up', 'advanced-file-up'])) {
671 $fldsData->{$metaKey} = $metaValue->meta_value;
672 }
673 }
674 }
675
676 return $fldsData;
677 }
678
679 public function setFieldsValue($fields, $formID, $entryID)
680 {
681 $formEntryModel = new FormEntryMetaModel();
682 $metaValues = $formEntryModel->get(
683 [
684 'meta_key',
685 'meta_value'
686 ],
687 [
688 'bitforms_form_entry_id' => $entryID,
689 ]
690 );
691 if (!is_wp_error($metaValues)) {
692 foreach ($metaValues as $metaValue) {
693 $metaKey = $metaValue->meta_key;
694 $metaVal = $metaValue->meta_value;
695 // if meta value is array then convert to string
696 if (preg_match('/^\[.*\]$/', $metaVal)) {
697 $metaVal = json_decode($metaVal);
698 //check is it array of objects
699 if (is_array($metaVal) && is_object($metaVal[0])) {
700 $metaVal = $metaValue->meta_value;
701 } else {
702 $metaVal = implode(BITFORMS_BF_SEPARATOR, $metaVal);
703 }
704 }
705 if (property_exists($fields, $metaKey)) {
706 $fields->{$metaKey}->val = $metaVal;
707 if ('file-up' === $fields->{$metaKey}->typ || 'advanced-file-up' === $fields->{$metaKey}->typ) {
708 $fields->{$metaKey}->val = $metaValue->meta_value;
709 $fields->{$metaKey}->config->oldFiles = $metaValue->meta_value;
710 $urlQuery = wp_parse_url(FileDownloadProvider::getBaseDownloadURL(), PHP_URL_QUERY);
711 $baseDLURL = FileDownloadProvider::getBaseDownloadURL();
712 $baseDLURL = empty($urlQuery) ? $baseDLURL . '?' : $baseDLURL . '&';
713 $fields->{$metaKey}->config->baseDLURL = $baseDLURL . "formID={$formID}&entryID={$entryID}";
714 }
715 }
716 }
717 }
718 return $fields;
719 }
720
721 public function loadAssets($formID = 0, $fromType = 'classic')
722 {
723 $bfUniqFormIds = FrontendHelpers::getAllFormIdsInPage();
724 $isPageBuilder = FrontendHelpers::$isPageBuilder;
725 $bfMultipleFormsExists = $isPageBuilder ? true : count($bfUniqFormIds) > 1;
726
727 if (!empty($formID)) {
728 $formIds = [$formID];
729 } else {
730 $formIds = $bfUniqFormIds;
731 }
732 foreach ($formIds as $formID) {
733 global $bitform_dequeued_styles;
734 if (is_array($bitform_dequeued_styles) && in_array($formID, $bitform_dequeued_styles)) {
735 continue;
736 }
737 if ($bfMultipleFormsExists) {
738 $newFormId = $formID . '-formid';
739 } else {
740 $newFormId = $formID;
741 }
742 $formUpdateVersion = get_option('bit-form_form_update_version');
743 if (!wp_style_is('bitform-style-' . $newFormId) && is_readable(BITFORMS_CONTENT_DIR . '/form-styles/bitform-' . $newFormId . '.css')) {
744 wp_enqueue_style(
745 'bitform-style-' . $newFormId,
746 BITFORMS_UPLOAD_BASE_URL . "/form-styles/bitform-{$newFormId}.css",
747 [],
748 $formUpdateVersion
749 );
750 if ($isPageBuilder) {
751 $formStyle = file_get_contents(BITFORMS_CONTENT_DIR . '/form-styles/bitform-' . $newFormId . '.css');
752 echo sprintf("<style id='bitform-style-{$newFormId}'>%s</style>", $formStyle);
753 }
754 }
755 if (!wp_style_is('bitform-style-custom-' . $formID) && is_readable(BITFORMS_CONTENT_DIR . '/form-styles/bitform-custom-' . $formID . '.css')) {
756 wp_enqueue_style(
757 'bitform-style-custom-' . $formID,
758 BITFORMS_UPLOAD_BASE_URL . "/form-styles/bitform-custom-{$formID}.css",
759 [],
760 $formUpdateVersion
761 );
762 if ($isPageBuilder) {
763 $formStyle = file_get_contents(BITFORMS_CONTENT_DIR . '/form-styles/bitform-custom-' . $formID . '.css');
764 echo sprintf("<style id='bitform-style-custom-{$formID}'>%s</style>", $formStyle);
765 }
766 }
767 // load conversational form css
768 if ('conversational' === $fromType) {
769 if (!wp_style_is('bitform-conversational-style-' . $formID) &&
770 is_readable(BITFORMS_CONTENT_DIR . "/form-styles/bitform-conversational-{$formID}.css")) {
771 wp_enqueue_style(
772 'bitform-conversational-style',
773 BITFORMS_UPLOAD_BASE_URL . "/form-styles/bitform-conversational-{$formID}.css",
774 [],
775 $formUpdateVersion
776 );
777 }
778 }
779 }
780 }
781 }
782