796 lines
32 KiB
PHP
796 lines
32 KiB
PHP
<?php
|
|
|
|
namespace FluentCrm\App\Hooks\Handlers;
|
|
|
|
|
|
use FluentCrm\App\Models\Subscriber;
|
|
use FluentCrm\App\Services\Helper;
|
|
|
|
/**
|
|
* PurchaseHistory Class
|
|
*
|
|
* @package FluentCrm\App\Hooks
|
|
*
|
|
* @version 1.0.0
|
|
*/
|
|
class PurchaseHistory
|
|
{
|
|
/**
|
|
* Build the commerce summary widget for supported commerce providers.
|
|
*/
|
|
public function getCommerceStatWidget($subscriber)
|
|
{
|
|
/**
|
|
* Determine the commerce provider for the purchase history in FluentCRM.
|
|
*
|
|
* This filter allows you to modify the commerce provider used in FluentCRM.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @param string $commerceProvider The current commerce provider.
|
|
* @return string The modified commerce provider.
|
|
*/
|
|
$commerceProvider = apply_filters('fluentcrm_commerce_provider', '');
|
|
|
|
if ($commerceProvider) {
|
|
/**
|
|
* Determine the purchase statistics for a specific commerce provider for a specific subscriber in FluentCRM.
|
|
*
|
|
* The dynamic portion of the hook name, `$commerceProvider`, refers to the specific commerce provider.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @param array $stats An array of purchase statistics.
|
|
* @param int $subscriber->id The ID of the subscriber.
|
|
*/
|
|
$stats = apply_filters('fluent_crm/contact_purchase_stat_' . $commerceProvider, [], $subscriber->id);
|
|
if (!$stats) {
|
|
return false;
|
|
}
|
|
|
|
$html = '<ul class="fc_full_listed fcrm_customer_summary_list">';
|
|
foreach ($stats as $stat) {
|
|
$html .= '<li><span class="fc_list_sub">' . $stat['title'] . '</span> <span class="fc_list_value">' . $stat['value'] . '</span></li>';
|
|
}
|
|
$html .= '</ul>';
|
|
|
|
return [
|
|
'title' => __('Customer Summary', 'fluent-crm'),
|
|
'content' => $html
|
|
];
|
|
}
|
|
|
|
if (defined('WC_PLUGIN_FILE')) {
|
|
$summary = $this->getWooCustomerSummary($subscriber);
|
|
if ($summary) {
|
|
return [
|
|
'title' => __('Customer Summary', 'fluent-crm'),
|
|
'content' => $summary
|
|
];
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (Helper::isEdd3()) {
|
|
|
|
$customer = fluentCrmDb()->table('edd_customers')
|
|
->where('email', $subscriber->email);
|
|
if ($subscriber->user_id) {
|
|
$customer = $customer->orWhere('user_id', $subscriber->user_id);
|
|
}
|
|
$customer = $customer->first();
|
|
if (!$customer) {
|
|
return false;
|
|
}
|
|
|
|
$summaryData = [
|
|
'order_count' => $customer->purchase_count,
|
|
'lifetime_value' => number_format($customer->purchase_value, 2),
|
|
'avg_value' => ($customer->purchase_count) ? round($customer->purchase_value / $customer->purchase_count, 2) : 'n/a',
|
|
'stat_avg_count' => 0,
|
|
'stat_avg_spend' => 0,
|
|
'stat_avg_value' => 0,
|
|
'currency_sign' => edd_currency_symbol(),
|
|
'first_order_date' => $customer->date_created
|
|
];
|
|
|
|
$html = $this->formatSummaryData($summaryData, true);
|
|
|
|
return [
|
|
'title' => __('Customer Summary', 'fluent-crm'),
|
|
'content' => $html
|
|
];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function wooOrders($data, $subscriber)
|
|
{
|
|
if (!defined('WC_PLUGIN_FILE')) {
|
|
return $data;
|
|
}
|
|
|
|
$hasRecount = defined('FLUENTCAMPAIGN') && \FluentCampaign\App\Services\Commerce\Commerce::isEnabled('woo');
|
|
|
|
$app = fluentCrm();
|
|
|
|
if ($hasRecount && $app->request->get('will_recount') == 'yes') {
|
|
(new \FluentCampaign\App\Services\Integrations\WooCommerce\DeepIntegration)->syncCustomerBySubscriber($subscriber);
|
|
}
|
|
|
|
$page = (int)$app->request->get('page', 1);
|
|
$per_page = (int)$app->request->get('per_page', 10);
|
|
|
|
$sort_by = sanitize_sql_orderby($app->request->get('sort_by', 'id'));
|
|
$sort_type = sanitize_sql_orderby($app->request->get('sort_type', 'DESC'));
|
|
|
|
$valid_columns = ['id', 'date_created', 'total_amount'];
|
|
$valid_directions = ['ASC', 'DESC'];
|
|
|
|
if (!in_array($sort_by, $valid_columns)) {
|
|
$sort_by = 'id';
|
|
}
|
|
if (!in_array(strtoupper($sort_type), $valid_directions)) {
|
|
$sort_type = 'DESC';
|
|
}
|
|
|
|
$orders = $this->getWooOrders($subscriber, $sort_by, $sort_type);
|
|
$totalOrders = count($orders);
|
|
$orders = array_slice($orders, ($page - 1) * $per_page, $per_page);
|
|
|
|
$formattedOrders = [];
|
|
|
|
foreach ($orders as $order) {
|
|
$item_count = $order->get_item_count() - $order->get_item_count_refunded();
|
|
$actionsHtml = '<a target="_blank" href="' . $order->get_edit_order_url() . '">
|
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M8.5 5.5V7H4.75V15.25H13V11.5H14.5V16C14.5 16.1989 14.421 16.3897 14.2803 16.5303C14.1397 16.671 13.9489 16.75 13.75 16.75H4C3.80109 16.75 3.61032 16.671 3.46967 16.5303C3.32902 16.3897 3.25 16.1989 3.25 16V6.25C3.25 6.05109 3.32902 5.86032 3.46967 5.71967C3.61032 5.57902 3.80109 5.5 4 5.5H8.5ZM16.75 3.25V9.25H15.25V5.80975L9.40525 11.6553L8.34475 10.5948L14.1888 4.75H10.75V3.25H16.75Z" fill="#525866"/>
|
|
</svg>
|
|
</a>';
|
|
$date = '<span class="order_id">'.'#' . $order->get_order_number().'</span><span class="order_date">'.wc_format_datetime($order->get_date_created()).'</span>';
|
|
|
|
$status = '<span class="fcrm_badge fcrm_badge_'.esc_attr($order->get_status()).'">'. Helper::getStatusText($order->get_status()) .'</span>';
|
|
|
|
$formattedOrders[] = [
|
|
'date' => wp_kses_post($date),
|
|
'status' => wp_kses_post($status),
|
|
/* translators: 1: formatted order total (with currency), 2: number of items */
|
|
'total' => wp_kses_post(sprintf(_n('%1$s for %2$s item', '%1$s for %2$s items', $item_count, 'fluent-crm'), $order->get_formatted_order_total(), $item_count)),
|
|
'action' => $actionsHtml,
|
|
];
|
|
}
|
|
/**
|
|
* Determine the WooCommerce purchase history sidebar HTML in FluentCRM.
|
|
*
|
|
* This filter allows customization of the HTML content displayed in the WooCommerce purchase sidebar.
|
|
*
|
|
* @since 2.7.0
|
|
*
|
|
* @param string The current HTML content of the sidebar.
|
|
* @param object $subscriber The subscriber object containing subscriber data.
|
|
* @param int $page The current page identifier as an integer.
|
|
*/
|
|
$sidebarHtml = apply_filters('fluent_crm/woo_purchase_sidebar_html', '', $subscriber, $page);
|
|
|
|
return [
|
|
'data' => $formattedOrders,
|
|
'sidebar_html' => $sidebarHtml,
|
|
'total' => $totalOrders,
|
|
'has_recount' => $hasRecount,
|
|
'columns_config' => [
|
|
'date' => [
|
|
'label' => __('Date', 'fluent-crm'),
|
|
'sortable' => true,
|
|
'key' => 'date_created_gmt'
|
|
],
|
|
'status' => [
|
|
'label' => __('Status', 'fluent-crm'),
|
|
],
|
|
'total' => [
|
|
'label' => __('Total', 'fluent-crm'),
|
|
'width' => '160px',
|
|
'sortable' => true,
|
|
'key' => 'total_amount'
|
|
],
|
|
'actions' => [
|
|
'label' => __('', 'fluent-crm'),
|
|
'width' => '50px'
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
public function getWooCustomerSummary($subscriber)
|
|
{
|
|
$customerQuery = fluentCrmDb()->table('wc_customer_lookup')
|
|
->where('email', $subscriber->email);
|
|
|
|
if ($subscriber->user_id) {
|
|
$customerQuery = $customerQuery->orWhere('user_id', $subscriber->user_id);
|
|
}
|
|
|
|
$customer = $customerQuery->first();
|
|
|
|
if ($customer) {
|
|
$statuses = wc_get_is_paid_statuses();
|
|
$statuses = array_map(function ($status) {
|
|
return 'wc-' . $status;
|
|
}, $statuses);
|
|
|
|
$orderStats = fluentCrmDb()->table('wc_order_stats')
|
|
->where('customer_id', $customer->customer_id)
|
|
->whereIn('status', $statuses)
|
|
->get();
|
|
|
|
if ($orderStats->isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
$lifetimeValue = 0;
|
|
$orderIds = [];
|
|
|
|
$firstOrderDate = null;
|
|
$lastOrderDate = null;
|
|
|
|
foreach ($orderStats as $order) {
|
|
if (!$firstOrderDate) {
|
|
$firstOrderDate = $order->date_created;
|
|
}
|
|
|
|
if (!$lastOrderDate) {
|
|
$lastOrderDate = $order->date_created;
|
|
}
|
|
|
|
if (strtotime($order->date_created) < strtotime($firstOrderDate)) {
|
|
$firstOrderDate = $order->date_created;
|
|
}
|
|
|
|
if (strtotime($order->date_created) > strtotime($lastOrderDate)) {
|
|
$lastOrderDate = $order->date_created;
|
|
}
|
|
|
|
$lifetimeValue += $order->total_sales;
|
|
$orderIds[] = $order->order_id;
|
|
}
|
|
|
|
$orderIds = array_unique($orderIds);
|
|
|
|
$orderCount = count($orderIds);
|
|
|
|
$data_store = \WC_Data_Store::load('report-customers-stats');
|
|
$stat = $data_store->get_data();
|
|
|
|
$avg_value = $orderCount > 0 ? round($lifetimeValue / $orderCount, 2) : 0;
|
|
|
|
$summaryData = [
|
|
'order_count' => $orderCount,
|
|
'lifetime_value' => $lifetimeValue,
|
|
'avg_value' => $avg_value,
|
|
'stat_avg_count' => $stat->avg_orders_count,
|
|
'stat_avg_spend' => $stat->avg_total_spend,
|
|
'stat_avg_value' => $stat->avg_avg_order_value,
|
|
'currency_sign' => get_woocommerce_currency_symbol(),
|
|
'last_order_date' => $lastOrderDate,
|
|
'first_order_date' => $firstOrderDate,
|
|
];
|
|
|
|
return $this->formatSummaryData($summaryData, true);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return EDD 3 order history for the subscriber purchase-history panel.
|
|
*/
|
|
public function eddOrders($data, $subscriber)
|
|
{
|
|
if (!Helper::isEdd3()) {
|
|
return $data;
|
|
}
|
|
|
|
$app = fluentCrm();
|
|
$page = (int)$app->request->get('page', 1);
|
|
set_query_var('paged', $page);
|
|
|
|
$hasRecount = defined('FLUENTCAMPAIGN') && \FluentCampaign\App\Services\Commerce\Commerce::isEnabled('edd');
|
|
|
|
if ($hasRecount && $app->request->get('will_recount') == 'yes') {
|
|
(new \FluentCampaign\App\Services\Integrations\Edd\DeepIntegration)->syncCustomerBySubscriber($subscriber);
|
|
}
|
|
|
|
$sort_by = sanitize_sql_orderby($app->request->get('sort_by', 'id'));
|
|
$sort_type = sanitize_sql_orderby($app->request->get('sort_type', 'DESC'));
|
|
$per_page = (int)$app->request->get('per_page', 10);
|
|
$customer = new \EDD_Customer($subscriber->email);
|
|
|
|
if (!$customer || !$customer->id) {
|
|
return $data;
|
|
}
|
|
|
|
$lasOrderData = '';
|
|
|
|
/*
|
|
* EDD 3 stores orders in the edd_orders table. Legacy edd_payment posts
|
|
* are intentionally not queried because EDD 2 is no longer supported.
|
|
*/
|
|
$totalCount = fluentCrmDb()->table('edd_orders')
|
|
->where('customer_id', $customer->id)
|
|
->count();
|
|
|
|
if (!$totalCount) {
|
|
return $data;
|
|
}
|
|
|
|
$valid_columns = ['id', 'date_created', 'total'];
|
|
$valid_directions = ['ASC', 'DESC'];
|
|
|
|
if (!in_array($sort_by, $valid_columns)) {
|
|
$sort_by = 'id';
|
|
}
|
|
if (!in_array(strtoupper($sort_type), $valid_directions)) {
|
|
$sort_type = 'DESC';
|
|
}
|
|
|
|
$orders = fluentCrmDb()->table('edd_orders')
|
|
->where('customer_id', $customer->id)
|
|
->orderBy($sort_by, $sort_type)
|
|
->limit($per_page)
|
|
->offset(($page - 1) * $per_page)
|
|
->get();
|
|
|
|
$formattedOrders = [];
|
|
|
|
foreach ($orders as $order) {
|
|
$orderActionHtml = '<a target="_blank" href="' . add_query_arg('id', $order->id, admin_url('edit.php?post_type=download&page=edd-payment-history&view=view-order-details')) . '">
|
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M8.5 5.5V7H4.75V15.25H13V11.5H14.5V16C14.5 16.1989 14.421 16.3897 14.2803 16.5303C14.1397 16.671 13.9489 16.75 13.75 16.75H4C3.80109 16.75 3.61032 16.671 3.46967 16.5303C3.32902 16.3897 3.25 16.1989 3.25 16V6.25C3.25 6.05109 3.32902 5.86032 3.46967 5.71967C3.61032 5.57902 3.80109 5.5 4 5.5H8.5ZM16.75 3.25V9.25H15.25V5.80975L9.40525 11.6553L8.34475 10.5948L14.1888 4.75H10.75V3.25H16.75Z" fill="#525866"/>
|
|
</svg>
|
|
</a>';
|
|
$date = '<span class="order_id">'.'#' . $order->id .'</span><span class="order_date">'.date_i18n(get_option('date_format'), strtotime($order->date_created)).'</span>';
|
|
|
|
$status = '<span class="fcrm_badge fcrm_badge_'.esc_attr($order->status).'">'. Helper::getStatusText($order->status) .'</span>';
|
|
|
|
$formattedOrders[] = [
|
|
'date' => $date,
|
|
'status' => $status,
|
|
'total' => edd_currency_filter(edd_format_amount($order->total)),
|
|
'action' => $orderActionHtml
|
|
];
|
|
}
|
|
|
|
if (!$orders->isEmpty()) {
|
|
$lasOrderData = date_i18n(get_option('date_format'), strtotime($orders[0]->date_created));
|
|
}
|
|
|
|
/**
|
|
* Determine the HTML content displayed in the EDD purchase history sidebar for a subscriber in FluentCRM.
|
|
*
|
|
* This filter allows customization of the HTML content that appears in the EDD purchase
|
|
* history sidebar for a given subscriber on a specific page.
|
|
*
|
|
* @since 2.7.0
|
|
*
|
|
* @param string $beforeHtml The HTML content to be displayed before the purchase history.
|
|
* @param object $subscriber The subscriber object.
|
|
* @param int $page The current page identifier as an integer.
|
|
*/
|
|
$beforeHtml = apply_filters('fluent_crm/edd_purchase_sidebar_html', '', $subscriber, $page);
|
|
|
|
// if (!$beforeHtml && $subscriber->user_id && $page == 1 && $formattedOrders) {
|
|
// $summaryData = [
|
|
// 'order_count' => $customer->purchase_count,
|
|
// 'lifetime_value' => $customer->purchase_value,
|
|
// 'avg_value' => ($customer->purchase_count) ? round($customer->purchase_value / $customer->purchase_count, 2) : 'n/a',
|
|
// 'stat_avg_count' => 0,
|
|
// 'stat_avg_spend' => 0,
|
|
// 'stat_avg_value' => 0,
|
|
// 'currency_sign' => edd_currency_symbol(),
|
|
// 'last_order_date' => $lasOrderData
|
|
// ];
|
|
// $beforeHtml = $this->formatSummaryData($summaryData);
|
|
// }
|
|
|
|
return [
|
|
'data' => $formattedOrders,
|
|
'total' => $totalCount,
|
|
'sidebar_html' => $beforeHtml,
|
|
'after_html' => '<p><a target="_blank" rel="noopener" href="'.admin_url('edit.php?post_type=download&page=edd-customers&view=overview&id='.$customer->id).'">' . esc_html__('View Customer Profile', 'fluent-crm') . '</a></p>',
|
|
'has_recount' => $hasRecount,
|
|
'columns_config' => [
|
|
'order' => [
|
|
'label' => __('Order', 'fluent-crm'),
|
|
'width' => '100px',
|
|
'sortable' => true,
|
|
'key' => 'id'
|
|
],
|
|
'date' => [
|
|
'label' => __('Date', 'fluent-crm'),
|
|
'sortable' => true,
|
|
'key' => 'edd_orders'
|
|
],
|
|
'status' => [
|
|
'label' => __('Status', 'fluent-crm'),
|
|
'width' => '140px',
|
|
'sortable' => false
|
|
],
|
|
'total' => [
|
|
'label' => __('Total', 'fluent-crm'),
|
|
'width' => '120px',
|
|
'sortable' => true,
|
|
'key' => 'total'
|
|
],
|
|
'action' => [
|
|
'label' => __('Actions', 'fluent-crm'),
|
|
'width' => '100px',
|
|
'sortable' => false
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
public function payformSubmissions($data, $subscriber)
|
|
{
|
|
if (!defined('WPPAYFORM_VERSION')) {
|
|
return $data;
|
|
}
|
|
$app = fluentCrm();
|
|
$page = intval($app->request->get('page', 1));
|
|
$per_page = intval($app->request->get('per_page', 10));
|
|
$query = fluentCrmDb()->table('wpf_submissions')
|
|
->select([
|
|
'wpf_submissions.id',
|
|
'wpf_submissions.form_id',
|
|
'wpf_submissions.currency',
|
|
'wpf_submissions.payment_status',
|
|
'wpf_submissions.payment_total',
|
|
'wpf_submissions.payment_method',
|
|
'wpf_submissions.created_at',
|
|
'posts.post_title',
|
|
'wpf_subscriptions.recurring_amount',
|
|
])
|
|
->join('posts', 'posts.ID', '=', 'wpf_submissions.form_id')
|
|
->leftJoin('wpf_subscriptions', 'wpf_subscriptions.submission_id', '=', 'wpf_submissions.id')
|
|
->where(function ($query) use ($subscriber) {
|
|
$query->where('wpf_submissions.customer_email', '=', $subscriber->email);
|
|
if ($subscriber->user_id) {
|
|
$query->orWhere('wpf_submissions.user_id', '=', $subscriber->user_id);
|
|
}
|
|
})
|
|
// ->where('wpf_submissions.payment_total', '>', 0)
|
|
->limit($per_page)
|
|
->offset($per_page * ($page - 1))
|
|
->orderBy('wpf_submissions.id', 'desc');
|
|
|
|
$total = $query->count();
|
|
$submissions = $query->get();
|
|
$formattedSubmissions = [];
|
|
foreach ($submissions as $submission) {
|
|
$submissionUrl = admin_url('admin.php?page=wppayform.php#/edit-form/' . $submission->form_id . '/entries/' . $submission->id . '/view');
|
|
$actionUrl = '<a target="_blank" href="' . $submissionUrl . '">
|
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M8.5 5.5V7H4.75V15.25H13V11.5H14.5V16C14.5 16.1989 14.421 16.3897 14.2803 16.5303C14.1397 16.671 13.9489 16.75 13.75 16.75H4C3.80109 16.75 3.61032 16.671 3.46967 16.5303C3.32902 16.3897 3.25 16.1989 3.25 16V6.25C3.25 6.05109 3.32902 5.86032 3.46967 5.71967C3.61032 5.57902 3.80109 5.5 4 5.5H8.5ZM16.75 3.25V9.25H15.25V5.80975L9.40525 11.6553L8.34475 10.5948L14.1888 4.75H10.75V3.25H16.75Z" fill="#525866"/>
|
|
</svg>
|
|
</a>';
|
|
$paymentStatus = '<span class="fcrm_badge fcrm_badge_'.esc_attr($submission->payment_status).'">'. \FluentCrm\App\Services\Helper::getStatusText($submission->payment_status) .'</span>';
|
|
$formattedSubmissions[] = [
|
|
'id' => '#' . $submission->id,
|
|
'post_title' => $submission->post_title,
|
|
'recurring_amount' => $submission->recurring_amount ? wpPayFormFormatMoney($submission->recurring_amount, $subscriber->form_id) : wpPayFormFormatMoney($submission->payment_total, $subscriber->form_id),
|
|
'payment_status' => $paymentStatus,
|
|
'payment_method' => $submission->payment_method,
|
|
'created_at' => $submission->created_at,
|
|
'action' => $actionUrl
|
|
];
|
|
}
|
|
|
|
return [
|
|
'total' => $total,
|
|
'data' => $formattedSubmissions,
|
|
'columns_config' => [
|
|
'id' => [ 'label' => __('ID', 'fluent-crm'), 'width' => '100px', 'sortable' => false, 'key' => 'id'],
|
|
'post_title' => [ 'label' => __('Form Title', 'fluent-crm'), 'sortable' => false, 'key' => 'post_title'],
|
|
'recurring_amount' => [ 'label' => __('Payment Total', 'fluent-crm'), 'sortable' => false, 'key' => 'recurring_amount'],
|
|
'payment_status' => [ 'label' => __('Payment Status', 'fluent-crm'), 'sortable' => false, 'key' => 'payment_status'],
|
|
'payment_method' => [ 'label' => __('Payment Method', 'fluent-crm'), 'sortable' => false, 'key' => 'payment_method'],
|
|
'created_at' => [ 'label' => __('Submitted At', 'fluent-crm'), 'sortable' => false, 'key' => 'created_at']
|
|
]
|
|
];
|
|
|
|
}
|
|
|
|
public function formatSummaryData($data, $bodyOnly = false)
|
|
{
|
|
$blocks = [];
|
|
if (!empty($data['first_order_date'])) {
|
|
$blocks['Customer Since'] = gmdate(get_option('date_format'), strtotime($data['first_order_date']));
|
|
}
|
|
|
|
if (!empty($data['last_order_date'])) {
|
|
$blocks['Last Order'] = gmdate(get_option('date_format'), strtotime($data['last_order_date']));
|
|
}
|
|
|
|
$blocks['Order Count (paid)'] = $data['order_count'] . $this->getPercentChangeHtml($data['order_count'], $data['stat_avg_count']);
|
|
$blocks['Lifetime Value'] = $data['currency_sign'] . $data['lifetime_value'];
|
|
$blocks['AOV'] = $data['currency_sign'] . $data['avg_value'] . $this->getPercentChangeHtml($data['avg_value'], $data['stat_avg_value']);
|
|
|
|
|
|
$html = '<div class="fc_payment_summary"><h3 class="history_title">' . esc_html__("Customer Summary", "fluent-crm") . '</h3><div class="fc_history_widget">';
|
|
|
|
$body = '';
|
|
|
|
|
|
$body .= '<ul class="fc_full_listed">';
|
|
foreach ($blocks as $title => $block) {
|
|
$body .= '<li><span class="fc_list_sub">' . $title . '</span><span class="fc_list_value">' . $block . '</span></li>';
|
|
}
|
|
|
|
if (!empty($data['purchased_products'])) {
|
|
$body .= '<li><b>' . esc_html__("Purchased Products", "fluent-crm") . '</b><hr /><ul class="fc_list">';
|
|
foreach ($data['purchased_products'] as $product) {
|
|
$body .= '<li><a target="_blank" rel="nofollow" href="' . esc_url($product->guid) . '">' . esc_html($product->post_title) . '</a></li>';
|
|
}
|
|
$body .= '</ul></li>';
|
|
}
|
|
|
|
$body .= '</ul>';
|
|
|
|
if ($bodyOnly) {
|
|
return $body;
|
|
}
|
|
|
|
return $body . '</div></div>';
|
|
}
|
|
|
|
private function getPercentChangeHtml($value, $refValue)
|
|
{
|
|
if (!$refValue || !$value) {
|
|
return '';
|
|
}
|
|
$change = $value - $refValue;
|
|
$percentChange = absint(ceil($change / $refValue * 100));
|
|
if ($change >= 0) {
|
|
return '<span class="el-icon-caret-top fc_positive fc_change_ref">' . $percentChange . '%' . '</span>';
|
|
} else {
|
|
return '<span class="el-icon-caret-bottom fc_negative fc_change_ref">' . $percentChange . '%' . '</span>';
|
|
}
|
|
}
|
|
|
|
|
|
private function getWooOrders($subscriber, $sort_by, $sort_type)
|
|
{
|
|
$email = $subscriber->email;
|
|
|
|
$user = get_user_by('email', $email);
|
|
|
|
// check HPOS is enabled or not
|
|
if (get_option('woocommerce_custom_orders_table_enabled') === 'yes') {
|
|
// high performance order is enabled
|
|
if ($user) {
|
|
$hposOrders = fluentCrmDb()->table('wc_orders')
|
|
->where('status', '!=', 'trash')
|
|
->select(['id'])
|
|
->where(function ($query) use ($user) {
|
|
$query->where('customer_id', $user->ID)
|
|
->orWhere(function ($query) use ($user) {
|
|
$query->where('billing_email', $user->user_email)
|
|
->where('customer_id', 0);
|
|
});
|
|
})
|
|
->orderBy($sort_by, $sort_type)
|
|
->get();
|
|
} else {
|
|
$hposOrders = fluentCrmDb()->table('wc_orders')
|
|
->select(['id'])
|
|
->where('billing_email', $email)
|
|
->where('customer_id', 0)
|
|
->orderBy($sort_by, $sort_type)
|
|
->get();
|
|
}
|
|
|
|
if ($hposOrders->isEmpty()) {
|
|
return [];
|
|
}
|
|
|
|
$orders = [];
|
|
foreach ($hposOrders as $hposOrder) {
|
|
$order = wc_get_order($hposOrder->id);
|
|
if ($order) {
|
|
$orders[$hposOrder->id] = $order;
|
|
}
|
|
}
|
|
|
|
return array_values($orders);
|
|
}
|
|
|
|
|
|
$orders = [];
|
|
// Get all orders by user id
|
|
$storeUseId = $user ? $user->ID : false;
|
|
|
|
if ($storeUseId) {
|
|
$userOrders = wc_get_orders([
|
|
'customer_id' => $storeUseId,
|
|
'limit' => -1,
|
|
'orderby' => $sort_by,
|
|
'order' => $sort_type,
|
|
]);
|
|
|
|
// Sort orders by total amount manually
|
|
if ($sort_by === 'total_amount') {
|
|
$this->wooSortOrdersByTotalAmount($userOrders, $sort_type);
|
|
}
|
|
|
|
foreach ($userOrders as $order) {
|
|
$orders[$order->get_id()] = $order;
|
|
}
|
|
}
|
|
|
|
// get orders by billing email
|
|
$guestOrders = wc_get_orders([
|
|
'customer' => $email,
|
|
'limit' => -1,
|
|
'orderby' => $sort_by,
|
|
'order' => $sort_type,
|
|
]);
|
|
|
|
if ($sort_by === 'total_amount') {
|
|
$this->wooSortOrdersByTotalAmount($userOrders, $sort_type);
|
|
}
|
|
|
|
foreach ($guestOrders as $order) {
|
|
$userId = $order->get_user_id();
|
|
if ($userId && $storeUseId != $userId) {
|
|
continue;
|
|
}
|
|
$orders[$order->get_id()] = $order;
|
|
}
|
|
|
|
|
|
return array_values($orders);
|
|
}
|
|
|
|
/**
|
|
* Sorts an array of WooCommerce orders by their total amount.
|
|
*
|
|
* This method sorts an array of WooCommerce order objects based on the total order amount.
|
|
* The sorting can be done in either ascending ('ASC') or descending ('DESC') order,
|
|
* as specified by the $sort_type parameter.
|
|
*
|
|
* @param array $orders Array of WooCommerce order objects to be sorted.
|
|
* @param string $sort_type Specifies the sorting order.
|
|
* Accepts 'ASC' for ascending or 'DESC' for descending.
|
|
*
|
|
* @return void The $orders array is sorted in place.
|
|
*/
|
|
public function wooSortOrdersByTotalAmount(&$orders, $sort_type) {
|
|
usort($orders, function ($a, $b) use ($sort_type) {
|
|
$a_total = (float)$a->get_total();
|
|
$b_total = (float)$b->get_total();
|
|
|
|
return $sort_type === 'ASC' ? $a_total <=> $b_total : $b_total <=> $a_total;
|
|
});
|
|
}
|
|
|
|
public function pmproOrders($data, $subscriber)
|
|
{
|
|
if (!defined('PMPRO_VERSION')) {
|
|
return $data;
|
|
}
|
|
|
|
if (!defined('FLUENTCAMPAIGN')) {
|
|
return $data;
|
|
}
|
|
|
|
$customer = fluentCrmDb()->table('users')->where('user_email', $subscriber->email)->first();
|
|
|
|
if (!$customer) {
|
|
return false;
|
|
}
|
|
|
|
if (!$subscriber->user_id || $subscriber->user_id != $customer->ID) {
|
|
$subscriber->user_id = $customer->ID;
|
|
$subscriber->save();
|
|
}
|
|
|
|
$app = fluentCrm();
|
|
|
|
$page = (int)$app->request->get('page', 1);
|
|
$per_page = (int)$app->request->get('per_page', 10);
|
|
|
|
$sort_by = sanitize_sql_orderby($app->request->get('sort_by', 'ID'));
|
|
$sort_type = sanitize_sql_orderby($app->request->get('sort_type', 'DESC'));
|
|
|
|
$valid_columns = ['ID', 'date', 'modified'];
|
|
$valid_directions = ['ASC', 'DESC'];
|
|
|
|
if (!in_array($sort_by, $valid_columns)) {
|
|
$sort_by = 'ID';
|
|
}
|
|
if (!in_array(strtoupper($sort_type), $valid_directions)) {
|
|
$sort_type = 'DESC';
|
|
}
|
|
|
|
// Fetch the array of MemberOrder OBJECTS
|
|
$user_order_objects = \MemberOrder::get_orders([
|
|
'user_id' => $subscriber->user_id,
|
|
'status' => 'success',
|
|
'orderby' => $sort_by,
|
|
'order' => $sort_type
|
|
]);
|
|
|
|
// Create a new, simple array to hold the data for JSON conversion
|
|
$formattedOrders = [];
|
|
|
|
$totalOrders = count($user_order_objects);
|
|
$orders = array_slice($user_order_objects, ($page - 1) * $per_page, $per_page);
|
|
|
|
|
|
if (!empty($orders)) {
|
|
// Loop through each PHP object and extract its data into a simple array
|
|
foreach ($orders as $order) {
|
|
// Construct the URL using WordPress's admin_url() function
|
|
$order_page_url = admin_url('admin.php?page=pmpro-orders&order=' . $order->id);
|
|
$level = pmpro_getLevel($order->membership_id);
|
|
$actionsHtml = '<td><a href="' . esc_url($order_page_url) . '" target="_blank">View Order</a></td>';
|
|
$status = '<span class="fcrm_badge fcrm_badge_'.esc_attr($order->status).'">'. \FluentCrm\App\Services\Helper::getStatusText($order->status) .'</span>';
|
|
$formattedOrders[] = [
|
|
'order_code' => '#' . $order->code,
|
|
'membership_level_name' => $level ? $level->name : null,
|
|
'status' => $status,
|
|
'total' => $order->total,
|
|
'date' => gmdate('j F, Y', $order->timestamp),
|
|
'gateway' => $order->gateway,
|
|
'actions' => $actionsHtml
|
|
];
|
|
}
|
|
}
|
|
|
|
return [
|
|
'data' => $formattedOrders,
|
|
'sidebar_html' => '',
|
|
'total' => $totalOrders,
|
|
'has_recount' => false,
|
|
'columns_config' => [
|
|
'order_code' => [
|
|
'label' => __('Order Code', 'fluent-crm'),
|
|
'width' => '120px',
|
|
'sortable' => false,
|
|
'key' => 'id'
|
|
],
|
|
'membership_level_name' => [
|
|
'label' => __('Membership Level', 'fluent-crm'),
|
|
'sortable' => false,
|
|
],
|
|
'date' => [
|
|
'label' => __('Date', 'fluent-crm'),
|
|
'sortable' => false,
|
|
'key' => 'date_created_gmt'
|
|
],
|
|
'status' => [
|
|
'label' => __('Status', 'fluent-crm'),
|
|
'width' => '100px'
|
|
],
|
|
'total' => [
|
|
'label' => __('Total', 'fluent-crm'),
|
|
'width' => '130px',
|
|
'sortable' => false,
|
|
'key' => 'total_amount'
|
|
],
|
|
'gateway' => [
|
|
'label' => __('Gateway', 'fluent-crm'),
|
|
'width' => '120px',
|
|
'sortable' => false,
|
|
],
|
|
'actions' => [
|
|
'label' => __('Actions', 'fluent-crm'),
|
|
'width' => '100px'
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
|
|
}
|