context = adp_context(); $this->globalEngine = $engine; $this->productProcessor = new Processor(); $this->cartBuilder = new CartBuilder(); $this->cartItemConverter = new CartItemConverter(); } public function withContext(Context $context) { $this->context = $context; $this->productProcessor->withContext($context); $this->cartBuilder->withContext($context); } /** * @param Engine|null $engine */ public static function install($engine = null) { if (static::$instance === null) { static::$instance = new static($engine); } } /** * @return bool */ protected function isGlobalEngineExisting() { return isset($this->globalEngine); } /** * @return self */ public static function getInstance() { return static::$instance; } /** * @return array */ public function getGiftedCartProducts() { $products = array(); foreach (WC()->cart->cart_contents as $ket => $wcCartItem) { $facade = new WcCartItemFacade($this->context, $wcCartItem, $ket); if ($facade->isFreeItem()) { $prodId = $facade->getVariationId() ? $facade->getVariationId() : $facade->getProductId(); $qty = $facade->getQty(); if ( ! isset($products[$prodId])) { $products[$prodId] = floatval(0); } $products[$prodId] += $qty; } } return $products; } /** * @param int|WC_Product $theProd * @param float $qty * @param bool $useEmptyCart * * @return array */ public function getActiveRulesForProduct($theProd, $qty = 1.0, $useEmptyCart = false) { if ($useEmptyCart || ! $this->isGlobalEngineExisting()) { $productProcessor = $this->productProcessor; $cart = $this->cartBuilder->create(WC()->customer, WC()->session); $productProcessor->withCart($cart); } else { $productProcessor = $this->globalEngine->getProductProcessor(); } if (is_numeric($theProd)) { $product = CacheHelper::getWcProduct($theProd); } elseif ($theProd instanceof WC_Product) { $product = clone $theProd; } else { return array(); } $processedProduct = $productProcessor->calculateProduct($product, $qty); if (is_null($processedProduct)) { return array(); } if ($processedProduct instanceof ProcessedVariableProduct || $processedProduct instanceof ProcessedGroupedProduct) { return array(); } $rules = array(); /** @var ProcessedProductSimple $processedProduct */ foreach ($processedProduct->getHistory() as $ruleId => $amounts) { $rules[] = $ruleId; } return CacheHelper::loadRules($rules, $this->context); } /** * * @param array $listOfProducts * array[]['product_id'] * array[]['qty'] * array[]['cart_item_data'] Optional * @param boolean $plain Type of returning array. With False returns grouped by rules * * @return array * @throws Exception * */ public function getDiscountedProductsForCart($listOfProducts, $plain = false) { if ( ! did_action('wp_loaded')) { _doing_it_wrong(__FUNCTION__, /* translators: Message about the load order*/ //phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment sprintf(esc_html__('%1$s should not be called before the %2$s action.', 'woocommerce'), 'getDiscountedProductsForCart', 'wp_loaded'), esc_html(WC_ADP_VERSION)); return array(); } $result = array(); $cart = $this->cartBuilder->create(WC()->customer, WC()->session); $adapter = new ToPricingCartItemAdapter(); foreach ($listOfProducts as $data) { if ( ! isset($data['product_id'], $data['qty'])) { continue; } $prodId = intval($data['product_id']); $qty = floatval($data['qty']); $cartItemData = array(); if (isset($data['cart_item_data']) && is_array($data['cart_item_data'])) { $cartItemData = $data['cart_item_data']; } if ( ! $product = CacheHelper::getWcProduct($prodId)) { continue; } $cartItem = WcCartItemFacade::createFromProduct($this->context, $product, $cartItemData); $cartItem->setQty($qty); $adapter->adaptFacadeAndPutIntoCart($cart, $cartItem, -1); } $activeRuleCollection = CacheHelper::loadActiveRules($this->context); foreach ($activeRuleCollection->getRules() as $rule) { if ( ! ($rule instanceof SingleItemRule)) { continue; } /** @var SingleItemRule $rule */ try { $ruleProc = $rule->buildProcessor($this->context); } catch (Exception $e) { continue; } if ( ! $rule->getConditions() || ! $ruleProc->isRuleMatchedCart($cart)) { continue; } $filters = $rule->getFilters(); if ( ! $filters) { continue; } $listOfProductIds = array(); foreach ($filters as $filter) { if ($filter->getType() === $filter::TYPE_PRODUCT && $filter->getMethod() === $filter::METHOD_IN_LIST) { $listOfProductIds = array_merge($listOfProductIds, $filter->getValue()); } else { $listOfProductIds = null; break; } } if ( ! $listOfProductIds) { continue; } $items = array(); $adapter = new ToPricingCartItemAdapter(); foreach ($listOfProductIds as $index => $prodId) { if ($product = CacheHelper::getWcProduct($prodId)) { $item = $adapter->adaptWcProduct(new WcProductCalculationWrapper($product)); $item->addAttr(CartItemAttributeEnum::TEMPORARY()); $items[] = $item; $cart->addToCart($item); } } if ( ! $items) { continue; } if ($plain) { /** @var CartCalculator $calc $calc */ /** @see CartCalculator::make() */ $calc = Factory::callStaticMethod("Core_CartCalculator", 'make'); $calc->processCart($cart); } else { $ruleCollection = new RulesCollection(array($rule)); $calc = Factory::get("Core_CartCalculator", $ruleCollection); $calc->processCart($cart); } $ruleResult = array(); foreach ($cart->getItems() as $item) { if ( ! $item->hasAttr(CartItemAttributeEnum::TEMPORARY())) { continue; } $ruleResult[$item->getWcItem()->getProduct()->get_id()] = array( 'original_price' => $item->getOriginalPrice(), 'discounted_price' => $item->getPrice(), ); } if ( ! $ruleResult) { continue; } if ($plain) { if ( ! $result) { $result = $ruleResult; } else { foreach ($result as &$resultItem) { foreach ($ruleResult as $k => $ruleItem) { if ($ruleItem['product_id'] == $resultItem['product_id']) { if ($resultItem['discounted_price'] > $ruleItem['discounted_price']) { $resultItem['discounted_price'] = $ruleItem['discounted_price']; } if ($resultItem['original_price'] < $ruleItem['original_price']) { $resultItem['original_price'] = $ruleItem['original_price']; } unset($ruleResult[$k]); $ruleResult = array_values($ruleResult); break; } } } $result = array_merge($result, $ruleResult); } } else { $result[] = $ruleResult; } } return $result; } /** * @param int|WC_product $theProd * @param float $qty * @param bool $useEmptyCart * * @return float|array|null * float for simple product * array is (min, max) range for variable * null if product is incorrect */ public function getDiscountedProductPrice($theProd, $qty, $useEmptyCart = true) { if ($useEmptyCart || ! $this->isGlobalEngineExisting()) { $productProcessor = $this->productProcessor; $cart = $this->cartBuilder->create(WC()->customer, WC()->session); $productProcessor->withCart($cart); } else { $productProcessor = $this->globalEngine->getProductProcessor(); } if (is_numeric($theProd)) { $product = CacheHelper::getWcProduct($theProd); } elseif ($theProd instanceof WC_Product) { $product = clone $theProd; } else { return null; } $processedProduct = $productProcessor->calculateProduct($product, $qty); if (is_null($processedProduct)) { return array(); } if ($processedProduct instanceof ProcessedVariableProduct) { return array($processedProduct->getLowestPrice(), $processedProduct->getHighestPrice()); } elseif ($processedProduct instanceof ProcessedGroupedProduct) { return array($processedProduct->getLowestPrice(), $processedProduct->getHighestPrice()); } elseif ($processedProduct instanceof ProcessedProductSimple) { return $processedProduct->getPrice(); } else { return null; } } public function processCartManually() { if ($this->isGlobalEngineExisting()) { $this->globalEngine->process(false); } } /** * @param int|WC_product $theProd * @param float $qty * @param bool $useEmptyCart * * @return ProcessedProductSimple|ProcessedVariableProduct|ProcessedGroupedProduct|null */ public function calculateProduct($theProd, $qty, $useEmptyCart = true) { if ($useEmptyCart || ! $this->isGlobalEngineExisting()) { $productProcessor = $this->productProcessor; $cart = $this->cartBuilder->create(WC()->customer, WC()->session); $productProcessor->withCart($cart); } else { $productProcessor = $this->globalEngine->getProductProcessor(); } if (is_numeric($theProd)) { $product = CacheHelper::getWcProduct($theProd); } elseif ($theProd instanceof WC_Product) { $product = clone $theProd; } else { return null; } return $productProcessor->calculateProduct($product, $qty); } /** * @param SingleItemRule $rule * @param bool $useEmptyCart * * @return boolean */ public function isRuleMatchedCart($rule, $useEmptyCart = true) { $cart = $this->cartBuilder->create(WC()->customer, WC()->session); /** @var SingleItemRule $rule */ try { $ruleProc = $rule->buildProcessor($this->context); } catch (Exception $e) { return false; } return $ruleProc->isRuleMatchedCart($cart); } public function recalculatePersistenceCache() { $ruleRepository = new RuleRepository(); $persistentRuleRepository = new PersistentRuleRepository(); $rules = $ruleRepository->getRules( [ 'rule_types' => [ 'persistent' ], 'active_only' => true, 'include_deleted' => false, ] ); $persistentRuleRepository->truncate(); foreach ( $rules as $rule ) { $persistentRuleRepository->addRule( $persistentRuleRepository->getAddRuleData( $rule->id, $this->context ), $rule->id ); } } public function getProductProcessor(): Processor { return $this->productProcessor; } //TODO: delete unused function public function getProductsWithSalePriceAdp() { global $wpdb; $query = " SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_sale_price_adp' "; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared $ids = $wpdb->get_col($query); return array_map('intval', $ids); } public function getOnSaleProducts($include_wc_onsale = false, $ruleIds = null){ $productIds = []; // get rules list if( $ruleIds AND !is_array($ruleIds) ){ $ruleIds = [$ruleIds]; } if( !$ruleIds ){ $ruleIds = \ADP\BaseVersion\Includes\Shortcodes\OnSaleProducts::getActiveRules(); } //gather products foreach($ruleIds as $ruleId) { $productIds = array_merge( $productIds, \ADP\BaseVersion\Includes\Shortcodes\OnSaleProducts::getProductIdsByRuleId($ruleId) ); } //include WC onsale ? if( $include_wc_onsale ) { $productIds = array_merge( $productIds, wc_get_product_ids_on_sale()); } return array_unique($productIds); } }