PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.10.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.10.1
3.3.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 All 138 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.1, at includes/Frontend/Form/FrontendFormHandler.php

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