PluginProbe
Tiered Pricing Table for WooCommerce / 8.0.2
Tiered Pricing Table for WooCommerce v8.0.2
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
← All changes | src/Integrations/Plugins/MixMatch.php +121 -6 2.3.3 → 8.0.2 View file →
@@ -1,16 +1,131 @@
1 1 <?php namespace TierPricingTable\Integrations\Plugins;
2 2
3 -class MixMatch {
3 +use TierPricingTable\Integrations\Plugins\MixMatch\Settings as MixMatchSettings;
4 +use WC_Product;
4 5
5 - public function __construct() {
6 - add_filter( 'tier_pricing_table/cart/need_price_recalculation', function ( $bool, $cart_item ) {
6 +/**
7 + * Compatibility with WooCommerce Mix and Match Products.
8 + *
9 + * Container lines are never re-priced by tiered pricing: the Mix and Match plugin owns the
10 + * container's price, and re-pricing it would charge the tier price on top of the contents.
11 + *
12 + * Child items (the products inside a container) are excluded by default. The "Apply tiered pricing
13 + * inside containers" setting lets tiered pricing discount them — only for containers with per-item
14 + * pricing, where every child line carries its own real price. Children of statically priced
15 + * containers always stay untouched.
16 + */
17 +class MixMatch extends PluginIntegrationAbstract {
7 18
8 - if ( isset( $cart_item['mnm_container'] ) ) {
19 + public function run() {
20 +
21 + add_action( 'plugins_loaded', function () {
22 +
23 + if ( ! class_exists( 'WC_Mix_and_Match' ) ) {
24 + return;
25 + }
26 +
27 + add_filter( 'tiered_pricing_table/settings/sections', function ( $sections ) {
28 + $sections[] = new MixMatchSettings();
29 +
30 + return $sections;
31 + } );
32 + } );
33 +
34 + // Charging + subtotal column.
35 + add_filter( 'tiered_pricing_table/cart/need_price_recalculation',
36 + array( $this, 'filterNeedPriceRecalculation' ), 10, 2 );
37 +
38 + // Price column / mini cart — kept in sync with the charging decision.
39 + add_filter( 'tiered_pricing_table/cart/need_price_recalculation/item',
40 + array( $this, 'filterNeedPriceRecalculation' ), 10, 2 );
41 + }
42 +
43 + /**
44 + * Decide whether a cart item may be re-priced by tiered pricing.
45 + *
46 + * @param bool $state
47 + * @param array $cartItem
48 + *
49 + * @return bool
50 + */
51 + public function filterNeedPriceRecalculation( $state, $cartItem ) {
52 +
53 + // The container line itself: never re-price it. Its price belongs to Mix and Match, and a
54 + // matching pricing rule would otherwise charge the tier price on top of the contents.
55 + if ( isset( $cartItem['mnm_contents'] ) || isset( $cartItem['mnm_config'] ) ) {
56 + return false;
57 + }
58 +
59 + if ( isset( $cartItem['mnm_container'] ) ) {
60 +
61 + if ( ! $this->shouldPriceChildItems() ) {
9 62 return false;
10 63 }
11 64
12 - return $bool;
65 + // Only children of per-item-priced containers carry their own real price. Children of
66 + // statically priced containers are handled entirely by Mix and Match.
67 + return $this->isChildOfPerItemPricedContainer( $cartItem ) ? $state : false;
68 + }
13 69
14 - }, 10, 2 );
70 + return $state;
71 + }
72 +
73 + /**
74 + * Whether the "Apply tiered pricing inside containers" setting is enabled.
75 + *
76 + * @return bool
77 + */
78 + protected function shouldPriceChildItems(): bool {
79 + return $this->getContainer()->getSettings()->get( MixMatchSettings::PRICE_CHILD_ITEMS_KEY, 'no' ) === 'yes';
80 + }
81 +
82 + /**
83 + * Whether a child cart item belongs to a container with per-item pricing.
84 + *
85 + * @param array $cartItem
86 + *
87 + * @return bool
88 + */
89 + protected function isChildOfPerItemPricedContainer( array $cartItem ): bool {
90 +
91 + $containerItem = null;
92 +
93 + if ( function_exists( 'wc_mnm_get_cart_item_container' ) ) {
94 + $containerItem = wc_mnm_get_cart_item_container( $cartItem );
95 + } elseif ( isset( $cartItem['mnm_container'], wc()->cart->cart_contents[ $cartItem['mnm_container'] ] ) ) {
96 + $containerItem = wc()->cart->cart_contents[ $cartItem['mnm_container'] ];
97 + }
98 +
99 + $container = is_array( $containerItem ) ? ( $containerItem['data'] ?? null ) : null;
100 +
101 + if ( ! ( $container instanceof WC_Product ) || ! is_callable( array( $container, 'is_priced_per_product' ) ) ) {
102 + return false;
103 + }
104 +
105 + return (bool) $container->is_priced_per_product();
106 + }
107 +
108 + public function getIconURL(): string {
109 + return $this->getContainer()->getFileManager()->locateAsset( 'admin/integrations/mix-match-icon.png' );
110 + }
111 +
112 + public function getAuthorURL(): string {
113 + return 'https://woocommerce.com/products/woocommerce-mix-and-match-products/';
114 + }
115 +
116 + public function getTitle(): string {
117 + return 'Mix&Match for WooCommerce';
118 + }
119 +
120 + public function getDescription(): string {
121 + return __( 'Apply tiered pricing rules correctly to Mix and Match products.', 'tier-pricing-table' );
122 + }
123 +
124 + public function getSlug(): string {
125 + return 'mix-match-for-woocommerce';
126 + }
127 +
128 + public function getIntegrationCategory(): string {
129 + return 'custom_product_types';
15 130 }
16 131 }