feat(Core): add optimize and complete code

This commit is contained in:
2026-05-17 20:05:15 +03:30
parent aa944bf339
commit 4e60b7efdd
25 changed files with 858 additions and 54 deletions

View File

@@ -11,7 +11,8 @@ class PricingService {
private $trackingService;
private $settings;
private $cache;
private $trackedApplications = [];
private $appliedRules = [];
private $trackedConversions = [];
public function __construct(RuleRepository $ruleRepository, TrackingService $trackingService) {
$this->ruleRepository = $ruleRepository;
@@ -29,7 +30,14 @@ class PricingService {
return $price;
}
if (!$product || !is_a($product, 'WC_Product')) {
return $price;
}
$price = $this->normalizePrice($price);
if ($price <= 0) {
return $price;
}
if (!$this->settings->get('cart_pricing_enabled') && is_cart()) {
return $price;
@@ -50,8 +58,7 @@ class PricingService {
foreach ($rules as $rule) {
$oldPrice = $price;
$price = $this->applyRuleActions($rule, $price);
$this->trackDiscountOnce($product, $oldPrice, $price, $rule->id);
$this->rememberAppliedRule($product, $oldPrice, $price, $rule->id);
}
$price = $this->enforceLimits($originalPrice, $price);
@@ -59,6 +66,56 @@ class PricingService {
return max(0, $price);
}
public function getAppliedRulesForProduct($product) {
if (!$product || !is_a($product, 'WC_Product')) {
return [];
}
$keys = $this->getProductTrackingKeys($product);
$rules = [];
foreach ($keys as $key) {
if (!empty($this->appliedRules[$key])) {
$rules = array_merge($rules, $this->appliedRules[$key]);
}
}
if (empty($rules)) {
return [];
}
$unique = [];
foreach ($rules as $rule) {
$unique[(int) $rule['rule_id']] = $rule;
}
return array_values($unique);
}
public function trackAppliedRulesForProduct($product) {
foreach ($this->getAppliedRulesForProduct($product) as $rule) {
$trackingKey = implode(':', [
(int) $product->get_id(),
(int) $rule['rule_id'],
round((float) $rule['original_price'], 4),
round((float) $rule['discounted_price'], 4),
]);
if (isset($this->trackedConversions[$trackingKey])) {
continue;
}
$this->trackedConversions[$trackingKey] = true;
$this->trackingService->recordDiscountApplied(
$product,
(float) $rule['original_price'],
(float) $rule['discounted_price'],
(int) $rule['rule_id']
);
$this->ruleRepository->incrementUsage((int) $rule['rule_id']);
}
}
private function getApplicableRules($product) {
$rules = $this->ruleRepository->getEnabled();
$applicable = [];
@@ -160,6 +217,12 @@ class PricingService {
return $this->getCustomerOrderCount() >= intval($value);
case 'customer_order_count_max':
return $this->getCustomerOrderCount() <= intval($value);
case 'customer_days_since_last_order_min':
return $this->getCustomerDaysSinceLastOrder() >= intval($value);
case 'product_total_sales_max':
return $this->getProductTotalSales($product) <= intval($value);
case 'product_total_sales_min':
return $this->getProductTotalSales($product) >= intval($value);
case 'day_of_week':
return in_array((string) current_time('N'), array_map('strval', $this->normalizeIdList($value)), true);
default:
@@ -195,6 +258,35 @@ class PricingService {
return (int) wc_get_customer_order_count(get_current_user_id());
}
private function getCustomerDaysSinceLastOrder() {
if (!is_user_logged_in()) {
return 0;
}
$orders = wc_get_orders([
'customer_id' => get_current_user_id(),
'limit' => 1,
'orderby' => 'date',
'order' => 'DESC',
'status' => ['wc-completed', 'wc-processing'],
'return' => 'objects',
]);
if (empty($orders)) {
return 0;
}
$date = $orders[0]->get_date_created();
if (!$date) {
return 0;
}
$lastOrderTimestamp = $date->getTimestamp();
$now = current_time('timestamp', true);
return max(0, (int) floor(($now - $lastOrderTimestamp) / DAY_IN_SECONDS));
}
private function userHasAllowedRole($roles) {
if (!is_user_logged_in()) {
return false;
@@ -227,12 +319,36 @@ class PricingService {
return $this->productHasTerm($product, $categories, 'product_cat');
}
private function getProductTotalSales($product) {
if (!$product || !is_a($product, 'WC_Product')) {
return 0;
}
$productId = (int) $product->get_id();
if ($product->is_type('variation') && method_exists($product, 'get_parent_id')) {
$parentId = (int) $product->get_parent_id();
if ($parentId > 0) {
$productId = $parentId;
}
}
return (int) get_post_meta($productId, 'total_sales', true);
}
private function productHasTerm($product, $terms, $taxonomy) {
if (!$product || empty($terms)) {
return false;
}
$product_terms = wp_get_post_terms($product->get_id(), $taxonomy, ['fields' => 'ids']);
$productId = (int) $product->get_id();
if ($product->is_type('variation') && method_exists($product, 'get_parent_id')) {
$parentId = (int) $product->get_parent_id();
if ($parentId > 0) {
$productId = $parentId;
}
}
$product_terms = wp_get_post_terms($productId, $taxonomy, ['fields' => 'ids']);
if (is_wp_error($product_terms)) {
return false;
}
@@ -428,16 +544,30 @@ class PricingService {
return false;
}
private function trackDiscountOnce($product, $oldPrice, $price, $ruleId) {
$productId = $product ? $product->get_id() : 0;
$key = implode(':', [$productId, (int) $ruleId, round($oldPrice, 4), round($price, 4)]);
if ($price >= $oldPrice || isset($this->trackedApplications[$key])) {
private function rememberAppliedRule($product, $oldPrice, $price, $ruleId) {
if ($price >= $oldPrice || !$product || !is_a($product, 'WC_Product')) {
return;
}
$this->trackedApplications[$key] = true;
$this->trackingService->recordDiscountApplied($product, $oldPrice, $price, $ruleId);
$this->ruleRepository->incrementUsage($ruleId);
foreach ($this->getProductTrackingKeys($product) as $key) {
$this->appliedRules[$key][(int) $ruleId] = [
'rule_id' => (int) $ruleId,
'original_price' => (float) $oldPrice,
'discounted_price' => (float) $price,
];
}
}
private function getProductTrackingKeys($product) {
$keys = [(int) $product->get_id()];
if ($product->is_type('variation') && method_exists($product, 'get_parent_id')) {
$parentId = (int) $product->get_parent_id();
if ($parentId > 0) {
$keys[] = $parentId;
}
}
return array_values(array_unique($keys));
}
}