Skip to content

Commit 9eeed25

Browse files
mjoslynclaude
andcommitted
Bulk pricing table follows the admin-bar switcher role
The [pricebook_bulk_table] / [pricebook_bulk_pricing_applies] shortcodes (via bulk_sections) resolved the current view's tier with user_pricing_role(), which only reads the user's own roles. A manager previewing a specific ROLE through the admin-bar switcher was ignored, so the table stayed hidden even when the previewed role had quantity breaks. bulk_sections now takes the manager's switcher role first (mirroring active_tier_label() and the engine's switcher precedence), then falls back to the pricing user's own tier (which already honors a switcher-impersonated user via pricing_user_id). Net: the table shows exactly when the currently-previewed pricing — the current user's tier, or the switcher's role/user — has bulk breaks. Adds a shortcode_atts test shim and ShortcodesTest covering the three cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 4bd8061 commit 9eeed25

3 files changed

Lines changed: 103 additions & 3 deletions

File tree

src/Shortcodes.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,20 @@ private function bulk_sections( $product_id, $role ) {
221221
} elseif ( '' !== $role ) {
222222
$role_keys = isset( $tiers[ $role ] ) ? array( $role ) : array();
223223
} else {
224-
if ( $this->engine->user_has_override( $product_id ) ) {
225-
return array();
224+
// Reflect the admin-bar switcher so the table shows exactly when the
225+
// currently-previewed pricing has quantity breaks: a manager previewing a
226+
// specific ROLE uses that role; a manager previewing a USER (or a normal
227+
// customer) uses that user's own tier via pricing_user_id(). Mirrors
228+
// active_tier_label() and the engine's switcher precedence.
229+
$active = $this->context->is_manager() ? $this->context->switcher_role() : '';
230+
if ( '' === $active ) {
231+
// Pricing as an actual user: a per-user negotiated override suppresses
232+
// bulk (the negotiated price wins). Not relevant to a previewed role.
233+
if ( $this->engine->user_has_override( $product_id ) ) {
234+
return array();
235+
}
236+
$active = $this->context->user_pricing_role( $this->context->pricing_user_id() );
226237
}
227-
$active = $this->context->user_pricing_role( $this->context->pricing_user_id() );
228238
$role_keys = ( '' !== $active && isset( $tiers[ $active ] ) ) ? array( $active ) : array();
229239
}
230240

tests/ShortcodesTest.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
/**
3+
* Shortcodes tests: bulk-pricing visibility follows the effective pricing view.
4+
*
5+
* @package WCPricebook\Tests
6+
*/
7+
8+
declare( strict_types=1 );
9+
10+
namespace WCPricebook\Tests;
11+
12+
/**
13+
* @covers \WCPricebook\Shortcodes
14+
*/
15+
class ShortcodesTest extends TestCase {
16+
17+
/**
18+
* @return \WCPricebook\Shortcodes
19+
*/
20+
private function shortcodes() {
21+
return new \WCPricebook\Shortcodes( $this->config, $this->context, $this->engine );
22+
}
23+
24+
/**
25+
* @return void
26+
*/
27+
private function seed_dealer_bulk_product() {
28+
$this->set_meta(
29+
10,
30+
array(
31+
'_regular_price' => '100',
32+
'dealer_price' => '70',
33+
'_pricebook_bulk_pricing' => array( 'dealer' => array( array( 'min_qty' => 10, 'price' => '65' ) ) ),
34+
)
35+
);
36+
}
37+
38+
public function test_bulk_applies_for_current_user_with_bulk_tier() {
39+
$this->seed_dealer_bulk_product();
40+
Store::add_user( 5, array( 'dealer' ), array( 'dealer' ) );
41+
Store::$current_user = 5;
42+
43+
$this->assertSame( '1', $this->shortcodes()->render_bulk_applies( array( 'product' => 10 ) ) );
44+
}
45+
46+
public function test_bulk_hidden_for_user_without_bulk_tier() {
47+
$this->seed_dealer_bulk_product();
48+
Store::add_user( 6, array( 'customer' ), array() );
49+
Store::$current_user = 6;
50+
51+
$this->assertSame( '', $this->shortcodes()->render_bulk_applies( array( 'product' => 10 ) ) );
52+
}
53+
54+
public function test_bulk_follows_manager_switcher_role() {
55+
// A manager who is NOT a dealer, previewing as 'dealer' via the admin-bar
56+
// switcher, must see the bulk table — the shortcode reflects the switcher
57+
// role, not the manager's own roles.
58+
$this->seed_dealer_bulk_product();
59+
Store::add_user( 9, array( 'shop_manager' ), array( 'manage_woocommerce' ) );
60+
Store::$current_user = 9;
61+
$sc = $this->shortcodes();
62+
63+
// No switcher: the manager holds no bulk tier of their own -> hidden.
64+
$this->assertSame( '', $sc->render_bulk_applies( array( 'product' => 10 ) ) );
65+
66+
// Switcher set to 'dealer' (a role with a bulk break) -> shown.
67+
Store::$user_meta[9]['pricebook_switcher_role'] = 'dealer';
68+
$this->assertSame( '1', $sc->render_bulk_applies( array( 'product' => 10 ) ) );
69+
}
70+
}

tests/wp-shims.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,23 @@ function current_user_can( $capability, ...$args ) {
314314
return ! empty( Store::$user_caps[ $id ][ $capability ] );
315315
}
316316
}
317+
318+
if ( ! function_exists( 'shortcode_atts' ) ) {
319+
/**
320+
* Merge user shortcode attributes over defaults (the WordPress semantics: only
321+
* keys present in $defaults survive).
322+
*
323+
* @param array<string,mixed> $defaults Default attributes.
324+
* @param mixed $atts Supplied attributes.
325+
* @param string $shortcode Shortcode tag (unused here).
326+
* @return array<string,mixed>
327+
*/
328+
function shortcode_atts( $defaults, $atts, $shortcode = '' ) {
329+
$atts = (array) $atts;
330+
$out = array();
331+
foreach ( (array) $defaults as $name => $default ) {
332+
$out[ $name ] = array_key_exists( $name, $atts ) ? $atts[ $name ] : $default;
333+
}
334+
return $out;
335+
}
336+
}

0 commit comments

Comments
 (0)