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

476 lines 17.8 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\Core\Database\FormModel;
7 use BitCode\BitForm\Core\Form\FormManager;
8 use BitCode\BitForm\Core\Integration\IntegrationHandler;
9 use BitCode\BitForm\Core\Util\FieldValueHandler;
10 use BitCode\BitForm\Core\Util\FrontendHelpers;
11 use BitCode\BitForm\Core\WorkFlow\WorkFlow;
12
13 final class FrontendFormHandler {
14 public function __construct() {
15 add_action('wp_enqueue_scripts', [$this, 'loadAssets']);
16 add_action('wp_footer', [$this, 'generateJS']);
17 add_shortcode('bitform', [$this, 'handleFrontendRenderRequest']);
18 }
19
20 private function validPassowordResetToken($token, $userID, $formId) {
21 $existResetInteg = (new IntegrationHandler($formId))->getAllIntegration('wp_user_auth', 'wp_auth', 1);
22 if (!is_wp_error($existResetInteg) && count($existResetInteg) > 0) {
23 if ('reset' === $existResetInteg[0]->integration_name) {
24 $user = get_userdata($userID);
25 if ($user) {
26 $validKey = check_password_reset_key($token, $user->user_login);
27 if (is_wp_error($validKey)) {
28 echo "<div id='bf-resp' style='display:grid;justify-content:center;color:#860000;'>This password reset token is invalid.</div>";
29 exit();
30 }
31 } else {
32 echo "<div id='bf-resp' style='display:grid;justify-content:center;color:#860000;'>Invalid User!!</div>";
33 exit();
34 }
35 }
36 }
37 }
38
39 private function getJSFileSrc($postId) {
40 $formUpdateVersion = get_option('bit-form_form_update_version');
41 $formScriptSrc = BITFORMS_UPLOAD_BASE_URL . "/form-scripts/$postId/bitform-js-$postId.js?bfv=$formUpdateVersion";
42
43 return $formScriptSrc;
44 }
45
46 public function generateJs($formID = null) {
47 $isFormPreview = get_transient('bitform_form_preview');
48 if ($isFormPreview && !$formID) {
49 delete_transient('bitform_form_preview');
50 return;
51 }
52 FrontendHelpers::isPageBuilder();
53 global $isPageBuilder;
54 if ($isPageBuilder) {
55 return;
56 }
57 // for unique fields ids in the same form (e.g. multiple forms in the same page)
58 $allFields = [];
59 $formContents = [];
60 $contentIds = [];
61 $formIDs = [];
62 $preview = false;
63 $postId = '';
64
65 if ($formID) {
66 $formIDs[] = $formID;
67 $FrontendFormManager = new FrontendFormManager($formID, 1);
68 $FormIdentifier = esc_js($FrontendFormManager->getFormIdentifier());
69 $formContent = $FrontendFormManager->getFormContentWithValue($this->getValuesFromQueryParams());
70 $formContents[] = $formContent;
71 $fields = $this->triggerWorkflowOnLoad($formID, 1, $formContent->fields);
72 array_push($contentIds, $FormIdentifier);
73 foreach ($fields as $fk => $field) {
74 $allFields[$field->typ][] = ['fk' => $fk, 'field' => $field, 'formID' => $formID, 'contentId' => $FormIdentifier];
75 }
76 $preview = true;
77 $postId = $formID;
78 } else {
79 global $post;
80 if (!is_object($post) && !isset($post->ID)) {
81 return;
82 }
83 FrontendHelpers::handleBfFormIdsSession();
84 global $bfFrontendFormIds;
85 $bfUniqFormIds = array_unique($bfFrontendFormIds);
86
87 $regenerateScriptFlag = $this->regenerateScriptChecker($bfUniqFormIds);
88 $postId = $post->ID;
89 if (!$regenerateScriptFlag) {
90 $regenerateScriptFlag = $this->deleteUnusedFormPageIds($postId, $bfUniqFormIds);
91 }
92 $isJsGenerating = get_option('bitforms_frontend_js_generating');
93 if (!$regenerateScriptFlag && !$isJsGenerating) {
94 wp_enqueue_script('bit-form-all-script-test', $this->getJSFileSrc($postId), [], '', true);
95 return;
96 }
97
98 $formIDs = $bfUniqFormIds;
99
100 foreach ($bfFrontendFormIds as $index => $formId) {
101 $shortCodeCounter = $index + 1;
102 $FrontendFormManager = new FrontendFormManager($formId, $shortCodeCounter);
103 $FormIdentifier = esc_js($FrontendFormManager->getFormIdentifier());
104 $formContent = $FrontendFormManager->getFormContentWithValue($this->getValuesFromQueryParams());
105 $formContents[] = $formContent;
106 $fields = $this->triggerWorkflowOnLoad($formId, $shortCodeCounter, $formContent->fields);
107 array_push($contentIds, $FormIdentifier);
108 foreach ($fields as $fk => $field) {
109 $allFields[$field->typ][] = ['fk' => $fk, 'field' => $field, 'formID' => $formId, 'contentId' => $FormIdentifier];
110 }
111 }
112 }
113 (new FrontEndScriptGenerator())->generateJsFile($formContents, $allFields, $contentIds, $postId, $formIDs, $preview);
114 wp_enqueue_script('bit-form-all-script-test', $this->getJSFileSrc($postId), [], '', true);
115 }
116
117 private function deleteUnusedFormPageIds($postId, $formIDs) {
118 global $post;
119 if (!is_object($post) && !isset($post->ID)) {
120 return;
121 }
122 $postId = $post->ID;
123 $formModel = new FormModel();
124 $forms = $formModel->get(
125 ['id', 'generated_script_page_ids']
126 );
127 $regenerateScriptFlag = false;
128 foreach ($forms as $form) {
129 $formId = $form->id;
130 $generatedScriptPageIdsDecoded = json_decode($form->generated_script_page_ids, true);
131 $generatedScriptPageIds = is_array($generatedScriptPageIdsDecoded) ? array_keys($generatedScriptPageIdsDecoded) : [];
132 if (!empty($generatedScriptPageIds) && !in_array($formId, $formIDs) && in_array($postId, $generatedScriptPageIds)) {
133 unset($generatedScriptPageIdsDecoded[$postId]);
134 $regenerateScriptFlag = true;
135 $formModel->update(['generated_script_page_ids' => wp_json_encode($generatedScriptPageIdsDecoded)], ['id' => $formId]);
136 }
137 }
138 return $regenerateScriptFlag;
139 }
140
141 private function regenerateScriptChecker($formsIds) {
142 global $post;
143 if (!is_object($post) && !isset($post->ID)) {
144 return;
145 }
146 $postId = $post->ID;
147 $regenerateScriptFlag = false;
148 $formModel = new FormModel();
149 foreach ($formsIds as $formId) {
150 $formInstance = new FormManager($formId);
151 $generatedPages = $formInstance->getFormData('generated_script_page_ids');
152
153 if (empty($generatedPages)) {
154 $regenerateScriptFlag = true;
155 } elseif (is_object($generatedPages) && (!isset($generatedPages->{$postId}) || (isset($generatedPages->{$postId}) && false === $generatedPages->{$postId}))) {
156 $regenerateScriptFlag = true;
157 }
158 if (!$regenerateScriptFlag) {
159 continue;
160 }
161
162 $generatedPages->{$postId} = true;
163 $formModel->update(
164 [
165 'generated_script_page_ids' => \wp_json_encode($generatedPages)
166 ],
167 [
168 'id' => $formId,
169 ]
170 );
171 }
172 return $regenerateScriptFlag;
173 }
174
175 private function addInlineScript($code, $handle = '', $position = 'after') {
176 $scriptHandle = !empty($handle) ? $handle : 'bf-inline-script';
177 if (!wp_script_is($scriptHandle)) {
178 wp_register_script($scriptHandle, '', [], '', true);
179 wp_enqueue_script($scriptHandle);
180 }
181 wp_add_inline_script($scriptHandle, $code, $position);
182 }
183
184 private function addInlineStyle($code, $handle = '') {
185 $styleHandle = !empty($handle) ? $handle : 'bf-inline-style';
186 if (!wp_style_is($styleHandle)) {
187 wp_register_style($styleHandle, '', [], '', true);
188 wp_enqueue_style($styleHandle);
189 }
190 wp_add_inline_style($styleHandle, $code);
191 }
192
193 private function triggerWorkflowOnLoad($formID, $shortCodeCounter, $fields) {
194 $FrontendFormManager = new FrontendFormManager($formID, $shortCodeCounter);
195 $previousValue = $this->getValuesFromQueryParams();
196 $formContent = $FrontendFormManager->getFormContentWithValue($previousValue);
197 if (!empty($formContent->workFlowExist)) {
198 $workFlowRunHelper = new WorkFlow($formID);
199 if (!empty($formContent->workFlowExist->onload)) {
200 $workFlowreturnedOnLoad = $workFlowRunHelper->executeOnLoad(
201 'create',
202 $fields
203 );
204
205 if (!empty($workFlowreturnedOnLoad['fields'])) {
206 return $workFlowreturnedOnLoad['fields'];
207 }
208 }
209 }
210
211 return $fields;
212 }
213
214 private function executeOnUserInput($formID, $shortCodeCounter, $fields) {
215 $FrontendFormManager = new FrontendFormManager($formID, $shortCodeCounter);
216 $previousValue = $this->getValuesFromQueryParams();
217 $formContent = $FrontendFormManager->getFormContentWithValue($previousValue);
218 $customCodesExist = strpos(FrontEndScriptGenerator::getCustomCodes($formID)['JavaScript'], 'bfVars');
219 if ($customCodesExist || (!empty($formContent->workFlowExist) && !empty($formContent->workFlowExist->oninput))) {
220 $workFlowRunHelper = new WorkFlow($formID);
221 return $workFlowRunHelper->executeOnUserInput('create', $fields);
222 }
223 }
224
225 private function getValuesFromQueryParams() {
226 $reqField = $_SERVER['QUERY_STRING'];
227 $queryParamsValue = [];
228 if (!empty($reqField)) {
229 foreach (explode('&', $reqField) as $keyValue) {
230 // $pattern = '/([a-zA-Z0-9])([a-zA-Z])\=+/';
231 $pattern = '/([^.]+)=(.*?)([^.]+)/';
232 $matches = preg_match($pattern, $keyValue, $matchFormat);
233 if ($matches) {
234 list($field, $value) = explode('=', $keyValue, 2);
235
236 if (!trim($value)) {
237 continue;
238 }
239
240 $queryParamsValue[$field][] = sanitize_text_field(urldecode($value));
241 }
242 }
243 }
244
245 return $queryParamsValue;
246 }
247
248 public function handleFrontendRenderRequest($atts, $formPreview = false) {
249 static $shortCodeCounter = 0;
250 $shortCodeCounter += 1;
251
252 if ($formPreview) {
253 // when $formPreview is true, it means that the atts is the form id
254 $formID = $atts;
255 } else {
256 $atts = shortcode_atts(['id' => 0], $atts);
257 $formID = intval($atts['id']);
258 }
259
260 if (!$formID) {
261 return __('Form ID cannot be empty', 'bit-form');
262 }
263
264 if (!$this->isExist($formID)) {
265 return sprintf(__('#%s no. Form doesn\'t exists', 'bit-form'), $formID);
266 }
267 FrontendHelpers::handleBfFormIdsSession($formID);
268 $FrontendFormManager = new FrontendFormManager($formID, $shortCodeCounter);
269
270 $font = $FrontendFormManager->getFont();
271
272 if ($font && !$formPreview) {
273 wp_enqueue_style('google-font', $font, '1.0.0', true);
274 }
275
276 if (!empty($_GET['token']) && !empty($_GET['id'])) {
277 $this->validPassowordResetToken($_GET['token'], $_GET['id'], $formID);
278 }
279
280 $previousValue = $this->getValuesFromQueryParams();
281 $errorMessages = []; // delete
282 $FormIdentifier = esc_js($FrontendFormManager->getFormIdentifier());
283 $nonce = $FrontendFormManager->getFormToken();
284 $file = count($FrontendFormManager->getUploadFields()) > 0 ? $FrontendFormManager->getUploadFields() : false;
285
286 if ($FrontendFormManager->checkStatus()) {
287 $FrontendFormManager->setViewCount();
288
289 $formContent = $FrontendFormManager->getFormContentWithValue($previousValue);
290 $fields = $formContent->fields;
291 $layout = $formContent->layout;
292 $buttons = !empty($formContent->buttons) ? $formContent->buttons : '';
293 $additional = $formContent->additional;
294
295 $fields = $this->triggerWorkflowOnLoad($formID, $shortCodeCounter, $fields);
296 $workFlowreturnedOnUserInput = $this->executeOnUserInput($formID, $shortCodeCounter, $fields);
297
298 // only for form not preview
299 if (!wp_style_is('bitform-style' . $formID)) {
300 $this->loadAssets(true, $formID, $file);
301 }
302
303 // test for form before remove
304 $noLabel = ['decision-box', 'html', 'button', 'paypal', 'razorpay', 'recaptcha'];
305 $newFields = json_decode(json_encode($fields), true);
306 foreach ($newFields as $fldKey => $field) {
307 if (!in_array($field['typ'], $noLabel) && isset($field['lbl'])) {
308 $lblReplaceToBackslash = str_replace('$_bf_$', '\\', $field['lbl']);
309 $newFields[$fldKey]['lbl'] = FieldValueHandler::replaceSmartTagWithValue($lblReplaceToBackslash);
310 }
311 }
312 $fieldsKey = $FrontendFormManager->getFieldsKey();
313
314 $captchaV3Settings = $FrontendFormManager->getCaptchaV3Settings();
315 if ($FrontendFormManager->getCaptchaSettings() || $captchaV3Settings) {
316 $integrationHandler = new IntegrationHandler(0);
317 $allFormIntegrations = $integrationHandler->getAllIntegration('app');
318 if (!is_wp_error($allFormIntegrations)) {
319 foreach ($allFormIntegrations as $integration) {
320 if (
321 $FrontendFormManager->getCaptchaSettings()
322 && !is_null($integration->integration_type)
323 && 'gReCaptcha' === $integration->integration_type
324 ) {
325 $integrationDetails = json_decode($integration->integration_details);
326 $integrationDetails->id = $integration->id;
327 $reCAPTCHA = $integrationDetails;
328 $reCAPTCHAVersion = 'v2';
329 }
330
331 if ($captchaV3Settings) {
332 if (!is_null($integration->integration_type) && 'gReCaptchaV3' === $integration->integration_type) {
333 $integrationDetails = json_decode($integration->integration_details);
334 $integrationDetails->id = $integration->id;
335 $reCAPTCHA = $integrationDetails;
336 $reCAPTCHAVersion = 'v3';
337 }
338 }
339 }
340 }
341 }
342
343 $configs = [
344 'bf_separator' => BITFORMS_BF_SEPARATOR,
345 ];
346
347 $bitFormFrontArr = [
348 'ajaxURL' => admin_url('admin-ajax.php'),
349 'nonce' => $nonce,
350 'version' => BITFORMS_VERSION,
351 'layout' => $layout,
352 'fields' => $newFields,
353 'buttons' => $buttons,
354 'fieldsKey' => $fieldsKey,
355 'file' => $file,
356 'configs' => $configs,
357 'formId' => $formID,
358 'GCLID' => $FrontendFormManager->isGCLIDEnabled(),
359 'assetUrl' => BITFORMS_ASSET_URI,
360 'onfieldCondition' => !empty($workFlowreturnedOnUserInput['onfield_input_conditions']) ? $workFlowreturnedOnUserInput['onfield_input_conditions'] : false,
361 'smartTags' => !empty($workFlowreturnedOnUserInput['smart_tags']) ? $workFlowreturnedOnUserInput['smart_tags'] : [],
362 'paymentCallbackUrl' => get_rest_url() . 'bitform/v1/payments/razorpay',
363 'gRecaptchaSiteKey' => !empty($reCAPTCHA->siteKey) ? $reCAPTCHA->siteKey : null,
364 'gRecaptchaVersion' => !empty($reCAPTCHAVersion) ? $reCAPTCHAVersion : null,
365 ];
366
367 if (isset($additional->enabled->validateFocusLost)) {
368 $bitFormFrontArr['validateFocusLost'] = true;
369 }
370
371 $bitFormsFront = apply_filters(
372 'bitforms_localized_script',
373 $bitFormFrontArr
374 );
375
376 $fields = \json_encode($fields);
377 $layout = \json_encode($layout);
378 $buttons = \json_encode($buttons);
379 $frontArr = json_encode($bitFormFrontArr);
380
381 $bfGlobals = "if(!window.bf_globals) {
382 window.bf_globals = {}
383 } if(!window.bf_globals.{$FormIdentifier}) {
384 window.bf_globals.{$FormIdentifier} = {}
385 }
386 window.bf_globals.{$FormIdentifier} = {...window.bf_globals.{$FormIdentifier}, ...{$frontArr}};";
387 $this->addInlineScript($bfGlobals, 'bit-form-all-script', 'before');
388
389 $html = '';
390
391 FrontendHelpers::isPageBuilder();
392 global $isPageBuilder;
393 if ($isPageBuilder) {
394 $newFormId = $formID . '-formid';
395 $formStyles = file_get_contents(BITFORMS_CONTENT_DIR . '/form-styles/bitform-' . $newFormId . '.css');
396 $html .= '<style>' . $formStyles . '</style>';
397 }
398 $html .= $FrontendFormManager->formView($fields, $file, $errorMessages);
399 // if form preview then return html otherwise echo with output buffer
400 if ($formPreview) {
401 $formViewObject = new \stdClass();
402 $formViewObject->html = $html;
403 $formViewObject->font = $font;
404 $formViewObject->bfGlobals = $bfGlobals;
405 return $formViewObject;
406 }
407
408 ob_start();
409 echo trim($html);
410 return ob_get_clean();
411 }
412 }
413
414 private function isExist($formID) {
415 $formModel = new FormModel();
416 $form = $formModel->get(
417 [
418 'id'
419 ],
420 [
421 'id' => $formID,
422 ]
423 );
424 if (!is_wp_error($form)) {
425 return true;
426 }
427 return false;
428 }
429
430 public function loadAssets($recheck = false, $formID = 0, $isFileExists = false) {
431 FrontendHelpers::getFormIdsFromPost();
432 FrontendHelpers::isPageBuilder();
433 global $bfUniqFormIds;
434 global $bfMultipleFormsExists;
435
436 if ($formID) {
437 $formIds = [$formID];
438 if (count($bfUniqFormIds) > 1) {
439 $bfMultipleFormsExists = true;
440 }
441 } else {
442 $formIds = $bfUniqFormIds;
443 }
444
445 foreach ($formIds as $formID) {
446 if ($bfMultipleFormsExists) {
447 $newFormId = $formID . '-formid';
448 } else {
449 $newFormId = $formID;
450 }
451 if (is_readable(BITFORMS_CONTENT_DIR . '/form-styles/bitform-' . $newFormId . '.css')) {
452 $styleModifyTime = filemtime(BITFORMS_CONTENT_DIR . '/form-styles/bitform-' . $newFormId . '.css');
453 wp_register_style(
454 'bitform-style' . $formID,
455 BITFORMS_UPLOAD_BASE_URL . '/form-styles/bitform-' . $newFormId . '.css',
456 [],
457 $styleModifyTime,
458 'all'
459 );
460 wp_enqueue_style('bitform-style' . $formID);
461 }
462 if (is_readable(BITFORMS_CONTENT_DIR . '/form-styles/bitform-custom-' . $newFormId . '.css')) {
463 $styleModifyTime = filemtime(BITFORMS_CONTENT_DIR . '/form-styles/bitform-custom-' . $newFormId . '.css');
464 wp_register_style(
465 'bitform-style-custom-' . $formID,
466 BITFORMS_UPLOAD_BASE_URL . '/form-styles/bitform-custom-' . $newFormId . '.css',
467 [],
468 $styleModifyTime,
469 'all'
470 );
471 wp_enqueue_style('bitform-style-custom-' . $formID);
472 }
473 }
474 }
475 }
476