Abandoned Cart Lite for WooCommerce - Version 4.3

Version Description

(29.08.2017) =

  • This version has 1 bug fix along with 3 Enhancements.

  • Bug Fixed - When abandoned cart will have a variable product which has 3 attributes or more than that. Then the slug name of selected variations were showing in the abandoned cart reminder emails and on the abandoned cart details page. This has been fixed.

  • Enhancement - If the abandoned cart total is zero then abandoned cart reminder emails will not be sent to the customers.

  • Enhancement - When the email sending script is executed on the server, it was running a large number of MySQL queries for guest users. That was causing an increase in the server load. In this version, we have optimised the queries. Initially, it used to query even those guest user records for which emails were already sent. Now, it will only query those records where email is yet to be sent.

  • Enhancement - Removed the Active field from the add / edit email template page. Admin can activate or deactivate the templates from the Email templates page.

Download this release

Release Info

Developer bhavik.kiri
Plugin Icon 128x128 Abandoned Cart Lite for WooCommerce
Version 4.3
Comparing to
See all releases

Code changes from version 4.2 to 4.3

Files changed (3) hide show
  1. cron/wcal_send_email.php +407 -321
  2. readme.txt +48 -15
  3. woocommerce-ac.php +236 -131
cron/wcal_send_email.php CHANGED
@@ -47,13 +47,6 @@ if ( !class_exists( 'woocommerce_abandon_cart_cron' ) ) {
47
  $time_to_send_template_after = $value->frequency * $hour_seconds;
48
  }
49
  $carts = $this->wcal_get_carts( $time_to_send_template_after, $cart_abandon_cut_off_time );
50
- /**
51
- * When there are 3 templates and for cart id 1 all template time has been reached. BUt all templates are deactivated.
52
- * If we activate all 3 template then at a 1 time all 3 email templates send to the users.
53
- * So below function check that after first email is sent time and then from that time it will send the 2nd template time. ( It will not consider the cart abadoned time in this case. )
54
- */
55
- $carts = $this->wcal_remove_cart_for_mutiple_templates( $carts, $time_to_send_template_after, $value->id );
56
- $carts = woocommerce_abandon_cart_cron ::wcal_update_abandoned_cart_status_for_placed_orders ( $carts, $time_to_send_template_after );
57
  $email_frequency = $value->frequency;
58
  $email_body_template = $value->body;
59
  $email_subject = stripslashes ( $value->subject );
@@ -96,217 +89,288 @@ if ( !class_exists( 'woocommerce_abandon_cart_cron' ) ) {
96
  if( isset( $value->abandoned_cart_info ) ) {
97
  $cart_info_db_field = json_decode( $value->abandoned_cart_info );
98
  }
 
 
 
 
99
  if( count( $cart_info_db_field->cart ) > 0 && isset( $value->user_id ) && $value->user_id != '0') {
100
  $cart_update_time = $value->abandoned_cart_time;
101
  $new_user = $this->wcal_check_sent_history( $value->user_id, $cart_update_time, $template_id, $value->id );
102
  if ( $new_user == true ) {
103
- $cart_info_db = $value->abandoned_cart_info;
104
- $email_body = $email_body_template;
105
- if ( $value->user_type == "GUEST" ) {
106
- if ( isset( $results_guest[0]->billing_first_name ) ) {
107
- $email_body = str_replace( "{{customer.firstname}}", $results_guest[0]->billing_first_name, $email_body );
108
- $email_subject = str_replace( "{{customer.firstname}}", $results_guest[0]->billing_first_name, $email_subject );
109
- }
110
- if ( isset( $results_guest[0]->billing_last_name ) ) {
111
- $email_body = str_replace( "{{customer.lastname}}", $results_guest[0]->billing_last_name, $email_body );
112
- }
113
- if ( isset( $results_guest[0]->billing_first_name ) && isset( $results_guest[0]->billing_last_name ) ) {
114
- $email_body = str_replace( "{{customer.fullname}}", $results_guest[0]->billing_first_name." ".$results_guest[0]->billing_last_name, $email_body );
115
- }
116
- else if ( isset( $results_guest[0]->billing_first_name ) ) {
117
- $email_body = str_replace( "{{customer.fullname}}", $results_guest[0]->billing_first_name, $email_body );
118
- }
119
- else if ( isset( $results_guest[0]->billing_last_name ) ) {
120
- $email_body = str_replace( "{{customer.fullname}}", $results_guest[0]->billing_last_name, $email_body );
121
- }
122
- } else {
123
- $user_first_name = '';
124
- $user_first_name_temp = get_user_meta( $value->user_id, 'billing_first_name', true );
125
- if( isset( $user_first_name_temp ) && "" == $user_first_name_temp ) {
126
- $user_data = get_userdata( $user_id );
127
- $user_first_name = $user_data->first_name;
128
- } else {
129
- $user_first_name = $user_first_name_temp;
130
- }
131
- $email_body = str_replace( "{{customer.firstname}}", $user_first_name, $email_body );
132
- $email_subject = str_replace( "{{customer.firstname}}", $user_first_name, $email_subject );
133
- $user_last_name = '';
134
- $user_last_name_temp = get_user_meta( $value->user_id, 'billing_last_name', true );
135
- if( isset( $user_last_name_temp ) && "" == $user_last_name_temp ) {
136
- $user_data = get_userdata( $user_id );
137
- $user_last_name = $user_data->last_name;
138
- } else {
139
- $user_last_name = $user_last_name_temp;
140
- }
141
- $email_body = str_replace( "{{customer.lastname}}", $user_last_name, $email_body );
142
- $email_body = str_replace( "{{customer.fullname}}", $user_first_name." ".$user_last_name, $email_body );
143
- }
144
- $order_date = "";
145
- if( $cart_update_time != "" && $cart_update_time != 0 ) {
146
- $date_format = date_i18n( get_option( 'date_format' ), $cart_update_time );
147
- $time_format = date_i18n( get_option( 'time_format' ), $cart_update_time );
148
- $order_date = $date_format . ' ' . $time_format;
149
- }
150
- $email_body = str_replace( "{{cart.abandoned_date}}", $order_date, $email_body );
151
- $query_sent = "INSERT INTO `".$wpdb->prefix."ac_sent_history_lite` ( template_id, abandoned_order_id, sent_time, sent_email_id )
152
- VALUES ( %s, %s, '".current_time( 'mysql' )."', %s )";
153
-
154
- $wpdb->query( $wpdb->prepare( $query_sent, $template_id, $value->id, $value->user_email ) );
155
-
156
- $query_id = "SELECT * FROM `".$wpdb->prefix."ac_sent_history_lite`
157
- WHERE template_id = %s AND abandoned_order_id = %s
158
- ORDER BY id DESC
159
- LIMIT 1 ";
160
- $results_sent = $wpdb->get_results( $wpdb->prepare( $query_id, $template_id, $value->id ) );
161
- $email_sent_id = $results_sent[0]->id;
162
-
163
- if( $woocommerce->version < '2.3' ) {
164
- $cart_page_link = $woocommerce->cart->get_cart_url();
165
- } else {
166
- $cart_page_id = woocommerce_get_page_id( 'cart' );
167
- $cart_page_link = $cart_page_id ? get_permalink( $cart_page_id ) : '';
168
  }
169
-
170
- $encoding_cart = $email_sent_id.'&url='.$cart_page_link;
171
- $validate_cart = $this->wcal_encrypt_validate( $encoding_cart );
172
- $cart_link_track = get_option('siteurl').'/?wcal_action=track_links&validate=' . $validate_cart;
173
- $email_body = str_replace( "{{cart.link}}", $cart_link_track, $email_body );
174
-
175
- $validate_unsubscribe = $this->wcal_encrypt_validate( $email_sent_id );
176
- $email_sent_id_address = $results_sent[0]->sent_email_id;
177
- $encrypt_email_sent_id_address = hash( 'sha256', $email_sent_id_address );
178
- $plugins_url = get_option( 'siteurl' ) . "/?wcal_track_unsubscribe=wcal_unsubscribe&validate=" . $validate_unsubscribe . "&track_email_id=" . $encrypt_email_sent_id_address;
179
- $unsubscribe_link_track = $plugins_url;
180
- $email_body = str_replace( "{{cart.unsubscribe}}" , $unsubscribe_link_track , $email_body );
181
- $var = '';
182
- if( preg_match( "{{products.cart}}", $email_body, $matched ) ) {
183
- if ( class_exists( 'WP_Better_Emails' ) ) {
184
- $var = '<table width = 100%>
185
- <tr> <td colspan="5"> <h3>'.__( "Your Shopping Cart", "woocommerce-ac" ).'</h3> </td></tr>
186
- <tr>
187
- <th>'.__( "Item", "woocommerce-ac" ).'</th>
188
- <th>'.__( "Name", "woocommerce-ac" ).'</th>
189
- <th>'.__( "Quantity", "woocommerce-ac" ).'</th>
190
- <th>'.__( "Price", "woocommerce-ac" ).'</th>
191
- <th>'.__( "Line Subtotal", "woocommerce-ac" ).'</th>
192
- </tr>';
193
- } else {
194
- $var = '<h3>'.__( "Your Shopping Cart", "woocommerce-ac" ).'</h3>
195
- <table border="0" cellpadding="10" cellspacing="0" class="templateDataTable">
196
- <tr>
197
- <th>'.__( "Item", "woocommerce-ac" ).'</th>
198
- <th>'.__( "Name", "woocommerce-ac" ).'</th>
199
- <th>'.__( "Quantity", "woocommerce-ac" ).'</th>
200
- <th>'.__( "Price", "woocommerce-ac" ).'</th>
201
- <th>'.__( "Line Subtotal", "woocommerce-ac" ).'</th>
202
- </tr>';
203
- }
204
- $cart_details = $cart_info_db_field->cart;
205
- $cart_total = $item_subtotal = $item_total = 0;
206
- $sub_line_prod_name = '';
207
- foreach ( $cart_details as $k => $v ) {
208
- $quantity_total = $v->quantity;
209
- $product_id = $v->product_id;
210
- $prod_name = get_post( $product_id );
211
- $product_link_track = get_permalink( $product_id );
212
- $product_name = $prod_name->post_title;
213
- if( $sub_line_prod_name == '' ) {
214
- $sub_line_prod_name = $product_name;
215
- }
216
- // Item subtotal is calculated as product total including taxes
217
- if( $v->line_subtotal_tax != 0 && $v->line_subtotal_tax > 0 ) {
218
- $item_subtotal = $item_subtotal + $v->line_total + $v->line_subtotal_tax;
219
  } else {
220
- $item_subtotal = $item_subtotal + $v->line_total;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  }
222
- // Line total
223
- $item_total = $item_subtotal;
224
- $item_subtotal = $item_subtotal / $quantity_total;
225
- $item_total_display = wc_price( $item_total );
226
- $item_subtotal = wc_price( $item_subtotal );
227
- $product = wc_get_product( $product_id );
228
- $prod_image = $product->get_image();
229
- $image_url = wp_get_attachment_url( get_post_thumbnail_id( $product_id ) );
230
- if ( isset( $v->variation_id ) && '' != $v->variation_id ) {
231
- $variation_id = $v->variation_id;
232
- $variation = wc_get_product( $variation_id );
233
- $name = $variation->get_formatted_name() ;
234
- $explode_all = explode ( "&ndash;", $name );
235
- if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
236
-
237
- $attributes = $explode_all[1];
238
- $explode_attributes = explode( "(#" , $attributes) ;
239
- if (isset($explode_attributes [0])){
240
- $add_product_name = $product_name . "," . $explode_attributes[0];
241
- $pro_name_variation = (array) $add_product_name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  }
243
- }else{
244
- $pro_name_variation = array_slice( $explode_all, 1, -1 );
245
- }
246
- $product_name_with_variable = '';
247
- $explode_many_varaition = array();
248
- foreach ( $pro_name_variation as $pro_name_variation_key => $pro_name_variation_value ){
249
- $explode_many_varaition = explode ( ",", $pro_name_variation_value );
250
- if ( !empty( $explode_many_varaition ) ) {
251
- foreach( $explode_many_varaition as $explode_many_varaition_key => $explode_many_varaition_value ){
252
- $product_name_with_variable = $product_name_with_variable . "<br>". html_entity_decode ( $explode_many_varaition_value );
253
- }
254
  } else {
255
- $product_name_with_variable = $product_name_with_variable . "<br>". html_entity_decode ( $explode_many_varaition_value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  }
257
- }
258
- $product_name = $product_name_with_variable;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  }
260
- $var .='<tr align="center">
261
- <td> <a href="'.$cart_link_track.'"> <img src="' . $image_url . '" alt="" height="42" width="42" /> </a></td>
262
- <td> <a href="'.$cart_link_track.'">'.__( $product_name, "woocommerce-ac" ).'</a></td>
263
- <td> '.$quantity_total.'</td>
264
- <td> '.$item_subtotal.'</td>
265
- <td> '.$item_total_display.'</td>
266
- </tr>';
267
- $cart_total += $item_total;
268
- $item_subtotal = $item_total = 0;
269
- }
270
- $cart_total = wc_price( $cart_total );
271
- $var .= '<tr align="center">
272
- <td> </td>
273
- <td> </td>
274
- <td> </td>
275
- <td>'.__( "Cart Total:", "woocommerce-ac" ).'</td>
276
- <td> '.$cart_total.'</td>
277
- </tr>';
278
- $var .= '</table>
279
- ';
280
- $email_body = str_replace( "{{products.cart}}", $var, $email_body );
281
- $email_subject = str_replace( "{{product.name}}", __( $sub_line_prod_name, "woocommerce-ac" ), $email_subject );
282
  }
283
-
284
- $user_email = $value->user_email;
285
- $email_body_final = stripslashes( $email_body );
286
- $email_body_final = convert_smilies( $email_body_final );
287
- if ( isset( $is_wc_template ) && "1" == $is_wc_template ){
288
- ob_start();
289
-
290
- wc_get_template( 'emails/email-header.php', array( 'email_heading' => $wc_template_header ) );
291
- $email_body_template_header = ob_get_clean();
292
-
293
- ob_start();
294
-
295
- wc_get_template( 'emails/email-footer.php' );
296
- $email_body_template_footer = ob_get_clean();
297
-
298
- $final_email_body = $email_body_template_header . $email_body_final . $email_body_template_footer;
299
-
300
- wc_mail( $user_email, $email_subject, $final_email_body, $headers );
301
-
302
- } else {
303
- wp_mail( $user_email, $email_subject, __( $email_body_final, 'woocommerce-ac' ), $headers );
304
- }
305
  }
306
  }
307
  }
308
  }
309
  }
 
 
 
 
 
 
 
 
 
310
  }
311
  /**
312
  * get all carts which have the creation time earlier than the one that is passed
@@ -326,151 +390,173 @@ if ( !class_exists( 'woocommerce_abandon_cart_cron' ) ) {
326
  exit;
327
  }
328
 
329
- public static function wcal_update_abandoned_cart_status_for_placed_orders( $carts, $time_to_send_template_after ){
330
  global $wpdb;
331
- foreach( $carts as $carts_key => $carts_value ) {
332
- $abandoned_cart_time = $carts_value->abandoned_cart_time;
333
- $user_id = $carts_value->user_id;
334
- $user_type = $carts_value->user_type;
335
- $cart_id = $carts_value->id;
336
- if( $user_id >= '63000000' && 'GUEST' == $user_type ) {
337
- $query_guest_records = "SELECT id FROM `" . $wpdb->prefix . "ac_guest_abandoned_cart_history_lite` ORDER BY id DESC LIMIT 1";
338
- $results_guest_list = $wpdb->get_results( $query_guest_records );
339
- $last_guest_id = 0 ;
340
- $get_last_checked_id = get_option( 'wcal_guest_last_id_checked' );
341
- if( isset( $results_guest_list ) && count( $results_guest_list ) > 0 ) {
342
- $last_guest_id = $results_guest_list[0]->id;
343
- }
344
- if( false == $get_last_checked_id || $get_last_checked_id <= $last_guest_id ) {
345
- $updated_value = woocommerce_abandon_cart_cron ::wcal_update_status_of_guest( $cart_id, $abandoned_cart_time , $time_to_send_template_after );
346
- if( 1 == $updated_value ) {
347
- unset ( $carts [ $carts_key ] );
348
- }
349
- update_option ( 'wcal_guest_last_id_checked' , $last_guest_id );
350
- }
351
- } elseif ( $user_id < '63000000' && 'REGISTERED' == $user_type ) {
352
- $updated_value = woocommerce_abandon_cart_cron ::wcal_update_status_of_loggedin ( $cart_id, $abandoned_cart_time , $time_to_send_template_after );
353
- if( 1 == $updated_value ) {
354
- unset( $carts [ $carts_key ] );
355
- }
356
  }
357
  }
358
- return $carts;
359
  }
360
 
361
- public static function wcal_update_status_of_guest( $cart_id, $abandoned_cart_time , $time_to_send_template_after ) {
362
  global $wpdb;
363
- $get_last_checked_id = get_option( 'wcal_guest_last_id_checked' );
364
 
365
- $query_guest_records = "SELECT wacgh.id, wacgh.email_id FROM `" . $wpdb->prefix . "ac_guest_abandoned_cart_history_lite` as wacgh LEFT JOIN " . $wpdb->prefix . "ac_abandoned_cart_history_lite AS wpac ON wacgh.id = wpac.user_id WHERE wpac.id = $cart_id ";
366
- $results_guest_list = $wpdb->get_results( $query_guest_records );
367
- // This is to ensure that recovered guest carts r removed from the delete list
368
-
369
- if ( count( $results_guest_list ) > 0 ) {
 
 
370
 
371
- $wcal_user_email_address = $results_guest_list[0]->email_id;
372
  $current_time = current_time( 'timestamp' );
373
  $todays_date = date( 'Y-m-d', $current_time );
374
- $query_email_id = "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID Order BY wpm.post_id DESC LIMIT 1";
375
-
376
- $results_query_email = $wpdb->get_results( $wpdb->prepare( $query_email_id, $wcal_user_email_address ) );
377
-
378
- /* This will check that For abc@abc.com email address we have order for todays date in WC post table */
379
- if ( count( $results_query_email ) > 0 ) {
380
- $order_date_with_time = $results_query_email[0]->post_date;
381
- $order_date = substr( $order_date_with_time, 0, 10 );
382
-
383
- if ( $order_date == $todays_date ) {
384
- $query_ignored = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
385
- $wpdb->query( $query_ignored );
386
- return 1;
387
- } else if ( strtotime( $order_date_with_time ) > $abandoned_cart_time ) {
388
- $query_ignored = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
389
- $wpdb->query( $query_ignored );
390
- return 1;
391
- } else if( $results_query_email[0]->post_status == "wc-pending" || $results_query_email[0]->post_status == "wc-failed" ) {
392
-
393
- /* If the post status are pending or failed the send them for abandoned cart reminder emails */
394
- return 0;
 
 
 
 
 
 
 
 
 
395
  }
396
-
397
- }
398
- }
399
- return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
  }
401
 
402
- public static function wcal_update_status_of_loggedin( $cart_id, $abandoned_cart_time , $time_to_send_template_after ) {
403
- global $wpdb;
404
- // Update the record of the loggedin user who had paid before the first abandoned cart reminder email send to customer.
405
- $query_records = "SELECT DISTINCT user_id FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE user_type = 'REGISTERED' AND id = $cart_id AND recovered_cart = '0'";
406
- $results_list = $wpdb->get_results( $query_records );
407
- foreach( $results_list as $key => $value ) {
408
- $user_id = $value->user_id;
409
- $key = 'billing_email';
410
- $single = true;
411
- $user_billing_email = get_user_meta( $user_id, $key, $single );
412
- if( isset( $user_billing_email ) && $user_billing_email == '' ) {
413
- $user_id = $value->user_id;
414
- if( is_multisite() ) {
415
- $main_prefix = $wpdb->get_blog_prefix(1);
416
- $query_email = "SELECT user_email FROM `".$main_prefix."users` WHERE ID = %d";
417
- } else {
418
- $query_email = "SELECT user_email FROM `".$wpdb->prefix."users` WHERE ID = %d";
419
- }
420
- $results_email = $wpdb->get_results( $wpdb->prepare( $query_email, $user_id ) );
421
- if( !empty( $results_email[0]->user_email ) ) {
422
- $user_billing_email = $results_email[0]->user_email;
423
- }
424
- }
425
- $query_email_id = "SELECT post_id FROM `" . $wpdb->prefix . "postmeta` WHERE meta_key = '_billing_email' AND meta_value = %s";
426
- $results_query_email = $wpdb->get_results( $wpdb->prepare( $query_email_id, $user_billing_email ) );
427
- //if any orders are found with the same email addr..delete those ac records
428
- if( is_array( $results_query_email ) && count( $results_query_email ) > 0 ) {
429
- for( $i = 0; $i < count( $results_query_email ); $i++ ) {
430
- $cart_abandoned_time = date ('Y-m-d h:i:s', $abandoned_cart_time);
431
- $query_post = "SELECT post_date,post_status FROM `" . $wpdb->prefix . "posts` WHERE ID = %d AND post_date >= %s";
432
- $results_post = $wpdb->get_results( $wpdb->prepare( $query_post, $results_query_email[ $i ]->post_id, $cart_abandoned_time ) );
433
- if( count ($results_post) > 0 ) {
434
- $current_time = current_time( 'timestamp' );
435
- $todays_date = date( 'Y-m-d', $current_time );
436
- $order_date_time = $results_post[0]->post_date;
437
- $order_date = substr( $order_date_time, 0, 10 );
438
-
439
- if ( $order_date == $todays_date ) {
440
- $query_ignored = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
441
- $wpdb->query( $query_ignored );
442
- return 1;
443
- } else if ( strtotime( $order_date_time ) >= $abandoned_cart_time ) {
444
- $query_ignored = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
445
- $wpdb->query( $query_ignored );
446
- return 1; //We return here 1 so it indicate that the cart has been modifed so do not sent email and delete from the array.
447
- } else if( $results_post[0]->post_status == "wc-pending" || $results_post[0]->post_status == "wc-failed" ) {
448
- return 0; //if status of the order is pending or falied then return 0 so it will not delete that cart and send reminder email
449
- }
450
  }
 
 
 
 
451
  }
 
 
 
 
 
 
 
452
  }
453
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
454
  return 0;
455
  }
456
 
457
 
458
- public static function wcal_remove_cart_for_mutiple_templates( $carts, $time_to_send_template_after, $template_id ) {
459
  global $wpdb;
460
 
461
- foreach( $carts as $carts_key => $carts_value ) {
462
- $wcal_get_last_email_sent_time = "SELECT * FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = $carts_value->id ORDER BY `sent_time` DESC LIMIT 1";
463
- $wcal_get_last_email_sent_time_results_list = $wpdb->get_results( $wcal_get_last_email_sent_time );
464
- if( count( $wcal_get_last_email_sent_time_results_list ) > 0 ) {
465
- $last_template_send_time = strtotime( $wcal_get_last_email_sent_time_results_list[0]->sent_time );
466
- $second_template_send_time = $last_template_send_time + $time_to_send_template_after ;
467
- $current_time_test = current_time( 'timestamp' );
468
- if( $second_template_send_time > $current_time_test ) {
469
- unset( $carts [ $carts_key ] );
470
- }
471
  }
472
  }
473
- return $carts;
 
474
  }
475
  /******
476
  * This function is used to encode the validate string.
47
  $time_to_send_template_after = $value->frequency * $hour_seconds;
48
  }
49
  $carts = $this->wcal_get_carts( $time_to_send_template_after, $cart_abandon_cut_off_time );
 
 
 
 
 
 
 
50
  $email_frequency = $value->frequency;
51
  $email_body_template = $value->body;
52
  $email_subject = stripslashes ( $value->subject );
89
  if( isset( $value->abandoned_cart_info ) ) {
90
  $cart_info_db_field = json_decode( $value->abandoned_cart_info );
91
  }
92
+ $cart = array();
93
+ if( !empty( $cart_info_db_field ) ) {
94
+ $cart = $cart_info_db_field->cart;
95
+ }
96
  if( count( $cart_info_db_field->cart ) > 0 && isset( $value->user_id ) && $value->user_id != '0') {
97
  $cart_update_time = $value->abandoned_cart_time;
98
  $new_user = $this->wcal_check_sent_history( $value->user_id, $cart_update_time, $template_id, $value->id );
99
  if ( $new_user == true ) {
100
+
101
+ /**
102
+ * When there are 3 templates and for cart id 1 all template time has been reached. BUt all templates are deactivated.
103
+ * If we activate all 3 template then at a 1 time all 3 email templates send to the users.
104
+ * So below function check that after first email is sent time and then from that time it will send the 2nd template time. ( It will not consider the cart abadoned time in this case. )
105
+ */
106
+
107
+ $wcal_check_cart_needed_for_multiple_template = $this->wcal_remove_cart_for_mutiple_templates( $value->id, $time_to_send_template_after, $template_id );
108
+
109
+ /**
110
+ * When we click on the place order button, we check if the order is placed after the
111
+ * cut off time. And if yes then if the status of the order is pending or falied then
112
+ * we keep it as the abandonoed and we need to send reminder emails. So in below function
113
+ * we first check if any order is placed with todays date then we do not send the
114
+ * reminder email. But what if placed order status is pending or falied? So this
115
+ * condition will not call that function andthe reminder email will be sent.
116
+ */
117
+
118
+ $wcal_check_if_cart_is_present_in_post_meta = "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm
119
+ LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost
120
+ ON wpm.post_id = wpost.ID
121
+ WHERE wpm.meta_key = 'wcap_recover_order_placed' AND
122
+ wpm.meta_value = %s AND wpm.post_id = wpost.ID AND
123
+ wpost.post_type = 'shop_order'
124
+ ORDER BY wpm.post_id DESC LIMIT 1";
125
+
126
+ $results_wcal_check_if_cart_is_present_in_post_meta = $wpdb->get_results( $wpdb->prepare( $wcal_check_if_cart_is_present_in_post_meta, $value->id ) );
127
+
128
+ $wcap_check_cart_staus_need_to_update = false;
129
+
130
+ if ( empty ($results_wcal_check_if_cart_is_present_in_post_meta) ||
131
+ ( isset( $results_wcal_check_if_cart_is_present_in_post_meta[0] ) &&
132
+ $results_wcal_check_if_cart_is_present_in_post_meta[0]->post_status != "wc-failed" &&
133
+ $results_wcal_check_if_cart_is_present_in_post_meta [0]->post_status != "wc-pending" ) ){
134
+
135
+ $wcap_check_cart_staus_need_to_update = woocommerce_abandon_cart_cron::wcal_update_abandoned_cart_status_for_placed_orders ( $time_to_send_template_after, $cart_update_time, $value->user_id, $value->user_type, $value->id, $value->user_email );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  }
137
+
138
+ if ( false == $wcal_check_cart_needed_for_multiple_template &&
139
+ false == $wcap_check_cart_staus_need_to_update ) {
140
+
141
+ $cart_info_db = $value->abandoned_cart_info;
142
+ $email_body = $email_body_template;
143
+ $wcal_check_cart_total = $this->wcal_check_cart_total( $cart );
144
+ if( true == $wcal_check_cart_total ) {
145
+ if ( $value->user_type == "GUEST" ) {
146
+ if ( isset( $results_guest[0]->billing_first_name ) ) {
147
+ $email_body = str_replace( "{{customer.firstname}}", $results_guest[0]->billing_first_name, $email_body );
148
+ $email_subject = str_replace( "{{customer.firstname}}", $results_guest[0]->billing_first_name, $email_subject );
149
+ }
150
+ if ( isset( $results_guest[0]->billing_last_name ) ) {
151
+ $email_body = str_replace( "{{customer.lastname}}", $results_guest[0]->billing_last_name, $email_body );
152
+ }
153
+ if ( isset( $results_guest[0]->billing_first_name ) && isset( $results_guest[0]->billing_last_name ) ) {
154
+ $email_body = str_replace( "{{customer.fullname}}", $results_guest[0]->billing_first_name." ".$results_guest[0]->billing_last_name, $email_body );
155
+ }
156
+ else if ( isset( $results_guest[0]->billing_first_name ) ) {
157
+ $email_body = str_replace( "{{customer.fullname}}", $results_guest[0]->billing_first_name, $email_body );
158
+ }
159
+ else if ( isset( $results_guest[0]->billing_last_name ) ) {
160
+ $email_body = str_replace( "{{customer.fullname}}", $results_guest[0]->billing_last_name, $email_body );
161
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  } else {
163
+ $user_first_name = '';
164
+ $user_first_name_temp = get_user_meta( $value->user_id, 'billing_first_name', true );
165
+ if( isset( $user_first_name_temp ) && "" == $user_first_name_temp ) {
166
+ $user_data = get_userdata( $user_id );
167
+ $user_first_name = $user_data->first_name;
168
+ } else {
169
+ $user_first_name = $user_first_name_temp;
170
+ }
171
+ $email_body = str_replace( "{{customer.firstname}}", $user_first_name, $email_body );
172
+ $email_subject = str_replace( "{{customer.firstname}}", $user_first_name, $email_subject );
173
+ $user_last_name = '';
174
+ $user_last_name_temp = get_user_meta( $value->user_id, 'billing_last_name', true );
175
+ if( isset( $user_last_name_temp ) && "" == $user_last_name_temp ) {
176
+ $user_data = get_userdata( $user_id );
177
+ $user_last_name = $user_data->last_name;
178
+ } else {
179
+ $user_last_name = $user_last_name_temp;
180
+ }
181
+ $email_body = str_replace( "{{customer.lastname}}", $user_last_name, $email_body );
182
+ $email_body = str_replace( "{{customer.fullname}}", $user_first_name." ".$user_last_name, $email_body );
183
+ }
184
+ $order_date = "";
185
+ if( $cart_update_time != "" && $cart_update_time != 0 ) {
186
+ $date_format = date_i18n( get_option( 'date_format' ), $cart_update_time );
187
+ $time_format = date_i18n( get_option( 'time_format' ), $cart_update_time );
188
+ $order_date = $date_format . ' ' . $time_format;
189
  }
190
+ $email_body = str_replace( "{{cart.abandoned_date}}", $order_date, $email_body );
191
+ $query_sent = "INSERT INTO `".$wpdb->prefix."ac_sent_history_lite` ( template_id, abandoned_order_id, sent_time, sent_email_id )
192
+ VALUES ( %s, %s, '".current_time( 'mysql' )."', %s )";
193
+
194
+ $wpdb->query( $wpdb->prepare( $query_sent, $template_id, $value->id, $value->user_email ) );
195
+
196
+ $query_id = "SELECT * FROM `".$wpdb->prefix."ac_sent_history_lite`
197
+ WHERE template_id = %s AND abandoned_order_id = %s
198
+ ORDER BY id DESC
199
+ LIMIT 1 ";
200
+ $results_sent = $wpdb->get_results( $wpdb->prepare( $query_id, $template_id, $value->id ) );
201
+ $email_sent_id = $results_sent[0]->id;
202
+
203
+ if( $woocommerce->version < '2.3' ) {
204
+ $cart_page_link = $woocommerce->cart->get_cart_url();
205
+ } else {
206
+ $cart_page_id = woocommerce_get_page_id( 'cart' );
207
+ $cart_page_link = $cart_page_id ? get_permalink( $cart_page_id ) : '';
208
+ }
209
+
210
+ $encoding_cart = $email_sent_id.'&url='.$cart_page_link;
211
+ $validate_cart = $this->wcal_encrypt_validate( $encoding_cart );
212
+ $cart_link_track = get_option('siteurl').'/?wcal_action=track_links&validate=' . $validate_cart;
213
+ $email_body = str_replace( "{{cart.link}}", $cart_link_track, $email_body );
214
+
215
+ $validate_unsubscribe = $this->wcal_encrypt_validate( $email_sent_id );
216
+ $email_sent_id_address = $results_sent[0]->sent_email_id;
217
+ $encrypt_email_sent_id_address = hash( 'sha256', $email_sent_id_address );
218
+ $plugins_url = get_option( 'siteurl' ) . "/?wcal_track_unsubscribe=wcal_unsubscribe&validate=" . $validate_unsubscribe . "&track_email_id=" . $encrypt_email_sent_id_address;
219
+ $unsubscribe_link_track = $plugins_url;
220
+ $email_body = str_replace( "{{cart.unsubscribe}}" , $unsubscribe_link_track , $email_body );
221
+ $var = '';
222
+ if( preg_match( "{{products.cart}}", $email_body, $matched ) ) {
223
+ if ( class_exists( 'WP_Better_Emails' ) ) {
224
+ $var = '<table width = 100%>
225
+ <tr> <td colspan="5"> <h3>'.__( "Your Shopping Cart", "woocommerce-ac" ).'</h3> </td></tr>
226
+ <tr>
227
+ <th>'.__( "Item", "woocommerce-ac" ).'</th>
228
+ <th>'.__( "Name", "woocommerce-ac" ).'</th>
229
+ <th>'.__( "Quantity", "woocommerce-ac" ).'</th>
230
+ <th>'.__( "Price", "woocommerce-ac" ).'</th>
231
+ <th>'.__( "Line Subtotal", "woocommerce-ac" ).'</th>
232
+ </tr>';
233
+ } else {
234
+ $var = '<h3>'.__( "Your Shopping Cart", "woocommerce-ac" ).'</h3>
235
+ <table border="0" cellpadding="10" cellspacing="0" class="templateDataTable">
236
+ <tr>
237
+ <th>'.__( "Item", "woocommerce-ac" ).'</th>
238
+ <th>'.__( "Name", "woocommerce-ac" ).'</th>
239
+ <th>'.__( "Quantity", "woocommerce-ac" ).'</th>
240
+ <th>'.__( "Price", "woocommerce-ac" ).'</th>
241
+ <th>'.__( "Line Subtotal", "woocommerce-ac" ).'</th>
242
+ </tr>';
243
+ }
244
+ $cart_details = $cart_info_db_field->cart;
245
+ $cart_total = $item_subtotal = $item_total = 0;
246
+ $sub_line_prod_name = '';
247
+ foreach ( $cart_details as $k => $v ) {
248
+ $quantity_total = $v->quantity;
249
+ $product_id = $v->product_id;
250
+ $prod_name = get_post( $product_id );
251
+ $product_link_track = get_permalink( $product_id );
252
+ $product_name = $prod_name->post_title;
253
+ if( $sub_line_prod_name == '' ) {
254
+ $sub_line_prod_name = $product_name;
255
  }
256
+ // Item subtotal is calculated as product total including taxes
257
+ if( $v->line_subtotal_tax != 0 && $v->line_subtotal_tax > 0 ) {
258
+ $item_subtotal = $item_subtotal + $v->line_total + $v->line_subtotal_tax;
 
 
 
 
 
 
 
 
259
  } else {
260
+ $item_subtotal = $item_subtotal + $v->line_total;
261
+ }
262
+ // Line total
263
+ $item_total = $item_subtotal;
264
+ $item_subtotal = $item_subtotal / $quantity_total;
265
+ $item_total_display = wc_price( $item_total );
266
+ $item_subtotal = wc_price( $item_subtotal );
267
+ $product = wc_get_product( $product_id );
268
+ $prod_image = $product->get_image();
269
+ $image_url = wp_get_attachment_url( get_post_thumbnail_id( $product_id ) );
270
+ if ( isset( $v->variation_id ) && '' != $v->variation_id ) {
271
+ $variation_id = $v->variation_id;
272
+ $variation = wc_get_product( $variation_id );
273
+ $name = $variation->get_formatted_name() ;
274
+ $explode_all = explode ( "&ndash;", $name );
275
+ if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
276
+ $attributes = $explode_all[0];
277
+ $explode_attributes = explode( "(#" , $attributes) ;
278
+ if( isset( $explode_attributes[0] ) ) {
279
+ $add_product_name = $explode_attributes[0];
280
+ $add_product_name = rtrim( $add_product_name );
281
+ if ( $product_name == $add_product_name ) {
282
+ $wcal_selected_variation = '';
283
+ $wcal_all_attribute = $v->variation;
284
+ $variation_id_only = $v->variation_id;
285
+ foreach ($wcal_all_attribute as $wcal_all_attribute_key => $wcal_all_attribute_value) {
286
+ $taxonomy = explode( 'attribute_', $wcal_all_attribute_key );
287
+ $meta = get_post_meta( $variation_id_only, $wcal_all_attribute_key, true );
288
+ $term = get_term_by( 'slug', $meta, $taxonomy[1] );
289
+ $variation_name_only = $term->name;
290
+ $wcal_selected_variation .= $variation_name_only . "<br>";
291
+ }
292
+ $add_product_name = $product_name . ' - ' . $wcal_selected_variation;
293
+ }
294
+ $pro_name_variation = (array) $add_product_name;
295
+ }
296
+ } else {
297
+ $pro_name_variation = array_slice( $explode_all, 1, -1 );
298
+ }
299
+ $product_name_with_variable = '';
300
+ $explode_many_varaition = array();
301
+ foreach ( $pro_name_variation as $pro_name_variation_key => $pro_name_variation_value ){
302
+ $explode_many_varaition = explode ( ",", $pro_name_variation_value );
303
+ if ( !empty( $explode_many_varaition ) ) {
304
+ foreach( $explode_many_varaition as $explode_many_varaition_key => $explode_many_varaition_value ){
305
+ $product_name_with_variable = $product_name_with_variable . "<br>". html_entity_decode ( $explode_many_varaition_value );
306
+ }
307
+ } else {
308
+ $product_name_with_variable = $product_name_with_variable . "<br>". html_entity_decode ( $explode_many_varaition_value );
309
+ }
310
+ }
311
+ $product_name = $product_name_with_variable;
312
  }
313
+ $var .='<tr align="center">
314
+ <td> <a href="'.$cart_link_track.'"> <img src="' . $image_url . '" alt="" height="42" width="42" /> </a></td>
315
+ <td> <a href="'.$cart_link_track.'">'.__( $product_name, "woocommerce-ac" ).'</a></td>
316
+ <td> '.$quantity_total.'</td>
317
+ <td> '.$item_subtotal.'</td>
318
+ <td> '.$item_total_display.'</td>
319
+ </tr>';
320
+ $cart_total += $item_total;
321
+ $item_subtotal = $item_total = 0;
322
+ }
323
+ $cart_total = wc_price( $cart_total );
324
+ $var .= '<tr align="center">
325
+ <td> </td>
326
+ <td> </td>
327
+ <td> </td>
328
+ <td>'.__( "Cart Total:", "woocommerce-ac" ).'</td>
329
+ <td> '.$cart_total.'</td>
330
+ </tr>';
331
+ $var .= '</table>
332
+ ';
333
+ $email_body = str_replace( "{{products.cart}}", $var, $email_body );
334
+ $email_subject = str_replace( "{{product.name}}", __( $sub_line_prod_name, "woocommerce-ac" ), $email_subject );
335
+ }
336
+
337
+ $user_email = $value->user_email;
338
+ $email_body_final = stripslashes( $email_body );
339
+ $email_body_final = convert_smilies( $email_body_final );
340
+ if ( isset( $is_wc_template ) && "1" == $is_wc_template ){
341
+ ob_start();
342
+
343
+ wc_get_template( 'emails/email-header.php', array( 'email_heading' => $wc_template_header ) );
344
+ $email_body_template_header = ob_get_clean();
345
+
346
+ ob_start();
347
+
348
+ wc_get_template( 'emails/email-footer.php' );
349
+ $email_body_template_footer = ob_get_clean();
350
+
351
+ $final_email_body = $email_body_template_header . $email_body_final . $email_body_template_footer;
352
+
353
+ wc_mail( $user_email, $email_subject, $final_email_body, $headers );
354
+
355
+ } else {
356
+ wp_mail( $user_email, $email_subject, __( $email_body_final, 'woocommerce-ac' ), $headers );
357
  }
358
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }
361
  }
362
  }
363
  }
364
  }
365
+ }
366
+ function wcal_check_cart_total ( $cart ){
367
+ foreach( $cart as $k => $v ) {
368
+ //wc_mail("chetna@tychesoftwares.com", "line total", print_r($cart,true));
369
+ if( $v->line_total != 0 && $v->line_total > 0 ) {
370
+ return true;
371
+ }
372
+ }
373
+ return false;
374
  }
375
  /**
376
  * get all carts which have the creation time earlier than the one that is passed
390
  exit;
391
  }
392
 
393
+ public static function wcal_update_abandoned_cart_status_for_placed_orders( $time_to_send_template_after, $wcal_cart_time, $wcal_user_id, $wcal_user_type, $wcal_cart_id, $wcal_user_email ){
394
  global $wpdb;
395
+
396
+ if( $wcal_user_id >= '63000000' && 'GUEST' == $wcal_user_type ) {
397
+ $updated_value = woocommerce_abandon_cart_cron::wcal_update_status_of_guest( $wcal_cart_id, $wcal_cart_time , $time_to_send_template_after, $wcal_user_email );
398
+ if( 1 == $updated_value ) {
399
+ return true;
400
+ }
401
+ } elseif ( $wcal_user_id < '63000000' && 'REGISTERED' == $wcal_user_type ) {
402
+ $updated_value = woocommerce_abandon_cart_cron::wcal_update_status_of_loggedin ( $wcal_cart_id, $wcal_cart_time , $time_to_send_template_after, $wcal_user_email );
403
+ if( 1 == $updated_value ) {
404
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  }
406
  }
407
+ return false;
408
  }
409
 
410
+ public static function wcal_update_status_of_guest ( $cart_id, $abandoned_cart_time , $time_to_send_template_after, $wcal_user_email_address ) {
411
  global $wpdb;
 
412
 
413
+ $query_email_id = "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID
414
+ WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID AND wpost.post_type = 'shop_order' Order BY wpm.post_id DESC LIMIT 1";
415
+
416
+ $results_query_email = $wpdb->get_results( $wpdb->prepare( $query_email_id, $wcal_user_email_address ) );
417
+
418
+ /* This will check that For abc@abc.com email address we have order for todays date in WC post table */
419
+ if ( count( $results_query_email ) > 0 ) {
420
 
 
421
  $current_time = current_time( 'timestamp' );
422
  $todays_date = date( 'Y-m-d', $current_time );
423
+
424
+ $order_date_with_time = $results_query_email[0]->post_date;
425
+ $order_date = substr( $order_date_with_time, 0, 10 );
426
+
427
+ if ( $order_date == $todays_date ) {
428
+
429
+ /**
430
+ * in some case the cart is recovered but it is not marked as the recovred. So here we check if any
431
+ * record is found for that cart id if yes then update the record respectively.
432
+ */
433
+ $wcal_check_email_sent_to_cart = woocommerce_abandon_cart_cron::wcal_get_cart_sent_data ( $cart_id );
434
+
435
+ if ( 0 != $wcal_check_email_sent_to_cart ) {
436
+
437
+ $wcal_query = "SELECT `post_id` FROM `" . $wpdb->prefix . "postmeta` WHERE meta_value = %s";
438
+ $wcal_results = $wpdb->get_results ( $wpdb->prepare( $wcal_query , $cart_id ) );
439
+
440
+ if ( count( $wcal_results ) > 0 ) {
441
+
442
+ $order_id = $wcal_results[0]->post_id;
443
+
444
+ $order = new WC_Order( $order_id );
445
+
446
+ $query_order = "UPDATE `" . $wpdb->prefix."ac_abandoned_cart_history_lite` SET recovered_cart= '" . $order_id . "', cart_ignored = '1' WHERE id = '".$cart_id."' ";
447
+ $wpdb->query( $query_order );
448
+
449
+ $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-ac' ) );
450
+
451
+ delete_post_meta( $order_id, 'wcal_recover_order_placed', $cart_id );
452
+ delete_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $wcal_check_email_sent_to_cart );
453
  }
454
+ }else{
455
+
456
+ $query_ignored = "UPDATE `" . $wpdb->prefix."ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
457
+ $wpdb->query( $query_ignored );
458
+ }
459
+ return 1;
460
+ }else if ( strtotime( $order_date_with_time ) > $abandoned_cart_time ) {
461
+ $query_ignored = "UPDATE `" . $wpdb->prefix."ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
462
+ $wpdb->query( $query_ignored );
463
+ return 1;
464
+ } else if( "wc-pending" == $results_query_email[0]->post_status || "wc-failed" == $results_query_email[0]->post_status ) {
465
+
466
+ /**
467
+ * If the post status are pending or failed the send them for abandoned cart reminder emails.
468
+ */
469
+ return 0;
470
+ }
471
+ }
472
+ return 0;
473
  }
474
 
475
+ public static function wcal_update_status_of_loggedin( $cart_id, $abandoned_cart_time , $time_to_send_template_after, $user_billing_email ) {
476
+ global $wpdb;
477
+
478
+ $query_email_id = "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID Order BY wpm.post_id DESC LIMIT 1";
479
+
480
+ $results_query_email = $wpdb->get_results( $wpdb->prepare( $query_email_id, $user_billing_email ) );
481
+
482
+ if ( count ( $results_query_email ) > 0 ){
483
+ $current_time = current_time( 'timestamp' );
484
+ $todays_date = date( 'Y-m-d', $current_time );
485
+ $order_date_time = $results_query_email[0]->post_date;
486
+ $order_date = substr( $order_date_time, 0, 10 );
487
+
488
+ if ( $order_date == $todays_date ){
489
+
490
+ $wcal_check_email_sent_to_cart = woocommerce_abandon_cart_cron::wcal_get_cart_sent_data ( $cart_id );
491
+
492
+ if ( 0 != $wcal_check_email_sent_to_cart ){
493
+
494
+ $wcal_query = "SELECT `post_id` FROM `" . $wpdb->prefix . "postmeta` WHERE meta_value = %s";
495
+ $wcal_results = $wpdb->get_results ( $wpdb->prepare( $wcal_query , $cart_id ) );
496
+
497
+ if ( count( $wcal_results ) > 0 ){
498
+
499
+ $order_id = $wcal_results[0]->post_id;
500
+
501
+ $order = new WC_Order( $order_id );
502
+
503
+ $query_order = "UPDATE `" . $wpdb->prefix."ac_abandoned_cart_history_lite` SET recovered_cart= '" . $order_id . "', cart_ignored = '1' WHERE id = '".$cart_id."' ";
504
+ $wpdb->query( $query_order );
505
+
506
+
507
+
508
+ $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-ac' ) );
509
+
510
+ delete_post_meta( $order_id, 'wcap_recover_order_placed', $cart_id );
511
+ delete_post_meta( $order_id , 'wcap_recover_order_placed_sent_id', $wcal_check_email_sent_to_cart );
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
+ }else{
514
+
515
+ $query_ignored = "UPDATE `" . $wpdb->prefix."ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
516
+ $wpdb->query( $query_ignored );
517
  }
518
+ return 1;
519
+ }else if ( strtotime( $order_date_time ) >= $abandoned_cart_time ) {
520
+ $query_ignored = "UPDATE `" . $wpdb->prefix."ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
521
+ $wpdb->query( $query_ignored );
522
+ return 1; //We return here 1 so it indicate that the cart has been modifed so do not sent email and delete from the array.
523
+ }else if( "wc-pending" == $results_query_email[0]->post_status || "wc-failed" == $results_query_email[0]->post_status ) {
524
+ return 0; //if status of the order is pending or falied then return 0 so it will not delete that cart and send reminder email
525
  }
526
  }
527
+ return 0; // it means there are no record found to be update it.
528
+ }
529
+
530
+ public static function wcal_get_cart_sent_data ( $wcal_cart_id ) {
531
+ global $wpdb;
532
+
533
+ $wcal_query = "SELECT id FROM `" . $wpdb->prefix."ac_sent_history_lite` WHERE abandoned_order_id = %d ORDER BY 'id' DESC LIMIT 1 ";
534
+ $wcal_results = $wpdb->get_results ( $wpdb->prepare( $wcal_query , $wcal_cart_id ) );
535
+
536
+ if ( count( $wcal_results ) > 0 ) {
537
+ $wcal_sent_id = $wcal_results[0]->id;
538
+ return $wcal_sent_id;
539
+ }
540
  return 0;
541
  }
542
 
543
 
544
+ public static function wcal_remove_cart_for_mutiple_templates( $wcal_cart_id, $time_to_send_template_after, $template_id ) {
545
  global $wpdb;
546
 
547
+ $wcal_get_last_email_sent_time = "SELECT * FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = $wcal_cart_id ORDER BY `sent_time` DESC LIMIT 1";
548
+ $wcal_get_last_email_sent_time_results_list = $wpdb->get_results( $wcal_get_last_email_sent_time );
549
+
550
+ if( count( $wcal_get_last_email_sent_time_results_list ) > 0 ) {
551
+ $last_template_send_time = strtotime( $wcal_get_last_email_sent_time_results_list[0]->sent_time );
552
+ $second_template_send_time = $last_template_send_time + $time_to_send_template_after ;
553
+ $current_time_test = current_time( 'timestamp' );
554
+ if( $second_template_send_time > $current_time_test ) {
555
+ return true;
 
556
  }
557
  }
558
+
559
+ return false;
560
  }
561
  /******
562
  * This function is used to encode the validate string.
readme.txt CHANGED
@@ -4,7 +4,7 @@ Contributors: ashokrane, pinal.shah, bhavik.kiri, chetnapatel, tychesoftwares
4
  Tags: abandon cart, cart recovery, increase woocommerce conversion rate , recover woocommerce cart, increase sales with woocommerce
5
  Author URI: https://www.tychesoftwares.com/
6
  Requires at least: 1.3
7
- Tested up to: 4.8
8
  Stable tag: trunk
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -52,20 +52,26 @@ You can check the detailed difference between Pro and Lite version **[here](http
52
 
53
  **[Abandoned Cart Pro for WooCommerce](http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wprepo&utm_medium=link&utm_campaign=AbandonedCartLite "Abandoned Cart Pro for WooCommerce")** enables to do the following additional things:
54
 
55
- 1. Works off-the-shelf as it comes with **3 default email templates**.
56
- 2. Offer **incentives to customers** to return and complete their checkout with **discounts and coupons**.
57
- 3. Add custom variables like **Customer Name, Product Information, Coupons**, etc. in the email template.
58
- 4. Embed WooCommerce coupons & also **generate unique coupons** in the emails being sent to customers.
59
- 5. Track whether **expired coupons** are causing cart abandonment.
60
- 6. Track **emails sent, emails opened, links clicked** for each template/email.
61
- 7. **Product report** allows you to see which products are being abandoned & which are being recovered the most.
62
- 8. Start sending email templates **within minutes** of cart being abandoned.
63
- 9. Admin can send the customer emails to specific abandoned cart(s) using **'Send Custom Email'** feature.
64
- 10. If the store is using **WPML** then admin can translate all the abandoned cart reminder email templates using WPML. Then the emails will be sent to the customers in the **same language in which they have abandoned the cart**.
65
- 11. Admin can **Print** or export the Abandoned Orders to **CSV** format.
66
- 12. Admin can send **different email templates** to **'Registered Users', 'Guest Users', 'For carts Abandoned with one product' or 'with more than one product' or to 'All'**.
67
- 13. Admin can **restrict** the abandoned carts based on the **'Email address'**, **'IP address'** & **'Domain name'**.
68
- 14. Admin can take a **glimpse** of **abandoned carts**, **recovered orders**, and the **states of the email template** from the **Dashboard** tab.
 
 
 
 
 
 
69
 
70
  You can check the detailed difference between Pro and Lite version **[here](https://www.tychesoftwares.com/differences-between-pro-and-lite-versions-of-abandoned-cart-for-woocommerce-plugin/?utm_source=wprepo&utm_medium=prolink&utm_campaign=AbandonedCartLite "Lite and Pro version Difference")**
71
 
@@ -91,6 +97,8 @@ Abandoned Cart Plugin relies on a function called WP-Cron, and this function onl
91
 
92
  4. **[Product Delivery Date Pro for WooCommerce](https://www.tychesoftwares.com/store/premium-plugins/product-delivery-date-pro-for-woocommerce/?utm_source=wprepo&utm_medium=link&utm_campaign=AbandonedCartLite "Product Delivery Date Pro for WooCommerce")**
93
 
 
 
94
 
95
  **Some of our other free plugins:**
96
 
@@ -180,6 +188,18 @@ You can refer **[here](https://www.tychesoftwares.com/differences-between-pro-an
180
 
181
  == Changelog ==
182
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  = 4.2 (25.07.2017) =
184
 
185
  * This version has 1 bug fix.
@@ -459,6 +479,19 @@ For existing users, this setting will remain unchecked. For new users of the plu
459
 
460
  == Upgrade Notice ==
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  = 4.2 (25.07.2017) =
463
 
464
  * This version has 1 bug fix.
4
  Tags: abandon cart, cart recovery, increase woocommerce conversion rate , recover woocommerce cart, increase sales with woocommerce
5
  Author URI: https://www.tychesoftwares.com/
6
  Requires at least: 1.3
7
+ Tested up to: 4.8.1
8
  Stable tag: trunk
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
52
 
53
  **[Abandoned Cart Pro for WooCommerce](http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wprepo&utm_medium=link&utm_campaign=AbandonedCartLite "Abandoned Cart Pro for WooCommerce")** enables to do the following additional things:
54
 
55
+ 1. Super powerful feature, **Add To Cart Popup Modal** - Grab your visitors' attention and build your mailing list. It offers an innovative, exclusive Add to Cart Popup Modal to abandoners to re-engage and capture emails from more of your guest customers before the checkout page.
56
+
57
+ It is simple, effective & a highly customizable popup using Live Preview when customizing it in the Add to Cart Popup Editor.
58
+
59
+ When guest customers clicks on the **Add to Cart** button on the shop or product page, the popup modal will appear immediately and ask for the email address. You can choose to prevent users from proceeding without submitting their email, or allow them to checkout as a guest.
60
+ 2. Works off-the-shelf as it comes with **3 default email templates**.
61
+ 3. Offer **incentives to customers** to return and complete their checkout with **discounts and coupons**.
62
+ 4. Add custom variables like **Customer Name, Product Information, Coupons**, etc. in the email template.
63
+ 5. Embed WooCommerce coupons & also **generate unique coupons** in the emails being sent to customers.
64
+ 6. Track whether **expired coupons** are causing cart abandonment.
65
+ 7. Track **emails sent, emails opened, links clicked** for each template/email.
66
+ 8. **Product report** allows you to see which products are being abandoned & which are being recovered the most.
67
+ 9. Start sending email templates **within minutes** of cart being abandoned.
68
+ 10. Admin can send the customer emails to specific abandoned cart(s) using **'Send Custom Email'** feature.
69
+ 11. If the store is using **WPML** then admin can translate all the abandoned cart reminder email templates using WPML. Then the emails will be sent to the customers in the **same language in which they have abandoned the cart**.
70
+ 12. Admin can **Print** or export the Abandoned Orders to **CSV** format.
71
+ 13. Admin can send **different email templates** to **'Registered Users', 'Guest Users', 'For carts Abandoned with one product' or 'with more than one product' or to 'All'**.
72
+ 14. Admin can **restrict** the abandoned carts based on the **'Email address'**, **'IP address'** & **'Domain name'**.
73
+ 15. Admin can take a **glimpse** of **abandoned carts**, **recovered orders**, and the **states of the email template** from the **Dashboard** tab.
74
+ 16. The plugin will consider the **taxation** which is set in the WooCommerce. The abandoned cart total will be displayed as per the selected tax setting.
75
 
76
  You can check the detailed difference between Pro and Lite version **[here](https://www.tychesoftwares.com/differences-between-pro-and-lite-versions-of-abandoned-cart-for-woocommerce-plugin/?utm_source=wprepo&utm_medium=prolink&utm_campaign=AbandonedCartLite "Lite and Pro version Difference")**
77
 
97
 
98
  4. **[Product Delivery Date Pro for WooCommerce](https://www.tychesoftwares.com/store/premium-plugins/product-delivery-date-pro-for-woocommerce/?utm_source=wprepo&utm_medium=link&utm_campaign=AbandonedCartLite "Product Delivery Date Pro for WooCommerce")**
99
 
100
+ 5. **[Deposits For WooCommerce](https://www.tychesoftwares.com/store/premium-plugins/deposits-for-woocommerce/?utm_source=wprepo&utm_medium=link&utm_campaign=AbandonedCartLite "Deposits For WooCommerce")**
101
+
102
 
103
  **Some of our other free plugins:**
104
 
188
 
189
  == Changelog ==
190
 
191
+ = 4.3 (29.08.2017) =
192
+
193
+ * This version has 1 bug fix along with 3 Enhancements.
194
+
195
+ * Bug Fixed - When abandoned cart will have a variable product which has 3 attributes or more than that. Then the slug name of selected variations were showing in the abandoned cart reminder emails and on the abandoned cart details page. This has been fixed.
196
+
197
+ * Enhancement - If the abandoned cart total is zero then abandoned cart reminder emails will not be sent to the customers.
198
+
199
+ * Enhancement - When the email sending script is executed on the server, it was running a large number of MySQL queries for guest users. That was causing an increase in the server load. In this version, we have optimised the queries. Initially, it used to query even those guest user records for which emails were already sent. Now, it will only query those records where email is yet to be sent.
200
+
201
+ * Enhancement - Removed the Active field from the add / edit email template page. Admin can activate or deactivate the templates from the Email templates page.
202
+
203
  = 4.2 (25.07.2017) =
204
 
205
  * This version has 1 bug fix.
479
 
480
  == Upgrade Notice ==
481
 
482
+ = 4.3 (29.08.2017) =
483
+
484
+ * This version has 1 bug fix along with 3 Enhancements.
485
+
486
+ * Bug Fixed - When abandoned cart will have a variable product which has 3 attributes or more than that. Then the slug name of selected variations were showing in the abandoned cart reminder emails and on the abandoned cart details page. This has been fixed.
487
+
488
+ * Enhancement - If the abandoned cart total is zero then abandoned cart reminder emails will not be sent to the customers.
489
+
490
+ * Enhancement - When the email sending script is executed on the server, it was running a large number of MySQL queries for guest users. That was causing an increase in the server load. In this version, we have optimised the queries. Initially, it used to query even those guest user records for which emails were already sent. Now, it will only query those records where email is yet to be sent.
491
+
492
+ * Enhancement - Removed the Active field from the add / edit email template page. Admin can activate or deactivate the templates from the Email templates page.
493
+
494
+
495
  = 4.2 (25.07.2017) =
496
 
497
  * This version has 1 bug fix.
woocommerce-ac.php CHANGED
@@ -3,11 +3,13 @@
3
  Plugin Name: Abandoned Cart Lite for WooCommerce
4
  Plugin URI: http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro
5
  Description: This plugin captures abandoned carts by logged-in users & emails them about it. <strong><a href="http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro">Click here to get the PRO Version.</a></strong>
6
- Version: 4.2
7
  Author: Tyche Softwares
8
  Author URI: http://www.tychesoftwares.com/
9
  Text Domain: woocommerce-ac
10
  Domain Path: /i18n/languages/
 
 
11
  */
12
 
13
  // Deletion Settings
@@ -57,7 +59,7 @@ if ( ! wp_next_scheduled( 'wcal_ts_tracker_send_event' ) ) {
57
  add_action( 'woocommerce_ac_send_email_action', 'wcal_send_email_cron' );
58
 
59
  function wcal_send_email_cron() {
60
- //require_once( ABSPATH.'wp-content/plugins/woocommerce-abandoned-cart/cron/send_email.php' );
61
  $plugin_dir_path = plugin_dir_path( __FILE__ );
62
  require_once( $plugin_dir_path . 'cron/wcal_send_email.php' );
63
  }
@@ -299,109 +301,222 @@ if( !class_exists( 'woocommerce_abandon_cart_lite' ) ) {
299
  session_start();
300
  }
301
 
 
 
 
 
 
 
 
 
 
302
  if ( isset( $_SESSION['email_sent_id'] ) && $_SESSION['email_sent_id'] !='' ) {
303
- global $woocommerce, $wpdb;
304
- $email_sent_id = $_SESSION['email_sent_id'];
305
- $get_ac_id_query = "SELECT abandoned_order_id FROM `" . $wpdb->prefix."ac_sent_history_lite` WHERE id = %d";
306
- $get_ac_id_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_query, $email_sent_id ) );
307
- $abandoned_order_id = $get_ac_id_results[0]->abandoned_order_id;
308
-
309
- update_post_meta( $order_id , 'wcal_recover_order_placed', $abandoned_order_id );
310
- update_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $email_sent_id );
311
- } else if ( isset( $_SESSION['abandoned_cart_id_lite'] ) && $_SESSION['abandoned_cart_id_lite'] != '' &&
312
- isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) {
313
-
314
  global $woocommerce, $wpdb;
315
- $results_sent = array();
316
- $abandoned_cart_id_new_user = $_SESSION['abandoned_cart_id_lite'];
317
- $wcap_user_id_of_guest = $_SESSION['user_id'];
318
- /* delete the guest record. As it become the logged in user */
319
- $table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
320
- $wpdb->delete( $table_name , array( 'user_id' => $wcap_user_id_of_guest ) );
321
-
322
- $table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
323
- $wpdb->delete( $table_name , array( 'id' => $wcap_user_id_of_guest ) );
324
-
325
- /* Check if for the logged in user we have sent any abandoned cart reminder email */
326
- $get_email_sent_for_abandoned_id = "SELECT * FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = %d ";
327
- $results_sent = $wpdb->get_results( $wpdb->prepare( $get_email_sent_for_abandoned_id, $abandoned_cart_id_new_user ) );
328
-
329
- if ( empty( $results_sent ) && count( $results_sent ) == 0 ) {
330
-
331
- /*
332
- * If logged in user place the order once it is displyed under the abandoned orders tab.
333
- * But the email has been not sent to the user. And order is placed successfuly
334
- * Then We are deleteing those order. But for those orders Recovered email has been set to the Admin.
335
- * Below code ensure that admin recovery email wil not be sent for tose orders.
336
- */
337
- $get_user_id_of_abandoned_cart = "SELECT * FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE id = %d ";
338
- $get_results_of_user_id = $wpdb->get_results ( $wpdb->prepare( $get_user_id_of_abandoned_cart, $abandoned_cart_id_new_user ) );
339
- $user_id = $get_results_of_user_id[0]->user_id;
340
-
341
- delete_user_meta( $user_id, '_woocommerce_ac_modified_cart' );
342
- /*
343
- * It will delete the order from history table if the order is placed before any email sent to the user.
344
- *
345
- */
346
- $table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
347
- $wpdb->delete( $table_name , array( 'id' => $abandoned_cart_id_new_user ) );
348
- } else {
349
- $email_sent_id = $results_sent[0]->id;
350
- update_post_meta( $order_id , 'wcal_recover_order_placed', $abandoned_cart_id_new_user );
351
- update_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $email_sent_id );
352
  }
353
- } else if ( isset( $_SESSION['abandoned_cart_id_lite'] ) && $_SESSION['abandoned_cart_id_lite'] !='' ) {
354
- global $woocommerce, $wpdb;
355
- $results_sent = array();
356
- $abandoned_cart_id = $_SESSION['abandoned_cart_id_lite'];
357
- $get_email_sent_for_abandoned_id = "SELECT * FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = %d ";
358
- $results_sent = $wpdb->get_results ( $wpdb->prepare( $get_email_sent_for_abandoned_id, $abandoned_cart_id ) );
359
- if ( empty( $results_sent ) && count( $results_sent ) == 0 ) {
360
- /*
361
- * If logeged in user place the order once it isdisplyed under the abandoned orders tab.
362
- * But the email has been not sent to the user. And order is placed successfuly
363
- * Then We are deleteing those order. But for those orders Recovered email has been set to the Admin.
364
- * Below code ensure that admin recovery email will not be sent for those orders.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  */
366
- $get_user_id_of_abandoned_cart = "SELECT * FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE id = %d ";
367
- $get_results_of_user_id = $wpdb->get_results ( $wpdb->prepare( $get_user_id_of_abandoned_cart, $abandoned_cart_id ) );
368
- $user_id = $get_results_of_user_id[0]->user_id;
369
- delete_user_meta( $user_id, '_woocommerce_ac_modified_cart' );
370
- /*
371
- * It will delete the order from history table if the order is placed before any email sent to the user.
372
- *
373
- */
374
- $table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
375
- $wpdb->delete( $table_name , array( 'id' => $abandoned_cart_id ) );
376
- } else {
377
- $email_sent_id = $results_sent[0]->id;
378
- update_post_meta( $order_id , 'wcal_recover_order_placed', $abandoned_cart_id );
379
- update_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $email_sent_id );
380
- }
381
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  }
383
 
384
  public function wcal_order_complete_action( $order_status, $order_id ) {
385
- if ( 'failed' != $order_status ) {
 
 
 
 
 
386
  global $woocommerce, $wpdb;
387
- $order = new WC_Order( $order_id );
388
- $get_abandoned_id_of_order = '';
389
- $get_sent_email_id_of_order = '';
390
  $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
391
-
392
- if ( isset( $get_abandoned_id_of_order ) && $get_abandoned_id_of_order != '' ){
393
- $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
394
- $get_sent_email_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', true );
395
-
396
- $query_order = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET recovered_cart= '" . $order_id . "', cart_ignored = '1'
397
- WHERE id = '".$get_abandoned_id_of_order."' ";
 
 
 
 
 
 
 
398
  $wpdb->query( $query_order );
399
 
400
  $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-ac' ) );
401
-
402
- delete_post_meta( $order_id, 'wcal_recover_order_placed', $get_abandoned_id_of_order );
403
- delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', $get_sent_email_id_of_order );
404
- delete_post_meta( $order_id, 'wcap_recovered_email_sent', 'yes' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  }
406
  }
407
  return $order_status;
@@ -624,7 +739,7 @@ if( !class_exists( 'woocommerce_abandon_cart_lite' ) ) {
624
 
625
  add_settings_field(
626
  'ac_lite_track_guest_cart_from_cart_page',
627
- __( 'Enable tracking carts when customer doesn\'t enter details', 'woocommerce-ac' ),
628
  array( $this, 'wcal_track_guest_cart_from_cart_page_callback' ),
629
  'woocommerce_ac_page',
630
  'ac_lite_general_settings_section',
@@ -1317,9 +1432,14 @@ if( !class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1317
  }
1318
 
1319
  // Decrypt Function
1320
- function wcal_decrypt_validate( $validate ) {
1321
- $cryptKey = get_option( 'wcal_security_key' );
1322
- $validate_decoded = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, md5( $cryptKey ), base64_decode( $validate ), MCRYPT_MODE_CBC, md5( md5( $cryptKey ) ) ), "\0");
 
 
 
 
 
1323
  return( $validate_decoded );
1324
  }
1325
 
@@ -2758,15 +2878,28 @@ if( !class_exists( 'woocommerce_abandon_cart_lite' ) ) {
2758
  $name = $variation->get_formatted_name() ;
2759
  $explode_all = explode ( "&ndash;", $name );
2760
  if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
2761
-
2762
- $attributes = $explode_all[1];
2763
  $explode_attributes = explode( "(#" , $attributes) ;
2764
- if (isset($explode_attributes [0])){
2765
- $add_product_name = $product_name . "," . $explode_attributes[0];
2766
- $pro_name_variation = (array) $add_product_name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2767
  }
2768
  }else{
2769
- $pro_name_variation = array_slice( $explode_all, 1, -1 );
2770
  }
2771
  $product_name_with_variable = '';
2772
  $explode_many_varaition = array();
@@ -3026,34 +3159,6 @@ if( !class_exists( 'woocommerce_abandon_cart_lite' ) ) {
3026
  </td>
3027
  </tr>
3028
 
3029
- <tr>
3030
- <th>
3031
- <label for="is_active"><b><?php _e( 'Active:', 'woocommerce-ac' ); ?></b></label>
3032
- </th>
3033
- <td>
3034
- <?php
3035
- $is_active_edit="";
3036
- if ( $mode == 'edittemplate' ) {
3037
- $active_edit = $results[0]->is_active;
3038
- if ( $active_edit == '1' ) {
3039
- $is_active_edit = "checked";
3040
- } else {
3041
- $is_active_edit = "";
3042
- }
3043
- }
3044
- if ( $mode == 'copytemplate' ) {
3045
- $active_edit = $results_copy[0]->is_active;
3046
- if( $active_edit == '1' ) {
3047
- $is_active_edit = "checked";
3048
- } else {
3049
- $is_active_edit = "";
3050
- }
3051
- }
3052
- print'<input type="checkbox" name="is_active" id="is_active" ' . $is_active_edit . '> </input>'; ?>
3053
- <img class="help_tip" width="16" height="16" data-tip='<?php _e( 'The email template will be sent to customers only if the "Active" checkbox is enabled. Leave this unchecked if you want to add the email template but not send it to customers.', 'woocommerce' ) ?>' src="<?php echo plugins_url(); ?>/woocommerce/assets/images/help.png" /></p>
3054
- </td>
3055
- </tr>
3056
-
3057
  <tr>
3058
  <th>
3059
  <label for="woocommerce_ac_email_frequency"><b><?php _e( 'Send this email:', 'woocommerce-ac' ); ?></b></label>
3
  Plugin Name: Abandoned Cart Lite for WooCommerce
4
  Plugin URI: http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro
5
  Description: This plugin captures abandoned carts by logged-in users & emails them about it. <strong><a href="http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro">Click here to get the PRO Version.</a></strong>
6
+ Version: 4.3
7
  Author: Tyche Softwares
8
  Author URI: http://www.tychesoftwares.com/
9
  Text Domain: woocommerce-ac
10
  Domain Path: /i18n/languages/
11
+ WC requires at least: 3.0.0
12
+ WC tested up to: 3.2.0
13
  */
14
 
15
  // Deletion Settings
59
  add_action( 'woocommerce_ac_send_email_action', 'wcal_send_email_cron' );
60
 
61
  function wcal_send_email_cron() {
62
+
63
  $plugin_dir_path = plugin_dir_path( __FILE__ );
64
  require_once( $plugin_dir_path . 'cron/wcal_send_email.php' );
65
  }
301
  session_start();
302
  }
303
 
304
+ /**
305
+ * When user comes from the abandoned cart reminder email this conditon will be executed.
306
+ * It will check the guest uers data in further 3 conditions.
307
+ * 1. When WC setting mandatory to become the logged in users. And places the order
308
+ * 2. When WC setting is non - mandatory to become the logged in users. And user choose to be the loggedin
309
+ * to the site And places the order
310
+ * 3. When user places the orde as guest user.
311
+ * It will consider the old cart of the customer as the recovered order and delete the unwanted new records.
312
+ */
313
  if ( isset( $_SESSION['email_sent_id'] ) && $_SESSION['email_sent_id'] !='' ) {
 
 
 
 
 
 
 
 
 
 
 
314
  global $woocommerce, $wpdb;
315
+
316
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
317
+ $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
318
+ $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
319
+
320
+ $email_sent_id = $_SESSION['email_sent_id'];
321
+
322
+ $get_ac_id_query = "SELECT abandoned_order_id FROM ". $wcal_sent_email_table_name ." WHERE id = %d";
323
+ $get_ac_id_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_query, $email_sent_id ) );
324
+
325
+ $abandoned_order_id = $get_ac_id_results[0]->abandoned_order_id;
326
+
327
+ $wcal_account_password_check = 'no';
328
+
329
+ /*if user becomes the registered user */
330
+ if ( isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) {
331
+
332
+ $abandoned_cart_id_new_user = $_SESSION['abandoned_cart_id_lite'];
333
+ $wcal_user_id_of_guest = $_SESSION['user_id'];
334
+
335
+ /* delete the guest record. As it become the logged in user */
336
+
337
+ $get_ac_id_guest_query = "SELECT id FROM `" . $wcal_history_table_name ."` WHERE user_id = %d ORDER BY id DESC";
338
+ $get_ac_id_guest_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_guest_query, $wcal_user_id_of_guest ) );
339
+
340
+
341
+ if ( count ($get_ac_id_guest_results) > 1 ) {
342
+ $abandoned_order_id_of_guest = $get_ac_id_guest_results[0]->id;
343
+ $wpdb->delete( $wcal_history_table_name , array( 'id' => $abandoned_order_id_of_guest ) );
344
+ }
345
+ /* it is the new registered users cart id */
346
+ $wpdb->delete( $wcal_history_table_name , array( 'id' => $abandoned_cart_id_new_user ) );
347
+
348
+ $wcal_account_password_check = 'yes';
 
 
 
349
  }
350
+
351
+ $wcap_create_account = 'no';
352
+ /*if user becomes the registred user */
353
+ if ( isset( $_POST['createaccount'] ) &&
354
+ $_POST['createaccount'] != '' &&
355
+ 'no' == $wcal_account_password_check ) {
356
+
357
+ $abandoned_cart_id_new_user = $_SESSION['abandoned_cart_id_lite'];
358
+ $wcal_user_id_of_guest = $_SESSION['user_id'];
359
+
360
+ /* delete the guest record. As it become the logged in user */
361
+
362
+ $get_ac_id_guest_query = "SELECT id FROM `" . $wcal_history_table_name ."` WHERE user_id = %d ORDER BY id DESC";
363
+ $get_ac_id_guest_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_guest_query, $wcal_user_id_of_guest ) );
364
+
365
+ if ( count ($get_ac_id_guest_results) > 1 ){
366
+ $abandoned_order_id_of_guest = $get_ac_id_guest_results[0]->id;
367
+ $wpdb->delete( $wcal_history_table_name , array( 'id' => $abandoned_order_id_of_guest ) );
368
+ }
369
+
370
+ /* it is the new registered users cart id */
371
+ $wpdb->delete( $wcal_history_table_name , array( 'id' => $abandoned_cart_id_new_user ) );
372
+
373
+ $wcap_create_account = 'yes';
374
+ }
375
+
376
+ if ( 'no' == $wcal_account_password_check && 'no' == $wcap_create_account ) {
377
+
378
+ $wcal_user_id_of_guest = $_SESSION['user_id'];
379
+
380
+ $get_ac_id_guest_query = "SELECT id FROM `" . $wcal_history_table_name ."` WHERE user_id = %d ORDER BY id DESC";
381
+ $get_ac_id_guest_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_guest_query, $wcal_user_id_of_guest ) );
382
+
383
+ if ( count ($get_ac_id_guest_results) > 1 ) {
384
+ $abandoned_order_id_of_guest = $get_ac_id_guest_results[0]->id;
385
+ $wpdb->delete( $wcal_history_table_name, array( 'id' => $abandoned_order_id_of_guest ) );
386
+ }
387
+ }
388
+
389
+ add_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $email_sent_id );
390
+ add_post_meta( $order_id , 'wcal_recover_order_placed', $abandoned_order_id );
391
+
392
+ }else if ( isset( $_SESSION['abandoned_cart_id_lite'] ) && $_SESSION['abandoned_cart_id_lite'] != '' ) {
393
+
394
+ /**
395
+ * In this codition we are cheking that if the order is placed before the cart cut off time then we
396
+ * will delete the abandond cart records.
397
+ * If the order is placed after the cart cutoff time then we will create the post meta with
398
+ * the abandoned cart id. So we will refer this abandoned cart id when order staus is changed
399
+ * while placing the order.
400
  */
401
+ if( session_id() === '' ){
402
+ //session has not started
403
+ session_start();
404
+ }
405
+
406
+ global $woocommerce, $wpdb;
407
+
408
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
409
+ $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
410
+ $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
411
+
412
+ $current_time = current_time( 'timestamp' );
413
+ $wcal_cart_abandoned_time = '';
414
+ $wcal_abandoned_cart_id = $_SESSION['abandoned_cart_id_lite'];
415
+
416
+
417
+ $get_abandoned_cart_query = "SELECT abandoned_cart_time FROM `" . $wcal_history_table_name . "` WHERE id = %d ";
418
+ $get_abandoned_cart_results = $wpdb->get_results( $wpdb->prepare( $get_abandoned_cart_query, $wcal_abandoned_cart_id ) );
419
+
420
+ if ( count( $get_abandoned_cart_results ) > 0 ){
421
+ $wcal_cart_abandoned_time = $get_abandoned_cart_results[0]->abandoned_cart_time;
422
+ }
423
+
424
+ $ac_cutoff_time = get_option( 'ac_lite_cart_abandoned_time' );
425
+ $cut_off_time = $ac_cutoff_time * 60;
426
+ $compare_time = $current_time - $cut_off_time;
427
+
428
+ if ( $compare_time > $wcal_cart_abandoned_time ) {
429
+ /* cart is declared as adandoned */
430
+
431
+ add_post_meta( $order_id , 'wcal_recover_order_placed', $wcal_abandoned_cart_id );
432
+ }else {
433
+ /* cart order is placed within the cutoff time.
434
+ we will delete that abandoned cart */
435
+
436
+ /* if user becomes the registred user */
437
+
438
+ if ( isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) {
439
+
440
+ $abandoned_cart_id_new_user = $_SESSION['abandoned_cart_id_lite'];
441
+ $wcal_user_id_of_guest = $_SESSION['user_id'];
442
+
443
+ /* delete the guest record. As it become the logged in user */
444
+
445
+ $wpdb->delete( $wcal_history_table_name , array( 'user_id' => $wcal_user_id_of_guest ) );
446
+ $wpdb->delete( $wcal_guest_table_name , array( 'id' => $wcal_user_id_of_guest ) );
447
+
448
+ /* it is the new registered users cart id */
449
+ $wpdb->delete( $wcal_history_table_name , array( 'id' => $abandoned_cart_id_new_user ) );
450
+ }else {
451
+
452
+ /**
453
+ * It will delete the order from history table if the order is placed before any email sent to
454
+ * the user.
455
+ */
456
+ $wpdb->delete( $wcal_history_table_name , array( 'id' => $wcap_abandoned_cart_id ) );
457
+
458
+ /* this user id is set for the guest uesrs. */
459
+ if ( isset( $_SESSION['user_id'] ) && $_SESSION['user_id'] != '' ) {
460
+
461
+ $wcal_user_id_of_guest = $_SESSION['user_id'];
462
+ $wpdb->delete( $wcal_guest_table_name, array( 'id' => $wcal_user_id_of_guest ) );
463
+ }
464
+ }
465
+ }
466
+ }
467
  }
468
 
469
  public function wcal_order_complete_action( $order_status, $order_id ) {
470
+
471
+ /**
472
+ * If the order status is not pending or failed then we will check the order and its respective abandoned
473
+ * cart data.
474
+ */
475
+ if ( 'pending' != $order_status && 'failed' != $order_status ) {
476
  global $woocommerce, $wpdb;
477
+ $order = new WC_Order( $order_id );
478
+
 
479
  $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
480
+ $get_sent_email_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', true );
481
+
482
+ $wcal_ac_table_name = $wpdb->prefix . "ac_abandoned_cart_history_lite";
483
+ $wcal_email_sent_history_table_name = $wpdb->prefix . "ac_sent_history_lite";
484
+ $wcal_guest_ac_table_name = $wpdb->prefix . "ac_guest_abandoned_cart_history_lite";
485
+
486
+ /**
487
+ * Here, in this condition we are checking that if abadoned cart id has any record for the reminder
488
+ * email is sent or not.
489
+ * If the reminde email is sent to the abandoned cart id the mark that cart as a recovered.
490
+ */
491
+ if ( isset( $get_sent_email_id_of_order ) && '' != $get_sent_email_id_of_order ) {
492
+
493
+ $query_order = "UPDATE $wcal_ac_table_name SET recovered_cart = '" . $order_id . "', cart_ignored = '1' WHERE id = '".$get_abandoned_id_of_order."' ";
494
  $wpdb->query( $query_order );
495
 
496
  $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-ac' ) );
497
+
498
+ delete_post_meta( $order_id, 'wcal_recover_order_placed', $get_abandoned_id_of_order );
499
+ delete_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $get_sent_email_id_of_order );
500
+ } else if ( isset( $get_abandoned_id_of_order ) && '' != $get_abandoned_id_of_order ) {
501
+
502
+ /**
503
+ * If the recover email has not sent then we will delete the abandoned cart data.
504
+ */
505
+ $get_abandoned_cart_user_id_query = "SELECT user_id FROM $wcal_ac_table_name WHERE id = %d ";
506
+ $get_abandoned_cart_user_id_results = $wpdb->get_results( $wpdb->prepare( $get_abandoned_cart_user_id_query, $get_abandoned_id_of_order ) );
507
+
508
+ $var = $wpdb->prepare( $get_abandoned_cart_user_id_query, $get_abandoned_id_of_order );
509
+
510
+ if ( count( $get_abandoned_cart_user_id_results ) > 0 ) {
511
+ $wcap_user_id = $get_abandoned_cart_user_id_results[0]->user_id;
512
+
513
+ if ( $wcap_user_id >= 63000000 ){
514
+ $wpdb->delete( $wcal_guest_ac_table_name , array( 'id' => $wcap_user_id ) );
515
+ }
516
+
517
+ $wpdb->delete( $wcal_ac_table_name , array( 'id' => $get_abandoned_id_of_order ) );
518
+ delete_post_meta( $order_id, 'wcap_recover_order_placed', $get_abandoned_id_of_order );
519
+ }
520
  }
521
  }
522
  return $order_status;
739
 
740
  add_settings_field(
741
  'ac_lite_track_guest_cart_from_cart_page',
742
+ __( 'Start tracking from Cart Page', 'woocommerce-ac' ),
743
  array( $this, 'wcal_track_guest_cart_from_cart_page_callback' ),
744
  'woocommerce_ac_page',
745
  'ac_lite_general_settings_section',
1432
  }
1433
 
1434
  // Decrypt Function
1435
+ function wcal_decrypt_validate( $validate ) {
1436
+ $validate_decoded = '';
1437
+ if( function_exists( "mcrypt_encrypt" ) ) {
1438
+ $cryptKey = get_option( 'wcal_security_key' );
1439
+ $validate_decoded = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, md5( $cryptKey ), base64_decode( $validate ), MCRYPT_MODE_CBC, md5( md5( $cryptKey ) ) ), "\0");
1440
+ }else {
1441
+ $validate_decoded = base64_decode ( $validate );
1442
+ }
1443
  return( $validate_decoded );
1444
  }
1445
 
2878
  $name = $variation->get_formatted_name() ;
2879
  $explode_all = explode ( "&ndash;", $name );
2880
  if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
2881
+ $attributes = $explode_all[0];
 
2882
  $explode_attributes = explode( "(#" , $attributes) ;
2883
+ if( isset( $explode_attributes[0] ) ) {
2884
+ $add_product_name = $explode_attributes[0];
2885
+ $add_product_name = rtrim( $add_product_name );
2886
+ if ( $product_name == $add_product_name ) {
2887
+ $wcal_selected_variation = '';
2888
+ $wcal_all_attribute = $v->variation;
2889
+ $variation_id_only = $v->variation_id;
2890
+ foreach ($wcal_all_attribute as $wcal_all_attribute_key => $wcal_all_attribute_value) {
2891
+ $taxonomy = explode( 'attribute_', $wcal_all_attribute_key );
2892
+ $meta = get_post_meta( $variation_id_only, $wcal_all_attribute_key, true );
2893
+ $term = get_term_by( 'slug', $meta, $taxonomy[1] );
2894
+ $variation_name_only = $term->name;
2895
+ $wcal_selected_variation .= $variation_name_only . "<br>";
2896
+ }
2897
+ $add_product_name = $product_name . ' - ' . $wcal_selected_variation;
2898
+ }
2899
+ $pro_name_variation = (array) $add_product_name;
2900
  }
2901
  }else{
2902
+ $pro_name_variation = array_slice( $explode_all, 1, -1 );
2903
  }
2904
  $product_name_with_variable = '';
2905
  $explode_many_varaition = array();
3159
  </td>
3160
  </tr>
3161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3162
  <tr>
3163
  <th>
3164
  <label for="woocommerce_ac_email_frequency"><b><?php _e( 'Send this email:', 'woocommerce-ac' ); ?></b></label>