Skip to content

Commit

Permalink
3.44.1
Browse files Browse the repository at this point in the history
= 3.44.1 - 8/12/2024 =
* *Note:* Infusionsoft/Keap have removed the standard "Password" and "Username" fields from the new API, due to security concerns. To avoid errors when syncing passwords and usernames, WP Fusion will log a notice when these fields are detected and remove them from the sync. If you need to sync usernames and passwords, please create new custom text fields to store the data.
* Improved Ontraport error handling for duplicate and not found contacts
* Improved - (Infusionsoft / Keap) Added ISO 3166-1 country name conversion for "United States" to "USA" (previously only matched "United States of America")
* Fixed new Infusionsoft integration swapping the Billing and Shipping addresses
* Fixed new Infusionsoft integration not syncing dates in ISO8601 format
* Fixed new Infusionsoft integration not loading more than 10 available products
* Fixed error "PHP error: Uncaught TypeError: array_flip(): Argument #1 ($array) must be of type array" when syncing new custom fields with the new Infusionsoft REST API integration
* Fixed Groundhogg (same site) integration immediately loading custom fields that were added when creating a new contact
* Fixed date fields syncing to Groundhogg (REST API) as timestamps instead of dates
* Fixed tags that were removed in a FluentCRM automation (same site) that was triggered by WP Fusion applying a tag not triggering a sync back to the user's tags in WordPress
* Developers: `add_contact()` will now return a `WP_Error` if no fields are enabled for sync, instead of `false`
* Developers: The WP Fusion logs are now sorted by log ID instead of timestamp, to avoid confusion when changing the site's timezone

= 3.44.0.2 - 8/6/2024 =
* Fixed custom fields with spaces in the labels not migrating to the new Infusionsoft API field mapping
* Fixed "Unprocessable entity" errors when syncing custom fields with spaces in the label to Infusionsoft/Keap since 3.44.0
  • Loading branch information
verygoodplugins committed Aug 12, 2024
1 parent 9f561cf commit 823cabb
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 157 deletions.
2 changes: 1 addition & 1 deletion includes/admin/logging/class-log-table-list.php
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ protected function get_items_query_order() {
// $by = wc_clean( $_REQUEST['orderby'] );
$by = esc_attr( $_REQUEST['orderby'] );
} else {
$by = 'timestamp';
$by = 'log_id';
}
$by = esc_sql( $by );

Expand Down
3 changes: 1 addition & 2 deletions includes/crms/class-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,7 @@ public function __call( $method, $args ) {
$args[1] = false;

if ( empty( $args[0] ) ) {
wpf_log( 'notice', wpf_get_current_user_id(), 'Attempted to add contact with no fields enabled for sync.' );
return false; // no enabled fields.
return new WP_Error( 'error', 'Attempted to add contact with no fields enabled for sync.' );
}
} elseif ( 'update_contact' === $method && ( ! isset( $args[2] ) || true === $args[2] ) ) {

Expand Down
22 changes: 14 additions & 8 deletions includes/crms/fluentcrm/class-fluentcrm.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ class WPF_FluentCRM {
*/
public $edit_url = '';

/**
* Prevent syncing back tags that were just applied.
*
* @since 3.44.1
*
* @var bool Skip tag sync
*/
public $skip_tag_sync = false;

/**
* Get things started
*
Expand Down Expand Up @@ -327,9 +336,7 @@ public function get_tags( $contact_id ) {

public function apply_tags( $tags, $contact_id ) {

if ( ! defined( 'FLUENTCRM_SKIP_TAG_SYNC' ) ) {
define( 'FLUENTCRM_SKIP_TAG_SYNC', true ); // Prevents infinite loop (see contact_tags_added_removed() below).
}
$this->skip_tag_sync = true; // Prevents infinite loop (see contact_tags_added_removed() below).

$contact = FluentCrmApi( 'contacts' )->getContact( $contact_id );

Expand All @@ -352,9 +359,7 @@ public function apply_tags( $tags, $contact_id ) {

public function remove_tags( $tags, $contact_id ) {

if ( ! defined( 'FLUENTCRM_SKIP_TAG_SYNC' ) ) {
define( 'FLUENTCRM_SKIP_TAG_SYNC', true ); // Prevents infinite loop (see contact_tags_added_removed() below).
}
$this->skip_tag_sync = true; // Prevents infinite loop (see contact_tags_added_removed() below).

$contact = FluentCrmApi( 'contacts' )->getContact( $contact_id );

Expand Down Expand Up @@ -571,8 +576,9 @@ public function load_contacts( $tag_id = false ) {
*/
public function contact_tags_added_removed( $tags, $subscriber ) {

if ( defined( 'FLUENTCRM_SKIP_TAG_SYNC' ) && ! doing_action( 'fluentcrm_funnel_sequence_handle_add_contact_to_tag' ) && ! doing_action( 'fluentcrm_funnel_sequence_handle_detach_contact_from_tag' ) ) {
if ( $this->skip_tag_sync && ! doing_action( 'fluentcrm_funnel_sequence_handle_add_contact_to_tag' ) && ! doing_action( 'fluentcrm_funnel_sequence_handle_detach_contact_from_tag' ) ) {
// Don't sync tag changes if we've just applied them and aren't currently in a funnel sequence.
$this->skip_tag_sync = false; // allow it to repeat after this.
return;
}

Expand All @@ -594,7 +600,7 @@ public function contact_tags_added_removed( $tags, $subscriber ) {

if ( $user_id ) {

if ( defined( 'FLUENTCRM_SKIP_TAG_SYNC' ) ) {
if ( $this->skip_tag_sync ) {

// If we're currently in the process of applying tags, then we need to wait
// until WPF_User::apply_tags() has updated the usermeta before we can load them.
Expand Down
22 changes: 22 additions & 0 deletions includes/crms/groundhogg-rest/class-groundhogg-rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ public function init() {
// Webhooks.
add_filter( 'wpf_crm_post_data', array( $this, 'format_post_data' ) );

// Data formats.
add_filter( 'wpf_format_field_value', array( $this, 'format_field_value' ), 10, 2 );

// Add tracking code to footer.
// add_action( 'wp_enqueue_scripts', array( $this, 'tracking_code' ) );

Expand Down Expand Up @@ -161,6 +164,25 @@ public function format_post_data( $post_data ) {

}

/**
* Formats user entered data to match Groundhogg field formats.
*
* @since 3.44.1
*
* @param mixed $value The field data.
* @param string $field_type The field type.
* @param string $field The field in the CRM.
* @return mixed The field value.
*/
public function format_field_value( $value, $field_type ) {

if ( 'date' === $field_type ) {
$value = gmdate( 'Y-m-d H:i:s', $value );
}

return $value;
}


/**
* Gets params for API calls.
Expand Down
10 changes: 7 additions & 3 deletions includes/crms/groundhogg/class-groundhogg.php
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ public function add_contact( $data ) {
}

// Prevent looping.
remove_action( 'groundhogg/admin/contact/save', array( $this, 'contact_post_update' ), 10, 2 );
remove_action( 'groundhogg/admin/contact/save', array( $this, 'contact_post_update' ) );

$contact = new \Groundhogg\Contact( $data );

Expand All @@ -674,12 +674,16 @@ public function add_contact( $data ) {
unset( $data['last_name'] );
unset( $data['email'] );

foreach ( $data as $key => $value ) {
// Prevent looping.
remove_action( 'groundhogg/meta/contact/update', array( $this, 'contact_post_update_fallback' ) );

foreach ( $data as $key => $value ) {
$contact->update_meta( $key, $value );

}

// Add it back in case the benchmark triggers custom field changes.
add_action( 'groundhogg/meta/contact/update', array( $this, 'contact_post_update_fallback' ), 10, 4 );

// Trigger user created benchmarks.

if ( $user ) {
Expand Down
10 changes: 0 additions & 10 deletions includes/crms/infusionsoft/admin/infusionsoft-fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@
'crm_field' => 'Nickname',
);

$infusionsoft_fields['user_login'] = array(
'crm_label' => 'Username',
'crm_field' => 'Username',
);

$infusionsoft_fields['user_email'] = array(
'crm_label' => 'Email',
'crm_field' => 'Email',
Expand All @@ -38,11 +33,6 @@
'crm_field' => 'EmailAddress3',
);

$infusionsoft_fields['user_pass'] = array(
'crm_label' => 'Password',
'crm_field' => 'Password',
);

$infusionsoft_fields['country'] = array(
'crm_label' => 'Country',
'crm_field' => 'Country',
Expand Down
128 changes: 73 additions & 55 deletions includes/crms/infusionsoft/class-infusionsoft-app.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ class WPF_Infusionsoft_App {
*/
public $params;

public $pending_orders = array();

/**
* @var array The mapping of old field names to new field names.
*/
public $fields_mapping = array(
'ProductName' => 'product_name',
'ProductPrice' => 'product_price',
'ProductDesc' => 'product_desc',
'Id' => 'id',
'Sku' => 'sku',
'Referral' => 'affiliate',
Expand Down Expand Up @@ -145,6 +148,9 @@ private function remap_array_fields( $data, $fields_mapping = array() ) {
/**
* Creates a blank order.
*
* We can't create a blank order anymore so let's just return the next expected order ID
* and create the order in manualPmt.
*
* @since 3.44.0
*
* @param int $contact_id The contact ID.
Expand All @@ -156,56 +162,38 @@ private function remap_array_fields( $data, $fields_mapping = array() ) {
*/
public function blankOrder( $contact_id, $desc, $order_date, $lead_aff, $sale_aff ) {

// Add fake product as we can't create a blank order or empty order_items in rest api.
$rest_product_id = wpf_get_option( 'rest_product_id' );
if ( empty( $rest_product_id ) ) {
$rest_product_id = $this->dsAdd(
'Product',
array(
'ProductName' => 'wpf_rest_product',
'ProductPrice' => 0,
)
);
wp_fusion()->settings->set( 'rest_product_id', $rest_product_id );
$response = wp_safe_remote_get( $this->url . 'orders/?limit=1', $this->params );

if ( is_wp_error( $response ) ) {
return $response;
}

$params = $this->params;
$order_date = date( 'Y-m-d\TH:i:s\Z', strtotime( $order_date ) );
$response = json_decode( wp_remote_retrieve_body( $response ), true );

$data = array(
if ( ! empty( $response['orders'] ) ) {
$new_order_id = $response['orders'][0]['id'] + 1;
} else {
// New account.
$new_order_id = 1;
}

$this->pending_orders[ $new_order_id ] = array(
'contact_id' => $contact_id,
'order_title' => $desc,
'order_date' => $order_date,
'order_items' => array(
array(
'product_id' => $rest_product_id,
'quantity' => 0,
),
),
'order_date' => gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $order_date ) ),
'order_items' => array(),
'order_type' => 'Online',
);

if ( $lead_aff ) {
$data['lead_affiliate_id'] = $lead_aff;
$this->pending_orders[ $new_order_id ]['lead_affiliate_id'] = $lead_aff;
}
if ( $sale_aff ) {
$data['sales_affiliate_id'] = $sale_aff;
$this->pending_orders[ $new_order_id ]['sales_affiliate_id'] = $sale_aff;
}

$params['body'] = wp_json_encode( $data );
$request = $this->url . 'orders/';
$response = wp_safe_remote_post( $request, $params );
return $new_order_id;

if ( is_wp_error( $response ) ) {
return $response;
}

$response = json_decode( wp_remote_retrieve_body( $response ), true );

// Save fake order item to remove it later.
wp_fusion()->settings->set( 'rest_order_item', $response['order_items'][0]['id'] );

return $response['id'];
}

/**
Expand Down Expand Up @@ -271,8 +259,32 @@ public function dsLoad( $table, $id, $return_fields ) {
* @return bool|WP_Error True on success, WP_Error on failure.
*/
public function manualPmt( $invoice_id = '', $amt = '', $payment_date = '', $payment_type = '', $payment_description = '', $bypass_commissions = false ) {

$params = $this->params;

// If there's a pending order, create it now in a single API call.

if ( isset( $this->pending_orders[ $invoice_id ] ) ) {

$data = $this->pending_orders[ $invoice_id ];

$params['body'] = wp_json_encode( $data );
$request = $this->url . 'orders/';

$response = wp_safe_remote_post( $request, $params );

if ( is_wp_error( $response ) ) {
return $response;
}

$response = json_decode( wp_remote_retrieve_body( $response ), true );

unset( $this->pending_orders[ $invoice_id ] );

$invoice_id = $response['id'];

}

if ( strpos( strtolower( $payment_type ), 'cash' ) !== false ) {
$payemnt_type = 'CASH';
} elseif ( strpos( strtolower( $payment_type ), 'check' ) !== false ) {
Expand Down Expand Up @@ -314,19 +326,9 @@ public function manualPmt( $invoice_id = '', $amt = '', $payment_date = '', $pay
* @param int $qty The quantity of items.
* @param string $desc The description of the item.
* @param string $notes Any notes for the item.
* @return boolean
* @return bool|WP_Error True or error on failure.
*/
public function addOrderItem( $order_id, $product_id, $type, $price, $qty, $desc = '', $notes = '' ) {
$params = $this->params;

// Remove fake rest product.
$rest_order_item = wpf_get_option( 'rest_order_item' );
if ( $rest_order_item ) {
$params['method'] = 'DELETE';
$request = $this->url . 'orders/' . $order_id . '/items/' . $rest_order_item . '';
$result = wp_safe_remote_post( $request, $params );
$response = json_decode( wp_remote_retrieve_body( $result ), true );
}

$data = array(
'product_id' => $product_id,
Expand All @@ -335,13 +337,24 @@ public function addOrderItem( $order_id, $product_id, $type, $price, $qty, $desc
'description' => $desc,
);

$params['body'] = wp_json_encode( $data );
$params['method'] = 'POST';
$request = $this->url . 'orders/' . $order_id . '/items/';
$response = wp_safe_remote_post( $request, $params );
if ( isset( $this->pending_orders[ $order_id ] ) ) {

if ( is_wp_error( $response ) ) {
return $response;
// Pending order
$this->pending_orders[ $order_id ]['order_items'][] = $data;

} else {

// Send the API call.

$params = $this->params;
$params['body'] = wp_json_encode( $data );
$params['method'] = 'POST';
$request = $this->url . 'orders/' . $order_id . '/items/';
$response = wp_safe_remote_post( $request, $params );

if ( is_wp_error( $response ) ) {
return $response;
}
}

return true;
Expand All @@ -359,14 +372,19 @@ public function addOrderItem( $order_id, $product_id, $type, $price, $qty, $desc
* @param array $r_fields The fields to retrieve.
* @return mixed
*/
public function dsQuery( $t_name, $limit = 1000, $page = 1, $query = array(), $r_fields = array() ) {
$request = $this->url . strtolower( $t_name ) . 's/';
public function dsQuery( $t_name, $limit = 1000, $page = 0, $query = array(), $r_fields = array() ) {

$offset = $page * $limit;

$request = $this->url . strtolower( $t_name ) . 's/?limit=' . $limit . '&offset=' . $offset;
$response = wp_safe_remote_get( $request, $this->params );

if ( is_wp_error( $response ) ) {
return $response;
}

$response = json_decode( wp_remote_retrieve_body( $response ), true );

if ( ! isset( $response['products'] ) || empty( $response['products'] ) ) {
return array();
}
Expand Down
Loading

0 comments on commit 823cabb

Please sign in to comment.