From cfd011345930581582cb5b777e682c925e1cfecb Mon Sep 17 00:00:00 2001 From: Alex Brea Date: Fri, 24 Apr 2026 13:41:09 +0200 Subject: [PATCH 1/8] fix error typo --- includes/admin/class-error-log.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index 8906e6a..37cb258 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -347,6 +347,11 @@ public function ajax_resend_entry() { wp_send_json_error( array( 'message' => __( 'Log entry not found', 'formscrm' ) ) ); } + // Check if we've reached max attempts. + if ( $log->resend_attempts >= 3 ) { + wp_send_json_error( array( 'message' => __( 'Max attempts reached', 'formscrm' ) ) ); + } + // Decode lead data. $lead_data = json_decode( $log->lead_data, true ); @@ -397,10 +402,11 @@ public function ajax_resend_entry() { } $this->increment_resend_attempts( $log_id ); + try { - $response = $api_class->create_entry( $settings, $lead_data ); + $response = $api_class->create_entry( $settings, $lead_data, $log_id ); - if ( isset( $response['success'] ) && $response['success'] ) { + if ( isset( $response['status'] ) && 'ok' === strtolower( $response['status'] ) ) { $this->update_status( $log_id, 'success' ); // Clear any scheduled retries. From ab636401052f019d4e81333cd1f1263836bd1e80 Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Wed, 29 Apr 2026 10:52:24 +0200 Subject: [PATCH 2/8] fix auto resend errors --- includes/admin/class-error-log.php | 90 +++++++++++++++++++----------- includes/admin/js/error-log.js | 17 +----- 2 files changed, 57 insertions(+), 50 deletions(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index 37cb258..83a93da 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -37,11 +37,38 @@ public function __construct() { add_action( 'wp_ajax_formscrm_resend_entry', array( $this, 'ajax_resend_entry' ) ); add_action( 'wp_ajax_formscrm_delete_log', array( $this, 'ajax_delete_log' ) ); add_action( 'wp_ajax_formscrm_clear_all_logs', array( $this, 'ajax_clear_all_logs' ) ); + add_action( 'wp_ajax_formscrm_export_csv', array( $this, 'ajax_export_csv' ) ); - // Hook for automatic retry cron. + // Hook for automatic retry via Action Scheduler. add_action( 'formscrm_retry_failed_entry', array( $this, 'retry_failed_entry' ), 10, 1 ); } + /** + * Schedule retry using Action Scheduler or WP-Cron fallback + * + * @param int $log_id Log ID to retry. + * @return void + */ + private function schedule_action_scheduler_retry( $log_id ) { + $retry_delay = HOUR_IN_SECONDS; + $timestamp = time() + $retry_delay; + + // Try Action Scheduler first. + if ( function_exists( 'as_schedule_single_action' ) ) { + try { + as_schedule_single_action( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); + formscrm_debug_message( 'Scheduled retry via Action Scheduler for log ' . $log_id . ' at ' . date( 'Y-m-d H:i:s', $timestamp ) ); + return; + } catch ( Exception $e ) { + formscrm_debug_message( 'Action Scheduler failed for log ' . $log_id . ': ' . $e->getMessage() . '. Fallback to WP-Cron.' ); + } + } + + // Fallback to WP-Cron. + wp_schedule_single_event( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); + formscrm_debug_message( 'Scheduled retry via WP-Cron for log ' . $log_id . ' at ' . date( 'Y-m-d H:i:s', $timestamp ) ); + } + /** * Check database version and create/update table if needed * @@ -128,8 +155,8 @@ public function insert_log( $crm, $error, $data, $url = '', $json = '', $form_in if ( $result ) { $log_id = $wpdb->insert_id; - // Schedule automatic retry in 1 hour. - $this->schedule_retry( $log_id ); + // Schedule automatic retry using Action Scheduler (if available). + $this->schedule_action_scheduler_retry( $log_id ); return $log_id; } @@ -347,11 +374,6 @@ public function ajax_resend_entry() { wp_send_json_error( array( 'message' => __( 'Log entry not found', 'formscrm' ) ) ); } - // Check if we've reached max attempts. - if ( $log->resend_attempts >= 3 ) { - wp_send_json_error( array( 'message' => __( 'Max attempts reached', 'formscrm' ) ) ); - } - // Decode lead data. $lead_data = json_decode( $log->lead_data, true ); @@ -401,8 +423,6 @@ public function ajax_resend_entry() { wp_send_json_error( array( 'message' => $error_msg ) ); } - $this->increment_resend_attempts( $log_id ); - try { $response = $api_class->create_entry( $settings, $lead_data, $log_id ); @@ -420,12 +440,6 @@ public function ajax_resend_entry() { } else { $error_message = isset( $response['message'] ) ? $response['message'] : __( 'Unknown error occurred', 'formscrm' ); - // Schedule next retry if we haven't reached max attempts. - $log = $this->get_log( $log_id ); - if ( $log && $log->resend_attempts < 3 ) { - $this->schedule_retry( $log_id ); - } - wp_send_json_error( array( 'message' => $error_message, @@ -433,12 +447,6 @@ public function ajax_resend_entry() { ); } } catch ( Exception $e ) { - // Schedule next retry if we haven't reached max attempts. - $log = $this->get_log( $log_id ); - if ( $log && $log->resend_attempts < 3 ) { - $this->schedule_retry( $log_id ); - } - wp_send_json_error( array( 'message' => $e->getMessage(), @@ -509,14 +517,8 @@ private function schedule_retry( $log_id ) { return; } - // Schedule retry in 1 hour. - $timestamp = time() + HOUR_IN_SECONDS; - - // Clear any existing scheduled retry for this log. - wp_clear_scheduled_hook( 'formscrm_retry_failed_entry', array( $log_id ) ); - - // Schedule new retry. - wp_schedule_single_event( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); + // Use Action Scheduler (same as initial schedule). + $this->schedule_action_scheduler_retry( $log_id ); } /** @@ -537,14 +539,20 @@ public function get_next_retry_time( $log_id ) { * @return void */ public function retry_failed_entry( $log_id ) { + formscrm_debug_message( 'retry_failed_entry called for log ' . $log_id ); + $log = $this->get_log( $log_id ); if ( ! $log || 'failed' !== $log->status ) { + formscrm_debug_message( 'Log ' . $log_id . ' not found or not failed status. Status: ' . ( $log ? $log->status : 'N/A' ) ); return; } + formscrm_debug_message( 'Log ' . $log_id . ' status is failed. Attempts: ' . $log->resend_attempts . '/3' ); + // Check if we've reached max attempts. if ( $log->resend_attempts >= 3 ) { + formscrm_debug_message( 'Log ' . $log_id . ' max attempts reached, stopping retries' ); return; } @@ -552,6 +560,7 @@ public function retry_failed_entry( $log_id ) { $lead_data = json_decode( $log->lead_data, true ); if ( ! $lead_data ) { + formscrm_debug_message( 'Log ' . $log_id . ' lead data decode failed' ); return; } @@ -559,6 +568,7 @@ public function retry_failed_entry( $log_id ) { $settings = formscrm_get_crm_settings( $log->form_type ); if ( empty( $settings ) ) { + formscrm_debug_message( 'Log ' . $log_id . ' CRM settings not found' ); return; } @@ -566,32 +576,41 @@ public function retry_failed_entry( $log_id ) { $api_class = formscrm_get_api_class( $log->crm_type ); if ( ! $api_class || ! method_exists( $api_class, 'create_entry' ) ) { + formscrm_debug_message( 'Log ' . $log_id . ' API class not found or missing create_entry method' ); return; } // Increment attempts before trying. $this->increment_resend_attempts( $log_id ); + formscrm_debug_message( 'Log ' . $log_id . ' incremented attempts' ); try { - $response = $api_class->create_entry( $settings, $lead_data ); + $response = $api_class->create_entry( $settings, $lead_data, $log_id ); + + formscrm_debug_message( 'Log ' . $log_id . ' create_entry response: ' . wp_json_encode( $response ) ); - if ( isset( $response['success'] ) && $response['success'] ) { + if ( isset( $response['status'] ) && 'ok' === strtolower( $response['status'] ) ) { // Success - update status. + formscrm_debug_message( 'Log ' . $log_id . ' response is success, updating status' ); $this->update_status( $log_id, 'success' ); // Clear any scheduled retries. wp_clear_scheduled_hook( 'formscrm_retry_failed_entry', array( $log_id ) ); } else { // Failed - check if we should schedule another retry. + formscrm_debug_message( 'Log ' . $log_id . ' response is failure, checking for next retry' ); $log = $this->get_log( $log_id ); if ( $log && $log->resend_attempts < 3 ) { + formscrm_debug_message( 'Log ' . $log_id . ' scheduling next retry. Current attempts: ' . $log->resend_attempts . '/3' ); $this->schedule_retry( $log_id ); } } } catch ( Exception $e ) { // Failed - check if we should schedule another retry. + formscrm_debug_message( 'Log ' . $log_id . ' exception: ' . $e->getMessage() ); $log = $this->get_log( $log_id ); if ( $log && $log->resend_attempts < 3 ) { + formscrm_debug_message( 'Log ' . $log_id . ' scheduling next retry after exception. Current attempts: ' . $log->resend_attempts . '/3' ); $this->schedule_retry( $log_id ); } } @@ -600,7 +619,10 @@ public function retry_failed_entry( $log_id ) { } // Initialize error log. +global $formscrm_error_log; +$formscrm_error_log = new FORMSCRM_Error_Log(); + +// Enqueue scripts only in admin. if ( is_admin() ) { - global $formscrm_error_log; - $formscrm_error_log = new FORMSCRM_Error_Log(); + // Scripts are handled by FORMSCRM_Error_Log_Page class. } diff --git a/includes/admin/js/error-log.js b/includes/admin/js/error-log.js index 6d31457..2312bcd 100644 --- a/includes/admin/js/error-log.js +++ b/includes/admin/js/error-log.js @@ -46,22 +46,7 @@ success: function(response) { if (response.success) { alert(response.data.message || 'Entry resent successfully'); - - // Update status in table. - const $row = $button.closest('tr'); - $row.find('.fcrm-status') - .removeClass('fcrm-status-error') - .addClass('fcrm-status-success') - .css({ - 'background': '#e8f5e9', - 'color': '#2e7d32' - }) - .text(formscrmErrorLog.successText || 'Success'); - - // Update attempts count. - const $attemptsCell = $row.find('td').eq(5); - const currentAttempts = parseInt($attemptsCell.text()); - $attemptsCell.text(currentAttempts + 1); + location.reload(); } else { alert('Error: ' + (response.data.message || 'Failed to resend entry')); } From 29e72c42295266d1d85627736f24bf29ef2e60ce Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Wed, 29 Apr 2026 11:03:32 +0200 Subject: [PATCH 3/8] fix linting errors --- includes/admin/class-error-log.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index 83a93da..7ee6eb7 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -57,7 +57,7 @@ private function schedule_action_scheduler_retry( $log_id ) { if ( function_exists( 'as_schedule_single_action' ) ) { try { as_schedule_single_action( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); - formscrm_debug_message( 'Scheduled retry via Action Scheduler for log ' . $log_id . ' at ' . date( 'Y-m-d H:i:s', $timestamp ) ); + formscrm_debug_message( 'Scheduled retry via Action Scheduler for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s', ) ); return; } catch ( Exception $e ) { formscrm_debug_message( 'Action Scheduler failed for log ' . $log_id . ': ' . $e->getMessage() . '. Fallback to WP-Cron.' ); @@ -66,7 +66,7 @@ private function schedule_action_scheduler_retry( $log_id ) { // Fallback to WP-Cron. wp_schedule_single_event( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); - formscrm_debug_message( 'Scheduled retry via WP-Cron for log ' . $log_id . ' at ' . date( 'Y-m-d H:i:s', $timestamp ) ); + formscrm_debug_message( 'Scheduled retry via WP-Cron for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s', ) ); } /** @@ -621,8 +621,3 @@ public function retry_failed_entry( $log_id ) { // Initialize error log. global $formscrm_error_log; $formscrm_error_log = new FORMSCRM_Error_Log(); - -// Enqueue scripts only in admin. -if ( is_admin() ) { - // Scripts are handled by FORMSCRM_Error_Log_Page class. -} From fea92681f9dfc0bcc4c5b529018c14ad83ec65f1 Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Wed, 29 Apr 2026 11:06:13 +0200 Subject: [PATCH 4/8] fix spaces --- includes/admin/class-error-log.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index 7ee6eb7..111e921 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -57,7 +57,7 @@ private function schedule_action_scheduler_retry( $log_id ) { if ( function_exists( 'as_schedule_single_action' ) ) { try { as_schedule_single_action( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); - formscrm_debug_message( 'Scheduled retry via Action Scheduler for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s', ) ); + formscrm_debug_message( 'Scheduled retry via Action Scheduler for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s' ) ); return; } catch ( Exception $e ) { formscrm_debug_message( 'Action Scheduler failed for log ' . $log_id . ': ' . $e->getMessage() . '. Fallback to WP-Cron.' ); @@ -66,7 +66,7 @@ private function schedule_action_scheduler_retry( $log_id ) { // Fallback to WP-Cron. wp_schedule_single_event( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); - formscrm_debug_message( 'Scheduled retry via WP-Cron for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s', ) ); + formscrm_debug_message( 'Scheduled retry via WP-Cron for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s' ) ); } /** From 2d77227e7fe1ae7b1458b1215ece0272c8bb8179 Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Thu, 30 Apr 2026 09:12:35 +0200 Subject: [PATCH 5/8] delete formscrm debug message --- includes/admin/class-error-log.php | 36 +++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index 111e921..e475709 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -57,16 +57,16 @@ private function schedule_action_scheduler_retry( $log_id ) { if ( function_exists( 'as_schedule_single_action' ) ) { try { as_schedule_single_action( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); - formscrm_debug_message( 'Scheduled retry via Action Scheduler for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s' ) ); return; } catch ( Exception $e ) { - formscrm_debug_message( 'Action Scheduler failed for log ' . $log_id . ': ' . $e->getMessage() . '. Fallback to WP-Cron.' ); + // Fallback to WP-Cron. + wp_schedule_single_event( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); + return; } } - // Fallback to WP-Cron. + // Fallback to WP-Cron if Action Scheduler not available. wp_schedule_single_event( $timestamp, 'formscrm_retry_failed_entry', array( $log_id ) ); - formscrm_debug_message( 'Scheduled retry via WP-Cron for log ' . $log_id . ' at ' . wp_date( 'Y-m-d H:i:s' ) ); } /** @@ -385,7 +385,7 @@ public function ajax_resend_entry() { $settings = formscrm_get_crm_settings( $log->form_type ); if ( empty( $settings ) ) { - formscrm_debug_message( 'ERROR: CRM settings not found for form type: ' . $log->form_type ); + wp_send_json_error( array( 'message' => __( 'CRM settings not found. Please configure the CRM connection in FormsCRM settings.', 'formscrm' ), @@ -539,20 +539,19 @@ public function get_next_retry_time( $log_id ) { * @return void */ public function retry_failed_entry( $log_id ) { - formscrm_debug_message( 'retry_failed_entry called for log ' . $log_id ); + $log = $this->get_log( $log_id ); if ( ! $log || 'failed' !== $log->status ) { - formscrm_debug_message( 'Log ' . $log_id . ' not found or not failed status. Status: ' . ( $log ? $log->status : 'N/A' ) ); return; } - formscrm_debug_message( 'Log ' . $log_id . ' status is failed. Attempts: ' . $log->resend_attempts . '/3' ); + // Check if we've reached max attempts. if ( $log->resend_attempts >= 3 ) { - formscrm_debug_message( 'Log ' . $log_id . ' max attempts reached, stopping retries' ); + return; } @@ -560,7 +559,7 @@ public function retry_failed_entry( $log_id ) { $lead_data = json_decode( $log->lead_data, true ); if ( ! $lead_data ) { - formscrm_debug_message( 'Log ' . $log_id . ' lead data decode failed' ); + return; } @@ -568,7 +567,7 @@ public function retry_failed_entry( $log_id ) { $settings = formscrm_get_crm_settings( $log->form_type ); if ( empty( $settings ) ) { - formscrm_debug_message( 'Log ' . $log_id . ' CRM settings not found' ); + return; } @@ -576,41 +575,38 @@ public function retry_failed_entry( $log_id ) { $api_class = formscrm_get_api_class( $log->crm_type ); if ( ! $api_class || ! method_exists( $api_class, 'create_entry' ) ) { - formscrm_debug_message( 'Log ' . $log_id . ' API class not found or missing create_entry method' ); + return; } // Increment attempts before trying. $this->increment_resend_attempts( $log_id ); - formscrm_debug_message( 'Log ' . $log_id . ' incremented attempts' ); + try { $response = $api_class->create_entry( $settings, $lead_data, $log_id ); - formscrm_debug_message( 'Log ' . $log_id . ' create_entry response: ' . wp_json_encode( $response ) ); - if ( isset( $response['status'] ) && 'ok' === strtolower( $response['status'] ) ) { // Success - update status. - formscrm_debug_message( 'Log ' . $log_id . ' response is success, updating status' ); + $this->update_status( $log_id, 'success' ); // Clear any scheduled retries. wp_clear_scheduled_hook( 'formscrm_retry_failed_entry', array( $log_id ) ); } else { // Failed - check if we should schedule another retry. - formscrm_debug_message( 'Log ' . $log_id . ' response is failure, checking for next retry' ); + $log = $this->get_log( $log_id ); if ( $log && $log->resend_attempts < 3 ) { - formscrm_debug_message( 'Log ' . $log_id . ' scheduling next retry. Current attempts: ' . $log->resend_attempts . '/3' ); + $this->schedule_retry( $log_id ); } } } catch ( Exception $e ) { // Failed - check if we should schedule another retry. - formscrm_debug_message( 'Log ' . $log_id . ' exception: ' . $e->getMessage() ); $log = $this->get_log( $log_id ); if ( $log && $log->resend_attempts < 3 ) { - formscrm_debug_message( 'Log ' . $log_id . ' scheduling next retry after exception. Current attempts: ' . $log->resend_attempts . '/3' ); + $this->schedule_retry( $log_id ); } } From f774c423423a2659e4beb449e23f40036e0703d4 Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Thu, 30 Apr 2026 09:16:53 +0200 Subject: [PATCH 6/8] fix linting --- includes/admin/class-error-log.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index e475709..da28529 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -385,7 +385,6 @@ public function ajax_resend_entry() { $settings = formscrm_get_crm_settings( $log->form_type ); if ( empty( $settings ) ) { - wp_send_json_error( array( 'message' => __( 'CRM settings not found. Please configure the CRM connection in FormsCRM settings.', 'formscrm' ), @@ -539,19 +538,14 @@ public function get_next_retry_time( $log_id ) { * @return void */ public function retry_failed_entry( $log_id ) { - - $log = $this->get_log( $log_id ); if ( ! $log || 'failed' !== $log->status ) { return; } - - // Check if we've reached max attempts. if ( $log->resend_attempts >= 3 ) { - return; } @@ -559,7 +553,6 @@ public function retry_failed_entry( $log_id ) { $lead_data = json_decode( $log->lead_data, true ); if ( ! $lead_data ) { - return; } @@ -567,7 +560,6 @@ public function retry_failed_entry( $log_id ) { $settings = formscrm_get_crm_settings( $log->form_type ); if ( empty( $settings ) ) { - return; } @@ -575,7 +567,6 @@ public function retry_failed_entry( $log_id ) { $api_class = formscrm_get_api_class( $log->crm_type ); if ( ! $api_class || ! method_exists( $api_class, 'create_entry' ) ) { - return; } @@ -588,17 +579,14 @@ public function retry_failed_entry( $log_id ) { if ( isset( $response['status'] ) && 'ok' === strtolower( $response['status'] ) ) { // Success - update status. - $this->update_status( $log_id, 'success' ); // Clear any scheduled retries. wp_clear_scheduled_hook( 'formscrm_retry_failed_entry', array( $log_id ) ); } else { // Failed - check if we should schedule another retry. - $log = $this->get_log( $log_id ); if ( $log && $log->resend_attempts < 3 ) { - $this->schedule_retry( $log_id ); } } @@ -606,7 +594,6 @@ public function retry_failed_entry( $log_id ) { // Failed - check if we should schedule another retry. $log = $this->get_log( $log_id ); if ( $log && $log->resend_attempts < 3 ) { - $this->schedule_retry( $log_id ); } } From f2736dbab64da9657ffb47a1a9505b5ecaf7ead0 Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Thu, 30 Apr 2026 09:18:08 +0200 Subject: [PATCH 7/8] fix increment_resend_attempts --- includes/admin/class-error-log.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/admin/class-error-log.php b/includes/admin/class-error-log.php index da28529..c45526e 100644 --- a/includes/admin/class-error-log.php +++ b/includes/admin/class-error-log.php @@ -573,7 +573,6 @@ public function retry_failed_entry( $log_id ) { // Increment attempts before trying. $this->increment_resend_attempts( $log_id ); - try { $response = $api_class->create_entry( $settings, $lead_data, $log_id ); From cdbd9bdda6fa5a74d84661d7f507144513e24fd0 Mon Sep 17 00:00:00 2001 From: Matias Quero Date: Thu, 30 Apr 2026 09:20:21 +0200 Subject: [PATCH 8/8] 4.3.4-beta.5 --- formscrm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formscrm.php b/formscrm.php index 7020c71..ccfaae8 100644 --- a/formscrm.php +++ b/formscrm.php @@ -3,7 +3,7 @@ * Plugin Name: FormsCRM * Plugin URI : https://close.technology/wordpress-plugins/formscrm/ * Description: Connects Forms with CRM, ERP and Email Marketing. - * Version: 4.3.4-beta.1 + * Version: 4.3.4-beta.5 * Author: CloseTechnology * Author URI: https://close.technology * Text Domain: formscrm