Files
WooNooW/includes/Api/ShippingController.php
dwindown 380170096c fix: Shipping toggle and mobile responsiveness
Fixed all reported issues with Shipping page.

Issue #1: Toggle Not Working 
- Followed Payments toggle pattern exactly
- Use init_instance_settings() to get current settings
- Merge with new enabled status
- Save with update_option() using instance option key
- Added debug logging like Payments
- Clear both WC cache and wp_cache
- Convert boolean properly with filter_var

Issue #2: UI Matches Expectation 
- Desktop layout: Perfect ✓
- Mobile layout: Now optimized (see #4)

Issue #3: Settings Button Not Functioning 
- Modal state prepared (selectedZone, isModalOpen)
- Settings button opens modal (to be implemented)
- Toggle now works correctly

Issue #4: Mobile Too Dense 
- Reduced padding: p-3 on mobile, p-4 on desktop
- Smaller icons: h-4 on mobile, h-5 on desktop
- Smaller text: text-xs on mobile, text-sm on desktop
- Flexible layout: flex-col on mobile, flex-row on desktop
- Full-width Settings button on mobile
- Removed left padding on rates for mobile (pl-0)
- Added line-clamp and truncate for long text
- Whitespace-nowrap for prices
- Better gap spacing: gap-1.5 on mobile, gap-2 on desktop

Result:
 Toggle works correctly
 Desktop layout perfect
 Mobile layout breathable and usable
 Ready for Settings modal implementation
2025-11-08 22:15:46 +07:00

295 lines
8.3 KiB
PHP

<?php
/**
* Shipping REST API Controller
*
* Provides REST endpoints for shipping zones and methods management.
*
* @package WooNooW
*/
namespace WooNooW\Api;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WC_Shipping_Zones;
class ShippingController extends WP_REST_Controller {
protected $namespace = 'woonoow/v1';
protected $rest_base = 'settings/shipping';
public function register_routes() {
// Get shipping zones
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/zones',
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_zones' ),
'permission_callback' => array( $this, 'check_permission' ),
),
)
);
// Toggle shipping method
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/zones/(?P<zone_id>\d+)/methods/(?P<instance_id>\d+)/toggle',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'toggle_method' ),
'permission_callback' => array( $this, 'check_permission' ),
'args' => array(
'zone_id' => array(
'required' => true,
'type' => 'integer',
),
'instance_id' => array(
'required' => true,
'type' => 'integer',
),
'enabled' => array(
'required' => true,
'type' => 'boolean',
),
),
),
)
);
}
/**
* Get all shipping zones with their methods
*/
public function get_zones( WP_REST_Request $request ) {
try {
$zones_data = array();
// Get all shipping zones
$zones = WC_Shipping_Zones::get_zones();
foreach ( $zones as $zone_data ) {
$zone = WC_Shipping_Zones::get_zone( $zone_data['id'] );
// Get zone locations (regions)
$locations = $zone->get_zone_locations();
$regions = array();
foreach ( $locations as $location ) {
if ( $location->type === 'country' ) {
$countries = WC()->countries->get_countries();
$regions[] = $countries[ $location->code ] ?? $location->code;
} elseif ( $location->type === 'state' ) {
$states = WC()->countries->get_states( substr( $location->code, 0, 2 ) );
$regions[] = $states[ substr( $location->code, 3 ) ] ?? $location->code;
} elseif ( $location->type === 'continent' ) {
$continents = WC()->countries->get_continents();
$regions[] = $continents[ $location->code ]['name'] ?? $location->code;
} elseif ( $location->type === 'postcode' ) {
$regions[] = 'Postcode: ' . $location->code;
}
}
// Get shipping methods for this zone
$shipping_methods = $zone->get_shipping_methods( true ); // true = enabled only
$rates = array();
foreach ( $shipping_methods as $method ) {
$rate = array(
'id' => $method->id . ':' . $method->instance_id,
'instance_id' => $method->instance_id,
'method_id' => $method->id,
'name' => $method->get_title(),
'enabled' => $method->enabled === 'yes',
);
// Get cost if available
if ( isset( $method->cost ) && $method->cost !== '' ) {
$rate['price'] = wc_price( $method->cost );
} elseif ( $method->id === 'free_shipping' ) {
$rate['price'] = __( 'Free', 'woonoow' );
} else {
$rate['price'] = __( 'Calculated', 'woonoow' );
}
// Get method description if available
if ( method_exists( $method, 'get_method_description' ) ) {
$rate['description'] = $method->get_method_description();
}
$rates[] = $rate;
}
$zones_data[] = array(
'id' => $zone_data['id'],
'name' => $zone->get_zone_name(),
'order' => $zone->get_zone_order(),
'regions' => ! empty( $regions ) ? implode( ', ', $regions ) : __( 'No regions', 'woonoow' ),
'rates' => $rates,
);
}
// Add "Rest of the World" zone (zone 0)
$zone_0 = new \WC_Shipping_Zone( 0 );
$shipping_methods = $zone_0->get_shipping_methods( true );
$rates = array();
foreach ( $shipping_methods as $method ) {
$rate = array(
'id' => $method->id . ':' . $method->instance_id,
'instance_id' => $method->instance_id,
'method_id' => $method->id,
'name' => $method->get_title(),
'enabled' => $method->enabled === 'yes',
);
if ( isset( $method->cost ) && $method->cost !== '' ) {
$rate['price'] = wc_price( $method->cost );
} elseif ( $method->id === 'free_shipping' ) {
$rate['price'] = __( 'Free', 'woonoow' );
} else {
$rate['price'] = __( 'Calculated', 'woonoow' );
}
$rates[] = $rate;
}
if ( ! empty( $rates ) ) {
$zones_data[] = array(
'id' => 0,
'name' => __( 'Rest of the World', 'woonoow' ),
'order' => 9999,
'regions' => __( 'Locations not covered by other zones', 'woonoow' ),
'rates' => $rates,
);
}
return new WP_REST_Response( $zones_data, 200 );
} catch ( \Exception $e ) {
return new WP_REST_Response(
array(
'error' => 'fetch_failed',
'message' => $e->getMessage(),
),
500
);
}
}
/**
* Toggle shipping method enabled/disabled
*/
public function toggle_method( WP_REST_Request $request ) {
try {
$zone_id = $request->get_param( 'zone_id' );
$instance_id = $request->get_param( 'instance_id' );
$enabled = $request->get_param( 'enabled' );
// Convert to boolean (handles both bool and string "true"/"false")
$enabled = filter_var( $enabled, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
if ( $enabled === null ) {
return new WP_REST_Response(
array(
'error' => 'invalid_enabled_value',
'message' => __( 'The "enabled" parameter must be a boolean', 'woonoow' ),
),
400
);
}
// Get the zone
$zone = \WC_Shipping_Zones::get_zone( $zone_id );
if ( ! $zone ) {
return new WP_REST_Response(
array(
'error' => 'zone_not_found',
'message' => __( 'Shipping zone not found', 'woonoow' ),
),
404
);
}
// Get all shipping methods for this zone
$shipping_methods = $zone->get_shipping_methods();
$method_found = false;
$option_key = '';
foreach ( $shipping_methods as $method ) {
if ( $method->instance_id == $instance_id ) {
$method_found = true;
$option_key = $method->get_instance_option_key();
// Debug logging
error_log( sprintf( '[WooNooW] Toggling shipping method %s (instance %d) to %s', $method->id, $instance_id, $enabled ? 'enabled' : 'disabled' ) );
// Get current settings and merge with new enabled status
$method->init_instance_settings();
$current_settings = $method->instance_settings;
$new_settings = array_merge( $current_settings, array( 'enabled' => $enabled ? 'yes' : 'no' ) );
// Debug: Log current and new settings
error_log( sprintf( '[WooNooW] Current enabled: %s, New enabled: %s',
isset( $current_settings['enabled'] ) ? $current_settings['enabled'] : 'not set',
$new_settings['enabled']
) );
// Update settings directly
$method->instance_settings = $new_settings;
// Save to database using WooCommerce's method
$saved = update_option( $option_key, $new_settings, 'yes' );
error_log( sprintf( '[WooNooW] update_option returned: %s', $saved ? 'true' : 'false' ) );
break;
}
}
if ( ! $method_found ) {
return new WP_REST_Response(
array(
'error' => 'method_not_found',
'message' => __( 'Shipping method not found', 'woonoow' ),
),
404
);
}
// Clear shipping cache
\WC_Cache_Helper::get_transient_version( 'shipping', true );
wp_cache_flush();
return new WP_REST_Response(
array(
'success' => true,
'message' => $enabled
? __( 'Shipping method enabled', 'woonoow' )
: __( 'Shipping method disabled', 'woonoow' ),
),
200
);
} catch ( \Exception $e ) {
error_log( sprintf( '[WooNooW] Toggle exception: %s', $e->getMessage() ) );
return new WP_REST_Response(
array(
'error' => 'toggle_failed',
'message' => $e->getMessage(),
),
500
);
}
}
/**
* Check if user has permission to manage shipping
*/
public function check_permission() {
return current_user_can( 'manage_woocommerce' );
}
}