context = adp_context();
}
public function withContext(Context $context)
{
$this->context = $context;
}
/**
* @param string $currency
*
* @return string
*/
public function getCurrencySymbol($currency = '')
{
if ($this->context->isUsingGlobalPriceSettings()) {
return get_woocommerce_currency_symbol($currency);
}
$currencyController = $this->context->currencyController;
if ( ! $currency) {
$currency = $currencyController->getCurrentCurrency()->getCode();
}
$symbols = $currencyController->getCurrencySymbols();
return isset($symbols[$currency]) ? $symbols[$currency] : '';
}
/**
* @param float $price
* @param array $args
*
* @return string
*/
public function format($price, $args = array())
{
if ($this->context->isUsingGlobalPriceSettings()) {
return wc_price($price, $args);
}
$priceSettings = $this->context->priceSettings;
$currentCurrency = $this->context->currencyController->getCurrentCurrency();
$args = wp_parse_args(
$args, array(
'ex_tax_label' => false,
'currency' => $currentCurrency->getCode(),
'decimal_separator' => $priceSettings->getDecimalSeparator(),
'thousand_separator' => $priceSettings->getThousandSeparator(),
'decimals' => $priceSettings->getDecimals(),
'price_format' => $priceSettings->getPriceFormat(),
));
$negative = $price < 0;
$price = floatval($negative ? $price * -1 : $price);
$price = number_format($price, $args['decimals'], $args['decimal_separator'], $args['thousand_separator']);
$formattedPrice = ($negative ? '-' : '') . sprintf($args['price_format'],
'' . $this->getCurrencySymbol($args['currency']) . '',
$price);
$return = '' . $formattedPrice . '';
if ($args['ex_tax_label'] && $priceSettings->isTaxEnabled()) {
$return .= ' ' . WC()->countries->ex_tax_or_vat() . ''; // todo replace global WC()->countries->ex_tax_or_vat()
}
return $return;
}
/**
* @param WC_Product $product WC_Product object.
* @param array $args Optional arguments to pass product quantity and price.
*
* @return float|null
* @see wc_get_price_including_tax()
*/
public function getPriceIncludingTax($product, $args = array())
{
if ($this->context->isUsingGlobalPriceSettings()) {
$this->forcePriceDecimals();
$price = wc_get_price_including_tax($product, $args);
$this->stopForcePriceDecimals();
return $price !== '' ? (float)$price : null;
}
$args = wp_parse_args(
$args, array(
'qty' => '',
'price' => '',
'adjust_non_base_location_prices' => true,
));
// always get product product price without hooks!
$price = '' !== $args['price'] ? max(0.0, (float)$args['price']) : $product->get_price('edit');
$qty = '' !== $args['qty'] ? max(0.0, (float)$args['qty']) : 1;
if ('' === $price) {
return null;
} elseif (empty($qty)) {
return 0.0;
}
$priceSettings = $this->context->priceSettings;
$linePrice = $price * $qty;
$returnPrice = (float)$linePrice;
if ($product->is_taxable()) {
if ( ! $priceSettings->isIncludeTax()) {
$taxRates = WC_Tax::get_rates($product->get_tax_class());
$taxes = WC_Tax::calc_tax($linePrice, $taxRates, false);
if ('yes' === get_option('woocommerce_tax_round_at_subtotal')) {
$taxesTotal = array_sum($taxes);
} else {
$taxesTotal = array_sum(array_map('wc_round_tax_total', $taxes));
}
$returnPrice = round($linePrice + $taxesTotal, $priceSettings->getDecimals());
} else {
$taxRates = WC_Tax::get_rates($product->get_tax_class());
$baseTaxRates = WC_Tax::get_base_tax_rates($product->get_tax_class('unfiltered'));
/**
* If the customer is excempt from VAT, remove the taxes here.
* Either remove the base or the user taxes depending on woocommerce_adjust_non_base_location_prices setting.
*/
if ( ! empty(WC()->customer) && WC()->customer->get_is_vat_exempt()) { // @codingStandardsIgnoreLine.
$removeTaxes = $args['adjust_non_base_location_prices'] ? WC_Tax::calc_tax($linePrice,
$baseTaxRates, true) : WC_Tax::calc_tax($linePrice, $taxRates, true);
if ('yes' === get_option('woocommerce_tax_round_at_subtotal')) {
$removeTaxesTotal = array_sum($removeTaxes);
} else {
$removeTaxesTotal = array_sum(array_map('wc_round_tax_total', $removeTaxes));
}
$returnPrice = round($linePrice - $removeTaxesTotal, $priceSettings->getDecimals());
/**
* The woocommerce_adjust_non_base_location_prices filter can stop base taxes being taken off when dealing with out of base locations.
* e.g. If a product costs 10 including tax, all users will pay 10 regardless of location and taxes.
* This feature is experimental @since 2.4.7 and may change in the future. Use at your risk.
*/
} elseif ($taxRates !== $baseTaxRates && $args['adjust_non_base_location_prices']) {
$baseTaxes = WC_Tax::calc_tax($linePrice, $baseTaxRates, true);
$moddedTaxes = WC_Tax::calc_tax($linePrice - array_sum($baseTaxes), $taxRates, false);
if ('yes' === get_option('woocommerce_tax_round_at_subtotal')) {
$baseTaxesTotal = array_sum($baseTaxes);
$moddedTaxesTotal = array_sum($moddedTaxes);
} else {
$baseTaxesTotal = array_sum(array_map('wc_round_tax_total', $baseTaxes));
$moddedTaxesTotal = array_sum(array_map('wc_round_tax_total', $moddedTaxes));
}
$returnPrice = round($linePrice - $baseTaxesTotal + $moddedTaxesTotal,
$priceSettings->getDecimals());
}
}
}
return $returnPrice;
}
/**
* @param WC_Product $product WC_Product object.
* @param array $args Optional arguments to pass product quantity and price.
*
* @return float|null
* @see wc_get_price_excluding_tax()
*/
public function getPriceExcludingTax($product, $args = array())
{
if ($this->context->isUsingGlobalPriceSettings()) {
$this->forcePriceDecimals();
$price = wc_get_price_excluding_tax($product, $args);
$this->stopForcePriceDecimals();
return $price !== '' ? (float)$price : null;
}
$args = wp_parse_args(
$args, array(
'qty' => '',
'price' => '',
'adjust_non_base_location_prices' => true,
));
// always get product product price without hooks!
$price = '' !== $args['price'] ? max(0.0, (float)$args['price']) : $product->get_price();
$qty = '' !== $args['qty'] ? max(0.0, (float)$args['qty']) : 1;
if ('' === $price) {
return null;
} elseif (empty($qty)) {
return 0.0;
}
$priceSettings = $this->context->priceSettings;
$linePrice = (float)($price * $qty);
if ($product->is_taxable() && $priceSettings->isIncludeTax()) {
$taxRates = WC_Tax::get_rates($product->get_tax_class());
$baseTaxRates = WC_Tax::get_base_tax_rates($product->get_tax_class('unfiltered'));
$removeTaxes = $args['adjust_non_base_location_prices']
? WC_Tax::calc_tax($linePrice, $baseTaxRates,true)
: WC_Tax::calc_tax($linePrice, $taxRates, true);
$returnPrice = $linePrice - (float)array_sum($removeTaxes); // Unrounded since we're dealing with tax inclusive prices. Matches logic in cart-totals class. @see adjust_non_base_location_price.
} else {
$returnPrice = $linePrice;
}
return $returnPrice;
}
/**
* @param WC_Product $product WC_Product object.
* @param array $args Optional arguments to pass product quantity and price.
*
* @return float|null
* @see wc_get_price_to_display()
*/
public function getPriceToDisplay($product, $args = array())
{
if ($this->context->isUsingGlobalPriceSettings()) {
$this->forcePriceDecimals();
$price = wc_get_price_to_display($product, $args);
$this->stopForcePriceDecimals();
return $price;
}
$args = wp_parse_args(
$args, array(
'qty' => 1,
// always get product product price without hooks!
'price' => $product->get_price('edit'),
));
$price = $args['price'];
$qty = $args['qty'];
return 'incl' === $this->context->getTaxDisplayShopMode() ? $this->getPriceIncludingTax($product,
array('qty' => $qty, 'price' => $price,)) : $this->getPriceExcludingTax($product,
array('qty' => $qty, 'price' => $price,));
}
/**
* @param string $from Price from.
* @param string $to Price to.
*
* @return string
* @see wc_format_price_range()
*/
function formatRange($from, $to)
{
if ($this->context->isUsingGlobalPriceSettings()) {
return wc_format_price_range($from, $to);
}
/* translators: 1: price from 2: price to */
//phpcs:ignore WordPress.WP.I18n.TextDomainMismatch, WordPress.WP.I18n.MissingTranslatorsComment
return sprintf(_x('%1$s – %2$s', 'Price range: from-to', 'woocommerce'),
is_numeric($from) ? wc_price($from) : $from, is_numeric($to) ? wc_price($to) : $to);
}
/**
* @param string $regularPrice Regular price.
* @param string $salePrice Sale price.
*
* @return string
* @see wc_format_sale_price()
*/
function formatSalePrice($regularPrice, $salePrice)
{
if ($this->context->isUsingGlobalPriceSettings()) {
return wc_format_sale_price($regularPrice, $salePrice);
}
$del = is_numeric($regularPrice) ? $this->format($regularPrice) : $regularPrice;
$ins = is_numeric($salePrice) ? $this->format($salePrice) : $salePrice;
return '' . $del . ' ' . $ins . '';
}
/**
* @param string $price Regular price.
*
* @return string
* @see wc_format_sale_price()
*/
function formatStrikedPrice($regularPrice, $salePrice = null)
{
$del = is_numeric($regularPrice) ? $this->format($regularPrice) : $regularPrice;
if($salePrice < $regularPrice) {
return '' . $del . '';
}
return "";
}
/**
* @param ProcessedProductSimple $prod
* @param float|null $price
*
* @return float
*/
public function getProcProductPriceToDisplay(ProcessedProductSimple $prod, $price = null)
{
if (is_null($price)) {
$price = $prod->getPrice();
}
return $this->getPriceToDisplay($prod->getProduct(), array('price' => $price, 'qty' => 1));
}
protected function forcePriceDecimals()
{
if ( ! $this->context->getOption('is_calculate_based_on_wc_precision')) {
add_filter('wc_get_price_decimals', array($this, 'setPriceDecimals'), 10, 0);
}
}
public function setPriceDecimals()
{
return $this->context->priceSettings->getDecimals() + 2;
}
protected function stopForcePriceDecimals()
{
remove_filter('wc_get_price_decimals', array($this, 'setPriceDecimals'), 10);
}
}