PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.21.4
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.21.4
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 / Admin / Form / FrontEndScriptGenerator.php

FrontEndScriptGenerator.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 2.21.4, at includes/Admin/Form/FrontEndScriptGenerator.php

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