1.7.0: shipping rule "Only" reserves a method, "Show" no longer does

Since 1.6.0 "Show" both whitelisted a method for its group and hid it from
everybody else. A group shown ordinary methods next to a free one therefore
took the ordinary ones away from every stranger, who was left with only the
free method. "Only" now carries the reservation; "Show" is just the group's
whitelist. Existing show rules are converted to only once on update so the
checkout does not change until the shop chooses.

Co-Authored-By: Claude Code <[email protected]>
This commit is contained in:
kristianwind
2026-10-02 12:28:45 +02:00
co-authored by Claude Code
parent 5875638f2c
commit 0793a1ee82
11 changed files with 129 additions and 37 deletions
+52 -5
View File
@@ -184,7 +184,7 @@ WC_EDM_DB::replace_shipping_rules(
// shape. A rule holding a bare method id silently matches nothing, and the
// "never leave the customer without shipping" fallback then hands back
// every rate, so the misconfiguration looks exactly like no rule at all.
array( array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'show', 'sort_order' => 0 ) )
array( array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'only', 'sort_order' => 0 ) )
);
$rates = array(
@@ -194,7 +194,7 @@ $rates = array(
WC()->customer->set_billing_email( '[email protected]' );
$filtered = wc_edm()->frontend->filter_shipping_rates( $rates, array() );
wc_edm_is( 'a "show" rule hides every method it does not name', array( 'flat_rate:1' ), array_keys( $filtered ) );
wc_edm_is( 'an "only" rule hides every method it does not name', array( 'flat_rate:1' ), array_keys( $filtered ) );
// 🔴 This used to assert "an unmatched customer sees every method", which is
// what made a reserved free-delivery method visible to everybody on a live
@@ -212,8 +212,8 @@ wc_edm_is(
WC_EDM_DB::replace_shipping_rules(
(int) $fixtures['group_id'],
array(
array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'show', 'sort_order' => 0 ),
array( 'shipping_method_id' => 'local_pickup:2', 'action' => 'show', 'sort_order' => 1 ),
array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'only', 'sort_order' => 0 ),
array( 'shipping_method_id' => 'local_pickup:2', 'action' => 'only', 'sort_order' => 1 ),
)
);
$filtered = wc_edm()->frontend->filter_shipping_rates( $rates, array() );
@@ -221,7 +221,7 @@ wc_edm_is( 'but is never left with no shipping at all', 2, count( $filtered ) );
WC_EDM_DB::replace_shipping_rules(
(int) $fixtures['group_id'],
array( array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'show', 'sort_order' => 0 ) )
array( array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'only', 'sort_order' => 0 ) )
);
// A SECOND group, with no rules of its own. Its members must not see what the
@@ -267,6 +267,53 @@ wc_edm_ok(
'saw: ' . implode( ', ', array_keys( $filtered ) )
);
// 🔴 "show" is a whitelist for the group and reserves NOTHING. 1.6.0 made it
// do both, so a shop that listed ordinary methods next to a free-delivery one
// took the ordinary ones away from every stranger and left them only the
// free one (reported live: strangers saw nothing but "Fri levering").
WC_EDM_DB::replace_shipping_rules(
(int) $fixtures['group_id'],
array(
array( 'shipping_method_id' => 'flat_rate:1', 'action' => 'show', 'sort_order' => 0 ),
array( 'shipping_method_id' => 'local_pickup:2', 'action' => 'only', 'sort_order' => 1 ),
)
);
WC()->customer->set_billing_email( '[email protected]' );
$filtered = wc_edm()->frontend->filter_shipping_rates( $wc_edm_rates3, array() );
wc_edm_is(
'a stranger keeps a "show" method and loses the "only" one',
array( 'flat_rate:1', 'flat_rate:9' ),
array_keys( $filtered )
);
WC()->customer->set_billing_email( '[email protected]' );
$filtered = wc_edm()->frontend->filter_shipping_rates( $wc_edm_rates3, array() );
wc_edm_is(
'a group member sees both its "show" and its "only" method, in rule order',
array( 'flat_rate:1', 'local_pickup:2' ),
array_keys( $filtered )
);
// The update from 1.6.x: rows written as "show" were reserved, and must stay so.
global $wpdb;
$wc_edm_table = WC_EDM_DB::table( 'shipping_rules' );
WC_EDM_DB::replace_shipping_rules( (int) $fixtures['group_id'], array() );
$wpdb->insert( $wc_edm_table, array( 'group_id' => (int) $fixtures['group_id'], 'shipping_method_id' => 'local_pickup:2', 'action' => 'show', 'sort_order' => 0 ) );
delete_option( 'wc_edm_show_to_only_done' );
WC_EDM_DB::create_tables();
wc_edm_is(
'an update turns every old "show" rule into "only"',
array( 'only' ),
$wpdb->get_col( $wpdb->prepare( "SELECT action FROM {$wc_edm_table} WHERE group_id = %d", (int) $fixtures['group_id'] ) ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
);
$wpdb->update( $wc_edm_table, array( 'action' => 'show' ), array( 'shipping_method_id' => 'local_pickup:2' ) );
WC_EDM_DB::create_tables();
wc_edm_is(
'and does it once only: a later "show" stays "show"',
array( 'show' ),
$wpdb->get_col( $wpdb->prepare( "SELECT action FROM {$wc_edm_table} WHERE group_id = %d", (int) $fixtures['group_id'] ) ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
);
WC()->customer->set_billing_email( '[email protected]' );
WC_EDM_DB::replace_shipping_rules( (int) $fixtures['group_id'], array() );