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

467 lines 16.2 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\RecaptchaV3;
6 use BitCode\BitForm\Core\Form\FormManager;
7 use BitCode\BitForm\Core\Integration\IntegrationHandler;
8 use BitCode\BitForm\Core\Util\Log;
9 use WP_Error;
10
11 class FrontEndScriptGenerator {
12 private $_scriptAddedFlags;
13 private $_fields;
14 private $_formContents;
15 private $_jsFilesNeeded;
16 private $_loadedScriptsList;
17 private $_validationJsFilesNeeded;
18
19 public function __construct() {
20 $this->_scriptAddedFlags = [];
21 $this->_fields = [];
22 $this->_jsFilesNeeded = [];
23 $this->_loadedScriptsList = [];
24 $this->_validationJsFilesNeeded = ScriptFilePriorityManager::validationScriptFile();
25 }
26
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);
31 return <<<GLOBALOBJ
32 if(!window.bf_globals){ window.bf_globals = {};}
33 $contentidArray.forEach(function(contentId){
34 if(!window.bf_globals[contentId]){
35 window.bf_globals[contentId] = {inits: {}, contentId: contentId};
36 }else{
37 window.bf_globals[contentId].inits = {};
38 window.bf_globals[contentId].contentId = contentId;
39 }
40 });
41 GLOBALOBJ;
42 }
43
44 private static function isValidationNeeded($fldData) {
45 $validationsToCheck = ['valid->req', 'valid->regexr', 'mn', 'mx', 'opt', 'err->invalid->show'];
46 foreach ($validationsToCheck as $property) {
47 $needValidation = Helpers::property_exists_nested($fldData, $property);
48 if ($needValidation) {
49 return true;
50 }
51 }
52 return false;
53 }
54
55 public function generateJsFile($formContents, $fields, $contentIds, $postId, $formIDs = null, $preview = false) {
56 add_option('bitforms_frontend_js_generating', true);
57 $this->_formContents = $formContents;
58 $this->_fields = $fields;
59
60 $this->appendJs(self::generateBfGlobalObjJS($contentIds), $postId, $preview, 'w');
61 $this->_jsFilesNeeded = ScriptFilePriorityManager::jsFile();
62
63 // Recaptcha v3 script is loaded separately
64 $this->appendJs($this->getRecaptchaV3Script($formIDs), $postId, $preview);
65
66 // helper js files for whole form
67 foreach ($this->_jsFilesNeeded['helperScript'] as $jsFile) {
68 $this->addScriptInLoadedScriptsList($jsFile);
69 }
70
71 // for add validation js files
72 $this->jsValidationNeededFile();
73
74 // js files for all fields
75 $this->jsFieldsNeededFile();
76
77 // for frontend helper js files
78 $this->jsFrontendScript();
79
80 // for hidden Field when catch plugin on
81 $this->jsHiddenFieldScript();
82
83 //⚠👆 every script file generate method call before this method
84 $this->appendJs($this->getScript(), $postId, $preview);
85
86 // for js file minification
87 $this->appendJs(self::getCustomJsCodes($contentIds), $postId, $preview);
88 delete_option('bitforms_frontend_js_generating');
89 return true;
90 }
91
92 /*
93 public function generateJsFile($formContents, $fields, $contentIds, $postId, $formIDs = null, $preview = false) {
94 $this->_formContents = $formContents;
95 $this->_fields = $fields;
96
97 $script = '';
98 $script .= self::generateBfGlobalObjJS($contentIds);
99 $this->_jsFilesNeeded = ScriptFilePriorityManager::jsFile();
100
101 // Recaptcha v3 script is loaded separately
102 $script .= $this->getRecaptchaV3Script($formIDs);
103
104 // custom js files for whole form
105 foreach ($this->_jsFilesNeeded['helperScript'] as $jsFile) {
106 $this->addScriptInLoadedScriptsList($jsFile);
107 }
108
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
130 $fileName = '';
131 $path = '';
132 if ($preview) {
133 $fileName = "preview-{$postId}.js";
134 $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) {
147 $fileName = "preview-{$postId}.js";
148 $path = 'form-scripts';
149 } else {
150 $fileName = "bitform-js-$postId.js";
151 $path = "form-scripts/{$postId}";
152 }
153 Helpers::saveFile($path, $fileName, Helpers::minifyJS($script), $mode);
154 }
155
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() {
173 usort($this->_loadedScriptsList, function ($a, $b) {
174 return $a['priority'] - $b['priority'];
175 });
176
177 $script = '';
178 foreach ($this->_loadedScriptsList as $scriptFileArr) {
179 $fileNam = $scriptFileArr['filename'];
180 if (!isset($scriptFileArr['scriptTyp']) || 'script' === $scriptFileArr['scriptTyp']) {
181 if (self::getFileFromAssetsJs($fileNam)) {
182 $script .= self::getFileFromAssetsJs($fileNam);
183 continue;
184 }
185 continue;
186 }
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 if ('custom' === $scriptFileArr['scriptTyp']) {
197 $fileInstance = $scriptFileArr['source'] . $fileNam;
198 if (!class_exists($fileInstance)) {
199 continue;
200 } // when class not found, skip load script
201 $script .= $fileInstance::init($scriptFileArr['fk'], $scriptFileArr['field'], $scriptFileArr['contentId']);
202 }
203 }
204 return $script;
205 }
206
207 private function jsValidationNeededFile() {
208 foreach ($this->_fields as $flds) {
209 foreach ($flds as $fld) {
210 $fldData = $fld['field'];
211 // for validation js files
212 if (self::isValidationNeeded($fldData)) {
213 $validation = $this->_validationJsFilesNeeded['validation'];
214 $this->addScriptInLoadedScriptsList($validation);
215 }
216 // for required
217 if (Helpers::property_exists_nested($fldData, 'valid->req')) {
218 $fileArr = $this->_validationJsFilesNeeded['requiredFldValidation'];
219 $this->addScriptInLoadedScriptsList($fileArr);
220 }
221 // for regex
222 if (Helpers::property_exists_nested($fldData, 'valid->regexr')) {
223 $patternFile = $this->_validationJsFilesNeeded['generateBackslashPattern'];
224 $rgx = $this->_validationJsFilesNeeded['regexPatternValidation'];
225 $this->addScriptInLoadedScriptsList($patternFile);
226 $this->addScriptInLoadedScriptsList($rgx);
227 }
228
229 $validationScriptFileMapping = ScriptFilePriorityManager::validationScriptFileMapping($fldData->typ);
230 if ($validationScriptFileMapping) {
231 foreach ($validationScriptFileMapping as $key => $value) {
232 foreach ($value['paths'] as $path) {
233 if (Helpers::property_exists_nested($fldData, $path)) {
234 $file = $this->_validationJsFilesNeeded[$key];
235 $this->addScriptInLoadedScriptsList($file);
236 }
237 }
238 if (isset($value['dependencies'])) {
239 foreach ($value['dependencies'] as $dependency) {
240 $dependencyFile = $this->_validationJsFilesNeeded[$dependency];
241 $this->addScriptInLoadedScriptsList($dependencyFile);
242 }
243 }
244 }
245 }
246 }
247 }
248 }
249
250 private function jsFieldsNeededFile() {
251 foreach ($this->_fields as $typ => $flds) {
252 if (!array_key_exists($typ, $this->_jsFilesNeeded)) {
253 continue;
254 }
255 $fldScriptArr = $this->_jsFilesNeeded[$typ];
256
257 foreach ($flds as $fld) {
258 if ('advanced-file-up' === $typ) {
259 $configs = $fld['field']->config;
260 foreach ($configs as $configKey => $config) {
261 if ($configs->$configKey) {
262 $filepondPlugin = ScriptFilePriorityManager::filePondPlugins($configKey);
263 if ($filepondPlugin) {
264 $this->addScriptInLoadedScriptsList($filepondPlugin);
265 }
266 }
267 }
268 }
269 foreach ($fldScriptArr as $scriptFile) {
270 if (!isset($scriptFile['scriptTyp'])) {
271 $this->addScriptInLoadedScriptsList($scriptFile);
272 continue;
273 }
274 if ('init' === $scriptFile['scriptTyp']) {
275 $scriptFile['field'] = $fld['field'];
276 $scriptFile['fk'] = $fld['fk'];
277 $scriptFile['formID'] = $fld['formID'];
278 $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 $this->addScriptInLoadedScriptsList($scriptFile);
288 }
289 }
290 }
291 }
292 }
293
294 private static function getCustomJsCodes($contentIds = []) {
295 $script = 'let bfContentId = "", bfVars= "";';
296 foreach ($contentIds as $contentId) {
297 $jsCode = self::getCustomCodes(explode('_', $contentId)[1])['JavaScript'];
298 if (!empty($jsCode)) {
299 $script .= " bfContentId = '{$contentId}'; bfVars = window.bf_globals.{$contentId}.smartTags; {$jsCode}";
300 }
301 }
302
303 return $script;
304 }
305
306 private static function getFileFromAssetsJs($fileName) {
307 $sourceJsFile = BITFORMS_PLUGIN_DIR_PATH . 'assets' . DIRECTORY_SEPARATOR . $fileName;
308 if (file_exists($sourceJsFile)) {
309 return file_get_contents($sourceJsFile);
310 }
311 Log::debug_log('file not found: ' . $fileName);
312 return false;
313 }
314
315 public static function saveCssFile($formId, $atomicCssText) {
316 $path = 'form-styles';
317 $fileName = "bitform-$formId.css";
318 if (!isset($formId) || '' === $formId) {
319 return new WP_Error('missing_form_id', __('Error Occurred, Please Reload', 'bit-form'));
320 }
321 return Helpers::saveFile($path, $fileName, $atomicCssText, 'w');
322 }
323
324 public static function customCodeFile($formId, $customCodes) {
325 // for js file
326 $path = 'form-scripts';
327 $fileName = "bitform-custom-$formId.js";
328 self::customCodeFileSaveOrDelete($customCodes->JavaScript, $path, $fileName);
329
330 // for css file
331 $path = 'form-styles';
332 $fileName = "bitform-custom-$formId.css";
333 self::customCodeFileSaveOrDelete($customCodes->CSS, $path, $fileName);
334
335 return true;
336 }
337
338 private static function customCodeFileSaveOrDelete($script, $path, $fileName) {
339 if ($script) {
340 Helpers::saveFile($path, $fileName, $script, 'w');
341 } else {
342 $uploadPath = "$path/$fileName";
343 $uploadFilePath = Helpers::generatePathDirOrFile($uploadPath);
344 if (file_exists($uploadFilePath)) {
345 unlink($uploadFilePath);
346 }
347 }
348 return true;
349 }
350
351 public static function getCustomCodes($formId) {
352 $customCodes = ['JavaScript' => '', 'CSS' => ''];
353 $customJsPath = Helpers::generatePathDirOrFile("form-scripts/bitform-custom-$formId.js");
354 $customCodes['JavaScript'] = Helpers::fileRead($customJsPath);
355
356 $customCSSPath = Helpers::generatePathDirOrFile("form-styles/bitform-custom-$formId.css");
357 $customCodes['CSS'] = Helpers::fileRead($customCSSPath);
358
359 return $customCodes;
360 }
361
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;
369 }
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']];
375 }
376 if (empty($value) && isset($fldPath['path'])) {
377 $value = Helpers::getDataFromNestedPath($field, $fldPath['path']);
378 }
379 if (empty($value) && isset($fldPath['val'])) {
380 $value = $fldPath['val'];
381 }
382 $fldConf = Helpers::setDataToNestedPath($fldConf, $confPath, $value);
383 }
384 return $fldConf;
385 }
386
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 }
398 }
399 }
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 }
408 }
409 } else {
410 // for all field types
411 $this->addScriptInLoadedScriptsList($scriptFile);
412 }
413 }
414
415 if (isset($funcArr['dependencies'])) {
416 foreach ($funcArr['dependencies'] as $dependency) {
417 $this->addScriptInLoadedScriptsList($dependency);
418 }
419 }
420 }
421 }
422
423 private function addScriptInLoadedScriptsList($fileArr) {
424 $fileName = $fileArr['filename'];
425 if (!in_array($fileName, $this->_scriptAddedFlags)) {
426 $this->_loadedScriptsList[] = $fileArr;
427 $this->_scriptAddedFlags[] = $fileName;
428 }
429 return true;
430 }
431
432 private function jsFrontendScript() {
433 foreach ($this->_formContents as $formContent) {
434 if (Helpers::property_exists_nested($formContent, 'workFlowExist->oninput', true)) {
435 $fileArr = ScriptFilePriorityManager::validationScriptFile()['conditionalLogic'];
436 $this->addScriptInLoadedScriptsList($fileArr);
437 $fileArr = ScriptFilePriorityManager::validationScriptFile()['validateFocusLost'];
438 $this->addScriptInLoadedScriptsList($fileArr);
439 $fileArr = ScriptFilePriorityManager::frontendScriptFile()['observeElm'];
440 $this->addScriptInLoadedScriptsList($fileArr);
441 }
442 if (Helpers::property_exists_nested($formContent, 'additional->enabled->validateFocusLost', true)) {
443 $fileArr = ScriptFilePriorityManager::validationScriptFile()['validateFocusLost'];
444 $this->addScriptInLoadedScriptsList($fileArr);
445 }
446 }
447 }
448
449 private function jsHiddenFieldScript() {
450 $appConfig = get_option('bitform_app_config');
451 if (Helpers::property_exists_nested($appConfig, 'cache_plugin', true)) {
452 $fileArr = ScriptFilePriorityManager::frontendScriptFile()['hidden-token-field'];
453 $this->addScriptInLoadedScriptsList($fileArr);
454 return;
455 }
456 }
457
458 public function dd($data, $exit = false) {
459 echo '+++++++++++++';
460 echo '<pre>';
461 var_dump($data);
462 echo '</pre>';
463 echo '+++++++++++++';
464 $exit ? exit : '';
465 }
466 }
467