PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.9.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.9.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 2.10.2 All 137 releases
← All changes | includes/Admin/Form/FrontEndScriptGenerator.php +315 -161 2.02.9.1 View file →
@@ -1,15 +1,23 @@
1 1 <?php
2 2
3 3 namespace BitCode\BitForm\Admin\Form;
4 4
5 +use BitCode\BitForm\Admin\Form\InitJs\Paypal;
6 +use BitCode\BitForm\Admin\Form\InitJs\Razorpay;
7 +use BitCode\BitForm\Admin\Form\InitJs\Recaptcha;
5 8 use BitCode\BitForm\Admin\Form\InitJs\RecaptchaV3;
6 -use BitCode\BitForm\Core\Form\FormManager;
7 -use BitCode\BitForm\Core\Integration\IntegrationHandler;
9 +use BitCode\BitForm\Admin\Form\InitJs\ScriptLoader;
10 +use BitCode\BitForm\Admin\Form\InitJs\Stripe;
11 +use BitCode\BitForm\Admin\Form\InitJs\Turnstile;
8 12 use BitCode\BitForm\Core\Util\Log;
13 +use BitCode\BitForm\Core\Util\Utilities;
14 +use BitCode\BitForm\Core\WorkFlow\WorkFlowHandler;
15 +use BitCode\BitFormPro\Admin\FormSettings\FormAbandonment;
9 16 use WP_Error;
10 17
11 -class FrontEndScriptGenerator {
18 +class FrontEndScriptGenerator
19 +{
12 20 private $_scriptAddedFlags;
13 21 private $_fields;
14 22 private $_formContents;
15 23 private $_jsFilesNeeded;
@@ -15,23 +23,28 @@
15 23 private $_jsFilesNeeded;
16 24 private $_loadedScriptsList;
17 25 private $_validationJsFilesNeeded;
18 26
19 - public function __construct() {
27 + public function __construct()
28 + {
20 29 $this->_scriptAddedFlags = [];
21 30 $this->_fields = [];
22 31 $this->_jsFilesNeeded = [];
23 32 $this->_loadedScriptsList = [];
24 - $this->_validationJsFilesNeeded = ScriptFilePriorityManager::validationScriptFile();
33 + $this->_validationJsFilesNeeded = ScriptFilePriorityManager::validationAndOtherScriptFile();
25 34 }
26 35
27 - private static function generateBfGlobalObjJS($contentIds = []) {
28 - // ["bitforms_3_submit_85_1", "bitforms_3_submit_85_2"]
29 - // bf_globals.{contentId}.inits
36 + private static function generateBfGlobalObjJS($contentIds = [])
37 + {
30 38 $contentidArray = json_encode($contentIds);
31 39 return <<<GLOBALOBJ
32 40 if(!window.bf_globals){ window.bf_globals = {};}
33 41 $contentidArray.forEach(function(contentId){
42 + const form = document.getElementById(contentId);
43 + if(!form){
44 + delete window.bf_globals[contentId];
45 + return;
46 + }
34 47 if(!window.bf_globals[contentId]){
35 48 window.bf_globals[contentId] = {inits: {}, contentId: contentId};
36 49 }else{
37 50 window.bf_globals[contentId].inits = {};
@@ -36,13 +49,15 @@
36 49 }else{
37 50 window.bf_globals[contentId].inits = {};
38 51 window.bf_globals[contentId].contentId = contentId;
39 52 }
53 +
40 54 });
41 55 GLOBALOBJ;
42 56 }
43 57
44 - private static function isValidationNeeded($fldData) {
58 + private static function isValidationNeeded($fldData)
59 + {
45 60 $validationsToCheck = ['valid->req', 'valid->regexr', 'mn', 'mx', 'opt', 'err->invalid->show'];
46 61 foreach ($validationsToCheck as $property) {
47 62 $needValidation = Helpers::property_exists_nested($fldData, $property);
48 63 if ($needValidation) {
@@ -51,9 +66,10 @@
51 66 }
52 67 return false;
53 68 }
54 69
55 - public function generateJsFile($formContents, $fields, $contentIds, $postId, $formIDs = null, $preview = false) {
70 + public function generateJsFile($formContents, $fields, $contentIds, $postId, $formIDs = null, $preview = false)
71 + {
56 72 add_option('bitforms_frontend_js_generating', true);
57 73 $this->_formContents = $formContents;
58 74 $this->_fields = $fields;
59 75
@@ -59,11 +75,8 @@
59 75
60 76 $this->appendJs(self::generateBfGlobalObjJS($contentIds), $postId, $preview, 'w');
61 77 $this->_jsFilesNeeded = ScriptFilePriorityManager::jsFile();
62 78
63 - // Recaptcha v3 script is loaded separately
64 - $this->appendJs($this->getRecaptchaV3Script($formIDs), $postId, $preview);
65 -
66 79 // helper js files for whole form
67 80 foreach ($this->_jsFilesNeeded['helperScript'] as $jsFile) {
68 81 $this->addScriptInLoadedScriptsList($jsFile);
69 82 }
@@ -76,13 +89,25 @@
76 89
77 90 // for frontend helper js files
78 91 $this->jsFrontendScript();
79 92
80 - // for hidden Field when catch plugin on
93 + // for hidden Field when cache plugin on
81 94 $this->jsHiddenFieldScript();
82 95
96 + // for form abandonment scripts
97 + $this->jsFormAbandonmentScripts();
98 +
99 + // multi step form scripts
100 + $this->multiStepFormScripts();
101 +
83 102 //⚠👆 every script file generate method call before this method
84 103 $this->appendJs($this->getScript(), $postId, $preview);
104 + $this->appendJs($this->generateFieldConfigsJs($contentIds), $postId, $preview);
105 + // init all js events and functions at last
106 + $this->appendJs(self::getFileFromAssetsJs('bitform-init.min.js'), $postId, $preview);
107 + if (defined('ELEMENTOR_PRO_VERSION')) {
108 + $this->appendJs(self::getFileFromAssetsJs('bitform-elementor.min.js'), $postId, $preview);
109 + }
85 110
86 111 // for js file minification
87 112 $this->appendJs(self::getCustomJsCodes($contentIds), $postId, $preview);
88 113 delete_option('bitforms_frontend_js_generating');
@@ -88,46 +113,74 @@
88 113 delete_option('bitforms_frontend_js_generating');
89 114 return true;
90 115 }
91 116
92 -/*
93 - public function generateJsFile($formContents, $fields, $contentIds, $postId, $formIDs = null, $preview = false) {
94 - $this->_formContents = $formContents;
95 - $this->_fields = $fields;
117 + private function multiStepFormScripts()
118 + {
119 + foreach ($this->_formContents as $formContent) {
120 + $layout = $formContent->layout;
121 + if (is_array($layout) && count($layout) > 1) {
122 + $files = ScriptFilePriorityManager::multiStepFiles();
123 + foreach ($files as $file) {
124 + $this->addScriptInLoadedScriptsList($file);
125 + }
126 + }
127 + }
128 + }
96 129
97 - $script = '';
98 - $script .= self::generateBfGlobalObjJS($contentIds);
99 - $this->_jsFilesNeeded = ScriptFilePriorityManager::jsFile();
130 + private function jsFormAbandonmentScripts()
131 + {
132 + if (!Utilities::isPro() || !class_exists('\BitCode\BitFormPro\Admin\FormSettings\FormAbandonment')) {
133 + return;
134 + }
135 + // check if any of the form has form abandonment enabled
136 + $allFiles = [];
137 + foreach ($this->_formContents as $formContent) {
138 + $formAbandonmentSettings = FormAbandonment::getFormAbandonmentSettings($formContent->formId);
139 + if (!empty($formAbandonmentSettings->saveFormDraft)) {
140 + $neededFiles = ScriptFilePriorityManager::formAbandonmentNeededFiles('autoSave');
141 + $allFiles = array_merge($allFiles, $neededFiles);
142 + break;
143 + }
100 144
101 - // Recaptcha v3 script is loaded separately
102 - $script .= $this->getRecaptchaV3Script($formIDs);
103 -
104 - // custom js files for whole form
105 - foreach ($this->_jsFilesNeeded['helperScript'] as $jsFile) {
145 + $workflowHandler = new WorkFlowHandler($formContent->formId);
146 + $allWorkflows = $workflowHandler->getAllworkFlow();
147 + foreach ($allWorkflows as $workflow) {
148 + foreach ($workflow['conditions'] as $cond) {
149 + if (!empty($cond->actions) && !empty($cond->actions->fields)) {
150 + foreach ($cond->actions->fields as $fldAction) {
151 + if (empty($fldAction->field) || empty($fldAction->action)) {
152 + continue;
153 + }
154 + if ('_bf_form' === $fldAction->field && 'save_draft' === $fldAction->action) {
155 + $neededFiles = ScriptFilePriorityManager::formAbandonmentNeededFiles();
156 + $allFiles = array_merge($allFiles, $neededFiles);
157 + }
158 + }
159 + }
160 + }
161 + }
162 + }
163 + if (isset($this->_fields['button'])) {
164 + foreach ($this->_fields['button'] as $button) {
165 + if ('save-draft' === $button['field']->btnTyp) {
166 + $neededFiles = ScriptFilePriorityManager::formAbandonmentNeededFiles();
167 + $allFiles = array_merge($allFiles, $neededFiles);
168 + break;
169 + }
170 + }
171 + }
172 + //
173 + if (empty($allFiles)) {
174 + return;
175 + }
176 + foreach ($allFiles as $jsFile) {
106 177 $this->addScriptInLoadedScriptsList($jsFile);
107 178 }
179 + }
108 180
109 - // for add validation js files
110 - $this->jsValidationNeededFile();
111 -
112 - // js files for all fields
113 - $this->jsFieldsNeededFile();
114 -
115 - // for frontend helper js files
116 - $this->jsFrontendScript();
117 -
118 - // for hidden Field when catch plugin on
119 - $this->jsHiddenFieldScript();
120 -
121 - //⚠👆 every script file generate method call before this method
122 - $script .= $this->getScript();
123 -
124 - // for js file minification
125 - $script = Helpers::minifyJS($script);
126 -
127 - $script .= self::getCustomJsCodes($contentIds);
128 -
129 - // write script file
181 + private function appendJs($script, $postId, $preview, $mode = 'a')
182 + {
130 183 $fileName = '';
131 184 $path = '';
132 185 if ($preview) {
133 186 $fileName = "preview-{$postId}.js";
@@ -135,42 +188,13 @@
135 188 } else {
136 189 $fileName = "bitform-js-$postId.js";
137 190 $path = "form-scripts/{$postId}";
138 191 }
139 - Helpers::saveFile($path, $fileName, $script, 'w');
140 - return true;
192 + Helpers::saveFile($path, $fileName, Helpers::minifyJs($script), $mode);
141 193 }
142 -*/
143 - private function appendJs($script, $postId, $preview, $mode = 'a') {
144 - $fileName = '';
145 - $path = '';
146 - if ($preview) {
147 - $fileName = "preview-{$postId}.js";
148 - $path = 'form-scripts';
149 - } else {
150 - $fileName = "bitform-js-$postId.js";
151 - $path = "form-scripts/{$postId}";
152 - }
153 - Helpers::saveFile($path, $fileName, Helpers::minifyJS($script), $mode);
154 - }
155 194
156 - private function getRecaptchaV3Script($formIds) {
157 - foreach ($formIds as $formID) {
158 - if (in_array('RecaptchaV3', $this->_scriptAddedFlags)) {
159 - break;
160 - }
161 - $getCaptchaV3Settings = (new FormManager($formID))->getCaptchaV3Settings();
162 - if ($getCaptchaV3Settings) {
163 - $integrationHandler = new IntegrationHandler(0);
164 - $allFormIntegrations = $integrationHandler->getAllIntegration('app', 'gReCaptchaV3');
165 - $siteKey = json_decode($allFormIntegrations[0]->integration_details)->siteKey;
166 - $this->_scriptAddedFlags[] = 'RecaptchaV3';
167 - return RecaptchaV3::init($siteKey);
168 - }
169 - }
170 - }
171 -
172 - private function getScript() {
195 + private function getScript()
196 + {
173 197 usort($this->_loadedScriptsList, function ($a, $b) {
174 198 return $a['priority'] - $b['priority'];
175 199 });
176 200
@@ -183,17 +207,8 @@
183 207 continue;
184 208 }
185 209 continue;
186 210 }
187 - if ('init' === $scriptFileArr['scriptTyp']) {
188 - $fieldObjInstance = $scriptFileArr['source'] . $fileNam;
189 - if (!class_exists($fieldObjInstance)) {
190 - continue;
191 - } // when class not found, skip load script
192 - $encodedConf = json_encode($scriptFileArr['field']->fldConfigs);
193 - $script .= $fieldObjInstance::init($scriptFileArr['fk'], $encodedConf, $scriptFileArr['contentId']);
194 - continue;
195 - }
196 211 if ('custom' === $scriptFileArr['scriptTyp']) {
197 212 $fileInstance = $scriptFileArr['source'] . $fileNam;
198 213 if (!class_exists($fileInstance)) {
199 214 continue;
@@ -203,9 +218,10 @@
203 218 }
204 219 return $script;
205 220 }
206 221
207 - private function jsValidationNeededFile() {
222 + private function jsValidationNeededFile()
223 + {
208 224 foreach ($this->_fields as $flds) {
209 225 foreach ($flds as $fld) {
210 226 $fldData = $fld['field'];
211 227 // for validation js files
@@ -246,9 +262,10 @@
246 262 }
247 263 }
248 264 }
249 265
250 - private function jsFieldsNeededFile() {
266 + private function jsFieldsNeededFile()
267 + {
251 268 foreach ($this->_fields as $typ => $flds) {
252 269 if (!array_key_exists($typ, $this->_jsFilesNeeded)) {
253 270 continue;
254 271 }
@@ -270,21 +287,12 @@
270 287 if (!isset($scriptFile['scriptTyp'])) {
271 288 $this->addScriptInLoadedScriptsList($scriptFile);
272 289 continue;
273 290 }
274 - if ('init' === $scriptFile['scriptTyp']) {
291 + if ('custom' === $scriptFile['scriptTyp'] && Helpers::property_exists_nested($fld['field'], $scriptFile['path'], true)) {
275 292 $scriptFile['field'] = $fld['field'];
276 293 $scriptFile['fk'] = $fld['fk'];
277 - $scriptFile['formID'] = $fld['formID'];
278 294 $scriptFile['contentId'] = $fld['contentId'];
279 - $fld['field']->fldConfigs = self::generateFieldConfig($fld['fk'], $fld['field'], $fld['formID']);
280 - $this->_loadedScriptsList[] = $scriptFile;
281 - continue;
282 - }
283 - if ('custom' === $scriptFile['scriptTyp']) {
284 - $scriptFile['field'] = $fld['field'];
285 - $scriptFile['fk'] = $fld['fk'];
286 - $scriptFile['contentId'] = $fld['contentId'];
287 295 $this->addScriptInLoadedScriptsList($scriptFile);
288 296 }
289 297 }
290 298 }
@@ -290,14 +298,15 @@
290 298 }
291 299 }
292 300 }
293 301
294 - private static function getCustomJsCodes($contentIds = []) {
302 + private static function getCustomJsCodes($contentIds = [])
303 + {
295 304 $script = 'let bfContentId = "", bfVars= "";';
296 305 foreach ($contentIds as $contentId) {
297 306 $jsCode = self::getCustomCodes(explode('_', $contentId)[1])['JavaScript'];
298 307 if (!empty($jsCode)) {
299 - $script .= " bfContentId = '{$contentId}'; bfVars = window.bf_globals.{$contentId}.smartTags; {$jsCode}";
308 + $script .= " if(bfSelect('#{$contentId}')){ bfContentId = '{$contentId}'; bfVars = window.bf_globals.{$contentId}.smartTags; {$jsCode}}";
300 309 }
301 310 }
302 311
303 312 return $script;
@@ -302,9 +311,10 @@
302 311
303 312 return $script;
304 313 }
305 314
306 - private static function getFileFromAssetsJs($fileName) {
315 + private static function getFileFromAssetsJs($fileName)
316 + {
307 317 $sourceJsFile = BITFORMS_PLUGIN_DIR_PATH . 'assets' . DIRECTORY_SEPARATOR . $fileName;
308 318 if (file_exists($sourceJsFile)) {
309 319 return file_get_contents($sourceJsFile);
310 320 }
@@ -311,9 +321,10 @@
311 321 Log::debug_log('file not found: ' . $fileName);
312 322 return false;
313 323 }
314 324
315 - public static function saveCssFile($formId, $atomicCssText) {
325 + public static function saveCssFile($formId, $atomicCssText)
326 + {
316 327 $path = 'form-styles';
317 328 $fileName = "bitform-$formId.css";
318 329 if (!isset($formId) || '' === $formId) {
319 330 return new WP_Error('missing_form_id', __('Error Occurred, Please Reload', 'bit-form'));
@@ -320,9 +331,10 @@
320 331 }
321 332 return Helpers::saveFile($path, $fileName, $atomicCssText, 'w');
322 333 }
323 334
324 - public static function customCodeFile($formId, $customCodes) {
335 + public static function customCodeFile($formId, $customCodes)
336 + {
325 337 // for js file
326 338 $path = 'form-scripts';
327 339 $fileName = "bitform-custom-$formId.js";
328 340 self::customCodeFileSaveOrDelete($customCodes->JavaScript, $path, $fileName);
@@ -334,9 +346,10 @@
334 346
335 347 return true;
336 348 }
337 349
338 - private static function customCodeFileSaveOrDelete($script, $path, $fileName) {
350 + public static function customCodeFileSaveOrDelete($script, $path, $fileName)
351 + {
339 352 if ($script) {
340 353 Helpers::saveFile($path, $fileName, $script, 'w');
341 354 } else {
342 355 $uploadPath = "$path/$fileName";
@@ -347,9 +360,10 @@
347 360 }
348 361 return true;
349 362 }
350 363
351 - public static function getCustomCodes($formId) {
364 + public static function getCustomCodes($formId)
365 + {
352 366 $customCodes = ['JavaScript' => '', 'CSS' => ''];
353 367 $customJsPath = Helpers::generatePathDirOrFile("form-scripts/bitform-custom-$formId.js");
354 368 $customCodes['JavaScript'] = Helpers::fileRead($customJsPath);
355 369
@@ -358,70 +372,205 @@
358 372
359 373 return $customCodes;
360 374 }
361 375
362 - public static function generateFieldConfig($fieldKey, $field, $formID) {
363 - $fieldType = $field->typ;
364 - $missingConfigs = ScriptFilePriorityManager::fieldMissingConfigsProps($fieldType, $field) ?: [];
365 - $hasConfigProp = in_array('config', $missingConfigs);
366 - $fldConf = (object) [];
367 - if (false === $hasConfigProp && isset($field->config)) {
368 - $fldConf = $field->config;
376 + private $fldContainersByType = [
377 + 'select' => '.__$fk__-dpd-fld-wrp',
378 + 'country' => '.__$fk__-country-fld-wrp',
379 + 'currency' => '.__$fk__-currency-fld-wrp',
380 + 'phone-number' => '.__$fk__-phone-fld-wrp',
381 + 'file-up' => '.__$fk__-file-up-wrpr',
382 + 'advanced-file-up' => '#filepond-__$fk__-container',
383 + 'paypal' => '.__$fk__-paypal-wrp',
384 + 'razorpay' => '.__$fk__-razorpay-wrp',
385 + 'recaptcha' => '.__$fk__-recaptcha-wrp',
386 + 'stripe' => '.__$fk__-stripe-fld',
387 + 'repeater' => '.__$fk__-rpt-fld-wrp',
388 + 'signature' => '.__$fk__-inp-fld-wrp',
389 + 'rating' => '.__$fk__-inp-fld-wrp',
390 + ];
391 +
392 + private function generateFieldConfigsJs()
393 + {
394 + $customFlds = ['select', 'country', 'currency', 'phone-number', 'file-up', 'advanced-file-up', 'paypal', 'razorpay', 'stripe', 'recaptcha', 'repeater', 'signature', 'rating', 'turnstile'];
395 + $allFieldTypes = array_keys($this->_fields);
396 + $customFldsInForms = array_intersect($allFieldTypes, $customFlds);
397 + $formContents = $this->_formContents;
398 + $recaptchaV3Enabled = false;
399 + foreach ($formContents as $content) {
400 + if (isset($content->additional->enabled->recaptchav3) && $content->additional->enabled->recaptchav3) {
401 + $recaptchaV3Enabled = true;
402 + break;
403 + }
369 404 }
370 - $vars = ['fieldKey' => $fieldKey, 'formID' => $formID];
371 - foreach ($missingConfigs as $confPath => $fldPath) {
372 - $value = '';
373 - if (isset($fldPath['var']) && $vars[$fldPath['var']]) {
374 - $value = $vars[$fldPath['var']];
405 + if (empty($customFldsInForms) && !$recaptchaV3Enabled) {
406 + return '';
407 + }
408 +
409 + $containers = [];
410 + foreach ($customFldsInForms as $customFldTyp) {
411 + if (isset($this->fldContainersByType[$customFldTyp])) {
412 + $containers[$customFldTyp] = $this->fldContainersByType[$customFldTyp];
375 413 }
376 - if (empty($value) && isset($fldPath['path'])) {
377 - $value = Helpers::getDataFromNestedPath($field, $fldPath['path']);
414 + }
415 +
416 + $customFldConfigPaths = [];
417 +
418 + foreach ($customFldsInForms as $customFldTyp) {
419 + $allConfs = ScriptFilePriorityManager::getAllFldConfs();
420 + if (isset($allConfs[$customFldTyp])) {
421 + $customFldConfigPaths[$customFldTyp] = $allConfs[$customFldTyp];
422 + } else {
423 + $customFldConfigPaths[$customFldTyp] = (object) [];
378 424 }
379 - if (empty($value) && isset($fldPath['val'])) {
380 - $value = $fldPath['val'];
381 - }
382 - $fldConf = Helpers::setDataToNestedPath($fldConf, $confPath, $value);
383 425 }
384 - return $fldConf;
385 - }
386 426
387 - private function getJsFuncForValidation() {
388 - $validationCmnFunc = ScriptFilePriorityManager::validationCommonFunction();
389 - foreach ($validationCmnFunc as $funcName => $funcArr) {
390 - // get need validation function from validationScriptFile()
391 - $scriptFile = $this->_validationJsFilesNeeded[$funcName];
392 - if (isset($funcArr['notFields'])) {
393 - if (is_array($funcArr['notFields'])) {
394 - foreach ($funcArr['notFields'] as $notField) {
395 - if (!isset($this->_fields[$notField])) {
396 - $this->addScriptInLoadedScriptsList($scriptFile);
397 - }
427 + $customFldConfigPaths = json_encode($customFldConfigPaths);
428 + $containers = json_encode($containers);
429 +
430 + $scriptLoaderFields = ['paypal', 'razorpay', 'stripe', 'recaptcha', 'turnstile'];
431 + $scriptLoadedNeeded = array_intersect($scriptLoaderFields, $customFldsInForms) || $recaptchaV3Enabled;
432 + if ($scriptLoadedNeeded) {
433 + $scriptLoaderJs = ScriptLoader::init();
434 + } else {
435 + $scriptLoaderJs = '';
436 + }
437 +
438 + if (in_array('paypal', $customFldsInForms)) {
439 + $paypalInitJs = Paypal::init();
440 + } else {
441 + $paypalInitJs = '';
442 + }
443 +
444 + if (in_array('razorpay', $customFldsInForms)) {
445 + $razorpayInitJs = Razorpay::init();
446 + } else {
447 + $razorpayInitJs = '';
448 + }
449 +
450 + if (in_array('stripe', $customFldsInForms)) {
451 + $stripeInitJs = Stripe::init();
452 + } else {
453 + $stripeInitJs = '';
454 + }
455 +
456 + if (in_array('recaptcha', $customFldsInForms)) {
457 + $recaptchaInitJs = Recaptcha::init();
458 + } else {
459 + $recaptchaInitJs = '';
460 + }
461 +
462 + if (in_array('turnstile', $customFldsInForms)) {
463 + $turnstileInitJs = Turnstile::init();
464 + } else {
465 + $turnstileInitJs = '';
466 + }
467 +
468 + if ($recaptchaV3Enabled) {
469 + $recaptchaV3InitJs = RecaptchaV3::init();
470 + } else {
471 + $recaptchaV3InitJs = '';
472 + }
473 +
474 + $script = <<<FIELDCONFIGJS
475 + const customFldConfigPaths = $customFldConfigPaths;
476 + const fldContainers = $containers;
477 +
478 + $scriptLoaderJs;
479 +
480 + function initAllCustomFlds (formContentId = null) {
481 + const allContendIds = formContentId ? [formContentId] : Object.keys(bf_globals);
482 + allContendIds.forEach((contentId) => {
483 + const contentData = bf_globals[contentId];
484 + const flds = bf_globals[contentId].fields;
485 + const fldKeys = Object.keys(flds).reverse();
486 + fldKeys.forEach((fldKey) => {
487 + const fldData = flds[fldKey];
488 + const fldType = fldData.typ;
489 + if(fldType === 'paypal') {
490 + $paypalInitJs;
491 + } else if(fldType === 'razorpay') {
492 + $razorpayInitJs;
493 + } else if(fldType === 'recaptcha') {
494 + $recaptchaInitJs;
495 + } else if(fldType === 'turnstile') {
496 + $turnstileInitJs;
497 + } else if(fldType === 'stripe') {
498 + $stripeInitJs;
499 + } else if (customFldConfigPaths[fldType]) {
500 + contentData.inits[fldKey] = getFldInstance(contentId, fldKey, fldType);
398 501 }
502 + });
503 + if(contentData.gRecaptchaVersion === 'v3' && contentData.gRecaptchaSiteKey){
504 + $recaptchaV3InitJs;
399 505 }
400 - }
401 - if (isset($funcArr['fields'])) {
402 - if (is_array($funcArr['fields'])) {
403 - foreach ($funcArr['fields'] as $fieldType) {
404 - if (isset($this->_fields[$fieldType])) {
405 - // for set function array in $this->_loadedScriptsList
406 - $this->addScriptInLoadedScriptsList($scriptFile);
407 - }
506 + });
507 + };
508 + function getFldInstance(contentId, fldKey, fldTyp, nestedSelector = '') {
509 + const fldClass = this['bit_'+fldTyp.replace(/-/g, '_')+'_field'];
510 + const selector = '#form-'+contentId+' '+nestedSelector+fldContainers[fldTyp].replace("__\$fk__", fldKey);
511 + if(!fldClass || !bfSelect(selector)) return;
512 + return new fldClass(selector, getFldConf(contentId, fldKey, fldTyp));
513 + };
514 + function getFldConf(contentId, fieldKey, fldTyp) {
515 + const fldData = bf_globals[contentId].fields[fieldKey];
516 + const fldConfPaths = Object.entries(customFldConfigPaths[fldTyp]);
517 + let fldConf = {};
518 + const { formId } = bf_globals[contentId];
519 + if (!("config" in customFldConfigPaths[fldTyp]) && "config" in fldData) fldConf = fldData.config;
520 + const varData = { contentId, fieldKey, formId };
521 + fldConfPaths.forEach(([ confPath, fldPath ]) => {
522 + let value = "";
523 + if (fldPath.var) value = varData[fldPath.var];
524 + if (!value && fldPath.path) {
525 + if(Array.isArray(fldPath.path)) {
526 + fldPath.path.forEach((path) => {
527 + if(!value) value = getDataFromNestedPath(fldData, path);
528 + });
529 + } else {
530 + value = getDataFromNestedPath(fldData, fldPath.path);
408 531 }
409 - } else {
410 - // for all field types
411 - $this->addScriptInLoadedScriptsList($scriptFile);
412 532 }
413 - }
414 -
415 - if (isset($funcArr['dependencies'])) {
416 - foreach ($funcArr['dependencies'] as $dependency) {
417 - $this->addScriptInLoadedScriptsList($dependency);
533 + if (!value && fldPath.val) {
534 + value = fldPath.val;
535 + if(typeof value === 'string') {
536 + Object.entries(varData).forEach(([key, val]) => {
537 + value = value.replace("__\$"+key+"__", val);
538 + });
539 + }
418 540 }
541 + fldConf = setDataToNestedPath(fldConf, confPath, value);
542 + });
543 + return fldConf;
544 + };
545 + function getDataFromNestedPath(data, key) {
546 + const keys = key.split("->");
547 + const lastKey = keys.pop();
548 + let current = {...data};
549 + for (const k of keys) {
550 + if (!(k in current)) return null;
551 + current = current[k];
419 552 }
553 + return current[lastKey] || null;
420 554 }
555 + function setDataToNestedPath(data, key, value) {
556 + const keys = key.split("->");
557 + const lastKey = keys.pop();
558 + let current = {...data};
559 + keys.forEach((k) => {
560 + if (!current[k]) current[k] = {};
561 + current = current[k];
562 + });
563 + current[lastKey] = value;
564 + return current;
565 + }
566 +FIELDCONFIGJS;
567 +
568 + return $script;
421 569 }
422 570
423 - private function addScriptInLoadedScriptsList($fileArr) {
571 + private function addScriptInLoadedScriptsList($fileArr)
572 + {
424 573 $fileName = $fileArr['filename'];
425 574 if (!in_array($fileName, $this->_scriptAddedFlags)) {
426 575 $this->_loadedScriptsList[] = $fileArr;
427 576 $this->_scriptAddedFlags[] = $fileName;
@@ -428,26 +577,30 @@
428 577 }
429 578 return true;
430 579 }
431 580
432 - private function jsFrontendScript() {
581 + private function jsFrontendScript()
582 + {
433 583 foreach ($this->_formContents as $formContent) {
434 584 if (Helpers::property_exists_nested($formContent, 'workFlowExist->oninput', true)) {
435 - $fileArr = ScriptFilePriorityManager::validationScriptFile()['conditionalLogic'];
585 + $fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['conditionalLogic'];
436 586 $this->addScriptInLoadedScriptsList($fileArr);
437 - $fileArr = ScriptFilePriorityManager::validationScriptFile()['validateFocusLost'];
587 + $fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['resetPlaceholders'];
438 588 $this->addScriptInLoadedScriptsList($fileArr);
589 + $fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['validateFocusLost'];
590 + $this->addScriptInLoadedScriptsList($fileArr);
439 591 $fileArr = ScriptFilePriorityManager::frontendScriptFile()['observeElm'];
440 592 $this->addScriptInLoadedScriptsList($fileArr);
441 593 }
442 594 if (Helpers::property_exists_nested($formContent, 'additional->enabled->validateFocusLost', true)) {
443 - $fileArr = ScriptFilePriorityManager::validationScriptFile()['validateFocusLost'];
595 + $fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['validateFocusLost'];
444 596 $this->addScriptInLoadedScriptsList($fileArr);
445 597 }
446 598 }
447 599 }
448 600
449 - private function jsHiddenFieldScript() {
601 + private function jsHiddenFieldScript()
602 + {
450 603 $appConfig = get_option('bitform_app_config');
451 604 if (Helpers::property_exists_nested($appConfig, 'cache_plugin', true)) {
452 605 $fileArr = ScriptFilePriorityManager::frontendScriptFile()['hidden-token-field'];
453 606 $this->addScriptInLoadedScriptsList($fileArr);
@@ -454,9 +607,10 @@
454 607 return;
455 608 }
456 609 }
457 610
458 - public function dd($data, $exit = false) {
611 + public function dd($data, $exit = false)
612 + {
459 613 echo '+++++++++++++';
460 614 echo '<pre>';
461 615 var_dump($data);
462 616 echo '</pre>';