Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions assets/wp/js/form-billing-address.js
Original file line number Diff line number Diff line change
Expand Up @@ -825,19 +825,18 @@
if (window.console) console.log('[KiriminAja] Persist district selection', data);
var updateKey = kiriofBuildBlockCartUpdateKey(data);
if (updateKey && updateKey === kiriofLastBlockCartUpdateKey) {
if (window.console) console.log('[KiriminAja] District already persisted (dedup), refreshing rates');
kiriofScheduleBlockShippingRatesRefresh(160);
kiriofForceBlockCartUpdate(data.destination_name || '', data.destination_id || '');
if (window.console) console.log('[KiriminAja] District already persisted (dedup)');
return;
}

kiriofLastBlockCartUpdateKey = updateKey;

function kiriofAfterBlockDistrictPersist() {
kiriofScheduleBlockShippingRatesRefresh(80);
kiriofSyncBlockDistrictWarningState();
}

// Save session data (insurance, payment_method, destination) via AJAX
// as fallback when extensionCartUpdate is not available.
function kiriofPersistBlockDistrictFallback() {
var ajaxUrl = (typeof kiriofAjax !== 'undefined' && kiriofAjax.ajaxurl)
? kiriofAjax.ajaxurl
: kiriofBillingAddressConfig.ajaxUrl || '';
Expand Down Expand Up @@ -874,11 +873,10 @@
result.then(function() {
kiriofAfterBlockDistrictPersist();
}).catch(function() {
kiriofScheduleBlockShippingRatesRefresh(160);
kiriofForceBlockCartUpdate(data.destination_name || '', data.destination_id || '');
kiriofPersistBlockDistrictFallback();
});
} else {
kiriofAfterBlockDistrictPersist();
kiriofPersistBlockDistrictFallback();
}
}

Expand Down Expand Up @@ -926,7 +924,8 @@
// Direct change handler on the select for reliability.
// The delegated handler on `document` may not fire in WooCommerce
// blocks (React 18 captures native events before they reach document).
$select.on('change.kiriofBlockDistrictDirect', function() {
$select.on('change.kiriofBlockDistrictDirect', function(event) {
event.kiriofDistrictHandled = true;
if (window.console) console.log('[KiriminAja] Select changed', jQuery(this).val());
try {
var districtVal = jQuery(this).val();
Expand Down Expand Up @@ -1561,7 +1560,8 @@
}

jQuery(document).off('change.kiriofBlockDistrict', '[name="' + kiriofFieldId + '"], .kiriof-block-district-select')
.on('change.kiriofBlockDistrict', '[name="' + kiriofFieldId + '"], .kiriof-block-district-select', function() {
.on('change.kiriofBlockDistrict', '[name="' + kiriofFieldId + '"], .kiriof-block-district-select', function(event) {
if (event.kiriofDistrictHandled) return;
var val = jQuery(this).val();
var label = jQuery(this).find('option:selected').text();
var postcode = kiriofGetCurrentPostcodeKey();
Expand Down
7 changes: 5 additions & 2 deletions inc/Base/KiriminAjaApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,17 @@ public function get($endpoint, $body = array(), $log_context = array())

return $this->finalize_response( $response, $request_meta );
}
public function post($endpoint, $body = array(), $log_context = array())
public function post($endpoint, $body = array(), $log_context = array(), $request_args = array())
{
$requestBody = $body;
if ( is_array( $body ) && empty( $body ) ) {
$requestBody = (object) array();
}

$args = wp_parse_args(array('body' => wp_json_encode($requestBody)), $this->default_args);
$args = wp_parse_args(
array_merge( $request_args, array( 'body' => wp_json_encode( $requestBody ) ) ),
$this->default_args
);
$request_meta = $this->build_request_log_context( 'POST', $endpoint, $body, $log_context );
$response = wp_remote_post($this->base_url . $endpoint, $args);

Expand Down
12 changes: 12 additions & 0 deletions inc/Controllers/AccountAddressController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function addDistrictFields( array $fields, string $address_type ): array
return $fields;
}

$fields = $this->removeBlocksDistrictFields( $fields, $address_type );
$district = ( new CustomerDistrictService() )->get( get_current_user_id(), $address_type );
$field_key = $address_type . '_kiriof_destination_area';
$name_key = $address_type . '_kiriof_destination_area_name';
Expand Down Expand Up @@ -49,6 +50,17 @@ public function addDistrictFields( array $fields, string $address_type ): array
return $fields;
}

private function removeBlocksDistrictFields( array $fields, string $address_type ): array {
$canonical_key = $address_type . '_kiriof_destination_area';
foreach ( array_keys( $fields ) as $key ) {
if ( $key !== $canonical_key && false !== strpos( (string) $key, 'kiriof_destination_area' ) ) {
unset( $fields[ $key ] );
}
}

return $fields;
}

public function validateDistrict( int $user_id, string $address_type, array $address, $customer ): void {
unset( $user_id, $address, $customer );
if ( ! in_array( $address_type, array( 'billing', 'shipping' ), true ) ) {
Expand Down
10 changes: 2 additions & 8 deletions inc/Controllers/CheckoutController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2079,14 +2079,8 @@ public function kiriof_store_api_update_checkout( $data ) {
WC()->session->set( 'kiriof_destination_postcode_map', $saved_destination_map );
}

if (
( $destination_id > 0 || '' !== $shipping_method || '' !== $payment_method )
&& isset( WC()->cart )
&& is_object( WC()->cart )
&& method_exists( WC()->cart, 'calculate_totals' )
) {
WC()->cart->calculate_totals();
}
// WooCommerce recalculates the Store API cart after this callback returns.
// Calling calculate_totals() here duplicates shipping and pricing work.
}

/**
Expand Down
3 changes: 3 additions & 0 deletions inc/Repositories/KiriminajaApiRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public function getPricing($payload){
], array(
'source' => 'kiriminaja_shipping',
'operation' => 'get_pricing',
), array(
'timeout' => (int) apply_filters( 'kiriof_pricing_api_timeout', 8 ),
'httpversion' => '1.1',
));
}

Expand Down
31 changes: 31 additions & 0 deletions tests/CheckoutShippingPerformanceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,35 @@ public function plugin_ajax_handlers_defer_totals_recalculation_to_woocommerce_u
'Fee AJAX should only cache calculated fees; the following update_checkout request renders them'
);
}

#[Test]
public function pricing_api_uses_a_short_filterable_timeout(): void
{
$repository = file_get_contents( PLUGIN_DIR . '/inc/Repositories/KiriminajaApiRepository.php' );
$api = file_get_contents( PLUGIN_DIR . '/inc/Base/KiriminAjaApi.php' );

$this->assertStringContainsString("apply_filters( 'kiriof_pricing_api_timeout', 8 )", $repository);
$this->assertStringContainsString("'httpversion' => '1.1'", $repository);
$this->assertStringContainsString('$request_args = array()', $api);
$this->assertStringContainsString('array_merge( $request_args', $api);
}

#[Test]
public function block_district_persistence_uses_ajax_only_as_fallback(): void
{
$script = file_get_contents( PLUGIN_DIR . '/assets/wp/js/form-billing-address.js' );
$start = strpos( $script, 'function kiriofPersistBlockDistrictSelection' );
$end = strpos( $script, 'var kiriofLastDistrictResults', $start );
$body = substr( $script, $start, $end - $start );

$this->assertStringContainsString('function kiriofPersistBlockDistrictFallback()', $body);
$this->assertStringContainsString('result.then(function()', $body);
$this->assertStringContainsString('kiriofAfterBlockDistrictPersist();', $body);
$this->assertStringContainsString('kiriofPersistBlockDistrictFallback();', $body);
$this->assertLessThan(
strpos( $body, 'kiriofPersistBlockDistrictFallback();' ),
strpos( $body, 'kiriofAfterBlockDistrictPersist();' ),
'Successful extensionCartUpdate should finish without the fallback AJAX and raw Store API update chain'
);
}
}
10 changes: 10 additions & 0 deletions tests/MyAccountDistrictTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ public function account_address_controller_registers_account_only_district_lifec
$this->assertStringContainsString("\$address_type . '_kiriof_destination_area'", $content);
}

#[Test]
public function account_address_controller_removes_blocks_duplicate_district_fields(): void
{
$content = file_get_contents(PLUGIN_DIR . '/inc/Controllers/AccountAddressController.php');

$this->assertStringContainsString('removeBlocksDistrictFields', $content);
$this->assertStringContainsString("strpos( (string) \$key, 'kiriof_destination_area' )", $content);
$this->assertStringContainsString("\$key !== \$canonical_key", $content);
}

#[Test]
public function account_district_service_reads_and_writes_canonical_and_legacy_metadata(): void
{
Expand Down
22 changes: 8 additions & 14 deletions tests/ShopVerseBlockCheckoutCompatibilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1925,7 +1925,7 @@ public function store_api_update_callback_does_not_overwrite_visible_block_postc
}

#[Test]
public function store_api_update_callback_recalculates_totals_after_block_destination_changes(): void
public function store_api_update_callback_defers_totals_to_woocommerce(): void
{
$content = file_get_contents(PLUGIN_DIR . '/inc/Controllers/CheckoutController.php');
$start = strpos($content, 'public function kiriof_store_api_update_checkout');
Expand All @@ -1934,21 +1934,15 @@ public function store_api_update_callback_recalculates_totals_after_block_destin
$this->assertNotFalse($end, 'Store API update callback boundary must exist');
$methodBody = substr($content, $start, $end - $start);

$destinationPosition = strpos($methodBody, "WC()->session->set( 'kiriof_destination_area', \$destination_id );");
$calculatePosition = strpos($methodBody, 'WC()->cart->calculate_totals();');

$this->assertNotFalse(
$destinationPosition,
$this->assertStringContainsString(
"WC()->session->set( 'kiriof_destination_area', \$destination_id );",
$methodBody,
'Store API callback must persist the selected District before rates are recalculated'
);
$this->assertNotFalse(
$calculatePosition,
'Store API callback must recalculate totals after District/payment/shipping context changes so block checkout receives fresh rates'
);
$this->assertLessThan(
$calculatePosition,
$destinationPosition,
'Destination must be in session before Woo recalculates shipping totals'
$this->assertStringNotContainsString(
'WC()->cart->calculate_totals();',
$methodBody,
'Store API already recalculates the cart after extension callbacks; nested totals duplicate pricing calls'
);
}

Expand Down
Loading