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/Admin/AdminAjax.php +107 -17 3.2.13.3.1 View file →
@@ -8,8 +8,9 @@
8 8
9 9 use BitCode\BitForm\Admin\Form\FrontEndScriptGenerator;
10 10 use BitCode\BitForm\Admin\Form\Helpers;
11 11 use BitCode\BitForm\Admin\Form\Template\TemplateProvider;
12 +use BitCode\BitForm\Core\Database\FormEntryLogModel;
12 13 use BitCode\BitForm\Core\Database\FormEntryModel;
13 14 use BitCode\BitForm\Core\Database\FormModel;
14 15 use BitCode\BitForm\Core\Form\FormHandler;
15 16 use BitCode\BitForm\Core\Integration\IntegrationHandler;
@@ -16,8 +17,9 @@
16 17 use BitCode\BitForm\Core\Integration\Integrations;
17 18 use BitCode\BitForm\Core\Util\IpTool;
18 19 use BitCode\BitForm\Core\Util\MailConfig;
19 20 use BitCode\BitForm\Core\Util\MetaBoxService;
21 +use BitCode\BitForm\Core\Util\Utilities;
20 22 use BitCode\BitForm\Frontend\Form\FrontendFormManager;
21 23 use BitCode\BitForm\GlobalHelper;
22 24 use WP_Error;
23 25
@@ -28,8 +30,10 @@
28 30 add_action('wp_ajax_bitforms_integrations', [$this, 'integrations']);
29 31 add_action('wp_ajax_bitforms_save_connected_integration_apps', [$this, 'saveConnectedIntegrationApps']);
30 32 add_action('wp_ajax_bitforms_get_connected_integration_apps', [$this, 'getConnectedIntegrationApps']);
31 33 add_action('wp_ajax_bitforms_delete_connected_app', [$this, 'deleteConnectedApp']);
34 + add_action('wp_ajax_bitforms_update_connected_app', [$this, 'updateConnectedApp']);
35 + add_action('wp_ajax_bitforms_integration_last_runs', [$this, 'integrationLastRuns']);
32 36 add_action('wp_ajax_bitforms_update_form', [$this, 'updateForm']);
33 37 add_action('wp_ajax_bitforms_templates', [$this, 'templates']);
34 38 add_action('wp_ajax_bitforms_create_new_form', [$this, 'createNewForm']);
35 39 add_action('wp_ajax_bitforms_save_css', [$this, 'saveCss']);
@@ -110,9 +114,8 @@
110 114 add_action('wp_ajax_bitforms_changelog_version', [$this, 'setChangelogVersion']);
111 115
112 116 // Notice Options
113 117 add_action('wp_ajax_bitforms_handle_notice', [$this, 'handleNotice']);
114 - add_action('wp_ajax_bitforms_dismiss_pro_notice', [$this, 'dismissProUpgradeNotice']);
115 118
116 119 // conversational
117 120 add_action('wp_ajax_bitforms_save_conversational_css', [$this, 'saveConversationalCSS']);
118 121
@@ -133,9 +136,15 @@
133 136 $this->verifyAdminPermission();
134 137 $formId = isset($_REQUEST['formID']) ? sanitize_text_field(wp_unslash($_REQUEST['formID'])) : '';
135 138
136 139 $FrontendFormManager = FrontendFormManager::getInstance($formId);
140 + if (!$FrontendFormManager->isExist()) {
141 + wp_send_json_error(__('Form is not exists.', 'bit-form'), 404);
142 + }
137 143 $formContent = $FrontendFormManager->getFormContentWithValue();
144 + if (!is_object($formContent) || !isset($formContent->fields, $formContent->layout)) {
145 + wp_send_json_error(__('Form content is unavailable.', 'bit-form'), 404);
146 + }
138 147 $fields = $formContent->fields;
139 148 $layout = $formContent->layout;
140 149 $file = count($FrontendFormManager->getUploadFields()) > 0 ? $FrontendFormManager->getUploadFields() : false;
141 150 $html = $FrontendFormManager->formView($fields, $file);
@@ -290,11 +299,14 @@
290 299 } catch (\InvalidArgumentException $e) {
291 300 wp_send_json_error($e->getMessage(), 400);
292 301 }
293 302 // Nonce verified at handler entry (wp_verify_nonce 'bitforms_save', line 273).
294 - $appId = isset($_REQUEST['appId']) && $_REQUEST['appId']
303 + $requestedAppId = isset($_REQUEST['appId'])
295 304 ? sanitize_text_field(wp_unslash($_REQUEST['appId']))
296 - : sanitize_text_field(wp_unslash((string) $input->appId));
305 + : '';
306 + $appId = $requestedAppId
307 + ? $requestedAppId
308 + : sanitize_text_field(wp_unslash((string) ($input->appId ?? '')));
297 309 $integrationHandler = Integrations::getInstance();
298 310 $status = $integrationHandler->deleteConnectedApp($appId);
299 311 if (is_wp_error($status)) {
300 312 wp_send_json_error($status->get_error_message(), 411);
@@ -311,8 +323,89 @@
311 323 );
312 324 }
313 325 }
314 326
327 + /**
328 + * Renames a connected account (category connected_integration_apps, form_id 0).
329 + * Only integration_name is writable; updateIntegration would overwrite the rest.
330 + *
331 + * @return void
332 + */
333 + public function updateConnectedApp()
334 + {
335 + if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
336 + $this->verifyAdminPermission();
337 + GlobalHelper::requirePostMethod();
338 + try {
339 + $input = GlobalHelper::formatRequestData();
340 + } catch (\InvalidArgumentException $e) {
341 + wp_send_json_error($e->getMessage(), 400);
342 + }
343 + $appId = !empty($input->appId) ? sanitize_text_field((string) $input->appId) : '';
344 + $name = isset($input->name) ? sanitize_text_field((string) $input->name) : '';
345 + if (empty($appId) || '' === trim($name)) {
346 + wp_send_json_error(__('Invalid request', 'bit-form'), 400);
347 + }
348 + $integrations = Integrations::getInstance();
349 + $status = $integrations->renameConnectedApp($appId, $name);
350 + if (is_wp_error($status)) {
351 + wp_send_json_error($status->get_error_message(), 411);
352 + } else {
353 + wp_send_json_success($status, 200);
354 + }
355 + } else {
356 + wp_send_json_error(
357 + __(
358 + 'Token expired',
359 + 'bit-form'
360 + ),
361 + 401
362 + );
363 + }
364 + }
365 +
366 + /**
367 + * Last execution per integration of a form, for the integrations list Last Run column.
368 + *
369 + * @return void
370 + */
371 + public function integrationLastRuns()
372 + {
373 + if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
374 + $this->verifyAdminPermission();
375 + GlobalHelper::requirePostMethod();
376 + try {
377 + $input = GlobalHelper::formatRequestData();
378 + } catch (\InvalidArgumentException $e) {
379 + wp_send_json_error($e->getMessage(), 400);
380 + }
381 + $formID = !empty($input->formID) ? absint($input->formID) : 0;
382 + if (empty($formID)) {
383 + wp_send_json_error(__('Invalid request', 'bit-form'), 400);
384 + }
385 + $logModel = new FormEntryLogModel();
386 + $rows = $logModel->getIntegrationLastRuns($formID);
387 + if (is_wp_error($rows)) {
388 + // result_empty means nothing has run yet, which is a success. Any other
389 + // error is a failed query — answering [] would paint every integration
390 + // as never executed. Message stays generic: no DB detail to the browser.
391 + if ('result_empty' !== $rows->get_error_code()) {
392 + wp_send_json_error(__('Could not load integration run history', 'bit-form'), 500);
393 + }
394 + $rows = [];
395 + }
396 + wp_send_json_success($rows, 200);
397 + } else {
398 + wp_send_json_error(
399 + __(
400 + 'Token expired',
401 + 'bit-form'
402 + ),
403 + 401
404 + );
405 + }
406 + }
407 +
315 408 public function templates()
316 409 {
317 410 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
318 411 $this->verifyAdminPermission();
@@ -496,15 +589,8 @@
496 589 );
497 590 }
498 591 }
499 592
500 - public function dismissProUpgradeNotice()
501 - {
502 - check_ajax_referer('bitforms_dismiss_pro_notice', 'nonce');
503 - update_user_meta(get_current_user_id(), 'bitforms_dismiss_pro_upgrade_notice', BITFORMS_REQUIRED_BITFORMPRO_VERSION);
504 - wp_die();
505 - }
506 -
507 593 private function formatFormContentForUpdate($formContents)
508 594 {
509 595 $updatedFormContents = (object) [];
510 596 $updatedPaths = [
@@ -548,9 +634,9 @@
548 634 }
549 635
550 636 public function getEmailConfig()
551 637 {
552 - \ignore_user_abort();
638 + Utilities::ignoreUserAbort();
553 639
554 640 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
555 641 $this->verifyAdminPermission();
556 642 $ipTool = new IpTool();
@@ -577,9 +663,9 @@
577 663 }
578 664
579 665 public function saveEmailConfig()
580 666 {
581 - \ignore_user_abort();
667 + Utilities::ignoreUserAbort();
582 668 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
583 669 $this->verifyAdminPermission();
584 670 GlobalHelper::requirePostMethod();
585 671 $ipTool = new IpTool();
@@ -815,9 +901,9 @@
815 901 * @return void
816 902 */
817 903 public function updateForm()
818 904 {
819 - \ignore_user_abort();
905 + Utilities::ignoreUserAbort();
820 906 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
821 907 $this->verifyAdminPermission();
822 908 GlobalHelper::requirePostMethod();
823 909 try {
@@ -1070,9 +1156,9 @@
1070 1156 }
1071 1157
1072 1158 public function duplicateAForm()
1073 1159 {
1074 - \ignore_user_abort();
1160 + Utilities::ignoreUserAbort();
1075 1161 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
1076 1162 $this->verifyAdminPermission();
1077 1163 GlobalHelper::requirePostMethod();
1078 1164 try {
@@ -1102,9 +1188,9 @@
1102 1188 }
1103 1189
1104 1190 public function importAForm()
1105 1191 {
1106 - \ignore_user_abort();
1192 + Utilities::ignoreUserAbort();
1107 1193 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
1108 1194 $this->verifyAdminPermission();
1109 1195 GlobalHelper::requirePostMethod();
1110 1196 try {
@@ -1383,9 +1469,9 @@
1383 1469 }
1384 1470
1385 1471 public function updateFormEntry()
1386 1472 {
1387 - \ignore_user_abort();
1473 + Utilities::ignoreUserAbort();
1388 1474 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
1389 1475 $this->verifyAdminPermission();
1390 1476 $formHandler = FormHandler::getInstance();
1391 1477 $sanitized_request = [
@@ -1740,9 +1826,13 @@
1740 1826 update_option('bitform_secret_api_key', sanitize_text_field($input->api_key));
1741 1827 $api_key = $input->api_key;
1742 1828 }
1743 1829 if (!$api_key) {
1744 - $api_key = hash('sha1', base64_encode(12345));
1830 + // The generated key authenticates the whole bitform/v1 data API. It was
1831 + // previously a constant (sha1 of a fixed string), so every install that
1832 + // never set one explicitly shared the same secret. Existing stored keys
1833 + // are left untouched — only first-time generation changes.
1834 + $api_key = wp_generate_password(64, false, false);
1745 1835 update_option('bitform_secret_api_key', $api_key);
1746 1836 }
1747 1837 wp_send_json_success($api_key, 200);
1748 1838 } else {