From e053dd73b59ec5478493618944684ed532ee9563 Mon Sep 17 00:00:00 2001 From: dwindown Date: Sun, 9 Nov 2025 17:14:38 +0700 Subject: [PATCH] feat: Add backend API endpoints for shipping method management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 backend complete - Full CRUD for shipping methods. New Endpoints: ✅ GET /methods/available - List all available shipping methods ✅ POST /zones/{id}/methods - Add method to zone ✅ DELETE /zones/{id}/methods/{instance_id} - Remove method ✅ GET /zones/{id}/methods/{instance_id}/settings - Get method form fields ✅ PUT /zones/{id}/methods/{instance_id}/settings - Update method settings Features: - Get available methods (Flat Rate, Free Shipping, etc.) - Add any method to any zone - Delete methods from zones - Fetch method settings with current values - Update method settings (cost, conditions, etc.) - Proper error handling - Cache clearing after changes Next: Frontend implementation --- includes/Api/ShippingController.php | 361 ++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) diff --git a/includes/Api/ShippingController.php b/includes/Api/ShippingController.php index 1dfc3b3..d44f4cb 100644 --- a/includes/Api/ShippingController.php +++ b/includes/Api/ShippingController.php @@ -59,6 +59,91 @@ class ShippingController extends WP_REST_Controller { ), ) ); + + // Get available shipping methods + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/methods/available', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_available_methods' ), + 'permission_callback' => array( $this, 'check_permission' ), + ), + ) + ); + + // Add shipping method to zone + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/zones/(?P\d+)/methods', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'add_method' ), + 'permission_callback' => array( $this, 'check_permission' ), + 'args' => array( + 'zone_id' => array( + 'required' => true, + 'type' => 'integer', + ), + 'method_id' => array( + 'required' => true, + 'type' => 'string', + ), + ), + ), + ) + ); + + // Delete shipping method from zone + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/zones/(?P\d+)/methods/(?P\d+)', + array( + array( + 'methods' => \WP_REST_Server::DELETABLE, + 'callback' => array( $this, 'delete_method' ), + 'permission_callback' => array( $this, 'check_permission' ), + 'args' => array( + 'zone_id' => array( + 'required' => true, + 'type' => 'integer', + ), + 'instance_id' => array( + 'required' => true, + 'type' => 'integer', + ), + ), + ), + ) + ); + + // Get method settings + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/zones/(?P\d+)/methods/(?P\d+)/settings', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_method_settings' ), + 'permission_callback' => array( $this, 'check_permission' ), + ), + ) + ); + + // Update method settings + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/zones/(?P\d+)/methods/(?P\d+)/settings', + array( + array( + 'methods' => \WP_REST_Server::EDITABLE, + 'callback' => array( $this, 'update_method_settings' ), + 'permission_callback' => array( $this, 'check_permission' ), + ), + ) + ); } /** @@ -304,6 +389,282 @@ class ShippingController extends WP_REST_Controller { } } + /** + * Get available shipping methods + */ + public function get_available_methods( WP_REST_Request $request ) { + try { + $shipping = \WC()->shipping(); + $methods = $shipping->get_shipping_methods(); + + $available = array(); + foreach ( $methods as $method ) { + $available[] = array( + 'id' => $method->id, + 'title' => $method->get_method_title(), + 'description' => $method->get_method_description(), + ); + } + + return new WP_REST_Response( $available, 200 ); + } catch ( \Exception $e ) { + return new WP_REST_Response( + array( + 'error' => 'fetch_failed', + 'message' => $e->getMessage(), + ), + 500 + ); + } + } + + /** + * Add shipping method to zone + */ + public function add_method( WP_REST_Request $request ) { + try { + $zone_id = $request->get_param( 'zone_id' ); + $method_id = $request->get_param( 'method_id' ); + + $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 + ); + } + + // Add method to zone + $instance_id = $zone->add_shipping_method( $method_id ); + + if ( ! $instance_id ) { + return new WP_REST_Response( + array( + 'error' => 'add_failed', + 'message' => __( 'Failed to add shipping method', 'woonoow' ), + ), + 500 + ); + } + + // Clear caches + \WC_Cache_Helper::get_transient_version( 'shipping', true ); + wp_cache_flush(); + + return new WP_REST_Response( + array( + 'success' => true, + 'instance_id' => $instance_id, + 'message' => __( 'Shipping method added successfully', 'woonoow' ), + ), + 200 + ); + } catch ( \Exception $e ) { + return new WP_REST_Response( + array( + 'error' => 'add_failed', + 'message' => $e->getMessage(), + ), + 500 + ); + } + } + + /** + * Delete shipping method from zone + */ + public function delete_method( WP_REST_Request $request ) { + try { + $zone_id = $request->get_param( 'zone_id' ); + $instance_id = $request->get_param( 'instance_id' ); + + $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 + ); + } + + // Delete method from zone + $zone->delete_shipping_method( $instance_id ); + + // Clear caches + \WC_Cache_Helper::get_transient_version( 'shipping', true ); + wp_cache_flush(); + + return new WP_REST_Response( + array( + 'success' => true, + 'message' => __( 'Shipping method deleted successfully', 'woonoow' ), + ), + 200 + ); + } catch ( \Exception $e ) { + return new WP_REST_Response( + array( + 'error' => 'delete_failed', + 'message' => $e->getMessage(), + ), + 500 + ); + } + } + + /** + * Get method settings (form fields) + */ + public function get_method_settings( WP_REST_Request $request ) { + try { + $zone_id = $request->get_param( 'zone_id' ); + $instance_id = $request->get_param( 'instance_id' ); + + $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 + ); + } + + $shipping_methods = $zone->get_shipping_methods( false ); + foreach ( $shipping_methods as $method ) { + if ( $method->instance_id == $instance_id ) { + // Get form fields + $form_fields = $method->get_instance_form_fields(); + + // Get current settings + $settings = get_option( $method->get_instance_option_key(), array() ); + + // Format fields with current values + $formatted_fields = array(); + foreach ( $form_fields as $key => $field ) { + $formatted_fields[ $key ] = array( + 'id' => $key, + 'type' => $field['type'] ?? 'text', + 'title' => $field['title'] ?? '', + 'description' => $field['description'] ?? '', + 'default' => $field['default'] ?? '', + 'value' => $settings[ $key ] ?? ( $field['default'] ?? '' ), + 'placeholder' => $field['placeholder'] ?? '', + 'options' => $field['options'] ?? array(), + ); + } + + return new WP_REST_Response( + array( + 'method_id' => $method->id, + 'method_title' => $method->get_method_title(), + 'instance_id' => $instance_id, + 'settings' => $formatted_fields, + ), + 200 + ); + } + } + + return new WP_REST_Response( + array( + 'error' => 'method_not_found', + 'message' => __( 'Shipping method not found', 'woonoow' ), + ), + 404 + ); + } catch ( \Exception $e ) { + return new WP_REST_Response( + array( + 'error' => 'fetch_failed', + 'message' => $e->getMessage(), + ), + 500 + ); + } + } + + /** + * Update method settings + */ + public function update_method_settings( WP_REST_Request $request ) { + try { + $zone_id = $request->get_param( 'zone_id' ); + $instance_id = $request->get_param( 'instance_id' ); + $settings = $request->get_param( 'settings' ); + + if ( empty( $settings ) || ! is_array( $settings ) ) { + return new WP_REST_Response( + array( + 'error' => 'invalid_settings', + 'message' => __( 'Invalid settings data', 'woonoow' ), + ), + 400 + ); + } + + $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 + ); + } + + $shipping_methods = $zone->get_shipping_methods( false ); + foreach ( $shipping_methods as $method ) { + if ( $method->instance_id == $instance_id ) { + // Get current settings + $option_key = $method->get_instance_option_key(); + $current_settings = get_option( $option_key, array() ); + + // Merge with new settings + $new_settings = array_merge( $current_settings, $settings ); + + // Save to database + update_option( $option_key, $new_settings, 'yes' ); + + // Clear caches + \WC_Cache_Helper::get_transient_version( 'shipping', true ); + wp_cache_flush(); + + return new WP_REST_Response( + array( + 'success' => true, + 'message' => __( 'Shipping method settings updated successfully', 'woonoow' ), + ), + 200 + ); + } + } + + return new WP_REST_Response( + array( + 'error' => 'method_not_found', + 'message' => __( 'Shipping method not found', 'woonoow' ), + ), + 404 + ); + } catch ( \Exception $e ) { + return new WP_REST_Response( + array( + 'error' => 'update_failed', + 'message' => $e->getMessage(), + ), + 500 + ); + } + } + /** * Check if user has permission to manage shipping */