Plugin Directory

Changeset 3443187


Ignore:
Timestamp:
01/20/2026 11:18:22 AM (2 months ago)
Author:
algol.plus
Message:

dev update

Location:
advanced-dynamic-pricing-for-woocommerce/trunk
Files:
1 added
30 edited

Legend:

Unmodified
Added
Removed
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php

    r3412190 r3443187  
    187187                    20 => "disable_shipping_calc_during_process",
    188188                    30 => "dont_recalculate_cart_on_page_load",
     189                    35 => "dont_recalculate_cart_if_not_changed",
    189190                    40 => "combine_discounts",
    190191                    50 => "default_discount_name",
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Cache/CacheHelper.php

    r3412260 r3443187  
    8080        self::cacheFlushGroup(self::GROUP_RULES_CACHE);
    8181        self::cacheFlushGroup(self::GROUP_PROCESSED_PRODUCTS_TO_DISPLAY);
     82
     83        Factory::callStaticMethod('Shortcodes_OnSaleProducts', 'clearCache');
     84        Factory::callStaticMethod('Shortcodes_BogoProducts', 'clearCache');
    8285    }
    8386
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/CartProcessor/CartCouponsProcessorMerge/MergeDiscountsCalculator.php

    r3297317 r3443187  
    2020use WC_Coupon;
    2121
     22if ( ! defined( 'ABSPATH' ) ) exit;
     23
    2224class MergeDiscountsCalculator
    2325{
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/CartProcessor/CartProcessor.php

    r3412190 r3443187  
    348348        }
    349349
     350        if ($this->context->getOption('dont_recalculate_cart_if_not_changed')) {
     351            $applicableRules = $this->calc->getApplicableRulesForCart($cart);
     352            $rulesHash = $this->calc->getRulesCollection()->getHash($applicableRules);
     353            $cartHash = $this->getWcCartHash($wcCart);
     354            $rulesCartHash = md5($rulesHash.$cartHash);
     355
     356            $storedRulesCartHash = WC()->session->get("adp_rules_cart_hash");
     357
     358            if($rulesCartHash === $storedRulesCartHash) {
     359                foreach ($wcCart->cart_contents as $cartKey => $wcCartItem) {
     360                    $facade  = new WcCartItemFacade($this->context, $wcCartItem, $cartKey);
     361                    $product = $wcCartItem['data'];
     362
     363                    $product->set_price($facade->getNewPrice());
     364                }
     365
     366                return $cart;
     367            }
     368        }
     369
    350370        $optionDontProcessCart = apply_filters('adp_dont_process_cart_on_page_load', $this->context->getOption("dont_recalculate_cart_on_page_load", true));
    351371        if( $first AND $optionDontProcessCart ) {
     
    397417        $clonedWcCart     = clone $wcCart;
    398418        $currencySwitcher = $this->context->currencyController;
    399 
     419       
    400420        if ($currencySwitcher->isCurrencyChanged()) {
    401421            foreach ($clonedWcCart->cart_contents as $cartKey => $wcCartItem) {
     
    718738        }
    719739
     740        if ($this->context->getOption('dont_recalculate_cart_if_not_changed')) {
     741            $cartHash = $this->getWcCartHash($wcCart);
     742            $rulesCartHash = md5($rulesHash.$cartHash);
     743            WC()->session->set("adp_rules_cart_hash", $rulesCartHash);
     744        }
     745
    720746        $this->listener->processFinished($wcCart, WC()->session);
    721747
     
    15991625    }
    16001626
     1627    protected function getWcCartHash($wcCart)
     1628    {
     1629        $packages = $wcCart->get_shipping_packages();
     1630        foreach ( $packages as $package_key => $package ) {
     1631            // Remove data objects so hashes are consistent.
     1632            foreach ( $packages[$package_key]['contents'] as $item_id => $item ) {
     1633                unset( $packages[$package_key]['contents'][ $item_id ]['data'] );
     1634            }
     1635            unset($packages[$package_key]['rates']);
     1636        }
     1637
     1638        return md5(json_encode($packages));
     1639    }
    16011640}
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/CartProcessor/CartShippingProcessor.php

    r3319660 r3443187  
    7272        add_filter('woocommerce_package_rates', array($this, 'packageRates'), PHP_INT_MAX - 1, 2);
    7373        add_filter('woocommerce_package_rates', array($this, 'currencyPackageRates'), PHP_INT_MAX - 2, 2);
     74        add_filter('woocommerce_cart_shipping_packages', array($this, 'filterDataPackages'), 10, 1);
    7475    }
    7576
     
    288289        return isset($rates[$chosenMethod]) ? $chosenMethod : $default;
    289290    }
     291
     292    public function filterDataPackages($packages)
     293    {
     294        $newPackages = [];
     295        foreach ( $packages as $package_key => $package ) {
     296            $newPackages[$package_key] = $package;
     297            foreach ( $newPackages[$package_key]['contents'] as $item_id => $item ) {
     298                unset( $newPackages[$package_key]['contents'][ $item_id ]['adp'] );
     299            }
     300        }
     301        return $newPackages;
     302    }
    290303}
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Compatibility/Container/SomewhereWarmBundlesCmp.php

    r3412190 r3443187  
    7474                }
    7575            }
    76        
     76
    7777            return $data;
    7878        }, 10, 2);
     
    196196    public function isPartOfContainerFacadePricedIndividually(WcCartItemFacade $facade): ?bool
    197197    {
     198        if(apply_filters('adp_true_bundle_individ_price', false)){
     199            return true;
     200        }
     201
    198202        $product = $facade->getProduct();
    199203        $this->probablySetBundledItem($product, $facade);
     
    202206            return false;
    203207        }
    204 
    205208        $item = $product->bundled_cart_item;
    206209
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Compatibility/Container/WpcBundleCmp.php

    r3384329 r3443187  
    102102
    103103        if (isset($thirdPartyData['woosb_price'])) {
    104             return floatval($thirdPartyData['woosb_price']);
     104            return -floatval($thirdPartyData['woosb_price']);
    105105        }
    106106
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Compatibility/Container/YithBundlesCmp.php

    r3022260 r3443187  
    33namespace ADP\BaseVersion\Includes\Compatibility\Container;
    44
    5 use ADP\BaseVersion\Includes\CartProcessor\CartProcessor;
    65use ADP\BaseVersion\Includes\Context;
    7 use ADP\BaseVersion\Includes\Core\Cart\CartItem\Type\Container\ContainerCartItem;
    86use ADP\BaseVersion\Includes\Core\Cart\CartItem\Type\Container\ContainerPriceTypeEnum;
    97use ADP\BaseVersion\Includes\WC\WcCartItemFacade;
     8use YITH_WCPB_Frontend_Premium;
    109
    1110defined('ABSPATH') or exit;
     
    2423    private $context;
    2524
     25    /**
     26     * @var YITH_WCPB_Frontend_Premium
     27     */
     28    private $yithWcpbFrontendPremium = null;
     29
    2630    public function __construct(Context $context)
    2731    {
    2832        $this->context = $context;
     33        if(class_exists('YITH_WCPB_Frontend_Premium')){
     34            $this->yithWcpbFrontendPremium = yith_wcpb_frontend();
     35        }
    2936    }
    3037
     
    120127    public function calculateContainerPrice(WcCartItemFacade $facade, array $children): float
    121128    {
     129
     130        if (!is_null($this->yithWcpbFrontendPremium) && $this->yithWcpbFrontendPremium->show_item_prices_in_cart_and_checkout) {
     131            $containerPrice = 0.0;
     132
     133            foreach ($children as $child) {
     134                $containerPrice += floatval($child->getProduct()->get_price());
     135            }
     136            return $containerPrice;
     137        }
     138
    122139        return floatval($facade->getProduct()->get_price());
    123140    }
     
    130147    public function calculateContainerBasePrice(WcCartItemFacade $facade, array $children): float
    131148    {
    132         return floatval(CartProcessor::getProductPriceDependsOnPriceMode($facade->getProduct()));
     149        if (!is_null($this->yithWcpbFrontendPremium) && $this->yithWcpbFrontendPremium->show_item_prices_in_cart_and_checkout) {
     150            return 0.0;
     151        }
     152
     153        return floatval($facade->getProduct()->get_regular_price());
    133154    }
    134155
    135156    public function getContainerPriceTypeByParentFacade(WcCartItemFacade $facade): ?ContainerPriceTypeEnum
    136157    {
    137         return ContainerPriceTypeEnum::FIXED();
     158        $product = $facade->getProduct();
     159
     160        if (!($product instanceof \WC_Product_Yith_Bundle)) {
     161            return null;
     162        }
     163
     164        if (!is_null($this->yithWcpbFrontendPremium) && !$this->yithWcpbFrontendPremium->show_item_prices_in_cart_and_checkout) {
     165            return ContainerPriceTypeEnum::FIXED();
     166        } else {
     167            return ContainerPriceTypeEnum::BASE_PLUS_SUM_OF_SUB_ITEMS();
     168        }
    138169    }
    139170
    140171    public function isPartOfContainerFacadePricedIndividually(WcCartItemFacade $facade): ?bool
    141172    {
    142         return false;
     173        if (!is_null($this->yithWcpbFrontendPremium) && $this->yithWcpbFrontendPremium->show_item_prices_in_cart_and_checkout) {
     174            return true;
     175        }else {
     176            return false;
     177        }
    143178    }
    144179
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Compatibility/GermanMarketCmp.php

    r3319660 r3443187  
    22
    33namespace ADP\BaseVersion\Includes\Compatibility;
     4
     5if ( ! defined( 'ABSPATH' ) ) exit;
    46
    57/**
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Compatibility/WoocsCmp.php

    r3297317 r3443187  
    6767            foreach ($hooks as $hook) {
    6868                add_filter($hook, function ($price, $product) {
    69                     if ($product->get_meta('adp_price_converted')) {
     69                    if ($product AND $product->get_meta('adp_price_converted')) {
    7070                        $_REQUEST['woocs_block_price_hook'] = true;
    7171                    }
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Compatibility/YoastSEOCmp.php

    r3384329 r3443187  
    1313class YoastSEOCmp
    1414{
    15     static function isNewPriceSpecification() {
    16         return defined( 'WPSEO_WOO_VERSION' ) && version_compare( WPSEO_WOO_VERSION, '16.6' ) >= 0;
     15    static function isNewPriceSpecification($priceSpecification = array()) {
     16        if(is_array($priceSpecification) && array_key_exists('@type', $priceSpecification) && $priceSpecification['@type'] === 'PriceSpecification') {
     17            return false;
     18        }
     19
     20        return defined( 'WPSEO_WOO_VERSION' ) && version_compare( WPSEO_WOO_VERSION, '16.5' ) >= 0;
    1721    }
    1822
     
    2630                }
    2731
    28                 if (isset($wpseo_data['offers'][0]['priceSpecification'][0])) {
     32                $isNewPriceSpecification = $this::isNewPriceSpecification($wpseo_data['offers'][0]['priceSpecification']);
     33               
     34                if ($isNewPriceSpecification) {
    2935                    $priceSpecification = $wpseo_data['offers'][0]['priceSpecification'][0];
    3036                } else {
     
    3541                    $priceSpecification['price'] = $data['price'];
    3642
    37                     if (YoastSEOCmp::isNewPriceSpecification()) {
     43                    if ($isNewPriceSpecification) {
    3844                        $wpseo_data['offers'][0]['priceSpecification'] = [ $priceSpecification ];
    3945                    } else {
     
    5561                $originalPriceSpecification = $newPriceSpecification;
    5662
    57                 if ($this::isNewPriceSpecification()) {
     63                $isNewPriceSpecification = $this::isNewPriceSpecification($offer['priceSpecification']);
     64
     65                if ($isNewPriceSpecification) {
    5866                    $originalPriceSpecification = $newPriceSpecification[0];
    5967                }
     
    7482                        );
    7583
    76                         if ($this::isNewPriceSpecification()) {
     84                        if ($isNewPriceSpecification) {
    7785                            $newPriceSpecification[] = $newSpecUnit;
    7886                        } else {
     
    8290                }
    8391
    84                 if ($this::isNewPriceSpecification() && count($newPriceSpecification) > 1) {
     92                if ($isNewPriceSpecification && count($newPriceSpecification) > 1) {
    8593                    $maxPriceSpec = $newPriceSpecification[0];
    8694                    $minPriceSpec = $newPriceSpecification[0];
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Core/CartCalculator.php

    r3412190 r3443187  
    475475        $this->maxDiscountAmount = $maxDiscountAmount;
    476476    }
     477
     478    /**
     479     * @param Cart $cart
     480     *
     481     * @return array
     482     */
     483    public function getApplicableRulesForCart($cart)
     484    {
     485        $context = $this->context;
     486        return array_filter(array_map(function($rule) use($context, $cart) {
     487            $proc = $rule->buildProcessor($context);
     488            if ($proc->isRuleMatchedCart($cart)) {
     489                return $rule;
     490            }
     491            return null;
     492        }, $this->ruleCollection->getRules()));
     493    }
    477494}
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Core/RuleProcessor/PriceCalculator.php

    r3385738 r3443187  
    130130        }
    131131
    132         if ($item->getAddonsAmount() > 0) {
    133             if ($discount::TYPE_FIXED_VALUE === $discount->getType()) {
    134                 $newPrice += $item->getAddonsAmount();
    135             }
    136         } else {
     132        if (!$item->getAddonsAmount()) {
    137133            if ($globalContext->isToCompensateTrdPartAdjustmentForFixedPrice()) {
    138134                if ($discount::TYPE_FIXED_VALUE === $discount->getType()) {
     
    381377        foreach ($items as $item) {
    382378            if ($item->getAddonsAmount() > 0) {
    383                 $third_party_adjustments += $item->getAddonsAmount();
     379                $compatibilitySettings = $globalContext->getCompatibilitySettings();
     380                $dontApplyDiscountToAddons = $compatibilitySettings->getOption('dont_apply_discount_to_addons');
     381                if ($dontApplyDiscountToAddons) {
     382                    $third_party_adjustments += $item->getAddonsAmount() * $item->getQty();
     383                }
    384384            } elseif ($globalContext->isToCompensateTrdPartAdjustmentForFixedPrice()) {
    385385                $third_party_adjustments += $item->prices()->getTrdPartyAdjustmentsTotal();
     
    407407                }
    408408            }
     409        } else if(Discount::TYPE_FIXED_VALUE_PER_ITEM === $discountType) {
     410            $adjustments_left = $third_party_adjustments;
    409411        }
    410412
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Database/Models/Rule.php

    r3385738 r3443187  
    132132     */
    133133    public $summary;
     134
     135    /**
     136     * @var string
     137     */
     138    public $hash;
     139
     140    /**
     141     * @var string
     142     */
     143    public $date;
    134144
    135145    public function __construct(
     
    181191
    182192        $this->summary                = "";
     193        $this->hash                   = "";
     194        $this->date                   = null;
    183195    }
    184196
     
    306318        });
    307319
     320        $rule = $this->buildRule();
    308321        $data['summary'] = $this->buildSummary();
     322        $data['hash'] = $rule->getHash();
     323        $data['date'] = date('Y-m-d H:i:s', time());
    309324
    310325        return $data;
    311326    }
    312327
    313     /**
    314      * @return string
    315      */
    316     protected function buildSummary() {
     328    protected function buildRule() {
    317329        /** @var RuleStorage $ruleStorage */
    318330        $ruleStorage = Factory::get("Database_RuleStorage");
     
    329341
    330342        $rule = $rulesCol->getFirst();
     343
     344        return $rule;
     345    }
     346
     347    /**
     348     * @return string
     349     */
     350    protected function buildSummary() {
     351        $rule = $this->buildRule();
    331352
    332353        $pieces = [];
     
    465486            condition_message TEXT,
    466487            summary TEXT,
     488            hash VARCHAR(32),
     489            date datetime,
    467490            PRIMARY KEY  (id),
    468491            KEY deleted (deleted),
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Database/Repository/PersistentRuleRepository.php

    r3412190 r3443187  
    284284
    285285                    $processedProduct = $productProcessor->calculateProduct($product, 1.0, $cartItemData);
    286                    
     286
    287287                    remove_filter("adp_calculate_persistent_rule_product_hash", $customHash);
    288288                    $customer->setRoles($initialRoles);
     
    406406            return "'" . esc_sql($v) . "'";
    407407        }, $hash));
    408        
     408
    409409        global $wpdb;
    410410
     
    512512     */
    513513    protected function saveCacheInProductMetaData($product, $cache) {
     514        static $last_parent_id = false, $last_parent_min_price=0;
     515        global $wpdb;
     516
     517        $price = $cache['price'];
     518
    514519        // save calculated price in product meta
    515         update_post_meta($product->get_id(), '_sale_price_adp', $cache['price']);
     520        update_post_meta($product->get_id(), '_sale_price_adp', $price);
     521        //update lookup table too
     522        // phpcs:ignore WordPress.DB
     523        $wpdb->update( $wpdb->wc_product_meta_lookup, ['min_price' => $price],  ['product_id' => $product->get_id()] );
     524
    516525        if($product instanceof \WC_Product_Variation) {
    517             update_post_meta($product->get_parent_id('edit'), '_sale_price_adp', $cache['price']);
     526            $parent_id = $product->get_parent_id('edit');
     527            if( $last_parent_id == $parent_id){ // variations of same product processed still ?
     528                if($last_parent_min_price > $price) //use min price of variation
     529                    $last_parent_min_price = $price;
     530            } else {
     531                $last_parent_id = $parent_id;
     532                $last_parent_min_price = $price;
     533            }
     534
     535            update_post_meta($last_parent_id, '_sale_price_adp', $last_parent_min_price);
     536            // phpcs:ignore WordPress.DB
     537            $wpdb->update( $wpdb->wc_product_meta_lookup, ['min_price' => $last_parent_min_price],  ['product_id' => $last_parent_id] );
    518538        }
    519539    }
     
    522542        delete_post_meta_by_key('_sale_price_adp');
    523543    }
     544
     545    public function installHooksForProductLookupTable() {
     546        add_action( 'wc_update_product_lookup_tables_column', function($column){
     547            global $wpdb;
     548
     549            if($column !== 'min_max_price') return;
     550
     551            // phpcs:ignore WordPress.DB
     552            $sql = "UPDATE {$wpdb->wc_product_meta_lookup} lookup_table INNER JOIN {$wpdb->postmeta} meta ON lookup_table.product_id = meta.post_id AND meta.meta_key = '_sale_price_adp' SET lookup_table.min_price = meta.meta_value";
     553            // phpcs:ignore  WordPress.DB
     554            $wpdb->query($sql);
     555        } , 100 );
     556    }
    524557}
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Database/Repository/RuleRepository.php

    r3385738 r3443187  
    611611        $table = $wpdb->prefix . Rule::TABLE_NAME;
    612612
     613        $rules = $this->getRules(['id' => $rule_id]);
     614
     615        if (isset($rules[0]) && $rules[0] instanceof Rule) {
     616            $rule_data = $rules[0]->getDataForDB();
     617            $rule_data['deleted'] = 1;
     618        } else {
     619            $rule_data = null;
     620        }
     621
    613622        $data  = array('deleted' => 1);
    614623        $where = array('id' => $rule_id);
    615624        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
    616625        $wpdb->update($table, $data, $where);
     626
     627        do_action("adp_rule_deleted", $rule_id, $rule_data);
    617628    }
    618629
     
    630641            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
    631642            $wpdb->update($table, $data, $where);
     643            do_action("adp_rule_updated", $id, $data);
    632644
    633645            return $id;
     
    635647            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
    636648            $wpdb->insert($table, $data);
     649            do_action("adp_rule_added", $wpdb->insert_id, $data);
    637650
    638651            return $wpdb->insert_id;
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Database/RulesCollection.php

    r2661390 r3443187  
    9797        return new self($filtered_rules);
    9898    }
     99
     100    public function getHash($rules)
     101    {
     102        $hashes = array_values(array_map(function($rule) {
     103            return $rule->getHash();
     104        }, $rules));
     105
     106        $hash = md5(json_encode($hashes));
     107
     108        return $hash;
     109    }
    99110}
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Engine.php

    r3319660 r3443187  
    109109            $germanMarket->prepareHooks();
    110110        }
     111        if ($this->context->getOption("support_persistence_rules") ) {
     112            //must refill min_price when run >WooCommerce>Status>Tools>Product lookup tables, Regenerate
     113            $persistentRuleRepository = new PersistentRuleRepository();
     114            $persistentRuleRepository->installHooksForProductLookupTable();
     115        }
     116
    111117    }
    112118
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Functions.php

    r3297317 r3443187  
    451451    }
    452452
     453    //TODO: delete unused function
    453454    public function getProductsWithSalePriceAdp() {
    454455        global $wpdb;
     
    464465        return array_map('intval', $ids);
    465466    }
     467
     468    public function getOnSaleProducts($include_wc_onsale = false, $ruleIds = null){
     469        $productIds = [];
     470
     471        // get rules list
     472        if( $ruleIds AND !is_array($ruleIds) ){
     473            $ruleIds = [$ruleIds];
     474        }
     475        if( !$ruleIds ){
     476            $ruleIds = \ADP\BaseVersion\Includes\Shortcodes\OnSaleProducts::getActiveRules();
     477        }
     478
     479        //gather products
     480        foreach($ruleIds as $ruleId) {
     481            $productIds = array_merge( $productIds, \ADP\BaseVersion\Includes\Shortcodes\OnSaleProducts::getProductIdsByRuleId($ruleId) );
     482        }
     483
     484        //include WC onsale ?
     485        if( $include_wc_onsale ) {
     486            $productIds = array_merge( $productIds, wc_get_product_ids_on_sale());
     487        }
     488
     489        return array_unique($productIds);
     490    }
    466491}
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/PriceDisplay/WcProductProcessor/WcProductProcessorHelper.php

    r3222225 r3443187  
    1010use ADP\BaseVersion\Includes\PriceDisplay\ProcessedProductContainer;
    1111use WC_Product;
     12
     13if ( ! defined( 'ABSPATH' ) ) exit;
    1214
    1315class WcProductProcessorHelper
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/Settings/OptionsInstaller.php

    r3412190 r3443187  
    451451            ),
    452452            $builder::boolean(
     453                'dont_recalculate_cart_if_not_changed',
     454                true,
     455                __('Don\'t recalculate  cart if cart items don\'t have changed', 'advanced-dynamic-pricing-for-woocommerce')
     456            ),
     457            $builder::boolean(
    453458                'support_persistence_rules',
    454459                false,
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/WC/Utils.php

    r3205485 r3443187  
    44
    55use ADP\BaseVersion\Includes\Functions;
     6use ADP\Factory;
     7
     8if ( ! defined( 'ABSPATH' ) ) exit;
    69
    710class Utils
     
    6972            // Check if the shortcode is sale_products
    7073            if ($type === 'sale_products') {
    71                 $salePriceAdpProductIds = Functions::getInstance()->getProductsWithSalePriceAdp();
     74                // $salePriceAdpProductIds = Functions::getInstance()->getProductsWithSalePriceAdp();
     75
     76                $onSaleProducts = Factory::get("Shortcodes_OnSaleProducts");
     77                $salePriceAdpProductIds = $onSaleProducts->getCachedProductsIds();
    7278
    7379                // Merge the product IDs with the existing post__in array if it exists
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/WC/WcAdpMergedCouponHelper.php

    r3022127 r3443187  
    2929    public static function loadOfCouponCode($couponCode)
    3030    {
     31        global $wp_filter;
    3132        if (is_numeric($couponCode)) {
    3233            $couponCode = (string)$couponCode;
     
    4748            $coupon = new WcAdpMergedCoupon($couponCode);
    4849
     50            $oldHooks = $wp_filter['woocommerce_get_shop_coupon_data'];
     51            unset($wp_filter['woocommerce_get_shop_coupon_data']);
    4952            $wcCoupon = new \WC_Coupon();
     53            $wp_filter['woocommerce_get_shop_coupon_data'] = $oldHooks;
     54
    5055            $wcCoupon->set_code($couponCode);
    5156            if ($id = self::getCouponIdByCode($couponCode)) {
     
    5661
    5762            $coupon->setParts([new ExternalWcCoupon($wcCoupon, [])]);
     63            self::store($coupon);
    5864        }
    5965
     
    7581
    7682        if ($id === 0) {
    77             wp_cache_set(
    78                 \WC_Cache_Helper::get_cache_prefix('coupons') . 'coupon_id_from_code_' . $couponCode,
    79                 [],
    80                 'coupons'
    81             );
     83            $cacheKey = \WC_Cache_Helper::get_cache_prefix('coupons') . 'coupon_id_from_code_' . md5($couponCode);
     84            wp_cache_set($cacheKey, [], 'coupons');
    8285        }
    8386
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/Includes/WC/WcCartItemDisplayExtensions.php

    r3094267 r3443187  
    241241                        $originalPrice = $facade->getRegularPriceWithoutTax() + $facade->getRegularPriceTax();
    242242
    243                         $originalPrice += array_sum(
    244                             array_map(function ($child) use ($facade) {
    245                                 if ($child->isContaineredPricedIndividually()) {
    246                                     return ($child->getRegularPriceWithoutTax() + $child->getRegularPriceTax()) * $child->getQty() / $facade->getQty();
    247                                 } else {
    248                                     return 0.0;
    249                                 }
    250                             }, $children)
    251                         );
     243                        if(!apply_filters('adp_true_bundle_individ_price', false)) {
     244                            $originalPrice += array_sum(
     245                                array_map(function ($child) use ($facade) {
     246                                    if ($child->isContaineredPricedIndividually()) {
     247                                        return ($child->getRegularPriceWithoutTax() + $child->getRegularPriceTax()) * $child->getQty() / $facade->getQty();
     248                                    } else {
     249                                        return 0.0;
     250                                    }
     251                                }, $children)
     252                            );
     253                        }
    252254                    } else {
    253255                        $originalPrice = $facade->getOriginalPriceWithoutTax() + $facade->getOriginalPriceTax();
    254256
    255                         $originalPrice += array_sum(
    256                             array_map(function ($child) use ($facade) {
    257                                 if ($child->isContaineredPricedIndividually()) {
    258                                     return ($child->getOriginalPriceWithoutTax() + $child->getOriginalPriceTax()) * $child->getQty() / $facade->getQty();
    259                                 } else {
    260                                     return 0.0;
    261                                 }
    262                             }, $children)
    263                         );
     257                        if(!apply_filters('adp_true_bundle_individ_price', false)) {
     258                            $originalPrice += array_sum(
     259                                array_map(function ($child) use ($facade) {
     260                                    if ($child->isContaineredPricedIndividually()) {
     261                                        return ($child->getOriginalPriceWithoutTax() + $child->getOriginalPriceTax()) * $child->getQty() / $facade->getQty();
     262                                    } else {
     263                                        return 0.0;
     264                                    }
     265                                }, $children)
     266                            );
     267                        }
    264268                    }
    265269                } else {
     
    267271                        $originalPrice = $facade->getRegularPriceWithoutTax();
    268272
    269                         $originalPrice += array_sum(
    270                             array_map(function ($child) use ($facade) {
    271                                 if ($child->isContaineredPricedIndividually()) {
    272                                     return $child->getRegularPriceWithoutTax() * $child->getQty() / $facade->getQty();
    273                                 } else {
    274                                     return 0.0;
    275                                 }
    276                             }, $children)
    277                         );
     273                        if(!apply_filters('adp_true_bundle_individ_price', false)) {
     274                            $originalPrice += array_sum(
     275                                array_map(function ($child) use ($facade) {
     276                                    if ($child->isContaineredPricedIndividually()) {
     277                                        return $child->getRegularPriceWithoutTax() * $child->getQty() / $facade->getQty();
     278                                    } else {
     279                                        return 0.0;
     280                                    }
     281                                }, $children)
     282                            );
     283                        }
    278284                    } else {
    279285                        $originalPrice = $facade->getOriginalPriceWithoutTax();
    280286
    281                         $originalPrice += array_sum(
    282                             array_map(function ($child) use ($facade) {
    283                                 if ($child->isContaineredPricedIndividually()) {
    284                                     return $child->getOriginalPriceWithoutTax() * $child->getQty() / $facade->getQty();
    285                                 } else {
    286                                     return 0.0;
    287                                 }
    288                             }, $children)
    289                         );
     287                        if(!apply_filters('adp_true_bundle_individ_price', false)) {
     288                            $originalPrice += array_sum(
     289                                array_map(function ($child) use ($facade) {
     290                                    if ($child->isContaineredPricedIndividually()) {
     291                                        return $child->getOriginalPriceWithoutTax() * $child->getQty() / $facade->getQty();
     292                                    } else {
     293                                        return 0.0;
     294                                    }
     295                                }, $children)
     296                            );
     297                        }
    290298                    }
    291299                }
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/assets/js/rules.js

    r3412190 r3443187  
    529529          let $condition_block = $( this ).find('.wdp-condition');
    530530          if ( $condition_block.length ) {
    531             let $searchField = $condition_block.find( '.select2-search__field' );
    532             if ( ! $searchField.attr('disabled') ) {
    533               let $selectionRender = $condition_block.find( '.select2-selection__rendered' );
    534               let $inputFields = $condition_block.find( 'input' );
    535               let $textAreas = $condition_block.find( 'textarea' );
    536               let $qtyInputs = $condition_block.find( '.wdp-condition-field-qty' );
    537               let elements = [];
    538               let diff = [];
    539               for (let idx = 0; idx < $qtyInputs.length; idx++) {
    540                 if (idx % 2 === 0) {
    541                   diff.push($qtyInputs[idx]);
     531            let attachErrorTo = [];
     532            $condition_block.each(function () {
     533              let $searchField = $( this ).find( '.select2-search__field' );
     534              if ( ! $searchField.attr('disabled') ) {
     535                let $selectionRender = $( this ).find( '.select2-selection__rendered' );
     536                let $inputFields = $( this ).find( 'input' );
     537                let $textAreas = $( this ).find( 'textarea' );
     538                let $qtyInputs = $( this ).find( '.wdp-condition-field-qty' );
     539                let elements = [];
     540                let diff = [];
     541                for (let idx = 0; idx < $qtyInputs.length; idx++) {
     542                  if (idx % 2 === 0) {
     543                    diff.push($qtyInputs[idx]);
     544                  }
    542545                }
    543               }
    544               let attachErrorTo = [];
    545               if ($selectionRender.length) {
    546                 $selectionRender.each(function() {
    547                   elements.push($(this));
    548                 });
    549               }
    550               if ($inputFields.length) {
    551                 $inputFields.each(function () {
    552                   let $parent = $(this).parent();
    553                   let parentClasses = $parent.attr('class');
    554                   if ($(this).attr('type') !== 'checkbox'
    555                     && ! parentClasses.includes('select2')
    556                     && ! parentClasses.includes('qty')
    557                   ) {
     546
     547                if ($selectionRender.length) {
     548                  $selectionRender.each(function() {
    558549                    elements.push($(this));
     550                  });
     551                }
     552                if ($inputFields.length) {
     553                  $inputFields.each(function () {
     554                    let $parent = $(this).parent();
     555                    let parentClasses = $parent.attr('class');
     556                    if ($(this).attr('type') !== 'checkbox'
     557                      && ! parentClasses.includes('select2')
     558                      && ! parentClasses.includes('qty')
     559                    ) {
     560                      elements.push($(this));
     561                    }
     562                  });
     563                }
     564                if ($textAreas.length) {
     565                  elements = elements.concat($textAreas);
     566                }
     567                elements.filter(x => diff.includes(x));
     568                elements.forEach(function (el) {
     569                  if (el[0].localName !== 'input' && el[0].localName !== 'textarea') {
     570                    if (! el[0].textContent.length || el[0].textContent === 'Select value') {
     571                      beforeSendValidation = false;
     572                      attachErrorTo.push(el);
     573                    }
     574                  } else if (! el.val().length) {
     575                    beforeSendValidation = false;
     576                    attachErrorTo.push(el);
     577                  } else if(el.hasClass('hasDatepicker') && !el.val().match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/)) {
     578                    beforeSendValidation = false;
     579                    el.data('customError', 'Incorrect date format');
     580                    attachErrorTo.push(el);
     581                  } else if(el.hasClass('datetimepicker') && !el.val().match(/^(\d{4})\/(\d{1,2})\/(\d{1,2}) (\d{1,2}):(\d{1,2})$/)) {
     582                    beforeSendValidation = false;
     583                    el.data('customError', 'Incorrect date format');
     584                    attachErrorTo.push(el);
    559585                  }
    560586                });
    561587              }
    562               if ($textAreas.length) {
    563                 elements = elements.concat($textAreas);
     588            });
     589
     590            attachErrorTo.forEach(function (val) {
     591              if (!beforeSendValidation && !val.next('.cart-conditions__error-wrapper').length) {
     592                let $elEmptyValue = $("<div class=\"cart-conditions__error-wrapper\"><span class=\"cart-conditions__onempty-error\"></span></div>");
     593                val.after($elEmptyValue);
     594                $elEmptyValue.find('.cart-conditions__onempty-error').text(val.data('customError') || 'You must provide at least one value');
     595                val.removeData("customError");
     596                setTimeout(function () {
     597                  $form.find('.inside .cart-conditions__error-wrapper').remove();
     598                }, 5000);
    564599              }
    565               elements.filter(x => diff.includes(x));
    566               elements.forEach(function (el) {
    567                 if (el[0].localName !== 'input' && el[0].localName !== 'textarea') {
    568                   if (! el[0].textContent.length || el[0].textContent === 'Select value') {
    569                     beforeSendValidation = false;
    570                     attachErrorTo.push(el);
    571                   }
    572                 } else if (! el.val().length) {
    573                   beforeSendValidation = false;
    574                   attachErrorTo.push(el);
    575                 } else if(el.hasClass('hasDatepicker') && !el.val().match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/)) {
    576                   beforeSendValidation = false;
    577                   el.data('customError', 'Incorrect date format');
    578                   attachErrorTo.push(el);
    579                 } else if(el.hasClass('datetimepicker') && !el.val().match(/^(\d{4})\/(\d{1,2})\/(\d{1,2}) (\d{1,2}):(\d{1,2})$/)) {
    580                   beforeSendValidation = false;
    581                   el.data('customError', 'Incorrect date format');
    582                   attachErrorTo.push(el);
    583                 }
    584               });
    585               attachErrorTo.forEach(function (val) {
    586                 if (!beforeSendValidation && !val.next('.cart-conditions__error-wrapper').length) {
    587                   let $elEmptyValue = $("<div class=\"cart-conditions__error-wrapper\"><span class=\"cart-conditions__onempty-error\"></span></div>");
    588                   val.after($elEmptyValue);
    589                   $elEmptyValue.find('.cart-conditions__onempty-error').text(val.data('customError') || 'You must provide at least one value');
    590                   val.removeData("customError");
    591                   setTimeout(function () {
    592                     $form.find('.inside .cart-conditions__error-wrapper').remove();
    593                   }, 5000);
    594                 }
    595               });
    596             }
     600            });
    597601          }
    598602        });
     
    24082412            var disabled = [ 'at_least_one_any', 'none_at_all' ].indexOf( $( this ).val() ) >= 0;
    24092413            $container.find('.wdp-condition-field-value-coupon select').prop('disabled', disabled);
    2410             if ( disabled ) {
    2411                 $container.find('.wdp-condition-field-value-coupon select').val([]).trigger('change');
    2412             }
    24132414        } );
    24142415
     
    24162417            var disabled = [ 'at_least_one_any', 'none_at_all' ].indexOf( $( this ).val() ) >= 0;
    24172418            $container.find('.wdp-condition-field-value-coupon select').prop('disabled', disabled);
    2418             if ( disabled ) {
    2419                 $container.find('.wdp-condition-field-value-coupon select').val([]).trigger('change');
    2420             }
    24212419        } );
    24222420
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/views/admin_page/tabs/options/reset_settings.php

    r3297317 r3443187  
     1<?php if ( ! defined( 'ABSPATH' ) ) exit; ?>
    12<tr valign="top">
    23    <th scope="row" class="titledesc">
  • advanced-dynamic-pricing-for-woocommerce/trunk/BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php

    r3297317 r3443187  
    66
    77use ADP\BaseVersion\Includes\Database\Repository\RuleRepository;
     8
     9if ( ! defined( 'ABSPATH' ) ) exit;
    810
    911$repo = new RuleRepository();
  • advanced-dynamic-pricing-for-woocommerce/trunk/advanced-dynamic-pricing-for-woocommerce.php

    r3414625 r3443187  
    11<?php
    22/**
    3  * Plugin Name: Advanced Dynamic Pricing and Discount Rules for WooCommerce
     3 * Plugin Name: Advanced Dynamic Pricing and Discount Rules for WooCommerce (Pro)
    44 * Plugin URI:
    55 * Description: Manage WooCommerce discounts
    6  * Version: 4.10.5
     6 * Version: 4.11.0
    77 * Author: AlgolPlus
    88 * Author URI: https://algolplus.com/
     
    4444define('WC_ADP_MIN_PHP_VERSION', '7.0.0');
    4545define('WC_ADP_MIN_WC_VERSION', '3.6');
    46 define('WC_ADP_VERSION', '4.10.5');
     46define('WC_ADP_VERSION', '4.11.0');
    4747define('WC_ADP_WC_TIPTIP_SINCE_VERSION', '10.3');
    4848
  • advanced-dynamic-pricing-for-woocommerce/trunk/languages/advanced-dynamic-pricing-for-woocommerce.pot

    r3412190 r3443187  
    33msgstr ""
    44"Project-Id-Version: Advanced Dynamic Pricing and Discount Rules for "
    5 "WooCommerce (Pro)\n"
     5"WooCommerce\n"
    66"Report-Msgid-Bugs-To: \n"
    7 "POT-Creation-Date: 2025-12-05 12:23+0000\n"
     7"POT-Creation-Date: 2026-01-20 11:13+0000\n"
    88"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    99"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     
    1515"Content-Transfer-Encoding: 8bit\n"
    1616"X-Generator: Loco https://localise.biz/\n"
    17 "X-Loco-Version: 2.8.0; wp-6.9-RC3; php-8.4.6\n"
     17"X-Loco-Version: 2.8.1; wp-6.9-RC3; php-8.4.6\n"
    1818"X-Domain: advanced-dynamic-pricing-for-woocommerce"
    1919
     
    246246
    247247#. Name of the plugin
    248 msgid "Advanced Dynamic Pricing and Discount Rules for WooCommerce (Pro)"
     248msgid "Advanced Dynamic Pricing and Discount Rules for WooCommerce"
    249249msgstr ""
    250250
     
    272272msgstr ""
    273273
    274 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:263
     274#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:264
    275275msgid "Advertising"
    276276msgstr ""
     
    385385#: BaseVersion/Includes/Settings/OptionsInstaller.php:361
    386386#: BaseVersion/Includes/Settings/OptionsInstaller.php:387
    387 #: BaseVersion/Includes/Settings/OptionsInstaller.php:461
     387#: BaseVersion/Includes/Settings/OptionsInstaller.php:466
    388388#: BaseVersion/views/admin_page/tabs/rules.php:94
    389389#: BaseVersion/views/admin_page/tabs/options/external_coupons_behavior.php:19
     
    660660msgstr ""
    661661
    662 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:237
     662#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:238
    663663msgid "Bulk table"
    664664msgstr ""
     
    718718#: BaseVersion/templates/reporter/main.php:20
    719719#: BaseVersion/Includes/Core/Rule/CartCondition/ConditionsLoader.php:75
    720 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:212
     720#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:213
    721721msgid "Cart"
    722722msgstr ""
     
    764764msgstr ""
    765765
    766 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:230
     766#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:231
    767767msgid "Category page"
    768768msgstr ""
     
    904904#: BaseVersion/Includes/Debug/DebugBar.php:71
    905905#: BaseVersion/Includes/Core/Rule/CartAdjustment/CartAdjustmentsLoader.php:50
    906 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:254
     906#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:255
    907907msgid "Coupons"
    908908msgstr ""
     
    10031003msgstr ""
    10041004
    1005 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:299
     1005#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:300
    10061006msgid "Debug"
    10071007msgstr ""
     
    10571057#: BaseVersion/Includes/Settings/OptionsInstaller.php:374
    10581058#: BaseVersion/Includes/Settings/OptionsInstaller.php:396
    1059 #: BaseVersion/Includes/Settings/OptionsInstaller.php:464
     1059#: BaseVersion/Includes/Settings/OptionsInstaller.php:469
    10601060#: BaseVersion/views/admin_page/tabs/options/external_coupons_behavior.php:27
    10611061#: BaseVersion/views/admin_page/tabs/options/external_coupons_behavior.php:46
     
    10651065#: BaseVersion/Includes/Settings/OptionsInstaller.php:370
    10661066#: BaseVersion/Includes/Settings/OptionsInstaller.php:392
    1067 #: BaseVersion/Includes/Settings/OptionsInstaller.php:462
     1067#: BaseVersion/Includes/Settings/OptionsInstaller.php:467
    10681068#: BaseVersion/views/admin_page/tabs/options/external_coupons_behavior.php:23
    10691069#: BaseVersion/views/admin_page/tabs/options/external_coupons_behavior.php:42
     
    11811181#: BaseVersion/views/admin_page/tabs/tools/import_rule_csv.php:64
    11821182msgid "Don't optimize the rules during importing"
     1183msgstr ""
     1184
     1185#: BaseVersion/Includes/Settings/OptionsInstaller.php:455
     1186#: BaseVersion/views/admin_page/tabs/options/dont_recalculate_cart_if_not_changed.php:7
     1187#: BaseVersion/views/admin_page/tabs/options/dont_recalculate_cart_if_not_changed.php:12
     1188msgid "Don't recalculate  cart if cart items don't have changed"
    11831189msgstr ""
    11841190
     
    12501256msgstr ""
    12511257
    1252 #: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:22
     1258#: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:24
    12531259msgid "Export into CSV"
    12541260msgstr ""
     
    12581264msgstr ""
    12591265
    1260 #: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:15
     1266#: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:17
    12611267msgid "Export rules with non-empty bulk ranges as CSV"
    12621268msgstr ""
     
    12661272msgstr ""
    12671273
    1268 #: BaseVersion/Includes/Settings/OptionsInstaller.php:459
     1274#: BaseVersion/Includes/Settings/OptionsInstaller.php:464
    12691275#: BaseVersion/views/admin_page/tabs/options/external_coupons_behavior.php:9
    12701276msgid "External coupons"
     
    14111417
    14121418#: BaseVersion/Includes/Helpers/Helpers.php:573
    1413 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:247
     1419#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:248
    14141420#: BaseVersion/views/admin_page/tabs/rules/persistent_rule.php:571
    14151421#: BaseVersion/views/admin_page/tabs/rules/rule.php:564
     
    15291535msgstr ""
    15301536
     1537#: BaseVersion/Includes/Settings/OptionsInstaller.php:487
     1538msgid "Highlight rows (on hover) and set qty on click"
     1539msgstr ""
     1540
    15311541#: BaseVersion/Includes/Settings/OptionsInstaller.php:482
    1532 msgid "Highlight rows (on hover) and set qty on click"
    1533 msgstr ""
    1534 
    1535 #: BaseVersion/Includes/Settings/OptionsInstaller.php:477
    15361542msgid "Highlight selected range when qty changed"
    15371543msgstr ""
     
    15921598
    15931599#: BaseVersion/views/admin_page/tabs/tools/backup.php:89
    1594 #: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:35
     1600#: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:37
    15951601#: BaseVersion/views/admin_page/tabs/tools/import_rule_csv.php:58
    15961602msgid "Import"
     
    20172023msgstr ""
    20182024
    2019 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:268
     2025#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:269
    20202026msgid "Order"
    20212027msgstr ""
     
    20692075msgstr ""
    20702076
    2071 #: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:40
     2077#: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:42
    20722078msgid "Please, create some bulk rules at first"
    20732079msgstr ""
     
    22252231msgstr ""
    22262232
    2227 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:221
     2233#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:222
    22282234msgid "Product page"
    22292235msgstr ""
    22302236
    2231 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:200
     2237#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:201
    22322238msgid "Product price"
    22332239msgstr ""
     
    23862392msgstr ""
    23872393
    2388 #: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:26
     2394#: BaseVersion/views/admin_page/tabs/tools/manage_bulk_ranges.php:28
    23892395msgid "Re-import CSV to update ranges for EXISTING rules"
    23902396msgstr ""
     
    24152421msgstr ""
    24162422
    2417 #: BaseVersion/Includes/Settings/OptionsInstaller.php:472
     2423#: BaseVersion/Includes/Settings/OptionsInstaller.php:477
    24182424msgid "Read-only quantity for free products"
    24192425msgstr ""
     
    24372443msgstr ""
    24382444
    2439 #: BaseVersion/Includes/CartProcessor/CartProcessor.php:1083
     2445#: BaseVersion/Includes/CartProcessor/CartProcessor.php:1109
    24402446msgid "Removed {{qty}} free {{product_name}}"
    24412447msgstr ""
     
    24682474msgstr ""
    24692475
    2470 #: BaseVersion/views/admin_page/tabs/options/reset_settings.php:4
     2476#: BaseVersion/views/admin_page/tabs/options/reset_settings.php:5
    24712477msgid "Reset settings to default values"
    24722478msgstr ""
     
    25342540#: BaseVersion/templates/reporter/main.php:24
    25352541#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Rules.php:97
    2536 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:275
     2542#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:276
    25372543#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Tools.php:63
    25382544#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Tools.php:481
     
    29592965msgstr ""
    29602966
    2961 #: BaseVersion/Includes/Settings/OptionsInstaller.php:455
     2967#: BaseVersion/Includes/Settings/OptionsInstaller.php:460
    29622968#: BaseVersion/views/admin_page/tabs/options/support_persistence_rules.php:7
    29632969#: BaseVersion/views/admin_page/tabs/options/support_persistence_rules.php:17
     
    29832989msgstr ""
    29842990
    2985 #: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:288
     2991#: BaseVersion/Includes/AdminExtensions/AdminPage/Tabs/Options.php:289
    29862992msgid "System"
    29872993msgstr ""
  • advanced-dynamic-pricing-for-woocommerce/trunk/readme.txt

    r3415707 r3443187  
    184184== Changelog ==
    185185
     186= 4.11.0 - 2026-01-21 =
     187* This release dedicated to speed
     188* Added option "Don't recalculate  cart if cart items don't have changed"  (>Settings>Calculation, default ON)
     189* Added another cache, to avoid unnecessary coupon calculations
     190* Fixed bug - wrong key when caching shipping rates
     191* WooCommerce [products on_sale] shortcode displays products modified by our plugin, but you must enable shortcode [adp_products_on_sale](https://docs.algolplus.com/algol_pricing/settings-algol_pricing/rules/)
     192* If you want sort products by price at shop page - please use [Product Only](https://docs.algolplus.com/algol_pricing/rules/product-only-rule-type/) rules
     193* Updated compatibility with "WPC Product Bundles for WooCommerce"
     194* Updated compatibility with "WooCommerce Product Bundles"
     195* Updated compatibility with "YITH WooCommerce Product Bundles"
     196* Updated compatibility with WOOCS
     197* Updated compatibility with "WooCommerce Product Addons"
     198* Updated compatibility with "Yoast SEO: WooCommerce"
     199* Updated compatibility with "TM Extra product options"
     200* DEV - new helper function [getOnSaleProducts](https://docs.algolplus.com/algol_pricing/developers-algol_pricing/helpers/)
     201* DEV - added hooks "adp_rule_added", "adp_rule_updated", "adp_rule_deleted"
     202
    186203= 4.10.5 - 2025-12-09 =
    187204* Fixed critical bug - broken compatibility with some bundle/composite plugins
Note: See TracChangeset for help on using the changeset viewer.