PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 3.3.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v3.3.1
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 2.10.1 All 138 releases
← All changes | includes/Core/Database/DB.php +252 -59 1.1.83.3.1 View file →
@@ -8,36 +8,154 @@
8 8 */
9 9
10 10 namespace BitCode\BitForm\Core\Database;
11 11
12 +use BitCode\BitForm\Core\Util\Log;
13 +
12 14 /**
13 15 * Database Migration
14 16 */
15 17 final class DB
16 18 {
17 - /**
18 - * Undocumented function
19 - *
20 - * @return void
21 - */
22 - public static function migrate()
23 - {
24 - global $wpdb;
25 - global $bitforms_db_version;
26 - $collate = '';
19 + /**
20 + * Undocumented function
21 + *
22 + * @return void
23 + */
27 24
28 - if ($wpdb->has_cap('collation')) {
29 - if (!empty($wpdb->charset)) {
30 - $collate .= "DEFAULT CHARACTER SET $wpdb->charset";
31 - }
25 + /**
26 + * Idempotently add the email-template status/config columns.
27 + *
28 + * @return void
29 + */
30 + public static function ensureEmailTemplateStatusColumn()
31 + {
32 + global $wpdb;
33 + $emailTable = $wpdb->prefix . 'bitforms_email_template';
34 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$emailTable}` LIKE 'status'")) {
35 + // Schema migration: table name interpolation only (no user input). $wpdb->prepare() cannot parameterize DDL.
36 + $wpdb->query(
37 + "ALTER TABLE `{$emailTable}`
38 + ADD COLUMN `status` TINYINT(1) DEFAULT 1 AFTER `body`,
39 + ADD COLUMN `config` LONGTEXT NULL AFTER `status`"
40 + );
41 + }
42 + }
32 43
33 - if (!empty($wpdb->collate)) {
34 - $collate .= " COLLATE $wpdb->collate";
35 - }
36 - }
44 + /**
45 + * Idempotently add the workflows `workflow_info` column.
46 + *
47 + * @return void
48 + */
49 + public static function ensureWorkflowInfoColumn()
50 + {
51 + global $wpdb;
52 + $table = $wpdb->prefix . 'bitforms_workflows';
53 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$table}` LIKE 'workflow_info'")) {
54 + // Schema migration: table name interpolation only (no user input). $wpdb->prepare() cannot parameterize DDL.
55 + $wpdb->query(
56 + "ALTER TABLE `{$table}`
57 + ADD COLUMN `workflow_info` LONGTEXT NULL AFTER `workflow_condition`"
58 + );
59 + }
60 + }
37 61
38 - $table_schema = array(
39 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_reports` (
62 + /**
63 + * Idempotently add the workflows `workflow_category` column (conditional-logic classic/basic split).
64 + *
65 + * @return void
66 + */
67 + public static function ensureWorkflowCategoryColumn()
68 + {
69 + self::ensureWorkflowInfoColumn();
70 + global $wpdb;
71 + $table = $wpdb->prefix . 'bitforms_workflows';
72 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$table}` LIKE 'workflow_category'")) {
73 + // Schema migration: table name interpolation only (no user input). $wpdb->prepare() cannot parameterize DDL.
74 + $wpdb->query(
75 + "ALTER TABLE `{$table}`
76 + ADD COLUMN `workflow_category` VARCHAR(20) DEFAULT 'classic' AFTER `workflow_info`,
77 + ADD KEY `workflow_category` (`workflow_category`)"
78 + );
79 + }
80 + }
81 +
82 + /**
83 + * Idempotently add the workflows `workflow_order` column.
84 + *
85 + * @return void
86 + */
87 + public static function ensureWorkflowOrderColumn()
88 + {
89 + global $wpdb;
90 + $table = $wpdb->prefix . 'bitforms_workflows';
91 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$table}` LIKE 'workflow_order'")) {
92 + $wpdb->query(
93 + "ALTER TABLE `{$table}`
94 + ADD COLUMN `workflow_order` INT(11) DEFAULT NULL AFTER `workflow_condition`"
95 + );
96 + }
97 + }
98 +
99 + /**
100 + * Idempotently add the workflows `workflow_status` column.
101 + *
102 + * @return void
103 + */
104 + public static function ensureWorkflowStatusColumn()
105 + {
106 + self::ensureWorkflowOrderColumn();
107 + global $wpdb;
108 + $table = $wpdb->prefix . 'bitforms_workflows';
109 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$table}` LIKE 'workflow_status'")) {
110 + $wpdb->query(
111 + "ALTER TABLE `{$table}`
112 + ADD COLUMN `workflow_status` TINYINT(1) DEFAULT 1 NOT NULL AFTER `workflow_order`"
113 + );
114 + }
115 + }
116 +
117 + /**
118 + * Idempotently add every workflows column the queries reference, for installs whose
119 + * `bitforms_db_version` ran ahead of their real schema (a version-gated ALTER failed once).
120 + *
121 + * @return bool true when all four columns exist afterwards
122 + */
123 + public static function ensureWorkflowSchema()
124 + {
125 + global $wpdb;
126 + self::ensureWorkflowStatusColumn();
127 + self::ensureWorkflowCategoryColumn();
128 +
129 + $table = $wpdb->prefix . 'bitforms_workflows';
130 + foreach (['workflow_order', 'workflow_info', 'workflow_category', 'workflow_status'] as $column) {
131 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$table}` LIKE '{$column}'")) {
132 + return false;
133 + }
134 + }
135 + return true;
136 + }
137 +
138 + public static function migrate()
139 + {
140 + global $wpdb;
141 + global $bitforms_db_version;
142 + $collate = '';
143 +
144 + if ($wpdb->has_cap('collation')) {
145 + if (!empty($wpdb->charset)) {
146 + $collate .= "DEFAULT CHARACTER SET $wpdb->charset";
147 + }
148 +
149 + if (!empty($wpdb->collate)) {
150 + $collate .= " COLLATE $wpdb->collate";
151 + }
152 + }
153 +
154 + $max_index_length = 191;
155 +
156 + $table_schema = [
157 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_reports` (
40 158 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
41 159 `category` varchar(50) NOT NULL,
42 160 `type` varchar(20) NOT NULL,
43 161 `context` varchar(20) NOT NULL,
@@ -50,12 +168,15 @@
50 168 `updated_at` datetime DEFAULT NULL,
51 169 PRIMARY KEY (`id`)
52 170 ) $collate;",
53 171
54 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form` (
172 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form` (
55 173 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
56 174 `form_name` varchar(255) DEFAULT NULL,
57 175 `form_content` longtext DEFAULT NULL,
176 + `builder_helper_state` longtext DEFAULT NULL,
177 + `atomic_class_map` longtext DEFAULT NULL,
178 + `generated_script_page_ids` longtext DEFAULT NULL,
58 179 `user_id` bigint(20) unsigned DEFAULT NULL,
59 180 `user_ip` int(11) unsigned DEFAULT NULL,
60 181 `views` int(11) unsigned DEFAULT 0,
61 182 `entries` int(11) unsigned DEFAULT 0,
@@ -65,9 +186,9 @@
65 186 `updated_at` datetime DEFAULT NULL,
66 187 PRIMARY KEY (`id`)
67 188 ) $collate;",
68 189
69 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_workflows` (
190 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_workflows` (
70 191 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
71 192 `workflow_name` varchar(255) NOT NULL,
72 193 `workflow_type` varchar(50) NOT NULL,
73 194 `workflow_run` varchar(50) NOT NULL,
@@ -72,9 +193,12 @@
72 193 `workflow_type` varchar(50) NOT NULL,
73 194 `workflow_run` varchar(50) NOT NULL,
74 195 `workflow_behaviour` varchar(25) NOT NULL,
75 196 `workflow_condition` longtext DEFAULT NULL,
76 - `workflow_action` longtext DEFAULT NULL,
197 + `workflow_info` longtext DEFAULT NULL,
198 + `workflow_category` varchar(20) DEFAULT 'classic',/* classic = legacy, basic = field show/hide, advanced = multi-condition routing */
199 + `workflow_order` int(11) unsigned DEFAULT NULL,
200 + `workflow_status` tinyint(1) DEFAULT 1,/* 0 disable, 1 enable, 2 enable in field settings */
77 201 `form_id` bigint(20) unsigned DEFAULT NULL,
78 202 `user_id` bigint(20) unsigned DEFAULT NULL,
79 203 `user_ip` int(11) unsigned DEFAULT NULL,
80 204 `user_location` text DEFAULT NULL,
@@ -81,15 +205,17 @@
81 205 `user_device` varchar(50) DEFAULT NULL,
82 206 `created_at` datetime DEFAULT NULL,
83 207 `updated_at` datetime DEFAULT NULL,
84 208 PRIMARY KEY (`id`),
85 - KEY `form_id` (`form_id`)
209 + KEY `form_id` (`form_id`),
210 + KEY `workflow_category` (`workflow_category`)
86 211 ) $collate;",
87 212
88 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_success_messages` (
213 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_success_messages` (
89 214 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
90 215 `message_title` varchar(255) DEFAULT NULL,
91 216 `message_content` longtext DEFAULT NULL,
217 + `message_config` longtext DEFAULT NULL,
92 218 `form_id` bigint(20) unsigned DEFAULT NULL,
93 219 `user_id` bigint(20) unsigned DEFAULT NULL,
94 220 `user_ip` int(11) unsigned DEFAULT NULL,
95 221 `created_at` datetime DEFAULT NULL,
@@ -96,13 +222,15 @@
96 222 `updated_at` datetime DEFAULT NULL,
97 223 PRIMARY KEY (`id`)
98 224 ) $collate;",
99 225
100 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_email_template` (
226 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_email_template` (
101 227 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
102 228 `title` text DEFAULT NULL,
103 229 `sub` text DEFAULT NULL,
104 230 `body` longtext DEFAULT NULL,
231 + `status` tinyint(1) DEFAULT 1,/* 0 disabled, 1 enabled */
232 + `config` longtext DEFAULT NULL,/* SendTo / From / From Name / CC / BCC / Reply-To / attachments JSON */
105 233 `form_id` bigint(20) unsigned DEFAULT NULL,
106 234 `user_id` bigint(20) unsigned DEFAULT NULL,
107 235 `user_ip` int(11) unsigned DEFAULT NULL,
108 236 `created_at` datetime DEFAULT NULL,
@@ -109,9 +237,9 @@
109 237 `updated_at` datetime DEFAULT NULL,
110 238 PRIMARY KEY (`id`)
111 239 ) $collate;",
112 240
113 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_integration` (
241 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_integration` (
114 242 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
115 243 `category` varchar(50) NOT NULL,
116 244 `integration_name` varchar(255) DEFAULT NULL,
117 245 `integration_type` varchar(50) NOT NULL,
@@ -124,16 +252,16 @@
124 252 `updated_at` datetime DEFAULT NULL,
125 253 PRIMARY KEY (`id`)
126 254 ) $collate;",
127 255
128 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entries` (
256 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entries` (
129 257 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
130 258 `form_id` bigint(20) unsigned DEFAULT NULL,
131 259 `user_id` bigint(20) unsigned DEFAULT NULL,
132 - `user_ip` int(11) unsigned DEFAULT NULL,
260 + `user_ip` varchar(255) DEFAULT NULL,
133 261 `user_location` text DEFAULT NULL,
134 262 `user_device` varchar(50) DEFAULT NULL,
135 - `referer` varchar(255) DEFAULT NULL,
263 + `referer` TEXT DEFAULT NULL,
136 264 `status` tinyint(1) DEFAULT 0,/* 0 not viewed, 1 viewed, 2 trashed */
137 265 `created_at` datetime DEFAULT NULL,
138 266 `updated_at` datetime DEFAULT NULL,
139 267 PRIMARY KEY (`id`),
@@ -139,19 +267,19 @@
139 267 PRIMARY KEY (`id`),
140 268 KEY `form_id` (`form_id`)
141 269 ) $collate;",
142 270
143 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entrymeta` (
271 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entrymeta` (
144 272 `meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
145 273 `bitforms_form_entry_id` bigint(20) unsigned DEFAULT NULL,
146 274 `meta_key` varchar(255) DEFAULT NULL,
147 275 `meta_value` longtext,
148 276 PRIMARY KEY (`meta_id`),
149 - KEY `meta_key` (`meta_key`),
277 + KEY `meta_key` (`meta_key`({$max_index_length})),
150 278 KEY `entry_id` (`bitforms_form_entry_id`)
151 279 ) $collate;",
152 280
153 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entry_log` (
281 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entry_log` (
154 282 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
155 283 `user_id` int(11) NOT NULL,
156 284 `log_type` varchar(50) DEFAULT NULL,
157 285 `ip` int(11) DEFAULT NULL,
@@ -164,9 +292,9 @@
164 292 KEY `form_id` (`form_id`),
165 293 KEY `form_entry_id` (`form_entry_id`)
166 294 ) $collate;",
167 295
168 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_log_details` (
296 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_log_details` (
169 297 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
170 298 `log_id` bigint(20) NOT NULL,
171 299 `integration_id` bigint(20) DEFAULT NULL,
172 300 `api_type` varchar(255) DEFAULT NULL,
@@ -176,9 +304,9 @@
176 304 PRIMARY KEY (`id`),
177 305 KEY `log_id` (`log_id`),
178 306 KEY `integration_id` (`integration_id`)
179 307 ) $collate;",
180 - "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entry_relatedinfo` (
308 + "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}bitforms_form_entry_relatedinfo` (
181 309 `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
182 310 `info_type` VARCHAR(50) NOT NULL,
183 311 `info_details` LONGTEXT NULL,
184 312 `form_id` BIGINT(20) UNSIGNED NOT NULL,
@@ -191,35 +319,100 @@
191 319 PRIMARY KEY (`id`),
192 320 KEY `form_id` (`form_id`),
193 321 KEY `entry_id` (`entry_id`)
194 322 ) $collate;"
195 - );
323 + ];
196 324
197 - $table_schema_update = array(
198 - "ALTER TABLE `{$wpdb->prefix}bitforms_form_entry_log`
199 - CHANGE COLUMN `log_type` `log_type` VARCHAR(50) NULL DEFAULT NULL,
325 + try {
326 + include_once ABSPATH . 'wp-admin/includes/upgrade.php';
327 + foreach ($table_schema as $table) {
328 + dbDelta($table);
329 + }
330 + $installed_db_version = get_option('bitforms_db_version');
331 + if ($installed_db_version && version_compare('1.1', $installed_db_version, '>=')) {
332 + // if new db version is equal or higher than 1.1
333 + // Schema migration: table name interpolation only (no user input). $wpdb->prepare() cannot parameterize DDL statements.
334 + try {
335 + $wpdb->query("ALTER TABLE `{$wpdb->prefix}bitforms_form_entry_log`
336 + MODIFY `log_type` VARCHAR(50) NULL DEFAULT NULL,
337 + MODIFY `created_at` DATETIME NOT NULL,
338 + CHANGE COLUMN `meta_key` `content` LONGTEXT NULL,
200 339 ADD COLUMN `action_type` VARCHAR(50) NULL DEFAULT NULL,
201 - CHANGE COLUMN `meta_key` `content` LONGTEXT NULL,
202 - CHANGE COLUMN `created_at` `created_at` DATETIME NOT NULL",
203 - "ALTER TABLE `{$wpdb->prefix}bitforms_form_log_details`
204 - CHANGE COLUMN `api_type` `api_type` VARCHAR(255) NULL DEFAULT NULL,
205 - CHANGE COLUMN `response_obj` `response_obj` LONGTEXT NULL,
206 - CHANGE COLUMN `created_at` `created_at` DATETIME NOT NULL",
207 - );
340 + ADD COLUMN `content` LONGTEXT NULL AFTER `action_type`");
341 + } catch (\Exception $e) {
342 + Log::debug_log("Update failed: {$e->getMessage()} in query: ALTER TABLE `{$wpdb->prefix}bitforms_form_entry_log`...");
343 + }
344 + try {
345 + $wpdb->query("ALTER TABLE `{$wpdb->prefix}bitforms_form_log_details`
346 + MODIFY `api_type` VARCHAR(255) NULL DEFAULT NULL,
347 + MODIFY `response_obj` LONGTEXT NULL,
348 + MODIFY `created_at` DATETIME NOT NULL");
349 + } catch (\Exception $e) {
350 + Log::debug_log("Update failed: {$e->getMessage()} in query: ALTER TABLE `{$wpdb->prefix}bitforms_form_log_details`...");
351 + }
352 + }
353 + if ($installed_db_version && version_compare('1.3', $installed_db_version, '>=')) {
354 + // if new db version is equal or higher than 1.3
355 + $wpdb->query("ALTER TABLE `{$wpdb->prefix}bitforms_form_entries` MODIFY `user_ip` VARCHAR(255) NULL DEFAULT NULL");
356 + }
208 357
209 - include_once ABSPATH . 'wp-admin/includes/upgrade.php';
210 - foreach ($table_schema as $table) {
211 - dbDelta($table);
358 + if ($installed_db_version && version_compare('2.0', $installed_db_version, '>=')) {
359 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$wpdb->prefix}bitforms_success_messages` LIKE 'message_config'")) {
360 + $wpdb->query(
361 + "ALTER TABLE `{$wpdb->prefix}bitforms_success_messages`
362 + ADD COLUMN `message_config` LONGTEXT NULL AFTER `message_content`"
363 + );
212 364 }
213 - $installed_db_version = get_site_option("bitforms_db_version");
214 - if ($installed_db_version && version_compare('1.1', $installed_db_version, '<=')) {
215 - // if new db version is equal or higher than 1.1
216 - foreach ($table_schema_update as $table) {
217 - $wpdb->query($table);
218 - }
365 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$wpdb->prefix}bitforms_form` LIKE 'builder_helper_state'")) {
366 + $wpdb->query(
367 + "ALTER TABLE `{$wpdb->prefix}bitforms_form`
368 + ADD COLUMN `builder_helper_state` LONGTEXT NULL AFTER `form_content`,
369 + ADD COLUMN `atomic_class_map` LONGTEXT NULL AFTER `builder_helper_state`,
370 + ADD COLUMN `generated_script_page_ids` LONGTEXT NULL AFTER `atomic_class_map`"
371 + );
219 372 }
220 - update_site_option(
221 - 'bitforms_db_version',
222 - $bitforms_db_version
223 - );
373 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$wpdb->prefix}bitforms_workflows` LIKE 'workflow_order'")) {
374 + $wpdb->query(
375 + "ALTER TABLE `{$wpdb->prefix}bitforms_workflows`
376 + ADD COLUMN `workflow_order` INT(11) DEFAULT NULL AFTER `workflow_condition`"
377 + );
378 + }
379 + }
380 +
381 + if ($installed_db_version && version_compare('2.2', $installed_db_version, '>=')) {
382 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$wpdb->prefix}bitforms_form_entries` LIKE 'referer'")) {
383 + $wpdb->query(
384 + "ALTER TABLE `{$wpdb->prefix}bitforms_form_entries`
385 + ADD COLUMN `referer` TEXT NULL DEFAULT NULL"
386 + );
387 + }
388 + }
389 +
390 + if ($installed_db_version && version_compare('2.4', $installed_db_version, '>=')) {
391 + if (null === $wpdb->get_var("SHOW COLUMNS FROM `{$wpdb->prefix}bitforms_workflows` LIKE 'workflow_status'")) {
392 + $wpdb->query(
393 + "ALTER TABLE `{$wpdb->prefix}bitforms_workflows`
394 + ADD COLUMN `workflow_status` TINYINT(1) DEFAULT 1 NOT NULL AFTER `workflow_order`"
395 + );
396 + }
397 + }
398 +
399 + // add workflow_info column if not exists
400 + if ($installed_db_version && version_compare('3.0', $installed_db_version, '>=')) {
401 + self::ensureWorkflowInfoColumn();
402 + }
403 +
404 + // add workflow_category column if not exists (conditional logic separation)
405 + // existing rows default to 'classic' so Free keeps executing them unchanged; data normalization in Fallback WorkFlow@normalizeCategory
406 + if ($installed_db_version && version_compare('3.2', $installed_db_version, '>=')) {
407 + self::ensureWorkflowCategoryColumn();
408 + // email template enable/disable + per-template config (SendTo/From/CC/BCC/Reply-To/attachments)
409 + self::ensureEmailTemplateStatusColumn();
410 + }
411 +
412 + update_option('bitforms_db_version', $bitforms_db_version, true);
413 + } catch (\Exception $e) {
414 + // Log the error to a file or the database
415 + Log::debug_log('Error during DB migration: ' . $e->getMessage());
224 416 }
417 + }
225 418 }