| 1 |
<?php |
| 2 |
|
| 3 |
namespace BitCode\BitForm\Admin\Form; |
| 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; |
| 8 |
use BitCode\BitForm\Admin\Form\InitJs\RecaptchaV3; |
| 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\Log; |
| 13 |
use BitCode\BitForm\Core\Util\Utilities; |
| 14 |
use BitCode\BitForm\Core\WorkFlow\WorkFlowHandler; |
| 15 |
use BitCode\BitFormPro\Admin\FormSettings\FormAbandonment; |
| 16 |
use WP_Error; |
| 17 |
|
| 18 |
class FrontEndScriptGenerator |
| 19 |
{ |
| 20 |
private $_scriptAddedFlags; |
| 21 |
private $_fields; |
| 22 |
private $_formContents; |
| 23 |
private $_jsFilesNeeded; |
| 24 |
private $_loadedScriptsList; |
| 25 |
private $_validationJsFilesNeeded; |
| 26 |
|
| 27 |
public function __construct() |
| 28 |
{ |
| 29 |
$this->_scriptAddedFlags = []; |
| 30 |
$this->_fields = []; |
| 31 |
$this->_jsFilesNeeded = []; |
| 32 |
$this->_loadedScriptsList = []; |
| 33 |
$this->_validationJsFilesNeeded = ScriptFilePriorityManager::validationAndOtherScriptFile(); |
| 34 |
} |
| 35 |
|
| 36 |
private static function generateBfGlobalObjJS($contentIds = []) |
| 37 |
{ |
| 38 |
$contentidArray = json_encode($contentIds); |
| 39 |
return <<<GLOBALOBJ |
| 40 |
if(!window.bf_globals){ window.bf_globals = {};} |
| 41 |
$contentidArray.forEach(function(contentId){ |
| 42 |
const form = document.getElementById(contentId); |
| 43 |
if(!form){ |
| 44 |
delete window.bf_globals[contentId]; |
| 45 |
return; |
| 46 |
} |
| 47 |
if(!window.bf_globals[contentId]){ |
| 48 |
window.bf_globals[contentId] = {inits: {}, contentId: contentId}; |
| 49 |
}else{ |
| 50 |
window.bf_globals[contentId].inits = {}; |
| 51 |
window.bf_globals[contentId].contentId = contentId; |
| 52 |
} |
| 53 |
|
| 54 |
}); |
| 55 |
GLOBALOBJ; |
| 56 |
} |
| 57 |
|
| 58 |
private static function isValidationNeeded($fldData) |
| 59 |
{ |
| 60 |
$validationsToCheck = ['valid->req', 'valid->regexr', 'mn', 'mx', 'opt', 'err->invalid->show']; |
| 61 |
foreach ($validationsToCheck as $property) { |
| 62 |
$needValidation = Helpers::property_exists_nested($fldData, $property); |
| 63 |
if ($needValidation) { |
| 64 |
return true; |
| 65 |
} |
| 66 |
} |
| 67 |
return false; |
| 68 |
} |
| 69 |
|
| 70 |
public function generateJsFile($formContents, $fields, $contentIds, $postId, $formIDs = null, $preview = false) |
| 71 |
{ |
| 72 |
add_option('bitforms_frontend_js_generating', true); |
| 73 |
$this->_formContents = $formContents; |
| 74 |
$this->_fields = $fields; |
| 75 |
|
| 76 |
$this->appendJs(self::generateBfGlobalObjJS($contentIds), $postId, $preview, 'w'); |
| 77 |
$this->_jsFilesNeeded = ScriptFilePriorityManager::jsFile(); |
| 78 |
|
| 79 |
// helper js files for whole form |
| 80 |
foreach ($this->_jsFilesNeeded['helperScript'] as $jsFile) { |
| 81 |
$this->addScriptInLoadedScriptsList($jsFile); |
| 82 |
} |
| 83 |
|
| 84 |
// for add validation js files |
| 85 |
$this->jsValidationNeededFile(); |
| 86 |
|
| 87 |
// js files for all fields |
| 88 |
$this->jsFieldsNeededFile(); |
| 89 |
|
| 90 |
// for frontend helper js files |
| 91 |
$this->jsFrontendScript(); |
| 92 |
|
| 93 |
// for hidden Field when cache plugin on |
| 94 |
$this->jsHiddenFieldScript(); |
| 95 |
|
| 96 |
// for form abandonment scripts |
| 97 |
$this->jsFormAbandonmentScripts(); |
| 98 |
|
| 99 |
// multi step form scripts |
| 100 |
$this->multiStepFormScripts(); |
| 101 |
|
| 102 |
//⚠👆 every script file generate method call before this method |
| 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 |
} |
| 110 |
|
| 111 |
// for js file minification |
| 112 |
$this->appendJs(self::getCustomJsCodes($contentIds), $postId, $preview); |
| 113 |
delete_option('bitforms_frontend_js_generating'); |
| 114 |
return true; |
| 115 |
} |
| 116 |
|
| 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 |
} |
| 129 |
|
| 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 |
} |
| 144 |
|
| 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) { |
| 177 |
$this->addScriptInLoadedScriptsList($jsFile); |
| 178 |
} |
| 179 |
} |
| 180 |
|
| 181 |
private function appendJs($script, $postId, $preview, $mode = 'a') |
| 182 |
{ |
| 183 |
$fileName = ''; |
| 184 |
$path = ''; |
| 185 |
if ($preview) { |
| 186 |
$fileName = "preview-{$postId}.js"; |
| 187 |
$path = 'form-scripts'; |
| 188 |
} else { |
| 189 |
$fileName = "bitform-js-$postId.js"; |
| 190 |
$path = "form-scripts/{$postId}"; |
| 191 |
} |
| 192 |
Helpers::saveFile($path, $fileName, Helpers::minifyJs($script), $mode); |
| 193 |
} |
| 194 |
|
| 195 |
private function getScript() |
| 196 |
{ |
| 197 |
usort($this->_loadedScriptsList, function ($a, $b) { |
| 198 |
return $a['priority'] - $b['priority']; |
| 199 |
}); |
| 200 |
|
| 201 |
$script = ''; |
| 202 |
foreach ($this->_loadedScriptsList as $scriptFileArr) { |
| 203 |
$fileNam = $scriptFileArr['filename']; |
| 204 |
if (!isset($scriptFileArr['scriptTyp']) || 'script' === $scriptFileArr['scriptTyp']) { |
| 205 |
if (self::getFileFromAssetsJs($fileNam)) { |
| 206 |
$script .= self::getFileFromAssetsJs($fileNam); |
| 207 |
continue; |
| 208 |
} |
| 209 |
continue; |
| 210 |
} |
| 211 |
if ('custom' === $scriptFileArr['scriptTyp']) { |
| 212 |
$fileInstance = $scriptFileArr['source'] . $fileNam; |
| 213 |
if (!class_exists($fileInstance)) { |
| 214 |
continue; |
| 215 |
} // when class not found, skip load script |
| 216 |
$script .= $fileInstance::init($scriptFileArr['fk'], $scriptFileArr['field'], $scriptFileArr['contentId']); |
| 217 |
} |
| 218 |
} |
| 219 |
return $script; |
| 220 |
} |
| 221 |
|
| 222 |
private function jsValidationNeededFile() |
| 223 |
{ |
| 224 |
foreach ($this->_fields as $flds) { |
| 225 |
foreach ($flds as $fld) { |
| 226 |
$fldData = $fld['field']; |
| 227 |
// for validation js files |
| 228 |
if (self::isValidationNeeded($fldData)) { |
| 229 |
$validation = $this->_validationJsFilesNeeded['validation']; |
| 230 |
$this->addScriptInLoadedScriptsList($validation); |
| 231 |
} |
| 232 |
// for required |
| 233 |
if (Helpers::property_exists_nested($fldData, 'valid->req')) { |
| 234 |
$fileArr = $this->_validationJsFilesNeeded['requiredFldValidation']; |
| 235 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 236 |
} |
| 237 |
// for regex |
| 238 |
if (Helpers::property_exists_nested($fldData, 'valid->regexr')) { |
| 239 |
$patternFile = $this->_validationJsFilesNeeded['generateBackslashPattern']; |
| 240 |
$rgx = $this->_validationJsFilesNeeded['regexPatternValidation']; |
| 241 |
$this->addScriptInLoadedScriptsList($patternFile); |
| 242 |
$this->addScriptInLoadedScriptsList($rgx); |
| 243 |
} |
| 244 |
|
| 245 |
$validationScriptFileMapping = ScriptFilePriorityManager::validationScriptFileMapping($fldData->typ); |
| 246 |
if ($validationScriptFileMapping) { |
| 247 |
foreach ($validationScriptFileMapping as $key => $value) { |
| 248 |
foreach ($value['paths'] as $path) { |
| 249 |
if (Helpers::property_exists_nested($fldData, $path)) { |
| 250 |
$file = $this->_validationJsFilesNeeded[$key]; |
| 251 |
$this->addScriptInLoadedScriptsList($file); |
| 252 |
} |
| 253 |
} |
| 254 |
if (isset($value['dependencies'])) { |
| 255 |
foreach ($value['dependencies'] as $dependency) { |
| 256 |
$dependencyFile = $this->_validationJsFilesNeeded[$dependency]; |
| 257 |
$this->addScriptInLoadedScriptsList($dependencyFile); |
| 258 |
} |
| 259 |
} |
| 260 |
} |
| 261 |
} |
| 262 |
} |
| 263 |
} |
| 264 |
} |
| 265 |
|
| 266 |
private function jsFieldsNeededFile() |
| 267 |
{ |
| 268 |
foreach ($this->_fields as $typ => $flds) { |
| 269 |
if (!array_key_exists($typ, $this->_jsFilesNeeded)) { |
| 270 |
continue; |
| 271 |
} |
| 272 |
$fldScriptArr = $this->_jsFilesNeeded[$typ]; |
| 273 |
|
| 274 |
foreach ($flds as $fld) { |
| 275 |
if ('advanced-file-up' === $typ) { |
| 276 |
$configs = $fld['field']->config; |
| 277 |
foreach ($configs as $configKey => $config) { |
| 278 |
if ($configs->$configKey) { |
| 279 |
$filepondPlugin = ScriptFilePriorityManager::filePondPlugins($configKey); |
| 280 |
if ($filepondPlugin) { |
| 281 |
$this->addScriptInLoadedScriptsList($filepondPlugin); |
| 282 |
} |
| 283 |
} |
| 284 |
} |
| 285 |
} |
| 286 |
foreach ($fldScriptArr as $scriptFile) { |
| 287 |
if (!isset($scriptFile['scriptTyp'])) { |
| 288 |
$this->addScriptInLoadedScriptsList($scriptFile); |
| 289 |
continue; |
| 290 |
} |
| 291 |
if ('custom' === $scriptFile['scriptTyp'] && Helpers::property_exists_nested($fld['field'], $scriptFile['path'], true)) { |
| 292 |
$scriptFile['field'] = $fld['field']; |
| 293 |
$scriptFile['fk'] = $fld['fk']; |
| 294 |
$scriptFile['contentId'] = $fld['contentId']; |
| 295 |
$this->addScriptInLoadedScriptsList($scriptFile); |
| 296 |
} |
| 297 |
} |
| 298 |
} |
| 299 |
} |
| 300 |
} |
| 301 |
|
| 302 |
private static function getCustomJsCodes($contentIds = []) |
| 303 |
{ |
| 304 |
$script = 'let bfContentId = "", bfVars= "";'; |
| 305 |
foreach ($contentIds as $contentId) { |
| 306 |
$jsCode = self::getCustomCodes(explode('_', $contentId)[1])['JavaScript']; |
| 307 |
if (!empty($jsCode)) { |
| 308 |
$script .= " if(bfSelect('#{$contentId}')){ bfContentId = '{$contentId}'; bfVars = window.bf_globals.{$contentId}.smartTags; {$jsCode}}"; |
| 309 |
} |
| 310 |
} |
| 311 |
|
| 312 |
return $script; |
| 313 |
} |
| 314 |
|
| 315 |
private static function getFileFromAssetsJs($fileName) |
| 316 |
{ |
| 317 |
$sourceJsFile = BITFORMS_PLUGIN_DIR_PATH . 'assets' . DIRECTORY_SEPARATOR . $fileName; |
| 318 |
if (file_exists($sourceJsFile)) { |
| 319 |
return file_get_contents($sourceJsFile); |
| 320 |
} |
| 321 |
Log::debug_log('file not found: ' . $fileName); |
| 322 |
return false; |
| 323 |
} |
| 324 |
|
| 325 |
public static function saveCssFile($formId, $atomicCssText) |
| 326 |
{ |
| 327 |
$path = 'form-styles'; |
| 328 |
$fileName = "bitform-$formId.css"; |
| 329 |
if (!isset($formId) || '' === $formId) { |
| 330 |
return new WP_Error('missing_form_id', __('Error Occurred, Please Reload', 'bit-form')); |
| 331 |
} |
| 332 |
return Helpers::saveFile($path, $fileName, $atomicCssText, 'w'); |
| 333 |
} |
| 334 |
|
| 335 |
public static function customCodeFile($formId, $customCodes) |
| 336 |
{ |
| 337 |
// for js file |
| 338 |
$path = 'form-scripts'; |
| 339 |
$fileName = "bitform-custom-$formId.js"; |
| 340 |
self::customCodeFileSaveOrDelete($customCodes->JavaScript, $path, $fileName); |
| 341 |
|
| 342 |
// for css file |
| 343 |
$path = 'form-styles'; |
| 344 |
$fileName = "bitform-custom-$formId.css"; |
| 345 |
self::customCodeFileSaveOrDelete($customCodes->CSS, $path, $fileName); |
| 346 |
|
| 347 |
return true; |
| 348 |
} |
| 349 |
|
| 350 |
public static function customCodeFileSaveOrDelete($script, $path, $fileName) |
| 351 |
{ |
| 352 |
if ($script) { |
| 353 |
Helpers::saveFile($path, $fileName, $script, 'w'); |
| 354 |
} else { |
| 355 |
$uploadPath = "$path/$fileName"; |
| 356 |
$uploadFilePath = Helpers::generatePathDirOrFile($uploadPath); |
| 357 |
if (file_exists($uploadFilePath)) { |
| 358 |
unlink($uploadFilePath); |
| 359 |
} |
| 360 |
} |
| 361 |
return true; |
| 362 |
} |
| 363 |
|
| 364 |
public static function getCustomCodes($formId) |
| 365 |
{ |
| 366 |
$customCodes = ['JavaScript' => '', 'CSS' => '']; |
| 367 |
$customJsPath = Helpers::generatePathDirOrFile("form-scripts/bitform-custom-$formId.js"); |
| 368 |
$customCodes['JavaScript'] = Helpers::fileRead($customJsPath); |
| 369 |
|
| 370 |
$customCSSPath = Helpers::generatePathDirOrFile("form-styles/bitform-custom-$formId.css"); |
| 371 |
$customCodes['CSS'] = Helpers::fileRead($customCSSPath); |
| 372 |
|
| 373 |
return $customCodes; |
| 374 |
} |
| 375 |
|
| 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 |
} |
| 404 |
} |
| 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]; |
| 413 |
} |
| 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) []; |
| 424 |
} |
| 425 |
} |
| 426 |
|
| 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); |
| 501 |
} |
| 502 |
}); |
| 503 |
if(contentData.gRecaptchaVersion === 'v3' && contentData.gRecaptchaSiteKey){ |
| 504 |
$recaptchaV3InitJs; |
| 505 |
} |
| 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); |
| 531 |
} |
| 532 |
} |
| 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 |
} |
| 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]; |
| 552 |
} |
| 553 |
return current[lastKey] || null; |
| 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; |
| 569 |
} |
| 570 |
|
| 571 |
private function addScriptInLoadedScriptsList($fileArr) |
| 572 |
{ |
| 573 |
$fileName = $fileArr['filename']; |
| 574 |
if (!in_array($fileName, $this->_scriptAddedFlags)) { |
| 575 |
$this->_loadedScriptsList[] = $fileArr; |
| 576 |
$this->_scriptAddedFlags[] = $fileName; |
| 577 |
} |
| 578 |
return true; |
| 579 |
} |
| 580 |
|
| 581 |
private function jsFrontendScript() |
| 582 |
{ |
| 583 |
foreach ($this->_formContents as $formContent) { |
| 584 |
if (Helpers::property_exists_nested($formContent, 'workFlowExist->oninput', true)) { |
| 585 |
$fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['conditionalLogic']; |
| 586 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 587 |
$fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['resetPlaceholders']; |
| 588 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 589 |
$fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['validateFocusLost']; |
| 590 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 591 |
$fileArr = ScriptFilePriorityManager::frontendScriptFile()['observeElm']; |
| 592 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 593 |
} |
| 594 |
if (Helpers::property_exists_nested($formContent, 'additional->enabled->validateFocusLost', true)) { |
| 595 |
$fileArr = ScriptFilePriorityManager::validationAndOtherScriptFile()['validateFocusLost']; |
| 596 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 597 |
} |
| 598 |
} |
| 599 |
} |
| 600 |
|
| 601 |
private function jsHiddenFieldScript() |
| 602 |
{ |
| 603 |
$appConfig = get_option('bitform_app_config'); |
| 604 |
if (Helpers::property_exists_nested($appConfig, 'cache_plugin', true)) { |
| 605 |
$fileArr = ScriptFilePriorityManager::frontendScriptFile()['hidden-token-field']; |
| 606 |
$this->addScriptInLoadedScriptsList($fileArr); |
| 607 |
return; |
| 608 |
} |
| 609 |
} |
| 610 |
|
| 611 |
public function dd($data, $exit = false) |
| 612 |
{ |
| 613 |
echo '+++++++++++++'; |
| 614 |
echo '<pre>'; |
| 615 |
var_dump($data); |
| 616 |
echo '</pre>'; |
| 617 |
echo '+++++++++++++'; |
| 618 |
$exit ? exit : ''; |
| 619 |
} |
| 620 |
} |
| 621 |
|