d' );
$contact->set_field_by_slug( 'automation-completed', $completed_aids );
$contact->set_field_by_slug( 'automation-entered', $entered_aids );
$contact->save_fields();
$processed ++;
update_option( 'bwfan_automation_completed_processed', $processed );
}
}
/**
* @param $contact BWFCRM_Contact
* @param $new_aids
* @param $field_slug
*
* @return false|string
*/
public static function get_automation_contact_field_value( $contact, $new_aids, $field_slug ) {
$automation_aids = $contact->get_field_by_slug( $field_slug );
$automation_aids = json_decode( $automation_aids, true );
$automation_aids = ( ! empty( $automation_aids ) && is_array( $automation_aids ) ) ? $automation_aids : array();
$automation_aids = array_merge( $automation_aids, $new_aids );
$automation_aids = array_unique( $automation_aids );
sort( $automation_aids );
$automation_aids = wp_json_encode( $automation_aids );
return $automation_aids;
}
/**
* Works with pro version only
*
* @return void
*/
public static function bwfan_store_automation_active_ids() {
$max_count = get_option( 'bwfan_max_active_automation', 0 );
$processed = get_option( 'bwfan_active_automation_processed', 0 );
global $wpdb;
$query = "SELECT `cid`, GROUP_CONCAT(`aid`) AS `aid` FROM `{$wpdb->prefix}bwfan_automation_contact` WHERE `ID` <= {$max_count} GROUP BY `cid` ORDER BY `cid` ASC LIMIT {$processed},20";
$automations = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $automations ) ) {
delete_option( 'bwfan_max_active_automation' );
delete_option( 'bwfan_active_automation_processed' );
bwf_unschedule_actions( 'bwfan_store_automation_active_ids' );
return;
}
$start_time = time();
foreach ( $automations as $data ) {
if ( ( time() - $start_time ) > 10 ) {
return;
}
$aids = explode( ',', $data['aid'] );
$aids = array_unique( $aids );
$cid = $data['cid'];
/** CRM contact object */
$contact = new BWFCRM_Contact( $cid );
if ( ! $contact->is_contact_exists() ) {
$processed ++;
update_option( 'bwfan_active_automation_processed', $processed );
continue;
}
/** Get automation ids in entered automation */
$entered_aids = self::get_automation_contact_field_value( $contact, $aids, 'automation-entered' );
/** Get automation ids in active automation */
$active_aids = self::get_automation_contact_field_value( $contact, $aids, 'automation-active' );
$contact->set_field_by_slug( 'automation-active', $active_aids );
$contact->set_field_by_slug( 'automation-entered', $entered_aids );
$contact->save_fields();
$processed ++;
update_option( 'bwfan_active_automation_processed', $processed );
}
}
public static function get_contact_notes_type() {
return apply_filters( 'bwfcrm_contact_note_types', array(
array(
'value' => 'billing',
'label' => __( 'Billing', 'wp-marketing-automations' ),
),
array(
'value' => 'shipping',
'label' => __( 'Shipping', 'wp-marketing-automations' ),
),
array(
'value' => 'refund',
'label' => __( 'Refund', 'wp-marketing-automations' ),
),
array(
'value' => 'subscription',
'label' => __( 'Subscription', 'wp-marketing-automations' ),
),
array(
'value' => 'feedback',
'label' => __( 'Feedback', 'wp-marketing-automations' ),
),
array(
'value' => 'log',
'label' => __( 'Log', 'wp-marketing-automations' ),
),
array(
'value' => 'others',
'label' => __( 'Others', 'wp-marketing-automations' ),
),
) );
}
/**
* Checks if v1 older automation is active or not for functioning
*
* @return bool
*/
public static function is_automation_v1_active() {
if ( defined( 'BWFAN_AUTOMATION_V1_DISABLE' ) && true === BWFAN_AUTOMATION_V1_DISABLE ) {
return false;
}
$active = get_option( 'bwfan_automation_v1', 1 );
return ( 1 === intval( $active ) ) ? true : false;
}
public static function bulk_contact_automation_end( $option_key, $args, $scheduler_action ) {
$data = get_option( $option_key, [] );
if ( empty( $data ) ) {
delete_option( $option_key );
bwf_unschedule_actions( $scheduler_action, $args );
return;
}
$updated_data = $data;
$start_time = time();
foreach ( $data as $key => $id ) {
if ( ( time() - $start_time ) > 10 ) {
return;
}
$automation_contact = BWFAN_Model_Automation_Contact::get( $id );
/** End Automation */
self::end_v2_automation( 0, $automation_contact, 'manually' );
/** Update status as success for any step trail where status was waiting */
BWFAN_Model_Automation_Contact_Trail::update_all_step_trail_status_complete( $automation_contact['trail'] );
self::update_automation_contact_fields( $automation_contact['cid'], $automation_contact['aid'] );
unset( $updated_data[ $key ] );
update_option( $option_key, $updated_data, false );
}
}
public static function bwfan_automation_contact_bulk_action( $dynamic_str, $aid, $action, $status ) {
if ( 'end' === $action ) {
$option_key = "bwfan_bulk_automation_contact_end_{$dynamic_str}";
$args = array( 'key' => $dynamic_str, 'aid' => $aid, 'action' => $action, 'status' => $status );
$scheduler_action = 'bwfan_automation_contact_bulk_action';
self::bulk_contact_automation_end( $option_key, $args, $scheduler_action );
return;
}
$option_key = "bwfan_bulk_automation_contact_{$action}_{$dynamic_str}";
$a_cids = get_option( $option_key, [] );
if ( empty( $a_cids ) ) {
delete_option( $option_key );
bwf_unschedule_actions( 'bwfan_automation_contact_bulk_action', [ 'key' => $dynamic_str, 'aid' => $aid, 'action' => $action, 'status' => $status ] );
return;
}
if ( 'completed' === $status && 'rerun' !== $action ) {
$action = 'delete_complete';
}
self::perform_bulk_action( $a_cids, $option_key, $action, $status );
}
public static function perform_bulk_action( $a_cids, $option_key, $action = '', $status = '' ) {
$updated_a_cids = $a_cids;
$start_time = time();
$batch_size = 20;
while ( ( time() - $start_time ) < 10 ) {
/** Get first 20 automation contacts */
$a_cids = ( count( $a_cids ) > $batch_size ) ? array_slice( $a_cids, 0, $batch_size ) : $a_cids;
if ( empty( $a_cids ) ) {
delete_option( $option_key );
return;
}
$a_cids = array_filter( $a_cids, 'intval' );
$stringPlaceholders = array_fill( 0, count( $a_cids ), '%d' );
$stringPlaceholders = implode( ', ', $stringPlaceholders );
global $wpdb;
if ( 'delete_complete' === $action || 'completed' === $status ) {
$query = $wpdb->prepare( " SELECT `ID`,`cid`,`aid`,`trail`,`event`,`data` FROM {$wpdb->prefix}bwfan_automation_complete_contact WHERE `ID` IN ( $stringPlaceholders ) ", $a_cids );// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
} else {
$query = $wpdb->prepare( " SELECT `ID`,`cid`,`aid`,`trail` FROM {$wpdb->prefix}bwfan_automation_contact WHERE `ID` IN ( $stringPlaceholders )", $a_cids );// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
}
try {
BWFAN_Common::log_test_data( $option_key . ' - ' . $query, __FUNCTION__ );
$result = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
} catch ( Error $e ) {
delete_option( $option_key );
return;
}
if ( empty( $result ) ) {
$updated_a_cids = array_diff( $updated_a_cids, $a_cids );
sort( $updated_a_cids );
update_option( $option_key, $updated_a_cids, false );
$a_cids = $updated_a_cids;
continue;
}
$ids = array_column( $result, 'ID' );
/** Remove automation contact id if not in data */
$remove_ids = array_diff( $a_cids, $ids );
if ( ! empty( $remove_ids ) ) {
$updated_a_cids = array_diff( $updated_a_cids, $remove_ids );
sort( $updated_a_cids );
update_option( $option_key, $updated_a_cids, false );
}
$trails = array_column( $result, 'trail' );
switch ( true ) {
case ( 'delete' === $action || 'delete_complete' === $action ):
self::delete_automations( $ids, $trails, $action, $result );
break;
case ( 'paused' === $action ) :
BWFAN_Model_Automation_Contact::update_status_by_multiple_ids( $ids, 3 );
break;
case ( 'unpaused' === $action ):
BWFAN_Model_Automation_Contact::update_status_by_multiple_ids( $ids );
break;
case ( 'retry' === $action ):
BWFAN_Model_Automation_Contact::update_status_by_multiple_ids( $ids, 6 );
break;
case ( 'run_now' === $action ):
BWFAN_Model_Automation_Contact::update_e_time_col_of_ids( $ids );
break;
case ( 'rerun' === $action || 're_run' === $action ):
self::insert_automations( $result );
break;
case ( 'startbegin' === $action ):
$status = 1;
$e_time = current_time( 'timestamp', 1 );
self::update_automation_status( $ids, $status, $trails, $e_time, true );
break;
}
/** Remove automation contact id from data after updating the status of automation and trail */
$updated_a_cids = array_diff( $updated_a_cids, $ids );
if ( empty( $updated_a_cids ) ) {
delete_option( $option_key );
return;
}
sort( $updated_a_cids );
update_option( $option_key, $updated_a_cids, false );
/** Assign updated automation contact */
$a_cids = $updated_a_cids;
}
}
public static function update_automation_status( $ids, $status, $trails, $e_time = '', $last = false ) {
BWFAN_Model_Automation_Contact::update_status_by_multiple_ids( $ids, $status, $e_time, $last );
if ( 1 === $status ) {
BWFAN_Model_Automation_Contact_Trail::update_multiple_trail_status( $trails, 0 );
}
}
public static function delete_automations( $ids, $trails, $action = '', $automation_data = [] ) {
global $wpdb;
$table_name = "{$wpdb->prefix}bwfan_automation_contact";
if ( 'delete_complete' === $action ) {
$table_name = "{$wpdb->prefix}bwfan_automation_complete_contact";
}
if ( ! empty( $ids ) ) {
$ids = array_filter( $ids, 'intval' );
$stringPlaceholders = array_fill( 0, count( $ids ), '%d' );
$stringPlaceholders = implode( ', ', $stringPlaceholders );
$query = $wpdb->prepare( "DELETE FROM {$table_name} WHERE `ID` IN ( $stringPlaceholders )", $ids );// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
if ( ! empty( $trails ) ) {
$trails = array_filter( $trails );
$placeholder = array_fill( 0, count( $trails ), '%s' );
$placeholder = implode( ', ', $placeholder );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}bwfan_automation_contact_trail WHERE tid IN ( $placeholder )", $trails ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
}
if ( ! class_exists( 'BWFCRM_Contact' ) ) {
/** Works with pro version only */
return;
}
foreach ( $automation_data as $data ) {
self::maybe_remove_aid_from_contact_fields( $data['cid'], $data['aid'] );
}
}
/**
* Get automation active and completed count then remove from contact fields
*/
public static function maybe_remove_aid_from_contact_fields( $cid, $aid ) {
if ( ! class_exists( 'BWFCRM_Contact' ) ) {
/** Works with pro version only */
return;
}
/** Get active automation contact count */
$active = BWFAN_Model_Automation_Contact::get_automation_count_by_cid( $cid, $aid );
/** if active count is 0 then remove automation id from automation completed field */
if ( 0 === absint( $active ) ) {
self::remove_aid_from_contact_field( $cid, $aid, 'automation-active' );
}
/**Get completed automation contact count */
$completed = BWFAN_Model_Automation_Complete_Contact::get_automation_count_by_cid( $cid, $aid );
/** if active and completed count is 0 then remove automation id from automation entered field */
$is_entered = absint( $active ) + absint( $completed );
if ( 0 === $is_entered ) {
self::remove_aid_from_contact_field( $cid, $aid, 'automation-entered' );
}
/** if completed count is 0 then remove automation id from automation completed field */
if ( 0 === absint( $completed ) ) {
self::remove_aid_from_contact_field( $cid, $aid, 'automation-completed' );
}
}
/**
* Remove automation id from contact fields
*/
public static function remove_aid_from_contact_field( $cid, $removed_aid, $field_slg ) {
$contact = new BWFCRM_Contact( $cid );
if ( ! $contact->is_contact_exists() ) {
return;
}
$automations = $contact->get_field_by_slug( $field_slg );
$automation_ids = json_decode( $automations, true );
$automation_ids = ( ! empty( $automation_ids ) && is_array( $automation_ids ) ) ? $automation_ids : array();
if ( empty( $automation_ids ) ) {
return;
}
$aid = (string) $removed_aid;
/**remove automation from field */
$aid_index = array_search( $aid, $automation_ids );
if ( false !== $aid_index ) {
unset( $automation_ids[ $aid_index ] );
}
sort( $automation_ids );
$automation_ids = wp_json_encode( $automation_ids, true );
$contact->set_field_by_slug( $field_slg, $automation_ids );
$contact->save_fields();
}
public static function bwfan_bulk_action( $option_key, $type, $cart_type = '' ) {
$option_key = "bwfan_bulk_action_{$option_key}";
$ids = get_option( $option_key, [] );
if ( empty( $ids ) ) {
delete_option( $option_key );
bwf_unschedule_actions( "bwfan_bulk_action", [ 'key' => $option_key, 'type' => $type ] );
return;
}
$updated_ids = $ids;
$start_time = time();
$batch_size = 20;
while ( ( time() - $start_time ) < 15 ) {
/** Get first 20 ids */
$ids = ( count( $ids ) > $batch_size ) ? array_slice( $ids, 0, $batch_size ) : $ids;
$ids = array_filter( $ids, 'intval' );
$selected_ids = implode( ', ', $ids );
$stringPlaceholders = array_fill( 0, count( $ids ), '%d' );
$stringPlaceholders = implode( ', ', $stringPlaceholders );
global $wpdb;
switch ( true ) {
case ( 'tag' === $type || 'list' === $type || 'audience' === $type ):
$query = "DELETE FROM {$wpdb->prefix}bwfan_terms WHERE `ID` IN ( $stringPlaceholders )";
$wpdb->query( $wpdb->prepare( $query, $ids ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
break;
case ( 'automation_v1' === $type || 'automation_v2' === $type ):
BWFAN_Core()->automations->delete_automation( $ids );
BWFAN_Core()->automations->delete_automationmeta( $ids );
if ( 'automation_v2' === $type ) {
self::delete_automation_v2_migrations( $ids );
}
if ( 'automation_v1' === $type ) {
self::delete_automation_v1_migrations( $ids );
}
break;
case ( 'broadcast' === $type ):
$query = "DELETE FROM {$wpdb->prefix}bwfan_broadcast WHERE `id` IN ( $stringPlaceholders )";
$wpdb->query( $wpdb->prepare( $query, $ids ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
/** Remove parent from child broadcasts */
if ( bwfan_is_autonami_pro_active() && method_exists( 'BWFAN_Model_Broadcast', 'remove_parent_from_child' ) ) {
BWFAN_Model_Broadcast::remove_parent_from_child( $ids );
}
break;
case ( 'template' === $type ):
BWFAN_Model_Templates::bwf_delete_template( $ids );
break;
case ( 'form' === $type ):
$query = "DELETE FROM {$wpdb->prefix}bwfan_form_feeds WHERE `ID` IN ( $stringPlaceholders )";
$wpdb->query( $wpdb->prepare( $query, $ids ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
break;
case ( 'cart' === $type ):
if ( 'recovered' === $cart_type ) {
BWFAN_Recoverable_Carts::delete_recovered_carts( $selected_ids );
} else {
$query = "DELETE FROM {$wpdb->prefix}bwfan_abandonedcarts WHERE `ID` IN ($stringPlaceholders )";
$wpdb->query( $wpdb->prepare( $query, $ids ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
break;
case ( 'recovered-cart' === $type ):
$query = "DELETE FROM {$wpdb->prefix}postmeta WHERE (`meta_key` = '_bwfan_recovered_ab_id' OR `meta_key` = '_bwfan_ab_cart_recovered_a_id') AND `post_id` IN ( $stringPlaceholders )";
$wpdb->query( $wpdb->prepare( $query, $ids ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
break;
}
/** Remove id from data after deleting */
$updated_ids = array_diff( $updated_ids, $ids );
if ( empty( $updated_ids ) ) {
delete_option( $option_key );
return;
}
sort( $updated_ids );
update_option( $option_key, $updated_ids, false );
/** Assign updated ids */
$ids = $updated_ids;
}
return $ids;
}
public static function delete_automation_v2_migrations( $aids ) {
BWFAN_Model_Automation_Step::delete_steps_by_aid( $aids );
BWFAN_Model_Automation_Contact::delete_automation_contact_by_aid( $aids );
BWFAN_Model_Automation_Complete_Contact::delete_automation_contact_by_aid( $aids );
BWFAN_Model_Automation_Contact_Trail::delete_automation_trail_by_id( $aids );
}
public static function delete_automation_v1_migrations( $aids ) {
BWFAN_Core()->tasks->delete_tasks( array(), $aids );
BWFAN_Core()->logs->delete_logs( array(), $aids );
BWFAN_Core()->automations->set_automation_id( $aids );
}
/**
* @return void
*/
public static function delete_expired_dynamic_coupons() {
global $wpdb;
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$coupons = $wpdb->get_results( $wpdb->prepare( "
SELECT m1.post_id as id
FROM {$wpdb->prefix}postmeta as m1
LEFT JOIN {$wpdb->prefix}postmeta as m2
ON m1.post_id = m2.post_id
WHERE m1.meta_key = %s
AND m1.meta_value = %d
AND m2.meta_key = %s
AND TIMESTAMPDIFF(MINUTE,m2.meta_value,UTC_TIMESTAMP) > %d
LIMIT %d
", '_is_bwfan_coupon', 1, 'expiry_date', 0, 20 ) );
if ( empty( $coupons ) ) {
bwf_unschedule_actions( 'bwfan_delete_expired_coupons' );
return;
}
foreach ( $coupons as $coupon ) {
wp_delete_post( $coupon->id, true );
}
}
public static function append_extra_url_arguments( $url, $url_utm_args = [] ) {
$utm_campaign = filter_input( INPUT_GET, 'utm_campaign' );
if ( ! is_null( $utm_campaign ) && ! empty( $utm_campaign ) ) {
$url_utm_args['utm_campaign'] = $utm_campaign;
}
$utm_term = filter_input( INPUT_GET, 'utm_term' );
if ( ! is_null( $utm_term ) && ! empty( $utm_term ) ) {
$url_utm_args['utm_term'] = $utm_term;
}
$utm_source = filter_input( INPUT_GET, 'utm_source' );
if ( ! is_null( $utm_source ) && ! empty( $utm_source ) ) {
$url_utm_args['utm_source'] = $utm_source;
}
$utm_content = filter_input( INPUT_GET, 'utm_content' );
if ( ! is_null( $utm_content ) && ! empty( $utm_content ) ) {
$url_utm_args['utm_content'] = $utm_content;
}
$utm_medium = filter_input( INPUT_GET, 'utm_medium' );
if ( ! is_null( $utm_medium ) && ! empty( $utm_medium ) ) {
$url_utm_args['utm_medium'] = $utm_medium;
}
$url = add_query_arg( $url_utm_args, $url );
return $url;
}
public static function get_contact_columns() {
$columns = get_user_meta( get_current_user_id(), '_bwfan_contact_columns_v2', true );
if ( is_array( $columns ) ) {
return $columns;
}
$wc_columns = [];
$default_columns = [
[
'country' => 'Country/Region',
'label' => __( 'Country/Region', 'wp-marketing-automations' ),
'groupKey' => 'geography',
'groupLabel' => __( 'Geography', 'wp-marketing-automations' ),
],
[
'state' => 'State',
'label' => __( 'State', 'wp-marketing-automations' ),
'groupKey' => 'geography',
'groupLabel' => __( 'Geography', 'wp-marketing-automations' ),
],
[
'tags' => 'Tags',
'label' => __( 'Tags', 'wp-marketing-automations' ),
'groupKey' => 'segments',
'groupLabel' => __( 'Segments', 'wp-marketing-automations' ),
],
[
'lists' => __( 'Lists', 'wp-marketing-automations' ),
'label' => 'Lists',
'groupKey' => 'segments',
'groupLabel' => __( 'Segments', 'wp-marketing-automations' ),
]
];
if ( class_exists( 'WooCommerce' ) ) {
$wc_columns = [
[
'total_order_count' => 'Orders Count',
'label' => __( 'Orders Count', 'wp-marketing-automations' ),
'groupKey' => 'woocommerce',
'groupLabel' => __( 'WooCommerce', 'wp-marketing-automations' ),
],
[
'total_order_value' => 'Total Revenue',
'label' => __( 'Total Revenue', 'wp-marketing-automations' ),
'groupKey' => 'woocommerce',
'groupLabel' => __( 'WooCommerce', 'wp-marketing-automations' ),
],
[
'l_order_date' => 'Last Order Date',
'label' => __( 'Last Order Date', 'wp-marketing-automations' ),
'groupKey' => 'woocommerce',
'groupLabel' => __( 'WooCommerce', 'wp-marketing-automations' ),
],
];
}
return array_merge( $default_columns, $wc_columns );
}
/**
* Check if contact row found in the unsubscribe table and remove them.
*
* @param $contact
*
* @return bool
*/
public static function maybe_delete_unsubscribe_rows( $contact ) {
if ( ! $contact instanceof WooFunnels_Contact ) {
return false;
}
$email = $contact->get_email();
$contact_no = $contact->get_contact_no();
$data = array(
'recipient' => array( $email, $contact_no ),
);
$rows = BWFAN_Model_Message_Unsubscribe::get_message_unsubscribe_row( $data, false );
if ( empty( $rows ) ) {
return false;
}
$p_keys = array_column( $rows, 'ID' );
foreach ( $p_keys as $key ) {
BWFAN_Model_Message_Unsubscribe::delete( $key );
}
return true;
}
public static function get_admin_analytics_cache_lifespan() {
$time = apply_filters( 'bwfan_admin_analytics_cache_lifespan', ( 1 * HOUR_IN_SECONDS ) );
return ( intval( $time ) > 0 ) ? intval( $time ) : ( 1 * HOUR_IN_SECONDS );
}
/**
* @param $diff_time
*
* @return string
*/
public static function get_difference_string( $diff_time ) {
if ( empty( $diff_time ) || ! is_object( $diff_time ) ) {
return '';
}
if ( $diff_time->y > 0 ) {
return $diff_time->y . __( ' year ago', 'wp-marketing-automations' );
}
if ( $diff_time->m > 0 ) {
return $diff_time->m . __( ' months ago', 'wp-marketing-automations' );
}
if ( $diff_time->d > 0 ) {
return $diff_time->d . __( ' days ago', 'wp-marketing-automations' );
}
if ( $diff_time->h > 0 ) {
return $diff_time->h . __( ' hours ago', 'wp-marketing-automations' );
}
if ( $diff_time->i > 0 ) {
return $diff_time->i . __( ' minutes ago', 'wp-marketing-automations' );
}
if ( $diff_time->m > 0 ) {
return $diff_time->s . __( ' seconds ago', 'wp-marketing-automations' );
}
return '';
}
public static function ping_woofunnels_worker() {
$url = rest_url( '/woofunnels/v1/worker' ) . '?' . time();
$args = array(
'method' => 'GET',
'body' => array(),
'timeout' => 0.01,
'sslverify' => false,
);
wp_remote_post( $url, $args );
}
public static function get_formatted_price_wc( $price, $raw = true, $currency = '' ) {
if ( true === $raw ) {
return $price;
}
$decimal_separator = wc_get_price_decimal_separator();
$thousand_separator = wc_get_price_thousand_separator();
$decimals = wc_get_price_decimals();
if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $decimals > 0 ) {
$price = wc_trim_zeros( $price );
}
$output = number_format( $price, $decimals, $decimal_separator, $thousand_separator );
if ( ! empty( $currency ) ) {
$position = get_option( 'woocommerce_currency_pos' );
$prefix = '';
$suffix = '';
switch ( $position ) {
case 'left_space':
$prefix = $currency . ' ';
break;
case 'left':
$prefix = $currency;
break;
case 'right_space':
$suffix = ' ' . $currency;
break;
case 'right':
$suffix = $currency;
break;
}
$output = $prefix . $output . $suffix;
}
return $output;
}
public static function get_formatting_for_wc_price( $attr, $order ) {
$formatting = isset( $attr['format'] ) && ! empty( $attr['format'] ) ? $attr['format'] : 'raw';
$raw = ( 'raw' === strval( $formatting ) ) ? true : false;
$currency_format = '';
if ( 'formatted-currency' === strval( $formatting ) ) {
$currency = ! empty( $order ) && ! is_null( $order->get_currency() ) ? $order->get_currency() : get_option( 'woocommerce_currency' );
$currency_symbol = get_woocommerce_currency_symbol( $currency );
$currency_format = html_entity_decode( $currency_symbol );
}
return array( 'raw' => $raw, 'currency' => $currency_format );
}
/**
* Advanced logging to check wp-json endpoint for event enabled or not
*
* @return bool
*/
public static function event_cb_advanced_log_enabled() {
if ( self::is_log_enabled( 'bwfan_end_point_logging' ) ) {
return true;
}
if ( defined( 'BWFAN_ALLOW_EVENT_ENDPOINT_LOGS' ) && true === BWFAN_ALLOW_EVENT_ENDPOINT_LOGS ) {
return true;
}
if ( true === apply_filters( 'bwfan_allow_event_endpoint_logs', false ) ) {
return true;
}
return false;
}
/**
* Advanced logging for developers to check wp-json endpoint working or not
*
* @param $log
*
* @return void
*/
public static function event_advanced_logs( $log ) {
if ( empty( $log ) || false === self::event_cb_advanced_log_enabled() ) {
return;
}
$log = array(
't' => microtime( true ),
'm' => $log,
);
BWFAN_Common::log_test_data( $log, 'fka-event-endpoint-check', true );
}
/**
* Update Contact WP User ID to 0 after a WP user is deleted
*
* @param $user_id
*
* @return void
*/
public static function update_contact_wp_id( $user_id ) {
$bwf_contact = new WooFunnels_Contact( $user_id );
if ( 0 === intval( $bwf_contact->get_id() ) ) {
return;
}
$bwf_contact->set_wpid( 0 );
$bwf_contact->save();
}
/**
* Get midnight time of tomorrow in store timezone
*
* @return int
*/
public static function get_midnight_store_time() {
$timezone = new DateTimeZone( wp_timezone_string() );
$date = new DateTime();
$date->modify( '+1 days' );
$date->setTimezone( $timezone );
$date->setTime( 0, 0, 0 );
return $date->getTimestamp();
}
/**
* Fetch updated data
*
* @param $meta
*
* @return mixed
*/
public static function fetch_updated_data( $meta ) {
if ( ! bwfan_is_autonami_pro_active() || ( ! isset( $meta['tags'] ) && ! isset( $meta['list'] ) ) ) {
return $meta;
}
if ( isset( $meta['tags'] ) ) {
$meta['tags'] = self::get_updated_tags_and_list( $meta['tags'] );
}
if ( isset( $meta['list'] ) ) {
$meta['list'] = self::get_updated_tags_and_list( $meta['list'] );
}
return $meta;
}
/**
* Modify automation steps data, fetch latest names in admin
*
* @param $step_type
* @param $data
*
* @return mixed
*/
public static function modify_step_admin_data( $step_type, $data ) {
if ( ! bwfan_is_autonami_pro_active() ) {
return $data;
}
if ( defined( 'BWFAN_Disable_Automation_Fetch_Latest_Names' ) && 1 === intval( BWFAN_Disable_Automation_Fetch_Latest_Names ) ) {
return $data;
}
if ( 'conditional' === $step_type ) {
return BWFAN_Common::get_updated_tags_and_list_conditions( $data );
}
if ( 'benchmark' === $step_type ) {
if ( isset( $data->list ) ) {
$data->list = BWFAN_Common::get_updated_tags_and_list( (array) $data->list );
}
if ( isset( $data->tags ) ) {
$data->tags = BWFAN_Common::get_updated_tags_and_list( (array) $data->tags );
}
return $data;
}
if ( 'action' === $step_type ) {
if ( isset( $data->tags ) ) {
$data->tags = BWFAN_Common::get_updated_tags_and_list( (array) $data->tags );
}
if ( isset( $data->list_id ) ) {
$data->list_id = BWFAN_Common::get_updated_tags_and_list( (array) $data->list_id );
}
}
return $data;
}
/**
* Get updated tags & lists names
*
* @param $terms
* @param $id_key
* @param $name_key
*
* @return array|array[]|mixed|object[]
*/
public static function get_updated_tags_and_list( $terms, $id_key = 'id', $name_key = 'name' ) {
if ( ! bwfan_is_autonami_pro_active() ) {
return $terms;
}
return array_map( function ( $term ) use ( $id_key, $name_key ) {
$obj = false;
/** If data is in object then convert into array */
if ( is_object( $term ) ) {
$term = (array) $term;
$obj = true;
}
$data = BWFAN_Model_Terms::get( $term[ $id_key ] );
$term[ $name_key ] = is_array( $data ) && ! empty( $data['name'] ) ? $data['name'] : $term[ $name_key ];
return ( true === $obj ) ? (object) $term : $term;
}, $terms );
}
/**
* Get updated tags & lists names for conditional step
*
* @param $rules
*
* @return mixed
*/
public static function get_updated_tags_and_list_conditions( $rules ) {
if ( empty( $rules ) ) {
return $rules;
}
foreach ( $rules as $or_key => $or_rule ) {
if ( ! is_array( $or_rule ) ) {
continue;
}
/** OR block */
foreach ( $or_rule as $and_key => $rule ) {
/** AND block */
if ( ! isset( $rule->filter ) || ! in_array( $rule->filter, [ 'contact_tags', 'contact_lists' ] ) ) {
continue;
}
$rules[ $or_key ][ $and_key ]->data = self::get_updated_tags_and_list( $rule->data, 'key', 'label' );
}
}
return $rules;
}
/**
* Get contact marketing status
*
* @param $contact_status
* @param $email
* @param $phone
*
* @return array
*/
public static function get_contact_status( $contact_status = 0, $email = '', $phone = '' ) {
$response = [
'status' => $contact_status,
'email_status' => 1,
'sms_status' => 1
];
if ( empty( $email ) && empty( $phone ) ) {
return $response;
}
$data = array(
'recipient' => array( $email, $phone ),
);
$unsubscribed_rows = BWFAN_Model_Message_Unsubscribe::get_message_unsubscribe_row( $data, false );
if ( empty( $unsubscribed_rows ) || 0 === count( $unsubscribed_rows ) ) {
return $response;
}
$unsubscribed_rows = array_column( $unsubscribed_rows, 'recipient' );
$response['email_status'] = in_array( $email, $unsubscribed_rows, true ) ? 0 : 1;
$response['sms_status'] = in_array( $phone, $unsubscribed_rows, true ) ? 0 : 1;
return $response;
}
/**
* Validate create new order settings
*
* @param $data
*
* @return bool
*/
public static function validate_create_order_event_setting( $data ) {
/** Any product case */
if ( ! isset( $data['event_meta'] ) || ! isset( $data['event_meta']['order-contains'] ) || 'any' === $data['event_meta']['order-contains'] ) {
return true;
}
$order = wc_get_order( intval( $data['order_id'] ) );
if ( ! $order instanceof WC_Order ) {
return false;
}
/** Specific product case */
$get_selected_product = isset( $data['event_meta']['products'] ) ? $data['event_meta']['products'] : [];
$ordered_products = array();
foreach ( $order->get_items() as $item ) {
$ordered_products[] = $item->get_product_id();
/** In case variation */
if ( $item->get_variation_id() ) {
$ordered_products[] = $item->get_variation_id();
}
}
/** Selected product and ordered products */
$product_selected = array_column( $get_selected_product, 'id' );
$ordered_products = array_unique( $ordered_products );
sort( $ordered_products );
return count( array_intersect( $product_selected, $ordered_products ) ) > 0;
}
/**
* Update Automation meta data
* @return void
*/
public static function update_meta_automations_v2() {
$key = 'bwfan_automation_v2_meta_normalize';
$offset_id = get_option( $key );
if ( intval( $offset_id ) < 1 ) {
delete_option( $key );
bwf_unschedule_actions( 'bwfan_update_meta_automations_v2' );
return;
}
global $wpdb;
$query = "SELECT am.meta_value, a.ID FROM `{$wpdb->prefix}bwfan_automationmeta` AS am JOIN `{$wpdb->prefix}bwfan_automations` AS a ON am.bwfan_automation_id = a.ID WHERE a.ID >= %d AND am.meta_key = %s AND a.v = %d LIMIT 20";
$rows = $wpdb->get_results( $wpdb->prepare( $query, $offset_id, 'steps', 2 ), ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $rows ) ) {
delete_option( $key );
bwf_unschedule_actions( 'bwfan_update_meta_automations_v2' );
return;
}
$start_time = time();
foreach ( $rows as $single ) {
if ( ( time() - $start_time ) > 10 ) {
return;
}
if ( ! isset( $single['meta_value'] ) ) {
continue;
}
$meta_value = maybe_unserialize( $single['meta_value'] );
if ( ! is_array( $meta_value ) ) {
continue;
}
$meta_value = array_map( function ( $data ) {
if ( isset( $data['data'] ) && 'yesNoNode' !== $data['type'] ) {
$data['data'] = [];
}
return $data;
}, $meta_value );
BWFAN_Model_Automationmeta::update_automation_meta_values( $single['ID'], [ 'steps' => maybe_serialize( $meta_value ) ] );
/** updating the option key for next call */
update_option( 'bwfan_automation_v2_meta_normalize', ( intval( $single['ID'] ) + 1 ) );
}
}
/**
* deleting logs older than 1 month
* scheduler runs every month
*
* @return void
*/
public static function delete_bwfan_logs() {
$wp_dir = wp_upload_dir();
$autonami_log_dir = $wp_dir['basedir'] . '/funnelkit/autonami-logs/';
$files = @scandir( $autonami_log_dir ); // @codingStandardsIgnoreLine.
if ( empty( $files ) ) {
return;
}
$expire_time = strtotime( "-30 days" );
foreach ( $files as $file ) {
if ( in_array( $file, array( '.', '..' ), true ) ) {
continue;
}
if ( is_dir( $file ) ) {
continue;
}
if ( filemtime( $autonami_log_dir . $file ) > $expire_time ) {
continue;
}
@unlink( trailingslashit( $autonami_log_dir ) . $file ); // @codingStandardsIgnoreLine.
}
}
/**
* get desired store time
*
* @param $hours
* @param $mins
* @param $sec
*
* @return int
*/
public static function get_store_time( $hours = 0, $mins = 0, $sec = 0 ) {
$timezone = new DateTimeZone( wp_timezone_string() );
$date = new DateTime();
$date->setTimezone( $timezone );
$date->setTime( $hours, $mins, $sec );
if ( current_time( 'timestamp', 1 ) > $date->getTimestamp() ) {
$date->modify( '+1 days' );
}
return $date->getTimestamp();
}
/**
* Get database query cached result
*
* @param $query
*
* @return false|mixed
*/
public static function get_db_cache_data( $query = '' ) {
if ( empty( $query ) ) {
return false;
}
$query = md5( $query );
if ( ! is_array( self::$cached_db_data ) || ! isset( self::$cached_db_data[ $query ] ) ) {
return false;
}
return self::$cached_db_data[ $query ];
}
/**
* Set database query cached result
*
* @param $query
* @param $result
*
* @return bool
*/
public static function set_db_cache_data( $query = '', $result = '' ) {
if ( empty( $query ) ) {
return false;
}
$query = md5( $query );
self::$cached_db_data[ $query ] = $result;
return true;
}
/**
* Unset database query cached result
*
* @param $query
*
* @return false|void
*/
public static function unset_db_cache_key( $query = '' ) {
if ( empty( $query ) ) {
return false;
}
$query = md5( $query );
if ( isset( self::$cached_db_data[ $query ] ) ) {
unset( self::$cached_db_data[ $query ] );
}
}
/**
* get last order of the contact
*
* @param $contact
*
* @return array|stdClass|WC_Order[]
*/
public static function fetch_last_order_by_contact( $contact ) {
if ( ! $contact instanceof WooFunnels_Contact ) {
return [];
}
return wc_get_orders( array(
'meta_key' => '_woofunnel_cid',
'meta_value' => $contact->get_id(),
'orderby' => 'ID',
'order' => 'DESC',
'limit' => 1,
) );
}
/**
* @param $contact
*
* @return array|object|stdClass|null
*/
public static function fetch_last_refund_of_contact( $contact ) {
if ( ! $contact instanceof WooFunnels_Contact ) {
return [];
}
global $wpdb;
$orders_ids = wc_get_orders( array(
'meta_key' => '_woofunnel_cid',
'meta_value' => $contact->get_id(),
'limit' => - 1,
'return' => 'ids'
) );
if ( empty( $orders_ids ) ) {
return [];
}
$orders_ids = implode( ',', $orders_ids );
if ( BWF_WC_Compatibility::is_hpos_enabled() ) {
$query = $wpdb->prepare( "SELECT `id` AS refund_id, `parent_order_id` AS order_id FROM {$wpdb->prefix}wc_orders WHERE type = %s AND status = %s AND `parent_order_id` IN ($orders_ids) ORDER BY id DESC LIMIT 1", 'shop_order_refund', 'wc-completed' );// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
$refund = $wpdb->get_row( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
} else {
$query = $wpdb->prepare( "SELECT `ID` AS refund_id, `post_parent` AS order_id FROM {$wpdb->prefix}posts WHERE `post_type` = %s AND `post_status` = %s AND `post_parent` IN ($orders_ids) ORDER BY `ID` DESC LIMIT 1", 'shop_order', 'publish' );// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
$refund = $wpdb->get_row( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
return $refund;
}
/**
* Insert multiple contacts in automation contact table
*
* @param $automation_data
*
* @return void
*/
public static function insert_automations( $automation_data ) {
foreach ( $automation_data as $auto_data ) {
$data = [
'cid' => $auto_data['cid'],
'aid' => $auto_data['aid'],
'event' => $auto_data['event'],
'c_date' => current_time( 'mysql', 1 ),
'e_time' => current_time( 'timestamp', 1 ),
'last_time' => current_time( 'timestamp', 1 ),
'data' => $auto_data['data']
];
BWFAN_Model_Automation_Contact::insert( $data );
}
}
/**
* Bulk action for all the contacts of different automation ids
*
* @param $dynamic_str
* @param $action
* @param $status
*
* @return void
*/
public static function bwfan_automation_all_contact_bulk_action( $dynamic_str, $action, $status ) {
if ( 'end' === $action ) {
$option_key = "bwfan_bulk_automation_all_contact_end_{$dynamic_str}";
$args = array( 'key' => $dynamic_str, 'action' => $action, 'status' => $status );
$scheduler_action = 'bwfan_automation_all_contact_bulk_action';
self::bulk_contact_automation_end( $option_key, $args, $scheduler_action );
return;
}
$option_key = "bwfan_bulk_automation_all_contact_{$action}_{$dynamic_str}";
$a_cids = get_option( $option_key, [] );
if ( empty( $a_cids ) ) {
delete_option( $option_key );
bwf_unschedule_actions( 'bwfan_automation_all_contact_bulk_action', [ 'key' => $dynamic_str, 'action' => $action, 'status' => $status ] );
return;
}
if ( 'completed' === $status && 'rerun' !== $action ) {
$action = 'delete_complete';
}
self::perform_bulk_action( $a_cids, $option_key, $action, $status );
}
/**
* Correct shortcode string for block editor
*
* @param $body
* @param $type
*
* @return array|mixed|string|string[]
*/
public static function correct_shortcode_string( $body, $type ) {
if ( ! bwfan_is_autonami_pro_active() || ( $type !== 'block' && $type !== 5 ) || strpos( $body, 'bwfan_email_block_visibility' ) === false ) {
return $body;
}
BWFAN_Core()->rules->load_rules_classes();
$body = str_replace( "', "]", $body );
return str_replace( "", "[/bwfbe_email_block_visibility]", $body );
}
/**
* Get default contact's count
*
* @return int[]
*/
public static function get_contact_data_counts() {
$bulk_actions_all_count = 0;
$bulk_actions_active_count = 0;
if ( bwfan_is_autonami_pro_active() ) {
$bulk_actions_count = BWFAN_Model_Bulk_Action::get_bulk_actions_total_count( false );
$bulk_actions_all_count = isset( $bulk_actions_count['all'] ) ? $bulk_actions_count['all'] : 0;
$bulk_actions_active_count = isset( $bulk_actions_count['1'] ) ? $bulk_actions_count['1'] : 0;
}
return [
'contacts_contacts' => 0,
'contacts_manage_audiences' => 0,
'contacts_manage_fields' => 0,
'contacts_manage_lists' => 0,
'contacts_manage_tags' => 0,
'contacts_bulk_actions' => $bulk_actions_all_count,
'contacts_active_bulk_actions' => $bulk_actions_active_count,
];
}
/**
* Get formatted string for mysql query
*
* @param $value
*
* @return array|mixed|string|string[]
*/
public static function get_formatted_value_for_dbquery( $value ) {
return ( false !== strpos( $value, "'" ) ) ? str_replace( "'", "\'", $value ) : $value;
}
/**
* Get store average order value
*
* @return float|int
*/
public static function get_store_aov() {
$store_aov_key = 'bwfan_store_aov';
/** Get store aov from transient */
$store_aov = get_transient( $store_aov_key );
if ( ! empty( $store_aov ) ) {
return floatval( $store_aov );
}
/** Transient expiration time */
$exp = 12 * HOUR_IN_SECONDS;
global $wpdb;
$sql = "SELECT count(`order_id`) as `orders`, SUM(`total_sales`) as `total` FROM {$wpdb->prefix}wc_order_stats WHERE `status` NOT IN('wc-failed', 'wc-pending', 'wc-cancelled', 'wc-refunded') ";
$result = $wpdb->get_results( $sql, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$aov = 0;
if ( ! empty( $result[0]['orders'] ) && ! empty( $result[0]['total'] ) ) {
$aov = ( floatval( $result[0]['total'] ) / absint( $result[0]['orders'] ) );
}
set_transient( $store_aov_key, $aov, $exp );
return $aov;
}
/**
* @param string $message
* @param array $data
* @param int $code
*
* @return WP_Error
*/
public static function crm_error( $message = '', $data = array(), $code = 500 ) {
$wp_error = new WP_Error( $code, $message );
if ( ! empty( $data ) ) {
$wp_error->add_data( $data );
}
return $wp_error;
}
/**
* Remove filter before sending mail
*/
public static function bwf_remove_filter_before_wp_mail() {
remove_all_filters( 'wp_mail_from' );
remove_all_filters( 'wp_mail_from_name' );
remove_all_filters( 'wp_mail_content_type' );
remove_all_filters( 'wp_mail_charset' );
}
/**
* Update automation contact's step trail status
*
* @return void
*/
public static function bwfan_update_contact_trail() {
global $wpdb;
$start_time = time();
do {
$query = "SELECT ct.ID FROM `{$wpdb->prefix}bwfan_automation_contact_trail` AS ct JOIN `{$wpdb->prefix}bwfan_automation_complete_contact` AS cc ON ct.tid = cc.trail WHERE ct.status = 2 LIMIT 0,20";
$ids = $wpdb->get_col( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $ids ) ) {
bwf_unschedule_actions( 'bwfan_update_contact_trail' );
break;
}
$ids = implode( ',', $ids );
$query = "UPDATE `{$wpdb->prefix}bwfan_automation_contact_trail` SET `status` = 1, `data` = NULL WHERE ID IN ($ids);";
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
} while ( ( time() - $start_time ) < 10 );
}
/**
* Get product price with tax
*
* @param $product
*
* @return float|mixed|string|null
*/
public static function get_prices_with_tax( $product ) {
if ( ! wc_tax_enabled() ) {
return $product instanceof WC_Product && ! empty( $product->get_price() ) ? $product->get_price() : 0;
}
if ( ! $product instanceof WC_Product ) {
return 0;
}
$tax_display_cart = get_option( 'woocommerce_tax_display_cart', '' );
if ( 'incl' === $tax_display_cart ) {
return wc_get_price_including_tax( $product );
}
if ( 'excl' === $tax_display_cart ) {
return wc_get_price_excluding_tax( $product );
}
return 0;
}
/**
* Set headers to prevent caching
*
* @return void
*/
public static function nocache_headers() {
do_action( 'litespeed_control_set_nocache', 'fkautomations' );
if ( headers_sent() ) {
return;
}
header( 'Cache-Control: no-cache, no-store, must-revalidate, max-age=0' );
header( 'Pragma: no-cache' );
header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
header( 'Last-Modified: false' );
}
/**
* Check if contact is in automation for a particular order related event
*
* @param $aid
* @param $cid
* @param $order_id
* @param $item_id
* @param $event
*
* @return true|void
*/
public static function is_contact_in_automation( $aid, $cid, $order_id, $item_id = 0, $event = 'wc_new_order' ) {
$active_contact = BWFAN_Model_Automation_Contact::is_contact_with_same_order( $aid, $cid, $order_id, $item_id, $event );
if ( ! empty( $active_contact ) ) {
return true;
}
return BWFAN_Model_Automation_Complete_Contact::is_contact_with_same_order( $aid, $cid, $order_id, $item_id, $event );
}
/**
* Append extra data for order status change
*
* @param $extra_data
* @param $order_id
* @param $from
* @param $to
*
* @return mixed
*/
public static function order_status_change( $extra_data, $order_id, $from, $to ) {
$data = [
'order_id' => $order_id,
'from' => $from,
'to' => $to,
'unique_key' => get_option( 'bwfan_u_key', false ),
'function_name' => 'wc_order_status_changed',
];
try {
$a_e_id = BWFAN_Model_Automation_Events::insert_data( $data );
} catch ( Error $e ) {
BWFAN_Common::log_test_data( 'Automation Event Insert Row Error: ' . $e->getMessage(), 'db-creation-errors', true );
$table_instance = new BWFAN_DB_Table_Automation_Events();
$table_instance->create_table();
$a_e_id = BWFAN_Model_Automation_Events::insert_data( $data );
}
if ( ! empty( $a_e_id ) && intval( $a_e_id ) > 0 ) {
$extra_data['a_e_id'] = $a_e_id;
}
return $extra_data;
}
public static function order_status_change_async_capture( $order_data ) {
/** Delete row from automation events */
if ( isset( $order_data['a_e_id'] ) ) {
BWFAN_Model_Automation_Events::delete( $order_data['a_e_id'] );
}
$order = wc_get_order( $order_data['order_id'] );
if ( ! $order instanceof WC_Order ) {
return;
}
do_action( 'bwfan_wc_order_status_changed', $order, $order_data['from'], $order_data['to'] );
}
/**
* Set dynamic string prop
*
* @return void
*/
public static function set_dynamic_string() {
self::$dynamic_str = self::get_dynamic_string( 10 );
}
/**
* Get email from order
*
* @param $order_id
* @param $order
*
* @return string|null
*/
public static function get_email_from_order( $order_id = '', ?WC_Order $order = null ) {
if ( empty( $order_id ) && ! $order instanceof WC_Order ) {
return '';
}
if ( ! $order instanceof WC_Order ) {
$order = wc_get_order( $order_id );
}
return $order instanceof WC_Order ? $order->get_billing_email() : '';
}
/**
* Get phone from order
*
* @param $order_id
* @param $order
*
* @return mixed|string|null
*/
public static function get_phone_from_order( $order_id = '', ?WC_Order $order = null ) {
if ( empty( $order_id ) && ! $order instanceof WC_Order ) {
return '';
}
if ( ! $order instanceof WC_Order ) {
$order = wc_get_order( $order_id );
}
if ( ! $order instanceof WC_Order ) {
return '';
}
$phone = BWFAN_Woocommerce_Compatibility::get_order_data( $order, '_billing_phone' );
if ( empty( $phone ) ) {
$phone = BWFAN_Woocommerce_Compatibility::get_order_data( $order, '_shipping_phone' );
}
if ( empty( $phone ) || ! class_exists( 'BWFAN_Phone_Numbers' ) ) {
return $phone;
}
$country = BWFAN_Woocommerce_Compatibility::get_order_data( $order, '_billing_country' );
if ( empty( $country ) ) {
$country = BWFAN_Woocommerce_Compatibility::get_order_data( $order, '_shipping_country' );
}
if ( ! empty( $country ) ) {
$phone = BWFAN_Phone_Numbers::add_country_code( $phone, $country );
}
return $phone;
}
/**
* Get WP user id from order
*
* @param string $order_id
* @param $order
*
* @return int|string
*/
public static function get_wp_user_id_from_order( $order_id = '', ?WC_Order $order = null ) {
if ( empty( $order_id ) && ! $order instanceof WC_Order ) {
return '';
}
if ( ! $order instanceof WC_Order ) {
$order = wc_get_order( $order_id );
}
return $order instanceof WC_Order ? $order->get_customer_id() : '';
}
/**
* Save meta in order
*
* @param $order_id
* @param $meta_key
* @param $meta_value
*
* @return void
*/
public static function save_order_meta( $order_id, $meta_key, $meta_value ) {
global $wpdb;
$hpos_enabled = BWF_WC_Compatibility::is_hpos_enabled();
if ( $hpos_enabled ) {
$table = "{$wpdb->prefix}wc_orders_meta";
$query = " SELECT `id`,`meta_value` FROM {$table} WHERE `order_id` = %d AND `meta_key` = %s ";
} else {
$table = "{$wpdb->prefix}postmeta";
$query = " SELECT `meta_id`,`meta_value` FROM {$table} WHERE `post_id` = %d AND `meta_key` = %s ";
}
$row = $wpdb->get_row( $wpdb->prepare( $query, $order_id, $meta_key ), ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
/** If no data found */
if ( empty( $row ) ) {
$data = [
'meta_key' => $meta_key,
'meta_value' => $meta_value,
];
if ( $hpos_enabled ) {
$data['order_id'] = $order_id;
} else {
$data['post_id'] = $order_id;
}
$wpdb->insert( $table, $data ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
return;
}
/** If old value is equal to new value */
if ( $meta_value === $row['meta_value'] ) {
return;
}
/** update meta value */
$column = ( $hpos_enabled ) ? 'id' : 'meta_id';
$wpdb->update( $table, [ 'meta_value' => $meta_value ], [ $column => $row[ $column ] ] ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
/**
* Get FK Automation links
*
* @return array
*/
public static function get_fk_site_links() {
$default_args = [
'utm_source' => 'WordPress',
'utm_campaign' => 'FKA+Lite+Plugin'
];
return [
'upgrade' => apply_filters( 'bwfan_upgrade_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/exclusive-offer/' ) ),
'offer' => apply_filters( 'bwfan_offer_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/exclusive-offer/' ) ),
'autonami' => apply_filters( 'bwfan_fka_sales_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/wordpress-marketing-automation-autonami/' ) ),
'support' => apply_filters( 'bwfan_support_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/support/' ) ),
'docs' => apply_filters( 'bwfan_docs_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/docs/autonami-2/' ) ),
'nxtgenbuilder' => apply_filters( 'bwfan_fka_nextgen_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/autonami-next-generation-automation-builder/' ) ),
'migratefromv1' => apply_filters( 'bwfan_fka_migrate_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/docs/autonami-2/automations/migrate-from-older-version' ) ),
'whatsnew' => apply_filters( 'bwfan_fka_whatsnew_link_append_utm_args', add_query_arg( $default_args, 'https://funnelkit.com/whats-new/' ) ),
'publicapi' => apply_filters( 'bwfan_fka_public_api_link_append_utm_args', add_query_arg( $default_args, 'https://developers.funnelkit.com/#introduction' ) ),
];
}
/**
* Get unsubscribe link
*
* @param $data
*
* @return string
*/
public static function get_unsubscribe_link( $data ) {
if ( empty( self::$unsubscribe_page_link ) ) {
$global_settings = self::get_global_settings();
if ( ! isset( $global_settings['bwfan_unsubscribe_page'] ) || empty( $global_settings['bwfan_unsubscribe_page'] ) ) {
self::$unsubscribe_page_link = esc_url_raw( home_url() );
} else {
$page = absint( $global_settings['bwfan_unsubscribe_page'] );
self::$unsubscribe_page_link = get_permalink( $page );
}
}
if ( empty( $data ) || ! is_array( $data ) ) {
return self::$unsubscribe_page_link;
}
if ( empty( $data['uid'] ) && isset( $data['contact_id'] ) ) {
$contact = new WooFunnels_Contact( '', '', '', $data['contact_id'] );
$uid = ( $contact->get_id() > 0 ) ? $contact->get_uid() : '';
if ( ! empty( $uid ) ) {
$data['uid'] = $uid;
}
unset( $data['contact_id'] );
}
$data['bwfan-action'] = 'unsubscribe';
return add_query_arg( $data, self::$unsubscribe_page_link );
}
/**
* Checking wc new order goal in automation
*
* @param $aid
*
* @return bool
*/
public static function is_wc_order_goal( $aid ) {
global $wpdb;
$query = $wpdb->prepare( "SELECT `ID` FROM {$wpdb->prefix}bwfan_automations WHERE ID = %d AND `benchmark` LIKE %s", $aid, '%"wc_new_order"%' );
return ( ! empty( $wpdb->get_var( $query ) ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
/**
* Remove duplicate actions if found
*
* @return void
*/
public static function remove_duplicate_actions() {
global $wpdb;
$hooks = [
'bwfan_delete_logs',
'bwfan_delete_expired_autonami_coupons',
'bwfan_mark_abandoned_lost_cart',
'bwfan_run_midnight_cron',
'bwfan_run_midnight_connectors_sync',
'bwfan_run_queue',
'bwfan_run_queue_v2',
'bwfcrm_broadcast_run_queue',
'bwfan_check_abandoned_carts',
'bwfan_5_minute_worker',
'bwfan_run_event_queue'
];
$placeholders = array_fill( 0, count( $hooks ), '%s' );
$placeholders_hooks = implode( ', ', $placeholders );
$query = "SELECT `hook`, count(`id`) as `count` FROM `{$wpdb->prefix}bwf_actions` WHERE `hook` IN ($placeholders_hooks) AND `status` = 0 GROUP BY `hook`;";
$query = $wpdb->prepare( $query, $hooks );// phpcs:ignore WordPress.DB.PreparedSQL
$result = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $result ) ) {
return;
}
$result = array_filter( $result, function ( $row ) {
return $row['count'] > 1;
} );
if ( empty( $result ) ) {
return;
}
$hooks = array_column( $result, 'hook' );
sort( $hooks );
$placeholders = array_fill( 0, count( $hooks ), '%s' );
$placeholders_hooks = implode( ', ', $placeholders );
$query = $wpdb->prepare( "DELETE FROM `{$wpdb->prefix}bwf_actions` WHERE `hook` IN ($placeholders_hooks) AND `status` = 0", $hooks ); // phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
$wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( true === bwfan_is_autonami_pro_active() && in_array( 'bwfcrm_broadcast_run_queue', $hooks, true ) ) {
/** Reschedule broadcast */
bwf_schedule_recurring_action( time(), 60, 'bwfcrm_broadcast_run_queue', array(), 'bwfcrm' );
}
}
/**
* Save contact uid as cookie
*
* @param $optin_id
* @param $posted_data
* @param $bwf_contact WooFunnels_Contact
*
* @return void
*/
public static function set_uid_in_cookies( $optin_id, $posted_data, ?WooFunnels_Contact $bwf_contact = null ) {
if ( headers_sent() ) {
return;
}
/** If contact object available */
if ( ! is_null( $bwf_contact ) && $bwf_contact instanceof WooFunnels_Contact ) {
$uid = $bwf_contact->get_uid();
if ( ! empty( $uid ) ) {
BWFAN_Common::set_cookie( '_fk_contact_uid', $uid, time() + ( 10 * YEAR_IN_SECONDS ) );
return;
}
}
if ( ! isset( $posted_data['cid'] ) || empty( $posted_data['cid'] ) ) {
return;
}
$contact = new WooFunnels_Contact( '', '', '', $posted_data['cid'] );
if ( ! $contact instanceof WooFunnels_Contact ) {
return;
}
$uid = $contact->get_uid();
if ( empty( $uid ) ) {
return;
}
BWFAN_Common::set_cookie( '_fk_contact_uid', $uid, time() + ( 10 * YEAR_IN_SECONDS ) );
}
/**
* Returns block editor default settings
*
* @return array
*/
public static function get_block_editor_default_setting() {
return [
'site' => [
'logo' => '',
'url' => '',
'logoAuto' => [
'desktop' => true,
],
'logoSize' => [
'desktop' => [
'value' => 100,
],
],
],
'setting' => [
'background' => [
'desktop' => [
'color' => '#f6f6f6',
],
],
'contentBackground' => [
'desktop' => [
'color' => '#ffffff',
],
],
'width' => [
'desktop' => [
'value' => 640,
'unit' => 'px',
],
],
'align' => [
'desktop' => 'center',
],
'color' => [
'desktop' => '#353030',
],
'font' => [
'desktop' => [
'family' => 'arial,helvetica,sans-serif',
'size' => 14,
],
],
'fontH1' => [
'desktop' => [
'size' => 36,
],
],
'fontH2' => [
'desktop' => [
'size' => 32,
],
],
'fontH3' => [
'desktop' => [
'size' => 28,
],
],
'fontH4' => [
'desktop' => [
'size' => 24,
],
],
'fontH5' => [
'desktop' => [
'size' => 20,
],
],
'fontH6' => [
'desktop' => [
'size' => 16,
],
],
'linkLineType' => [
'desktop' => 'underline',
],
'linkColor' => [
'desktop' => '#236fa1',
],
'linkLineColor' => [],
'buttonColor' => [
'desktop' => '#ffffff',
],
'buttonBackground' => [
'desktop' => [
'color' => '#353030',
'gradient' => null,
],
],
'buttonSize' => [
'desktop' => [
'value' => 100,
],
],
'buttonAuto' => [
'desktop' => true,
],
'buttonBorder' => [
'desktop' => [
'top-left' => '8',
'top-right' => '8',
'bottom-left' => '8',
'bottom-right' => '8',
'radius_unit' => 'px',
]
],
'buttonPadding' => [
'desktop' => [
'left' => '24',
'right' => '24',
'top' => '16',
'bottom' => '16',
'unit' => 'px',
]
],
'buttonFont' => [
'desktop' => [
'size' => 16,
],
],
'backupFont' => [
'desktop' => [
'family' => 'arial,helvetica,sans-serif',
],
],
'social' => [
[ 'iconName' => 'facebook', 'link' => '' ],
[ 'iconName' => 'instagram', 'link' => '' ],
[ 'iconName' => 'youtube', 'link' => '' ],
[ 'iconName' => 'pinterest', 'link' => '' ],
],
'socialType' => 'circle',
],
];
}
/**
* Get block editor settings
*
* @return array|false|mixed|null
*/
public static function get_block_editor_settings() {
if ( ! empty( self::$block_editor_settings ) ) {
return self::$block_editor_settings;
}
$default = BWFAN_Common::get_block_editor_default_setting();
$saved_setting = get_option( 'bwf_global_block_editor_setting', $default );
if ( isset( $saved_setting['setting'] ) && isset( $default['setting'] ) ) {
$new_settings = array_merge( $default['setting'], $saved_setting['setting'] );
$saved_setting['setting'] = $new_settings;
}
self::$block_editor_settings = ! empty( $saved_setting ) ? $saved_setting : $default;
return self::$block_editor_settings;
}
/**
* Check pro is deactivated or 3.0
*
* @return bool
*/
public static function is_pro_3_0() {
return ( ( ! bwfan_is_autonami_pro_active() ) || ( defined( 'BWFAN_PRO_VERSION' ) && version_compare( BWFAN_PRO_VERSION, '3.0.beta.27032024', '>=' ) ) );
}
/**
* Insert default fields
*
* @return void
*/
public static function insert_default_crm_fields() {
global $wpdb;
$crm_fields_table = $wpdb->prefix . 'bwfan_fields';
$default_fields = self::$crm_default_fields;
$db_errors = [];
foreach ( $default_fields as $field => $field_data ) {
$already_exist = self::check_field_exist( $field );
if ( $already_exist ) {
continue;
}
$data = [
'name' => $field_data['name'],
'slug' => $field,
'type' => $field_data['type'],
'gid' => 0,
'meta' => wp_json_encode( $field_data['meta'] ),
'mode' => $field_data['mode'],
'vmode' => $field_data['vmode'],
'view' => $field_data['view'],
'search' => 1,
'created_at' => current_time( 'mysql', 1 ),
];
$wpdb->insert( $crm_fields_table, $data ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$field_id = $wpdb->insert_id;
if ( ! empty( $wpdb->last_error ) ) {
$db_errors[] = 'Error in default field creation: ' . $field_data['name'] . ' ' . $wpdb->last_error;
}
/** Check field column exist in contact_fields table **/
$exists = BWF_Model_Contact_Fields::column_already_exists( $field_id );
if ( empty( $exists ) ) {
$column_added = BWF_Model_Contact_Fields::add_column_field( $field_id, 1 );
/** If column not added */
if ( true !== $column_added ) {
BWFAN_Model_Fields::delete( $field_id );
$db_errors[] = 'Error in contact field column creation: ' . $column_added;
}
}
}
/** Log if any mysql errors */
if ( ! empty( $db_errors ) ) {
BWFAN_Common::log_test_data( array_merge( [ __FUNCTION__ ], $db_errors ), 'field-creation-error' );
}
}
/**
* Checking if field with slug exists or not
*
* @param $slug
*
* @return bool
*/
public static function check_field_exist( $slug ) {
global $wpdb;
$query = $wpdb->prepare( "SELECT `ID` FROM `{$wpdb->prefix}bwfan_fields` WHERE `slug` = %s LIMIT 0, 1", $slug );
$result = $wpdb->get_var( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return ! empty( $result );
}
/**
* Get the complete phone number of a contact with a country code
*
* @param $contact_obj WooFunnels_Contact
*
* @return mixed|string|void
*/
public static function get_contact_full_number( $contact_obj ) {
if ( ! $contact_obj instanceof WooFunnels_Contact || 0 === absint( $contact_obj->get_id() ) ) {
return '';
}
$phone = $contact_obj->get_contact_no();
if ( empty( $phone ) ) {
return '';
}
$country = $contact_obj->get_country();
if ( ! empty( $country ) ) {
$phone = BWFAN_Phone_Numbers::add_country_code( $phone, $country );
}
return $phone;
}
/**
* @param $link
*
* @return void
*/
public static function wp_redirect( $link ) {
remove_all_filters( 'wp_redirect' );
add_filter( 'allowed_redirect_hosts', function ( $allowed_hosts, $host ) use ( $link ) {
/** Add link host in allowed hosts, because already checked link is valid or not */
if ( $host === wp_parse_url( $link, PHP_URL_HOST ) ) {
$allowed_hosts[] = $host;
}
return $allowed_hosts;
}, 10, 2 );
if ( ! headers_sent() ) {
header( 'X-Robots-Tag: noindex, nofollow', true );
}
wp_safe_redirect( $link );
exit;
}
/**
* Get Contact id from contact object
*
* @param $email
* @param $user_id
* @param $phone
*
* @return int
*/
public static function get_cid_from_contact( $email = '', $user_id = 0, $phone = '' ) {
if ( empty( $email ) && empty( $phone ) ) {
return 0;
}
$contact = new WooFunnels_Contact( $user_id, $email, $phone );
if ( $contact->get_id() > 0 ) {
return $contact->get_id();
}
return 0;
}
/**
* Return regex pattern
*
* @param int $type
*
* @return string
*/
public static function get_regex_pattern( $type = 1 ) {
$type = (int) $type;
switch ( $type ) {
case 1:
/**
* [0] => href='https://google.com/?abcd=ss&utm_content=source'
* [1] => https://google.com/?abcd=ss&utm_content=source
*/ return '/href=["\']?([^"\'>]+)["\']?/';
case 2:
/**
* [0] =>
*/ return '/]+href=[^>]+>/i';
case 3:
/**
* [0] => https://...
*/ return '#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#';
default:
return '';
}
}
/**
* If url exists in excluded urls
*
* @param $url
*
* @return bool
*/
public static function is_exclude_url( $url ) {
if ( empty( $url ) ) {
return false;
}
$excluded_urls = [
'fonts.googleapis.com',
'mailto:',
'tel:',
'whatsapp:',
'wa.me:',
'//wa.me',
't.me',
'm.me',
'x.com',
'twitter.com',
'linkedin.com',
'instagram.com',
'pinterest.com',
'youtube.com',
'snapchat.com',
'reddit.com',
'tripadvisor.com',
'meetup.com',
'producthunt.com',
'tinder.com',
'tumblr.com',
'music.apple.com',
'open.spotify.com',
'soundcloud.com',
'yelp.com',
'medium.com',
'skype.com',
'flickr.com',
'github.com',
'discord.gg',
'tiktok.com',
'zoom.us'
];
$excluded_urls = apply_filters( 'bwfan_exclude_click_track_urls', $excluded_urls );
foreach ( $excluded_urls as $excluded_url ) {
if ( $url === $excluded_url || false !== strpos( $url, $excluded_url ) ) {
return true;
}
}
return false;
}
public static function get_country_name( $country_code ) {
$country_code = strtoupper( $country_code );
$countries = self::get_countries_data();
if ( isset( $countries[ $country_code ] ) ) {
return $countries[ $country_code ];
}
return $country_code;
}
/** countries data
* @return mixed|null
*/
public static function get_countries_data() {
$countries_json = file_get_contents( BWFAN_PLUGIN_DIR . '/includes/countries.json' );
$countries = json_decode( $countries_json, true );
return $countries;
}
/**
* Conversions indexing
*
* @param $table_empty
*
* @return void
*/
public static function bwfan_conversions_index( $table_empty ) {
$key = 'bwfan_conversions_index';
$order_ids = bwf_options_get( $key );
if ( empty( $order_ids ) || ! is_array( $order_ids ) || 0 === count( $order_ids ) ) {
delete_option( $key );
bwf_unschedule_actions( 'bwfan_conversions_index' );
return;
}
$start_time = time();
$updated_orders = $order_ids;
foreach ( $order_ids as $index => $order_id ) {
if ( ( time() - $start_time ) > 10 ) {
break;
}
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
unset( $updated_orders[ $index ] );
continue;
}
/** Check order is already exists in table if table is not empty */
if ( empty( $table_empty ) ) {
$already_exists = BWFAN_Model_Conversions::get_specific_rows( 'wcid', $order_id );
if ( ! empty( $already_exists ) ) {
unset( $updated_orders[ $index ] );
continue;
}
}
$cid = BWF_WC_Compatibility::get_order_meta( $order, '_woofunnel_cid' );
$oid = BWF_WC_Compatibility::get_order_meta( $order, '_bwfan_ab_cart_recovered_a_id' );
$data = array(
'wcid' => intval( $order_id ),
'cid' => intval( $cid ),
'oid' => intval( $oid ),
'otype' => 1,
'wctotal' => $order->get_total(),
'date' => $order->get_date_created()->date( 'Y-m-d H:i:s' )
);
BWFAN_Model_Conversions::insert( $data );
unset( $updated_orders[ $index ] );
}
sort( $updated_orders );
if ( empty( $updated_orders ) ) {
delete_option( $key );
bwf_unschedule_actions( 'bwfan_conversions_index' );
return;
}
bwf_options_update( $key, $updated_orders );
}
/**
* @return bool
*/
public static function is_conversion_empty() {
global $wpdb;
$query = "SELECT MAX(id) FROM {$wpdb->prefix}bwfan_conversions";
return empty( $wpdb->get_var( $query ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
}
public static function get_skip_conversion_automations() {
global $wpdb;
$skip_events = apply_filters( 'bwfan_skip_conversion_automations', [ 'wcs_before_renewal' ] );
/** Create string placeholder */
$placeholder = array_fill( 0, count( $skip_events ), '%s' );
$placeholder = implode( ", ", $placeholder );
$query = $wpdb->prepare( "SELECT `ID` FROM {$wpdb->prefix}bwfan_automations WHERE 1 = 1 AND `event` IN ($placeholder) ", $skip_events );// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.PreparedSQLPlaceholders
$query_res = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $query_res ) ) {
return [];
}
return array_column( $query_res, 'ID' );
}
/**
* Include block editor shortcode before send mail
*
* @return void
*/
public static function bwfan_before_send_mail( $type = 'block' ) {
if ( bwfan_is_autonami_pro_active() && version_compare( BWFAN_PRO_VERSION, '2.9.0', '>=' ) && in_array( $type, [ 5, 'block', '5', 7, '7' ] ) ) {
include_once BWFAN_PRO_PLUGIN_DIR . '/crm/includes/class-bwfcrm-block-editor.php';
}
}
/**
* Get product image url
*
* @param string|WC_Product $product
*
* @return string
*/
public static function get_product_image_url( $product = '', $size = 'thumbnail' ) {
/** check for woocommerce active **/
if ( ! function_exists( 'bwfan_is_woocommerce_active' ) || false === bwfan_is_woocommerce_active() ) {
return '';
}
if ( ! empty( $product ) ) {
if ( ! $product instanceof WC_Product || ( is_int( $product ) && intval( $product ) > 0 ) ) {
$product = wc_get_product( $product );
}
if ( $product ) {
$product_img_id = $product->get_image_id();
if ( ! empty( $product_img_id ) ) {
return wp_get_attachment_image_url( $product_img_id, $size );
} elseif ( $product->get_parent_id() ) {
$parent_product = wc_get_product( $product->get_parent_id() );
if ( $parent_product ) {
$image_id = $parent_product->get_image_id();
if ( ! empty( $image_id ) ) {
return wp_get_attachment_image_url( $image_id, $size );
}
}
}
}
}
return '';
}
public static function bwfan_run_event_queue() {
global $wpdb;
$query = $wpdb->prepare( "SELECT `ID`, `args` FROM {$wpdb->prefix}bwfan_automation_events WHERE `execution_time` < %d ORDER BY `execution_time` ASC LIMIT 100", current_time( 'timestamp', 1 ) );
$results = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $results ) ) {
return;
}
$events = [];
foreach ( $results as $result ) {
$events[ $result['ID'] ] = json_decode( $result['args'], true );
}
$start_time = time();
$batch_size = 10;
while ( count( $events ) > 0 && ( ( time() - $start_time ) < 15 ) ) {
$selected_ids = ( count( $events ) > $batch_size ) ? array_slice( $events, 0, $batch_size, true ) : $events;
foreach ( $selected_ids as $id => $args ) {
unset( $events[ $id ] );
/** Delete row */
BWFAN_Model_Automation_Events::delete( $id );
if ( empty( $args ) ) {
continue;
}
/** Order status change case */
if ( isset( $args['function_name'] ) && ( 'wc_order_status_changed' === $args['function_name'] ) ) {
$order = wc_get_order( $args['order_id'] );
if ( $order instanceof WC_Order ) {
do_action( 'bwfan_wc_order_status_changed', $order, $args['from'], $args['to'] );
}
continue;
};
/** Other events case */
BWFAN_Common::capture_async_helper( $args, false );
}
}
}
/**
* Set automation ended reason in data
*
* @param $reason
* @param $data
*
* @return mixed
*/
public static function set_automation_ended_reason( $reason, $data ) {
$decoded_data = ! empty( $data['data'] ) ? json_decode( $data['data'], true ) : [];
$decoded_data['end_reason'] = $reason;
$data['data'] = wp_json_encode( $decoded_data );
return $data;
}
/**
* Get automaton end reason message
*
* @param $reason_data
*
* @return string
*/
public static function get_end_reason_message( $reason_data ) {
if ( ! is_array( $reason_data ) || empty( $reason_data ) ) {
return '';
}
$messages = [
BWFAN_Automation_Controller::$MANUAL_END => __( "Manually ended by User #{user_id}", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$ACTION_END => __( "Ended by 'End automation' action (step #{step_id} of Automation #{automation_id})", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$BULK_ACTION_END => __( "Ended by Bulk Action #{id}", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$LINK_TRIGGER_END => __( "Ended by Link Trigger #{id}", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$GOAL_UPDATE_WITH_END => __( "Ended because goal step ( step #{step_id} ) is updated with end automation", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$GOAL_END => __( "Ended by Goal (Step #{step_id})", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$CART_RECOVERED_END => __( "Ended as Cart is Recovered", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$BEFORE_START_VALIDATION => __( "Ended as Event validation failed", 'wp-marketing-automations' ),
BWFAN_Automation_Controller::$AUTOMATION_DATA_NOT_FOUND => __( "Automation data not found for event ({event_slug})", 'wp-marketing-automations' ),
];
$type = intval( $reason_data['type'] );
if ( ! isset( $messages[ $type ] ) ) {
return '';
}
$message = '';
switch ( $type ) {
case BWFAN_Automation_Controller::$MANUAL_END:
$message = str_replace( '{user_id}', intval( $reason_data['data']['user_id'] ), $messages[ $type ] );
break;
case BWFAN_Automation_Controller::$ACTION_END:
$message = str_replace( '{step_id}', intval( $reason_data['data']['sid'] ), $messages[ $type ] );
$aid = intval( $reason_data['data']['aid'] );
$link = "#$aid";
$message = str_replace( '#{automation_id}', $link, $message );
break;
case BWFAN_Automation_Controller::$LINK_TRIGGER_END:
case BWFAN_Automation_Controller::$BULK_ACTION_END:
$id = intval( $reason_data['data']['id'] );
$action = ( $type === BWFAN_Automation_Controller::$BULK_ACTION_END ) ? 'bulk-action' : 'link-trigger';
$link = "#$id";
$message = str_replace( '#{id}', $link, $messages[ $type ] );
break;
case BWFAN_Automation_Controller::$GOAL_END:
case BWFAN_Automation_Controller::$GOAL_UPDATE_WITH_END:
$message = str_replace( '{step_id}', intval( $reason_data['data']['sid'] ), $messages[ $type ] );
break;
case BWFAN_Automation_Controller::$BEFORE_START_VALIDATION:
case BWFAN_Automation_Controller::$CART_RECOVERED_END:
$message = $messages[ $type ];
break;
case BWFAN_Automation_Controller::$AUTOMATION_DATA_NOT_FOUND:
$message = str_replace( '{event_slug}', $reason_data['data']['event_slug'], $messages[ $type ] );
break;
}
return $message;
}
/**
* Get or create Tag / list if not exists
*
* @param $terms
* @param $type
*
* @return array
*/
public static function get_or_create_terms( $terms, $type ) {
$terms = array_map( function ( $term ) {
if ( isset( $term['name'] ) ) {
$term['value'] = $term['name'];
}
return $term;
}, $terms );
$terms = self::check_for_comma_seperated( $terms );
$terms = BWFCRM_Term::get_or_create_terms( $terms, $type, true );
/** Preparing Data */
return array_map( function ( $term ) {
$term_data = [];
$term_data['id'] = $term->get_id();
$term_data['name'] = $term->get_name();
return $term_data;
}, $terms );
}
/**
* Create or update contact on form submit event
*
* @param $automation_data
*/
public static function maybe_create_update_contact( $automation_data ) {
if ( empty( $automation_data ) ) {
return;
}
$email = $automation_data['email'];
if ( ! is_email( trim( $email ) ) ) {
return;
}
$contact = new WooFunnels_Contact( '', $email, '', '', '' );
$args = [];
if ( isset( $automation_data['first_name'] ) && ! empty( $automation_data['first_name'] ) ) {
$args['f_name'] = $automation_data['first_name'];
}
if ( isset( $automation_data['last_name'] ) && ! empty( $automation_data['last_name'] ) ) {
$args['l_name'] = $automation_data['last_name'];
}
if ( isset( $automation_data['contact_phone'] ) && ! empty( $automation_data['contact_phone'] ) ) {
$args['contact_no'] = $automation_data['contact_phone'];
}
if ( isset( $automation_data['mark_contact_subscribed'] ) && 1 === absint( $automation_data['mark_contact_subscribed'] ) ) {
$args['status'] = 1;
}
/** checking if contact not exists than create otherwise update */
if ( ! $contact instanceof WooFunnels_Contact || 0 === absint( $contact->get_id() ) ) {
new BWFCRM_Contact( $email, true, $args );
} else { // update first_name, last_name, phone and status
$bwfcrm_contact = new BWFCRM_Contact( $contact, false, $args );
$bwfcrm_contact->update( $args );
if ( isset( $automation_data['mark_contact_subscribed'] ) && 1 === absint( $automation_data['mark_contact_subscribed'] ) ) {
$bwfcrm_contact->resubscribe();
}
}
}
/**
* Get WP User object
*
* @param $user_login
* @param $user
*
* @return false|WP_User|null
*/
public static function get_user( $user_login = false, $user = false ) {
if ( ! empty( $user ) && $user instanceof WP_User ) {
return $user;
}
if ( ! empty( $user_login ) ) {
$user = get_user_by( 'login', $user_login );
if ( false === $user ) {
$user = get_user_by( 'email', $user_login );
}
if ( ! empty( $user ) && $user instanceof WP_User ) {
return $user;
}
}
if ( is_user_logged_in() ) {
return wp_get_current_user();
}
return false;
}
/**
* Get paid orders count
*
* @param $renewal_orders
*
* @return int
*/
public static function get_paid_orders_count( $renewal_orders ) {
if ( empty( $renewal_orders ) ) {
return 0;
}
$paid_statuses = wc_get_is_paid_statuses();
if ( empty( $paid_statuses ) ) {
return 0;
}
$orders = array_filter( $renewal_orders, function ( $order_id ) use ( $paid_statuses ) {
$order = wc_get_order( $order_id );
return ( $order instanceof WC_ORDER && $order->has_status( $paid_statuses ) );
} );
return count( $orders );
}
/**
* Get order language
*
* @param $order
*
* @return array|mixed|string
*/
public static function get_order_language( $order ) {
if ( ! $order instanceof WC_Order ) {
return '';
}
if ( function_exists( 'pll_current_language' ) && function_exists( 'pll_get_post_language' ) ) {
$lang = pll_get_post_language( $order->get_id() );
return $lang && is_string( $lang ) ? $lang : '';
}
$meta_key = '';
if ( class_exists( 'woocommerce_wpml' ) ) {
$meta_key = 'wpml_language';
} elseif ( bwfan_is_translatepress_active() ) {
$meta_key = 'trp_language';
} elseif ( function_exists( 'bwfan_is_weglot_active' ) && bwfan_is_weglot_active() ) {
$meta_key = 'weglot_language';
}
return $meta_key ? $order->get_meta( $meta_key ) : '';
}
/**
* Validate scheduled recurring actions
*
* @return void
*/
public static function validate_scheduled_recurring_actions() {
$hooks = [
[
'name' => 'bwfan_run_event_queue',
'time' => MINUTE_IN_SECONDS,
'args' => [],
'group_slug' => ''
],
[
'name' => 'bwfan_run_queue_v2',
'time' => MINUTE_IN_SECONDS,
'args' => [],
'group_slug' => ''
],
[
'name' => 'bwfcrm_broadcast_run_queue',
'time' => MINUTE_IN_SECONDS,
'args' => [],
'group_slug' => 'bwfcrm'
]
];
foreach ( $hooks as $hook ) {
if ( bwf_has_action_scheduled( $hook['name'] ) ) {
continue;
}
bwf_schedule_recurring_action( time(), $hook['time'], $hook['name'], $hook['args'], $hook['group_slug'] );
}
}
/**
* Get contact status list
*
* @return array
*/
public static function get_contact_status_array_list() {
return [
[
'id' => 0,
'name' => __( 'Unverified', 'wp-marketing-automations' ),
'slug' => 'unverify',
'readableText' => __( 'Unverified', 'wp-marketing-automations' ),
'displaystatus' => 3,
'statusAction' => 'unverify',
'statusclass' => 'bwf-tags bwf-tag-gray',
],
[
'id' => 1,
'name' => __( 'Subscribed', 'wp-marketing-automations' ),
'slug' => 'resubscribe',
'readableText' => __( 'Opted In', 'wp-marketing-automations' ),
'displaystatus' => 1,
'statusAction' => 'resubscribe',
'statusclass' => 'bwf-tags bwf-tag-blue',
],
[
'id' => 2,
'name' => __( 'Bounced', 'wp-marketing-automations' ),
'slug' => 'bounced',
'readableText' => __( 'Bounced', 'wp-marketing-automations' ),
'displaystatus' => 4,
'statusAction' => 'bounced',
'statusclass' => 'bwf-tags bwf-tag-red',
],
[
'id' => 3,
'name' => __( 'Unsubscribed', 'wp-marketing-automations' ),
'slug' => 'unsubscribe',
'readableText' => __( 'Unsubscribed', 'wp-marketing-automations' ),
'displaystatus' => 2,
'statusAction' => 'unsubscribe',
'statusclass' => 'bwf-tags bwf-tag-orange',
],
[
'id' => 4,
'name' => __( 'Soft Bounced', 'wp-marketing-automations' ),
'slug' => 'softbounced',
'readableText' => __( 'Soft Bounced', 'wp-marketing-automations' ),
'displaystatus' => 5,
'statusAction' => 'softbounced',
'statusclass' => 'bwf-tags bwf-tag-red',
],
[
'id' => 5,
'name' => __( 'Complaint', 'wp-marketing-automations' ),
'slug' => 'complaint',
'readableText' => __( 'Complaint', 'wp-marketing-automations' ),
'displaystatus' => 6,
'statusAction' => 'complaint',
'statusclass' => 'bwf-tags bwf-tag-red',
]
];
}
/**
* Check if async http call timeout is high and status of the call is not 200
*
* @param $force
*
* @return array|int[]|mixed
*/
public static function validate_core_worker( $force = false ) {
$transient_val = get_transient( 'bwfan_core_worker_async' );
if ( false === $force && false !== $transient_val ) {
return $transient_val;
}
$start_time = microtime( true );
$url = rest_url( '/woofunnels/v1/worker' ) . '?' . time();
$args = array(
'method' => 'GET',
'body' => array(),
'timeout' => 0.01,
'sslverify' => false,
);
$request = wp_remote_post( $url, $args );
$end_time = microtime( true );
$data = [];
if ( 0.2 < ( $end_time - $start_time ) ) {
/** Taking more than 200ms */
$data = [ 'worker_async' => 1 ];
}
/** Check for response code in case of firewall */
$status_code = wp_remote_retrieve_response_code( $request );
if ( ! empty( $status_code ) && $status_code != 200 ) {
$data['response_code'] = $status_code;
set_transient( 'bwfan_core_worker_async', $data, 6 * HOUR_IN_SECONDS );
return [ 'response_code' => $status_code ];
}
set_transient( 'bwfan_core_worker_async', $data, 6 * HOUR_IN_SECONDS );
return $data;
}
public static function check_for_lks() {
if ( ! is_null( self::$c_lk_p ) ) {
return self::$c_lk_p;
}
$data = self::get_lk_data();
$s = isset( $data['s'] ) ? $data['s'] : 0;
$e = isset( $data['e'] ) ? $data['e'] : '';
$ad = isset( $data['ad'] ) ? $data['ad'] : '';
if ( 2 === intval( $s ) ) {
if ( $e === '' ) {
self::$c_lk_p = true;
return self::$c_lk_p;
}
$n = new DateTime();
$et = new DateTime( $e );
if ( $n > $et ) {
$d = $n->diff( $et )->days;
self::$c_lk_p = ( $d < 7 );
return self::$c_lk_p;
}
self::$c_lk_p = true;
return self::$c_lk_p;
}
if ( 1 === intval( $s ) ) {
if ( $ad !== '' ) {
$n = new DateTime();
$adt = new DateTime( $ad );
$d = $n->diff( $adt )->days;
if ( $d < 7 ) {
self::$c_lk_p = true;
return self::$c_lk_p;
}
}
self::$c_lk_p = false;
return self::$c_lk_p;
}
self::$c_lk_p = false;
return self::$c_lk_p;
}
/**
* Get last week date range
*
* @return array
* @throws DateMalformedStringException
*/
public static function get_notification_week_range() {
$dates = [];
$date = new DateTime( current_time( 'mysql', true ) );
if ( 1 !== intval( $date->format( 'N' ) ) ) {
$date->modify( 'last Monday' );
}
$date->setTime( 0, 0, 0 );
$date = $date->modify( '-7 day' );
$dates['from_date'] = $date->format( 'Y-m-d' );
$date = $date->modify( '+6 day' );
$dates['to_date'] = $date->format( 'Y-m-d' );
$date = $date->modify( '-7 day' );
$dates['to_date_previous'] = $date->format( 'Y-m-d' );
$date = $date->modify( '-6 day' );
$dates['from_date_previous'] = $date->format( 'Y-m-d' );
return $dates;
}
/**
* Get last month date range
*
* @return array
* @throws DateMalformedStringException
*/
public static function get_notification_month_range() {
$dates = [];
$date = new DateTime( current_time( 'mysql', true ) );
$date->modify( 'last Month' );
$date->setDate( $date->format( 'Y' ), $date->format( 'm' ), 1 );
$date->setTime( 0, 0, 0 );
$dates['from_date'] = $date->format( 'Y-m-d' );
$last_month = clone $date;
$date->modify( 'last day of this month' );
$dates['to_date'] = $date->format( 'Y-m-d' );
$last_month->modify( 'last Month' );
$last_month->setDate( $last_month->format( 'Y' ), $last_month->format( 'm' ), 1 );
$dates['from_date_previous'] = $last_month->format( 'Y-m-d' );
$last_month->modify( 'last day of this month' );
$dates['to_date_previous'] = $last_month->format( 'Y-m-d' );
return $dates;
}
/**
* Get last day date range
*
* @return array
* @throws DateMalformedStringException
*/
public static function get_notification_day_range() {
$dates = [];
$date = new DateTime( current_time( 'mysql', true ) );
$date->modify( '-1 day' );
$date->setTime( 0, 0, 0 );
$dates['from_date'] = $date->format( 'Y-m-d' );
$dates['to_date'] = $date->format( 'Y-m-d' );
$date->modify( '-1 day' );
$dates['from_date_previous'] = $date->format( 'Y-m-d' );
$dates['to_date_previous'] = $date->format( 'Y-m-d' );
return $dates;
}
/**
* This function deletes engagement meta table's merge tag data from the "Tools" tab.
*
* @return void
*/
public static function delete_engagement_tracking_meta_tool_action() {
$datetime = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
/** Fetched the last engagement ID of engagements from one day ago. */
$datetime->modify( '-1 day' );
$one_day_old = $datetime->format( 'Y-m-d H:i:s' );
global $wpdb;
$query = "SELECT MAX(`ID`) FROM {$wpdb->prefix}bwfan_engagement_tracking WHERE `created_at` < %s";
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$last_id = $wpdb->get_var( $wpdb->prepare( $query, $one_day_old ) );
if ( empty( $last_id ) ) {
bwf_unschedule_actions( 'bwfan_delete_engagement_tracking_meta_tool_action' );
return;
}
$start_time = time();
do {
$query = "DELETE FROM {$wpdb->prefix}bwfan_engagement_trackingmeta WHERE `eid` <= %d AND `meta_key` = %s LIMIT 500";
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
$rows_affected = $wpdb->query( $wpdb->prepare( $query, $last_id, 'merge_tags' ) );
/** If no rows deleted, we're done */
if ( $rows_affected === 0 ) {
bwf_unschedule_actions( 'bwfan_delete_engagement_tracking_meta_tool_action' );
break;
}
} while ( ( time() - $start_time ) < 15 && ! BWFAN_Common::memory_exceeded() );
}
/**
* Schedule email notification daily
*
* @return void
*/
public static function schedule_notification() {
$settings = BWFAN_Common::get_global_settings();
if ( empty( $settings['bwfan_enable_notification'] ) ) {
return;
}
$ins = BWFAN_Notification_Email::get_instance();
$old_settings = $settings;
$old_settings['bwfan_notification_time']['ampm'] = ( 'am' === $settings['bwfan_notification_time']['ampm'] ) ? 'pm' : 'am';
$ins->set_scheduler( $old_settings, $settings );
}
public static function bwfan_get_date_format() {
return ! empty( get_option( 'date_format' ) ) ? get_option( 'date_format' ) : 'Y-m-d';
}
public static function bwfan_get_time_format() {
return ! empty( get_option( 'time_format' ) ) ? get_option( 'time_format' ) : 'g:i a';
}
public static function get_worker_delay_timestamp() {
return ( 60 * apply_filters( 'bwfan_worker_notification_status_delay_var_in_min', 5 ) );
}
/**
* Get the UTC date time value from store date time value
*
* @param $store_date
* @param $format
*
* @return string
*/
public static function get_utc_date_from_store_date( $store_date, $format = 'Y-m-d H:i:s' ) {
if ( empty( $store_date ) ) {
return '';
}
try {
$utc_date = get_gmt_from_date( $store_date, $format );
return $utc_date ?: '';
} catch ( Exception|Error $e ) {
return '';
}
}
public static function get_user_menu_access() {
$user_menu_access = apply_filters( 'bwfan_user_menu_access_data', [] );
$menu_data = [];
if ( ! empty( $user_menu_access ) && isset( $user_menu_access[ get_current_user_id() ] ) ) {
$menu_data = $user_menu_access[ get_current_user_id() ];
}
return $menu_data;
}
/**
* Check advance log enabled
*
* @param $log
*
* @return bool
*/
public static function is_log_enabled( $log ) {
$global_settings = BWFAN_Common::get_global_settings();
return isset( $global_settings['bwfan_advance_logs'] ) && ! empty( $global_settings['bwfan_advance_logs'] ) && isset( $global_settings[ $log ] ) && ! empty( $global_settings[ $log ] );
}
/**
* Get formatted tag & list data if comma exists in value
*
* @param $data
*
* @return array|string[]
*/
public static function check_for_comma_seperated( $data ) {
if ( empty( $data ) || ! is_array( $data ) ) {
return [];
}
$formatted_data = [];
foreach ( $data as $value ) {
if ( ! empty( ( $value['id'] ) ) || false === strpos( $value['value'], ',' ) ) {
$formatted_data[] = $value;
continue;
}
$comma_separated_values = explode( ',', $value['value'] );
$comma_separated_values = array_map( function ( $single_value ) {
return [
'id' => 0,
'value' => trim( $single_value )
];
}, $comma_separated_values );
$formatted_data = array_merge( $formatted_data, $comma_separated_values );
}
return $formatted_data;
}
public static function minifyHtmlData( $content ) {
if ( empty( $content ) ) {
return '';
}
// Remove unnecessary whitespaces and newlines between tags
$htmlMinified = preg_replace( '/\s+/', ' ', $content );
$htmlMinified = preg_replace( '/> ', '><', $htmlMinified ); // Remove space between tags
// Call minifyCSS to handle embedded CSS inside ', $html, 1 );
return $html;
}
private static function mergeDuplicateMediaQueries( $style ) {
// Extract all media queries and their rules
$mediaQueries = [];
$change_resolution = apply_filters( 'bwfan_change_media_query_resolution', '' );
preg_match_all( '/@media[^{]+\{([\s\S]*?)\}}/i', $style, $mediaMatches );
foreach ( $mediaMatches[0] as $mediaQuery ) {
// Split the media query and its rules
$parts = explode( '{', $mediaQuery, 2 );
$query = trim( $parts[0] );
$rules = trim( $parts[1] );
if ( ! empty( $change_resolution ) && intval( $change_resolution ) > 0 ) {
// Update screen sizes from 768px to 480px
$query = preg_replace( '/(\(max-width:\s*)768px(\s*\))/i', '${1}' . $change_resolution . 'px${2}', $query );
}
// Store rules in the mediaQueries array
if ( ! isset( $mediaQueries[ $query ] ) ) {
$mediaQueries[ $query ] = [];
}
if ( str_ends_with( $rules, '}' ) ) {
// Remove the last character (brace) from the string
$rules = substr( $rules, 0, - 1 );
}
$mediaQueries[ $query ][] = $rules;
}
// Combine the media query rules into a single string
$combinedCSS = '';
foreach ( $mediaQueries as $query => $rules ) {
$combinedCSS .= "{$query} { " . implode( ' ', $rules ) . " }\n";
}
// Remove all media queries from the style
$style = preg_replace( '/@media[^{]*{([^{}]*{[^{}]*})*[^{}]*}/', '', $style );
return $style . " " . $combinedCSS;
}
/**
* Callback function for running v2 automation
*
* @param $request
*
* @return void
*/
public static function run_v2_worker_tasks( $request = '' ) {
self::event_advanced_logs( "V2 worker callback received" );
self::worker_as_run();
/** Logs */
$cron_check = self::is_log_enabled( 'bwfan_cron_check_logging' );
if ( true === $cron_check || ( defined( 'BWF_CHECK_CRON_SCHEDULE' ) && true === BWF_CHECK_CRON_SCHEDULE ) ) {
add_filter( 'bwf_logs_allowed', '__return_true', PHP_INT_MAX );
$logger_obj = BWF_Logger::get_instance();
$logger_obj->log( date_i18n( 'Y-m-d H:i:s' ) . ' - after worker run', 'fka-cron-check-v2', 'autonami' );
}
wp_send_json( [
'msg' => 'success',
'time' => date_i18n( 'Y-m-d H:i:s' ),
'datastore' => get_class( ActionScheduler_Store::instance() ),
] );
}
/**
* Validate redirect link by domain
*
* @param $link
* @param $l_hash
* @param $engagement_data
*
* @return mixed|string|null
*/
public static function validate_target_link( $link = '', $l_hash = '', $engagement_data = [] ) {
/** Validate target link if all links not saved and l_hash empty */
if ( empty( get_option( 'bwfan_all_link_saved' ) ) && empty( $l_hash ) ) {
return self::validate_old_target_link( $link, $engagement_data );
}
/** Checking by cleaned url */
$cleaned_url = BWFAN_Core()->conversation->get_cleaned_url( $link );
/** Checking by l_hash & clean url */
if ( ! empty( $l_hash ) ) {
$is_link_exists = BWFAN_Model_Links::is_link_hash_exists( $cleaned_url, $l_hash );
// if link entry not found return home url
if ( empty( $is_link_exists ) ) {
do_action( 'bwfan_invalid_tracking_link', $link );
return home_url();
}
BWFAN_Email_Conversations::$link_id = $is_link_exists;
return $link;
}
/** Checking by link exist in links table */
$is_link_exists = BWFAN_Model_Links::get_link_id_by_tid( $cleaned_url, $engagement_data[0] ?? [] );
if ( ! empty( $is_link_exists ) ) {
BWFAN_Email_Conversations::$link_id = $is_link_exists;
return $link;
}
/** If site url and redirect url host are same */
try {
$link_host = wp_parse_url( urldecode( $link ), PHP_URL_HOST );
$site_url = home_url();
$site_url_host = wp_parse_url( $site_url, PHP_URL_HOST );
} catch ( Error|Exception $e ) {
return $link;
}
if ( $link_host !== $site_url_host ) {
do_action( 'bwfan_invalid_tracking_link', $link );
return home_url();
}
return $link;
}
/**
* Validate old target link if link is not saved
*
* @param $link
* @param $e_data
*
* @return mixed|string|null
*/
public static function validate_old_target_link( $link, $e_data = [] ) {
try {
$link_host = wp_parse_url( urldecode( $link ), PHP_URL_HOST );
$site_url = home_url();
$site_url_host = wp_parse_url( $site_url, PHP_URL_HOST );
} catch ( Error|Exception $e ) {
return $link;
}
/** Checking by cleaned url */
$cleaned_url = BWFAN_Core()->conversation->get_cleaned_url( urldecode( $link ) );
BWFAN_Email_Conversations::$link_id = BWFAN_Model_Links::get_link_id_by_tid( $cleaned_url, $e_data[0] );
/** If site url and redirect url host are same */
if ( $link_host === $site_url_host ) {
return $link;
}
/** Allowed domains */
$allowed_domains = apply_filters( 'bwfan_allowed_redirect_domains', [] );
if ( empty( $allowed_domains ) ) {
return $link;
}
/** Filter valid domains */
$allowed_domains = array_filter( array_map( function ( $domain ) {
return ! empty( $domain ) && is_string( $domain ) ? wp_parse_url( $domain, PHP_URL_HOST ) : false;
}, $allowed_domains ) );
return in_array( $link_host, $allowed_domains, true ) ? $link : $site_url;
}
/**
* Store links
*
* @return void
*/
public static function bwfan_store_template_links() {
$last_id = intval( get_option( 'bwfan_template_links' ) );
BWFAN_Common::log_test_data( 'Template link store process start', 'fk-store-link', true );
global $wpdb;
$email_regex = BWFAN_Common::get_regex_pattern();
$sms_whatsapp_regex = BWFAN_Common::get_regex_pattern( 3 );
$start_time = time();
while ( ( time() - $start_time ) < 15 ) {
$query = "SELECT et.`oid`,et.`sid`,et.`type`,et.`mode`,t.`ID`,t.`template` FROM {$wpdb->prefix}bwfan_templates AS t JOIN {$wpdb->prefix}bwfan_engagement_tracking AS et ON t.`ID`=et.`tid` WHERE tid > $last_id GROUP BY tid LIMIT 20";
$templates = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
if ( empty( $templates ) ) {
bwf_unschedule_actions( 'bwfan_store_template_links' );
delete_option( 'bwfan_template_links' );
update_option( 'bwfan_all_link_saved', true, true );
BWFAN_Common::log_test_data( 'Template link store process complete', 'fk-store-link', true );
break;
}
$template_ids = array_column( $templates, 'ID' );
BWFAN_Common::log_test_data( 'Template ids :' . implode( ',', $template_ids ), 'fk-store-link', true );
foreach ( $templates as $template ) {
$mode = intval( $template['mode'] );
$mode = $mode === BWFAN_Email_Conversations::$MODE_EMAIL ? 'email' : ( $mode === BWFAN_Email_Conversations::$MODE_SMS ? 'sms' : 'whatsapp' );
$regex_pattern = ( $mode === 'email' ) ? $email_regex : $sms_whatsapp_regex;
preg_replace_callback( $regex_pattern, function ( $matches ) use ( $mode, $template ) {
/** According to Href (1) regex, URL is at 1 index. And for Link (3) Regex, 0 index. */
$url = 'email' !== $mode ? $matches[0] : $matches[1];
BWFAN_Common::log_test_data( 'id:' . $template['ID'] . ' URL: ' . $url, 'fk-store-link', true );
if ( BWFAN_Common::is_exclude_url( $url ) ) {
BWFAN_Common::log_test_data( 'exclude url', 'fk-store-link', true );
return $matches[0];
}
/** Exclude click tracking for unsubscribe link and view email browser link*/
if ( false !== strpos( $url, 'bwfan-action=unsubscribe' ) || false !== strpos( $url, 'bwfan-action=view_in_browser' ) ) {
BWFAN_Common::log_test_data( 'unsubscribe or view url', 'fk-store-link', true );
return 'email' !== $mode ? $url : str_replace( $matches[1], $url, $matches[0] );
}
$data = [
'type' => $template['type'],
'oid' => $template['oid'],
'step_id' => $template['sid'],
'template_id' => $template['ID'],
];
/** Save link in DB */
BWFAN_Core()->conversation->get_link_hash( $url, $data );
return 'email' !== $mode ? $url : str_replace( $matches[1], $url, $matches[0] );
}, $template['template'] );
$last_id = $template['ID'];
}
BWFAN_Common::log_test_data( 'Last process template id :' . $last_id, 'fk-store-link', true );
update_option( 'bwfan_template_links', $last_id );
}
BWFAN_Common::log_test_data( 'Template link store process end :', 'fk-store-link', true );
}
/**
* Get mail replace string
*
* @return array
*/
public static function get_mail_replace_string() {
if ( defined( 'BWFAN_PRO_VERSION' ) && version_compare( BWFAN_PRO_VERSION, '3.5.2', '<=' ) ) {
return [];
}
return [
'http-equiv' => md5( 'http-equiv' ),
];
}
/**
* Create contact if not created
*
* @param $user_id
*
* @return void
*/
public static function bwfan_register_user( $user_id ) {
if ( did_action( 'woocommerce_before_checkout_process' ) ) {
return;
}
$db_updater = WooFunnels_DB_Updater::get_instance();
$db_updater->do_profile_update_async_call( $user_id );
define( 'BWF_DISABLE_CONTACT_PROFILE_UPDATE', 1 );
}
/**
* @return string
*
*/
public static function get_wc_tax_label_if_displayed() {
if ( ! wc_tax_enabled() ) {
return '';
}
$tax_display_mode = get_option( 'woocommerce_tax_display_cart' );
$prices_include_tax = wc_prices_include_tax();
if ( $tax_display_mode === 'incl' && ! $prices_include_tax ) {
return WC()->countries->inc_tax_or_vat();
}
if ( $tax_display_mode === 'excl' && $prices_include_tax ) {
return WC()->countries->ex_tax_or_vat();
}
return '';
}
/**
* If constant define then get contact email by user id
*
* @param $user_id
* @param $contact_id
*
* @return string
*/
public static function get_contact_email( $user_id = 0, $contact_id = 0 ) {
if ( ! defined( 'BWFAN_GET_CONTACT_EMAIL' ) || true !== BWFAN_GET_CONTACT_EMAIL || ( empty( $user_id ) && empty( $contact_id ) ) ) {
return '';
}
$contact = new WooFunnels_Contact( $user_id, '', '', $contact_id );
return $contact->get_id() > 0 ? $contact->get_email() : '';
}
/**
* Check language support
*
* @return bool
*/
public static function should_skip_language_support() {
if ( ! function_exists( 'icl_get_languages' ) && ! function_exists( 'pll_the_languages' ) && ( ! function_exists( 'bwfan_is_translatepress_active' ) || ! bwfan_is_translatepress_active() ) && ( ! function_exists( 'bwfan_is_weglot_active' ) || ! bwfan_is_weglot_active() ) && ( ! function_exists( 'bwfan_is_gtranslate_active' ) || ! bwfan_is_gtranslate_active() ) ) {
return true;
}
return false;
}
/**
* Get wp terms id and name array from ids, static query
*
* @param $term_ids
*
* @return array|object|stdClass[]|null
*/
public static function get_wp_term( $term_ids ) {
if ( empty( $term_ids ) ) {
return [];
}
global $wpdb;
$placeholder = array_fill( 0, count( $term_ids ), '%d' );
$placeholder = implode( ', ', $placeholder );
$query = "SELECT `term_id` AS `id`,`name` FROM {$wpdb->prefix}terms WHERE `term_id` IN ($placeholder)";
//phpcs:ignore WordPress.DB.PreparedSQL
$query = $wpdb->prepare( $query, $term_ids );
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $wpdb->get_results( $query, ARRAY_A );
}
/**
* Get product names and id from ids, static query
*
* @param $product_ids
*
* @return array|object|stdClass[]|null
*/
public static function get_products_name( $product_ids ) {
if ( empty( $product_ids ) ) {
return [];
}
global $wpdb;
$placeholder = array_fill( 0, count( $product_ids ), '%d' );
$placeholder = implode( ', ', $placeholder );
$query = "SELECT `ID` AS `id`, `post_title` AS `name`, `post_parent` FROM {$wpdb->prefix}posts WHERE `ID` IN ($placeholder)";
//phpcs:ignore WordPress.DB.PreparedSQL
$query = $wpdb->prepare( $query, $product_ids );
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL
return $wpdb->get_results( $query, ARRAY_A );
}
/**
* Check server memory limit.
* Using 75% max
*
* @return bool
*/
public static function memory_exceeded() {
$memory_limit = self::get_memory_limit() * 0.9;
$current_memory = memory_get_usage( true );
return ( $current_memory >= $memory_limit );
}
/**
* Get the memory limit in bytes.
* If the memory limit is set to -1 or 'unlimited', it will return 32GB.
*
* @return int|mixed
*/
public static function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
$memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce
}
if ( ! $memory_limit || - 1 === $memory_limit || '-1' === $memory_limit ) {
// Unlimited, set to 32GB.
$memory_limit = '32G';
}
return self::convert_hr_to_bytes( $memory_limit );
}
/**
* Converts a shorthand byte value to an integer byte value.
*
* @param $value
*
* @return int|mixed
*/
public static function convert_hr_to_bytes( $value ) {
if ( function_exists( 'wp_convert_hr_to_bytes' ) ) {
return wp_convert_hr_to_bytes( $value );
}
$value = strtolower( trim( $value ) );
$bytes = (int) $value;
if ( false !== strpos( $value, 'g' ) ) {
$bytes *= GB_IN_BYTES;
} elseif ( false !== strpos( $value, 'm' ) ) {
$bytes *= MB_IN_BYTES;
} elseif ( false !== strpos( $value, 'k' ) ) {
$bytes *= KB_IN_BYTES;
}
// Deal with large (float) values which run into the maximum integer size.
return min( $bytes, PHP_INT_MAX );
}
/**
* Get a list of attach actions/filters hook
*
* @param $hook
*
* @return array
* @throws ReflectionException
*/
final public static function get_list_of_attach_actions( $hook ) {
global $wp_filter;
if ( ! isset( $wp_filter[ $hook ] ) || ! $wp_filter[ $hook ] instanceof WP_Hook ) {
return [];
}
$output = [];
$hooks = $wp_filter[ $hook ]->callbacks;
foreach ( $hooks as $priority => $reference ) {
if ( ! is_array( $reference ) || 0 === count( $reference ) ) {
continue;
}
foreach ( $reference as $index => $calls ) {
if ( isset( $calls['function'] ) && is_array( $calls['function'] ) && count( $calls['function'] ) > 0 ) {
if ( is_object( $calls['function'][0] ) ) {
$cls_name = get_class( $calls['function'][0] );
$output[] = [
'type' => 'class',
'class' => $cls_name,
'function' => $calls['function'][1],
'class_path' => self::get_class_path( $cls_name ),
'index' => $index,
'priority' => $priority,
];
} else {
$output[] = [
'type' => 'static_class',
'class' => $calls['function'][0],
'function' => $calls['function'][1],
'class_path' => self::get_class_path( $calls['function'][0] ),
'index' => $index,
'priority' => $priority,
];
}
} else {
$output[] = [
'type' => 'function',
'function' => $calls['function'],
'function_path' => self::get_function_path( $calls['function'] ),
'index' => $index,
'priority' => $priority,
];
}
}
}
return $output;
}
/**
* Get a class path
*
* @param $class
*
* @return string
* @throws ReflectionException
*/
public static function get_class_path( $class = 'BWFAN_Core' ) {
$reflector = new ReflectionClass( $class );
$file_name = $reflector->getFileName();
return dirname( $file_name );
}
/**
* Get a function path
*
* @param $function
*
* @return array|string|string[]
*/
public static function get_function_path( $function = '' ) {
if ( empty( $function ) ) {
return '';
}
try {
$reflector = new ReflectionFunction( $function );
$file_name = $reflector->getFileName();
$directory = dirname( $file_name );
if ( defined( 'WP_CONTENT_DIR' ) ) {
$directory = str_replace( WP_CONTENT_DIR, '', $directory );
}
} catch ( ReflectionException $exception ) {
$directory = $exception->getMessage();
}
return $directory;
}
}