PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / V3.3.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder vV3.3.2
V3.3.2 3.3.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 All 139 releases
bit-form / includes / Admin / Form / FrontEndScriptGenerator.php

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

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