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