current_action() ) {
$ids = array();
if ( isset( $_REQUEST['id'] ) && is_array( $_REQUEST['id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
$ids = array_map( 'intval', $_REQUEST['id'] ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
$deleted_row_count = empty( $ids ) ? 1 : count( $ids );
$wcf_list_table->process_bulk_action();
/* translators: %d count */
$message = '
' . sprintf( __( 'Items deleted: %d', 'woo-cart-abandonment-recovery' ), $deleted_row_count ) . '
';
set_transient( 'wcf_ca_show_message', $message, 5 );
if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
wp_safe_redirect( esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) );
exit;
}
} elseif ( 'unsubscribe' === $wcf_list_table->current_action() ) {
global $wpdb;
$cart_abandonment_table = $wpdb->prefix . CARTFLOWS_CA_CART_ABANDONMENT_TABLE;
$id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT );
$wpdb->update(
$cart_abandonment_table,
array( 'unsubscribed' => true ),
array( 'id' => $id )
); // db call ok; no-cache ok.
$wcf_list_table->process_bulk_action();
$message = '' . sprintf( __( 'User(s) unsubscribed successfully!', 'woo-cart-abandonment-recovery' ) ) . '
';
set_transient( 'wcf_ca_show_message', $message, 5 );
if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
wp_safe_redirect( esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) );
exit;
}
}
?>
sanitize_text_filter( 'action', 'GET' );
$sub_action = $helper_class->sanitize_text_filter( 'sub_action', 'GET' );
if ( ! $wcar_action ) {
$wcar_action = WCF_ACTION_REPORTS;
$active_settings = '';
$active_reports = '';
$active_email_templates = '';
}
switch ( $wcar_action ) {
case WCF_ACTION_SETTINGS:
$active_settings = 'nav-tab-active';
break;
case WCF_ACTION_REPORTS:
$active_reports = 'nav-tab-active';
break;
case WCF_ACTION_EMAIL_TEMPLATES:
$active_email_templates = 'nav-tab-active';
break;
default:
$active_reports = 'nav-tab-active';
break;
}
// phpcs:disable
?>
WCF_CA_PAGE_NAME,
'action' => WCF_ACTION_REPORTS
), admin_url( '/admin.php' ) )
?>
WCF_CA_PAGE_NAME,
'action' => WCF_ACTION_EMAIL_TEMPLATES
), admin_url( '/admin.php' ) )
?>
WCF_CA_PAGE_NAME,
'action' => WCF_ACTION_SETTINGS
), admin_url( '/admin.php' ) )
?>
sanitize_text_filter( 'filter', 'GET' );
$filter_table = $helper_class->sanitize_text_filter( 'filter_table', 'GET' );
if ( ! $filter ) {
$filter = 'last_month';
}
if ( ! $filter_table ) {
$filter_table = WCF_CART_ABANDONED_ORDER;
}
$from_date = $helper_class->sanitize_text_filter( 'from_date', 'GET' );
$to_date = $helper_class->sanitize_text_filter( 'to_date', 'GET' );
$export_data = filter_input( INPUT_GET, 'export_data', FILTER_VALIDATE_BOOLEAN );
switch ( $filter ) {
case 'yesterday':
$to_date = gmdate( 'Y-m-d', strtotime( '-1 days' ) );
$from_date = $to_date;
break;
case 'today':
$to_date = gmdate( 'Y-m-d' );
$from_date = $to_date;
break;
case 'last_week':
$from_date = gmdate( 'Y-m-d', strtotime( '-7 days' ) );
$to_date = gmdate( 'Y-m-d' );
break;
case 'last_month':
$from_date = gmdate( 'Y-m-d', strtotime( '-1 months' ) );
$to_date = gmdate( 'Y-m-d' );
break;
case 'custom':
$to_date = $to_date ? $to_date : gmdate( 'Y-m-d' );
$from_date = $from_date ? $from_date : $to_date;
break;
}
$abandoned_report = $this->get_report_by_type( $from_date, $to_date, WCF_CART_ABANDONED_ORDER );
$recovered_report = $this->get_report_by_type( $from_date, $to_date, WCF_CART_COMPLETED_ORDER );
$lost_report = $this->get_report_by_type( $from_date, $to_date, WCF_CART_LOST_ORDER );
$wcf_list_table = Cartflows_Ca_Order_Table::get_instance();
$wcf_list_table->prepare_items( $filter_table, $from_date, $to_date );
if ( $export_data ) {
$wpnonce = Cartflows_Ca_Helper::get_instance()->sanitize_text_filter( 'security', 'GET' );
if ( $wpnonce && wp_verify_nonce( $wpnonce, 'wcf_ca_export_orders' ) && current_user_can( 'manage_woocommerce' ) ) {
$this->download_send_headers();
// Here we are downloading the CSV file. Hence no escaping required.
echo $this->array2csv( $wcf_list_table->items ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
die;
}
}
$conversion_rate = 0;
$total_orders = ( $recovered_report['no_of_orders'] + $abandoned_report['no_of_orders'] + $lost_report['no_of_orders'] );
if ( $total_orders ) {
$conversion_rate = ( $recovered_report['no_of_orders'] / $total_orders ) * 100;
}
global $woocommerce;
$conversion_rate = number_format_i18n( $conversion_rate, 2 );
$currency_symbol = get_woocommerce_currency_symbol();
require_once CARTFLOWS_CART_ABANDONMENT_TRACKING_DIR . 'includes/cartflows-cart-abandonment-reports.php';
}
/**
* Send headers to export orders to csv format.
*/
public function download_send_headers() {
$now = gmdate( 'Y-m-d-H-i-s' );
$filename = 'woo-cart-abandonment-recovery-export-' . $now . '.csv';
header( 'Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate' );
header( "Last-Modified: {$now} GMT" );
// force download.
header( 'Content-Type: application/force-download' );
header( 'Content-Type: application/octet-stream' );
header( 'Content-Type: application/download' );
// disposition / encoding on response body.
header( "Content-Disposition: attachment;filename={$filename}" );
header( 'Content-Transfer-Encoding: binary' );
}
/**
* Convert users data to csv format.
*
* @param array $user_data users data.
*/
public function array2csv( array $user_data ) {
if ( empty( $user_data ) ) {
return;
}
ob_clean();
ob_start();
$data_file = fopen( 'php://output', 'w' );
// Ignoring below rule as we are not working on wp directory and do not require path.
fputcsv( //phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_fputcsv
$data_file,
array(
'First-Name',
'Last-Name',
'Email',
'Phone',
'Products',
'Cart-Total in ' . get_woocommerce_currency(),
'Order-Status',
'Unsubscribed',
'Coupon-Code',
)
);
foreach ( $user_data as $data ) {
$name = maybe_unserialize( $data['other_fields'] );
$checkout_details = Cartflows_Ca_Helper::get_instance()->get_checkout_details( $data['session_id'] );
$cart_data = Cartflows_Ca_Helper::get_instance()->get_comma_separated_products( $checkout_details->cart_contents );
fputcsv( //phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_fputcsv
$data_file,
array_map(
'esc_html',
array(
$name['wcf_first_name'],
$name['wcf_last_name'],
$data['email'],
$name['wcf_phone_number'],
$cart_data,
$data['cart_total'],
$data['order_status'],
$data['unsubscribed'] ? 'Yes' : 'No',
$data['coupon_code'],
)
)
);
}
fclose( $data_file );
return ob_get_clean();
}
/**
* Get Attributable revenue.
* Represents the revenue generated by this campaign.
*
* @param string $from_date from date.
* @param string $to_date to date.
* @param string $type abondened|completed.
*/
public function get_report_by_type( $from_date, $to_date, $type = WCF_CART_ABANDONED_ORDER ) {
global $wpdb;
$cart_abandonment_table = $wpdb->prefix . CARTFLOWS_CA_CART_ABANDONMENT_TABLE;
$minutes = wcf_ca()->utils->get_cart_abandonment_tracking_cut_off_time();
// Can't use placeholders for table/column names, it will be wrapped by a single quote (') instead of a backquote (`).
$attributable_revenue = $wpdb->get_row(
$wpdb->prepare( "SELECT SUM(`cart_total`) as revenue, count('*') as no_of_orders FROM {$cart_abandonment_table} WHERE `order_status` = %s AND DATE(`time`) >= %s AND DATE(`time`) <= %s ", $type, $from_date, $to_date ), // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
ARRAY_A
); // db call ok; no-cache ok.
return $attributable_revenue;
}
/**
* Show report details for specific order.
*/
public function wcf_display_report_details() {
$sesson_id = Cartflows_Ca_Helper::get_instance()->sanitize_text_filter( 'session_id', 'GET' );
if ( $sesson_id ) {
$details = Cartflows_Ca_Helper::get_instance()->get_checkout_details( $sesson_id );
$user_details = (object) maybe_unserialize( $details->other_fields );
$scheduled_emails = Cartflows_Ca_Helper::get_instance()->fetch_scheduled_emails( $sesson_id );
require_once CARTFLOWS_CART_ABANDONMENT_TRACKING_DIR . 'includes/cartflows-ca-single-report-details.php';
}
}
/**
* Generate the view for admin product cart block.
*
* @param string $cart_contents user cart contents details.
* @param float $cart_total user cart total.
* @return string
*/
public function get_admin_product_block( $cart_contents, $cart_total ) {
$cart_items = maybe_unserialize( $cart_contents );
if ( ! is_array( $cart_items ) || ! count( $cart_items ) ) {
return;
}
$tr = '';
$total = 0;
$discount = 0;
$tax = 0;
foreach ( $cart_items as $cart_item ) {
if ( isset( $cart_item['product_id'] ) && isset( $cart_item['quantity'] ) && isset( $cart_item['line_total'] ) && isset( $cart_item['line_subtotal'] ) ) {
$id = 0 !== $cart_item['variation_id'] ? $cart_item['variation_id'] : $cart_item['product_id'];
$discount = $discount + ( $cart_item['line_subtotal'] - $cart_item['line_total'] );
$total = $total + $cart_item['line_subtotal'];
$tax = $tax + $cart_item['line_tax'];
$image_url = get_the_post_thumbnail_url( $id );
$image_url = ! empty( $image_url ) ? $image_url : get_the_post_thumbnail_url( $cart_item['product_id'] );
$product = wc_get_product( $id );
$product_name = $product ? $product->get_formatted_name() : '';
if ( empty( $image_url ) ) {
$image_url = CARTFLOWS_CA_URL . 'admin/assets/images/image-placeholder.png';
}
$custom_field_data = '';
$custom_field_data = wp_kses( wc_get_formatted_cart_item_data( $cart_item ), array( 'ul', 'li' ) );
if ( ! empty( $custom_field_data ) ) {
$custom_field_data = '' . __( 'Product Custom Data: ', 'woo-cart-abandonment-recovery' ) . '
' . $custom_field_data;
}
$tr = $tr . '
|
' . $product_name . ' ' . $custom_field_data . ' |
' . $cart_item['quantity'] . ' |
' . wc_price( $cart_item['line_total'] ) . ' |
' . wc_price( $cart_item['line_total'] ) . ' |
';
}
}
return '
' . __( 'Item', 'woo-cart-abandonment-recovery' ) . ' |
' . __( 'Name', 'woo-cart-abandonment-recovery' ) . ' |
' . __( 'Quantity', 'woo-cart-abandonment-recovery' ) . ' |
' . __( 'Price', 'woo-cart-abandonment-recovery' ) . ' |
' . __( 'Line Subtotal', 'woo-cart-abandonment-recovery' ) . ' |
' . $tr . '
' . __( 'Discount', 'woo-cart-abandonment-recovery' ) . ' |
' . wc_price( $discount ) . ' |
' . __( 'Other', 'woo-cart-abandonment-recovery' ) . ' |
' . wc_price( $tax ) . ' |
' . __( 'Shipping', 'woo-cart-abandonment-recovery' ) . ' |
' . wc_price( $discount + ( $cart_total - $total ) - $tax ) . ' |
' . __( 'Cart Total', 'woo-cart-abandonment-recovery' ) . ' |
' . wc_price( $cart_total ) . ' |
';
}
/**
* Check and show warning message if cart abandonment is disabled.
*/
public function wcf_show_warning_ca() {
$settings_url = add_query_arg(
array(
'page' => WCF_CA_PAGE_NAME,
'action' => WCF_ACTION_SETTINGS,
),
admin_url( '/admin.php' )
);
if ( ! wcf_ca()->utils->is_cart_abandonment_tracking_enabled() ) {
?>