PluginProbe
SuperFrete / 3.3.2
SuperFrete v3.3.2
trunk 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4
superfrete / app / Controllers / ProductShipping.php

ProductShipping.php in SuperFrete 3.3.2, at app/Controllers/ProductShipping.php

777 lines 33.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SuperFrete_API\Controllers;
4
5 use SuperFrete_API\Http\Request;
6 use WC_Shipping_Zones;
7
8 if (!defined('ABSPATH'))
9 exit; // Segurança
10
11 class ProductShipping {
12
13 public function __construct() {
14
15 add_action('woocommerce_after_add_to_cart_form', array(__CLASS__, 'calculator'));
16 add_shortcode('pi_shipping_calculator', array($this, 'calculator_shortcode'));
17
18 add_action('wc_ajax_pi_load_location_by_ajax', array(__CLASS__, 'loadLocation') );
19 add_action('woocommerce_after_add_to_cart_form', [$this, 'enqueue_scripts']);
20 add_action('wp_ajax_superfrete_calculate', [$this, 'calculate_shipping']);
21 add_action('wp_ajax_nopriv_superfrete_calculate', [$this, 'calculate_shipping']); // Para usuários não logados
22
23 add_action('wp_ajax_superfrete_cal_shipping', array(__CLASS__, 'applyShipping'));
24 add_action('wp_ajax_nopriv_superfrete_cal_shipping', array(__CLASS__, 'applyShipping'));
25 add_action('wc_ajax_superfrete_cal_shipping', array(__CLASS__, 'applyShipping'));
26
27 // Hook the hideCalculator method to the filter so virtual products are automatically hidden
28 add_filter('superfrete_hide_calculator_on_single_product_page', array(__CLASS__, 'hideCalculator'), 10, 2);
29 }
30
31 static function resultHtml() {
32 echo '<div id="superfrete-alert-container" class="superfrete-alert-container"></div>';
33 }
34
35 function calculator_shortcode() {
36 if ($this->position != 'shortcode') {
37 return '<div class="error">' . __('Short code is disabled in setting', 'superfrete-product-page-shipping-calculator-woocommerce') . '</di>';
38 }
39
40 if (function_exists('is_product') && !is_product()) {
41 return '<div class="error">' . __('This shortcode will only work on product page', 'superfrete-product-page-shipping-calculator-woocommerce') . '</di>';
42 }
43
44 global $product;
45
46 if (!is_object($product) || $product->is_virtual() || !$product->is_in_stock())
47 return;
48
49 ob_start();
50 self::calculator();
51 $html = ob_get_contents();
52 ob_end_clean();
53 return $html;
54 }
55
56 static function calculator() {
57 global $product;
58
59 // Hide calculator for virtual products (they don't need shipping)
60 if (is_object($product) && $product->is_virtual()) {
61 return;
62 }
63
64 if (apply_filters('superfrete_hide_calculator_on_single_product_page', false, $product)) {
65 return;
66 }
67
68 if (is_object($product)) {
69 $product_id = $product->get_id();
70 } else {
71 $product = "";
72 }
73
74 $enable_calculator = get_option('superfrete_enable_calculator');
75
76 if ($enable_calculator === 'no')
77 return;
78
79 $button_text = get_option('superfrete_open_drawer_button_text', 'Calcular Entrega');
80 $update_address_btn_text = get_option('superfrete_update_button_text', 'Calcular');
81
82 include plugin_dir_path(__FILE__) . '../../templates/woocommerce/shipping-calculator.php';
83 }
84
85 static function hideCalculator($val, $product) {
86 if (is_object($product) && $product->is_virtual())
87 return true;
88
89 return $val;
90 }
91
92 static function applyShipping() {
93 if (!isset($_POST['superfrete_nonce']) || !wp_verify_nonce($_POST['superfrete_nonce'], 'superfrete_nonce')) {
94 wp_send_json_error(['message' => 'Requisição inválida.'], 403);
95 }
96 // Start timing the entire function execution
97 $total_start_time = microtime(true);
98
99 // Setup logging
100 $log_data = [
101 'method' => 'applyShipping',
102 'steps' => [],
103 'total_time' => 0
104 ];
105
106 if (!class_exists('WC_Shortcode_Cart')) {
107 include_once WC_ABSPATH . 'includes/shortcodes/class-wc-shortcode-cart.php';
108 }
109
110
111 if (self::doingCalculation()) {
112 $step_start = microtime(true);
113
114 if ((isset($_POST['action_auto_load']) && self::disableAutoLoadEstimate()) || empty($_POST['calc_shipping_postcode']) || !isset($_POST['calc_shipping_postcode'])) {
115 $return['shipping_methods'] = sprintf('<div class="superfrete-alert">%s</div>', esc_html(get_option('superfrete_no_address_added_yet', 'Informe seu Endereço para calcular')));
116 wp_send_json($return);
117 }
118
119 $log_data['steps']['initial_validation'] = round((microtime(true) - $step_start) * 1000, 2) . ' ms';
120 $step_start = microtime(true);
121
122 $return = array();
123 \WC_Shortcode_Cart::calculate_shipping();
124 WC()->cart->calculate_totals();
125
126 $log_data['steps']['calculate_shipping'] = round((microtime(true) - $step_start) * 1000, 2) . ' ms';
127 $step_start = microtime(true);
128
129 // OPTIMIZATION: Use a lightweight shipping package instead of manipulating the cart
130 // This avoids expensive cart operations that were causing performance issues
131
132 // Get product ID and variation ID
133 $product_id = filter_input(INPUT_POST, 'product_id', FILTER_VALIDATE_INT);
134 $variation_id = filter_input(INPUT_POST, 'variation_id', FILTER_VALIDATE_INT);
135 $quantity = filter_input(INPUT_POST, 'quantity', FILTER_VALIDATE_INT) ?: 1;
136
137 // Get product data directly without cart manipulation
138 if ($product_id) {
139 $product = wc_get_product($variation_id ?: $product_id);
140
141 if ($product) {
142 // Skip calculation for virtual products
143 if ($product->is_virtual()) {
144 $return['shipping_methods'] = sprintf('<div class="superfrete-alert">%s</div>', esc_html__('Produtos virtuais não necessitam de frete.', 'superfrete'));
145 wp_send_json($return);
146 }
147 // Get destination from form data (not customer data)
148 $destination_postcode = sanitize_text_field($_POST['calc_shipping_postcode'] ?? '');
149 $destination_country = sanitize_text_field($_POST['calc_shipping_country'] ?? 'BR');
150 $destination_state = sanitize_text_field($_POST['calc_shipping_state'] ?? '');
151 $destination_city = sanitize_text_field($_POST['calc_shipping_city'] ?? '');
152
153 // Create a lightweight package for shipping calculation
154 $package = [
155 'contents' => [
156 [
157 'data' => $product,
158 'quantity' => $quantity
159 ]
160 ],
161 'contents_cost' => $product->get_price() * $quantity,
162 'applied_coupons' => [],
163 'user' => [
164 'ID' => get_current_user_id(),
165 ],
166 'destination' => [
167 'country' => $destination_country,
168 'state' => $destination_state,
169 'postcode' => $destination_postcode,
170 'city' => $destination_city,
171 ],
172 'cart_subtotal' => $product->get_price() * $quantity,
173 ];
174
175 $log_data['steps']['prepare_package'] = round((microtime(true) - $step_start) * 1000, 2) . ' ms';
176 $step_start = microtime(true);
177
178 // Debug: Check all registered shipping methods
179 $wc_shipping = \WC_Shipping::instance();
180 $all_shipping_methods = $wc_shipping->get_shipping_methods();
181 $log_data['all_registered_methods'] = array_keys($all_shipping_methods);
182
183 // Debug: Check all shipping zones
184 $all_zones = \WC_Shipping_Zones::get_zones();
185 $log_data['all_zones'] = [];
186 foreach ($all_zones as $zone_data) {
187 $zone = new \WC_Shipping_Zone($zone_data['zone_id']);
188 $zone_methods = [];
189 foreach ($zone->get_shipping_methods() as $method) {
190 $zone_methods[] = [
191 'id' => $method->id,
192 'enabled' => $method->enabled,
193 'title' => $method->get_title(),
194 ];
195 }
196 $log_data['all_zones'][] = [
197 'id' => $zone->get_id(),
198 'name' => $zone->get_zone_name(),
199 'methods' => $zone_methods,
200 ];
201 }
202
203 // Calculate shipping rates directly with our package
204 $shipping_zone = \WC_Shipping_Zones::get_zone_matching_package($package);
205
206 // Add detailed debugging for shipping zone
207 $log_data['package_destination'] = $package['destination'];
208 $log_data['shipping_zone'] = [
209 'id' => $shipping_zone->get_id(),
210 'name' => $shipping_zone->get_zone_name(),
211 'locations' => $shipping_zone->get_zone_locations(),
212 ];
213
214 // Detailed logging for shipping calculation
215 $shipping_start = microtime(true);
216
217 // Log shipping providers being used
218 $active_shipping = [];
219 $all_methods = $shipping_zone->get_shipping_methods(true);
220 foreach ($all_methods as $method) {
221 $active_shipping[] = [
222 'id' => $method->id,
223 'enabled' => $method->is_enabled() ? 'yes' : 'no',
224 'title' => $method->get_title(),
225 'instance_id' => $method->get_instance_id(),
226 ];
227 }
228 $log_data['active_shipping_methods'] = $active_shipping;
229 $log_data['total_methods_found'] = count($all_methods);
230
231 // Calculate shipping directly
232 $rates = [];
233 $method_times = [];
234
235 foreach ($shipping_zone->get_shipping_methods(true) as $method) {
236 $method_start = microtime(true);
237 $method_id = $method->id;
238
239 // Log method details
240 $log_data['shipping_methods'][] = [
241 'id' => $method_id,
242 'title' => $method->get_title(),
243 'enabled' => $method->is_enabled() ? 'yes' : 'no',
244 'class' => get_class($method),
245 'instance_id' => $method->get_instance_id(),
246 ];
247
248 // Time each individual method
249 try {
250 // For SuperFrete shipping method, call calculate_shipping directly
251 if ($method_id === 'superfrete_shipping') {
252 $method->calculate_shipping($package);
253 $method_rates = $method->rates;
254 } else {
255 $method_rates = $method->get_rates_for_package($package);
256 }
257
258 $log_data['method_results'][$method_id] = [
259 'rates_count' => is_array($method_rates) ? count($method_rates) : 0,
260 'rates' => $method_rates ? array_keys($method_rates) : [],
261 ];
262 } catch (Exception $e) {
263 $log_data['method_errors'][$method_id] = $e->getMessage();
264 $method_rates = [];
265 }
266
267 $method_time = round((microtime(true) - $method_start) * 1000, 2);
268 $method_times[$method_id] = $method_time . ' ms';
269
270 // Log any methods taking over 500ms
271 if ($method_time > 500) {
272 $log_data['slow_methods'][$method_id] = $method_time . ' ms';
273 }
274
275 if ($method_rates) {
276 $rates = array_merge($rates, $method_rates);
277 }
278 }
279
280 // Add method timing to logs
281 $log_data['method_times'] = $method_times;
282
283 // Calculate shipping time first
284 $shipping_time = round((microtime(true) - $shipping_start) * 1000, 2);
285
286 // Check for common API bottlenecks
287 if ($shipping_time > 1000) {
288 // Get the HTTP stats to see external API calls
289 global $wp_version;
290 $http_counts = [
291 'total_requests' => 0,
292 'total_time' => 0,
293 'average_time' => 0
294 ];
295
296 // If using WordPress HTTP API, we can check the stats
297 if (function_exists('_get_http_stats')) {
298 $http_stats = _get_http_stats();
299 if (isset($http_stats['requests'])) {
300 $http_counts['total_requests'] = count($http_stats['requests']);
301
302 // Sum up all request times
303 foreach ($http_stats['requests'] as $request) {
304 if (isset($request['args']['timeout'])) {
305 // Log timeout values
306 $http_counts['timeouts'][] = $request['args']['timeout'];
307 }
308 if (isset($request['end_time']) && isset($request['start_time'])) {
309 $request_time = $request['end_time'] - $request['start_time'];
310 $http_counts['total_time'] += $request_time;
311
312 // Log slow individual requests (over 500ms)
313 if ($request_time > 0.5) {
314 $http_counts['slow_requests'][] = [
315 'url' => isset($request['url']) ? preg_replace('/\?.*/', '', $request['url']) : 'unknown',
316 'time' => round($request_time * 1000) . ' ms'
317 ];
318 }
319 }
320 }
321
322 if ($http_counts['total_requests'] > 0) {
323 $http_counts['average_time'] = round(($http_counts['total_time'] / $http_counts['total_requests']) * 1000, 2) . ' ms';
324 $http_counts['total_time'] = round($http_counts['total_time'] * 1000, 2) . ' ms';
325 }
326 }
327 }
328
329 $log_data['http_api'] = $http_counts;
330 }
331
332 $log_data['steps']['calculate_shipping_only'] = $shipping_time . ' ms';
333
334 // Log potential slow API calls
335 if ($shipping_time > 2000) { // If over 2 seconds
336 $log_data['warning'] = 'Shipping calculation is slow - may indicate API rate limiting or network issues';
337 }
338
339 $log_data['steps']['calculate_test_shipping'] = round((microtime(true) - $step_start) * 1000, 2) . ' ms';
340 $step_start = microtime(true);
341
342 // Sort rates by price (lowest to highest) before formatting
343 uasort($rates, function($a, $b) {
344 $cost_a = floatval($a->cost);
345 $cost_b = floatval($b->cost);
346
347 // Free shipping (cost = 0) should come first
348 if ($cost_a == 0 && $cost_b > 0) return -1;
349 if ($cost_b == 0 && $cost_a > 0) return 1;
350
351 // Both free or both paid - sort by cost ascending (lowest first)
352 if ($cost_a == $cost_b) {
353 // If costs are equal, sort by delivery time (faster first)
354 $time_a = isset($a->meta_data['delivery_time']) ? intval($a->meta_data['delivery_time']) : 999;
355 $time_b = isset($b->meta_data['delivery_time']) ? intval($b->meta_data['delivery_time']) : 999;
356 return $time_a <=> $time_b;
357 }
358
359 return $cost_a <=> $cost_b;
360 });
361
362 // Format shipping methods (now sorted by price)
363 $shipping_methods = [];
364 foreach ($rates as $rate_id => $rate) {
365 $title = wc_cart_totals_shipping_method_label($rate);
366 $title = self::modifiedTitle($title, $rate);
367 $shipping_methods[$rate_id] = apply_filters('superfrete_ppscw_shipping_method_name', $title, $rate, $product_id, $variation_id);
368 }
369
370 $log_data['steps']['get_shipping_methods'] = round((microtime(true) - $step_start) * 1000, 2) . ' ms';
371 $step_start = microtime(true);
372
373 $return['error'] = ''; // Empty the error to prevent notifications
374 $return['shipping_methods'] = self::messageTemplate($shipping_methods);
375
376 $log_data['steps']['format_methods_html'] = round((microtime(true) - $step_start) * 1000, 2) . ' ms';
377
378 // No need to restore cart or remove items - we never changed it
379 $log_data['steps']['restore_cart'] = 0;
380 } else {
381 $return['error'] = __('Produto não encontrado.', 'superfrete');
382 $return['shipping_methods'] = '';
383 }
384 } else {
385 $return['error'] = __('ID do produto não fornecido.', 'superfrete');
386 $return['shipping_methods'] = '';
387 }
388
389 // Calculate total execution time
390 $log_data['total_time'] = round((microtime(true) - $total_start_time) * 1000, 2) . ' ms';
391
392 // Add log data to the return for debugging
393 $return['performance_log'] = $log_data;
394
395 // Log to the WordPress error log
396 error_log('SuperFrete Performance Log: ' . wp_json_encode($log_data));
397
398 echo wp_json_encode($return);
399 }
400 wp_die();
401 }
402
403 static function is_product_present_in_cart() {
404 return false;
405 }
406
407 static function noShippingLocationInserted() {
408 $country = WC()->customer->get_shipping_country();
409 if (empty($country) || $country == 'default')
410 return true;
411
412 return false;
413 }
414
415 static function onlyPassErrorNotice($notice_type) {
416 if (self::doingCalculation()) {
417 return array('error');
418 }
419 return $notice_type;
420 }
421
422 static function doingCalculation() {
423
424
425 if (wp_verify_nonce($_POST['superfrete_nonce'], 'superfrete_nonce') && !empty($_POST['calc_shipping']) ) {
426 return true;
427 }
428 return false;
429 }
430
431 static function addTestProductForProperShippingCost() {
432 $product_id = filter_input(INPUT_POST, 'product_id');
433 $quantity = filter_input(INPUT_POST, 'quantity');
434 if (empty($quantity))
435 $quantity = 1;
436
437 if ($product_id) {
438 $variation_id = filter_input(INPUT_POST, 'variation_id');
439 if (!$variation_id) {
440 $variation_id = 0;
441 }
442 $item_key = self::addProductToCart($product_id, $variation_id, $quantity);
443 } else {
444 $item_key = "";
445 }
446 return $item_key;
447 }
448
449 static function addProductToCart($product_id, $variation_id, $quantity = 1) {
450 $consider_product_quantity = apply_filters('superfrete_ppscw_consider_quantity_in_shipping_calculation', get_option('superfrete_consider_quantity_field', 'dont-consider-quantity-field'), $product_id, $variation_id, $quantity);
451
452 if ($consider_product_quantity == 'dont-consider-quantity-field') {
453 if (self::productExistInCart($product_id, $variation_id))
454 return "";
455 $quantity = 1;
456 }
457
458 if (!empty($variation_id)) {
459 $variation = self::getVariationAttributes($variation_id);
460 } else {
461 $variation = array();
462 }
463
464 $item_key = WC()->cart->add_to_cart(
465 $product_id,
466 $quantity,
467 $variation_id,
468 $variation,
469 array(
470 'superfrete_test_product_for_calculation' => '1',
471 )
472 );
473 return $item_key;
474 }
475
476 static function getVariationAttributes($product_id) {
477
478 if (empty($product_id))
479 return array();
480
481 $product = wc_get_product($product_id);
482
483 if (!is_object($product))
484 return array();
485
486 $variation = array();
487 $type = $product->get_type();
488 if ($type == 'variation') {
489 $parent_id = $product->get_parent_id();
490 $parent_obj = wc_get_product($parent_id);
491 $default_attributes = $parent_obj->get_default_attributes();
492 $variation_attributes = $product->get_variation_attributes();
493 // Get all parent attributes, needed to fetch attribute options.
494 $parent_attributes = $parent_obj->get_attributes();
495 $variation = self::getAttributes($variation_attributes, $default_attributes, $parent_attributes);
496 return $variation;
497 }
498 return $variation;
499 }
500
501 static function getAttributes($variation_attributes, $default_attributes, $parent_attributes) {
502 $list = array();
503 foreach ($variation_attributes as $name => $value) {
504 $att_name = str_replace('attribute_', "", $name);
505 if (empty($value)) {
506 $value = isset($default_attributes[$att_name]) ? $default_attributes[$att_name] : "";
507
508 if (empty($value) && isset($parent_attributes[$att_name])) {
509 $attribute_obj = $parent_attributes[$att_name];
510 if ($attribute_obj->get_variation()) {
511 $options = $attribute_obj->get_options();
512 if (!empty($options)) {
513 // If taxonomy based, options are term IDs so convert the first one to slug.
514 if ($attribute_obj->is_taxonomy()) {
515 $term = get_term($options[0]);
516 if (!is_wp_error($term) && $term) {
517 $value = $term->slug;
518 } else {
519 $value = 'x';
520 }
521 } else {
522 // For custom attributes, simply use the first option.
523 $value = $options[0];
524 }
525 } else {
526 $value = 'x'; // Fallback if no options found.
527 }
528 } else {
529 $value = 'x'; // Fallback if attribute is not variation-enabled.
530 }
531 }
532 }
533 $list[$name] = $value;
534 }
535 return $list;
536 }
537
538 static function productExistInCart($product_id, $variation_id) {
539 if (!WC()->cart->is_empty()) {
540 foreach (WC()->cart->get_cart() as $cart_item) {
541 if ($cart_item['product_id'] == $product_id && $cart_item['variation_id'] == $variation_id) {
542 return true;
543 }
544 }
545 }
546 return false;
547 }
548
549 static function get_shipping_packages() {
550 return array(
551 array(
552 'contents' => array(),
553 'contents_cost' => 0,
554 'applied_coupons' => '',
555 'user' => array(
556 'ID' => get_current_user_id(),
557 ),
558 'destination' => array(
559 'country' => self::get_customer()->get_shipping_country(),
560 'state' => self::get_customer()->get_shipping_state(),
561 'postcode' => self::get_customer()->get_shipping_postcode(),
562 'city' => self::get_customer()->get_shipping_city(),
563 ),
564 'cart_subtotal' => 0,
565 ),
566 );
567 }
568
569 static function get_customer() {
570 return WC()->customer;
571 }
572
573 static function getShippingMethods($packages) {
574 $shipping_methods = array();
575 $product_id = filter_input(INPUT_POST, 'product_id');
576 $variation_id = filter_input(INPUT_POST, 'variation_id');
577 foreach ($packages as $package) {
578 if (empty($package['rates']) || !is_array($package['rates']))
579 break;
580
581 foreach ($package['rates'] as $id => $rate) {
582 $title = wc_cart_totals_shipping_method_label($rate);
583 $title = self::modifiedTitle($title, $rate);
584 $shipping_methods[$id] = apply_filters('superfrete_ppscw_shipping_method_name', $title, $rate, $product_id, $variation_id);
585 }
586 }
587 return $shipping_methods;
588 }
589
590 static function noMethodAvailableMsg() {
591
592 if (self::noShippingLocationInserted()) {
593 return wp_kses_post(get_option('superfrete_no_address_added_yet', 'Informe seu Endereço para calcular'));
594 } else {
595 return wp_kses_post(get_option('superfrete_no_shipping_methods_msg', 'Nenhum método de envio encontrado'));
596 }
597 }
598
599 static function disableAutoLoadEstimate() {
600 $auto_loading = get_option('superfrete_auto_calculation', 'disabled'); // Changed default to disabled
601
602 if ($auto_loading == 'enabled')
603 return false;
604
605 return true;
606 }
607
608 static function messageTemplate($shipping_methods) {
609 $html = '';
610 if (!empty($shipping_methods)) {
611 $html .= '<div class="superfrete-shipping-methods">';
612 $html .= '<h3>' . __('Opções de Entrega', 'superfrete') . '</h3>';
613
614 foreach ($shipping_methods as $method_id => $method_name) {
615 // Extract shipping method name and price
616 $html .= '<div class="superfrete-shipping-method">';
617
618 // Get just the method name (everything before the colon)
619 $method_parts = explode(':', $method_name, 2);
620 $method_label = trim(strip_tags($method_parts[0]));
621
622 // Add method name to the HTML
623 $html .= '<span class="superfrete-shipping-method-name">' . esc_html($method_label) . '</span>';
624
625 // Handle price display - keeping the full HTML structure for WooCommerce price formatting
626 if (count($method_parts) > 1 && !empty($method_parts[1])) {
627 // Check if the price part contains HTML or not
628 if (strpos($method_parts[1], '<span') !== false) {
629 // Keep the HTML formatting intact for the price
630 $html .= '<span class="superfrete-shipping-method-price">' . wp_kses_post($method_parts[1]) . '</span>';
631 } else {
632 // Add simple text price
633 $html .= '<span class="superfrete-shipping-method-price">' . esc_html(trim($method_parts[1])) . '</span>';
634 }
635 } else {
636 // No price found, show as Free
637 $html .= '<span class="superfrete-shipping-method-price">Gratuito</span>';
638 }
639
640 $html .= '</div>';
641 }
642
643 $html .= '</div>';
644 } else {
645 $message = get_option('superfrete_no_rates_message', 'Desculpe, não encontramos métodos de envio para [country]. Por favor, verifique seu endereço ou entre em contato conosco.');
646
647 $country = __('Brasil', 'superfrete');
648
649 if (isset(WC()->customer)) {
650 $country_code = self::get_customer()->get_shipping_country();
651 if (!empty($country_code) && isset(WC()->countries) && $country_code !== 'default') {
652 $country = WC()->countries->countries[$country_code];
653 }
654 }
655
656 $find_replace = [
657 '[country]' => $country
658 ];
659
660 $message = str_replace(array_keys($find_replace), array_values($find_replace), $message);
661
662 $html .= '<div class="superfrete-no-shipping-methods">' . esc_html($message) . '</div>';
663 }
664
665 return $html;
666 }
667
668 static function shortCode($message) {
669
670 $country = __('Country', 'superfrete-product-page-shipping-calculator-woocommerce');
671
672 if (isset(WC()->customer)) {
673 $country_code = self::get_customer()->get_shipping_country();
674 if (!empty($country_code) && isset(WC()->countries) && $country_code !== 'default') {
675 $country = WC()->countries->countries[$country_code];
676 }
677 }
678
679 $find_replace = array(
680 '[country]' => $country
681 );
682
683 $message = str_replace(array_keys($find_replace), array_values($find_replace), $message);
684
685 return $message;
686 }
687
688 function enableShippingCalculationWithoutAddress($val) {
689 if (wp_verify_nonce($_POST['superfrete_nonce'], 'superfrete_nonce') && ((isset($_POST['action']) && $_POST['action'] === 'superfrete_cal_shipping') || (isset($_POST['action']) && $_POST['action'] === 'superfrete_save_address_form'))) {
690 return null;
691 }
692 return $val;
693 }
694
695 static function modifiedTitle($title, $rate) {
696
697 if (isset($rate->cost) && $rate->cost == 0) {
698 $free_display_type = get_option('superfrete_free_shipping_price', 'nothing');
699
700 if ($free_display_type == 'nothing')
701 return $title;
702
703 if ($free_display_type == 'zero') {
704 $label = $rate->get_label();
705 $title = $label . ': ' . wc_price($rate->cost);
706 }
707 }
708
709 return $title;
710 }
711
712 static function loadLocation() {
713 $location = ['calc_shipping_country' => '', 'calc_shipping_state' => '', 'calc_shipping_city' => '', 'calc_shipping_postcode' => ''];
714
715 if (function_exists('WC') && isset(WC()->customer) && is_object(WC()->customer)) {
716 $location['calc_shipping_country'] = WC()->customer->get_shipping_country();
717 $location['calc_shipping_state'] = WC()->customer->get_shipping_state();
718 $location['calc_shipping_city'] = WC()->customer->get_shipping_city();
719 $location['calc_shipping_postcode'] = WC()->customer->get_shipping_postcode();
720 }
721
722 wp_send_json($location);
723 }
724
725 /**
726 * Exibe o formulário de cálculo de frete na página do produto.
727 */
728 public function display_calculator_form() {
729 include plugin_dir_path(__FILE__) . '../../templates/woocommerce/shipping-calculator.php';
730 }
731 /**
732 * Adiciona os scripts necessários
733 */
734 public function enqueue_scripts() {
735 $plugin_file = plugin_dir_path(__FILE__) . '../../superfrete.php';
736
737 // Inclui função get_plugin_data se ainda não estiver disponível
738 if (!function_exists('get_plugin_data')) {
739 require_once ABSPATH . 'wp-admin/includes/plugin.php';
740 }
741 $plugin_data = get_plugin_data($plugin_file);
742 $plugin_version = $plugin_data['Version'];
743
744 // Enqueue JavaScript
745 wp_enqueue_script(
746 'superfrete-calculator',
747 plugin_dir_url(__FILE__) . '../../assets/scripts/superfrete-calculator.js',
748 ['jquery'],
749 $plugin_version, // Versão do script
750 true
751 );
752
753 // Enqueue CSS
754 wp_enqueue_style(
755 'superfrete-calculator-style',
756 plugin_dir_url(__FILE__) . '../../assets/styles/superfrete-calculator.css',
757 [],
758 $plugin_version
759 );
760
761 wp_localize_script('superfrete-calculator', 'superfrete_ajax', [
762 'ajax_url' => admin_url('admin-ajax.php'),
763 ]);
764
765 // Localize script with additional settings
766 wp_localize_script('superfrete-calculator', 'superfrete_setting', [
767 'wc_ajax_url' => add_query_arg(['wc-ajax' => '%%endpoint%%'], home_url('/')),
768 'auto_load' => true,
769 'country_code' => 'BR',
770 'i18n' => [
771 'state_label' => __('Estado', 'superfrete'),
772 'select_state_text' => __('Selecione um estado', 'superfrete')
773 ]
774 ]);
775 }
776 }
777