# bit-form/2.10.0/v1/includes/Plugin.php

Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator &amp; Custom Form Builder, version 2.10.0. 726 lines.

- Page: https://pluginprobe.com/plugins/bit-form/2.10.0/code/v1/includes/Plugin.php
- Raw: https://pluginprobe.com/plugins/bit-form/2.10.0/raw/v1/includes/Plugin.php
- Modified: 2024-01-13T07:08:22+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/bit-form/2.10.0/code/v1/includes/Plugin.php#L10-L20`.

```php
<?php

namespace BitCode\BitForm;

/**
 * Main class for the plugin.
 *
 * @since 1.0.0-alpha
 */

use BitCode\BitForm\Admin\Admin_Bar;
use BitCode\BitForm\Admin\Form\AdminFormHandler;
use BitCode\BitForm\Core\Ajax\AjaxService;
use BitCode\BitForm\Core\Capability\Request;
use BitCode\BitForm\Core\Database\DB;
use BitCode\BitForm\Core\Database\FormModel;
use BitCode\BitForm\Core\Database\ReportsModel;
use BitCode\BitForm\Core\Fallback\FormEntryMetaChange;
use BitCode\BitForm\Core\Form\FormHandler;
use BitCode\BitForm\Core\Integration\Integrations;
use BitCode\BitForm\Core\Util\Activation;
use BitCode\BitForm\Core\Util\Deactivation;
use BitCode\BitForm\Core\Util\FileDownloadProvider;
use BitCode\BitForm\Core\Util\GutenBlockProvider;
use BitCode\BitForm\Core\Util\IpTool;
use BitCode\BitForm\Core\Util\Uninstallation;

final class Plugin
{
  /**
   * Main instance of the plugin.
   *
   * @since 1.0.0-alpha
   * @var   Plugin|null
   */
  private static $instance = null;

  /**
   * Registers the plugin with WordPress.
   *
   * @since 1.0.0-alpha
   */
  public function register()
  {
    add_action('plugins_loaded', [$this, 'init_plugin']);
    (new Activation())->activate();
    (new Deactivation())->register();
    (new Uninstallation())->register();
  }

  /**
   * Initialize the hooks
   *
   * @return void
   */
  public function init_hooks()
  {
    add_action('init', [$this, 'registerBitformsPostType']);
    add_action('init', [$this, 'registerCustomPostType']);
    add_action('bitforms_exec_integrations', [Integrations::class, 'integrationExecutionHelper'], 1, 5);
    // Localize our plugin
    add_action('init', [$this, 'localization_setup']);

    // initialize the classes
    add_action('init', [$this, 'init_classes']);

    add_action('init', [$this, 'versionUpdateFallbacks']);

    add_filter('plugin_action_links_' . plugin_basename(BITFORMS_PLUGIN_MAIN_FILE), [$this, 'plugin_action_links']);
  }

  public function versionUpdateFallbacks()
  {
    $installed = get_option('bitforms_installed');
    $oldversion = null;
    if ($installed) {
      $oldversion = get_option('bitforms_version');
    }
    if ($oldversion && version_compare($oldversion, BITFORMS_VERSION, '!=')) {
      update_option('bitforms_version', BITFORMS_VERSION);
      if (version_compare('1.0.4', $oldversion, '>=')) {
        // if version is lower or equal than 1.0.4
        $formEntryMetaChange = new FormEntryMetaChange();
        $formEntryMetaChange->changeMeta();
      }

      if (version_compare('1.4.1', $oldversion, '>=')) {
        // if version is lower or equal than 1.4.1
        $this->addButtonToFieds();
      }

      if (version_compare('1.4.7', $oldversion, '>=')) {
        // if version is equal or lower than 1.4.7
        $this->validationErrMsgFallback();
      }

      if (version_compare('1.4.11', $oldversion, '>=')) {
        // if version is equal or lower than 1.4.11
        $this->buttonValidsObjectFallback();
      }

      if (version_compare('1.4.12.2', $oldversion, '>=')) {
        // if version is equal or lower than 1.4.12.2
        $this->validationEmailFallback();
      }
      if (version_compare('1.5.2', $oldversion, '>=')) {
        $this->reportFallback();
      }
      if (version_compare('1.7.2', $oldversion, '>=')) {
        $this->optionFallBack();
      }
    }
  }

  public function reportFallback()
  {
    $reportMdl = new ReportsModel();
    global $wpdb;
    $tablename = $wpdb->prefix . 'bitforms_reports';

    // $latestIds = $wpdb->get_results("SELECT  MAX(`id`) as latest_id FROM $tablename GROUP BY `context`");
    // $sql = $wpdb->prepare("SELECT  MAX(`id`) as latest_id FROM {$tablename} GROUP BY `context`");
    $wpdb->query(
      $wpdb->prepare(
        "SELECT  MAX(`id`) as latest_id FROM $tablename GROUP BY `context`"
      )
    );
    $latestIds = $wpdb->last_result;

    $notDeletedIds = array_column($latestIds, 'latest_id');

    if (!is_wp_error($latestIds) && count($notDeletedIds) > 0) {
      $reportMdl->bulkDelete(['id' => $notDeletedIds], 'NOT IN');
    }

    $ipTool = new IpTool();
    $user_details = $ipTool->getUserDetail();

    $formModel = new FormModel();

    $forms = $formModel->get(
      ['id']
    );

    $details = [
      'report_name'   => 'All Entries',
      'hiddenColumns' => [],
      'pageSize'      => 10,
      'sortBy'        => [],
      'filters'       => [],
      'globalFilter'  => '',
      'order'         => [],
    ];

    foreach ($forms as $form) {
      $existReportId = $reportMdl->get(
        [
          'id',
        ],
        [
          'context' => $form->id,
        ]
      );
      if (is_wp_error($existReportId)) {
        $defaultReport = [
          'type'        => 'table',
          'category'    => 'form',
          'context'     => $form->id,
          'details'     => wp_json_encode($details),
          'isDefault'   => (bool) 1,
          'user_id'     => $user_details['id'],
          'user_ip'     => $user_details['ip'],
          'user_device' => $user_details['device'],
          'created_at'  => $user_details['time'],
          'updated_at'  => $user_details['time'],
        ];

        $reportMdl->insert($defaultReport);
      }
    }
  }

  public function validationErrMsgFallback()
  {
    $formModel = new FormModel();
    $forms = $formModel->get(
      ['id', 'form_content']
    );

    if (isset($forms) && !is_wp_error($forms)) {
      foreach ($forms as $form) {
        $formID = $form->id;
        $formContent = json_decode($form->form_content);
        $fields = $formContent->fields;

        foreach ($fields as $fldKey => $fldData) {
          if (isset($fldData->valid->req)) {
            if (!isset($fldData->err)) {
              $fldData->err = (object) [];
            }
            $fldData->err->req = (object) [
              'show' => true,
              'dflt' => 'This field is required',
            ];
          }

          if ('check' === $fldData->typ) {
            $reqOpts = array_map(function ($op) {
              return $op->lbl;
            }, array_filter($fldData->opt, function ($ot) {
              return isset($ot->req);
            }));
            if (!empty($reqOpts)) {
              if (!isset($fldData->err)) {
                $fldData->err = (object) [];
              }
              $fldData->err->req = (object) [
                'show' => true,
                'dflt' => implode(', ', $reqOpts) . ' is required',
              ];
            }
          }

          if ('number' === $fldData->typ) {
            if (!isset($fldData->err)) {
              $fldData->err = (object) [];
            }
            $fldData->err->invalid = (object) [
              'show' => true,
              'dflt' => 'Number is invalid',
            ];

            if (isset($fldData->mn)) {
              $fldData->err->mn = (object) [
                'show' => true,
                'dflt' => 'Minimum number is ' . $fldData->mn,
              ];
            }

            if (isset($fldData->mx)) {
              $fldData->err->mx = (object) [
                'show' => true,
                'dflt' => 'Maximum number is ' . $fldData->mx,
              ];
            }
          }

          if ('email' === $fldData->typ) {
            $fldData->pattern = '^$_bf_$w+([.-]?$_bf_$w+)*@$_bf_$w+([.-]?$_bf_$w+)*($_bf_$.$_bf_$w{2,3})+$';
            if (!isset($fldData->err)) {
              $fldData->err = (object) [];
            }
            $fldData->err->invalid = (object) [
              'show' => true,
              'dflt' => 'Email is invalid',
            ];
          }

          if ('url' === $fldData->typ) {
            $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*)?$';
            if (!isset($fldData->err)) {
              $fldData->err = (object) [];
            }
            $fldData->err->invalid = [
              'show' => true,
              'dflt' => 'URL is invalid',
            ];
          }
          $fields->{$fldKey} = $fldData;
        }

        $formContent->fields = $fields;

        $formModel->update(
          [
            'form_content' => wp_json_encode($formContent),
          ],
          [
            'id' => $formID,
          ]
        );
      }
    }
  }

  public function validationEmailFallback()
  {
    $formModel = new FormModel();
    $forms = $formModel->get(
      ['id', 'form_content']
    );

    if (!is_wp_error($forms)) {
      foreach ($forms as $form) {
        $formID = $form->id;
        $formContent = json_decode($form->form_content);
        $fields = $formContent->fields;

        foreach ($fields as $fldKey => $fldData) {
          if ('email' === $fldData->typ) {
            $fldData->pattern = '^$_bf_$w+([.-]?$_bf_$w+)*@$_bf_$w+([.-]?$_bf_$w+)*($_bf_$.$_bf_$w{1,24})+$';
          }
          $fields->{$fldKey} = $fldData;
        }

        $formContent->fields = $fields;

        $formModel->update(
          [
            'form_content' => wp_json_encode($formContent),
          ],
          [
            'id' => $formID,
          ]
        );
      }
    }
  }

  public function buttonValidsObjectFallback()
  {
    $formModel = new FormModel();
    $forms = $formModel->get(
      ['id', 'form_content']
    );

    if (!is_wp_error($forms)) {
      foreach ($forms as $form) {
        $formID = $form->id;
        $formContent = json_decode($form->form_content);
        $fields = $formContent->fields;

        foreach ($fields as $fldKey => $fldData) {
          if ('button' === $fldData->typ && !isset($fldData->valid)) {
            $fldData->valid = (object) [];
          }
          $fields->{$fldKey} = $fldData;
        }

        $formContent->fields = $fields;

        $formModel->update(
          [
            'form_content' => wp_json_encode($formContent),
          ],
          [
            'id' => $formID,
          ]
        );
      }
    }
  }

  private function commaReplace($options, $lbl, $val)
  {
    foreach ($options as $key => $option) {
      if (!empty($option[$lbl]) && !empty($option[$val])) {
        $options[$key][$val] = str_replace(',', '_', $option[$val]);
      }
      if (!empty($option[$lbl]) && empty($option[$val])) {
        $options[$key][$val] = str_replace(',', '_', $option[$lbl]);
      }
    }
    return $options;
  }

  private function replaceOptionSeparator($formContent)
  {
    $updated = false;
    foreach ($formContent['fields'] as $key => $field) {
      if ('check' === $field['typ']) {
        $formContent['fields'][$key]['opt'] = $this->commaReplace($field['opt'], 'lbl', 'val');
        $updated = true;
      }
      if ('select' === $field['typ']) {
        $formContent['fields'][$key]['opt'] = $this->commaReplace($field['opt'], 'label', 'value');
        $updated = true;
      }
    }
    return [$formContent, $updated];
  }

  public function optionFallBack()
  {
    $formModel = new FormModel();
    $forms = $formModel->get(
      ['id', 'form_content']
    );

    foreach ($forms as $form) {
      $formContent = json_decode($form->form_content, true);
      $optReplaceComma = $this->replaceOptionSeparator($formContent);
      if ($optReplaceComma[1]) {
        $formModel->update(
          [
            'form_content' => wp_json_encode($optReplaceComma[0]),
          ],
          [
            'id' => $form->id,
          ]
        );
      }
    }
  }

  /**
   * Updates bit form content tables on wp db
   *
   * @return void
   */
  public function update_tables()
  {
    if (!current_user_can('manage_options')) {
      return;
    }

    global $bitforms_db_version;
    $installed_db_version = get_site_option('bitforms_db_version');
    if ($installed_db_version !== $bitforms_db_version) {
      DB::migrate();
    }
  }

  /**
   * Register post type for bitforms
   *
   * @return void
   */
  public function registerBitformsPostType()
  {
    $args = [
      'label'           => __('Bitform Pages', 'bit-form'),
      'public'          => true,
      'show_ui'         => true,
      'show_in_menu'    => false,
      'capability_type' => 'page',
      'hierarchical'    => false,
      'query_var'       => false,
      'supports'        => ['title'],
      'show_in_rest'    => false,
    ];
    register_post_type('bitforms', $args);
  }

  public function registerCustomPostType()
  {
    flush_rewrite_rules(false);
    $cpts = get_option('bitform_custom_post_types');
    if (!empty($cpts)) {
      foreach ($cpts as $cpt) {
        $labels = [
          'name'          => _x($cpt->name, 'Post type general name', 'bit-form'),
          'singular_name' => _x($cpt->singular_label, 'Post type singular name', 'bit-form'),
          'menu_name'     => _x($cpt->menu_name, 'Admin Menu text', 'bit-form'),
        ];
        $args = [
          'labels'             => $labels,
          'public'             => 1 === $cpt->public ? true : false,
          'publicly_queryable' => 1 === $cpt->public_queryable ? true : false,
          'show_ui'            => 1 === $cpt->show_ui ? true : false,
          'show_in_menu'       => 1 === $cpt->show_in_menu ? true : false,
          'query_var'          => true,
          'rewrite'            => ['slug' => $cpt->name],
          'capability_type'    => 'post',
          'has_archive'        => true,
          'hierarchical'       => false,
          'show_in_rest'       => 1 === isset($cpt->show_in_rest) ? true : false,
          'menu_icon'          => $cpt->menu_icon,
          'supports'           => ['title', 'editor', 'author', 'excerpt', 'comments'],
        ];
        register_post_type($cpt->name, $args);
      }
    }
  }

  /**
   * Initialize plugin for localization
   *
   * @uses load_plugin_textdomain()
   */
  public function localization_setup()
  {
    load_plugin_textdomain('bitform', false, dirname(BITFORMS_PLUGIN_BASENAME) . '/languages');
  }

  /**
   * Instantiate the required classes
   *
   * @return void
   */
  public function init_classes()
  {
    if (Request::Check('admin')) {
      (new Admin_Bar())->register();
    }
    if (Request::Check('ajax')) {
      new AjaxService();
    }
    if (Request::Check('frontend')) {
      $formHandler = new FormHandler();
      $formHandler->frontend;
    }
    if (Request::isPluginPage()) {
      (new FileDownloadProvider())->register();
    }
    if (current_user_can('edit_posts')) {
      (new GutenBlockProvider())->register();
    }
  }

  /**
   * Plugin action links
   *
   * @param  array $links
   *
   * @return array
   */
  public function plugin_action_links($links)
  {
    $links[] = '<a href="https://docs.form.bitapps.pro" target="_blank">' . __('Docs', 'bit-form') . '</a>';

    return $links;
  }

  public function init_plugin()
  {
    $this->init_hooks();
    $this->update_tables();
    do_action('bitform_loaded');
  }

  /**
   * Retrieves the main instance of the plugin.
   *
   * @since 1.0.0-alpha
   *
   * @return BITFORM Plugin main instance.
   */
  public static function instance()
  {
    return static::$instance;
  }

  /**
   * Loads the plugin main instance and initializes it.
   *
   * @param  string $main_file Absolute path to the plugin main file.
   *
   * @return bool True if the plugin main instance could be loaded, false otherwise.
   */
  public static function load($main_file)
  {
    if (null !== static::$instance) {
      return false;
    }

    static::$instance = new static($main_file);
    static::$instance->register();
    return true;
  }

  public function addButtonToFieds()
  {
    // if version is lower or equal than 1.3.13
    $formModel = new FormModel();
    $forms = $formModel->get(
      ['id', 'form_content'],
      [
        'form_content' => ['operator' => 'LIKE', 'value' => '%\"buttons\":%'],
      ]
    );
    if (!is_wp_error($forms)) {
      $adminFormHandler = new AdminFormHandler();
      foreach ($forms as $form) {
        $formID = $form->id;
        $formContent = json_decode($form->form_content);
        $fields = wp_json_encode($formContent->fields);
        if (isset($formContent->buttons)) {
          if (false === strpos($fields, '"btnTyp":"submit"')) {
            $align = isset($formContent->buttons->align) ? $formContent->buttons->align : 'right';
            $btnSiz = isset($formContent->buttons->btnSiz) ? $formContent->buttons->btnSiz : 'md';
            $fulW = isset($formContent->buttons->fulW) ? $formContent->buttons->fulW : false;
            $btnData = [
              'typ'    => 'button',
              'btnSiz' => $btnSiz,
              'fulW'   => $fulW,
            ];
            $newID = 0;
            foreach ($formContent->fields as $key => $value) {
              $oldID = \preg_replace('/bf?\d+-(\d+)-?/', '$1', $key);
              if ($oldID > $newID) {
                $newID = $oldID;
              }
            }
            $newID = $newID + 1;
            $sBtnID = "bf${formID}-${newID}";
            $lY = 0;
            $mY = 0;
            $sY = 0;
            foreach ($formContent->layout->lg as $lg) {
              if ($lg->y > $lY) {
                $lY = $lg->y;
              }
            }
            $lY = $lY + $lg->h + 1;
            foreach ($formContent->layout->md as $md) {
              if ($md->y > $mY) {
                $mY = $md->y;
              }
            }
            $mY = $mY + $md->h + 1;
            foreach ($formContent->layout->sm as $sm) {
              if ($sm->y > $sY) {
                $sY = $sm->y;
              }
            }
            $sY = $sY + $sm->h + 1;
            if (isset($formContent->buttons->rstBtnTxt)) {
              $newID += 1;
              $rBtnID = "bf${formID}-${newID}";

              if ($fulW) {
                $btnData['btnTyp'] = 'submit';
                $btnData['align'] = $align;
                $btnData['txt'] = $formContent->buttons->subBtnTxt;
                $formContent->fields->{$sBtnID} = (object) $btnData;
                $rBtnData = $btnData;
                $rBtnData['btnTyp'] = 'reset';
                $rBtnData['align'] = $align;
                $rBtnData['txt'] = $formContent->buttons->rstBtnTxt;
                $formContent->fields->{$rBtnID} = (object) $rBtnData;
              } else {
                $btnData['btnTyp'] = 'submit';
                $btnData['align'] = 'right';
                $btnData['txt'] = $formContent->buttons->subBtnTxt;
                $formContent->fields->{$sBtnID} = (object) $btnData;
                $rBtnData = $btnData;
                $rBtnData['btnTyp'] = 'reset';
                $rBtnData['align'] = 'left';
                $rBtnData['txt'] = $formContent->buttons->rstBtnTxt;
                $formContent->fields->{$rBtnID} = (object) $rBtnData;
              }
              $subBtnLay = [
                'h'    => 2,
                'i'    => $sBtnID,
                'minH' => 2,
                'x'    => 0,
                'y'    => 1000,
              ];

              $subBtnLay['w'] = 3;
              $subBtnLay['y'] = $lY;

              $formContent->layout->lg[] = (object) $subBtnLay;

              $subBtnLay['w'] = 2;
              $subBtnLay['y'] = $mY;

              $formContent->layout->md[] = (object) $subBtnLay;

              $subBtnLay['w'] = 1;
              $subBtnLay['y'] = $sY;

              $formContent->layout->sm[] = (object) $subBtnLay;

              $subBtnLay['i'] = $rBtnID;
              $subBtnLay['x'] = 3;
              $subBtnLay['w'] = 3;
              $subBtnLay['y'] = $lY;

              $formContent->layout->lg[] = (object) $subBtnLay;

              $subBtnLay['x'] = 2;
              $subBtnLay['w'] = 2;
              $subBtnLay['y'] = $mY;

              $formContent->layout->md[] = (object) $subBtnLay;

              $subBtnLay['w'] = 1;
              $subBtnLay['x'] = 1;
              $subBtnLay['y'] = $sY;

              $formContent->layout->sm[] = (object) $subBtnLay;
            } else {
              $btnData['btnTyp'] = 'submit';
              $btnData['txt'] = $formContent->buttons->subBtnTxt;
              $btnData['align'] = $align;
              $formContent->fields->{$sBtnID} = (object) $btnData;

              $subBtnLay = [
                'h'    => 2,
                'i'    => $sBtnID,
                'minH' => 2,
                'x'    => 0,
                'w'    => 6,
              ];

              $subBtnLay['y'] = $lY;

              $formContent->layout->lg[] = (object) $subBtnLay;

              $subBtnLay['y'] = $mY;

              $formContent->layout->md[] = (object) $subBtnLay;

              $subBtnLay['y'] = $sY;

              $formContent->layout->sm[] = (object) $subBtnLay;
            }
          }
          $adminFormHandler->saveLayoutStyleSheet($formContent->layout, 'bitform-layout-' . $formID . '.css');
          unset($formContent->buttons);
          $formModel->update(
            [
              'form_content' => wp_json_encode($formContent),
            ],
            [
              'id' => $formID,
            ]
          );
        }
      }
    }
  }
}

```
