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