← All changes
|
includes/widgets/Woo_Cart_Table/Woo_Cart_Table.php
+81
-21
51.1.65
→
51.1.87
View file →
| @@ -47,9 +47,9 @@ | ||
| 47 | 47 | * @return string |
| 48 | 48 | */ |
| 49 | 49 | public function get_icon(): string |
| 50 | 50 | { |
| 51 | - return 'eicon-cart'; | |
| 51 | + return 'king-addons-icon king-addons-woo-cart-table'; | |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | /** |
| 55 | 55 | * Categories. |
| @@ -111,9 +111,10 @@ | ||
| 111 | 111 | 'heading_empty', |
| 112 | 112 | [ |
| 113 | 113 | 'label' => esc_html__('Empty title', 'king-addons'), |
| 114 | 114 | 'type' => Controls_Manager::TEXT, |
| 115 | - 'default' => esc_html__('Your cart is empty', 'king-addons'), | |
| 115 | + 'dynamic' => ['active' => true], | |
| 116 | + 'default' => __('Your cart is empty', 'king-addons'), | |
| 116 | 117 | ] |
| 117 | 118 | ); |
| 118 | 119 | |
| 119 | 120 | $this->add_control( |
| @@ -120,9 +121,10 @@ | ||
| 120 | 121 | 'message_empty', |
| 121 | 122 | [ |
| 122 | 123 | 'label' => esc_html__('Empty message', 'king-addons'), |
| 123 | 124 | 'type' => Controls_Manager::TEXTAREA, |
| 124 | - 'default' => esc_html__('Looks like you have not added anything to your cart yet.', 'king-addons'), | |
| 125 | + 'dynamic' => ['active' => true], | |
| 126 | + 'default' => __('Looks like you have not added anything to your cart yet.', 'king-addons'), | |
| 125 | 127 | ] |
| 126 | 128 | ); |
| 127 | 129 | |
| 128 | 130 | $this->add_control( |
| @@ -129,9 +131,10 @@ | ||
| 129 | 131 | 'primary_btn_text', |
| 130 | 132 | [ |
| 131 | 133 | 'label' => esc_html__('Primary button text', 'king-addons'), |
| 132 | 134 | 'type' => Controls_Manager::TEXT, |
| 133 | - 'default' => esc_html__('Return to shop', 'king-addons'), | |
| 135 | + 'dynamic' => ['active' => true], | |
| 136 | + 'default' => __('Return to shop', 'king-addons'), | |
| 134 | 137 | ] |
| 135 | 138 | ); |
| 136 | 139 | |
| 137 | 140 | $this->add_control( |
| @@ -138,8 +141,9 @@ | ||
| 138 | 141 | 'primary_btn_url', |
| 139 | 142 | [ |
| 140 | 143 | 'label' => esc_html__('Primary button URL', 'king-addons'), |
| 141 | 144 | 'type' => Controls_Manager::URL, |
| 145 | + 'dynamic' => ['active' => true], | |
| 142 | 146 | 'placeholder' => 'https://', |
| 143 | 147 | ] |
| 144 | 148 | ); |
| 145 | 149 | |
| @@ -147,9 +151,10 @@ | ||
| 147 | 151 | 'secondary_btn_text', |
| 148 | 152 | [ |
| 149 | 153 | 'label' => sprintf(__('Secondary button text %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'), |
| 150 | 154 | 'type' => Controls_Manager::TEXT, |
| 151 | - 'default' => esc_html__('View offers', 'king-addons'), | |
| 155 | + 'dynamic' => ['active' => true], | |
| 156 | + 'default' => __('View offers', 'king-addons'), | |
| 152 | 157 | ] |
| 153 | 158 | ); |
| 154 | 159 | |
| 155 | 160 | $this->add_control( |
| @@ -156,8 +161,9 @@ | ||
| 156 | 161 | 'secondary_btn_url', |
| 157 | 162 | [ |
| 158 | 163 | 'label' => sprintf(__('Secondary button URL %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'), |
| 159 | 164 | 'type' => Controls_Manager::URL, |
| 165 | + 'dynamic' => ['active' => true], | |
| 160 | 166 | 'placeholder' => 'https://', |
| 161 | 167 | ] |
| 162 | 168 | ); |
| 163 | 169 | |
| @@ -247,9 +253,21 @@ | ||
| 247 | 253 | } |
| 248 | 254 | |
| 249 | 255 | $ajax_nonce = wp_create_nonce('ka_cart'); |
| 250 | 256 | |
| 251 | - echo '<div class="ka-cart-table" data-ka-cart="1" data-ajax-url="' . esc_url(admin_url('admin-ajax.php')) . '" data-nonce="' . esc_attr($ajax_nonce) . '">'; | |
| 257 | + // The empty-cart block after an AJAX removal used to be a hardcoded | |
| 258 | + // minimal version, so emptying the cart in place looked nothing like | |
| 259 | + // loading an empty cart. Hand the configured copy to the script. | |
| 260 | + $shop_id = wc_get_page_id('shop'); | |
| 261 | + $shop_url = $shop_id > 0 ? get_permalink($shop_id) : home_url('/'); | |
| 262 | + $empty_attrs = ' data-empty-title="' . esc_attr((string) ($settings['heading_empty'] ?? '')) . '"' | |
| 263 | + . ' data-empty-message="' . esc_attr((string) ($settings['message_empty'] ?? '')) . '"' | |
| 264 | + . ' data-empty-primary-text="' . esc_attr((string) ($settings['primary_btn_text'] ?? '')) . '"' | |
| 265 | + . ' data-empty-primary-url="' . esc_url(!empty($settings['primary_btn_url']['url']) ? $settings['primary_btn_url']['url'] : $shop_url) . '"' | |
| 266 | + . ' data-empty-secondary-text="' . esc_attr($can_pro ? (string) ($settings['secondary_btn_text'] ?? '') : '') . '"' | |
| 267 | + . ' data-empty-secondary-url="' . esc_url(($can_pro && !empty($settings['secondary_btn_url']['url'])) ? $settings['secondary_btn_url']['url'] : '') . '"'; | |
| 268 | + | |
| 269 | + echo '<div class="ka-cart-table" data-ka-cart="1" data-ajax-url="' . esc_url(admin_url('admin-ajax.php')) . '" data-nonce="' . esc_attr($ajax_nonce) . '"' . $empty_attrs . '>'; | |
| 252 | 270 | woocommerce_output_all_notices(); |
| 253 | 271 | wc_get_template('cart/cart.php'); |
| 254 | 272 | echo '</div>'; |
| 255 | 273 | |
| @@ -280,11 +298,11 @@ | ||
| 280 | 298 | $shop_id = wc_get_page_id('shop'); |
| 281 | 299 | $shop_url = $shop_id > 0 ? get_permalink($shop_id) : home_url('/'); |
| 282 | 300 | $can_pro = king_addons_can_use_pro(); |
| 283 | 301 | |
| 284 | - $heading = $settings['heading_empty'] ?? esc_html__('Your cart is empty', 'king-addons'); | |
| 285 | - $message = $settings['message_empty'] ?? esc_html__('Looks like you have not added anything to your cart yet.', 'king-addons'); | |
| 286 | - $primary_text = $settings['primary_btn_text'] ?? esc_html__('Return to shop', 'king-addons'); | |
| 302 | + $heading = $settings['heading_empty'] ?? __('Your cart is empty', 'king-addons'); | |
| 303 | + $message = $settings['message_empty'] ?? __('Looks like you have not added anything to your cart yet.', 'king-addons'); | |
| 304 | + $primary_text = $settings['primary_btn_text'] ?? __('Return to shop', 'king-addons'); | |
| 287 | 305 | $primary_url = !empty($settings['primary_btn_url']['url']) ? $settings['primary_btn_url']['url'] : $shop_url; |
| 288 | 306 | $secondary_text = (!empty($settings['secondary_btn_text']) && $can_pro) ? $settings['secondary_btn_text'] : ''; |
| 289 | 307 | $secondary_url = (!empty($settings['secondary_btn_url']['url']) && $can_pro) ? $settings['secondary_btn_url']['url'] : ''; |
| 290 | 308 | |
| @@ -384,12 +402,15 @@ | ||
| 384 | 402 | private static function build_fragments(): array |
| 385 | 403 | { |
| 386 | 404 | $empty = WC()->cart->is_empty(); |
| 387 | 405 | |
| 406 | + // Capture notices before cart HTML. Previously render_cart_html() printed | |
| 407 | + // them first via woocommerce_output_all_notices(), so ajax fragments | |
| 408 | + // returned an empty notices string and the coupon widget stayed silent. | |
| 409 | + $notices = function_exists('wc_print_notices') ? wc_print_notices(true) : ''; | |
| 388 | 410 | $cart_html = $empty ? self::render_empty_cart_html() : self::render_cart_html(); |
| 389 | 411 | $totals_html = self::render_totals_html($empty); |
| 390 | 412 | $cross_html = self::render_cross_sells_html($empty); |
| 391 | - $notices = function_exists('wc_print_notices') ? wc_print_notices(true) : ''; | |
| 392 | 413 | |
| 393 | 414 | return [ |
| 394 | 415 | 'cart_html' => $cart_html, |
| 395 | 416 | 'totals_html' => $totals_html, |
| @@ -408,11 +429,25 @@ | ||
| 408 | 429 | */ |
| 409 | 430 | private static function render_cart_html(): string |
| 410 | 431 | { |
| 411 | 432 | ob_start(); |
| 412 | - woocommerce_output_all_notices(); | |
| 433 | + $had_totals = has_action('woocommerce_cart_collaterals', 'woocommerce_cart_totals'); | |
| 434 | + $had_cross = has_action('woocommerce_cart_collaterals', 'woocommerce_cross_sell_display'); | |
| 435 | + if ($had_totals) { | |
| 436 | + remove_action('woocommerce_cart_collaterals', 'woocommerce_cart_totals', 10); | |
| 437 | + } | |
| 438 | + if ($had_cross) { | |
| 439 | + remove_action('woocommerce_cart_collaterals', 'woocommerce_cross_sell_display', 10); | |
| 440 | + } | |
| 413 | 441 | wc_get_template('cart/cart.php'); |
| 414 | - return (string) ob_get_clean(); | |
| 442 | + if ($had_totals) { | |
| 443 | + add_action('woocommerce_cart_collaterals', 'woocommerce_cart_totals', 10); | |
| 444 | + } | |
| 445 | + if ($had_cross) { | |
| 446 | + add_action('woocommerce_cart_collaterals', 'woocommerce_cross_sell_display', 10); | |
| 447 | + } | |
| 448 | + $html = (string) ob_get_clean(); | |
| 449 | + return (string) preg_replace('#<div class="cart-collaterals">\s*</div>#', '', $html); | |
| 415 | 450 | } |
| 416 | 451 | |
| 417 | 452 | /** |
| 418 | 453 | * Render totals HTML. |
| @@ -457,24 +492,49 @@ | ||
| 457 | 492 | { |
| 458 | 493 | $shop_id = wc_get_page_id('shop'); |
| 459 | 494 | $shop_url = $shop_id > 0 ? get_permalink($shop_id) : home_url('/'); |
| 460 | 495 | |
| 496 | + // The copy comes from the widget, passed along by the script, so the | |
| 497 | + // markup matches what a full page load of an empty cart produces. | |
| 498 | + // phpcs:disable WordPress.Security.NonceVerification.Missing -- verified by the caller. | |
| 499 | + $heading = isset($_POST['empty_title']) ? sanitize_text_field(wp_unslash($_POST['empty_title'])) : __('Your cart is empty', 'king-addons'); | |
| 500 | + $message = isset($_POST['empty_message']) ? sanitize_text_field(wp_unslash($_POST['empty_message'])) : ''; | |
| 501 | + $primary_text = isset($_POST['empty_primary_text']) ? sanitize_text_field(wp_unslash($_POST['empty_primary_text'])) : __('Return to shop', 'king-addons'); | |
| 502 | + $primary_url = isset($_POST['empty_primary_url']) ? esc_url_raw(wp_unslash($_POST['empty_primary_url'])) : ''; | |
| 503 | + $secondary_text = isset($_POST['empty_secondary_text']) ? sanitize_text_field(wp_unslash($_POST['empty_secondary_text'])) : ''; | |
| 504 | + $secondary_url = isset($_POST['empty_secondary_url']) ? esc_url_raw(wp_unslash($_POST['empty_secondary_url'])) : ''; | |
| 505 | + // phpcs:enable WordPress.Security.NonceVerification.Missing | |
| 506 | + | |
| 507 | + if ('' === $primary_url) { | |
| 508 | + $primary_url = $shop_url; | |
| 509 | + } | |
| 510 | + | |
| 461 | 511 | ob_start(); |
| 462 | 512 | echo '<div class="ka-cart-empty">'; |
| 463 | - echo '<p class="ka-cart-empty__text">' . esc_html__('Your cart is empty.', 'king-addons') . '</p>'; | |
| 464 | - echo '<a class="ka-cart-empty__link" href="' . esc_url($shop_url) . '">' . esc_html__('Return to shop', 'king-addons') . '</a>'; | |
| 513 | + echo '<div class="ka-cart-empty__icon" aria-hidden="true">🛒</div>'; | |
| 514 | + if ($heading) { | |
| 515 | + echo '<h3 class="ka-cart-empty__title">' . esc_html($heading) . '</h3>'; | |
| 516 | + } | |
| 517 | + if ($message) { | |
| 518 | + echo '<p class="ka-cart-empty__text">' . esc_html($message) . '</p>'; | |
| 519 | + } | |
| 520 | + echo '<div class="ka-cart-empty__actions">'; | |
| 521 | + if ($primary_text && $primary_url) { | |
| 522 | + echo '<a class="ka-cart-empty__btn ka-cart-empty__btn--primary" href="' . esc_url($primary_url) . '">' . esc_html($primary_text) . '</a>'; | |
| 523 | + } | |
| 524 | + if ($secondary_text && $secondary_url) { | |
| 525 | + echo '<a class="ka-cart-empty__btn ka-cart-empty__btn--ghost" href="' . esc_url($secondary_url) . '">' . esc_html($secondary_text) . '</a>'; | |
| 526 | + } | |
| 465 | 527 | echo '</div>'; |
| 528 | + do_action('king_addons/cart/empty_after'); | |
| 529 | + echo '</div>'; | |
| 466 | 530 | return (string) ob_get_clean(); |
| 467 | 531 | } |
| 468 | 532 | } |
| 469 | 533 | |
| 470 | -// Register AJAX handlers only if WooCommerce is active | |
| 471 | -if (class_exists('WooCommerce')) { | |
| 472 | - add_action('wp_ajax_ka_cart_update', [Woo_Cart_Table::class, 'ajax_update']); | |
| 473 | - add_action('wp_ajax_nopriv_ka_cart_update', [Woo_Cart_Table::class, 'ajax_update']); | |
| 474 | - add_action('wp_ajax_ka_cart_coupon', [Woo_Cart_Table::class, 'ajax_coupon']); | |
| 475 | - add_action('wp_ajax_nopriv_ka_cart_coupon', [Woo_Cart_Table::class, 'ajax_coupon']); | |
| 476 | -} | |
| 534 | +// Registration lives in Woo_Builder: admin-ajax.php never loads Elementor | |
| 535 | +// widget files, so hooking from here meant the quantity, remove and coupon | |
| 536 | +// requests all came back as "0". | |
| 477 | 537 | |
| 478 | 538 | |
| 479 | 539 | |
| 480 | 540 | |