id = 'aieo_table_rate'; $this->instance_id = absint($instance_id); $this->method_title = __('Rooster One Table Rate', 'ai-eshop-optimizer'); $this->method_description = __( 'Optimised table-rate shipping with object-cached rule lookup. Manage rules from the Rooster One admin.', 'ai-eshop-optimizer' ); $this->supports = array( 'shipping-zones', 'instance-settings', 'instance-settings-modal', ); $this->init(); } public function init() { $this->init_form_fields(); $this->init_settings(); $this->title = $this->get_option('title', __('Shipping', 'ai-eshop-optimizer')); $this->enabled = $this->get_option('enabled', 'yes'); $this->tax_status = $this->get_option('tax_status', 'taxable'); add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options')); } public function init_form_fields() { $admin_url = admin_url('admin.php?page=aieo-shipping-rates&instance_id=' . $this->instance_id); $this->instance_form_fields = array( 'title' => array( 'title' => __('Method title', 'ai-eshop-optimizer'), 'type' => 'text', 'description' => __('Storefront-facing name of this shipping option.', 'ai-eshop-optimizer'), 'default' => '', 'desc_tip' => true, ), 'tax_status' => array( 'title' => __('Tax status', 'ai-eshop-optimizer'), 'type' => 'select', 'default' => 'taxable', 'options' => array( 'taxable' => __('Taxable', 'ai-eshop-optimizer'), 'none' => _x('None', 'Tax status', 'ai-eshop-optimizer'), ), ), 'manage_rates' => array( 'title' => __('Rate rules', 'ai-eshop-optimizer'), 'type' => 'title', 'description' => sprintf( __('Rules for this method are managed centrally in the AIEO Shipping Rates admin.', 'ai-eshop-optimizer'), esc_url($admin_url) ), ), ); } public function calculate_shipping($package = array()) { if (!is_array($package)) { return; } $summary = AIEO_Runtime_TRS_Matcher::summarise_package($package); $version = AIEO_Runtime_TRS_Rule_Loader::cache_version(); $hash = AIEO_Runtime_TRS_Cache::package_hash($this->instance_id, $package, $summary, $version); $matched = AIEO_Runtime_TRS_Cache::get($hash); $cache_status = ($matched !== null) ? 'HIT' : 'MISS'; if ($matched === null) { $rules = AIEO_Runtime_TRS_Rule_Loader::get_rules($this->instance_id); $matched = AIEO_Runtime_TRS_Matcher::match($rules, $summary); AIEO_Runtime_TRS_Cache::set($hash, $matched); } if (defined('WP_DEBUG') && WP_DEBUG) { $req_action = isset($_REQUEST['wc-ajax']) ? $_REQUEST['wc-ajax'] : (isset($_REQUEST['action']) ? $_REQUEST['action'] : 'render'); $is_store_api = (defined('REST_REQUEST') && REST_REQUEST) ? '|REST' : ''; error_log(sprintf( '[AIEO_TRS] inst=%d ctx=%s%s cache=%s subtotal=%.2f weight=%.4f qty=%d -> %d rules: %s', (int) $this->instance_id, $req_action, $is_store_api, $cache_status, (float) $summary['subtotal'], (float) $summary['total_weight'], (int) $summary['total_qty'], count($matched), wp_json_encode(array_map(function ($r) { return array( 'rid' => $r['rule_id'] ?? 0, 'cost' => $r['cost'] ?? 0, 'abort' => !empty($r['abort']), ); }, $matched)) )); } if (empty($matched)) { return; } $abort = $matched[0]; if (!empty($abort['abort'])) { if (!empty($abort['abort_reason']) && function_exists('is_checkout') && is_checkout() && function_exists('wc_has_notice') && function_exists('wc_add_notice') && !wc_has_notice($abort['abort_reason'], 'notice')) { wc_add_notice((string) $abort['abort_reason'], 'notice'); } return; } $title_default = (string) $this->title; foreach ($matched as $i => $rule) { if (!empty($rule['abort'])) { continue; } $rate_id = $this->get_rate_id() . '_rule_' . (int) $rule['rule_id']; $rate_label = $rule['label'] !== '' ? $rule['label'] : $title_default; $cost = (float) $rule['cost']; $this->add_rate(array( 'id' => $rate_id, 'label' => $rate_label, 'cost' => $cost, 'package' => $package, 'meta_data' => array( 'aieo_rule_id' => (int) $rule['rule_id'], 'aieo_method' => $this->id, 'aieo_instance' => (int) $this->instance_id, ), )); } } public function is_available($package) { $available = ($this->enabled === 'yes'); return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $available, $package, $this ); } } }