PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.9.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.9.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 2.10.1 2.10.2 All 137 releases
bit-form / v1 / includes / Plugin.php

Plugin.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 2.9.1, at v1/includes/Plugin.php

707 lines 25.3 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;
4
5 /**
6 * Main class for the plugin.
7 *
8 * @since 1.0.0-alpha
9 */
10
11 use BitCode\BitForm\Admin\Admin_Bar;
12 use BitCode\BitForm\Admin\Form\AdminFormHandler;
13 use BitCode\BitForm\Core\Ajax\AjaxService;
14 use BitCode\BitForm\Core\Capability\Request;
15 use BitCode\BitForm\Core\Database\DB;
16 use BitCode\BitForm\Core\Database\FormModel;
17 use BitCode\BitForm\Core\Database\ReportsModel;
18 use BitCode\BitForm\Core\Fallback\FormEntryMetaChange;
19 use BitCode\BitForm\Core\Form\FormHandler;
20 use BitCode\BitForm\Core\Integration\Integrations;
21 use BitCode\BitForm\Core\Util\Activation;
22 use BitCode\BitForm\Core\Util\Deactivation;
23 use BitCode\BitForm\Core\Util\FileDownloadProvider;
24 use BitCode\BitForm\Core\Util\GutenBlockProvider;
25 use BitCode\BitForm\Core\Util\IpTool;
26 use BitCode\BitForm\Core\Util\Uninstallation;
27
28 final class Plugin {
29
30 /**
31 * Main instance of the plugin.
32 *
33 * @since 1.0.0-alpha
34 * @var Plugin|null
35 */
36 private static $instance = null;
37
38 /**
39 * Registers the plugin with WordPress.
40 *
41 * @since 1.0.0-alpha
42 */
43 public function register() {
44 add_action('plugins_loaded', array($this, 'init_plugin'));
45 (new Activation())->activate();
46 (new Deactivation())->register();
47 (new Uninstallation())->register();
48 }
49
50 /**
51 * Initialize the hooks
52 *
53 * @return void
54 */
55 public function init_hooks() {
56 add_action('init', array($this, 'registerBitformsPostType'));
57 add_action('init', array($this, 'registerCustomPostType'));
58 add_action("bitforms_exec_integrations", array(Integrations::class, 'integrationExecutionHelper'), 1, 5);
59 // Localize our plugin
60 add_action('init', array($this, 'localization_setup'));
61
62 // initialize the classes
63 add_action('init', array($this, 'init_classes'));
64
65 add_action('init', array($this, 'versionUpdateFallbacks'));
66
67 add_filter('plugin_action_links_' . plugin_basename(BITFORMS_PLUGIN_MAIN_FILE), array($this, 'plugin_action_links'));
68 }
69
70 public function versionUpdateFallbacks() {
71 $installed = get_option('bitforms_installed');
72 $oldversion = null;
73 if ($installed) {
74 $oldversion = get_option('bitforms_version');
75 }
76 if ($oldversion && version_compare($oldversion, BITFORMS_VERSION, '!=')) {
77 update_option('bitforms_version', BITFORMS_VERSION);
78 if (version_compare('1.0.4', $oldversion, '>=')) {
79 // if version is lower or equal than 1.0.4
80 $formEntryMetaChange = new FormEntryMetaChange();
81 $formEntryMetaChange->changeMeta();
82 }
83
84 if (version_compare('1.4.1', $oldversion, '>=')) {
85 // if version is lower or equal than 1.4.1
86 $this->addButtonToFieds();
87 }
88
89 if (version_compare('1.4.7', $oldversion, '>=')) {
90 // if version is equal or lower than 1.4.7
91 $this->validationErrMsgFallback();
92 }
93
94 if (version_compare('1.4.11', $oldversion, '>=')) {
95 // if version is equal or lower than 1.4.11
96 $this->buttonValidsObjectFallback();
97 }
98
99 if (version_compare('1.4.12.2', $oldversion, '>=')) {
100 // if version is equal or lower than 1.4.12.2
101 $this->validationEmailFallback();
102 }
103 if (version_compare('1.5.2', $oldversion, '>=')) {
104 $this->reportFallback();
105 }
106 if (version_compare('1.7.2', $oldversion, '>=')) {
107 $this->optionFallBack();
108 }
109 }
110 }
111
112 public function reportFallback() {
113
114 $reportMdl = new ReportsModel();
115 global $wpdb;
116 $tablename = $wpdb->prefix . "bitforms_reports";
117
118 $latestIds = $wpdb->get_results("SELECT MAX(`id`) as latest_id FROM $tablename GROUP BY `context`");
119
120 $notDeletedIds = array_column($latestIds, 'latest_id');
121
122 if (!is_wp_error($latestIds) && count($notDeletedIds) > 0) {
123 $reportMdl->bulkDelete(['id' => $notDeletedIds], 'NOT IN');
124 }
125
126 $ipTool = new IpTool();
127 $user_details = $ipTool->getUserDetail();
128
129 $formModel = new FormModel();
130
131 $forms = $formModel->get(
132 ['id']
133 );
134
135 $details = [
136 'report_name' => 'All Entries',
137 'hiddenColumns' => [],
138 'pageSize' => 10,
139 'sortBy' => [],
140 'filters' => [],
141 'globalFilter' => "",
142 'order' => [],
143 ];
144
145 foreach ($forms as $form) {
146 $existReportId = $reportMdl->get(
147 [
148 "id",
149 ],
150 [
151 "context" => $form->id,
152 ]
153 );
154 if (is_wp_error($existReportId)) {
155 $defaultReport = [
156 "type" => 'table',
157 "category" => 'form',
158 "context" => $form->id,
159 "details" => wp_json_encode($details),
160 "isDefault" => (bool) 1,
161 "user_id" => $user_details['id'],
162 "user_ip" => $user_details['ip'],
163 "user_device" => $user_details['device'],
164 "created_at" => $user_details['time'],
165 "updated_at" => $user_details['time'],
166 ];
167
168 $reportMdl->insert($defaultReport);
169
170 }
171
172 }
173
174 }
175
176 public function validationErrMsgFallback() {
177 $formModel = new FormModel();
178 $forms = $formModel->get(
179 ['id', 'form_content']
180 );
181
182 if (isset($forms) && !is_wp_error($forms)) {
183 foreach ($forms as $form) {
184 $formID = $form->id;
185 $formContent = json_decode($form->form_content);
186 $fields = $formContent->fields;
187
188 foreach ($fields as $fldKey => $fldData) {
189 if (isset($fldData->valid->req)) {
190 if (!isset($fldData->err)) {
191 $fldData->err = (object) [];
192 }
193 $fldData->err->req = (object) [
194 'show' => true,
195 'dflt' => 'This field is required',
196 ];
197 }
198
199 if ($fldData->typ === 'check') {
200 $reqOpts = array_map(function ($op) {
201 return $op->lbl;
202 }, array_filter($fldData->opt, function ($ot) {
203 return isset($ot->req);
204 }));
205 if (!empty($reqOpts)) {
206 if (!isset($fldData->err)) {
207 $fldData->err = (object) [];
208 }
209 $fldData->err->req = (object) [
210 'show' => true,
211 'dflt' => implode(', ', $reqOpts) . ' is required',
212 ];
213 }
214 }
215
216 if ($fldData->typ === 'number') {
217 if (!isset($fldData->err)) {
218 $fldData->err = (object) [];
219 }
220 $fldData->err->invalid = (object) [
221 'show' => true,
222 'dflt' => 'Number is invalid',
223 ];
224
225 if (isset($fldData->mn)) {
226 $fldData->err->mn = (object) [
227 'show' => true,
228 'dflt' => 'Minimum number is ' . $fldData->mn,
229 ];
230 }
231
232 if (isset($fldData->mx)) {
233 $fldData->err->mx = (object) [
234 'show' => true,
235 'dflt' => 'Maximum number is ' . $fldData->mx,
236 ];
237 }
238 }
239
240 if ($fldData->typ === 'email') {
241 $fldData->pattern = '^$_bf_$w+([.-]?$_bf_$w+)*@$_bf_$w+([.-]?$_bf_$w+)*($_bf_$.$_bf_$w{2,3})+$';
242 if (!isset($fldData->err)) {
243 $fldData->err = (object) [];
244 }
245 $fldData->err->invalid = (object) [
246 'show' => true,
247 'dflt' => 'Email is invalid',
248 ];
249 }
250
251 if ($fldData->typ === 'url') {
252 $fldData->attr->pattern = '^(?:(?:https?|ftp):$_bf_$/$_bf_$/)?(?:(?!(?:10|127)(?:$_bf_$.$_bf_$d{1,3}){3})(?!(?:169$_bf_$.254|192$_bf_$.168)(?:$_bf_$.$_bf_$d{1,3}){2})(?!172$_bf_$.(?:1[6-9]|2$_bf_$d|3[0-1])(?:$_bf_$.$_bf_$d{1,3}){2})(?:[1-9]$_bf_$d?|1$_bf_$d$_bf_$d|2[01]$_bf_$d|22[0-3])(?:$_bf_$.(?:1?$_bf_$d{1,2}|2[0-4]$_bf_$d|25[0-5])){2}(?:$_bf_$.(?:[1-9]$_bf_$d?|1$_bf_$d$_bf_$d|2[0-4]$_bf_$d|25[0-4]))|(?:(?:[a-z$_bf_$u00a1-$_bf_$uffff0-9]-*)*[a-z$_bf_$u00a1-$_bf_$uffff0-9]+)(?:$_bf_$.(?:[a-z$_bf_$u00a1-$_bf_$uffff0-9]-*)*[a-z$_bf_$u00a1-$_bf_$uffff0-9]+)*(?:$_bf_$.(?:[a-z$_bf_$u00a1-$_bf_$uffff]{2,})))(?::$_bf_$d{2,5})?(?:$_bf_$/$_bf_$S*)?$';
253 if (!isset($fldData->err)) {
254 $fldData->err = (object) [];
255 }
256 $fldData->err->invalid = [
257 'show' => true,
258 'dflt' => 'URL is invalid',
259 ];
260 }
261 $fields->{$fldKey} = $fldData;
262 }
263
264 $formContent->fields = $fields;
265
266 $formModel->update(
267 array(
268 "form_content" => wp_json_encode($formContent),
269 ),
270 array(
271 "id" => $formID,
272 )
273 );
274 }
275 }
276 }
277
278 public function validationEmailFallback() {
279 $formModel = new FormModel();
280 $forms = $formModel->get(
281 ['id', 'form_content']
282 );
283
284 if (!is_wp_error($forms)) {
285 foreach ($forms as $form) {
286 $formID = $form->id;
287 $formContent = json_decode($form->form_content);
288 $fields = $formContent->fields;
289
290 foreach ($fields as $fldKey => $fldData) {
291 if ($fldData->typ === 'email') {
292 $fldData->pattern = '^$_bf_$w+([.-]?$_bf_$w+)*@$_bf_$w+([.-]?$_bf_$w+)*($_bf_$.$_bf_$w{1,24})+$';
293 }
294 $fields->{$fldKey} = $fldData;
295 }
296
297 $formContent->fields = $fields;
298
299 $formModel->update(
300 array(
301 "form_content" => wp_json_encode($formContent),
302 ),
303 array(
304 "id" => $formID,
305 )
306 );
307 }
308 }
309 }
310
311 public function buttonValidsObjectFallback() {
312 $formModel = new FormModel();
313 $forms = $formModel->get(
314 ['id', 'form_content']
315 );
316
317 if (!is_wp_error($forms)) {
318 foreach ($forms as $form) {
319 $formID = $form->id;
320 $formContent = json_decode($form->form_content);
321 $fields = $formContent->fields;
322
323 foreach ($fields as $fldKey => $fldData) {
324 if ($fldData->typ === 'button' && !isset($fldData->valid)) {
325 $fldData->valid = (object) [];
326 }
327 $fields->{$fldKey} = $fldData;
328 }
329
330 $formContent->fields = $fields;
331
332 $formModel->update(
333 array(
334 "form_content" => wp_json_encode($formContent),
335 ),
336 array(
337 "id" => $formID,
338 )
339 );
340 }
341 }
342 }
343
344 private function commaReplace($options, $lbl, $val)
345 {
346 foreach ($options as $key => $option) {
347 if (!empty($option[$lbl]) && !empty($option[$val])) {
348 $options[$key][$val] = str_replace(',', '_', $option[$val]);
349 }
350 if (!empty($option[$lbl]) && empty($option[$val])) {
351 $options[$key][$val] = str_replace(',', '_', $option[$lbl]);
352 }
353 }
354 return $options;
355 }
356
357 private function replaceOptionSeparator($formContent)
358 {
359 $updated = false;
360 foreach ($formContent['fields'] as $key => $field) {
361 if ($field['typ'] === 'check') {
362 $formContent['fields'][$key]['opt'] = $this->commaReplace($field['opt'], 'lbl', 'val');
363 $updated = true;
364 }
365 if ($field['typ'] === 'select') {
366 $formContent['fields'][$key]['opt'] = $this->commaReplace($field['opt'], 'label', 'value');
367 $updated = true;
368 }
369 }
370 return [$formContent, $updated];
371 }
372
373 public function optionFallBack()
374 {
375 $formModel = new FormModel();
376 $forms = $formModel->get(
377 ['id', 'form_content']
378 );
379
380 foreach ($forms as $form) {
381 $formContent = json_decode($form->form_content, true);
382 $optReplaceComma = $this->replaceOptionSeparator($formContent);
383 if ($optReplaceComma[1]) {
384 $formModel->update(
385 [
386 'form_content' => wp_json_encode($optReplaceComma[0]),
387 ],
388 [
389 'id' => $form->id,
390 ]
391 );
392 }
393 }
394 }
395
396
397 /**
398 * Updates bit form content tables on wp db
399 *
400 * @return void
401 */
402 public function update_tables() {
403 if (!current_user_can('manage_options')) {
404 return;
405 }
406
407 global $bitforms_db_version;
408 $installed_db_version = get_site_option("bitforms_db_version");
409 if ($installed_db_version != $bitforms_db_version) {
410 DB::migrate();
411 }
412 }
413
414 /**
415 * Register post type for bitforms
416 *
417 * @return void
418 */
419 public function registerBitformsPostType() {
420 $args = array(
421 'label' => __('Bitform Pages', 'bit-form'),
422 'public' => true,
423 'show_ui' => true,
424 'show_in_menu' => false,
425 'capability_type' => 'page',
426 'hierarchical' => false,
427 'query_var' => false,
428 'supports' => array('title'),
429 'show_in_rest' => false,
430 );
431 register_post_type('bitforms', $args);
432 }
433
434 public function registerCustomPostType() {
435 flush_rewrite_rules(false);
436 $cpts = get_option('bitform_custom_post_types');
437 if (!empty($cpts)) {
438 foreach ($cpts as $cpt) {
439 $labels = array(
440 'name' => _x($cpt->name, 'Post type general name', 'bit-form'),
441 'singular_name' => _x($cpt->singular_label, 'Post type singular name', 'bit-form'),
442 'menu_name' => _x($cpt->menu_name, 'Admin Menu text', 'bit-form'),
443 );
444 $args = array(
445 'labels' => $labels,
446 'public' => $cpt->public == 1 ? true : false,
447 'publicly_queryable' => $cpt->public_queryable == 1 ? true : false,
448 'show_ui' => $cpt->show_ui == 1 ? true : false,
449 'show_in_menu' => $cpt->show_in_menu == 1 ? true : false,
450 'query_var' => true,
451 'rewrite' => array('slug' => $cpt->name),
452 'capability_type' => 'post',
453 'has_archive' => true,
454 'hierarchical' => false,
455 'show_in_rest' => isset($cpt->show_in_rest) == 1 ? true : false,
456 'menu_icon' => $cpt->menu_icon,
457 'supports' => array('title', 'editor', 'author', 'excerpt', 'comments'),
458 );
459 register_post_type($cpt->name, $args);
460 }
461 }
462 }
463
464 /**
465 * Initialize plugin for localization
466 *
467 * @uses load_plugin_textdomain()
468 */
469 public function localization_setup() {
470 load_plugin_textdomain('bitform', false, dirname(BITFORMS_PLUGIN_BASENAME) . '/languages');
471 }
472
473 /**
474 * Instantiate the required classes
475 *
476 * @return void
477 */
478 public function init_classes() {
479 if (Request::Check('admin')) {
480 (new Admin_Bar())->register();
481 }
482 if (Request::Check('ajax')) {
483 new AjaxService();
484 }
485 if (Request::Check('frontend')) {
486 $formHandler = new FormHandler();
487 $formHandler->frontend;
488 }
489 if (Request::isPluginPage()) {
490 (new FileDownloadProvider())->register();
491 }
492 if (current_user_can('edit_posts')) {
493 (new GutenBlockProvider())->register();
494 }
495 }
496
497 /**
498 * Plugin action links
499 *
500 * @param array $links
501 *
502 * @return array
503 */
504 public function plugin_action_links($links) {
505 $links[] = '<a href="https://docs.form.bitapps.pro" target="_blank">' . __('Docs', 'bit-form') . '</a>';
506
507 return $links;
508 }
509
510 public function init_plugin() {
511 $this->init_hooks();
512 $this->update_tables();
513 do_action('bitform_loaded');
514 }
515
516 /**
517 * Retrieves the main instance of the plugin.
518 *
519 * @since 1.0.0-alpha
520 *
521 * @return BITFORM Plugin main instance.
522 */
523 public static function instance() {
524 return static::$instance;
525 }
526
527 /**
528 * Loads the plugin main instance and initializes it.
529 *
530 * @param string $main_file Absolute path to the plugin main file.
531 *
532 * @return bool True if the plugin main instance could be loaded, false otherwise.
533 */
534 public static function load($main_file) {
535 if (null !== static::$instance) {
536 return false;
537 }
538
539 static::$instance = new static($main_file);
540 static::$instance->register();
541 return true;
542 }
543
544 public function addButtonToFieds() {
545 // if version is lower or equal than 1.3.13
546 $formModel = new FormModel();
547 $forms = $formModel->get(
548 ['id', 'form_content'],
549 [
550 'form_content' => ['operator' => 'LIKE', 'value' => '%\"buttons\":%'],
551 ]
552 );
553 if (!is_wp_error($forms)) {
554 $adminFormHandler = new AdminFormHandler();
555 foreach ($forms as $form) {
556 $formID = $form->id;
557 $formContent = json_decode($form->form_content);
558 $fields = json_encode($formContent->fields);
559 if (isset($formContent->buttons)) {
560 if (strpos($fields, '"btnTyp":"submit"') === false) {
561 $align = isset($formContent->buttons->align) ? $formContent->buttons->align : 'right';
562 $btnSiz = isset($formContent->buttons->btnSiz) ? $formContent->buttons->btnSiz : 'md';
563 $fulW = isset($formContent->buttons->fulW) ? $formContent->buttons->fulW : false;
564 $btnData = [
565 'typ' => 'button',
566 'btnSiz' => $btnSiz,
567 'fulW' => $fulW,
568 ];
569 $newID = 0;
570 foreach ($formContent->fields as $key => $value) {
571 $oldID = \preg_replace('/bf?\d+-(\d+)-?/', "$1", $key);
572 if ($oldID > $newID) {
573 $newID = $oldID;
574 }
575 }
576 $newID = $newID + 1;
577 $sBtnID = "bf${formID}-${newID}";
578 $lY = 0;
579 $mY = 0;
580 $sY = 0;
581 foreach ($formContent->layout->lg as $lg) {
582 if ($lg->y > $lY) {
583 $lY = $lg->y;
584 }
585 }
586 $lY = $lY + $lg->h + 1;
587 foreach ($formContent->layout->md as $md) {
588 if ($md->y > $mY) {
589 $mY = $md->y;
590 }
591 }
592 $mY = $mY + $md->h + 1;
593 foreach ($formContent->layout->sm as $sm) {
594 if ($sm->y > $sY) {
595 $sY = $sm->y;
596 }
597 }
598 $sY = $sY + $sm->h + 1;
599 if (isset($formContent->buttons->rstBtnTxt)) {
600 $newID += 1;
601 $rBtnID = "bf${formID}-${newID}";
602
603 if ($fulW) {
604 $btnData['btnTyp'] = 'submit';
605 $btnData['align'] = $align;
606 $btnData['txt'] = $formContent->buttons->subBtnTxt;
607 $formContent->fields->{$sBtnID} = (object) $btnData;
608 $rBtnData = $btnData;
609 $rBtnData['btnTyp'] = 'reset';
610 $rBtnData['align'] = $align;
611 $rBtnData['txt'] = $formContent->buttons->rstBtnTxt;
612 $formContent->fields->{$rBtnID} = (object) $rBtnData;
613 } else {
614 $btnData['btnTyp'] = 'submit';
615 $btnData['align'] = 'right';
616 $btnData['txt'] = $formContent->buttons->subBtnTxt;
617 $formContent->fields->{$sBtnID} = (object) $btnData;
618 $rBtnData = $btnData;
619 $rBtnData['btnTyp'] = 'reset';
620 $rBtnData['align'] = 'left';
621 $rBtnData['txt'] = $formContent->buttons->rstBtnTxt;
622 $formContent->fields->{$rBtnID} = (object) $rBtnData;
623 }
624 $subBtnLay = [
625 "h" => 2,
626 "i" => $sBtnID,
627 "minH" => 2,
628 "x" => 0,
629 "y" => 1000,
630 ];
631
632 $subBtnLay["w"] = 3;
633 $subBtnLay["y"] = $lY;
634
635 $formContent->layout->lg[] = (object) $subBtnLay;
636
637 $subBtnLay["w"] = 2;
638 $subBtnLay["y"] = $mY;
639
640 $formContent->layout->md[] = (object) $subBtnLay;
641
642 $subBtnLay["w"] = 1;
643 $subBtnLay["y"] = $sY;
644
645 $formContent->layout->sm[] = (object) $subBtnLay;
646
647 $subBtnLay["i"] = $rBtnID;
648 $subBtnLay["x"] = 3;
649 $subBtnLay["w"] = 3;
650 $subBtnLay["y"] = $lY;
651
652 $formContent->layout->lg[] = (object) $subBtnLay;
653
654 $subBtnLay["x"] = 2;
655 $subBtnLay["w"] = 2;
656 $subBtnLay["y"] = $mY;
657
658 $formContent->layout->md[] = (object) $subBtnLay;
659
660 $subBtnLay["w"] = 1;
661 $subBtnLay["x"] = 1;
662 $subBtnLay["y"] = $sY;
663
664 $formContent->layout->sm[] = (object) $subBtnLay;
665 } else {
666 $btnData['btnTyp'] = 'submit';
667 $btnData['txt'] = $formContent->buttons->subBtnTxt;
668 $btnData['align'] = $align;
669 $formContent->fields->{$sBtnID} = (object) $btnData;
670
671 $subBtnLay = [
672 "h" => 2,
673 "i" => $sBtnID,
674 "minH" => 2,
675 "x" => 0,
676 "w" => 6,
677 ];
678
679 $subBtnLay["y"] = $lY;
680
681 $formContent->layout->lg[] = (object) $subBtnLay;
682
683 $subBtnLay["y"] = $mY;
684
685 $formContent->layout->md[] = (object) $subBtnLay;
686
687 $subBtnLay["y"] = $sY;
688
689 $formContent->layout->sm[] = (object) $subBtnLay;
690 }
691 }
692 $adminFormHandler->saveLayoutStyleSheet($formContent->layout, 'bitform-layout-' . $formID . '.css');
693 unset($formContent->buttons);
694 $formModel->update(
695 array(
696 "form_content" => wp_json_encode($formContent),
697 ),
698 array(
699 "id" => $formID,
700 )
701 );
702 }
703 }
704 }
705 }
706 }
707