Files
sodino/app/Services/UpsellService.php

185 lines
5.4 KiB
PHP

<?php
namespace Sodino\Services;
use Sodino\Repositories\UpsellRepository;
class UpsellService {
private $upsellRepository;
private $cache = null;
public function __construct(UpsellRepository $upsellRepository) {
$this->upsellRepository = $upsellRepository;
}
public function getActiveUpsells() {
if ($this->cache === null) {
$this->cache = $this->upsellRepository->getActive();
}
return $this->cache;
}
public function getMatchingUpsells($cart) {
if (!$cart || $cart->is_empty()) {
return [];
}
$matches = [];
foreach ($this->getActiveUpsells() as $upsell) {
if ($this->cartMatchesTrigger($upsell, $cart) && !$this->isProductAlreadyInCart($cart, $upsell->target_product_id)) {
$matches[] = $upsell;
}
}
usort($matches, function ($a, $b) {
return $b->priority <=> $a->priority;
});
return $matches;
}
public function applyUpsellDiscount($product, $upsell) {
if (!$product || !$upsell) {
return 0;
}
$price = floatval($product->get_price());
return $this->calculateDiscountedPrice($price, $upsell);
}
public function calculateDiscountedPrice($price, $upsell) {
$price = max(0, floatval($price));
if (!$upsell) {
return $price;
}
if ($upsell->discount_type === 'percentage') {
$percent = max(0, min(100, floatval($upsell->discount_value)));
return max(0, $price * (1 - $percent / 100));
}
if ($upsell->discount_type === 'fixed') {
return max(0, $price - floatval($upsell->discount_value));
}
return $price;
}
public function getById($id) {
return $this->upsellRepository->getById((int) $id);
}
public function isValidForCart($upsell, $cart) {
return $cart && !$cart->is_empty() && $this->cartMatchesTrigger($upsell, $cart);
}
public function canApplyToProduct($upsell, $productId, $variationId = 0) {
if (!$upsell || !$upsell->isActive()) {
return false;
}
$targetProductId = (int) $upsell->target_product_id;
return $targetProductId > 0 && ($targetProductId === (int) $productId || $targetProductId === (int) $variationId);
}
public function incrementImpression($upsellId) {
return $this->upsellRepository->incrementImpression((int) $upsellId);
}
public function incrementConversion($upsellId) {
return $this->upsellRepository->incrementConversion((int) $upsellId);
}
public function getTriggerLabel($upsell) {
switch ($upsell->trigger_type) {
case 'product':
return __('محصول خاص', 'sodino');
case 'category':
return __('دسته‌بندی', 'sodino');
case 'cart_total':
return __('مبلغ سبد خرید', 'sodino');
default:
return __('نامشخص', 'sodino');
}
}
public function getDiscountLabel($upsell) {
if ($upsell->discount_type === 'fixed') {
return sprintf('%s تومان', number_format_i18n($upsell->discount_value));
}
if ($upsell->discount_type === 'percentage') {
return sprintf('%s %%', esc_html($upsell->discount_value));
}
return __('بدون تخفیف', 'sodino');
}
private function cartMatchesTrigger($upsell, $cart) {
if (!$upsell->isActive()) {
return false;
}
$triggerType = $upsell->trigger_type;
$triggerValue = $upsell->trigger_value;
switch ($triggerType) {
case 'product':
return $this->cartContainsProduct($cart, intval($triggerValue));
case 'category':
return $this->cartContainsCategory($cart, intval($triggerValue));
case 'cart_total':
return floatval($cart->get_cart_contents_total()) >= floatval($triggerValue);
default:
return false;
}
}
private function cartContainsProduct($cart, $productId) {
if (!$productId) {
return false;
}
foreach ($cart->get_cart() as $cartItem) {
if ((int) $cartItem['product_id'] === $productId || (int) $cartItem['variation_id'] === $productId) {
return true;
}
}
return false;
}
private function cartContainsCategory($cart, $categoryId) {
if (!$categoryId) {
return false;
}
foreach ($cart->get_cart() as $cartItem) {
$product = wc_get_product($cartItem['product_id']);
if (!$product) {
continue;
}
$terms = wp_get_post_terms($product->get_id(), 'product_cat', ['fields' => 'ids']);
if (is_array($terms) && in_array($categoryId, $terms, true)) {
return true;
}
}
return false;
}
private function isProductAlreadyInCart($cart, $productId) {
if (!$productId) {
return false;
}
foreach ($cart->get_cart() as $cartItem) {
if ((int) $cartItem['product_id'] === $productId || (int) $cartItem['variation_id'] === $productId) {
return true;
}
}
return false;
}
}