PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.10.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.10.2
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.10.2, at includes/Frontend/Form/FrontendFormHandler.php

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