/** * Get the orders matching the conditions of the storewide email * @param FUE_Email $email * @return array */ private function get_orders_for_storewide_email($email) { $wpdb = Follow_Up_Emails::instance()->wpdb; $trigger = $email->trigger; $orders = array(); if ($trigger == 'cart') { // cart is an unsupported trigger return $orders; } if (in_array($email->trigger, $this->get_order_statuses())) { // count the number of orders matching the email's order status trigger // and exclude those Order IDs that are in the email queue, sent or unsent if (WC_FUE_Compatibility::is_wc_version_gte_2_2()) { $status = 'wc-' . $email->trigger; $orders = $wpdb->get_col($wpdb->prepare("SELECT ID\n FROM {$wpdb->posts} p\n WHERE p.post_status = %s\n AND (\n SELECT COUNT(id)\n FROM {$wpdb->prefix}followup_email_orders\n WHERE order_id = p.ID\n AND email_id = %d\n ) = 0", $status, $email->id)); } else { $excluded_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT order_id\n FROM {$wpdb->prefix}followup_email_orders\n WHERE order_id > 0\n AND email_id = %d", $email->id)); $orders = get_posts(array('post_status' => 'publish', 'tax_query' => array(array('taxonomy' => 'shop_order_status', 'field' => 'slug', 'terms' => $email->trigger)), 'post__not_in' => $excluded_ids, 'fields' => 'ids', 'posts_per_page' => -1)); } // filter out the orders that don't match the email's product or category filter if ($email->product_id) { $order_ids = implode(',', $orders); $orders = $wpdb->get_col($wpdb->prepare("SELECT order_id\n FROM {$wpdb->prefix}followup_order_items\n WHERE order_id IN ({$order_ids})\n AND (\n product_id = %d\n OR\n variation_id = %d\n )", $email->product_id, $email->product_id)); } if ($email->category_id) { $order_ids = implode(',', $orders); $orders = $wpdb->get_col($wpdb->prepare("SELECT order_id\n FROM {$wpdb->prefix}followup_order_categories\n WHERE order_id IN ({$order_ids})\n AND category_id = %d", $email->category_id)); } // remove orders with products/categories that are in the email exclusions list if (!empty($email->meta['excluded_categories'])) { foreach ($orders as $idx => $order_id) { if (in_array($order_id, $email->meta['excluded_categories'])) { unset($orders[$idx]); } } // reset the indices $orders = array_merge($orders, array()); } if (!empty($email->meta['excluded_customers_products'])) { // exclude orders from customers who have purchased any one of these products $product_ids = implode(',', $email->meta['excluded_customers_products']); foreach ($orders as $idx => $order_id) { $order = WC_FUE_Compatibility::wc_get_order($order_id); $user_id = WC_FUE_Compatibility::get_order_user_id($order); if ($user_id) { $customer = fue_get_customer($user_id); } else { $customer = fue_get_customer(0, $order->billing_email); } if (!$customer) { continue; } $sql = "SELECT COUNT(*)\n FROM {$wpdb->prefix}followup_order_items i\n WHERE o.followup_customer_id = %d\n AND o.order_id = i.order_id\n AND (\n i.product_id IN ( {$product_ids} )\n OR\n i.variation_id IN ( {$product_ids} )\n )"; $found = $wpdb->get_var($wpdb->prepare($sql, $customer->id)); if ($found > 0) { unset($orders[$idx]); } } } if (!empty($email->meta['excluded_customers_categories'])) { $product_ids = implode(',', $email->meta['excluded_customers_products']); foreach ($orders as $idx => $order_id) { $order = WC_FUE_Compatibility::wc_get_order($order_id); $user_id = WC_FUE_Compatibility::get_order_user_id($order); if ($user_id) { $customer = fue_get_customer($user_id); } else { $customer = fue_get_customer(0, $order->billing_email); } if (!$customer) { continue; } $sql = "SELECT COUNT(*)\n FROM {$wpdb->prefix}followup_order_items i, {$wpdb->prefix}followup_customer_orders o\n WHERE o.followup_customer_id = %d\n AND o.order_id = i.order_id\n AND (\n i.product_id IN ( {$product_ids} )\n OR\n i.variation_id IN ( {$product_ids} )\n )"; $found = $wpdb->get_var($wpdb->prepare($sql, $customer->id)); if ($found > 0) { unset($orders[$idx]); } } } } elseif ($trigger == 'first_purchase') { // get the order IDs of customers with only 1 order $customer_orders = $wpdb->get_col("SELECT order_id\n FROM {$wpdb->prefix}followup_customer_orders\n GROUP BY followup_customer_id\n HAVING COUNT(followup_customer_id) = 1"); if (count($customer_orders) > 0) { $queue_orders = $wpdb->get_col($wpdb->prepare("SELECT order_id\n FROM {$wpdb->prefix}followup_email_orders\n WHERE order_id IN (" . implode(',', $customer_orders) . ")\n AND email_id = %d", $email->id)); // exclude orders that are already in the queue foreach ($customer_orders as $customer_order) { if (!in_array($customer_order, $queue_orders)) { $orders[] = $customer_order; } } } } elseif ($trigger == 'product_purchase_above_one') { // Get the orders of customers with more than 1 order $customers = $wpdb->get_col("SELECT followup_customer_id\n FROM {$wpdb->prefix}followup_customer_orders\n GROUP BY followup_customer_id\n HAVING COUNT(followup_customer_id) > 1"); foreach ($customers as $customer_id) { $customer_orders = $wpdb->get_col($wpdb->prepare("SELECT order_id\n FROM {$wpdb->prefix}followup_customer_orders\n WHERE followup_customer_id = %d\n ORDER BY order_id ASC", $customer_id)); if (count($customer_orders) > 0) { // drop the customer's first order $customer_orders = array_slice($customer_orders, 1); $queue_orders = $wpdb->get_col($wpdb->prepare("SELECT order_id\n FROM {$wpdb->prefix}followup_email_orders\n WHERE order_id IN (" . implode(',', $customer_orders) . ")\n AND email_id = %d", $email->id)); // exclude orders that are already in the queue foreach ($customer_orders as $customer_order) { if (!in_array($customer_order, $queue_orders)) { $orders[] = $customer_order; } } } } } // Remove the orders that match the email's send_once property $email_meta = $email->meta; $adjust_date = false; if (!empty($email_meta)) { if (isset($email_meta['adjust_date']) && $email_meta['adjust_date'] == 'yes') { $adjust_date = true; } foreach ($orders as $idx => $order_id) { $order = WC_FUE_Compatibility::wc_get_order($order_id); // send email only once per customer if (isset($email_meta['one_time']) && $email_meta['one_time'] == 'yes') { $count_sent = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*)\n FROM {$wpdb->prefix}followup_email_orders\n WHERE `user_email` = %s\n AND `email_id` = %d", $order->billing_email, $email->id)); if ($count_sent > 0) { // do not send more of the same emails to this user unset($orders[$idx]); continue; } } // adjust date only applies to non-guest orders if ($adjust_date && $order->customer_user > 0) { // check for similar existing and unsent email orders // and adjust the date to send instead of inserting a duplicate row $similar_emails = $this->fue->scheduler->get_items(array('email_id' => $email->id, 'user_id' => $order->customer_user, 'product_id' => $email->product_id, 'is_cart' => 0, 'is_sent' => 0)); if (count($similar_emails) > 0) { unset($orders[$idx]); continue; } } } // reset the indices $orders = array_values($orders); } return $orders; }
/** * Add to queue all 'last purchased' emails * * @param WC_Order $order * @return array */ protected function queue_customer_last_purchased_emails($order) { $wpdb = Follow_Up_Emails::instance()->wpdb; $scheduler = Follow_Up_Emails::instance()->scheduler; $order_status = WC_FUE_Compatibility::get_order_status($order); $queued = array(); // If the order is a renewal order, switch to the parent order if ($this->is_subscription_renewal_order($order)) { $order = WC_FUE_Compatibility::wc_get_order($order->post->post_parent); } if ($order && ($order_status == 'processing' || $order_status == 'completed')) { $order_user_id = WC_FUE_Compatibility::get_order_user_id($order); $recipient = $order_user_id > 0 ? $order_user_id : $order->billing_email; // if there are any "last purchased" emails, automatically add this order to the queue $emails = fue_get_emails('customer', FUE_Email::STATUS_ACTIVE, array('meta_query' => array(array('key' => '_interval_type', 'value' => 'after_last_purchase')))); foreach ($emails as $email) { // look for unsent emails in the queue with the same email ID $queued_emails = $scheduler->get_items(array('is_sent' => 0, 'email_id' => $email->id)); // loop through the queue and delete unsent entries with identical customers foreach ($queued_emails as $queue) { if ($queue->user_id > 0 && $order_user_id > 0 && $queue->user_id == $order_user_id) { $scheduler->delete_item($queue->id); } elseif ($order_user_id > 0 && $queue->order_id > 0) { $queue_order_id = get_post_meta($queue->order_id, '_customer_user', true); if ($queue_order_id == $order_user_id) { $scheduler->delete_item($queue->id); } } else { // try to match the email address $email_address = get_post_meta($queue->order_id, '_billing_email', true); if ($email_address == $order->billing_email) { $scheduler->delete_item($queue->id); } } } // add this email to the queue $insert = array('send_on' => $email->get_send_timestamp(), 'email_id' => $email->id, 'product_id' => 0, 'order_id' => $order->id); if (!is_wp_error(FUE_Sending_Scheduler::queue_email($insert, $email))) { $queued[] = $insert; } } } return $queued; }
/** * Get the FUE Customer based on user ID or email address used in the $order * * @param int|WC_Order $order * @return object * @since 4.1 */ function fue_get_customer_from_order($order) { if (is_numeric($order)) { $order = WC_FUE_Compatibility::wc_get_order($order); } return fue_get_customer(WC_FUE_Compatibility::get_order_user_id($order), $order->billing_email); }
/** * Send emails that matches the provided triggers to the queue * @param int $booking_id * @param array $triggers */ private function create_email_order($booking_id, $triggers = array()) { /** * @var $booking WC_Booking * @var $order WC_Order */ $booking = get_wc_booking($booking_id); $last_status = get_post_meta($booking_id, '_last_status', true); $order = WC_FUE_Compatibility::wc_get_order($booking->order_id); $emails = fue_get_emails('wc_bookings', FUE_Email::STATUS_ACTIVE, array('meta_query' => array(array('key' => '_interval_type', 'value' => $triggers, 'compare' => 'IN')))); foreach ($emails as $email) { if (!empty($email->meta['bookings_last_status']) && $email->meta['bookings_last_status'] != $last_status) { continue; } if ($this->is_category_excluded($booking, $email)) { continue; } // A booking can have no order linked to it if ($order) { $customer = fue_get_customer_from_order($order); if (Follow_Up_Emails::instance()->fue_wc->wc_scheduler->exclude_customer_based_on_purchase_history($customer, $email)) { continue; } } if ($email->interval_type == 'before_booking_event') { $start = strtotime(get_post_meta($booking_id, '_booking_start', true)); $time = FUE_Sending_Scheduler::get_time_to_add($email->interval_num, $email->interval_duration); $send_on = $start - $time; } elseif ($email->interval_type == 'after_booking_event') { $start = strtotime(get_post_meta($booking_id, '_booking_end', true)); $time = FUE_Sending_Scheduler::get_time_to_add($email->interval_num, $email->interval_duration); $send_on = $start + $time; } else { $send_on = $email->get_send_timestamp(); } $insert = array('send_on' => $send_on, 'email_id' => $email->id, 'product_id' => $booking->product_id, 'order_id' => $booking->order_id, 'meta' => array('booking_id' => $booking_id)); if ($order) { $user_id = WC_FUE_Compatibility::get_order_user_id($order); if ($user_id) { $user = new WP_User($user_id); $insert['user_id'] = $user_id; $insert['user_email'] = $user->user_email; } } // Remove the nonce to avoid infinite loop because doing a // remove_action on WC_Bookings_Details_Meta_Box doesnt work unset($_POST['wc_bookings_details_meta_box_nonce']); if (!is_wp_error(FUE_Sending_Scheduler::queue_email($insert, $email))) { // Tell FUE that an email order has been created // to stop it from sending storewide emails if (!defined('FUE_ORDER_CREATED')) { define('FUE_ORDER_CREATED', true); } } } }
/** * Add needed data to $email_data depending on the email type * * @param array $email_data * @param object $queue_item * @param FUE_Email $email * * @return array */ public function add_to_email_data($email_data, $queue_item, $email) { global $wpdb; if (!$queue_item->order_id) { return $email_data; } // order $order = WC_FUE_Compatibility::wc_get_order($queue_item->order_id); if (WC_FUE_Compatibility::get_order_user_id($order) > 0) { $email_data['user_id'] = WC_FUE_Compatibility::get_order_user_id($order); if ($email_data['user_id']) { $wp_user = new WP_User($email_data['user_id']); $email_data['username'] = $wp_user->user_login; } } $email_data['email_to'] = $order->billing_email; $email_data['first_name'] = $order->billing_first_name; $email_data['last_name'] = $order->billing_last_name; $email_data['cname'] = $email_data['first_name'] . ' ' . $email_data['last_name']; return $email_data; }