Headline
CVE-2023-2986: woocommerce-ac.php in woocommerce-abandoned-cart/trunk – WordPress Plugin Repository
The Abandoned Cart Lite for WooCommerce plugin for WordPress is vulnerable to authentication bypass in versions up to, and including, 5.14.2. This is due to insufficient encryption on the user being supplied during the abandoned cart link decode through the plugin. This allows unauthenticated attackers to log in as users who have abandoned the cart, which users are typically customers.
1<?php2/**3 * Plugin Name: Abandoned Cart Lite for WooCommerce4 * Plugin URI: http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro5 * 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: 5.15.07 * Author: Tyche Softwares8 * Author URI: http://www.tychesoftwares.com/9 * Text Domain: woocommerce-abandoned-cart10 * Domain Path: /i18n/languages/11 * Requires PHP: 5.612 * WC requires at least: 4.0.013 * WC tested up to: 7.7.214 *15 * @package Abandoned-Cart-Lite-for-WooCommerce16 */1718use Automattic\WooCommerce\Utilities\OrderUtil;1920require_once 'class-wcal-update.php’;21require_once 'includes/class-wcal-guest-ac.php’;22require_once 'includes/class-wcal-default-template-settings.php’;23require_once 'includes/class-wcal-delete-handler.php’;24require_once 'includes/classes/class-wcal-aes.php’;25require_once 'includes/classes/class-wcal-aes-counter.php’;26require_once 'includes/class-wcal-common.php’;2728require_once 'includes/class-wcal-admin-notice.php’;29require_once 'includes/class-wcal-tracking-msg.php’;30require_once 'includes/admin/class-wcal-personal-data-eraser.php’;31require_once 'includes/admin/class-wcal-personal-data-export.php’;32require_once 'includes/admin/class-wcal-abandoned-cart-details.php’;3334require_once 'includes/admin/class-wcap-pro-settings.php’;35require_once 'includes/admin/class-wcap-pro-settings-callbacks.php’;36require_once 'includes/admin/class-wcap-add-cart-popup-modal.php’;37require_once 'includes/connectors/class-wcap-connectors-common.php’;38require_once 'includes/connectors/class-wcap-connector.php’;39require_once 'includes/connectors/class-wcap-display-connectors.php’;40require_once 'includes/class-wcap-integrations.php’;41require_once 'includes/wcal-functions.php’;42require_once 'includes/class-wcal-webhooks.php’;4344load_plugin_textdomain( 'woocommerce-abandoned-cart’, false, basename( dirname( __FILE__ ) ) . ‘/i18n/languages’ );4546/**47 * Schedule an action to delete old carts once a day48 *49 * @since 5.150 * @package Abandoned-Cart-Lite-for-WooCommerce/Cron51 */52if ( ! wp_next_scheduled( ‘wcal_clear_carts’ ) ) {53 wp_schedule_event( time(), 'daily’, ‘wcal_clear_carts’ );54}5556/**57 * Main class58 */59if ( ! class_exists( ‘woocommerce_abandon_cart_lite’ ) ) {606162 /**63 * It will add the hooks, filters, menu and the variables and all the necessary actions for the plguins which will be used64 * all over the plugin.65 *66 * @since 1.067 * @package Abandoned-Cart-Lite-for-WooCommerce/Core68 */69 class woocommerce_abandon_cart_lite {70 /**71 * Duration One hour.72 *73 * @var int74 */75 public $one_hour;76 /**77 * Duration three hours.78 *79 * @var int80 */81 public $three_hours;82 /**83 * Duration six hours.84 *85 * @var int86 */87 public $six_hours;88 /**89 * Duration 12 hours.90 *91 * @var int92 */93 public $twelve_hours;94 /**95 * Duration One day.96 *97 * @var int98 */99 public $one_day;100 /**101 * Duration One week.102 *103 * @var int104 */105 public $one_week;106 /**107 * Duration range select108 *109 * @var array110 */111 public $duration_range_select;112 /**113 * Duration start & end dates114 *115 * @var array116 */117 public $start_end_dates;118 /**119 * The constructor will add the hooks, filters and the variable which will be used all over the plugin.120 *121 * @since 1.0122 */123 public function __construct() {124 if ( ! defined( ‘WCAL_PLUGIN_URL’ ) ) {125 define( 'WCAL_PLUGIN_URL’, untrailingslashit( plugins_url( '/’, __FILE__ ) ) );126 }127128 if ( ! defined( ‘WCAL_PLUGIN_VERSION’ ) ) {129 define( 'WCAL_PLUGIN_VERSION’, ‘5.15.0’ );130 }131132 if ( ! defined( ‘WCAL_PLUGIN_PATH’ ) ) {133 define( 'WCAL_PLUGIN_PATH’, untrailingslashit( plugin_dir_path( __FILE__ ) ) );134 }135 $this->one_hour = 60 * 60;136 $this->three_hours = 3 * $this->one_hour;137 $this->six_hours = 6 * $this->one_hour;138 $this->twelve_hours = 12 * $this->one_hour;139 $this->one_day = 24 * $this->one_hour;140 $this->one_week = 7 * $this->one_day;141 $this->duration_range_select = array(142 ‘yesterday’ => 'Yesterday’,143 ‘today’ => 'Today’,144 ‘last_seven’ => 'Last 7 days’,145 ‘last_fifteen’ => 'Last 15 days’,146 ‘last_thirty’ => 'Last 30 days’,147 ‘last_ninety’ => 'Last 90 days’,148 ‘last_year_days’ => 'Last 365’,149 );150151 $this->start_end_dates = array(152 ‘yesterday’ => array(153 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 24 * 60 * 60 ) ), // phpcs:ignore154 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 7 * 24 * 60 * 60 ) ), // phpcs:ignore155 ),156 ‘today’ => array(157 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore158 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore159 ),160 ‘last_seven’ => array(161 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 7 * 24 * 60 * 60 ) ), // phpcs:ignore162 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore163 ),164 ‘last_fifteen’ => array(165 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 15 * 24 * 60 * 60 ) ), // phpcs:ignore166 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore167 ),168 ‘last_thirty’ => array(169 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 30 * 24 * 60 * 60 ) ), // phpcs:ignore170 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore171 ),172 ‘last_ninety’ => array(173 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 90 * 24 * 60 * 60 ) ), // phpcs:ignore174 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore175 ),176 ‘last_year_days’ => array(177 ‘start_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) - 365 * 24 * 60 * 60 ) ), // phpcs:ignore178 ‘end_date’ => date( 'd M Y’, ( current_time( ‘timestamp’ ) ) ), // phpcs:ignore179 ),180 );181182 // Initialize settings.183 register_activation_hook( __FILE__, array( &$this, ‘wcal_activate’ ) );184 register_deactivation_hook( __FILE__, array( &$this, ‘wcal_deactivate’ ) );185186 // Action Scheduler for Cron.187 if ( file_exists( WP_PLUGIN_DIR . ‘/woocommerce/packages/action-scheduler/action-scheduler.php’ ) ) {188 require_once WP_PLUGIN_DIR . '/woocommerce/packages/action-scheduler/action-scheduler.php’;189 } else {190 add_action( 'admin_notices’, array( &$this, ‘wcal_as_failed_notice’ ) );191 }192 add_action( 'init’, array( &$this, ‘wcal_add_scheduled_action’ ) );193 require_once 'cron/class-wcal-cron.php’;194 require_once 'includes/class-wcal-process-base.php’;195196 // WordPress Administration Menu.197 add_action( 'admin_menu’, array( &$this, ‘wcal_admin_menu’ ) );198 add_action( 'before_woocommerce_init’, array( &$this, ‘wcal_custom_order_tables_compatibility’ ), 999 );199200 // Actions to be done on cart update.201 add_action( 'woocommerce_add_to_cart’, array( &$this, ‘wcal_store_cart_timestamp’ ), PHP_INT_MAX );202 add_action( 'woocommerce_cart_item_removed’, array( &$this, ‘wcal_store_cart_timestamp’ ), PHP_INT_MAX );203 add_action( 'woocommerce_cart_item_restored’, array( &$this, ‘wcal_store_cart_timestamp’ ), PHP_INT_MAX );204 add_action( 'woocommerce_after_cart_item_quantity_update’, array( &$this, ‘wcal_store_cart_timestamp’ ), PHP_INT_MAX );205 add_action( 'woocommerce_calculate_totals’, array( &$this, ‘wcal_store_cart_timestamp’ ), PHP_INT_MAX );206207 add_filter( 'wcal_block_crawlers’, array( &$this, ‘wcal_detect_crawlers’ ), 10, 1 );208209 add_action( 'admin_init’, array( &$this, ‘wcal_action_admin_init’ ) );210211 // Update the options as per settings API.212 add_action( 'admin_init’, array( 'Wcal_Update’, ‘wcal_schedule_update_action’ ) );213 add_action( 'wcal_update_db’, array( 'Wcal_Update’, ‘wcal_update_db_check’ ) );214215 // WordPress settings API.216 add_action( 'admin_init’, array( &$this, ‘wcal_initialize_plugin_options’ ) );217218 // Language Translation.219 add_action( 'init’, array( &$this, ‘wcal_update_po_file’ ) );220221 add_action( 'init’, array( &$this, ‘wcal_add_component_file’ ) );222223 // track links.224 add_filter( 'template_include’, array( &$this, ‘wcal_email_track_links’ ), 99, 1 );225226 // It will used to unsubcribe the emails.227 add_action( 'template_include’, array( &$this, ‘wcal_email_unsubscribe’ ), 99, 1 );228229 add_action( 'admin_enqueue_scripts’, array( &$this, ‘wcal_enqueue_scripts_js’ ) );230 add_action( 'admin_enqueue_scripts’, array( &$this, ‘wcal_enqueue_scripts_css’ ) );231 // delete abandoned order after X number of days.232 if ( class_exists( ‘Wcal_Delete_Handler’ ) ) {233 add_action( 'wcal_clear_carts’, array( 'Wcal_Delete_Handler’, ‘wcal_delete_abandoned_carts_after_x_days’ ) );234 }235236 if ( is_admin() ) {237 // Load “admin-only” scripts here.238 add_action( 'admin_head’, array( &$this, ‘wcal_action_send_preview’ ) );239 add_action( 'wp_ajax_wcal_preview_email_sent’, array( &$this, ‘wcal_preview_email_sent’ ) );240 add_action( 'wp_ajax_wcal_toggle_template_status’, array( &$this, ‘wcal_toggle_template_status’ ) );241 add_action( 'wp_ajax_wcal_abandoned_cart_info’, array( &$this, ‘wcal_abandoned_cart_info’ ) );242 add_action( 'wp_ajax_wcal_dismiss_admin_notice’, array( &$this, ‘wcal_dismiss_admin_notice’ ) );243244 add_filter( 'ts_tracker_data’, array( 'wcal_common’, ‘ts_add_plugin_tracking_data’ ), 10, 1 );245 add_filter( 'ts_tracker_opt_out_data’, array( 'wcal_common’, ‘ts_get_data_for_opt_out’ ), 10, 1 );246 add_filter( 'ts_deativate_plugin_questions’, array( &$this, ‘wcal_deactivate_add_questions’ ), 10, 1 );247248 add_action( 'wp_ajax_wcal_json_find_coupons’, array( &$this, ‘wcal_json_find_coupons’ ) );249 }250251 // Plugin Settings link in WP->Plugins page.252 $plugin = plugin_basename( __FILE__ );253 add_action( “plugin_action_links_$plugin", array( &$this, ‘wcal_settings_link’ ) );254255 add_action( 'admin_init’, array( $this, ‘wcal_preview_emails’ ) );256 add_action( 'init’, array( $this, ‘wcal_app_output_buffer’ ) );257258 add_filter( 'admin_footer_text’, array( $this, ‘wcal_admin_footer_text’ ), 1 );259260 add_action( 'admin_notices’, array( 'Wcal_Admin_Notice’, ‘wcal_show_db_update_notice’ ) );261262 include_once 'includes/frontend/class-wcal-frontend.php’;263264 add_filter( 'cron_schedules’, array( __CLASS__, ‘wcal_add_cron_schedule’ ) ); //phpcs:ignore265 add_action( 'woocommerce_ac_delete_coupon_action’, array( __CLASS__, ‘wcal_delete_expired_used_coupon_code’ ) );266 add_action( 'wp_ajax_wcal_delete_expired_used_coupon_code’, array( __CLASS__, ‘wcal_delete_expired_used_coupon_code’ ) );267268 add_action( 'woocommerce_coupon_error’, array( 'wcal_common’, ‘wcal_capture_coupon_error’ ), 15, 2 );269 add_action( 'woocommerce_applied_coupon’, array( 'wcal_common’, ‘wcal_capture_applied_coupon’ ), 15, 2 );270271 add_action( 'woocommerce_before_cart_table’, array( 'wcal_common’, ‘wcal_apply_direct_coupon_code’ ) );272 // Add coupon when user views checkout page (would not be added otherwise, unless user views cart first).273 add_action( 'woocommerce_before_checkout_form’, array( 'wcal_common’, ‘wcal_apply_direct_coupon_code’ ) );274 add_filter( 'woocommerce_email_from_address’, array( __CLASS__, ‘wcal_from_address_for_emails’ ), 10, 3 );275 add_filter( 'woocommerce_email_from_name’, array( __CLASS__, ‘wcal_from_name_for_emails’ ), 10, 3 );276 // 5.14.0277 if ( ‘yes’ === get_option( 'wcal_guest_users_manual_reset_needed’, ‘’ ) ) {278 add_action( 'admin_notices’, array( ‘Wcal_Update’, ‘wcal_add_notice’ ) );279 }280 }281282 /**283 * Action Scheduler library load failed. So add an admin notice.284 *285 * @since 5.9.0286 */287 public static function wcal_as_failed_notice() {288 $as_link = "<a href=’https://www.tychesoftwares.com/moving-to-the-action-scheduler-library/’ target=’_blank’>Action Scheduler library</a>";289 ?>290 <div class="notice notice-error">291 <p>292 <?php293 echo wp_kses_post( __( “Abandoned Cart Lite for WooCommerce was unable to load the $as_link. Please ensure you are running WooCommerce 4.0.0 or higher to send automated reminder emails. Currrently no automated reminder emails are being sent for abandoned carts.", ‘woocommerce-abandoned-cart’ ) ); // phpcs:ignore294 ?>295 </p>296 </div>297 <?php298 }299300 /**301 * Add Recurring Scheduled Action.302 */303 public static function wcal_add_scheduled_action() {304 if ( function_exists( ‘as_next_scheduled_action’ ) ) {305 if ( false === as_next_scheduled_action( ‘woocommerce_ac_send_email_action’ ) ) {306 wp_clear_scheduled_hook( ‘woocommerce_ac_send_email_action’ ); // Remove the cron job is present.307 as_schedule_recurring_action( time() + 60, 900, ‘woocommerce_ac_send_email_action’ ); // Schedule recurring action.308 }309 }310 }311312 /**313 * Add Settings link to WP->Plugins page.314 *315 * @param array $links - Links to be displayed.316 * @return array $links - Includes custom links.317 * @since 5.3.0318 */319 public static function wcal_settings_link( $links ) {320 $settings_link = ‘<a href="admin.php?page=woocommerce_ac_page&action=emailsettings">’ . __( 'Settings’, ‘woocommerce-abandoned-cart’ ) . '</a>’;321 array_push( $links, $settings_link );322 return $links;323 }324325 /**326 * It will load the boilerplate components file. In this file we have included all boilerplate files.327 * We need to inlcude this file after the init hook.328 *329 * @hook init330 */331 public static function wcal_add_component_file() {332 if ( is_admin() ) {333 require_once 'includes/class-wcal-all-component.php’;334335 }336 }337 /**338 * It will add the Questions while admin deactivate the plugin.339 *340 * @hook ts_deativate_plugin_questions.341 * @param array $wcal_add_questions Blank array.342 * @return array $wcal_add_questions List of all questions.343 */344 public static function wcal_deactivate_add_questions( $wcal_add_questions ) {345346 $wcal_add_questions = array(347 0 => array(348 ‘id’ => 4,349 ‘text’ => __( 'Emails are not being sent to customers.’, ‘woocommerce-abandoned-cart’ ),350 ‘input_type’ => ‘’,351 ‘input_placeholder’ => ‘’,352 ),353 1 => array(354 ‘id’ => 5,355 ‘text’ => __( ‘Capturing of cart and other information was not satisfactory.’, ‘woocommerce-abandoned-cart’ ),356 ‘input_type’ => ‘’,357 ‘input_placeholder’ => ‘’,358 ),359 2 => array(360 ‘id’ => 6,361 ‘text’ => __( ‘I cannot see abandoned cart reminder emails records.’, ‘woocommerce-abandoned-cart’ ),362 ‘input_type’ => ‘’,363 ‘input_placeholder’ => ‘’,364 ),365 3 => array(366 ‘id’ => 7,367 ‘text’ => __( ‘I want to upgrade the plugin to the PRO version.’, ‘woocommerce-abandoned-cart’ ),368 ‘input_type’ => ‘’,369 ‘input_placeholder’ => ‘’,370 ),371372 );373 return $wcal_add_questions;374 }375376 /**377 * Replace Merge tags in email previews.378 *379 * @param string $content - Email content.380 * @return string $content - content with cart data.381 * @since 5.8382 */383 public function replace_mergetags( $content ) {384385 $admin_args = array(386 ‘role’ => ‘administrator’,387 ‘fields’ => array( ‘id’ ),388 );389390 $admin_usr = get_users( $admin_args );391 $uid = $admin_usr[0]->id;392 $admin_phone = get_user_meta( $uid, ‘billing_phone’, true );393394 $wcal_price = wc_price( ‘150’ );395 $wcal_total_price = wc_price( ‘300’ );396397 $allowed_html = array(398 ‘span’ => array(399 ‘class’ => array(),400 ),401 );402 $spectre_img_src = esc_url( plugins_url( ‘/assets/images/spectre.jpg’, __FILE__ ) );403 $replace_data[‘products_cart’] = "<table border=’0’ width=’100%’ cellspacing=’0’ cellpadding=’0’><b>Your Shopping Cart</b>404 <tbody>405 <tr>406 <td style=’background-color: #666666; color: #ffffff; text-align: center; font-size: 13px; text-transform: uppercase; padding: 5px;’ align=’center’ bgcolor=’#666666’></td>407408 <td style=’background-color: #666666; color: #ffffff; text-align: center; font-size: 13px; text-transform: uppercase; padding: 5px;’ align=’center’ bgcolor=’#666666’>Product</td>409410 <td style=’background-color: #666666; color: #ffffff; text-align: center; font-size: 13px; text-transform: uppercase; padding: 5px;’ align=’center’ bgcolor=’#666666’>Price</td>411412 <td style=’background-color: #666666; color: #ffffff; text-align: center; font-size: 13px; text-transform: uppercase; padding: 5px;’ align=’center’ bgcolor=’#666666’>Quantity</td>413414 <td style=’background-color: #666666; color: #ffffff; text-align: center; font-size: 13px; text-transform: uppercase; padding: 5px;’ align=’center’ bgcolor=’#666666’>Total</td>415416 </tr>417 <tr style=’background-color:#f4f5f4;’>418 <td><img src = ‘$spectre_img_src’ height=’40px’ width=’40px’></td><td>Spectre</td><td>” . wp_kses( $wcal_price, $allowed_html ) . ‘</td><td>2</td><td>’ . wp_kses( $wcal_total_price, $allowed_html ) . ‘</td>419 </tr>420 <tr>421 <td> </td>422 <td> </td>423 <td> </td>424 <th>Cart Total:</th>425 <td>’ . wp_kses( $wcal_total_price, $allowed_html ) . '</td>426 </tr>427428 </tbody>429 </table>’;430431 $current_time = current_time( ‘timestamp’ ); // phpcs:ignore432 $date_format = date_i18n( get_option( ‘date_format’ ), $current_time );433 $time_format = date_i18n( get_option( ‘time_format’ ), $current_time );434435 $replace_data[‘admin_phone’] = $admin_phone;436 $replace_data[‘site_title’] = get_bloginfo( ‘name’ );437 $replace_data[‘site_url’] = get_option( ‘siteurl’ );438 $replace_data[‘abandoned_date’] = “$date_format $time_format";439 $replace_data[‘cart_url’] = wc_get_page_permalink( ‘cart’ );440441 $content = str_ireplace( '{{products.cart}}’, $replace_data[‘products_cart’], $content );442 $content = str_ireplace( '{{admin.phone}}’, $replace_data[‘admin_phone’], $content );443 $content = str_ireplace( '{{customer.firstname}}’, 'John’, $content );444 $content = str_ireplace( '{{customer.lastname}}’, 'Doe’, $content );445 $content = str_ireplace( '{{customer.fullname}}’, 'John Doe’, $content );446 $content = str_ireplace( '{{cart.abandoned_date}}’, $replace_data[‘abandoned_date’], $content );447 $content = str_ireplace( '{{cart.link}}’, $replace_data[‘cart_url’], $content );448 $content = str_ireplace( '{{cart.unsubscribe}}’, '#’, $content );449 $content = str_ireplace( 'site_title’, $replace_data[‘site_title’], $content );450 $content = str_ireplace( 'site_url’, $replace_data[‘site_url’], $content );451452 return $content;453 }454455 /**456 * It will ganerate the preview email template.457 *458 * @hook admin_init459 * @globals mixed $woocommerce460 * @since 2.5461 */462 public function wcal_preview_emails() {463 global $woocommerce;464465 if ( isset( $_GET[‘id’] ) && 0 < sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification466 global $wpdb;467 $id = sanitize_text_field( wp_unslash( $_GET[‘id’] ) ); // phpcs:ignore WordPress.Security.NonceVerification468 $content = $wpdb->get_var( // phpcs:ignore469 $wpdb->prepare(470 ‘SELECT body FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d’,471 absint( $id )472 )473 );474 $content = $this->replace_mergetags( $content );475 }476477 if ( isset( $_GET[‘wcal_preview_woocommerce_mail’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification478 if ( ! isset( $_REQUEST[‘_wpnonce’] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST[‘_wpnonce’] ) ), ‘woocommerce-abandoned-cart’ ) ) {479 die( ‘Security check’ );480 }481 $message = '’;482 // create a new email.483 if ( $woocommerce->version < ‘2.3’ ) {484 global $email_heading;485 ob_start();486487 include 'views/wcal-wc-email-template-preview.php’;488 $mailer = WC()->mailer();489 $message = ob_get_clean();490 $email_heading = __( 'HTML Email Template’, ‘woocommerce-abandoned-cart’ );491 $message = $mailer->wrap_message( $email_heading, $message );492 } else {493 // load the mailer class.494 $mailer = WC()->mailer();495 // get the preview email subject.496 $email_heading = __( 'Abandoned cart Email Template’, ‘woocommerce-abandoned-cart’ );497 // get the preview email content.498 ob_start();499 if ( isset( $_GET[‘id’] ) && 0 < sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification500 $message = stripslashes( $content );501 } else {502 include 'views/wcal-wc-email-template-preview.php’;503 $message = ob_get_clean();504 }505 // create a new email.506 $email = new WC_Email();507 // wrap the content with the email template and then add styles.508 $message = $email->style_inline( $mailer->wrap_message( $email_heading, $message ) );509 }510 echo $message; // phpcs:ignore511 exit;512 }513514 if ( isset( $_GET[‘wcal_preview_mail’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification515 if ( ! isset( $_REQUEST[‘_wpnonce’] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST[‘_wpnonce’] ) ), ‘woocommerce-abandoned-cart’ ) ) {516 die( ‘Security check’ );517 }518 // get the preview email content.519 ob_start();520 if ( isset( $_GET[‘id’] ) && 0 < sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification521 $message = stripslashes( $content );522 } else {523 include_once 'views/wcal-email-template-preview.php’;524 $message = ob_get_clean();525 }526 // print the preview email.527 echo $message; // phpcs:ignore528 exit;529 }530 }531532 /**533 * In this version we have allowed customer to transalte the plugin string using .po and .pot file.534 *535 * @hook init536 * @return $loaded537 * @since 1.6538 */539 public function wcal_update_po_file() {540 /*541 * Due to the introduction of language packs through translate.wordpress.org, loading our textdomain is complex.542 *543 * In v4.7, our textdomain changed from “woocommerce-ac” to “woocommerce-abandoned-cart".544 */545 $domain = 'woocommerce-abandoned-cart’;546 $locale = apply_filters( 'plugin_locale’, get_locale(), $domain );547 $loaded = load_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain . '-' . $locale . ‘.mo’ );548 if ( $loaded ) {549 return $loaded;550 } else {551 load_plugin_textdomain( $domain, false, basename( dirname( __FILE__ ) ) . ‘/i18n/languages/’ );552 }553 }554555 /**556 * It will create the plugin tables & the options reqired for plugin.557 *558 * @hook register_activation_hook559 * @globals mixed $wpdb560 * @since 1.0561 */562 public static function wcal_activate() {563564 // check whether its a multi site install or a single site install.565 if ( is_multisite() ) {566567 $blog_list = get_sites();568 foreach ( $blog_list as $blog_list_key => $blog_list_value ) {569 if ( $blog_list_value->blog_id > 1 ) { // child sites.570 $blog_id = $blog_list_value->blog_id;571 self::wcal_process_activate( $blog_id );572 add_blog_option( $blog_id, 'wcal_db_version’, WCAL_PLUGIN_VERSION );573 } else { // parent site.574 self::wcal_process_activate();575 add_blog_option( 1, 'wcal_db_version’, WCAL_PLUGIN_VERSION );576 }577 }578 } else { // single site.579 self::wcal_process_activate();580 add_option( 'wcal_db_version’, WCAL_PLUGIN_VERSION );581 }582 }583584 /**585 * Things to do when the plugin is deactivated.586 *587 * @since 5.8.0588 */589 public static function wcal_deactivate() {590 if ( false !== as_next_scheduled_action( ‘woocommerce_ac_send_email_action’ ) ) {591 as_unschedule_action( ‘woocommerce_ac_send_email_action’ ); // Remove the scheduled action.592 }593 do_action( ‘wcal_deactivate’ );594 }595 /**596 * Sets the compatibility with Woocommerce HPOS.597 *598 * @since 5.14.2599 */600 public static function wcal_custom_order_tables_compatibility() {601602 if ( class_exists( ‘\Automattic\WooCommerce\Utilities\FeaturesUtil’ ) ) {603 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables’, 'woocommerce-abandoned-cart/woocommerce-ac.php’, true );604 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'orders_cache’, 'woocommerce-abandoned-cart/woocommerce-ac.php’, true );605 }606 }607608 /**609 * Activation code: Create tables, default settings etc.610 *611 * @param int $blog_id - Greater than 0 for subsites in a multisite install, 0 for single sites.612 */613 public static function wcal_process_activate( $blog_id = 0 ) {614 global $wpdb;615616 $db_prefix = ( 0 === $blog_id ) ? $wpdb->prefix : $wpdb->prefix . $blog_id . '_’;617618 $wcap_collate = '’;619 if ( $wpdb->has_cap( ‘collation’ ) ) {620 $wcap_collate = $wpdb->get_charset_collate();621 }622 $table_name = $db_prefix . 'ac_email_templates_lite’;623 $wpdb->query( // phpcs:ignore624 “CREATE TABLE IF NOT EXISTS $table_name (625 `id` int(11) NOT NULL AUTO_INCREMENT,626 `email_type` varchar(50) NOT NULL,627 `subject` text NOT NULL,628 `body` mediumtext NOT NULL,629 `is_active` enum(‘0’,’1’) NOT NULL,630 `frequency` int(11) NOT NULL,631 `day_or_hour` enum(‘Days’,’Hours’,’Minutes’) NOT NULL,632 `template_name` text NOT NULL,633 `is_wc_template` enum(‘0’,’1’) NOT NULL,634 `default_template` int(11) NOT NULL,635 `wc_email_header` varchar(50) NOT NULL,636 `coupon_code` varchar(50) NOT NULL,637 `discount` varchar(50) NOT NULL,638 `discount_type` varchar(50) NOT NULL,639 `discount_shipping` varchar(50) NOT NULL,640 `discount_expiry` varchar(50) NOT NULL,641 `individual_use` enum(‘0’,’1’) NOT NULL,642 `generate_unique_coupon_code` enum(‘0’,’1’) NOT NULL,643 PRIMARY KEY (`id`)644 ) $wcap_collate AUTO_INCREMENT=1” // phpcs:ignore645 );646647 $sent_table_name = $db_prefix . 'ac_sent_history_lite’;648 $wpdb->query( // phpcs:ignore649 “CREATE TABLE IF NOT EXISTS $sent_table_name (650 `id` int(11) NOT NULL auto_increment,651 `template_id` varchar(40) collate utf8_unicode_ci NOT NULL,652 `abandoned_order_id` int(11) NOT NULL,653 `sent_time` datetime NOT NULL,654 `sent_email_id` text COLLATE utf8_unicode_ci NOT NULL,655 `encrypt_key` varchar(500) COLLATE utf8_unicode_ci NOT NULL,656 PRIMARY KEY (`id`)657 ) $wcap_collate AUTO_INCREMENT=1 " // phpcs:ignore658 );659660 $ac_history_table_name = $db_prefix . 'ac_abandoned_cart_history_lite’;661 $wpdb->query( // phpcs:ignore662 “CREATE TABLE IF NOT EXISTS $ac_history_table_name (663 `id` int(11) NOT NULL AUTO_INCREMENT,664 `user_id` int(11) NOT NULL,665 `abandoned_cart_info` text COLLATE utf8_unicode_ci NOT NULL,666 `abandoned_cart_time` int(11) NOT NULL,667 `cart_ignored` enum(‘0’,’1’) COLLATE utf8_unicode_ci NOT NULL,668 `recovered_cart` int(11) NOT NULL,669 `user_type` text,670 `unsubscribe_link` enum(‘0’,’1’) COLLATE utf8_unicode_ci NOT NULL,671 `session_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,672 `email_reminder_status` varchar(50) COLLATE utf8_unicode_ci NOT NULL,673 `checkout_link` varchar(500) COLLATE utf8_unicode_ci NOT NULL,674 PRIMARY KEY (`id`)675 ) $wcap_collate” // phpcs:ignore676 );677678 $guest_table = $db_prefix . 'ac_guest_abandoned_cart_history_lite’;679 $result_guest_table = $wpdb->get_results( // phpcs:ignore680 “SHOW TABLES LIKE '$guest_table’” // phpcs:ignore681 );682683 if ( 0 === count( $result_guest_table ) ) {684 $ac_guest_history_table_name = $db_prefix . 'ac_guest_abandoned_cart_history_lite’;685 $wpdb->query( // phpcs:ignore686 “CREATE TABLE IF NOT EXISTS $ac_guest_history_table_name (687 `id` int(15) NOT NULL AUTO_INCREMENT,688 `billing_first_name` text,689 `billing_last_name` text,690 `billing_company_name` text,691 `billing_address_1` text,692 `billing_address_2` text,693 `billing_city` text,694 `billing_county` text,695 `billing_zipcode` text,696 `email_id` text,697 `phone` text,698 `ship_to_billing` text,699 `order_notes` text,700 `shipping_first_name` text,701 `shipping_last_name` text,702 `shipping_company_name` text,703 `shipping_address_1` text,704 `shipping_address_2` text,705 `shipping_city` text,706 `shipping_county` text,707 `shipping_zipcode` double,708 `shipping_charges` double,709 PRIMARY KEY (`id`)710 ) $wcap_collate AUTO_INCREMENT=63000000” // phpcs:ignore711 );712 }713714 $wcal_guest_user_id_altered = 0 === $blog_id ? get_option( ‘wcal_guest_user_id_altered’ ) : get_blog_option( $blog_id, ‘wcal_guest_user_id_altered’ );715716 // Alter Guest Table A_I value if needed.717 if ( ‘yes’ !== $wcal_guest_user_id_altered ) {718 Wcal_Update::wcal_reset_guest_user_id( $db_prefix, $blog_id, 1 );719 }720 // Default templates - function call to create default templates.721 $check_table_empty = $wpdb->get_var( ‘SELECT COUNT(*) FROM `’ . $db_prefix . ‘ac_email_templates_lite`’ ); // phpcs:ignore722723 /**724 * This is add for thos user who Install the plguin first time.725 * So for them this option will be cheked.726 */727 if ( 0 === $blog_id ) {728 if ( ! get_option( ‘wcal_new_default_templates’ ) ) {729 if ( 0 === (int) $check_table_empty ) {730 $default_template = new Wcal_Default_Template_Settings();731 $default_template->wcal_create_default_templates( $db_prefix, $blog_id );732 }733 }734 if ( ! get_option( ‘ac_lite_cart_abandoned_time’ ) ) {735 add_option( 'ac_lite_cart_abandoned_time’, 10 );736 }737 if ( ! get_option( ‘ac_lite_track_guest_cart_from_cart_page’ ) ) {738 add_option( 'ac_lite_track_guest_cart_from_cart_page’, ‘on’ );739 }740 if ( ! get_option( ‘wcal_from_name’ ) ) {741 add_option( 'wcal_from_name’, ‘Admin’ );742 }743 $wcal_get_admin_email = get_option( ‘admin_email’ );744 if ( ! get_option( ‘wcal_from_email’ ) ) {745 add_option( 'wcal_from_email’, $wcal_get_admin_email );746 }747748 if ( ! get_option( ‘wcal_reply_email’ ) ) {749 add_option( 'wcal_reply_email’, $wcal_get_admin_email );750 }751 } else {752 if ( ! get_blog_option( $blog_id, ‘wcal_new_default_templates’ ) ) {753 if ( 0 === $check_table_empty ) {754 $default_template = new Wcal_Default_Template_Settings();755 $default_template->wcal_create_default_templates( $db_prefix, $blog_id );756 }757 }758 if ( ! get_blog_option( $blog_id, ‘ac_lite_cart_abandoned_time’ ) ) {759 add_blog_option( $blog_id, 'ac_lite_cart_abandoned_time’, 10 );760 }761 if ( ! get_blog_option( $blog_id, ‘ac_lite_track_guest_cart_from_cart_page’ ) ) {762 add_blog_option( $blog_id, 'ac_lite_track_guest_cart_from_cart_page’, ‘on’ );763 }764 if ( ! get_blog_option( $blog_id, ‘wcal_from_name’ ) ) {765 add_blog_option( $blog_id, 'wcal_from_name’, ‘Admin’ );766 }767 $wcal_get_admin_email = get_option( ‘admin_email’ );768 if ( ! get_blog_option( $blog_id, ‘wcal_from_email’ ) ) {769 add_blog_option( $blog_id, 'wcal_from_email’, $wcal_get_admin_email );770 }771772 if ( ! get_blog_option( $blog_id, ‘wcal_reply_email’ ) ) {773 add_blog_option( $blog_id, 'wcal_reply_email’, $wcal_get_admin_email );774 }775 }776 do_action( ‘wcal_activate’ );777 }778779 /**780 * It will add the section, field, & registres the plugin fields using Settings API.781 *782 * @hook admin_init783 * @since 2.5784 */785 public function wcal_initialize_plugin_options() {786787 // First, we register a section. This is necessary since all future options must belong to a section.788 add_settings_section(789 'ac_lite_general_settings_section’, // ID used to identify this section and with which to register options.790 __( 'Cart Abandonment Settings’, ‘woocommerce-abandoned-cart’ ), // Title to be displayed on the administration page.791 array( $this, ‘ac_lite_general_options_callback’ ), // Callback used to render the description of the section.792 ‘woocommerce_ac_page’ // Page on which to add this section of options.793 );794795 add_settings_field(796 'wcal_enable_cart_emails’,797 __( 'Enable abandoned cart emails’, ‘woocommerce-abandoned-cart’ ),798 array( $this, ‘wcal_enable_cart_emails_callback’ ),799 'woocommerce_ac_page’,800 'ac_lite_general_settings_section’,801 array( __( 'Yes, enable the abandoned cart emails.’, ‘woocommerce-abandoned-cart’ ) )802 );803804 add_settings_field(805 'ac_lite_cart_abandoned_time’,806 __( 'Cart abandoned cut-off time’, ‘woocommerce-abandoned-cart’ ),807 array( $this, ‘ac_lite_cart_abandoned_time_callback’ ),808 'woocommerce_ac_page’,809 'ac_lite_general_settings_section’,810 array( __( 'Consider cart abandoned after X minutes of item being added to cart & order not placed.’, ‘woocommerce-abandoned-cart’ ) )811 );812813 add_settings_field(814 'ac_lite_delete_abandoned_order_days’,815 __( 'Automatically Delete Abandoned Orders after X days’, ‘woocommerce-abandoned-cart’ ),816 array( $this, ‘wcal_delete_abandoned_orders_days_callback’ ),817 'woocommerce_ac_page’,818 'ac_lite_general_settings_section’,819 array( __( 'Automatically delete abandoned cart orders after X days.’, ‘woocommerce-abandoned-cart’ ) )820 );821822 add_settings_field(823 'ac_lite_email_admin_on_recovery’,824 __( 'Email admin On Order Recovery’, ‘woocommerce-abandoned-cart’ ),825 array( $this, ‘ac_lite_email_admin_on_recovery’ ),826 'woocommerce_ac_page’,827 'ac_lite_general_settings_section’,828 array( __( 'Sends email to Admin if an Abandoned Cart Order is recovered.’, ‘woocommerce-abandoned-cart’ ) )829 );830831 add_settings_field(832 'ac_lite_track_guest_cart_from_cart_page’,833 __( 'Start tracking from Cart Page’, ‘woocommerce-abandoned-cart’ ),834 array( $this, ‘wcal_track_guest_cart_from_cart_page_callback’ ),835 'woocommerce_ac_page’,836 'ac_lite_general_settings_section’,837 array( __( 'Enable tracking of abandoned products & carts even if customer does not visit the checkout page or does not enter any details on the checkout page like Name or Email. Tracking will begin as soon as a visitor adds a product to their cart and visits the cart page.’, ‘woocommerce-abandoned-cart’ ) )838 );839840 add_settings_section(841 'ac_lite_gdpr_settings’, // ID used to identify this section and with which to register options.842 __( 'GDPR Settings’, ‘woocommerce-abandoned-cart’ ), // Title to be displayed on the administration page.843 array( $this, ‘ac_lite_gdpr_callback’ ), // Callback used to render the description of the section.844 ‘woocommerce_ac_page’ // Page on which to add this section of options.845 );846847 add_settings_field(848 'wcal_enable_gdpr_consent’,849 __( 'Enable GDPR Notice’, ‘woocommerce-abandoned-cart’ ),850 array( $this, ‘wcal_enable_gdpr_callback’ ),851 'woocommerce_ac_page’,852 'ac_lite_gdpr_settings’,853 array( __( 'Enable this setting to display a notice informing customers that their email and cart data are saved to send abandonment reminders.’, ‘woocommerce-abandoned-cart’ ) )854 );855856 add_settings_field(857 'wcal_guest_cart_capture_msg’,858 __( 'Message to be displayed for Guest users when tracking their carts’, ‘woocommerce-abandoned-cart’ ),859 array( $this, ‘wcal_guest_cart_capture_msg_callback’ ),860 'woocommerce_ac_page’,861 'ac_lite_gdpr_settings’,862 array( __( '<br>In compliance with GDPR, add a message on the Checkout page to inform Guest users of how their data is being used.<br><i>For example: Your email address will help us support your shopping experience throughout the site. Please check our Privacy Policy to see how we use your personal data.</i>’, ‘woocommerce-abandoned-cart’ ) )863 );864865 add_settings_field(866 'wcal_logged_cart_capture_msg’,867 __( 'Message to be displayed for registered users when tracking their carts.’, ‘woocommerce-abandoned-cart’ ),868 array( $this, ‘wcal_logged_cart_capture_msg_callback’ ),869 'woocommerce_ac_page’,870 'ac_lite_gdpr_settings’,871 array( __( '<br>In compliance with GDPR, add a message on the Shop & Product pages to inform Registered users of how their data is being used.<br><i>For example: Please check our Privacy Policy to see how we use your personal data.</i>’, ‘woocommerce-abandoned-cart’ ) )872 );873874 add_settings_field(875 'wcal_gdpr_allow_opt_out’,876 __( 'Allow the visitor to opt out of cart tracking.’, ‘woocommerce-abandoned-cart’ ),877 array( $this, ‘wcal_gdpr_allow_opt_out_callback’ ),878 'woocommerce_ac_page’,879 'ac_lite_gdpr_settings’,880 array( __( '<br>In compliance with GDPR, allow the site visitor (guests & registered users) to opt out from cart tracking. This message will be displayed in conjunction with the GDPR message above.</i>’, ‘woocommerce-abandoned-cart’ ) )881 );882883 add_settings_field(884 'wcal_gdpr_opt_out_message’,885 __( 'Message to be displayed when the user chooses to opt out of cart tracking.’, ‘woocommerce-abandoned-cart’ ),886 array( $this, ‘wcal_gdpr_opt_out_msg_callback’ ),887 'woocommerce_ac_page’,888 'ac_lite_gdpr_settings’,889 array( __( '<br>Message to be displayed when the user chooses to opt out of cart tracking.</i>’, ‘woocommerce-abandoned-cart’ ) )890 );891 add_settings_section(892 'ac_lite_coupon_settings’, // ID used to identify this section and with which to register options.893 __( 'Coupon Settings’, ‘woocommerce-abandoned-cart’ ), // Title to be displayed on the administration page.894 array( $this, ‘ac_lite_coupon_callback’ ), // Callback used to render the description of the section.895 ‘woocommerce_ac_page’ // Page on which to add this section of options.896 );897 add_settings_field(898 'wcal_delete_coupon_data’,899 __( 'Delete Coupons Automatically’, ‘woocommerce-abandoned-cart’ ),900 array( $this, ‘wcal_deleting_coupon_data’ ),901 'woocommerce_ac_page’,902 'ac_lite_coupon_settings’,903 array( __( 'Enable this setting if you want to completely remove the expired and used coupon code automatically every 15 days.’, ‘woocommerce-abandoned-cart’ ) )904 );905 add_settings_field(906 'wcal_delete_coupon_data_manually’,907 __( 'Delete Coupons Manually’, ‘woocommerce-abandoned-cart’ ),908 array( $this, ‘wcal_deleting_coupon_data_manually’ ),909 'woocommerce_ac_page’,910 'ac_lite_coupon_settings’,911 array( __( 'If you want to completely remove the expired and used coupon code now then click on “Delete” button.’, ‘woocommerce-abandoned-cart’ ) )912 );913 /**914 * New section for the Adding the abandoned cart setting.915 *916 * @since 4.7917 */918 add_settings_section(919 'ac_email_settings_section’, // ID used to identify this section and with which to register options.920 __( 'Settings for abandoned cart recovery emails’, ‘woocommerce-abandoned-cart’ ), // Title to be displayed on the administration page.921 array( $this, ‘wcal_email_callback’ ), // Callback used to render the description of the section.922 ‘woocommerce_ac_email_page’ // Page on which to add this section of options.923 );924925 add_settings_field(926 'wcal_from_name’,927 __( '"From” Name’, ‘woocommerce-abandoned-cart’ ),928 array( $this, ‘wcal_from_name_callback’ ),929 'woocommerce_ac_email_page’,930 'ac_email_settings_section’,931 array( 'Enter the name that should appear in the email sent.’, ‘woocommerce-abandoned-cart’ )932 );933934 add_settings_field(935 'wcal_from_email’,936 __( '"From” Address’, ‘woocommerce-abandoned-cart’ ),937 array( $this, ‘wcal_from_email_callback’ ),938 'woocommerce_ac_email_page’,939 'ac_email_settings_section’,940 array( 'Email address from which the reminder emails should be sent.’, ‘woocommerce-abandoned-cart’ )941 );942943 add_settings_field(944 'wcal_reply_email’,945 __( 'Send Reply Emails to’, ‘woocommerce-abandoned-cart’ ),946 array( $this, ‘wcal_reply_email_callback’ ),947 'woocommerce_ac_email_page’,948 'ac_email_settings_section’,949 array( 'When a contact receives your email and clicks reply, which email address should that reply be sent to?’, ‘woocommerce-abandoned-cart’ )950 );951952 add_settings_field(953 'wcal_add_utm_to_links’,954 __( 'UTM parameters to be added to all the links in reminder emails’, ‘woocommerce-abandoned-cart’ ),955 array( &$this, ‘wcal_add_utm_to_links_callback’ ),956 'woocommerce_ac_email_page’,957 'ac_email_settings_section’,958 array( __( 'UTM parameters that should be added to all the links in reminder emails.’, ‘woocommerce-abandoned-cart’ ) )959 );960961 // Finally, we register the fields with WordPress.962 register_setting(963 'woocommerce_ac_settings’,964 'wcal_enable_cart_emails’965 );966967 register_setting(968 'woocommerce_ac_settings’,969 'ac_lite_cart_abandoned_time’,970 array( $this, ‘ac_lite_cart_time_validation’ )971 );972973 register_setting(974 'woocommerce_ac_settings’,975 'ac_lite_delete_abandoned_order_days’,976 array( $this, ‘wcal_delete_days_validation’ )977 );978979 register_setting(980 'woocommerce_ac_settings’,981 'ac_lite_email_admin_on_recovery’982 );983984 register_setting(985 'woocommerce_ac_settings’,986 'ac_lite_track_guest_cart_from_cart_page’987 );988989 register_setting(990 'woocommerce_ac_settings’,991 'wcal_enable_gdpr_consent’992 );993994 register_setting(995 'woocommerce_ac_settings’,996 'wcal_guest_cart_capture_msg’997 );998999 register_setting(1000 'woocommerce_ac_settings’,1001 'wcal_logged_cart_capture_msg’1002 );10031004 register_setting(1005 'woocommerce_ac_settings’,1006 'wcal_gdpr_allow_opt_out’1007 );10081009 register_setting(1010 'woocommerce_ac_settings’,1011 'wcal_gdpr_opt_out_message’1012 );10131014 register_setting(1015 'woocommerce_ac_email_settings’,1016 'wcal_from_name’1017 );1018 register_setting(1019 'woocommerce_ac_email_settings’,1020 'wcal_from_email’1021 );1022 register_setting(1023 'woocommerce_ac_email_settings’,1024 'wcal_reply_email’1025 );10261027 register_setting(1028 'woocommerce_ac_email_settings’,1029 'wcal_add_utm_to_links’1030 );10311032 register_setting(1033 'woocommerce_ac_settings’,1034 'wcal_delete_coupon_data’1035 );10361037 do_action( ‘wcal_add_new_settings’ );1038 }10391040 /**1041 * Settings API callback for section “ac_lite_general_settings_section".1042 *1043 * @since 2.51044 */1045 public function ac_lite_general_options_callback() {1046 }10471048 /**1049 * Settings API callback for the enable cart reminder emails.1050 *1051 * @param array $args - Arguments.1052 * @since 5.51053 */1054 public static function wcal_enable_cart_emails_callback( $args ) {10551056 $enable_cart_emails = get_option( 'wcal_enable_cart_emails’, ‘’ );10571058 if ( isset( $enable_cart_emails ) && ‘’ === $enable_cart_emails ) {1059 $enable_cart_emails = 'off’;1060 }1061 printf(1062 '<input type="checkbox” id="wcal_enable_cart_emails” name="wcal_enable_cart_emails” value="on" ' . checked( 'on’, $enable_cart_emails, false ) . ' />’1063 );1064 $html = '<label for="wcal_enable_cart_emails"> ' . $args[0] . '</label>’;1065 echo wp_kses_post( $html );1066 }10671068 /**1069 * Settings API callback for cart time field.1070 *1071 * @param array $args Arguments.1072 * @since 2.51073 */1074 public function ac_lite_cart_abandoned_time_callback( $args ) {1075 // First, we read the option.1076 $cart_abandoned_time = get_option( ‘ac_lite_cart_abandoned_time’ );1077 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1078 // We also access the show_header element of the options collection in the call to the checked() helper function.1079 printf(1080 '<input type="text" id="ac_lite_cart_abandoned_time" name="ac_lite_cart_abandoned_time" value="%s" />’,1081 isset( $cart_abandoned_time ) ? esc_attr( $cart_abandoned_time ) : '’1082 );1083 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1084 $html = '<label for="ac_lite_cart_abandoned_time"> ' . $args[0] . '</label>’;1085 echo wp_kses_post( $html );1086 }10871088 /**1089 * Settings API cart time field validation.1090 *1091 * @param int|string $input - Input to be validated.1092 * @return int|string $output - Validated output.1093 * @since 2.51094 */1095 public function ac_lite_cart_time_validation( $input ) {1096 $output = '’;1097 if ( ‘’ != $input && ( is_numeric( $input ) && $input > 0 ) ) { // phpcs:ignore1098 $output = stripslashes( $input );1099 } else {1100 add_settings_error( 'ac_lite_cart_abandoned_time’, 'error found’, __( 'Abandoned cart cut off time should be numeric and has to be greater than 0.’, ‘woocommerce-abandoned-cart’ ) );1101 }1102 return $output;1103 }11041105 /**1106 * Validation for automatically delete abandoned carts after X days.1107 *1108 * @param int | string $input input of the field Abandoned cart cut off time.1109 * @return int | string $output Error message or the input value.1110 * @since 5.01111 */1112 public static function wcal_delete_days_validation( $input ) {1113 $output = '’;1114 if ( is_numeric( $input ) && $input > 0 ) {1115 $output = stripslashes( $input );1116 } else {1117 $output = '365’;1118 add_settings_error( 'ac_lite_delete_abandoned_order_days’, 'error found’, __( 'Automatically Delete Abandoned Orders after X days has to be greater than 0.’, ‘woocommerce-abandoned-cart’ ) );1119 }1120 return $output;1121 }11221123 /**1124 * Callback for deleting abandoned order after X days field.1125 *1126 * @param array $args Argument given while adding the field.1127 * @since 5.01128 */1129 public static function wcal_delete_abandoned_orders_days_callback( $args ) {1130 // First, we read the option.1131 $delete_abandoned_order_days = get_option( 'ac_lite_delete_abandoned_order_days’, ‘365’ );1132 if ( ‘’ === $delete_abandoned_order_days ) {1133 $delete_abandoned_order_days = '365’;1134 }1135 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1136 // We also access the show_header element of the options collection in the call to the checked() helper function.1137 printf(1138 '<input type="text" id="ac_lite_delete_abandoned_order_days" name="ac_lite_delete_abandoned_order_days" value="%s" />’,1139 isset( $delete_abandoned_order_days ) ? esc_attr( $delete_abandoned_order_days ) : '’1140 );1141 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1142 $html = '<label for="ac_lite_delete_abandoned_order_days"> ' . $args[0] . '</label>’;1143 echo wp_kses_post( $html );1144 }11451146 /**1147 * Settings API callback for email admin on cart recovery field.1148 *1149 * @param array $args Arguments.1150 * @since 2.51151 */1152 public function ac_lite_email_admin_on_recovery( $args ) {1153 // First, we read the option.1154 $email_admin_on_recovery = get_option( 'ac_lite_email_admin_on_recovery’, ‘’ );11551156 // This condition added to avoid the notie displyed while Check box is unchecked.1157 if ( isset( $email_admin_on_recovery ) && ‘’ === $email_admin_on_recovery ) {1158 $email_admin_on_recovery = 'off’;1159 }1160 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1161 // We also access the show_header element of the options collection in the call to the checked() helper function.1162 $html = '’;1163 printf(1164 '<input type="checkbox" id="ac_lite_email_admin_on_recovery" name="ac_lite_email_admin_on_recovery" value="on"1165 ' . checked( 'on’, $email_admin_on_recovery, false ) . ' />’1166 );11671168 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1169 $html .= ‘<label for="ac_lite_email_admin_on_recovery"> ' . $args[0] . ‘</label>’;1170 echo wp_kses_post( $html );1171 }11721173 /**1174 * Settings API callback for capturing guest cart which do not reach the checkout page.1175 *1176 * @param array $args Arguments.1177 * @since 2.71178 */1179 public function wcal_track_guest_cart_from_cart_page_callback( $args ) {1180 // First, we read the option.1181 $disable_guest_cart_from_cart_page = get_option( ‘ac_lite_track_guest_cart_from_cart_page’, ‘’ );11821183 // This condition added to avoid the notice displyed while Check box is unchecked.1184 if ( isset( $disable_guest_cart_from_cart_page ) && ‘’ === $disable_guest_cart_from_cart_page ) {1185 $disable_guest_cart_from_cart_page = ‘off’;1186 }1187 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1188 // We also access the show_header element of the options collection in the call to the checked() helper function.1189 $html = ‘’;11901191 printf(1192 ‘<input type="checkbox" id="ac_lite_track_guest_cart_from_cart_page" name="ac_lite_track_guest_cart_from_cart_page" value="on"1193 ' . checked( ‘on’, $disable_guest_cart_from_cart_page, false ) . ' />’1194 );1195 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1196 $html .= ‘<label for="ac_lite_track_guest_cart_from_cart_page"> ' . $args[0] . ‘</label>’;1197 echo wp_kses_post( $html );1198 }11991200 /**1201 * Callback - Enable GDPR consent.1202 *1203 * @param array $args - Arguments.1204 * @since 5.12.01205 */1206 public static function wcal_enable_gdpr_callback( $args ) {1207 $wcal_enable_gdpr = get_option( ‘wcal_enable_gdpr_consent’, ‘’ );1208 $wcal_gdpr_status = isset( $wcal_enable_gdpr ) && ‘’ === $wcal_enable_gdpr ? ‘off’ : ‘on’;1209 ?>1210 <input type="checkbox" id="wcal_enable_gdpr_consent" name="wcal_enable_gdpr_consent" value="on" <?php echo checked( ‘on’, $wcal_gdpr_status, false ); ?> />1211 <label for="wcal_enable_gdpr_consent"> <?php echo esc_attr( $args[0] ); ?></label>1212 <a >1213 <?php1214 }1215 /**1216 * Call back function for guest user cart capture message1217 *1218 * @param array $args Argument for adding field details.1219 * @since 7.81220 */1221 public static function wcal_guest_cart_capture_msg_callback( $args ) {12221223 $guest_msg = get_option( ‘wcal_guest_cart_capture_msg’ );12241225 printf(1226 "<textarea rows=’4’ cols=’80’ id=’wcal_guest_cart_capture_msg’ name=’wcal_guest_cart_capture_msg’>" . htmlspecialchars( $guest_msg, ENT_QUOTES ) . ‘</textarea>’ // phpcs:ignore1227 );12281229 $html = ‘<label for="wcal_guest_cart_capture_msg"> ' . $args[0] . ‘</label>’;1230 echo wp_kses_post( $html );1231 }12321233 /**1234 * Call back function for registered user cart capture message1235 *1236 * @param array $args Argument for adding field details.1237 * @since 7.81238 */1239 public static function wcal_logged_cart_capture_msg_callback( $args ) {12401241 $logged_msg = get_option( ‘wcal_logged_cart_capture_msg’ );12421243 printf(1244 "<input type=’text’ class=’regular-text’ id=’wcal_logged_cart_capture_msg’ name=’wcal_logged_cart_capture_msg’ value=’" . htmlspecialchars( $logged_msg, ENT_QUOTES ) . "’ />" // phpcs:ignore1245 );12461247 $html = ‘<label for="wcal_logged_cart_capture_msg"> ' . $args[0] . ‘</label>’;1248 echo wp_kses_post( $html );1249 }125012511252 /**1253 * Text to allow the user the choice to opt out of cart tracking.1254 *1255 * @param array $args - Arguments.1256 * @since 5.51257 */1258 public static function wcal_gdpr_allow_opt_out_callback( $args ) {12591260 $wcal_gdpr_allow_opt_out = get_option( ‘wcal_gdpr_allow_opt_out’ );12611262 printf(1263 "<input type=’text’ class=’regular-text’ id=’wcal_gdpr_allow_opt_out’ name=’wcal_gdpr_allow_opt_out’ value=’" . htmlspecialchars( $wcal_gdpr_allow_opt_out, ENT_QUOTES ) . "’ />" // phpcs:ignore1264 );12651266 $html = ‘<label for="wcal_gdpr_allow_opt_out"> ' . $args[0] . ‘</label>’;1267 echo wp_kses_post( $html );1268 }12691270 /**1271 * Message to display when the user chooses to opt out of cart tracking.1272 *1273 * @param array $args - Arguments.1274 * @since 5.51275 */1276 public static function wcal_gdpr_opt_out_msg_callback( $args ) {12771278 $wcal_gdpr_opt_out_message = get_option( ‘wcal_gdpr_opt_out_message’ );12791280 printf(1281 "<input type=’text’ class=’regular-text’ id=’wcal_gdpr_opt_out_message’ name=’wcal_gdpr_opt_out_message’ value=’" . htmlspecialchars( $wcal_gdpr_opt_out_message, ENT_QUOTES ) . "’ />" // phpcs:ignore1282 );12831284 $html = '<label for="wcal_gdpr_opt_out_message"> ' . $args[0] . '</label>’;1285 echo wp_kses_post( $html );1286 }12871288 /**1289 * Settings API callback for Abandoned cart email settings of the plugin.1290 *1291 * @since 3.51292 */1293 public function wcal_email_callback() {1294 }12951296 /**1297 * Settings API callback for from name used in Abandoned cart email.1298 *1299 * @param array $args Arguments.1300 * @since 3.51301 */1302 public static function wcal_from_name_callback( $args ) {1303 // First, we read the option.1304 $wcal_from_name = get_option( ‘wcal_from_name’ );1305 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1306 // We also access the show_header element of the options collection in the call to the checked() helper function.1307 printf(1308 '<input type="text" id="wcal_from_name" name="wcal_from_name" value="%s" />’,1309 isset( $wcal_from_name ) ? esc_attr( $wcal_from_name ) : '’1310 );1311 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1312 $html = '<label for="wcal_from_name_label"> ' . $args[0] . '</label>’;1313 echo wp_kses_post( $html );1314 }13151316 /**1317 * Settings API callback for from email used in Abandoned cart email.1318 *1319 * @param array $args Arguments.1320 * @since 3.51321 */1322 public static function wcal_from_email_callback( $args ) {1323 // First, we read the option.1324 $wcal_from_email = get_option( ‘wcal_from_email’ );1325 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1326 // We also access the show_header element of the options collection in the call to the checked() helper function.1327 printf(1328 '<input type="text" id="wcal_from_email" name="wcal_from_email" value="%s" />’,1329 isset( $wcal_from_email ) ? esc_attr( $wcal_from_email ) : '’1330 );1331 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1332 $html = '<label for="wcal_from_email_label"> ' . $args[0] . '</label>’;1333 echo wp_kses_post( $html );1334 }13351336 /**1337 * Settings API callback for reply email used in Abandoned cart email.1338 *1339 * @param array $args Arguments.1340 * @since 3.51341 */1342 public static function wcal_reply_email_callback( $args ) {1343 // First, we read the option.1344 $wcal_reply_email = get_option( ‘wcal_reply_email’ );1345 // Next, we update the name attribute to access this element’s ID in the context of the display options array.1346 // We also access the show_header element of the options collection in the call to the checked() helper function.1347 printf(1348 '<input type="text" id="wcal_reply_email" name="wcal_reply_email" value="%s" />’,1349 isset( $wcal_reply_email ) ? esc_attr( $wcal_reply_email ) : ‘’1350 );1351 // Here, we’ll take the first argument of the array and add it to a label next to the checkbox.1352 $html = ‘<label for="wcal_reply_email_label"> ' . $args[0] . ‘</label>’;1353 echo wp_kses_post( $html );1354 }13551356 /**1357 * Callback for UTM parameters.1358 *1359 * @param array $args - Arguments for the setting.1360 * @since 5.9.01361 */1362 public static function wcal_add_utm_to_links_callback( $args ) {13631364 $wcal_add_utm_to_links = get_option( ‘wcal_add_utm_to_links’, ‘’ );13651366 ?>1367 <textarea id=’wcal_add_utm_to_links’ rows=’4’ cols=’50’ name=’wcal_add_utm_to_links’ ><?php echo esc_html( $wcal_add_utm_to_links ); ?></textarea>1368 <?php1369 $html = ‘<label for="wcal_add_utm_to_links">’ . $args[0] . '</label>’;1370 echo wp_kses_post( $html );1371 }13721373 /**1374 * Add a submenu page under the WooCommerce.1375 *1376 * @hook admin_menu1377 * @since 1.01378 */1379 public function wcal_admin_menu() {1380 $page = add_submenu_page( 'woocommerce’, __( 'Abandoned Carts’, ‘woocommerce-abandoned-cart’ ), __( 'Abandoned Carts’, ‘woocommerce-abandoned-cart’ ), 'manage_woocommerce’, 'woocommerce_ac_page’, array( &$this, ‘wcal_menu_page’ ) );1381 }13821383 /**1384 * Capture the cart and insert the information of the cart into DataBase.1385 *1386 * @hook woocommerce_cart_updated1387 * @globals mixed $wpdb1388 * @globals mixed $woocommerce1389 * @since 1.01390 */1391 public function wcal_store_cart_timestamp() {13921393 $block_crawlers = apply_filters( 'wcal_block_crawlers’, false );13941395 if ( $block_crawlers ) {1396 return;1397 }13981399 if ( get_transient( ‘wcal_email_sent_id’ ) !== false ) {1400 wcal_common::wcal_set_cart_session( 'email_sent_id’, get_transient( ‘wcal_email_sent_id’ ) );1401 delete_transient( ‘wcal_email_sent_id’ );1402 }1403 if ( get_transient( ‘wcal_abandoned_id’ ) !== false ) {1404 wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite’, get_transient( ‘wcal_abandoned_id’ ) );1405 delete_transient( ‘wcal_abandoned_id’ );1406 }14071408 global $wpdb,$woocommerce;1409 $current_time = current_time( ‘timestamp’ ); // phpcs:ignore1410 $cut_off_time = get_option( ‘ac_lite_cart_abandoned_time’ );1411 $track_guest_cart_from_cart_page = get_option( ‘ac_lite_track_guest_cart_from_cart_page’ );1412 $cart_ignored = 0;1413 $recovered_cart = 0;14141415 $track_guest_user_cart_from_cart = '’;1416 if ( isset( $track_guest_cart_from_cart_page ) ) {1417 $track_guest_user_cart_from_cart = $track_guest_cart_from_cart_page;1418 }14191420 if ( isset( $cut_off_time ) ) {1421 $cart_cut_off_time = intval( $cut_off_time ) * 60;1422 } else {1423 $cart_cut_off_time = 60 * 60;1424 }1425 $compare_time = $current_time - $cart_cut_off_time;14261427 if ( is_user_logged_in() ) {14281429 $user_id = get_current_user_id();1430 $gdpr_consent = get_user_meta( $user_id, 'wcal_gdpr_tracking_choice’, true );14311432 if ( ‘’ === $gdpr_consent ) {1433 $gdpr_consent = true;1434 }14351436 $wcal_user_restricted = false;1437 $wcal_user_restricted = apply_filters( 'wcal_restrict_user’, $wcal_user_restricted, $user_id );14381439 if ( $gdpr_consent && ! $wcal_user_restricted ) {14401441 $results = $wpdb->get_results( // phpcs:ignore1442 $wpdb->prepare(1443 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s AND recovered_cart = %s’,1444 $user_id,1445 $cart_ignored,1446 $recovered_cart1447 )1448 );1449 if ( 0 === count( $results ) ) {1450 $cart_info_meta = array();1451 $cart_info_meta[‘cart’] = WC()->session->cart;1452 $cart_info_meta = wp_json_encode( $cart_info_meta );14531454 if ( ‘’ !== $cart_info_meta && ‘{"cart":[]}’ !== $cart_info_meta && ‘""’ !== $cart_info_meta ) {1455 $cart_info = $cart_info_meta;1456 $user_type = 'REGISTERED’;1457 $wpdb->query( //phpcs:ignore1458 $wpdb->prepare(1459 ‘INSERT INTO `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` ( user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type ) VALUES ( %d, %s, %d, %s, %s )',1460 $user_id,1461 $cart_info,1462 $current_time,1463 $cart_ignored,1464 $user_type1465 )1466 );1467 $abandoned_cart_id = $wpdb->insert_id;1468 wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite’, $abandoned_cart_id );1469 wcal_common::wcal_add_checkout_link( $abandoned_cart_id );1470 wcal_common::wcal_run_webhook_after_cutoff( $abandoned_cart_id );1471 }1472 } elseif ( isset( $results[0]->abandoned_cart_time ) && $compare_time > $results[0]->abandoned_cart_time ) {1473 $updated_cart_info = array();1474 $updated_cart_info[‘cart’] = WC()->session->cart;1475 $updated_cart_info = wp_json_encode( $updated_cart_info );14761477 if ( ! $this->wcal_compare_carts( $user_id, $results[0]->abandoned_cart_info ) ) {1478 $updated_cart_ignored = 1;1479 $wpdb->query( //phpcs:ignore1480 $wpdb->prepare(1481 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE user_id = %d’,1482 $updated_cart_ignored,1483 $user_id1484 )1485 );1486 $user_type = 'REGISTERED’;1487 $wpdb->query( //phpcs:ignore1488 $wpdb->prepare(1489 ‘INSERT INTO `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` (user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type) VALUES (%d, %s, %d, %s, %s)',1490 $user_id,1491 $updated_cart_info,1492 $current_time,1493 $cart_ignored,1494 $user_type1495 )1496 );1497 update_user_meta( $user_id, '_woocommerce_ac_modified_cart’, md5( ‘yes’ ) );14981499 $abandoned_cart_id = $wpdb->insert_id;1500 wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite’, $abandoned_cart_id );1501 wcal_common::wcal_add_checkout_link( $abandoned_cart_id );1502 wcal_common::wcal_run_webhook_after_cutoff( $abandoned_cart_id );1503 } else {1504 update_user_meta( $user_id, '_woocommerce_ac_modified_cart’, md5( ‘no’ ) );1505 }1506 } else {1507 $updated_cart_info = array();1508 $updated_cart_info[‘cart’] = WC()->session->cart;1509 $updated_cart_info = wp_json_encode( $updated_cart_info );15101511 $wpdb->query( //phpcs:ignore1512 $wpdb->prepare(1513 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET abandoned_cart_info = %s, abandoned_cart_time = %d WHERE user_id = %d AND cart_ignored = %s’,1514 $updated_cart_info,1515 $current_time,1516 $user_id,1517 $cart_ignored1518 )1519 );15201521 $get_abandoned_record = $wpdb->get_results( //phpcs:ignore1522 $wpdb->prepare(1523 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s’,1524 $user_id,1525 01526 )1527 );15281529 if ( count( $get_abandoned_record ) > 0 ) {1530 $abandoned_cart_id = $get_abandoned_record[0]->id;1531 wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite’, $abandoned_cart_id );1532 wcal_common::wcal_add_checkout_link( $abandoned_cart_id );1533 wcal_common::wcal_run_webhook_after_cutoff( $abandoned_cart_id );1534 }1535 }1536 }1537 } else {1538 // start here guest user.1539 $user_id = wcal_common::wcal_get_cart_session( ‘user_id’ );15401541 // GDPR consent.1542 $gdpr_consent = true;1543 $show_gdpr_msg = wcal_common::wcal_get_cart_session( ‘wcal_cart_tracking_refused’ );1544 if ( isset( $show_gdpr_msg ) && ‘yes’ == $show_gdpr_msg ) { // phpcs:ignore1545 $gdpr_consent = false;1546 }15471548 if ( $gdpr_consent ) {1549 $results = $wpdb->get_results( //phpcs:ignore1550 $wpdb->prepare(1551 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s AND recovered_cart = %s AND user_id != %s’,1552 $user_id,1553 0,1554 0,1555 01556 )1557 );1558 $cart = array();15591560 $get_cookie = WC()->session->get_customer_id();15611562 if ( function_exists( ‘WC’ ) ) {1563 $cart[‘cart’] = WC()->session->cart;1564 } else {1565 $cart[‘cart’] = $woocommerce->session->cart;1566 }15671568 $updated_cart_info = wp_json_encode( $cart );15691570 if ( count( $results ) > 0 && ‘{"cart":[]}’ !== $updated_cart_info ) {1571 if ( $compare_time > $results[0]->abandoned_cart_time ) {1572 if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {15731574 $wpdb->query( //phpcs:ignore1575 $wpdb->prepare(1576 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE user_id = %s’,1577 1,1578 $user_id1579 )1580 );1581 $user_type = 'GUEST’;1582 $wpdb->query( //phpcs:ignore1583 $wpdb->prepare(1584 ‘INSERT INTO `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` (user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type, session_id, checkout_link) VALUES (%d, %s, %d, %s, %s, %s, %s)',1585 $user_id,1586 $updated_cart_info,1587 $current_time,1588 $cart_ignored,1589 $user_type,1590 $get_cookie,1591 $results[0]->checkout_link1592 )1593 );1594 update_user_meta( $user_id, '_woocommerce_ac_modified_cart’, md5( ‘yes’ ) );1595 } else {1596 update_user_meta( $user_id, '_woocommerce_ac_modified_cart’, md5( ‘no’ ) );1597 }1598 } else {1599 $wpdb->query( //phpcs:ignore1600 $wpdb->prepare(1601 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET abandoned_cart_info = %s, abandoned_cart_time = %s WHERE user_id = %d AND cart_ignored = %s’,1602 $updated_cart_info,1603 $current_time,1604 $user_id,1605 01606 )1607 );1608 }1609 } else {1610 // Here we capture the guest cart from the cart page @since 3.5.1611 if ( ‘on’ === $track_guest_user_cart_from_cart && isset( $get_cookie ) && ‘’ !== $get_cookie ) {1612 $results = $wpdb->get_results( //phpcs:ignore1613 $wpdb->prepare(1614 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE session_id LIKE %s AND cart_ignored = %s AND recovered_cart = %s’,1615 $get_cookie,1616 0,1617 01618 )1619 );1620 if ( 0 === count( $results ) ) {1621 $cart_info = $updated_cart_info;1622 $blank_cart_info = '[]';1623 if ( $blank_cart_info !== $cart_info && ‘{"cart":[]}’ !== $cart_info ) {1624 $wpdb->query( //phpcs:ignore1625 $wpdb->prepare(1626 ‘INSERT INTO `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` ( abandoned_cart_info , abandoned_cart_time , cart_ignored , recovered_cart, user_type, session_id ) VALUES ( %s, %s, %s, %s, %s, %s )',1627 $cart_info,1628 $current_time,1629 0,1630 0,1631 'GUEST’,1632 $get_cookie1633 )1634 );1635 $abandoned_cart_id = $wpdb->insert_id;1636 }1637 } elseif ( $compare_time > $results[0]->abandoned_cart_time ) {1638 $blank_cart_info = '[]';1639 if ( $blank_cart_info !== $updated_cart_info && ‘{"cart":[]}’ !== $updated_cart_info ) {1640 if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {1641 $wpdb->query( // phpcs:ignore1642 $wpdb->prepare(1643 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE session_id = %s’,1644 1,1645 $get_cookie1646 )1647 );1648 $wpdb->query( //phpcs:ignore1649 $wpdb->prepare(1650 ‘INSERT INTO `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` ( abandoned_cart_info, abandoned_cart_time, cart_ignored, recovered_cart, user_type, session_id ) VALUES ( %s, %s, %s, %s, %s, %s )',1651 $updated_cart_info,1652 $current_time,1653 0,1654 0,1655 'GUEST’,1656 $get_cookie1657 )1658 );1659 $abandoned_cart_id = $wpdb->insert_id;1660 }1661 }1662 } else {1663 $blank_cart_info = '[]';1664 if ( $blank_cart_info !== $updated_cart_info && ‘{"cart":[]}’ !== $updated_cart_info ) {1665 if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {1666 $wpdb->query( //phpcs:ignore1667 $wpdb->prepare(1668 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET abandoned_cart_info = %s, abandoned_cart_time = %s WHERE session_id = %s AND cart_ignored = %s’,1669 $updated_cart_info,1670 $current_time,1671 $get_cookie,1672 01673 )1674 );1675 }1676 }1677 }1678 if ( isset( $abandoned_cart_id ) ) {1679 // add the abandoned id in the session.1680 wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite’, $abandoned_cart_id );1681 }1682 }1683 }1684 }1685 }1686 }16871688 /**1689 * Detect Crawlers1690 *1691 * @param boolean $ignore - Ignore.1692 * @return boolean $ignore - Ignore.1693 */1694 public function wcal_detect_crawlers( $ignore ) {1695 $user_agent = isset( $_SERVER[‘HTTP_USER_AGENT’] ) ? sanitize_text_field( wp_unslash( $_SERVER[‘HTTP_USER_AGENT’] ) ) : '’;16961697 if ( ‘’ === $user_agent ) {1698 return $ignore;1699 }17001701 // Current list of bots being blocked:1702 // 1. Googlebot, BingBot, DuckDuckBot, YandexBot, Exabot.1703 // 2. cURL.1704 // 3. wget.1705 // 4. Yahoo/Slurp.1706 // 5. Baiduspider.1707 // 6. Sogou.1708 // 7. Alexa.1709 $bot_agents = array(1710 'curl’,1711 'wget’,1712 'bot’,1713 'bots’,1714 'slurp’,1715 'baiduspider’,1716 'sogou’,1717 'ia_archiver’,1718 );17191720 foreach ( $bot_agents as $url ) {1721 if ( false !== stripos( $user_agent, $url ) ) {1722 return true;1723 }1724 }17251726 return $ignore;1727 }17281729 /**1730 * It will unsubscribe the abandoned cart, so user will not recieve further abandoned cart emails.1731 *1732 * @hook template_include1733 * @param string $args Arguments.1734 * @return string $args Arguments.1735 * @globals mixed $wpdb1736 * @since 2.91737 */1738 public function wcal_email_unsubscribe( $args ) {1739 global $wpdb;17401741 if ( isset( $_GET[‘wcal_track_unsubscribe’] ) && ‘wcal_unsubscribe’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_track_unsubscribe’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification1742 $encoded_email_id = isset( $_GET[‘validate’] ) ? rawurldecode( sanitize_text_field( wp_unslash( $_GET[‘validate’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification1743 $validate_email_id_string = str_replace( ' ', '+’, $encoded_email_id );1744 $validate_email_address_string = '’;1745 $validate_email_id_decode = 0;1746 if ( isset( $_GET[‘user_email’] ) && ‘’ !== $_GET[‘user_email’] ) { // phpcs:ignore1747 $sent_email = sanitize_text_field( wp_unslash( $_GET[‘user_email’] ) ); // phpcs:ignore1748 $crypt_key = $wpdb->get_var( // phpcs:ignore1749 $wpdb->prepare(1750 ‘SELECT encrypt_key FROM `’ . $wpdb->prefix . 'ac_sent_history_lite` WHERE sent_email_id = %s ORDER BY id DESC’,1751 $sent_email1752 )1753 );1754 } else {1755 $crypt_key = get_option( ‘wcal_security_key’ );1756 }1757 $validate_email_id_decode = Wcal_Aes_Ctr::decrypt( $validate_email_id_string, $crypt_key, 256 );1758 if ( isset( $_GET[‘track_email_id’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification1759 $encoded_email_address = rawurldecode( sanitize_text_field( wp_unslash( $_GET[‘track_email_id’] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification1760 $validate_email_address_string = str_replace( ' ', '+’, $encoded_email_address );1761 }17621763 $results_sent = $wpdb->get_results( //phpcs:ignore1764 $wpdb->prepare(1765 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_sent_history_lite` WHERE id = %d ',1766 $validate_email_id_decode1767 )1768 );1769 $email_address = '’;1770 if ( isset( $results_sent[0] ) ) {1771 $email_address = $results_sent[0]->sent_email_id;1772 }1773 if ( hash( 'sha256’, $email_address ) === $validate_email_address_string && ‘’ !== $email_address ) {1774 $email_sent_id = $validate_email_id_decode;1775 $get_ac_id_results = $wpdb->get_results( //phpcs:ignore1776 $wpdb->prepare(1777 ‘SELECT abandoned_order_id FROM `’ . $wpdb->prefix . 'ac_sent_history_lite` WHERE id = %d’,1778 $email_sent_id1779 )1780 );1781 $user_id = 0;1782 if ( isset( $get_ac_id_results[0] ) ) {1783 $get_user_results = $wpdb->get_results( //phpcs:ignore1784 $wpdb->prepare(1785 ‘SELECT user_id FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE id = %d’,1786 $get_ac_id_results[0]->abandoned_order_id1787 )1788 );1789 }1790 if ( isset( $get_user_results[0] ) ) {1791 $user_id = $get_user_results[0]->user_id;1792 }17931794 $wpdb->query( //phpcs:ignore1795 $wpdb->prepare(1796 ‘UPDATE `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET unsubscribe_link = %s WHERE user_id= %d AND cart_ignored = %s’,1797 1,1798 $user_id,1799 01800 )1801 );1802 echo esc_html( ‘Unsubscribed Successfully’ );1803 sleep( 2 );1804 $url = apply_filters( 'wcal_unsubscribe_redirect’, get_option( ‘home’ ) );1805 ?>1806 <script>1807 location.href = “<?php echo esc_url( $url ); ?>";1808 </script>1809 <?php1810 }1811 } else {1812 return $args;1813 }1814 }18151816 /**1817 * It will track the URL of cart link from email, and it will populate the logged-in and guest users cart.1818 *1819 * @hook template_include1820 * @param string $template - Template name.1821 * @return string $template - Template name.1822 * @globals mixed $wpdb1823 * @globals mixed $woocommerce1824 * @since 1.01825 */1826 public function wcal_email_track_links( $template ) {1827 global $woocommerce;18281829 $track_link = isset( $_GET[‘wcal_action’] ) ? sanitize_text_field( wp_unslash( $_GET[‘wcal_action’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification18301831 if ( ‘track_links’ === $track_link || ‘checkout_link’ === $track_link ) {1832 if ( ‘’ === session_id() ) {1833 // session has not started.1834 session_start();1835 }1836 global $wpdb;1837 $validate_server_string = isset( $_GET [‘validate’] ) ? rawurldecode( wp_unslash( $_GET [‘validate’] ) ) : '’; // phpcs:ignore1838 $validate_server_string = str_replace( ' ', '+’, $validate_server_string );1839 $validate_encoded_string = $validate_server_string;1840 if ( isset( $_GET[‘user_email’] ) && ‘’ !== $_GET[‘user_email’] ) { // phpcs:ignore1841 $sent_email = sanitize_text_field( wp_unslash( $_GET[‘user_email’] ) ); // phpcs:ignore1842 $crypt_key = $wpdb->get_var( // phpcs:ignore1843 $wpdb->prepare(1844 ‘SELECT encrypt_key FROM `’ . $wpdb->prefix . 'ac_sent_history_lite` WHERE sent_email_id = %s ORDER BY id DESC’,1845 $sent_email1846 )1847 );1848 } else {1849 $crypt_key = get_option( ‘wcal_security_key’ );1850 }1851 $link_decode = Wcal_Aes_Ctr::decrypt( $validate_encoded_string, $crypt_key, 256 );1852 $sent_email_id_pos = strpos( $link_decode, ‘&’ );1853 $email_sent_id = substr( $link_decode, 0, $sent_email_id_pos );18541855 if ( isset( $_GET[‘c’] ) ) { // phpcs:ignore 1856 $decrypt_coupon_code = rawurldecode( sanitize_text_field( wp_unslash( $_GET[‘c’] ) ) ); //phpcs:ignore1857 $decrypt_coupon_code = str_replace( ' ', '+’, $decrypt_coupon_code );1858 $decode_coupon_code = Wcal_Aes_Ctr::decrypt( $decrypt_coupon_code, $crypt_key, 256 );18591860 wcal_common::wcal_set_cart_session( 'wcal_c’, $decode_coupon_code ); // we need to set in session coz we directly apply coupon.1861 set_transient( 'wcal_c’, $decode_coupon_code, 5 );1862 } else {1863 $decode_coupon_code = '’;1864 }18651866 if ( ‘track_links’ === $track_link ) {1867 $email_sent_id = 0;1868 $sent_email_id_pos = strpos( $link_decode, ‘&’ );1869 $email_sent_id = substr( $link_decode, 0, $sent_email_id_pos );18701871 wcal_common::wcal_set_cart_session( 'email_sent_id’, $email_sent_id );1872 set_transient( 'wcal_email_sent_id’, $email_sent_id, 5 );18731874 $get_ac_id_results = $wpdb->get_results( // phpcs:ignore1875 $wpdb->prepare(1876 ‘SELECT abandoned_order_id FROM `’ . $wpdb->prefix . 'ac_sent_history_lite` WHERE id = %d’,1877 $email_sent_id1878 )1879 );1880 $abandoned_id = $get_ac_id_results[0]->abandoned_order_id;1881 } elseif ( ‘checkout_link’ === $track_link ) {1882 $abandoned_id = 0;1883 $abandoned_id_pos = strpos( $link_decode, ‘&’ );1884 $abandoned_id = substr( $link_decode, 0, $abandoned_id_pos );1885 wcal_common::wcal_set_cart_session( 'wcal_recovered_cart’, true );1886 }18871888 $url_pos = strpos( $link_decode, ‘=’ );1889 ++$url_pos;1890 $url = substr( $link_decode, $url_pos );18911892 wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite’, $abandoned_id );1893 set_transient( 'wcal_abandoned_id’, $abandoned_id, 5 );18941895 $get_user_results = array();1896 if ( $abandoned_id > 0 ) {1897 $get_user_results = $wpdb->get_results( //phpcs:ignore1898 $wpdb->prepare(1899 ‘SELECT user_id FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE id = %d’,1900 $abandoned_id1901 )1902 );1903 }1904 $user_id = isset( $get_user_results ) && count( $get_user_results ) > 0 ? (int) $get_user_results[0]->user_id : 0;19051906 if ( 0 === $user_id ) {1907 echo esc_html( ‘Link expired’ );1908 exit;1909 }1910 $user = wp_set_current_user( $user_id );1911 if ( $user_id >= ‘63000000’ ) {1912 $results_guest = $wpdb->get_results( //phpcs:ignore1913 $wpdb->prepare(1914 ‘SELECT * from `’ . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE id = %d’,1915 $user_id1916 )1917 );19181919 $results = $wpdb->get_results( //phpcs:ignore1920 $wpdb->prepare(1921 ‘SELECT recovered_cart FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d’,1922 $user_id1923 )1924 );1925 if ( $results_guest && ‘0’ == $results[0]->recovered_cart ) { // phpcs:ignore1926 wcal_common::wcal_set_cart_session( 'guest_first_name’, $results_guest[0]->billing_first_name );1927 wcal_common::wcal_set_cart_session( 'guest_last_name’, $results_guest[0]->billing_last_name );1928 wcal_common::wcal_set_cart_session( 'guest_email’, $results_guest[0]->email_id );1929 wcal_common::wcal_set_cart_session( 'user_id’, $user_id );1930 } else {1931 if ( version_compare( $woocommerce->version, '3.0.0’, ‘>=’ ) ) {1932 wp_safe_redirect( get_permalink( wc_get_page_id( ‘shop’ ) ) );1933 exit;1934 } else {1935 wp_safe_redirect( get_permalink( woocommerce_get_page_id( ‘shop’ ) ) );1936 exit;1937 }1938 }1939 }19401941 if ( $user_id < ‘63000000’ ) {1942 $user_login = $user->data->user_login;1943 wp_set_auth_cookie( $user_id );1944 $my_temp = wc_load_persistent_cart( $user_login, $user );1945 do_action( 'wp_login’, $user_login, $user );1946 if ( isset( $sign_in ) && is_wp_error( $sign_in ) ) {1947 echo esc_html( $sign_in->get_error_message() );1948 exit;1949 }1950 } else {1951 $my_temp = $this->wcal_load_guest_persistent_cart( $user_id );1952 }19531954 if ( $email_sent_id > 0 && is_numeric( $email_sent_id ) ) {1955 wp_safe_redirect( $url );1956 exit;1957 }1958 } else {1959 return $template;1960 }1961 }19621963 /**1964 * When customer clicks on the abandoned cart link and that cart is for the the guest users the it will load the guest1965 * user’s cart detail.1966 *1967 * @globals mixed $woocommerce1968 * @since 1.01969 */1970 public function wcal_load_guest_persistent_cart() {1971 if ( wcal_common::wcal_get_cart_session( ‘user_id’ ) != ‘’ ) { // phpcs:ignore1972 global $woocommerce;1973 $saved_cart = json_decode( get_user_meta( wcal_common::wcal_get_cart_session( ‘user_id’ ), '_woocommerce_persistent_cart’, true ), true );1974 $c = array();19751976 $cart_contents_total = 0;1977 $cart_contents_weight = 0;1978 $cart_contents_count = 0;1979 $cart_contents_tax = 0;1980 $total = 0;1981 $subtotal = 0;1982 $subtotal_ex_tax = 0;1983 $tax_total = 0;1984 if ( count( $saved_cart ) > 0 ) {1985 foreach ( $saved_cart as $key => $value ) {1986 if ( is_array( $value ) && count( $value ) > 0 ) {1987 foreach ( $value as $a => $b ) {1988 $c[‘product_id’] = $b[‘product_id’];1989 $c[‘variation_id’] = $b[‘variation_id’];1990 $c[‘variation’] = $b[‘variation’];1991 $c[‘quantity’] = $b[‘quantity’];1992 $product_id = $b[‘product_id’];1993 $c[‘data’] = wc_get_product( $product_id );1994 $c[‘line_total’] = $b[‘line_total’];1995 $c[‘line_tax’] = $cart_contents_tax;1996 $c[‘line_subtotal’] = $b[‘line_subtotal’];1997 $c[‘line_subtotal_tax’] = $cart_contents_tax;1998 $value_new[ $a ] = $c;1999 $cart_contents_total = $b[‘line_subtotal’] + $cart_contents_total;2000 $cart_contents_count = $cart_contents_count + $b[‘quantity’];2001 $total = $total + $b[‘line_total’];2002 $subtotal = $subtotal + $b[‘line_subtotal’];2003 $subtotal_ex_tax = $subtotal_ex_tax + $b[‘line_subtotal’];2004 }2005 $saved_cart_data[ $key ] = $value_new;2006 $woocommerce_cart_hash = $a;2007 }2008 }2009 }20102011 if ( $saved_cart ) {2012 if ( empty( $woocommerce->session->cart ) || ! is_array( $woocommerce->session->cart ) || 0 === count( $woocommerce->session->cart ) ) {2013 $woocommerce->session->cart = $saved_cart[‘cart’];2014 $woocommerce->session->cart_contents_total = $cart_contents_total;2015 $woocommerce->session->cart_contents_weight = $cart_contents_weight;2016 $woocommerce->session->cart_contents_count = $cart_contents_count;2017 $woocommerce->session->cart_contents_tax = $cart_contents_tax;2018 $woocommerce->session->total = $total;2019 $woocommerce->session->subtotal = $subtotal;2020 $woocommerce->session->subtotal_ex_tax = $subtotal_ex_tax;2021 $woocommerce->session->tax_total = $tax_total;2022 $woocommerce->session->shipping_taxes = array();2023 $woocommerce->session->taxes = array();2024 $woocommerce->session->ac_customer = array();2025 $woocommerce->cart->cart_contents = $saved_cart_data[‘cart’];2026 $woocommerce->cart->cart_contents_total = $cart_contents_total;2027 $woocommerce->cart->cart_contents_weight = $cart_contents_weight;2028 $woocommerce->cart->cart_contents_count = $cart_contents_count;2029 $woocommerce->cart->cart_contents_tax = $cart_contents_tax;2030 $woocommerce->cart->total = $total;2031 $woocommerce->cart->subtotal = $subtotal;2032 $woocommerce->cart->subtotal_ex_tax = $subtotal_ex_tax;2033 $woocommerce->cart->tax_total = $tax_total;2034 }2035 }2036 }2037 }20382039 /**2040 * It will compare only guest users cart while capturing the cart.2041 *2042 * @param json_encode $new_cart New abandoned cart details.2043 * @param json_encode $last_abandoned_cart Old abandoned cart details.2044 * @return boolean true | false.2045 * @since 1.02046 */2047 public function wcal_compare_only_guest_carts( $new_cart, $last_abandoned_cart ) {2048 $current_woo_cart = array();2049 $current_woo_cart = json_decode( stripslashes( $new_cart ), true );2050 $abandoned_cart_arr = array();2051 $abandoned_cart_arr = json_decode( $last_abandoned_cart, true );2052 $temp_variable = '’;2053 if ( isset( $current_woo_cart[‘cart’] ) && isset( $abandoned_cart_arr[‘cart’] ) ) {2054 if ( count( $current_woo_cart[‘cart’] ) >= count( $abandoned_cart_arr[‘cart’] ) ) { // phpcs:ignore2055 // do nothing.2056 } else {2057 $temp_variable = $current_woo_cart;2058 $current_woo_cart = $abandoned_cart_arr;2059 $abandoned_cart_arr = $temp_variable;2060 }2061 if ( is_array( $current_woo_cart ) || is_object( $current_woo_cart ) ) {2062 foreach ( $current_woo_cart as $key => $value ) {2063 foreach ( $value as $item_key => $item_value ) {2064 $current_cart_product_id = $item_value[‘product_id’];2065 $current_cart_variation_id = $item_value[‘variation_id’];2066 $current_cart_quantity = $item_value[‘quantity’];20672068 if ( isset( $abandoned_cart_arr[ $key ][ $item_key ][‘product_id’] ) ) {2069 $abandoned_cart_product_id = $abandoned_cart_arr[ $key ][ $item_key ][‘product_id’];2070 } else {2071 $abandoned_cart_product_id = '’;2072 }2073 if ( isset( $abandoned_cart_arr[ $key ][ $item_key ][‘variation_id’] ) ) {2074 $abandoned_cart_variation_id = $abandoned_cart_arr[ $key ][ $item_key ][‘variation_id’];2075 } else {2076 $abandoned_cart_variation_id = '’;2077 }2078 if ( isset( $abandoned_cart_arr[ $key ][ $item_key ][‘quantity’] ) ) {2079 $abandoned_cart_quantity = $abandoned_cart_arr[ $key ][ $item_key ][‘quantity’];2080 } else {2081 $abandoned_cart_quantity = '’;2082 }2083 if ( ( $current_cart_product_id != $abandoned_cart_product_id ) || ( $current_cart_variation_id != $abandoned_cart_variation_id ) || ( $current_cart_quantity != $abandoned_cart_quantity ) ) { // phpcs:ignore2084 return false;2085 }2086 }2087 }2088 }2089 }2090 return true;2091 }20922093 /**2094 * It will compare only loggedin users cart while capturing the cart.2095 *2096 * @param int | string $user_id User id.2097 * @param json_encode $last_abandoned_cart Old abandoned cart details.2098 * @return boolean true | false.2099 * @since 1.02100 */2101 public function wcal_compare_carts( $user_id, $last_abandoned_cart ) {2102 global $woocommerce;2103 $current_woo_cart = array();2104 $abandoned_cart_arr = array();2105 $wcal_woocommerce_persistent_cart = version_compare( $woocommerce->version, '3.1.0’, ‘>=’ ) ? ‘_woocommerce_persistent_cart_’ . get_current_blog_id() : '_woocommerce_persistent_cart’;2106 $current_woo_cart = get_user_meta( $user_id, $wcal_woocommerce_persistent_cart, true );2107 $abandoned_cart_arr = json_decode( $last_abandoned_cart, true );2108 $temp_variable = '’;2109 if ( isset( $current_woo_cart[‘cart’] ) && isset( $abandoned_cart_arr[‘cart’] ) ) {2110 if ( count( $current_woo_cart[‘cart’] ) >= count( $abandoned_cart_arr[‘cart’] ) ) { // phpcs:ignore2111 // do nothing.2112 } else {2113 $temp_variable = $current_woo_cart;2114 $current_woo_cart = $abandoned_cart_arr;2115 $abandoned_cart_arr = $temp_variable;2116 }2117 if ( is_array( $current_woo_cart ) && is_array( $abandoned_cart_arr ) ) {2118 foreach ( $current_woo_cart as $key => $value ) {21192120 foreach ( $value as $item_key => $item_value ) {2121 $current_cart_product_id = $item_value[‘product_id’];2122 $current_cart_variation_id = $item_value[‘variation_id’];2123 $current_cart_quantity = $item_value[‘quantity’];21242125 if ( isset( $abandoned_cart_arr[ $key ][ $item_key ][‘product_id’] ) ) {2126 $abandoned_cart_product_id = $abandoned_cart_arr[ $key ][ $item_key ][‘product_id’];2127 } else {2128 $abandoned_cart_product_id = '’;2129 }2130 if ( isset( $abandoned_cart_arr[ $key ][ $item_key ][‘variation_id’] ) ) {2131 $abandoned_cart_variation_id = $abandoned_cart_arr[ $key ][ $item_key ][‘variation_id’];2132 } else {2133 $abandoned_cart_variation_id = '’;2134 }2135 if ( isset( $abandoned_cart_arr[ $key ][ $item_key ][‘quantity’] ) ) {2136 $abandoned_cart_quantity = $abandoned_cart_arr[ $key ][ $item_key ][‘quantity’];2137 } else {2138 $abandoned_cart_quantity = '’;2139 }2140 if ( ( $current_cart_product_id != $abandoned_cart_product_id ) || ( $current_cart_variation_id != $abandoned_cart_variation_id ) || ( $current_cart_quantity != $abandoned_cart_quantity ) ) { // phpcs:ignore2141 return false;2142 }2143 }2144 }2145 }2146 }2147 return true;2148 }21492150 /**2151 * It will add the wp editor for email body on the email edit page.2152 *2153 * @hook admin_init2154 * @since 2.62155 */2156 public function wcal_action_admin_init() {21572158 // only hook up these filters if we’re in the admin panel and the current user has permission.2159 // to edit posts and pages.2160 if ( ! isset( $_GET[‘page’] ) || ‘woocommerce_ac_page’ !== sanitize_text_field( wp_unslash( $_GET[‘page’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2161 return;2162 }2163 if ( ! current_user_can( ‘edit_posts’ ) && ! current_user_can( ‘edit_pages’ ) ) {2164 return;2165 }2166 if ( ‘true’ === get_user_option( ‘rich_editing’ ) ) {2167 remove_filter( 'the_excerpt’, ‘wpautop’ );2168 add_filter( 'tiny_mce_before_init’, array( &$this, ‘wcal_format_tiny_mce’ ) );2169 add_filter( 'mce_buttons’, array( &$this, ‘wcal_filter_mce_button’ ) );2170 add_filter( 'mce_external_plugins’, array( &$this, ‘wcal_filter_mce_plugin’ ) );2171 }2172 }21732174 /**2175 * It will create a button on the WordPress editor.2176 *2177 * @hook mce_buttons2178 * @param array $buttons - List of buttons.2179 * @return array $buttons - List of buttons.2180 * @since 2.62181 */2182 public function wcal_filter_mce_button( $buttons ) {2183 // add a separation before our button, here our button’s id is abandoncart.2184 array_push( $buttons, 'abandoncart’, ‘|’ );2185 return $buttons;2186 }21872188 /**2189 * It will add the list for the added extra button.2190 *2191 * @hook mce_external_plugins2192 * @param array $plugins - Plugins.2193 * @return array $plugins - Plugins.2194 * @since 2.62195 */2196 public function wcal_filter_mce_plugin( $plugins ) {2197 // this plugin file will work the magic of our button.2198 $plugins[‘abandoncart’] = plugin_dir_url( __FILE__ ) . 'assets/js/abandoncart_plugin_button.js’;2199 return $plugins;2200 }22012202 /**2203 * It will add the tabs on the Abandoned cart page.2204 *2205 * @since 1.02206 */2207 public function wcal_display_tabs() {22082209 $action = '’;2210 $active_listcart = '’;2211 $active_emailtemplates = '’;2212 $active_settings = '’;2213 $active_stats = '’;2214 $active_dash = '’;22152216 if ( isset( $_GET[‘action’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification2217 $action = sanitize_text_field( wp_unslash( $_GET[‘action’] ) ); // phpcs:ignore WordPress.Security.NonceVerification2218 } else {2219 $action = '’;2220 $action = apply_filters( 'wcal_default_tab’, $action );2221 }22222223 switch ( $action ) {2224 case '’:2225 case 'dashboard’:2226 $active_dash = 'nav-tab-active’;2227 break;2228 case 'listcart’:2229 case 'orderdetails’:2230 $active_listcart = 'nav-tab-active’;2231 break;2232 case 'emailtemplates’:2233 $active_emailtemplates = 'nav-tab-active’;2234 break;2235 case 'emailsettings’:2236 $active_settings = 'nav-tab-active’;2237 break;2238 case 'stats’:2239 $active_stats = 'nav-tab-active’;2240 break;2241 case 'report’:2242 $active_report = 'nav-tab-active’;2243 break;2244 }22452246 ?>2247 <div style="background-image: url('<?php echo esc_url( plugins_url( ‘/assets/images/ac_tab_icon.png’, __FILE__ ) ); ?>’) !important;” class="icon32"><br>2248 </div>2249 <h2 class="nav-tab-wrapper woo-nav-tab-wrapper">2250 <a href="admin.php?page=woocommerce_ac_page&action=dashboard" class="nav-tab 2251 <?php2252 if ( isset( $active_dash ) ) {2253 echo esc_attr( $active_dash );2254 }2255 ?>2256 “> <?php esc_html_e( 'Dashboard’, ‘woocommerce-abandoned-cart’ ); ?> </a>2257 <a href="admin.php?page=woocommerce_ac_page&action=listcart” class="nav-tab 2258 <?php2259 if ( isset( $active_listcart ) ) {2260 echo esc_attr( $active_listcart );2261 }2262 ?>2263 “> <?php esc_html_e( 'Abandoned Orders’, ‘woocommerce-abandoned-cart’ ); ?> </a>2264 <a href="admin.php?page=woocommerce_ac_page&action=emailtemplates” class="nav-tab 2265 <?php2266 if ( isset( $active_emailtemplates ) ) {2267 echo esc_attr( $active_emailtemplates );2268 }2269 ?>2270 “> <?php esc_html_e( 'Email Templates’, ‘woocommerce-abandoned-cart’ ); ?> </a>2271 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings” class="nav-tab 2272 <?php2273 if ( isset( $active_settings ) ) {2274 echo esc_attr( $active_settings );2275 }2276 ?>2277 “> <?php esc_html_e( 'Settings’, ‘woocommerce-abandoned-cart’ ); ?> </a>2278 <a href="admin.php?page=woocommerce_ac_page&action=stats” class="nav-tab 2279 <?php2280 if ( isset( $active_stats ) ) {2281 echo esc_attr( $active_stats );2282 }2283 ?>2284 “> <?php esc_html_e( 'Recovered Orders’, ‘woocommerce-abandoned-cart’ ); ?> </a>2285 <a href="admin.php?page=woocommerce_ac_page&action=report” class="nav-tab 2286 <?php2287 if ( isset( $active_report ) ) {2288 echo esc_attr( $active_report );2289 }2290 ?>2291 “> <?php esc_html_e( 'Product Report’, ‘woocommerce-abandoned-cart’ ); ?> </a>22922293 <?php do_action( ‘wcal_add_settings_tab’ ); ?>2294 </h2>2295 <?php2296 }22972298 /**2299 * It will add the scripts needed for the plugin.2300 *2301 * @hook admin_enqueue_scripts2302 * @param string $hook Name of hook.2303 * @since 1.02304 */2305 public function wcal_enqueue_scripts_js( $hook ) {2306 global $pagenow, $woocommerce;2307 $page = isset( $_GET[‘page’] ) ? sanitize_text_field( wp_unslash( $_GET[‘page’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2308 $action = isset( $_GET[‘action’] ) ? sanitize_text_field( wp_unslash( $_GET[‘action’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification23092310 if ( ‘’ === $page || ‘woocommerce_ac_page’ !== $page ) {2311 return;2312 } else {2313 wp_enqueue_script( ‘jquery’ );2314 wp_enqueue_script( ‘jquery-ui-core’ );23152316 wp_enqueue_script( ‘jquery-ui-datepicker’ );2317 wp_enqueue_script(2318 'jquery-tip’,2319 plugins_url( '/assets/js/jquery.tipTip.minified.js’, __FILE__ ),2320 '’,2321 WCAL_PLUGIN_VERSION,2322 false2323 );2324 $mode = isset( $_GET[‘mode’] ) ? sanitize_text_field( wp_unslash( $_GET[‘mode’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2325 $wcal_section = isset( $_GET[‘wcal_section’] ) ? sanitize_text_field( wp_unslash( $_GET[‘wcal_section’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2326 if ( ( ‘emailtemplates’ === $action && ( ‘addnewtemplate’ === $mode || ‘edittemplate’ === $mode ) ) || ( ‘emailsettings’ === $action && ‘wcap_atc_settings’ === $wcal_section ) ) {2327 wp_register_script( 'woocommerce_admin’, WC()->plugin_url() . '/assets/js/admin/woocommerce_admin.min.js’, array( 'jquery’, ‘jquery-tiptip’ ), WCAL_PLUGIN_VERSION, false );2328 wp_enqueue_script( ‘woocommerce_admin’ );2329 $locale = localeconv();2330 $decimal = isset( $locale[‘decimal_point’] ) ? $locale[‘decimal_point’] : '.’;2331 $params = array(2332 // translators: %s: decimal.2333 ‘i18n_decimal_error’ => sprintf( __( 'Please enter in decimal (%s) format without thousand separators.’, ‘woocommerce’ ), $decimal ),2334 // translators: %s: price decimal separator.2335 ‘i18n_mon_decimal_error’ => sprintf( __( 'Please enter in monetary decimal (%s) format without thousand separators and currency symbols.’, ‘woocommerce’ ), wc_get_price_decimal_separator() ),2336 ‘i18n_country_iso_error’ => __( 'Please enter in country code with two capital letters.’, ‘woocommerce’ ),2337 ‘i18_sale_less_than_regular_error’ => __( 'Please enter in a value less than the regular price.’, ‘woocommerce’ ),2338 ‘decimal_point’ => $decimal,2339 ‘mon_decimal_point’ => wc_get_price_decimal_separator(),2340 ‘strings’ => array(2341 ‘import_products’ => __( 'Import’, ‘woocommerce’ ),2342 ‘export_products’ => __( 'Export’, ‘woocommerce’ ),2343 ),2344 ‘urls’ => array(2345 ‘import_products’ => esc_url_raw( admin_url( ‘edit.php?post_type=product&page=product_importer’ ) ),2346 ‘export_products’ => esc_url_raw( admin_url( ‘edit.php?post_type=product&page=product_exporter’ ) ),2347 ),2348 );23492350 // If we dont localize this script then from the WooCommerce check it will not run the javascript further and tooltip wont show any data.2351 // Also, we need above all parameters for the WooCoomerce js file. So we have taken it from the WooCommerce. @since: 5.1.2.2352 wp_localize_script( 'woocommerce_admin’, 'woocommerce_admin’, $params );2353 }2354 ?>2355 <script type="text/javascript” >2356 function wcal_activate_email_template( template_id, active_state ) {2357 location.href = 'admin.php?page=woocommerce_ac_page&action=emailtemplates&mode=activate_template&id=’+template_id+’&active_state=’+active_state ;2358 }2359 </script>2360 <?php2361 $js_src = includes_url( ‘js/tinymce/’ ) . 'tinymce.min.js’;2362 wp_enqueue_script( 'tinyMce_ac’, $js_src, '’, WCAL_PLUGIN_VERSION, false );2363 wp_enqueue_script(2364 'ac_email_variables’,2365 plugins_url( '/assets/js/abandoncart_plugin_button.js’, __FILE__ ),2366 '’,2367 WCAL_PLUGIN_VERSION,2368 false2369 );2370 wp_enqueue_script(2371 'wcal_activate_template’,2372 plugins_url( '/assets/js/wcal_template_activate.js’, __FILE__ ),2373 '’,2374 WCAL_PLUGIN_VERSION,2375 false2376 );23772378 // Needed only on the dashboard page.2379 if ( ‘woocommerce_ac_page’ === $page && ( ‘’ === $action || ‘dashboard’ === $action ) ) {2380 wp_register_script( 'jquery-ui-datepicker’, WC()->plugin_url() . '/assets/js/admin/ui-datepicker.js’, '’, WCAL_PLUGIN_VERSION, false );2381 wp_enqueue_script( ‘jquery-ui-datepicker’ );23822383 wp_enqueue_script(2384 'bootstrap_js’,2385 plugins_url( '/assets/js/admin/bootstrap.min.js’, __FILE__ ),2386 '’,2387 WCAL_PLUGIN_VERSION,2388 false2389 );23902391 wp_enqueue_script(2392 'd3_js’,2393 WCAL_PLUGIN_URL . '/assets/js/admin/d3.v3.min.js’,2394 '’,2395 WCAL_PLUGIN_VERSION,2396 false2397 );23982399 wp_register_script(2400 'reports_js’,2401 plugins_url( '/assets/js/admin/wcal_adv_dashboard.min.js’, __FILE__ ),2402 '’,2403 WCAL_PLUGIN_VERSION,2404 false2405 );2406 }2407 // Needed only on the abandoned orders page.2408 wp_enqueue_script(2409 'wcal_abandoned_cart_details’,2410 plugins_url( '/assets/js/admin/wcal_abandoned_cart_detail_modal.min.js’, __FILE__ ),2411 '’,2412 WCAL_PLUGIN_VERSION,2413 false2414 );24152416 wp_enqueue_script(2417 'wcal_admin_notices’,2418 plugins_url( '/assets/js/admin/wcal_ts_dismiss_notice.js’, __FILE__ ),2419 '’,2420 WCAL_PLUGIN_VERSION,2421 false2422 );2423 wp_localize_script(2424 'wcal_admin_notices’,2425 'wcal_dismiss_params’,2426 array(2427 ‘ajax_url’ => admin_url( ‘admin-ajax.php’ ),2428 ‘ajax_nonce’ => wp_create_nonce( ‘delete_expired_used_coupon_code’ ),2429 )2430 );2431 wp_register_script( 'enhanced’, plugins_url() . '/woocommerce/assets/js/admin/wc-enhanced-select.js’, array( 'jquery’, ‘select2’ ), WCAL_PLUGIN_VERSION, false );24322433 wp_localize_script(2434 'enhanced’,2435 'wc_enhanced_select_params’,2436 array(2437 ‘i18n_matches_1’ => _x( 'One result is available, press enter to select it.’, 'enhanced select’, ‘woocommerce’ ),2438 ‘i18n_matches_n’ => _x( '%qty% results are available, use up and down arrow keys to navigate.’, 'enhanced select’, ‘woocommerce’ ),2439 ‘i18n_no_matches’ => _x( 'No matches found’, 'enhanced select’, ‘woocommerce’ ),2440 ‘i18n_ajax_error’ => _x( 'Loading failed’, 'enhanced select’, ‘woocommerce’ ),2441 ‘i18n_input_too_short_1’ => _x( 'Please enter 1 or more characters’, 'enhanced select’, ‘woocommerce’ ),2442 ‘i18n_input_too_short_n’ => _x( 'Please enter %qty% or more characters’, 'enhanced select’, ‘woocommerce’ ),2443 ‘i18n_input_too_long_1’ => _x( 'Please delete 1 character’, 'enhanced select’, ‘woocommerce’ ),2444 ‘i18n_input_too_long_n’ => _x( 'Please delete %qty% characters’, 'enhanced select’, ‘woocommerce’ ),2445 ‘i18n_selection_too_long_1’ => _x( 'You can only select 1 item’, 'enhanced select’, ‘woocommerce’ ),2446 ‘i18n_selection_too_long_n’ => _x( 'You can only select %qty% items’, 'enhanced select’, ‘woocommerce’ ),2447 ‘i18n_load_more’ => _x( 'Loading more results…’, 'enhanced select’, ‘woocommerce’ ),2448 ‘i18n_searching’ => _x( 'Searching…’, 'enhanced select’, ‘woocommerce’ ),2449 ‘ajax_url’ => admin_url( ‘admin-ajax.php’ ),2450 ‘search_products_nonce’ => wp_create_nonce( ‘search-products’ ),2451 ‘search_customers_nonce’ => wp_create_nonce( ‘search-customers’ ),2452 )2453 );24542455 wp_enqueue_script( ‘enhanced’ );24562457 wp_register_script( 'selectWoo’, plugins_url() . '/woocommerce/assets/js/selectWoo/selectWoo.full.js’, array( ‘jquery’ ), WCAL_PLUGIN_VERSION, false );2458 wp_enqueue_script( ‘selectWoo’ );24592460 wp_register_script( 'select2’, plugins_url() . '/woocommerce/assets/js/select2/select2.js’, array( 'jquery’, 'jquery-ui-widget’, ‘jquery-ui-core’ ), WCAL_PLUGIN_VERSION, false );2461 wp_enqueue_script( ‘select2’ );24622463 wp_dequeue_script( ‘wc-enhanced-select’ );2464 }2465 }24662467 /**2468 * It will add the parameter to the editor.2469 *2470 * @hook tiny_mce_before_init2471 * @param array $in - Editor params.2472 * @return array $in - Editor params.2473 * @since 2.62474 */2475 public function wcal_format_tiny_mce( $in ) {2476 $in[‘force_root_block’] = false;2477 $in[‘valid_children’] = '+body[style]';2478 $in[‘remove_linebreaks’] = false;2479 $in[‘gecko_spellcheck’] = false;2480 $in[‘keep_styles’] = true;2481 $in[‘accessibility_focus’] = true;2482 $in[‘tabfocus_elements’] = 'major-publishing-actions’;2483 $in[‘media_strict’] = false;2484 $in[‘paste_remove_styles’] = false;2485 $in[‘paste_remove_spans’] = false;2486 $in[‘paste_strip_class_attributes’] = 'none’;2487 $in[‘paste_text_use_dialog’] = true;2488 $in[‘wpeditimage_disable_captions’] = true;2489 $in[‘wpautop’] = false;2490 $in[‘apply_source_formatting’] = true;2491 $in[‘cleanup’] = true;2492 $in[‘convert_newlines_to_brs’] = false;2493 $in[‘fullpage_default_xml_pi’] = false;2494 $in[‘convert_urls’] = false;2495 // Do not remove redundant BR tags.2496 $in[‘remove_redundant_brs’] = false;2497 return $in;2498 }24992500 /**2501 * It will add the necesaary css for the plugin.2502 *2503 * @hook admin_enqueue_scripts2504 * @param string $hook Name of page.2505 * @since 1.02506 */2507 public function wcal_enqueue_scripts_css( $hook ) {25082509 global $pagenow;25102511 $page = isset( $_GET[‘page’] ) ? sanitize_text_field( wp_unslash( $_GET[‘page’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2512 $action = isset( $_GET[‘action’] ) ? sanitize_text_field( wp_unslash( $_GET[‘action’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2513 $section = isset( $_GET[‘wcal_section’] ) ? sanitize_text_field( wp_unslash( $_GET[‘wcal_section’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2514 if ( ‘woocommerce_ac_page’ !== $page ) {2515 return;2516 } elseif ( ‘woocommerce_ac_page’ === $page && ( ‘dashboard’ === $action || ‘’ === $action ) ) {2517 wp_enqueue_style( 'wcal-dashboard-adv’, plugins_url( '/assets/css/admin/wcal_reports_adv.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );25182519 wp_register_style( 'bootstrap_css’, plugins_url( '/assets/css/admin/bootstrap.min.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION, ‘all’ );2520 wp_enqueue_style( ‘bootstrap_css’ );25212522 wp_enqueue_style( 'wcal-font-awesome’, plugins_url( '/assets/css/admin/font-awesome.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );25232524 wp_enqueue_style( 'wcal-font-awesome-min’, plugins_url( '/assets/css/admin/font-awesome.min.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );25252526 wp_enqueue_style( 'jquery-ui’, plugins_url( '/assets/css/admin/jquery-ui.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION, false );2527 wp_enqueue_style( 'woocommerce_admin_styles’, WC()->plugin_url() . '/assets/css/admin.css’, '’, WCAL_PLUGIN_VERSION );2528 wp_enqueue_style( 'jquery-ui-style’, plugins_url( '/assets/css/admin/jquery-ui-smoothness.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );2529 wp_enqueue_style( 'wcal-reports’, plugins_url( '/assets/css/admin/wcal_reports.min.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );25302531 } elseif ( ‘woocommerce_ac_page’ === $page && ‘emailsettings’ === $action && ‘wcap_connectors’ === $section ) {2532 wp_enqueue_style( 'wcap-connectors’, plugins_url( 'assets/css/admin/wcap_integrations_main.min.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );2533 } elseif ( ‘woocommerce_ac_page’ === $page ) {25342535 wp_enqueue_style( 'jquery-ui’, plugins_url( '/assets/css/admin/jquery-ui.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION, false );2536 wp_enqueue_style( 'woocommerce_admin_styles’, WC()->plugin_url() . '/assets/css/admin.css’, '’, WCAL_PLUGIN_VERSION );25372538 wp_enqueue_style( 'jquery-ui-style’, plugins_url( '/assets/css/admin/jquery-ui-smoothness.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );2539 wp_enqueue_style( 'abandoned-orders-list’, plugins_url( '/assets/css/view.abandoned.orders.style.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );2540 wp_enqueue_style( 'wcal_email_template’, plugins_url( '/assets/css/wcal_template_activate.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );2541 wp_enqueue_style( 'wcal_cart_details’, plugins_url( '/assets/css/admin/wcal_abandoned_cart_detail_modal.min.css’, __FILE__ ), '’, WCAL_PLUGIN_VERSION );2542 }2543 }25442545 /**2546 * When we have added the wp list table for the listing then while deleting the record with the bulk action it was showing2547 * the notice. To overcome the wp redirect warning we need to start the ob_start.2548 *2549 * @hook init2550 * @since 2.5.22551 */2552 public function wcal_app_output_buffer() {2553 ob_start();2554 }25552556 /**2557 * Abandon Cart Settings Page. It will show the tabs, notices for the plugin.2558 * It will also update the template records and display the template fields.2559 * It will also show the abandoned cart details page.2560 * It will also show the details of all the tabs.2561 *2562 * @globals mixed $wpdb2563 * @since 1.02564 */2565 public function wcal_menu_page() {25662567 if ( is_user_logged_in() ) {2568 global $wpdb;2569 // Check the user capabilities.2570 if ( ! current_user_can( ‘manage_woocommerce’ ) ) {2571 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.’, ‘woocommerce-abandoned-cart’ ) );2572 }2573 ?>2574 <div class="wrap">2575 <h2><?php esc_html_e( 'WooCommerce - Abandon Cart Lite’, ‘woocommerce-abandoned-cart’ ); ?></h2>2576 <?php25772578 if ( isset( $_GET[‘ac_update’] ) && ‘email_templates’ === sanitize_text_field( wp_unslash( $_GET[‘ac_update’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2579 $status = wcal_common::update_templates_table();25802581 if ( false !== $status ) {2582 wcal_common::show_update_success();2583 } else {2584 wcal_common::show_update_failure();2585 }2586 }25872588 if ( isset( $_GET[‘action’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification2589 $action = sanitize_text_field( wp_unslash( $_GET[‘action’] ) ); // phpcs:ignore WordPress.Security.NonceVerification2590 } else {2591 $action = '’;2592 $action = apply_filters( 'wcal_default_tab’, $action );2593 }2594 $mode = isset( $_GET[‘mode’] ) ? sanitize_text_field( wp_unslash( $_GET[‘mode’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2595 $this->wcal_display_tabs();25962597 do_action( ‘wcal_add_tab_content’ );25982599 // When we delete the item from the below drop down it is registred in action 2.2600 $action_two = isset( $_GET[‘action2’] ) ? sanitize_text_field( wp_unslash( $_GET[‘action2’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification26012602 // Detect when a bulk action is being triggered on abandoned orders page.2603 if ( ‘wcal_delete’ === $action || ‘wcal_delete’ === $action_two ) {2604 $ids = isset( $_GET[‘abandoned_order_id’] ) && is_array( $_GET[‘abandoned_order_id’] ) ? array_map( 'intval’, wp_unslash( $_GET[‘abandoned_order_id’] ) ) : sanitize_text_field( wp_unslash( $_GET[‘abandoned_order_id’] ) ); // phpcs:ignore WordPress.Security.NonceVerification2605 if ( ! is_array( $ids ) ) {2606 $ids = array( $ids );2607 }2608 foreach ( $ids as $id ) {2609 $class = new Wcal_Delete_Handler();2610 $class->wcal_delete_bulk_action_handler_function( $id );2611 }2612 }2613 // Abandoned Orders page - Bulk Action - Delete all registered user carts.2614 if ( ‘wcal_delete_all_registered’ === $action || ‘wcal_delete_all_registered’ === $action_two ) {2615 $class = new Wcal_Delete_Handler();2616 $class->wcal_bulk_action_delete_registered_carts_handler();2617 }2618 // Abandoned Orders page - Bulk Action - Delete all guest carts.2619 if ( ‘wcal_delete_all_guest’ === $action || ‘wcal_delete_all_guest’ === $action_two ) {2620 $class = new Wcal_Delete_Handler();2621 $class->wcal_bulk_action_delete_guest_carts_handler();2622 }2623 // Abandoned Orders page - Bulk Action - Delete all visitor carts.2624 if ( ‘wcal_delete_all_visitor’ === $action || ‘wcal_delete_all_visitor’ === $action_two ) {2625 $class = new Wcal_Delete_Handler();2626 $class->wcal_bulk_action_delete_visitor_carts_handler();2627 }2628 // Abandoned Orders page - Bulk Action - Delete all carts.2629 if ( ‘wcal_delete_all’ === $action || ‘wcal_delete_all’ === $action_two ) {2630 $class = new Wcal_Delete_Handler();2631 $class->wcal_bulk_action_delete_all_carts_handler();2632 }26332634 // Detect when a bulk action is being triggered on templates page.2635 if ( ‘wcal_delete_template’ === $action || ‘wcal_delete_template’ === $action_two ) {2636 $ids = isset( $_GET[‘template_id’] ) && is_array( $_GET[‘template_id’] ) ? array_map( 'intval’, wp_unslash( $_GET[‘template_id’] ) ) : sanitize_text_field( wp_unslash( $_GET[‘template_id’] ) ); // phpcs:ignore WordPress.Security.NonceVerification2637 if ( ! is_array( $ids ) ) {2638 $ids = array( $ids );2639 }2640 foreach ( $ids as $id ) {2641 $class = new Wcal_Delete_Handler();2642 $class->wcal_delete_template_bulk_action_handler_function( $id );2643 }2644 }26452646 if ( isset( $_GET[‘wcal_deleted’] ) && ‘YES’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_deleted’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2647 $msg = __( 'The Abandoned cart has been successfully deleted.’, ‘woocommerce-abandoned-cart’ ); // Default Msg.2648 if ( isset( $_GET[‘wcal_deleted_all’] ) && ‘YES’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_deleted_all’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2649 $msg = __( 'All Abandoned Carts have been successfully deleted.’, ‘woocommerce-abandoned-cart’ ); // Delete All Carts.2650 } elseif ( isset( $_GET[‘wcal_deleted_all_visitor’] ) && ‘YES’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_deleted_all_visitor’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2651 $msg = __( 'All Visitor carts have been successfully deleted.’, ‘woocommerce-abandoned-cart’ ); // Delete all visitor carts.2652 } elseif ( isset( $_GET[‘wcal_deleted_all_guest’] ) && ‘YES’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_deleted_all_guest’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2653 $msg = __( 'All Guest carts have been successfully deleted.’, ‘woocommerce-abandoned-cart’ ); // Delete all Guest carts.2654 } elseif ( isset( $_GET[‘wcal_deleted_all_registered’] ) && ‘YES’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_deleted_all_registered’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2655 $msg = __( 'All Registered carts have been deleted.’, ‘woocommerce-abandoned-cart’ ); // Delete all registered carts.2656 }2657 ?>2658 <div id="message" class="updated fade">2659 <p><strong><?php echo esc_html( $msg ); ?></strong></p>2660 </div>2661 <?php2662 }2663 if ( isset( $_GET [‘wcal_template_deleted’] ) && ‘YES’ === sanitize_text_field( wp_unslash( $_GET[‘wcal_template_deleted’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification2664 ?>2665 <div id="message" class="updated fade">2666 <p><strong><?php esc_html_e( 'The Template has been successfully deleted.’, ‘woocommerce-abandoned-cart’ ); ?></strong></p>2667 </div>2668 <?php2669 }2670 if ( ‘emailsettings’ === $action ) {2671 // Save the field values.2672 ?>2673 <div id="content">2674 <?php2675 $wcal_general_settings_class = '’;2676 $wcal_email_setting = '’;2677 $wcap_sms_settings = '’;2678 $wcap_atc_settings = '’;2679 $wcap_fb_settings = '’;2680 $wcap_connectors = '’;26812682 $section = isset( $_GET[‘wcal_section’] ) ? sanitize_text_field( wp_unslash( $_GET[‘wcal_section’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2683 switch ( $section ) {2684 case 'wcal_general_settings’:2685 case '’:2686 $wcal_general_settings_class = 'current’;2687 break;2688 case 'wcal_email_settings’:2689 $wcal_email_setting = 'current’;2690 break;2691 case 'wcap_sms_settings’:2692 $wcap_sms_settings = 'current’;2693 break;2694 case 'wcap_atc_settings’:2695 $wcap_atc_settings = 'current’;2696 break;2697 case 'wcap_fb_settings’:2698 $wcap_fb_settings = 'current’;2699 break;2700 case 'wcap_connectors’:2701 $wcap_connectors = 'current’;2702 break;2703 default:2704 $wcal_general_settings_class = 'current’;2705 break;2706 }2707 ?>2708 <ul class="subsubsub" id="wcal_general_settings_list">2709 <li>2710 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcal_general_settings" class="<?php echo esc_attr( $wcal_general_settings_class ); ?>"><?php esc_html_e( 'General Settings’, ‘woocommerce-abandoned-cart’ ); ?> </a> |2711 </li>2712 <li>2713 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcal_email_settings" class="<?php echo esc_attr( $wcal_email_setting ); ?>"><?php esc_html_e( 'Email Sending Settings’, ‘woocommerce-abandoned-cart’ ); ?> </a> |2714 </li>2715 <li>2716 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_atc_settings" class="<?php echo esc_attr( $wcap_atc_settings ); ?>"><?php esc_html_e( 'Add To Cart Popup Editor’, ‘woocommerce-ac’ ); ?> </a> |2717 </li>2718 <li>2719 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_fb_settings" class="<?php echo esc_attr( $wcap_fb_settings ); ?>"><?php esc_html_e( 'Facebook Messenger’, ‘woocommerce-ac’ ); ?> </a> |2720 </li>2721 <li>2722 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_sms_settings" class="<?php echo esc_attr( $wcap_sms_settings ); ?>"><?php esc_html_e( 'SMS’, ‘woocommerce-ac’ ); ?> </a> |2723 </li>2724 <li>2725 <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_connectors" class="<?php echo esc_attr( $wcap_connectors ); ?>"><?php esc_html_e( 'Connectors’, ‘woocommerce-ac’ ); ?> </a>2726 </li>2727 <?php do_action( 'wcal_add_custom_settings_tab’, $section ); ?>2728 </ul>2729 <br class="clear">2730 <?php2731 if ( ‘wcal_general_settings’ === $section || ‘’ === $section ) {2732 ?>2733 <p><?php esc_html_e( 'Change settings for sending email notifications to Customers, to Admin etc.’, ‘woocommerce-abandoned-cart’ ); ?></p>2734 <form method="post" action="options.php">2735 <?php settings_fields( ‘woocommerce_ac_settings’ ); ?>2736 <?php do_settings_sections( ‘woocommerce_ac_page’ ); ?>2737 <?php settings_errors(); ?>2738 <?php submit_button(); ?>2739 </form>2740 <?php2741 } elseif ( ‘wcal_email_settings’ === $section ) {2742 ?>2743 <p><?php esc_html_e( 'Change settings for sending email notifications to Customers, to Admin etc.’, ‘woocommerce-abandoned-cart’ ); ?></p>2744 <form method="post" action="options.php">2745 <?php settings_fields( ‘woocommerce_ac_email_settings’ ); ?>2746 <?php do_settings_sections( ‘woocommerce_ac_email_page’ ); ?>2747 <?php settings_errors(); ?>2748 <?php submit_button(); ?>2749 </form>2750 <?php2751 } elseif ( ‘wcap_atc_settings’ === $section ) {2752 WCAP_Pro_Settings::wcap_atc_settings();2753 } elseif ( ‘wcap_fb_settings’ === $section ) {2754 WCAP_Pro_Settings::wcap_fb_settings();2755 } elseif ( ‘wcap_sms_settings’ === $section ) {2756 WCAP_Pro_Settings::wcap_sms_settings();2757 } elseif ( ‘wcap_connectors’ === $section ) {2758 WCAP_Pro_Settings::wcap_connectors();2759 }2760 do_action( ‘wcal_add_custom_settings_tab_content’, $section );2761 ?>2762 </div>2763 <?php2764 } elseif ( ‘dashboard’ === $action || ‘’ === $action || '-1’ === $action || ‘1’ === $action_two ) {2765 include_once 'includes/classes/class-wcal-dashboard-report.php’;2766 Wcal_Dashboard_Report::wcal_dashboard_display();2767 } elseif ( ‘listcart’ === $action ) {27682769 ?>2770 <p> <?php esc_html_e( 'The list below shows all Abandoned Carts which have remained in cart for a time higher than the “Cart abandoned cut-off time” setting.’, ‘woocommerce-abandoned-cart’ ); ?> </p>2771 <?php2772 $get_all_abandoned_count = wcal_common::wcal_get_abandoned_order_count( ‘wcal_all_abandoned’ );2773 $get_registered_user_ac_count = wcal_common::wcal_get_abandoned_order_count( ‘wcal_all_registered’ );2774 $get_guest_user_ac_count = wcal_common::wcal_get_abandoned_order_count( ‘wcal_all_guest’ );2775 $get_visitor_user_ac_count = wcal_common::wcal_get_abandoned_order_count( ‘wcal_all_visitor’ );27762777 $wcal_user_reg_text = 'User’;2778 if ( $get_registered_user_ac_count > 1 ) {2779 $wcal_user_reg_text = 'Users’;2780 }2781 $wcal_user_gus_text = 'User’;2782 if ( $get_guest_user_ac_count > 1 ) {2783 $wcal_user_gus_text = 'Users’;2784 }2785 $wcal_all_abandoned_carts = '’;2786 $section = '’;2787 $wcal_all_registered = '’;2788 $wcal_all_guest = '’;2789 $wcal_all_visitor = '’;27902791 $section = isset( $_GET[‘wcal_section’] ) ? sanitize_text_field( wp_unslash( $_GET[‘wcal_section’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2792 if ( ‘wcal_all_abandoned’ === $section || ‘’ === $section ) {2793 $wcal_all_abandoned_carts = 'current’;2794 }27952796 if ( ‘wcal_all_registered’ === $section ) {2797 $wcal_all_registered = 'current’;2798 $wcal_all_abandoned_carts = '’;2799 }2800 if ( ‘wcal_all_guest’ === $section ) {2801 $wcal_all_guest = 'current’;2802 $wcal_all_abandoned_carts = '’;2803 }28042805 if ( ‘wcal_all_visitor’ === $section ) {2806 $wcal_all_visitor = 'current’;2807 $wcal_all_abandoned_carts = '’;2808 }2809 ?>2810 <ul class="subsubsub" id="wcal_recovered_orders_list">2811 <li>2812 <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_abandoned" class="<?php echo esc_attr( $wcal_all_abandoned_carts ); ?>"><?php esc_html_e( 'All ', ‘woocommerce-abandoned-cart’ ); ?> <span class = “count” > <?php echo esc_html( "( $get_all_abandoned_count )" ); ?> </span></a>2813 </li>28142815 <?php if ( $get_registered_user_ac_count > 0 ) { ?>2816 <li><?php // translators: Users. ?>2817 | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_registered" class="<?php echo esc_attr( $wcal_all_registered ); ?>"><?php printf( esc_html__( 'Registered %s’, ‘woocommerce-abandoned-cart’ ), esc_html( $wcal_user_reg_text ) ); ?> <span class = “count” > <?php echo esc_html( "( $get_registered_user_ac_count )" ); ?> </span></a>2818 </li>2819 <?php } ?>28202821 <?php if ( $get_guest_user_ac_count > 0 ) { ?>2822 <li><?php // translators: Users. ?>2823 | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_guest" class="<?php echo esc_attr( $wcal_all_guest ); ?>"><?php printf( esc_html__( 'Guest %s’, ‘woocommerce-abandoned-cart’ ), esc_html( $wcal_user_gus_text ) ); ?> <span class = “count” > <?php echo esc_html( "( $get_guest_user_ac_count )" ); ?> </span></a>2824 </li>2825 <?php } ?>28262827 <?php if ( $get_visitor_user_ac_count > 0 ) { ?>2828 <li>2829 | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_visitor" class="<?php echo esc_attr( $wcal_all_visitor ); ?>"><?php esc_html_e( ‘Carts without Customer Details’, ‘woocommerce-abandoned-cart’ ); ?> <span class = “count” > <?php echo esc_html( "( $get_visitor_user_ac_count )" ); ?> </span></a>2830 </li>2831 <?php } ?>2832 </ul>28332834 <?php2835 global $wpdb;2836 include_once ‘includes/classes/class-wcal-abandoned-orders-table.php’;2837 $wcal_abandoned_order_list = new WCAL_Abandoned_Orders_Table();2838 $wcal_abandoned_order_list->wcal_abandoned_order_prepare_items();2839 ?>2840 <div class="wrap">2841 <form id="wcal-abandoned-orders" method="get" >2842 <input type="hidden" name="page" value="woocommerce_ac_page" />2843 <input type="hidden" name="action" value="listcart" />2844 <?php $wcal_abandoned_order_list->display(); ?>2845 </form>2846 </div>2847 <?php2848 } elseif ( ( ‘emailtemplates’ === $action && ( ‘edittemplate’ !== $mode && ‘addnewtemplate’ !== $mode ) || ‘’ === $action || '-1’ === $action || '-1’ === $action_two ) ) {2849 ?>2850 <p> <?php esc_html_e( 'Add email templates at different intervals to maximize the possibility of recovering your abandoned carts.’, ‘woocommerce-abandoned-cart’ ); ?> </p>2851 <?php2852 // Save the field values.2853 $insert_template_successfuly = '’;2854 $update_template_successfuly = '’;2855 $woocommerce_ac_email_subject = isset( $_POST[‘woocommerce_ac_email_subject’] ) ? trim( htmlspecialchars( sanitize_text_field( wp_unslash( $_POST[‘woocommerce_ac_email_subject’] ) ) ), ENT_QUOTES ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2856 $woocommerce_ac_email_body = isset( $_POST[‘woocommerce_ac_email_body’] ) ? trim( wp_unslash( $_POST[‘woocommerce_ac_email_body’] ) ) : '’; // phpcs:ignore2857 $woocommerce_ac_template_name = isset( $_POST[‘woocommerce_ac_template_name’] ) ? trim( sanitize_text_field( wp_unslash( $_POST[‘woocommerce_ac_template_name’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2858 $woocommerce_ac_email_header = isset( $_POST[‘wcal_wc_email_header’] ) ? stripslashes( trim( htmlspecialchars( sanitize_text_field( wp_unslash( $_POST[‘wcal_wc_email_header’] ) ) ), ENT_QUOTES ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification28592860 $email_frequency = isset( $_POST[‘email_frequency’] ) ? trim( sanitize_text_field( wp_unslash( $_POST[‘email_frequency’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2861 $day_or_hour = isset( $_POST[‘day_or_hour’] ) ? trim( sanitize_text_field( wp_unslash( $_POST[‘day_or_hour’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2862 $is_wc_template = empty( $_POST[‘is_wc_template’] ) ? ‘0’ : '1’; // phpcs:ignore WordPress.Security.NonceVerification28632864 // If the link merge tags are prefixed with http://|https:// please remove it.2865 $rectify_links = array(2866 'http://{{cart.link}}’,2867 'https://{{cart.link}}’,2868 'http://{{cart.unsubscribe}}’,2869 'https://{{cart.unsubscribe}}’,2870 'http://{{shop.url}}’,2871 'https://{{shop.url}}’,2872 );2873 foreach ( $rectify_links as $merge_tag ) {2874 $start_tag = stripos( $merge_tag, ‘{{’ );2875 $new_tag = substr( $merge_tag, $start_tag );2876 $woocommerce_ac_email_body = str_ireplace( $merge_tag, $new_tag, $woocommerce_ac_email_body );2877 }2878 if ( isset( $_POST[‘ac_settings_frm’] ) && ‘save’ === sanitize_text_field( wp_unslash( $_POST[‘ac_settings_frm’] ) ) ) { // phpcs:ignore 2879 $default_value = 0;2880 $coupon_code_id = isset( $_POST[‘coupon_ids’][0] ) ? sanitize_text_field( wp_unslash( implode( ',’, $_POST[‘coupon_ids’] ) ) ) : '’; // phpcs:ignore 2881 $unique_coupon = ( empty( $_POST[‘unique_coupon’] ) ) ? ‘0’ : '1’; // phpcs:ignore WordPress.Security.NonceVerification2882 $coupon_code_options = self::wcal_coupon_options();2883 $email_type = 'abandoned_cart_email’;28842885 $insert_template_successfuly = $wpdb->query( //phpcs:ignore2886 $wpdb->prepare(2887 ‘INSERT INTO `’ . $wpdb->prefix . 'ac_email_templates_lite` (email_type, subject, body, frequency, day_or_hour, template_name, is_wc_template, default_template, wc_email_header, coupon_code, individual_use, generate_unique_coupon_code, discount, discount_type, discount_shipping, discount_expiry ) VALUES ( %s, %s, %s, %d, %s, %s, %s, %d, %s, %s, %s, %s, %s, %s, %s, %s )',2888 $email_type,2889 $woocommerce_ac_email_subject,2890 $woocommerce_ac_email_body,2891 $email_frequency,2892 $day_or_hour,2893 $woocommerce_ac_template_name,2894 $is_wc_template,2895 $default_value,2896 $woocommerce_ac_email_header,2897 $coupon_code_id,2898 $coupon_code_options[‘individual_use’],2899 $unique_coupon,2900 $coupon_code_options[‘coupon_amount’],2901 $coupon_code_options[‘discount_type’],2902 $coupon_code_options[‘discount_shipping’],2903 $coupon_code_options[‘coupon_expiry’]2904 )2905 );2906 }29072908 if ( isset( $_POST[‘ac_settings_frm’] ) && ‘update’ === sanitize_text_field( wp_unslash( $_POST[‘ac_settings_frm’] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification29092910 $updated_is_active = '0’;2911 $id = isset( $_POST[‘id’] ) ? trim( sanitize_text_field( wp_unslash( $_POST[‘id’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification29122913 $check_results = $wpdb->get_results( //phpcs:ignore2914 $wpdb->prepare(2915 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d’,2916 $id2917 )2918 );2919 $default_value = '’;29202921 if ( count( $check_results ) > 0 ) {2922 if ( isset( $check_results[0]->default_template ) && ‘1’ === $check_results[0]->default_template ) {2923 $default_value = '1’;2924 }2925 }2926 $coupon_code_id = isset( $_POST[‘coupon_ids’][0] ) ? sanitize_text_field( wp_unslash( implode( ',’, $_POST[‘coupon_ids’] ) ) ) : '’; // phpcs:ignore 2927 $unique_coupon = ( empty( $_POST[‘unique_coupon’] ) ) ? ‘0’ : '1’; // phpcs:ignore 2928 $coupon_code_options = self::wcal_coupon_options();29292930 $update_template_successfuly = $wpdb->query( //phpcs:ignore2931 $wpdb->prepare(2932 ‘UPDATE `’ . $wpdb->prefix . 'ac_email_templates_lite` SET subject = %s, body = %s, frequency = %d, day_or_hour = %s, template_name = %s, is_wc_template = %s, default_template = %d, wc_email_header = %s,coupon_code = %s, individual_use =%s, generate_unique_coupon_code = %s, discount = %s, discount_type = %s, discount_shipping =%s, discount_expiry = %s WHERE id = %d’,2933 $woocommerce_ac_email_subject,2934 $woocommerce_ac_email_body,2935 $email_frequency,2936 $day_or_hour,2937 $woocommerce_ac_template_name,2938 $is_wc_template,2939 $default_value,2940 $woocommerce_ac_email_header,2941 $coupon_code_id,2942 $coupon_code_options[‘individual_use’],2943 $unique_coupon,2944 $coupon_code_options[‘coupon_amount’],2945 $coupon_code_options[‘discount_type’],2946 $coupon_code_options[‘discount_shipping’],2947 $coupon_code_options[‘coupon_expiry’],2948 $id2949 )2950 );2951 }29522953 if ( ‘emailtemplates’ === $action && ‘removetemplate’ === $mode ) {2954 $id_remove = isset( $_GET[‘id’] ) ? sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2955 $wpdb->query( //phpcs:ignore2956 $wpdb->prepare(2957 ‘DELETE FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` WHERE id= %d ',2958 $id_remove2959 )2960 );2961 }29622963 if ( ‘emailtemplates’ === $action && ‘activate_template’ === $mode ) {2964 $template_id = isset( $_GET[‘id’] ) ? sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification2965 $current_template_status = isset( $_GET[‘active_state’] ) ? sanitize_text_field( wp_unslash( $_GET[‘active_state’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification29662967 if ( ‘1’ === $current_template_status ) {2968 $active = '0’;2969 } else {2970 $active = '1’;2971 $get_selected_template_result = $wpdb->get_results( // phpcs:ignore2972 $wpdb->prepare(2973 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d’,2974 $template_id2975 )2976 );29772978 $email_frequncy = $get_selected_template_result[0]->frequency;2979 $email_day_or_hour = $get_selected_template_result[0]->day_or_hour;2980 $wcap_updated = $wpdb->query( // phpcs:ignore2981 $wpdb->prepare(2982 ‘UPDATE `’ . $wpdb->prefix . 'ac_email_templates_lite` SET is_active = %s WHERE frequency = %s AND day_or_hour = %s’,2983 0,2984 $email_frequncy,2985 $email_day_or_hour2986 )2987 );2988 }29892990 $wpdb->query( // phpcs:ignore2991 $wpdb->prepare(2992 ‘UPDATE `’ . $wpdb->prefix . 'ac_email_templates_lite` SET is_active = %s WHERE id = %s’,2993 $active,2994 $template_id2995 )2996 );29972998 wp_safe_redirect( admin_url( ‘/admin.php?page=woocommerce_ac_page&action=emailtemplates’ ) );2999 }30003001 if ( isset( $_POST[‘ac_settings_frm’] ) && ‘save’ === $_POST[‘ac_settings_frm’] && ( isset( $insert_template_successfuly ) && ‘’ !== $insert_template_successfuly ) ) { // phpcs:ignore WordPress.Security.NonceVerification3002 ?>3003 <div id="message" class="updated fade">3004 <p>3005 <strong>3006 <?php esc_html_e( 'The Email Template has been successfully added. In order to start sending this email to your customers, please activate it.’, ‘woocommerce-abandoned-cart’ ); ?>3007 </strong>3008 </p>3009 </div>3010 <?php3011 } elseif ( isset( $_POST[‘ac_settings_frm’] ) && ‘save’ === $_POST[‘ac_settings_frm’] && ( isset( $insert_template_successfuly ) && ‘’ === $insert_template_successfuly ) ) { // phpcs:ignore WordPress.Security.NonceVerification3012 ?>3013 <div id="message" class="error fade">3014 <p>3015 <strong>3016 <?php esc_html_e( 'There was a problem adding the email template. Please contact the plugin author via <a href= “https://wordpress.org/support/plugin/woocommerce-abandoned-cart">support forum</a>.’, ‘woocommerce-abandoned-cart’ ); ?>3017 </strong>3018 </p>3019 </div>3020 <?php3021 }30223023 if ( isset( $_POST[‘ac_settings_frm’] ) && ‘update’ === $_POST[‘ac_settings_frm’] && isset( $update_template_successfuly ) && false !== $update_template_successfuly ) { // phpcs:ignore WordPress.Security.NonceVerification3024 ?>3025 <div id="message” class="updated fade">3026 <p>3027 <strong>3028 <?php esc_html_e( 'The Email Template has been successfully updated.’, ‘woocommerce-abandoned-cart’ ); ?>3029 </strong>3030 </p>3031 </div>3032 <?php3033 } elseif ( isset( $_POST[‘ac_settings_frm’] ) && ‘update’ === $_POST[‘ac_settings_frm’] && isset( $update_template_successfuly ) && false === $update_template_successfuly ) { // phpcs:ignore WordPress.Security.NonceVerification3034 ?>3035 <div id="message" class="error fade">3036 <p>3037 <strong>3038 <?php esc_html_e( 'There was a problem updating the email template. Please contact the plugin author via <a href= “https://wordpress.org/support/plugin/woocommerce-abandoned-cart">support forum</a>.’, ‘woocommerce-abandoned-cart’ ); ?>3039 </strong>3040 </p>3041 </div>3042 <?php3043 }3044 ?>3045 <div class="tablenav">3046 <p style="float:left;">3047 <a cursor: pointer; href="<?php echo esc_url( ‘admin.php?page=woocommerce_ac_page&action=emailtemplates&mode=addnewtemplate’ ); ?>” class="button-secondary"><?php esc_html_e( 'Add New Template’, ‘woocommerce-abandoned-cart’ ); ?></a>3048 </p>30493050 <?php3051 // From here you can do whatever you want with the data from the $result link.3052 include_once 'includes/classes/class-wcal-templates-table.php’;3053 $wcal_template_list = new WCAL_Templates_Table();3054 $wcal_template_list->wcal_templates_prepare_items();3055 ?>3056 <div class="wrap">3057 <form id="wcal-abandoned-templates" method="get" >3058 <input type="hidden" name="page" value="woocommerce_ac_page" />3059 <input type="hidden" name="action" value="emailtemplates" />3060 <?php $wcal_template_list->display(); ?>3061 </form>3062 </div>3063 </div>3064 <?php3065 } elseif ( ‘stats’ === $action || ‘’ === $action ) {3066 ?>3067 <p>3068 <script language=’javascript’>3069 jQuery( document ).ready( function() {3070 jQuery( ‘#duration_select’ ).change( function() {3071 var group_name = jQuery( ‘#duration_select’ ).val();3072 var today = new Date();3073 var start_date = “";3074 var end_date = “";3075 if ( group_name == “yesterday” ) {3076 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 1 );3077 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 1 );3078 } else if ( group_name == “today”) {3079 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3080 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3081 } else if ( group_name == “last_seven” ) {3082 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 7 );3083 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3084 } else if ( group_name == “last_fifteen” ) {3085 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 15 );3086 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3087 } else if ( group_name == “last_thirty” ) {3088 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 30 );3089 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3090 } else if ( group_name == “last_ninety” ) {3091 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 90 );3092 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3093 } else if ( group_name == “last_year_days” ) {3094 start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 365 );3095 end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );3096 }30973098 var monthNames = [“Jan", “Feb", “Mar", “Apr", “May", “Jun", “Jul", “Aug", “Sep", “Oct", “Nov", “Dec”];30993100 var start_date_value = start_date.getDate() + " " + monthNames[start_date.getMonth()] + " " + start_date.getFullYear();3101 var end_date_value = end_date.getDate() + " " + monthNames[end_date.getMonth()] + " " + end_date.getFullYear();31023103 jQuery( ‘#start_date’ ).val( start_date_value );3104 jQuery( ‘#end_date’ ).val( end_date_value );3105 } );3106 });3107 </script>3108 <?php3109 $duration_range = isset( $_POST[‘duration_select’] ) ? sanitize_text_field( wp_unslash( $_POST[‘duration_select’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification3110 if ( ‘’ === $duration_range ) {3111 if ( isset( $_GET[‘duration_select’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification3112 $duration_range = sanitize_text_field( wp_unslash( $_GET[‘duration_select’] ) ); // phpcs:ignore WordPress.Security.NonceVerification3113 }3114 }3115 if ( ‘’ === $duration_range ) {3116 $duration_range = 'last_seven’;3117 }31183119 echo esc_html_e( 'The Report below shows how many Abandoned Carts we were able to recover for you by sending automatic emails to encourage shoppers.’, ‘woocommerce-abandoned-cart’ );3120 ?>3121 <div id="recovered_stats” class="postbox” style="display:block">3122 <div class="inside">3123 <form method="post” action="admin.php?page=woocommerce_ac_page&action=stats” id="ac_stats">3124 <select id="duration_select” name="duration_select” >3125 <?php3126 foreach ( $this->duration_range_select as $key => $value ) {3127 $sel = '’;3128 if ( $key == $duration_range ) { // phpcs:ignore3129 $sel = ' selected ';3130 }3131 printf(3132 '<option value="%s” %s> %s </option>’,3133 esc_attr( $key ),3134 esc_attr( $sel ),3135 esc_attr( $value )3136 );3137 }3138 $date_sett = $this->start_end_dates[ $duration_range ];3139 ?>3140 </select>3141 <script type="text/javascript">3142 jQuery( document ).ready( function() {3143 var formats = [“d.m.y", “d M yy","MM d, yy”];3144 jQuery( “#start_date” ).datepicker( { dateFormat: formats[1] } );3145 });31463147 jQuery( document ).ready( function()3148 {3149 var formats = [“d.m.y", “d M yy","MM d, yy”];3150 jQuery( “#end_date” ).datepicker( { dateFormat: formats[1] } );3151 });3152 </script>3153 <?php3154 include_once 'includes/classes/class-wcal-recover-orders-table.php’;3155 $wcal_recover_orders_list = new Wcal_Recover_Orders_Table();3156 $wcal_recover_orders_list->wcal_recovered_orders_prepare_items();31573158 $start_date_range = isset( $_POST[‘start_date’] ) ? sanitize_text_field( wp_unslash( $_POST[‘start_date’] ) ) : '’;// phpcs:ignore WordPress.Security.NonceVerification31593160 if ( ‘’ === $start_date_range ) {3161 $start_date_range = $date_sett[‘start_date’];3162 }31633164 $end_date_range = isset( $_POST[‘end_date’] ) ? sanitize_text_field( wp_unslash( $_POST[‘end_date’] ) ) : '’;// phpcs:ignore WordPress.Security.NonceVerification31653166 if ( ‘’ === $end_date_range ) {3167 $end_date_range = $date_sett[‘end_date’];3168 }3169 ?>3170 <label class="start_label” for="start_day"> <?php esc_html_e( 'Start Date:’, ‘woocommerce-abandoned-cart’ ); ?> </label>3171 <input type="text” id="start_date” name="start_date” readonly="readonly” value="<?php echo esc_attr( $start_date_range ); ?>"/>3172 <label class="end_label” for="end_day"> <?php esc_html_e( 'End Date:’, ‘woocommerce-abandoned-cart’ ); ?> </label>3173 <input type="text” id="end_date” name="end_date" readonly="readonly" value="<?php echo esc_attr( $end_date_range ); ?>"/>3174 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Go’, ‘woocommerce-abandoned-cart’ ); ?>" />3175 </form>3176 </div>3177 </div>3178 <div id="recovered_stats" class="postbox" style="display:block">3179 <div class="inside" >3180 <?php3181 $count = $wcal_recover_orders_list->total_abandoned_cart_count;3182 $total_of_all_order = $wcal_recover_orders_list->total_order_amount;3183 $recovered_item = $wcal_recover_orders_list->recovered_item;3184 $recovered_total = wc_price( $wcal_recover_orders_list->total_recover_amount );3185 ?>3186 <p style="font-size: 15px;">3187 <?php3188 printf(3189 // translators: All counts of items & amounts.3190 wp_kses_post(3191 // translators: Abandoned & recovered numbers and order totals.3192 __( 'During the selected range <strong>%1$d</strong> carts totaling <strong>%2$s</strong> were abandoned. We were able to recover <strong>%3$d</strong> of them, which led to an extra <strong>%4$s</strong>’, ‘woocommerce-abandoned-cart’ )3193 ),3194 esc_attr( $count ),3195 wp_kses_post( $total_of_all_order ),3196 esc_attr( $recovered_item ),3197 wp_kses_post( $recovered_total )3198 );3199 ?>3200 </p>3201 </div>3202 </div>3203 <div class="wrap">3204 <form id="wcal-recover-orders" method="get" >3205 <input type="hidden" name="page" value="woocommerce_ac_page" />3206 <input type="hidden" name="action" value="stats" />3207 <?php $wcal_recover_orders_list->display(); ?>3208 </form>3209 </div>3210 <?php3211 } elseif ( ‘orderdetails’ === $action ) {3212 global $woocommerce;3213 $ac_order_id = isset( $_GET[‘id’] ) ? sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification3214 ?>3215 <div id="ac_order_details" class="postbox" style="display:block">3216 <?php // translators: Abandoned Order ID. ?>3217 <h3 class="details-title"> <p> <?php printf( esc_html__( 'Abandoned Order #%s Details’, ‘woocommerce-abandoned-cart’ ), esc_attr( $ac_order_id ) ); ?> </p> </h3>3218 <div class="inside">3219 <table cellpadding="0" cellspacing="0" class="wp-list-table widefat fixed posts">3220 <tr>3221 <th> <?php esc_html_e( 'Item’, ‘woocommerce-abandoned-cart’ ); ?> </th>3222 <th> <?php esc_html_e( 'Name’, ‘woocommerce-abandoned-cart’ ); ?> </th>3223 <th> <?php esc_html_e( 'Quantity’, ‘woocommerce-abandoned-cart’ ); ?> </th>3224 <th> <?php esc_html_e( 'Line Subtotal’, ‘woocommerce-abandoned-cart’ ); ?> </th>3225 <th> <?php esc_html_e( 'Line Total’, ‘woocommerce-abandoned-cart’ ); ?> </th>3226 </tr>3227 <?php3228 $results = $wpdb->get_results( // phpcs:ignore3229 $wpdb->prepare(3230 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE id = %d’,3231 sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) // phpcs:ignore WordPress.Security.NonceVerification3232 )3233 );32343235 $shipping_charges = 0;3236 $currency_symbol = get_woocommerce_currency_symbol();3237 $number_decimal = wc_get_price_decimals();3238 if ( ‘GUEST’ === $results[0]->user_type && $results[0]->user_id > 0 ) {3239 $results_guest = $wpdb->get_results( // phpcs:ignore3240 $wpdb->prepare(3241 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE id = %d’,3242 $results[0]->user_id3243 )3244 );32453246 $user_email = '’;3247 $user_first_name = '’;3248 $user_last_name = '’;3249 $user_billing_postcode = '’;3250 $user_shipping_postcode = '’;3251 $shipping_charges = '’;3252 if ( count( $results_guest ) > 0 ) {3253 $user_email = $results_guest[0]->email_id;3254 $user_first_name = $results_guest[0]->billing_first_name;3255 $user_last_name = $results_guest[0]->billing_last_name;3256 $user_billing_postcode = $results_guest[0]->billing_zipcode;3257 $user_shipping_postcode = $results_guest[0]->shipping_zipcode;3258 $shipping_charges = $results_guest[0]->shipping_charges;3259 }3260 $user_billing_company = '’;3261 $user_billing_address_1 = '’;3262 $user_billing_address_2 = '’;3263 $user_billing_city = '’;3264 $user_billing_state = '’;3265 $user_billing_country = '’;3266 $user_billing_phone = '’;32673268 $user_shipping_company = '’;3269 $user_shipping_address_1 = '’;3270 $user_shipping_address_2 = '’;3271 $user_shipping_city = '’;3272 $user_shipping_state = '’;3273 $user_shipping_country = '’;3274 } elseif ( ‘GUEST’ === $results[0]->user_type && $results[0]->user_id > 0 ) {3275 $user_email = '’;3276 $user_first_name = 'Visitor’;3277 $user_last_name = '’;3278 $user_billing_postcode = '’;3279 $user_shipping_postcode = '’;3280 $shipping_charges = '’;3281 $user_billing_phone = '’;3282 $user_billing_company = '’;3283 $user_billing_address_1 = '’;3284 $user_billing_address_2 = '’;3285 $user_billing_city = '’;3286 $user_billing_state = '’;3287 $user_billing_country = '’;3288 $user_shipping_company = '’;3289 $user_shipping_address_1 = '’;3290 $user_shipping_address_2 = '’;3291 $user_shipping_city = '’;3292 $user_shipping_state = '’;3293 $user_shipping_country = '’;3294 } else {3295 $user_id = $results[0]->user_id;3296 if ( isset( $results[0]->user_login ) ) {3297 $user_login = $results[0]->user_login;3298 }3299 $user_email = get_user_meta( $results[0]->user_id, 'billing_email’, true );3300 if ( ‘’ == $user_email ) { // phpcs:ignore3301 $user_data = get_userdata( $results[0]->user_id );3302 if ( isset( $user_data->user_email ) ) {3303 $user_email = $user_data->user_email;3304 } else {3305 $user_email = '’;3306 }3307 }33083309 $user_first_name = '’;3310 $user_first_name_temp = get_user_meta( $user_id, 'billing_first_name’, true );3311 if ( isset( $user_first_name_temp ) && ‘’ == $user_first_name_temp ) { // phpcs:ignore3312 $user_data = get_userdata( $user_id );3313 if ( isset( $user_data->first_name ) ) {3314 $user_first_name = $user_data->first_name;3315 } else {3316 $user_first_name = '’;3317 }3318 } else {3319 $user_first_name = $user_first_name_temp;3320 }3321 $user_last_name = '’;3322 $user_last_name_temp = get_user_meta( $user_id, 'billing_last_name’, true );3323 if ( isset( $user_last_name_temp ) && ‘’ == $user_last_name_temp ) { // phpcs:ignore3324 $user_data = get_userdata( $user_id );3325 if ( isset( $user_data->last_name ) ) {3326 $user_last_name = $user_data->last_name;3327 } else {3328 $user_last_name = '’;3329 }3330 } else {3331 $user_last_name = $user_last_name_temp;3332 }3333 $user_billing_first_name = get_user_meta( $results[0]->user_id, ‘billing_first_name’ );3334 $user_billing_last_name = get_user_meta( $results[0]->user_id, ‘billing_last_name’ );33353336 $user_billing_details = wcal_common::wcal_get_billing_details( $results[0]->user_id );33373338 $user_billing_company = $user_billing_details[‘billing_company’];3339 $user_billing_address_1 = $user_billing_details[‘billing_address_1’];3340 $user_billing_address_2 = $user_billing_details[‘billing_address_2’];3341 $user_billing_city = $user_billing_details[‘billing_city’];3342 $user_billing_postcode = $user_billing_details[‘billing_postcode’];3343 $user_billing_country = $user_billing_details[‘billing_country’];3344 $user_billing_state = $user_billing_details[‘billing_state’];33453346 $user_billing_phone_temp = get_user_meta( $results[0]->user_id, ‘billing_phone’ );3347 if ( isset( $user_billing_phone_temp[0] ) ) {3348 $user_billing_phone = $user_billing_phone_temp[0];3349 } else {3350 $user_billing_phone = '’;3351 }3352 $user_shipping_first_name = get_user_meta( $results[0]->user_id, ‘shipping_first_name’ );3353 $user_shipping_last_name = get_user_meta( $results[0]->user_id, ‘shipping_last_name’ );3354 $user_shipping_company_temp = get_user_meta( $results[0]->user_id, ‘shipping_company’ );3355 if ( isset( $user_shipping_company_temp[0] ) ) {3356 $user_shipping_company = $user_shipping_company_temp[0];3357 } else {3358 $user_shipping_company = '’;3359 }3360 $user_shipping_address_1_temp = get_user_meta( $results[0]->user_id, ‘shipping_address_1’ );3361 if ( isset( $user_shipping_address_1_temp[0] ) ) {3362 $user_shipping_address_1 = $user_shipping_address_1_temp[0];3363 } else {3364 $user_shipping_address_1 = '’;3365 }3366 $user_shipping_address_2_temp = get_user_meta( $results[0]->user_id, ‘shipping_address_2’ );3367 if ( isset( $user_shipping_address_2_temp[0] ) ) {3368 $user_shipping_address_2 = $user_shipping_address_2_temp[0];3369 } else {3370 $user_shipping_address_2 = '’;3371 }3372 $user_shipping_city_temp = get_user_meta( $results[0]->user_id, ‘shipping_city’ );3373 if ( isset( $user_shipping_city_temp[0] ) ) {3374 $user_shipping_city = $user_shipping_city_temp[0];3375 } else {3376 $user_shipping_city = '’;3377 }3378 $user_shipping_postcode_temp = get_user_meta( $results[0]->user_id, ‘shipping_postcode’ );3379 if ( isset( $user_shipping_postcode_temp[0] ) ) {3380 $user_shipping_postcode = $user_shipping_postcode_temp[0];3381 } else {3382 $user_shipping_postcode = '’;3383 }3384 $user_shipping_country_temp = get_user_meta( $results[0]->user_id, ‘shipping_country’ );3385 $user_shipping_country = '’;3386 if ( isset( $user_shipping_country_temp[0] ) ) {3387 $user_shipping_country = $user_shipping_country_temp[0];3388 if ( isset( $woocommerce->countries->countries[ $user_shipping_country ] ) ) {3389 $user_shipping_country = $woocommerce->countries->countries[ $user_shipping_country ];3390 } else {3391 $user_shipping_country = '’;3392 }3393 }3394 $user_shipping_state_temp = get_user_meta( $results[0]->user_id, ‘shipping_state’ );3395 $user_shipping_state = '’;3396 if ( isset( $user_shipping_state_temp[0] ) ) {3397 $user_shipping_state = $user_shipping_state_temp[0];3398 if ( isset( $woocommerce->countries->states[ $user_shipping_country_temp[0] ][ $user_shipping_state ] ) ) {3399 // code…3400 $user_shipping_state = $woocommerce->countries->states[ $user_shipping_country_temp[0] ][ $user_shipping_state ];3401 }3402 }3403 }34043405 $cart_details = array();3406 $cart_info = json_decode( $results[0]->abandoned_cart_info );3407 $cart_details = (array) $cart_info->cart;3408 $item_subtotal = 0;3409 $item_total = 0;34103411 if ( is_array( $cart_details ) && count( $cart_details ) > 0 ) {3412 foreach ( $cart_details as $k => $v ) {34133414 $item_details = wcal_common::wcal_get_cart_details( $v );34153416 $product_id = $v->product_id;3417 $product = wc_get_product( $product_id );3418 if ( ! $product ) { // product not found, exclude it from the cart display.3419 continue;3420 }3421 $prod_image = $product->get_image( array( 200, 200 ) );3422 $product_page_url = get_permalink( $product_id );3423 $product_name = $item_details[‘product_name’];3424 $item_subtotal = $item_details[‘item_total_formatted’];3425 $item_total = $item_details[‘item_total’];3426 $quantity_total = $item_details[‘qty’];34273428 $qty_item_text = 'item’;3429 if ( $quantity_total > 1 ) {3430 $qty_item_text = 'items’;3431 }3432 ?>3433 <tr>3434 <td> <?php echo $prod_image; // phpcs:ignore ?></td>3435 <td> <?php echo ‘<a href="’ . esc_url( $product_page_url ) . '"> ' . esc_html( $product_name ) . ' </a>’; ?> </td>3436 <td> <?php echo esc_html( $quantity_total ); ?></td>3437 <td> <?php echo esc_html( $item_subtotal ); ?></td>3438 <td> <?php echo esc_html( $item_total ); ?></td>3439 </tr>3440 <?php3441 $item_subtotal = 0;3442 $item_total = 0;3443 }3444 }3445 ?>3446 </table>3447 </div>3448 </div>3449 <div id="ac_order_customer_details" class="postbox" style="display:block">3450 <h3 class="details-title"> <p> <?php esc_html_e( 'Customer Details’, ‘woocommerce-abandoned-cart’ ); ?> </p> </h3>3451 <div class="inside" style="height: 300px;" >3452 <div id="order_data" class="panel">3453 <div style="width:50%;float:left">3454 <h3> <p> <?php esc_html_e( 'Billing Details’, ‘woocommerce-abandoned-cart’ ); ?> </p> </h3>3455 <p> <strong> <?php esc_html_e( 'Name:’, ‘woocommerce-abandoned-cart’ ); ?> </strong>3456 <?php echo esc_html( “$user_first_name $user_last_name” ); ?>3457 </p>3458 <p> <strong> <?php esc_html_e( 'Address:’, ‘woocommerce-abandoned-cart’ ); ?> </strong>3459 <?php3460 echo esc_html( $user_billing_company ) . ‘</br>’ .3461 esc_html( $user_billing_address_1 ) . ‘</br>’ .3462 esc_html( $user_billing_address_2 ) . ‘</br>’ .3463 esc_html( $user_billing_city ) . ‘</br>’ .3464 esc_html( $user_billing_postcode ) . ‘</br>’ .3465 esc_html( $user_billing_state ) . ‘</br>’ .3466 esc_html( $user_billing_country ) . '</br>’;3467 ?>3468 </p>3469 <p> <strong> <?php esc_html_e( 'Email:’, ‘woocommerce-abandoned-cart’ ); ?> </strong>3470 <?php $user_mail_to = ‘mailto:’ . $user_email; ?>3471 <a href=<?php echo esc_url( $user_mail_to ); ?>><?php echo esc_html( $user_email ); ?> </a>3472 </p>3473 <p> <strong> <?php esc_html_e( 'Phone:’, ‘woocommerce-abandoned-cart’ ); ?> </strong>3474 <?php echo esc_html( $user_billing_phone ); ?>3475 </p>3476 </div>3477 <div style="width:50%;float:right">3478 <h3> <p> <?php esc_html_e( 'Shipping Details’, ‘woocommerce-abandoned-cart’ ); ?> </p> </h3>3479 <p> <strong> <?php esc_html_e( 'Address:’, ‘woocommerce-abandoned-cart’ ); ?> </strong>3480 <?php3481 if ( ‘’ === $user_shipping_company &&3482 ‘’ === $user_shipping_address_1 &&3483 ‘’ === $user_shipping_address_2 &&3484 ‘’ === $user_shipping_city &&3485 ‘’ === $user_shipping_postcode &&3486 ‘’ === $user_shipping_state &&3487 ‘’ === $user_shipping_country ) {3488 echo esc_html_e( 'Shipping Address same as Billing Address’, ‘woocommerce-abandoned-cart’ );3489 } else {3490 ?>3491 <?php3492 echo esc_html( $user_shipping_company ) . ‘</br>’ .3493 esc_html( $user_shipping_address_1 ) . ‘</br>’ .3494 esc_html( $user_shipping_address_2 ) . ‘</br>’ .3495 esc_html( $user_shipping_city ) . ‘</br>’ .3496 esc_html( $user_shipping_postcode ) . ‘</br>’ .3497 esc_html( $user_shipping_state ) . ‘</br>’ .3498 esc_html( $user_shipping_country ) . '</br>’;3499 ?>3500 <br><br>3501 <strong><?php esc_html_e( 'Shipping Charges’, ‘woocommerce-abandoned-cart’ ); ?>: </strong>3502 <?php3503 if ( $shipping_charges > 0 ) {3504 echo wp_kses_post( $currency_symbol . $shipping_charges );3505 }3506 ?>3507 </p>3508 <?php } ?>3509 </div>3510 </div>3511 </div>3512 </div>3513 <?php3514 } elseif ( ‘report’ === $action ) {35153516 include_once 'includes/classes/class-wcal-product-report-table.php’;3517 $wcal_product_report_list = new WCAL_Product_Report_Table();3518 $wcal_product_report_list->wcal_product_report_prepare_items();3519 ?>3520 <div class="wrap">3521 <form id="wcal-sent-emails" method="get" >3522 <input type="hidden" name="page" value="woocommerce_ac_page" />3523 <input type="hidden" name="action" value="report" />3524 <?php $wcal_product_report_list->display(); ?>3525 </form>3526 </div>3527 <?php3528 }3529 }3530 echo( ‘</table>’ );35313532 $action = isset( $_GET[‘action’] ) ? sanitize_text_field( wp_unslash( $_GET[‘action’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification3533 $mode = isset( $_GET[‘mode’] ) ? sanitize_text_field( wp_unslash( $_GET[‘mode’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification35343535 $edit_id = 0;3536 if ( ‘emailtemplates’ === $action && ( ‘addnewtemplate’ === $mode || ‘edittemplate’ === $mode ) ) {3537 if ( ‘edittemplate’ === $mode ) {3538 $results = array();3539 if ( isset( $_GET[‘id’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification3540 $edit_id = sanitize_text_field( wp_unslash( $_GET[‘id’] ) ); // phpcs:ignore WordPress.Security.NonceVerification3541 $results = $wpdb->get_results( // phpcs:ignore3542 $wpdb->prepare(3543 ‘SELECT wpet . * FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` AS wpet WHERE id = %d’,3544 $edit_id3545 )3546 );3547 }3548 }3549 $active_post = ( empty( $_POST[‘is_active’] ) ) ? ‘0’ : '1’; // phpcs:ignore WordPress.Security.NonceVerification3550 ?>3551 <div id="content">3552 <form method="post" action="admin.php?page=woocommerce_ac_page&action=emailtemplates" id="ac_settings">3553 <input type="hidden" name="mode" value="<?php echo esc_html( $mode ); ?>" />3554 <?php3555 $id_by = isset( $_GET[‘id’] ) ? sanitize_text_field( wp_unslash( $_GET[‘id’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification3556 ?>3557 <input type="hidden" name="id" value="<?php echo esc_html( $id_by ); ?>" />3558 <?php3559 if ( ‘edittemplate’ === $mode ) {3560 print '<input type="hidden" name="ac_settings_frm" value="update">’;3561 $display_message = 'Edit Email Template’;3562 } else {3563 print '<input type="hidden" name="ac_settings_frm" value="save">’;3564 $display_message = 'Add Email Template’;3565 }3566 ?>3567 <div id="poststuff">3568 <div> <!-- <div class="postbox" > -->3569 <h3 class="hndle"><?php esc_html_e( $display_message, ‘woocommerce-abandoned-cart’ ); // phpcs:ignore?></h3>3570 <div>3571 <?php3572 wc_get_template(3573 'html-rules-engine.php’,3574 array(3575 ‘rules’ => array(),3576 ‘match’ => 'all’,3577 ),3578 'woocommerce-abandoned-cart/’,3579 WCAL_PLUGIN_PATH . '/includes/templates/rules/’3580 );3581 ?>3582 <table class="form-table" id="addedit_template">3583 <tr>3584 <th>3585 <label for="woocommerce_ac_template_name"><b><?php esc_html_e( 'Template Name:’, ‘woocommerce-abandoned-cart’ ); ?></b></label>3586 </th>3587 <td>3588 <?php3589 $template_name = '’;3590 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->template_name ) ) {3591 $template_name = $results[0]->template_name;3592 }3593 print ‘<input type="text" name="woocommerce_ac_template_name" id="woocommerce_ac_template_name" class="regular-text" value="’ . esc_html( $template_name ) . '">’;3594 ?>3595 <img class="help_tip" width="16" height="16" data-tip=’<?php esc_html_e( ‘Enter a template name for reference’, ‘woocommerce-abandoned-cart’ ); ?>’ src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/help.png" />3596 </td>3597 </tr>35983599 <tr>3600 <th>3601 <label for="woocommerce_ac_email_subject"><b><?php esc_html_e( 'Subject:’, ‘woocommerce-abandoned-cart’ ); ?></b></label>3602 </th>3603 <td>3604 <?php3605 $subject_edit = '’;3606 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->subject ) ) {3607 $subject_edit = stripslashes( $results[0]->subject );3608 }3609 print ‘<input type="text" name="woocommerce_ac_email_subject" id="woocommerce_ac_email_subject" class="regular-text" value="’ . esc_html( $subject_edit ) . '">’;3610 ?>3611 <img class="help_tip" width="16" height="16" data-tip=’<?php esc_html_e( ‘Enter the subject that should appear in the email sent’, ‘woocommerce-abandoned-cart’ ); ?>’ src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/help.png" />3612 </td>3613 </tr>36143615 <tr>3616 <th>3617 <label for="woocommerce_ac_email_body"><b><?php esc_html_e( 'Email Body:’, ‘woocommerce-abandoned-cart’ ); ?></b></label>3618 </th>3619 <td>3620 <?php3621 $initial_data = '’;3622 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->body ) ) {3623 $initial_data = stripslashes( $results[0]->body );3624 }36253626 $initial_data = str_replace( 'My document title’, '’, $initial_data );3627 wp_editor(3628 $initial_data,3629 'woocommerce_ac_email_body’,3630 array(3631 ‘media_buttons’ => true,3632 ‘textarea_rows’ => 15,3633 ‘tabindex’ => 4,3634 ‘tinymce’ => array(3635 ‘theme_advanced_buttons1’ => 'bold,italic,underline,|,bullist,numlist,blockquote,|,link,unlink,|,spellchecker,fullscreen,|,formatselect,styleselect’,3636 ),3637 )3638 );36393640 ?>3641 <?php echo wp_kses_post( stripslashes( get_option( ‘woocommerce_ac_email_body’ ) ) ); ?>3642 <span class="description">3643 <?php3644 esc_html_e( 'Message to be sent in the reminder email.’, ‘woocommerce-abandoned-cart’ );3645 ?>3646 <img width="16" height="16" src="<?php echo esc_url( plugins_url() ); ?>/woocommerce-abandoned-cart/assets/images/information.png" onClick="wcal_show_help_tips()“/>3647 </span>3648 <span id="help_message” style="display:none">3649 1. You can add customer & cart information in the template using this icon <img width="20" height="20" src="<?php echo esc_url( plugins_url( '/assets/images/ac_editor_icon.png’, __FILE__ ) ); ?>" /> in top left of the editor.<br>3650 2. The product information/cart contents table will be added in emails using the {{products.cart}} merge field.<br>3651 3. Insert/Remove any of the new shortcodes that have been included for the default template.<br>3652 4. Change the look and feel of the table by modifying the table style properties using CSS in “Text” mode. <br>3653 5. Change the text color of the table rows by using the Toolbar of the editor. <br>36543655 </span>3656 </td>3657 </tr>3658 <script type="text/javascript">3659 function wcal_show_help_tips() {3660 if ( jQuery( ‘#help_message’ ) . css( ‘display’ ) == ‘none’) {3661 document.getElementById( “help_message” ).style.display = “block";3662 }3663 else {3664 document.getElementById( “help_message” ) . style.display = “none";3665 }3666 }3667 </script>36683669 <tr>3670 <th>3671 <label for="is_wc_template"><b><?php esc_html_e( 'Use WooCommerce Template Style:’, ‘woocommerce-abandoned-cart’ ); ?></b></label>3672 </th>3673 <td>3674 <?php3675 $is_wc_template = '’;3676 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->is_wc_template ) ) {3677 $use_wc_template = $results[0]->is_wc_template;36783679 if ( ‘1’ === $use_wc_template ) {3680 $is_wc_template = 'checked’;3681 } else {3682 $is_wc_template = '’;3683 }3684 }3685 print '<input type="checkbox” name="is_wc_template” id="is_wc_template" ' . esc_attr( $is_wc_template ) . '> </input>’;3686 ?>3687 <img class="help_tip" width="16" height="16" data-tip=’<?php esc_html_e( ‘Use WooCommerce default style template for abandoned cart reminder emails.’, ‘woocommerce’ ); ?>’ src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/help.png" /><a target = ‘_blank’ href= <?php echo esc_url( wp_nonce_url( admin_url( “?wcal_preview_woocommerce_mail=true&id=$edit_id” ), ‘woocommerce-abandoned-cart’ ) ); ?> >3688 Click here to preview </a>how the email template will look with WooCommerce Template Style enabled. Alternatively, if this is unchecked, the template will appear as <a target = ‘_blank’ href=<?php echo esc_url( wp_nonce_url( admin_url( “?wcal_preview_mail=true&id=$edit_id” ), ‘woocommerce-abandoned-cart’ ) ); ?>>shown here</a>. <br> <strong>Note: </strong>When this setting is enabled, then “Send From This Name:” & “Send From This Email Address:” will be overwritten with WooCommerce -> Settings -> Email -> Email Sender Options.3689 </td>3690 </tr>36913692 <tr>3693 <th>3694 <label for="wcal_wc_email_header"><b><?php esc_html_e( 'Email Template Header Text: ', ‘woocommerce-abandoned-cart’ ); ?></b></label>3695 </th>3696 <td>36973698 <?php36993700 $wcal_wc_email_header = '’;3701 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->wc_email_header ) ) {3702 $wcal_wc_email_header = $results[0]->wc_email_header;3703 }3704 if ( ‘’ === $wcal_wc_email_header ) {3705 $wcal_wc_email_header = 'Abandoned cart reminder’;3706 }3707 print ‘<input type="text" name="wcal_wc_email_header" id="wcal_wc_email_header" class="regular-text" value="’ . esc_html( $wcal_wc_email_header ) . '">’;3708 ?>3709 <img class="help_tip" width="16" height="16" data-tip=’<?php esc_html_e( ‘Enter the header which will appear in the abandoned WooCommerce email sent. This is only applicable when only used when “Use WooCommerce Template Style:” is checked.’, ‘woocommerce-abandoned-cart’ ); ?>’ src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/help.png" />3710 </td>3711 </tr>37123713 <tr>3714 <th>3715 <label for="woocommerce_ac_email_frequency"><b><?php esc_html_e( 'Send this email:’, ‘woocommerce-abandoned-cart’ ); ?></b></label>3716 </th>3717 <td>3718 <select name="email_frequency" id="email_frequency">3719 <?php3720 $frequency_edit = '’;3721 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->frequency ) ) {3722 $frequency_edit = $results[0]->frequency;3723 }3724 for ( $i = 1; $i < 60; $i++ ) {3725 printf(3726 “<option %s value=’%s’>%s</option>\n",3727 selected( $i, $frequency_edit, false ),3728 esc_attr( $i ),3729 esc_html( $i )3730 );3731 }3732 ?>3733 </select>37343735 <select name="day_or_hour” id="day_or_hour">3736 <?php3737 $days_or_hours_edit = '’;3738 if ( ‘edittemplate’ === $mode && count( $results ) > 0 && isset( $results[0]->day_or_hour ) ) {3739 $days_or_hours_edit = $results[0]->day_or_hour;3740 }3741 $days_or_hours = array(3742 ‘Minutes’ => 'Minute(s)',3743 ‘Days’ => 'Day(s)',3744 ‘Hours’ => 'Hour(s)',3745 );3746 foreach ( $days_or_hours as $k => $v ) {3747 printf(3748 “<option %s value=’%s’>%s</option>\n",3749 selected( $k, $days_or_hours_edit, false ),3750 esc_attr( $k ),3751 esc_html( $v )3752 );3753 }3754 ?>3755 </select>3756 <span class="description">3757 <?php esc_html_e( 'after cart is abandoned.’, ‘woocommerce-abandoned-cart’ ); ?>3758 </span>3759 </td>3760 </tr>3761 <?php include_once 'views/wcal-email-coupon.php’; ?>3762 <tr>3763 <th>3764 <label for="woocommerce_ac_email_preview"><b><?php esc_html_e( 'Send a test email to:’, ‘woocommerce-abandoned-cart’ ); ?></b></label>3765 </th>3766 <td>3767 <?php3768 $user = wp_get_current_user();3769 $admin_email = isset( $user->user_email ) ? $user->user_email : '’;3770 ?>3771 <input type="text” id="send_test_email" name="send_test_email" class="regular-text" value="<?php echo esc_attr( $admin_email ); ?>" >3772 <input type="button" value="Send a test email" id="preview_email" onclick="javascript:void(0);">3773 <img class="help_tip" width="16" height="16" data-tip=’<?php esc_html_e( ‘Enter the email id to which the test email needs to be sent.’, ‘woocommerce-abandoned-cart’ ); ?>’ src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/help.png" />3774 <br>3775 <img class="ajax_img" src="<?php echo esc_url( plugins_url( '/assets/images/ajax-loader.gif’, __FILE__ ) ); ?>" style="display:none;" />3776 <div id="preview_email_sent_msg" style="display:none;"></div>3777 </td>3778 </tr>3779 </table>3780 </div>3781 </div>3782 </div>3783 <p class="submit">3784 <?php3785 if ( ‘edittemplate’ === $mode ) {3786 ?>3787 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Update Changes’, ‘woocommerce-abandoned-cart’ ); ?>" />3788 <?php3789 } else {3790 ?>3791 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes’, ‘woocommerce-abandoned-cart’ ); ?>" />3792 <?php3793 }3794 ?>3795 </p>3796 </form>3797 </div>3798 <?php3799 }3800 }38013802 /**3803 * It will add the footer text for the plugin.3804 *3805 * @hook admin_footer_text3806 * @param string $footer_text Text.3807 * @return string $footer_text3808 * @since 1.03809 */3810 public function wcal_admin_footer_text( $footer_text ) {38113812 if ( isset( $_GET[‘page’] ) && ‘woocommerce_ac_page’ === $_GET[‘page’] ) { // phpcs:ignore WordPress.Security.NonceVerification3813 $footer_text = __( 'If you love <strong>Abandoned Cart Lite for WooCommerce</strong>, then please leave us a <a href="https://wordpress.org/support/plugin/woocommerce-abandoned-cart/reviews/?rate=5#new-post" target="_blank" class="ac-rating-link" data-rated="Thanks :)“>★★★★★</a> rating. Thank you in advance. :)', ‘woocommerce-abandoned-cart’ );3814 wc_enqueue_js(3815 “3816 jQuery( ‘a.ac-rating-link’ ).click( function() {3817 jQuery( this ).parent().text( jQuery( this ).data( ‘rated’ ) );3818 });3819 “3820 );3821 }3822 return $footer_text;3823 }38243825 /**3826 * It will sort the record for the product reports tab.3827 *3828 * @param array $unsort_array Unsorted array.3829 * @param string $order Order details.3830 * @return array $array3831 * @since 2.63832 */3833 public function bubble_sort_function( $unsort_array, $order ) {3834 $temp = array();3835 foreach ( $unsort_array as $key => $value ) {3836 $temp[ $key ] = $value; // concatenate something unique to make sure two equal weights don’t overwrite each other.3837 }3838 asort( $temp, SORT_NUMERIC ); // or ksort( $temp, SORT_NATURAL ); see paragraph above to understand why.38393840 if ( ‘desc’ === $order ) {3841 $array = array_reverse( $temp, true );3842 } elseif ( ‘asc’ === $order ) {3843 $array = $temp;3844 }3845 unset( $temp );3846 return $array;3847 }38483849 /**3850 * It will be called when we send the test email from the email edit page.3851 *3852 * @hook wp_ajax_wcal_preview_email_sent3853 * @since 1.03854 */3855 public function wcal_action_send_preview() {3856 ?>3857 <script type="text/javascript” >3858 jQuery( document ).ready( function( $ )3859 {3860 $( “table#addedit_template input#preview_email” ).click( function()3861 { 3862 emailVal = jQuery( ‘#send_test_email’ ).val();3863 const re = /^(([^<>()[\]\.,;:\s@\”]+(\.[^<>()[\]\.,;:\s@\”]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; 3864 if ( !re.test( emailVal ) ) { 3865 jQuery( ‘#preview_email_sent_msg’ ).html( '<?php echo esc_html__( ‘Please enter a valid email.’, ‘woocommerce-abandoned-cart’ ); ?>’ );3866 jQuery( ‘#preview_email_sent_msg’ ).show();3867 return false; 3868 }38693870 jQuery( ‘#preview_email_sent_msg’ ).hide();38713872 $( ‘.ajax_img’ ).show();3873 var email_body = '’;3874 if ( jQuery(“#wp-woocommerce_ac_email_body-wrap”).hasClass( “tmce-active” ) ) {3875 email_body = tinyMCE.get(‘woocommerce_ac_email_body’).getContent();3876 } else {3877 email_body = jQuery(‘#woocommerce_ac_email_body’).val();3878 }3879 var subject_email_preview = $( ‘#woocommerce_ac_email_subject’ ).val();3880 var body_email_preview = email_body;3881 var send_email_id = $( ‘#send_test_email’ ).val();3882 var is_wc_template = document.getElementById( “is_wc_template” ).checked;3883 var wc_template_header = $( ‘#wcal_wc_email_header’ ).val() != ‘’ ? $( ‘#wcal_wc_email_header’ ).val() : 'Abandoned cart reminder’;3884 var data = {3885 subject_email_preview: subject_email_preview,3886 body_email_preview : body_email_preview,3887 send_email_id : send_email_id,3888 is_wc_template : is_wc_template,3889 wc_template_header : wc_template_header,3890 action : 'wcal_preview_email_sent’3891 };38923893 // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php3894 $.post( ajaxurl, data, function( response ) {3895 $( ‘.ajax_img’ ).hide();3896 if ( ‘not sent’ == response ) {3897 $( “#preview_email_sent_msg” ).html( “Test email is not sent as the Email body is empty.” );3898 $( “#preview_email_sent_msg” ).fadeIn();3899 setTimeout( function(){$( “#preview_email_sent_msg” ).fadeOut();}, 4000 );3900 } else {3901 $( “#preview_email_sent_msg” ).html( “<img src=’<?php echo esc_url( plugins_url( '/assets/images/check.jpg’, __FILE__ ) ); ?>’> Email has been sent successfully.” );3902 $( “#preview_email_sent_msg” ).fadeIn();3903 setTimeout( function(){$( “#preview_email_sent_msg” ).fadeOut();}, 3000 );3904 }3905 });3906 });3907 });3908 </script>3909 <?php3910 }39113912 /**3913 * Ajax function used to add the details in the abandoned order3914 * popup view.3915 *3916 * @since 5.63917 */3918 public static function wcal_abandoned_cart_info() {3919 Wcal_Abandoned_Cart_Details::wcal_get_cart_detail_view( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification3920 die();3921 }39223923 /**3924 * Ajax function which will save the notice state as dismissed.3925 *3926 * @since 5.73927 */3928 public static function wcal_dismiss_admin_notice() {39293930 $notice_key = isset( $_POST[‘notice’] ) ? sanitize_text_field( wp_unslash( $_POST[‘notice’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification3931 if ( ‘’ !== $notice_key ) {3932 update_option( $notice_key, true );3933 }3934 die();3935 }39363937 /**3938 * It will update the template satus when we change the template active status from the email template list page.3939 *3940 * @hook wp_ajax_wcal_toggle_template_status3941 * @globals mixed $wpdb3942 * @since 4.43943 */3944 public static function wcal_toggle_template_status() {3945 global $wpdb;3946 $template_id = isset( $_POST[‘wcal_template_id’] ) ? sanitize_text_field( wp_unslash( $_POST[‘wcal_template_id’] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification3947 $current_template_status = isset( $_POST[‘current_state’] ) ? sanitize_text_field( wp_unslash( $_POST[‘current_state’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification39483949 if ( $template_id > 0 ) {3950 if ( ‘on’ === $current_template_status ) {3951 $get_selected_template_result = $wpdb->get_results( // phpcs:ignore3952 $wpdb->prepare(3953 ‘SELECT * FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d’,3954 $template_id3955 )3956 );3957 $email_frequncy = $get_selected_template_result[0]->frequency;3958 $email_day_or_hour = $get_selected_template_result[0]->day_or_hour;39593960 $wcal_updated = $wpdb->query( // phpcs:ignore3961 $wpdb->prepare(3962 ‘UPDATE `’ . $wpdb->prefix . 'ac_email_templates_lite` SET is_active = %d WHERE frequency = %s AND day_or_hour = %s’,3963 0,3964 $email_frequncy,3965 $email_day_or_hour3966 )3967 );39683969 if ( 1 === $wcal_updated ) {3970 $wcal_updated_get_id = $wpdb->get_results( // phpcs:ignore3971 $wpdb->prepare(3972 ‘SELECT id FROM `’ . $wpdb->prefix . 'ac_email_templates_lite` WHERE id != %d AND frequency = %s AND day_or_hour = %s’,3973 $template_id,3974 $email_frequncy,3975 $email_day_or_hour3976 )3977 );3978 $wcal_all_ids = '’;3979 foreach ( $wcal_updated_get_id as $wcal_updated_get_id_key => $wcal_updated_get_id_value ) {3980 // code…3981 if ( ‘’ === $wcal_all_ids ) {3982 $wcal_all_ids = $wcal_updated_get_id_value->id;3983 } else {3984 $wcal_all_ids = $wcal_all_ids . ‘,’ . $wcal_updated_get_id_value->id;3985 }3986 }3987 echo esc_html( ‘wcal-template-updated:’ . $wcal_all_ids );3988 }39893990 $active = '1’;3991 update_option( ‘wcal_template_’ . $template_id . '_time’, current_time( ‘timestamp’ ) ); // phpcs:ignore3992 } else {3993 $active = '0’;3994 }3995 $wpdb->query( // phpcs:ignore3996 $wpdb->prepare(3997 ‘UPDATE `’ . $wpdb->prefix . 'ac_email_templates_lite` SET is_active = %s WHERE id = %d’,3998 $active,3999 $template_id4000 )4001 );4002 }4003 wp_die();4004 }40054006 /**4007 * Set up from email address in emails sent by our plugin when WC template style is ON.4008 *4009 * @param str $wp_admin_address - From email address set up in WP.4010 * @param object $email - Email object.4011 * @param str $from_email - Email Address passed in.4012 *4013 * @since 5.13.04014 */4015 public static function wcal_from_address_for_emails( $wp_admin_address, $email, $from_email ) {4016 $from_address = ‘’ == $email->title ? get_option( ‘wcal_from_email’ ) : $wp_admin_address; // phpcs:ignore4017 return $from_address;4018 }40194020 /**4021 * Set up from name in emails sent by our plugin when WC template style is ON.4022 *4023 * @param str $wp_admin_name - From name set up in WP.4024 * @param object $email - Email object.4025 * @param str $from_name_default - Name passed in.4026 *4027 * @since 5.13.04028 */4029 public static function wcal_from_name_for_emails( $wp_admin_name, $email, $from_name_default ) {4030 $from_name = ‘’ == $email->title ? get_option( ‘wcal_from_name’ ) : $wp_admin_name; // phpcs:ignore4031 return $from_name;4032 }4033 /**4034 * It will replace the test email data with the static content.4035 *4036 * @since 1.04037 */4038 public function wcal_preview_email_sent() {4039 if ( isset( $_POST[‘body_email_preview’] ) && ‘’ !== $_POST[‘body_email_preview’] ) { // phpcs:ignore WordPress.Security.NonceVerification4040 $from_email_name = get_option( ‘wcal_from_name’ );4041 $reply_name_preview = get_option( ‘wcal_from_email’ );4042 $from_email_preview = get_option( ‘wcal_reply_email’ );4043 $subject_email_preview = isset( $_POST[‘subject_email_preview’] ) ? stripslashes( sanitize_text_field( wp_unslash( $_POST[‘subject_email_preview’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification4044 $subject_email_preview = convert_smilies( $subject_email_preview );4045 $subject_email_preview = str_ireplace( '{{customer.firstname}}’, 'John’, $subject_email_preview );4046 $body_email_preview = isset( $_POST[‘body_email_preview’] ) ? convert_smilies( wp_unslash( $_POST[‘body_email_preview’] ) ) : '’; // phpcs:ignore4047 $is_wc_template = isset( $_POST[‘is_wc_template’] ) ? sanitize_text_field( wp_unslash( $_POST[‘is_wc_template’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification4048 $wc_template_header = isset( $_POST[‘wc_template_header’] ) ? stripslashes( sanitize_text_field( wp_unslash( $_POST[‘wc_template_header’] ) ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification40494050 $body_email_preview = str_ireplace( '{{customer.firstname}}’, 'John’, $body_email_preview );4051 $body_email_preview = str_ireplace( '{{customer.firstname}}’, 'John’, $body_email_preview );4052 $body_email_preview = str_ireplace( '{{customer.lastname}}’, 'Doe’, $body_email_preview );4053 $body_email_preview = str_ireplace( '{{customer.fullname}}’, 'John Doe’, $body_email_preview );4054 $current_time_stamp = current_time( ‘timestamp’ ); // phpcs:ignore4055 $date_format = date_i18n( get_option( ‘date_format’ ), $current_time_stamp );4056 $time_format = date_i18n( get_option( ‘time_format’ ), $current_time_stamp );4057 $test_date = $date_format . ' ' . $time_format;4058 $body_email_preview = str_ireplace( '{{cart.abandoned_date}}’, $test_date, $body_email_preview );4059 $cart_url = wc_get_page_permalink( ‘cart’ );4060 $body_email_preview = str_ireplace( '{{cart.link}}’, $cart_url, $body_email_preview );4061 $body_email_preview = str_ireplace( '{{cart.unsubscribe}}’, ‘#’, $body_email_preview );4062 $wcal_price = wc_price( ‘100’ );4063 $wcal_total_price = wc_price( ‘200’ );4064 if ( class_exists( ‘WP_Better_Emails’ ) ) {4065 $headers = ‘From: ' . $from_email_name . ' <’ . $from_email_preview . ‘>’ . “\r\n";4066 $headers .= ‘Content-Type: text/html’ . “\r\n";4067 $headers .= 'Reply-To: ' . $reply_name_preview . ' ' . “\r\n";4068 $var = ‘<table width = 100%>4069 <tr> <td colspan="5"> <h3 style="text-align:center">’ . __( 'Your Shopping Cart’, ‘woocommerce-abandoned-cart’ ) . ‘</h3> </td></tr>4070 <tr align="center">4071 <th>’ . __( 'Item’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4072 <th>’ . __( 'Name’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4073 <th>’ . __( 'Quantity’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4074 <th>’ . __( 'Price’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4075 <th>’ . __( 'Line Subtotal’, ‘woocommerce-abandoned-cart’ ) . '</th>4076 </tr>4077 <tr align="center">4078 <td><img class="demo_img” width="42” height="42” src="’ . plugins_url( ‘/assets/images/shoes.jpg’, __FILE__ ) . ‘"/></td>4079 <td>’ . __( “Men’s Formal Shoes", ‘woocommerce-abandoned-cart’ ) . ‘</td>4080 <td>1</td>4081 <td>’ . $wcal_price . ‘</td>4082 <td>’ . $wcal_price . '</td>4083 </tr>4084 <tr align="center">4085 <td><img class="demo_img” width="42" height="42" src="’ . plugins_url( ‘/assets/images/handbag.jpg’, __FILE__ ) . ‘"/></td>4086 <td>’ . __( “Woman’s Hand Bags", ‘woocommerce-abandoned-cart’ ) . ‘</td>4087 <td>1</td>4088 <td>’ . $wcal_price . ‘</td>4089 <td>’ . $wcal_price . ‘</td>4090 </tr>4091 <tr align="center">4092 <td></td>4093 <td></td>4094 <td></td>4095 <td>’ . __( 'Cart Total:’, ‘woocommerce-abandoned-cart’ ) . ‘</td>4096 <td>’ . $wcal_total_price . ‘</td>4097 </tr>4098 </table>’;4099 } else {4100 $headers = ‘From: ' . $from_email_name . ' <’ . $from_email_preview . ‘>’ . “\r\n";4101 $headers .= ‘Content-Type: text/html’ . “\r\n";4102 $headers .= 'Reply-To: ' . $reply_name_preview . ' ' . “\r\n";4103 $var = ‘<h3 style="text-align:center">’ . __( 'Your Shopping Cart’, ‘woocommerce-abandoned-cart’ ) . '</h3>4104 <table border="0” cellpadding="10” cellspacing="0” class="templateDataTable">4105 <tr align="center">4106 <th>’ . __( 'Item’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4107 <th>’ . __( 'Name’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4108 <th>’ . __( 'Quantity’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4109 <th>’ . __( 'Price’, ‘woocommerce-abandoned-cart’ ) . ‘</th>4110 <th>’ . __( 'Line Subtotal’, ‘woocommerce-abandoned-cart’ ) . '</th>4111 </tr>4112 <tr align="center">4113 <td><img class="demo_img” width="42" height="42" src="’ . plugins_url( ‘/assets/images/shoes.jpg’, __FILE__ ) . ‘"/></td>4114 <td>’ . __( “Men’s Formal Shoes", ‘woocommerce-abandoned-cart’ ) . ‘</td>4115 <td>1</td>4116 <td>’ . $wcal_price . ‘</td>4117 <td>’ . $wcal_price . '</td>4118 </tr>4119 <tr align="center">4120 <td><img class="demo_img” width="42" height="42" src="’ . plugins_url( '/assets/images/handbag.jpg’, __FILE__ ) . ‘"/></td>4121 <td>’ . __( “Woman’s Hand Bags", ‘woocommerce-abandoned-cart’ ) . ‘</td>4122 <td>1</td>4123 <td>’ . $wcal_price . ‘</td>4124 <td>’ . $wcal_price . ‘</td>4125 </tr>4126 <tr align="center">4127 <td></td>4128 <td></td>4129 <td></td>4130 <td>’ . __( 'Cart Total:’, ‘woocommerce-abandoned-cart’ ) . ‘</td>4131 <td>’ . $wcal_total_price . '</td>4132 </tr>4133 </table>’;4134 }4135 $body_email_preview = str_ireplace( '{{products.cart}}’, $var, $body_email_preview );4136 if ( isset( $_POST[‘send_email_id’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification4137 $to_email_preview = sanitize_text_field( wp_unslash( $_POST[‘send_email_id’] ) ); // phpcs:ignore WordPress.Security.NonceVerification4138 } else {4139 $to_email_preview = '’;4140 }4141 $user_email_from = get_option( ‘admin_email’ );4142 $body_email_final_preview = stripslashes( $body_email_preview );41434144 if ( isset( $is_wc_template ) && ‘true’ === $is_wc_template ) {4145 ob_start();4146 // Get email heading.4147 wc_get_template( 'emails/email-header.php’, array( ‘email_heading’ => $wc_template_header ) );4148 $email_body_template_header = ob_get_clean();41494150 ob_start();4151 wc_get_template( ‘emails/email-footer.php’ );4152 $email_body_template_footer = ob_get_clean();41534154 $final_email_body = $email_body_template_header . $body_email_final_preview . $email_body_template_footer;41554156 $site_title = get_bloginfo( ‘name’ );4157 $email_body_template_footer = str_ireplace( '{site_title}’, $site_title, $email_body_template_footer );41584159 wc_mail( $to_email_preview, $subject_email_preview, $final_email_body, $headers );4160 } else {4161 wp_mail( $to_email_preview, $subject_email_preview, stripslashes( $body_email_preview ), $headers );4162 }4163 echo 'email sent’;4164 die();4165 } else {4166 echo 'not sent’;4167 die();4168 }4169 }41704171 /**4172 * Return the coupon settings in the template.4173 *4174 * @return $coupon_code_options - Coupon code settings.4175 */4176 public static function wcal_coupon_options() {41774178 $coupon_expiry = '’;4179 if ( isset( $_POST[‘wcal_coupon_expiry’] ) && ‘’ !== $_POST[‘wcal_coupon_expiry’] ) { // phpcs:ignore WordPress.Security.NonceVerification4180 $coupon_expiry = sanitize_text_field( wp_unslash( $_POST[‘wcal_coupon_expiry’] ) ); // phpcs:ignore WordPress.Security.NonceVerification4181 }41824183 if ( isset( $_POST[‘expiry_day_or_hour’] ) && ‘’ !== $_POST[‘expiry_day_or_hour’] ) { // phpcs:ignore WordPress.Security.NonceVerification4184 $expiry_day_or_hour = sanitize_text_field( wp_unslash( $_POST[‘expiry_day_or_hour’] ) ); // phpcs:ignore WordPress.Security.NonceVerification4185 }4186 $coupon_expiry = $coupon_expiry . '-' . $expiry_day_or_hour;41874188 $discount_shipping = isset( $_POST[‘wcal_allow_free_shipping’] ) && ‘’ !== $_POST[‘wcal_allow_free_shipping’] ? ‘yes’ : 'off’; // phpcs:ignore WordPress.Security.NonceVerification4189 $individual_use = empty( $_POST[‘individual_use’] ) ? ‘0’ : '1’; // phpcs:ignore WordPress.Security.NonceVerification4190 $discount_type = isset( $_POST[‘wcal_discount_type’] ) && ‘’ !== $_POST[‘wcal_discount_type’] ? sanitize_text_field( wp_unslash( $_POST[‘wcal_discount_type’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification4191 $coupon_amount = isset( $_POST[‘wcal_coupon_amount’] ) && ‘’ !== $_POST[‘wcal_coupon_amount’] ? sanitize_text_field( wp_unslash( $_POST[‘wcal_coupon_amount’] ) ) : '’; // phpcs:ignore WordPress.Security.NonceVerification41924193 $coupon_code_options = array(4194 ‘discount_type’ => $discount_type,4195 ‘coupon_amount’ => $coupon_amount,4196 ‘coupon_expiry’ => $coupon_expiry,4197 ‘discount_shipping’ => $discount_shipping,4198 ‘individual_use’ => $individual_use,4199 );42004201 return $coupon_code_options;4202 }4203 /**4204 * It will search for the coupon code. It is called on the add / edit template page.4205 *4206 * @hook wp_ajax_wcal_json_find_coupons4207 * @param string $x - coupon code string.4208 * @param array $post_types Post type which we want to search.4209 * @since 5.11.0.4210 */4211 public function wcal_json_find_coupons( $x = '’, $post_types = array( ‘shop_coupon’ ) ) {4212 check_ajax_referer( 'search-products’, ‘security’ );4213 $term = (string) urldecode( stripslashes( wp_strip_all_tags( wp_unslash( $_GET[‘term’] ) ) ) ); //phpcs:ignore4214 if ( empty( $term ) ) {4215 die();4216 }4217 if ( is_numeric( $term ) ) {4218 $args = array(4219 ‘post_type’ => $post_types,4220 ‘post_status’ => 'publish’,4221 ‘posts_per_page’ => -1,4222 ‘post__in’ => array( 0, $term ),4223 ‘fields’ => 'ids’,4224 );4225 $args2 = array(4226 ‘post_type’ => $post_types,4227 ‘post_status’ => 'publish’,4228 ‘posts_per_page’ => -1,4229 ‘post_parent’ => $term,4230 ‘fields’ => 'ids’,4231 );4232 $args3 = array(4233 ‘post_type’ => $post_types,4234 ‘post_status’ => 'publish’,4235 ‘posts_per_page’ => -1,4236 ‘meta_query’ => array( // phpcs:ignore4237 array(4238 ‘key’ => '_sku’,4239 ‘value’ => $term,4240 ‘compare’ => 'LIKE’,4241 ),4242 ),4243 ‘fields’ => 'ids’,4244 );4245 $posts = array_unique( array_merge( get_posts( $args ), get_posts( $args2 ), get_posts( $args3 ) ) );4246 } else {4247 $args = array(4248 ‘post_type’ => $post_types,4249 ‘post_status’ => 'publish’,4250 ‘posts_per_page’ => -1,4251 ‘s’ => $term,4252 ‘fields’ => 'ids’,4253 );4254 $args2 = array(4255 ‘post_type’ => $post_types,4256 ‘post_status’ => 'publish’,4257 ‘posts_per_page’ => -1,4258 ‘meta_query’ => array( // phpcs:ignore4259 array(4260 ‘key’ => '_sku’,4261 ‘value’ => $term,4262 ‘compare’ => 'LIKE’,4263 ),4264 ),4265 ‘fields’ => 'ids’,4266 );4267 $posts = array_unique( array_merge( get_posts( $args ), get_posts( $args2 ) ) );4268 }4269 $found_products = array();4270 if ( $posts ) {4271 foreach ( $posts as $post ) {4272 $sku = get_post_meta( $post, '_sku’, true );4273 $wcal_product_sku = apply_filters( ‘wcal_product_sku’, $sku );4274 if ( false !== $wcal_product_sku && ‘’ !== $wcal_product_sku ) {4275 if ( isset( $sku ) && $sku ) {4276 $sku = ' ( SKU: ' . $sku . ' )‘;4277 }4278 $found_products[ $post ] = get_the_title( $post ) . ' – #’ . $post . $sku;4279 } else {4280 $found_products[ $post ] = get_the_title( $post ) . ' – #’ . $post;4281 }4282 }4283 }4284 echo wp_json_encode( $found_products );4285 die();4286 }42874288 /**4289 * Callback for Coupon settings section.4290 */4291 public static function ac_lite_coupon_callback() {}42924293 /**4294 * Option for deleting the plugin data upon uninstall.4295 *4296 * @param array $args Argument for adding field details.4297 * @since 8.34298 */4299 public static function wcal_deleting_coupon_data( $args ) {4300 $wcal_delete_coupon_data = get_option( 'wcal_delete_coupon_data’, ‘’ );4301 if ( isset( $wcal_delete_coupon_data ) && ‘’ === $wcal_delete_coupon_data ) {4302 $wcal_delete_coupon_data = 'off’;4303 wp_clear_scheduled_hook( ‘woocommerce_ac_delete_coupon_action’ );4304 } else {4305 if ( ! wp_next_scheduled( ‘woocommerce_ac_delete_coupon_action’ ) ) {4306 wp_schedule_event( time(), 'wcal_15_days’, ‘woocommerce_ac_delete_coupon_action’ );4307 }4308 }43094310 ?>4311 <input type="checkbox” id="wcal_delete_coupon_data" name="wcal_delete_coupon_data" value="on" <?php echo checked( 'on’, $wcal_delete_coupon_data, false ); ?> />4312 <label for="wcal_delete_coupon_data"> <?php echo esc_attr( $args[0] ); ?></label>4313 <a >4314 <?php4315 }4316 /**4317 * It will delete the expired and used coupon codes.4318 *4319 * @hook wp_ajax_wcal_change_manual_email_data4320 * @since: 5.11.04321 */4322 public static function wcal_delete_expired_used_coupon_code() {43234324 global $wpdb;4325 if ( ! current_user_can( ‘manage_options’ ) && ! wp_verify_nonce( sanitize_key( $_POST[‘ajax_nonce’] ), ‘delete_expired_used_coupon_code’ ) ) { //phpcs:ignore4326 wp_send_json_error();4327 }43284329 $expired_coupons = self::wcal_fetch_expired_coupons();4330 $used_coupons = self::wcal_fetch_used_coupons();4331 $coupons = array_unique( array_merge( $expired_coupons, $used_coupons ) );4332 $coupon_count = count( $coupons );43334334 if ( $coupon_count ) {4335 $coupons_ids = implode( ',’, $coupons );4336 $wpdb->query( “DELETE FROM {$wpdb->postmeta} WHERE post_id IN(" . $coupons_ids . ')' );//phpcs:ignore4337 $wpdb->query( “DELETE FROM {$wpdb->posts} WHERE ID IN(" . $coupons_ids . ')' );//phpcs:ignore4338 }43394340 // translators: %1$s: Coupons Deleted, %2$s: Deleted coupons count’.4341 wp_send_json_success( sprintf( __( '%1$s: %2$d’, ‘woo-cart-abandonment-recovery’ ), 'Coupons Deleted’, $coupon_count ) );4342 }43434344 /**4345 * Coupon deletion manual button.4346 *4347 * @param array $args - Arguments for the setting.4348 */4349 public static function wcal_deleting_coupon_data_manually( $args ) {4350 ?>4351 <input type="button” class="button-secondary” id="wcal_delete_coupons" value="<?php esc_html_e( 'Delete’, ‘woocommerce-ac’ ); ?>" >4352 <label> <?php echo esc_attr( $args[0] ); ?></label>4353 <br>4354 <span class="wcal-spinner" style="display:none;">4355 <img class="ajax_img" src="<?php echo esc_attr( WCAL_PLUGIN_URL . ‘/assets/images/ajax-loader.gif’ ); ?>" />4356 </span>4357 <span class="wcal-coupon-response-msg"></span>4358 <?php4359 }4360 /**4361 * It will fetch all expired coupons4362 *4363 * @hook wp_ajax_wcal_change_manual_email_data.4364 * @since: 5.114365 */4366 public static function wcal_fetch_expired_coupons() {4367 $coupon_ids = array();43684369 $args = array(4370 ‘posts_per_page’ => -1,4371 ‘post_type’ => 'shop_coupon’,4372 ‘post_status’ => 'publish’,4373 ‘meta_query’ => array( //phpcs:ignore4374 ‘relation’ => 'AND’,4375 array(4376 ‘key’ => 'date_expires’,4377 ‘value’ => strtotime( ‘today’ ),4378 ‘compare’ => '<=’,4379 ),4380 array(4381 ‘key’ => 'date_expires’,4382 ‘value’ => '’,4383 ‘compare’ => '!=’,4384 ),4385 array(4386 ‘key’ => 'wcal_created_by’,4387 ‘value’ => 'wcal’,4388 ‘compare’ => '=’,4389 ),4390 ),4391 );43924393 $args = array(4394 ‘posts_per_page’ => -1,4395 ‘post_type’ => 'shop_coupon’,4396 ‘post_status’ => 'publish’,4397 ‘meta_query’ => array( // phpcs:ignore4398 ‘relation’ => 'AND’,4399 array(4400 ‘key’ => 'date_expires’,4401 ‘value’ => strtotime( ‘today’ ),4402 ‘compare’ => '<=’,4403 ),4404 array(4405 ‘key’ => 'date_expires’,4406 ‘value’ => '’,4407 ‘compare’ => '!=’,4408 ),4409 array(4410 ‘key’ => 'wcal_created_by’,4411 ‘value’ => 'wcal’,4412 ‘compare’ => '=’,4413 ),4414 ),4415 );4416 $coupons = get_posts( $args );4417 if ( ! empty( $coupons ) ) {4418 $current_time = current_time( ‘timestamp’ ); // phpcs:ignore44194420 foreach ( $coupons as $coupon ) {4421 array_push( $coupon_ids, $coupon->ID );4422 }4423 }44244425 return $coupon_ids;4426 }44274428 /**4429 * It will fetch all used coupons.4430 *4431 * @hook wp_ajax_wcal_change_manual_email_data4432 * @since: 4.24433 */4434 public static function wcal_fetch_used_coupons() {44354436 $coupon_ids = array();4437 $args = array(4438 ‘posts_per_page’ => -1,4439 ‘post_type’ => 'shop_coupon’,4440 ‘post_status’ => 'publish’,4441 ‘meta_query’ => array( // phpcs:ignore4442 ‘relation’ => 'AND’,4443 array(4444 ‘key’ => 'usage_count’,4445 ‘value’ => 0,4446 ‘compare’ => '>’,4447 ),4448 array(4449 ‘key’ => 'wcal_created_by’,4450 ‘value’ => 'wcal’,4451 ‘compare’ => '=’,4452 ),4453 ),4454 );44554456 $coupons = get_posts( $args );4457 if ( ! empty( $coupons ) ) {4458 foreach ( $coupons as $coupon ) {4459 array_push( $coupon_ids, $coupon->ID );4460 }4461 }4462 return $coupon_ids;4463 }4464 /**4465 * It will create the cron job interval.4466 * Default value will be 15 minutes.4467 * If customer has changed the cron job interval time from the settings then it will be considered.4468 *4469 * @param array $schedules Array of all schedule events.4470 * @return array $schedule Array of new added schedule event.4471 * @since 5.04472 */4473 public static function wcal_add_cron_schedule( $schedules ) {4474 $duration = get_option( ‘wcal_cron_time_duration’ );4475 if ( isset( $duration ) && $duration > 0 ) {4476 $duration_in_seconds = $duration * 60;4477 } else {4478 $duration_in_seconds = 900;4479 }4480 $schedules[‘15_minutes’] = array(4481 ‘interval’ => $duration_in_seconds, // 15 minutes in seconds4482 ‘display’ => __( ‘Once Every Fifteen Minutes’ ),4483 );44844485 $schedules[‘wcal_15_days’] = array(4486 ‘interval’ => 1296000, // 15 days in seconds4487 ‘display’ => __( ‘Once Every Fifteen Days’ ),4488 );4489 return $schedules;4490 }44914492 /**4493 * Callback for Abandoned cart Coupon settings.4494 */4495 public static function wcal_coupon_callback() {4496 }44974498 /**4499 * Callback for GDPR settings section.4500 */4501 public static function ac_lite_gdpr_callback() {}4502 }4503}4504$woocommerce_abandon_cart = new woocommerce_abandon_cart_lite();
Related news
A critical security flaw has been disclosed in the WordPress "Abandoned Cart Lite for WooCommerce" plugin that's installed on more than 30,000 websites. "This vulnerability makes it possible for an attacker to gain access to the accounts of users who have abandoned their carts, who are typically customers but can extend to other high-level users when the right conditions are met," Defiant's
WordPress Abandoned Cart Lite for WooCommerce plugin versions 5.14.2 and below suffer from an authentication bypass vulnerability.
WordPress Abandoned Cart Lite for WooCommerce plugin versions 5.14.2 and below proof of concept authentication bypass exploit.