I’ll build this as a big, practical inc/woocommerce/cart.php module for your RX theme: safety checks, WooCommerce hooks, cart UX, notices, quantity controls, fragments, fees, cross-sells, shipping/free-shipping messages, AJAX helpers, and admin-friendly filters.
Yes my dear friend — create this file:
rx-theme/inc/woocommerce/cart.php
Then include it in your theme functions.php:
require_once get_template_directory() . '/inc/woocommerce/cart.php';
WooCommerce supports cart customization through hooks like woocommerce_before_cart, woocommerce_after_cart, cart fragments, notices, template overrides, and filters. Official WooCommerce docs recommend overriding template files from a theme instead of editing the plugin directly, and WooCommerce’s cart notices/functions are available through functions such as wc_add_notice() and wc_print_notice().
Below is a large, advanced cart.php module for your RX theme.
<?php
/**
* RX Theme WooCommerce Cart Enhancements
*
* File: inc/woocommerce/cart.php
*
* Features:
* - WooCommerce safety checks
* - Cart page wrappers
* - Cart notices
* - Free shipping progress
* - Cart item meta improvements
* - Quantity controls
* - AJAX mini-cart fragments
* - Cart count shortcode
* - Cart subtotal shortcode
* - Empty cart improvements
* - Continue shopping button
* - Cross-sell enhancements
* - Coupon helpers
* - Shipping messages
* - Secure checkout trust section
* - Cart body classes
* - Cart item thumbnail fallback
* - Product stock and backorder notices
* - Optional handling fee / discount examples
* - Clean extensible filters for future development
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
if ( ! defined( 'RX_THEME_VERSION' ) ) {
define( 'RX_THEME_VERSION', '1.0.0' );
}
/**
* Stop if WooCommerce is not active.
*/
if ( ! class_exists( 'WooCommerce' ) ) {
return;
}
if ( ! class_exists( 'RX_WooCommerce_Cart' ) ) :
final class RX_WooCommerce_Cart {
/**
* Single instance.
*
* @var RX_WooCommerce_Cart|null
*/
private static $instance = null;
/**
* Get instance.
*
* @return RX_WooCommerce_Cart
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*/
private function __construct() {
$this->hooks();
}
/**
* Register hooks.
*
* @return void
*/
private function hooks() {
/**
* Layout wrappers.
*/
add_action( 'woocommerce_before_cart', array( $this, 'cart_open_wrapper' ), 1 );
add_action( 'woocommerce_after_cart', array( $this, 'cart_close_wrapper' ), 99 );
/**
* Top and bottom cart sections.
*/
add_action( 'woocommerce_before_cart', array( $this, 'cart_page_header' ), 3 );
add_action( 'woocommerce_before_cart', array( $this, 'cart_login_reminder' ), 6 );
add_action( 'woocommerce_before_cart', array( $this, 'free_shipping_progress' ), 8 );
add_action( 'woocommerce_before_cart', array( $this, 'cart_coupon_tip' ), 10 );
add_action( 'woocommerce_after_cart_table', array( $this, 'after_cart_table_message' ), 10 );
add_action( 'woocommerce_after_cart_totals', array( $this, 'secure_checkout_box' ), 10 );
add_action( 'woocommerce_after_cart', array( $this, 'cart_help_section' ), 20 );
/**
* Empty cart.
*/
add_action( 'woocommerce_cart_is_empty', array( $this, 'empty_cart_extra_content' ), 20 );
/**
* Cart item enhancements.
*/
add_filter( 'woocommerce_cart_item_name', array( $this, 'cart_item_name_badges' ), 20, 3 );
add_filter( 'woocommerce_cart_item_thumbnail', array( $this, 'cart_item_thumbnail_fallback' ), 20, 3 );
add_filter( 'woocommerce_get_item_data', array( $this, 'cart_item_custom_data' ), 20, 2 );
add_filter( 'woocommerce_cart_item_remove_link', array( $this, 'cart_item_remove_link_accessible' ), 20, 2 );
add_filter( 'woocommerce_cart_item_quantity', array( $this, 'cart_quantity_wrapper' ), 20, 3 );
/**
* Buttons and actions.
*/
add_action( 'woocommerce_cart_actions', array( $this, 'continue_shopping_button' ), 20 );
add_action( 'woocommerce_proceed_to_checkout', array( $this, 'checkout_microcopy' ), 5 );
/**
* Notices.
*/
add_action( 'template_redirect', array( $this, 'cart_notices' ) );
/**
* Fragments.
*/
add_filter( 'woocommerce_add_to_cart_fragments', array( $this, 'cart_fragments' ) );
/**
* Body classes.
*/
add_filter( 'body_class', array( $this, 'body_classes' ) );
/**
* Cross-sells.
*/
add_filter( 'woocommerce_cross_sells_columns', array( $this, 'cross_sells_columns' ) );
add_filter( 'woocommerce_cross_sells_total', array( $this, 'cross_sells_total' ) );
/**
* Cart totals text.
*/
add_filter( 'woocommerce_cart_totals_coupon_label', array( $this, 'coupon_label' ), 20, 2 );
add_filter( 'woocommerce_cart_totals_order_total_html', array( $this, 'order_total_html' ), 20 );
/**
* Optional fees / discount examples.
* Disabled by default through filter.
*/
add_action( 'woocommerce_cart_calculate_fees', array( $this, 'optional_cart_fees' ), 20 );
/**
* Shortcodes.
*/
add_shortcode( 'rx_cart_count', array( $this, 'shortcode_cart_count' ) );
add_shortcode( 'rx_cart_subtotal', array( $this, 'shortcode_cart_subtotal' ) );
add_shortcode( 'rx_cart_link', array( $this, 'shortcode_cart_link' ) );
/**
* Assets.
*/
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
}
/**
* Check cart page.
*
* @return bool
*/
private function is_cart_page() {
return function_exists( 'is_cart' ) && is_cart();
}
/**
* Get cart object safely.
*
* @return WC_Cart|null
*/
private function cart() {
if ( function_exists( 'WC' ) && WC()->cart ) {
return WC()->cart;
}
return null;
}
/**
* Open cart wrapper.
*
* @return void
*/
public function cart_open_wrapper() {
if ( ! $this->is_cart_page() ) {
return;
}
echo '<section class="rx-cart-page" id="rx-cart-page">';
echo '<div class="rx-cart-container">';
}
/**
* Close cart wrapper.
*
* @return void
*/
public function cart_close_wrapper() {
if ( ! $this->is_cart_page() ) {
return;
}
echo '</div>';
echo '</section>';
}
/**
* Cart page header.
*
* @return void
*/
public function cart_page_header() {
if ( ! $this->is_cart_page() ) {
return;
}
$count = $this->get_cart_count();
echo '<header class="rx-cart-header">';
echo '<h1 class="rx-cart-title">' . esc_html__( 'Shopping Cart', 'rx-theme' ) . '</h1>';
if ( $count > 0 ) {
echo '<p class="rx-cart-subtitle">';
echo esc_html(
sprintf(
_n(
'You have %s item in your cart.',
'You have %s items in your cart.',
$count,
'rx-theme'
),
number_format_i18n( $count )
)
);
echo '</p>';
} else {
echo '<p class="rx-cart-subtitle">' . esc_html__( 'Your cart is ready when you are.', 'rx-theme' ) . '</p>';
}
echo '</header>';
}
/**
* Login reminder on cart page.
*
* @return void
*/
public function cart_login_reminder() {
if ( ! $this->is_cart_page() || is_user_logged_in() ) {
return;
}
$myaccount_url = wc_get_page_permalink( 'myaccount' );
if ( empty( $myaccount_url ) ) {
return;
}
echo '<div class="rx-cart-login-reminder">';
echo '<span class="rx-cart-login-icon" aria-hidden="true">👤</span>';
echo '<span>' . esc_html__( 'Already have an account?', 'rx-theme' ) . '</span> ';
echo '<a href="' . esc_url( $myaccount_url ) . '">' . esc_html__( 'Log in for faster checkout.', 'rx-theme' ) . '</a>';
echo '</div>';
}
/**
* Free shipping progress message.
*
* @return void
*/
public function free_shipping_progress() {
if ( ! $this->is_cart_page() ) {
return;
}
$cart = $this->cart();
if ( ! $cart || $cart->is_empty() ) {
return;
}
$threshold = (float) apply_filters( 'rx_cart_free_shipping_threshold', 0 );
if ( $threshold <= 0 ) {
return;
}
$subtotal = (float) $cart->get_displayed_subtotal();
if ( $subtotal <= 0 ) {
return;
}
$remaining = max( 0, $threshold - $subtotal );
$percent = min( 100, round( ( $subtotal / $threshold ) * 100 ) );
echo '<div class="rx-free-shipping-box">';
if ( $remaining > 0 ) {
echo '<p class="rx-free-shipping-message">';
echo wp_kses_post(
sprintf(
/* translators: %s remaining amount */
__( 'Add %s more to unlock free shipping.', 'rx-theme' ),
wc_price( $remaining )
)
);
echo '</p>';
} else {
echo '<p class="rx-free-shipping-message rx-success">';
echo esc_html__( 'Congratulations! Your cart may qualify for free shipping.', 'rx-theme' );
echo '</p>';
}
echo '<div class="rx-free-shipping-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' . esc_attr( $percent ) . '">';
echo '<span style="width:' . esc_attr( $percent ) . '%"></span>';
echo '</div>';
echo '</div>';
}
/**
* Coupon tip.
*
* @return void
*/
public function cart_coupon_tip() {
if ( ! $this->is_cart_page() || ! wc_coupons_enabled() ) {
return;
}
$cart = $this->cart();
if ( ! $cart || $cart->is_empty() ) {
return;
}
echo '<div class="rx-cart-coupon-tip">';
echo esc_html__( 'Have a coupon code? Apply it before checkout to update your total instantly.', 'rx-theme' );
echo '</div>';
}
/**
* Message after cart table.
*
* @return void
*/
public function after_cart_table_message() {
if ( ! $this->is_cart_page() ) {
return;
}
echo '<div class="rx-after-cart-table">';
echo '<p>' . esc_html__( 'Please review product quantity, coupon, shipping, and total before placing your order.', 'rx-theme' ) . '</p>';
echo '</div>';
}
/**
* Secure checkout section.
*
* @return void
*/
public function secure_checkout_box() {
if ( ! $this->is_cart_page() ) {
return;
}
echo '<div class="rx-secure-checkout-box">';
echo '<h3>' . esc_html__( 'Secure Checkout', 'rx-theme' ) . '</h3>';
echo '<ul>';
echo '<li>' . esc_html__( 'Encrypted checkout process', 'rx-theme' ) . '</li>';
echo '<li>' . esc_html__( 'Order summary before payment', 'rx-theme' ) . '</li>';
echo '<li>' . esc_html__( 'Safe customer information handling', 'rx-theme' ) . '</li>';
echo '</ul>';
echo '</div>';
}
/**
* Help section after cart.
*
* @return void
*/
public function cart_help_section() {
if ( ! $this->is_cart_page() ) {
return;
}
$contact_url = apply_filters( 'rx_cart_contact_url', home_url( '/contact/' ) );
echo '<div class="rx-cart-help">';
echo '<h2>' . esc_html__( 'Need help with your order?', 'rx-theme' ) . '</h2>';
echo '<p>' . esc_html__( 'Contact support if you have questions about product details, delivery, or checkout.', 'rx-theme' ) . '</p>';
echo '<a class="button rx-cart-help-button" href="' . esc_url( $contact_url ) . '">' . esc_html__( 'Contact Support', 'rx-theme' ) . '</a>';
echo '</div>';
}
/**
* Extra content on empty cart.
*
* @return void
*/
public function empty_cart_extra_content() {
if ( ! $this->is_cart_page() ) {
return;
}
$shop_url = wc_get_page_permalink( 'shop' );
echo '<div class="rx-empty-cart-extra">';
echo '<h2>' . esc_html__( 'Your cart is empty', 'rx-theme' ) . '</h2>';
echo '<p>' . esc_html__( 'Browse products and add your favorite items to start your order.', 'rx-theme' ) . '</p>';
if ( $shop_url ) {
echo '<a class="button rx-empty-cart-button" href="' . esc_url( $shop_url ) . '">' . esc_html__( 'Start Shopping', 'rx-theme' ) . '</a>';
}
echo '</div>';
}
/**
* Add badges below cart item name.
*
* @param string $name Product name HTML.
* @param array $cart_item Cart item.
* @param string $cart_item_key Cart item key.
*
* @return string
*/
public function cart_item_name_badges( $name, $cart_item, $cart_item_key ) {
if ( empty( $cart_item['data'] ) || ! is_a( $cart_item['data'], 'WC_Product' ) ) {
return $name;
}
$product = $cart_item['data'];
$badges = array();
if ( $product->is_on_sale() ) {
$badges[] = '<span class="rx-cart-badge rx-sale">' . esc_html__( 'Sale', 'rx-theme' ) . '</span>';
}
if ( $product->is_featured() ) {
$badges[] = '<span class="rx-cart-badge rx-featured">' . esc_html__( 'Featured', 'rx-theme' ) . '</span>';
}
if ( $product->backorders_allowed() && $product->is_on_backorder( $cart_item['quantity'] ) ) {
$badges[] = '<span class="rx-cart-badge rx-backorder">' . esc_html__( 'Backorder', 'rx-theme' ) . '</span>';
}
if ( ! $product->is_in_stock() ) {
$badges[] = '<span class="rx-cart-badge rx-out-stock">' . esc_html__( 'Out of stock', 'rx-theme' ) . '</span>';
}
$badges = apply_filters( 'rx_cart_item_badges', $badges, $product, $cart_item, $cart_item_key );
if ( empty( $badges ) ) {
return $name;
}
$name .= '<div class="rx-cart-item-badges">' . implode( '', array_map( 'wp_kses_post', $badges ) ) . '</div>';
return $name;
}
/**
* Product thumbnail fallback.
*
* @param string $thumbnail Thumbnail HTML.
* @param array $cart_item Cart item.
* @param string $cart_item_key Cart item key.
*
* @return string
*/
public function cart_item_thumbnail_fallback( $thumbnail, $cart_item, $cart_item_key ) {
if ( ! empty( $thumbnail ) ) {
return $thumbnail;
}
return '<span class="rx-cart-thumbnail-fallback" aria-hidden="true">🛒</span>';
}
/**
* Add custom data rows under item.
*
* @param array $item_data Item data.
* @param array $cart_item Cart item.
*
* @return array
*/
public function cart_item_custom_data( $item_data, $cart_item ) {
if ( empty( $cart_item['data'] ) || ! is_a( $cart_item['data'], 'WC_Product' ) ) {
return $item_data;
}
$product = $cart_item['data'];
if ( $product->get_sku() ) {
$item_data[] = array(
'key' => esc_html__( 'SKU', 'rx-theme' ),
'value' => esc_html( $product->get_sku() ),
);
}
if ( $product->is_downloadable() ) {
$item_data[] = array(
'key' => esc_html__( 'Type', 'rx-theme' ),
'value' => esc_html__( 'Downloadable product', 'rx-theme' ),
);
}
if ( $product->is_virtual() ) {
$item_data[] = array(
'key' => esc_html__( 'Delivery', 'rx-theme' ),
'value' => esc_html__( 'No physical delivery required', 'rx-theme' ),
);
}
return apply_filters( 'rx_cart_item_custom_data', $item_data, $cart_item );
}
/**
* Accessible remove link.
*
* @param string $link Remove link.
* @param string $cart_item_key Cart item key.
*
* @return string
*/
public function cart_item_remove_link_accessible( $link, $cart_item_key ) {
$cart = $this->cart();
if ( ! $cart ) {
return $link;
}
$cart_item = $cart->get_cart_item( $cart_item_key );
if ( empty( $cart_item['data'] ) || ! is_a( $cart_item['data'], 'WC_Product' ) ) {
return $link;
}
$product = $cart_item['data'];
return sprintf(
'<a href="%s" class="remove rx-cart-remove" aria-label="%s" data-product_id="%s" data-product_sku="%s">×<span class="screen-reader-text">%s</span></a>',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
esc_attr(
sprintf(
/* translators: %s product name */
__( 'Remove %s from cart', 'rx-theme' ),
$product->get_name()
)
),
esc_attr( $product->get_id() ),
esc_attr( $product->get_sku() ),
esc_html__( 'Remove item', 'rx-theme' )
);
}
/**
* Quantity wrapper.
*
* @param string $product_quantity Quantity HTML.
* @param string $cart_item_key Cart item key.
* @param array $cart_item Cart item.
*
* @return string
*/
public function cart_quantity_wrapper( $product_quantity, $cart_item_key, $cart_item ) {
if ( empty( $cart_item['data'] ) || ! is_a( $cart_item['data'], 'WC_Product' ) ) {
return $product_quantity;
}
$product = $cart_item['data'];
$html = '<div class="rx-cart-quantity-wrap">';
$html .= '<button type="button" class="rx-qty-btn rx-qty-minus" aria-label="' . esc_attr__( 'Decrease quantity', 'rx-theme' ) . '">−</button>';
$html .= '<div class="rx-qty-field">' . $product_quantity . '</div>';
$html .= '<button type="button" class="rx-qty-btn rx-qty-plus" aria-label="' . esc_attr__( 'Increase quantity', 'rx-theme' ) . '">+</button>';
if ( $product->managing_stock() && $product->get_stock_quantity() ) {
$html .= '<small class="rx-stock-note">';
$html .= esc_html(
sprintf(
/* translators: %s stock quantity */
__( '%s available', 'rx-theme' ),
wc_format_stock_quantity_for_display( $product->get_stock_quantity(), $product )
)
);
$html .= '</small>';
}
$html .= '</div>';
return $html;
}
/**
* Continue shopping button.
*
* @return void
*/
public function continue_shopping_button() {
$shop_url = wc_get_page_permalink( 'shop' );
if ( ! $shop_url ) {
return;
}
echo '<a class="button rx-continue-shopping" href="' . esc_url( $shop_url ) . '">';
echo esc_html__( 'Continue Shopping', 'rx-theme' );
echo '</a>';
}
/**
* Checkout microcopy before checkout button.
*
* @return void
*/
public function checkout_microcopy() {
echo '<p class="rx-checkout-microcopy">';
echo esc_html__( 'Your final shipping and payment options will be confirmed on the checkout page.', 'rx-theme' );
echo '</p>';
}
/**
* Cart notices.
*
* @return void
*/
public function cart_notices() {
if ( ! $this->is_cart_page() ) {
return;
}
$cart = $this->cart();
if ( ! $cart || $cart->is_empty() ) {
return;
}
/**
* Low stock notice.
*/
foreach ( $cart->get_cart() as $cart_item ) {
if ( empty( $cart_item['data'] ) || ! is_a( $cart_item['data'], 'WC_Product' ) ) {
continue;
}
$product = $cart_item['data'];
if ( ! $product->managing_stock() ) {
continue;
}
$stock_quantity = $product->get_stock_quantity();
if ( null !== $stock_quantity && $stock_quantity > 0 && $stock_quantity <= 3 ) {
wc_add_notice(
sprintf(
/* translators: 1 product name, 2 quantity */
__( 'Only %2$s left for "%1$s". Please checkout soon if you need it.', 'rx-theme' ),
$product->get_name(),
wc_format_stock_quantity_for_display( $stock_quantity, $product )
),
'notice'
);
}
}
/**
* Custom notice through filter.
*/
$custom_notice = apply_filters( 'rx_cart_custom_notice', '' );
if ( ! empty( $custom_notice ) ) {
wc_add_notice( wp_kses_post( $custom_notice ), 'notice' );
}
}
/**
* Cart fragments.
*
* @param array $fragments Fragments.
*
* @return array
*/
public function cart_fragments( $fragments ) {
ob_start();
?>
<span class="rx-cart-count"><?php echo esc_html( $this->get_cart_count() ); ?></span>
<?php
$fragments['span.rx-cart-count'] = ob_get_clean();
ob_start();
?>
<span class="rx-cart-subtotal"><?php echo wp_kses_post( $this->get_cart_subtotal() ); ?></span>
<?php
$fragments['span.rx-cart-subtotal'] = ob_get_clean();
ob_start();
?>
<a class="rx-header-cart-link" href="<?php echo esc_url( wc_get_cart_url() ); ?>" aria-label="<?php esc_attr_e( 'View cart', 'rx-theme' ); ?>">
<span class="rx-header-cart-icon" aria-hidden="true">🛒</span>
<span class="rx-cart-count"><?php echo esc_html( $this->get_cart_count() ); ?></span>
<span class="rx-cart-subtotal"><?php echo wp_kses_post( $this->get_cart_subtotal() ); ?></span>
</a>
<?php
$fragments['a.rx-header-cart-link'] = ob_get_clean();
return $fragments;
}
/**
* Body classes.
*
* @param array $classes Body classes.
*
* @return array
*/
public function body_classes( $classes ) {
if ( $this->is_cart_page() ) {
$classes[] = 'rx-is-cart-page';
$cart = $this->cart();
if ( $cart && $cart->is_empty() ) {
$classes[] = 'rx-cart-is-empty';
} else {
$classes[] = 'rx-cart-has-items';
}
}
return $classes;
}
/**
* Cross-sell columns.
*
* @param int $columns Columns.
*
* @return int
*/
public function cross_sells_columns( $columns ) {
return absint( apply_filters( 'rx_cart_cross_sells_columns', 4 ) );
}
/**
* Cross-sell total.
*
* @param int $total Total.
*
* @return int
*/
public function cross_sells_total( $total ) {
return absint( apply_filters( 'rx_cart_cross_sells_total', 4 ) );
}
/**
* Coupon label.
*
* @param string $label Coupon label.
* @param WC_Coupon $coupon Coupon object.
*
* @return string
*/
public function coupon_label( $label, $coupon ) {
if ( ! is_a( $coupon, 'WC_Coupon' ) ) {
return $label;
}
return sprintf(
'%s: <strong>%s</strong>',
esc_html__( 'Coupon applied', 'rx-theme' ),
esc_html( $coupon->get_code() )
);
}
/**
* Order total HTML.
*
* @param string $html Total HTML.
*
* @return string
*/
public function order_total_html( $html ) {
$html .= '<small class="rx-order-total-note">';
$html .= esc_html__( 'Taxes, shipping, and discounts are calculated according to your store settings.', 'rx-theme' );
$html .= '</small>';
return $html;
}
/**
* Optional cart fees.
*
* Disabled by default.
*
* @param WC_Cart $cart Cart object.
*
* @return void
*/
public function optional_cart_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
if ( ! $cart || $cart->is_empty() ) {
return;
}
/**
* Example 1: Small order handling fee.
* Enable with:
* add_filter( 'rx_cart_enable_small_order_fee', '__return_true' );
*/
$enable_small_order_fee = (bool) apply_filters( 'rx_cart_enable_small_order_fee', false );
$small_order_limit = (float) apply_filters( 'rx_cart_small_order_limit', 20 );
$small_order_fee = (float) apply_filters( 'rx_cart_small_order_fee', 2 );
if ( $enable_small_order_fee && $cart->get_subtotal() > 0 && $cart->get_subtotal() < $small_order_limit ) {
$cart->add_fee(
esc_html__( 'Small Order Handling Fee', 'rx-theme' ),
$small_order_fee,
false
);
}
/**
* Example 2: Large cart discount.
* Enable with:
* add_filter( 'rx_cart_enable_large_cart_discount', '__return_true' );
*/
$enable_large_cart_discount = (bool) apply_filters( 'rx_cart_enable_large_cart_discount', false );
$large_cart_minimum = (float) apply_filters( 'rx_cart_large_cart_minimum', 200 );
$large_cart_discount = (float) apply_filters( 'rx_cart_large_cart_discount', 10 );
if ( $enable_large_cart_discount && $cart->get_subtotal() >= $large_cart_minimum ) {
$cart->add_fee(
esc_html__( 'Large Cart Discount', 'rx-theme' ),
-abs( $large_cart_discount ),
false
);
}
}
/**
* Enqueue cart assets.
*
* @return void
*/
public function enqueue_assets() {
if ( ! $this->is_cart_page() ) {
return;
}
$css = $this->inline_css();
$js = $this->inline_js();
wp_register_style( 'rx-cart-inline-style', false, array(), RX_THEME_VERSION );
wp_enqueue_style( 'rx-cart-inline-style' );
wp_add_inline_style( 'rx-cart-inline-style', $css );
wp_register_script( 'rx-cart-inline-script', false, array( 'jquery' ), RX_THEME_VERSION, true );
wp_enqueue_script( 'rx-cart-inline-script' );
wp_add_inline_script( 'rx-cart-inline-script', $js );
}
/**
* Inline CSS.
*
* You can move this to assets/css/woocommerce-cart.css later.
*
* @return string
*/
private function inline_css() {
return '
.rx-cart-page {
width: 100%;
margin: 0 auto;
}
.rx-cart-container {
max-width: 1200px;
margin: 0 auto;
padding: 24px 16px;
}
.rx-cart-header {
margin-bottom: 24px;
padding: 24px;
border-radius: 18px;
background: #f8fafc;
border: 1px solid #e5e7eb;
}
.rx-cart-title {
margin: 0 0 8px;
font-size: clamp(28px, 4vw, 44px);
line-height: 1.15;
}
.rx-cart-subtitle {
margin: 0;
color: #475569;
font-size: 16px;
}
.rx-cart-login-reminder,
.rx-cart-coupon-tip,
.rx-after-cart-table,
.rx-free-shipping-box,
.rx-secure-checkout-box,
.rx-cart-help,
.rx-empty-cart-extra {
margin: 16px 0;
padding: 16px 18px;
border: 1px solid #e5e7eb;
border-radius: 14px;
background: #ffffff;
}
.rx-cart-login-reminder {
display: flex;
gap: 8px;
align-items: center;
background: #f9fafb;
}
.rx-free-shipping-message {
margin: 0 0 10px;
font-weight: 600;
}
.rx-free-shipping-message.rx-success {
color: #15803d;
}
.rx-free-shipping-progress {
position: relative;
width: 100%;
height: 10px;
overflow: hidden;
border-radius: 999px;
background: #e5e7eb;
}
.rx-free-shipping-progress span {
display: block;
height: 100%;
border-radius: 999px;
background: #22c55e;
transition: width .25s ease;
}
.rx-cart-badge {
display: inline-flex;
align-items: center;
margin: 6px 6px 0 0;
padding: 3px 8px;
border-radius: 999px;
font-size: 12px;
line-height: 1.3;
font-weight: 600;
background: #eef2ff;
color: #3730a3;
}
.rx-cart-badge.rx-sale {
background: #fee2e2;
color: #991b1b;
}
.rx-cart-badge.rx-featured {
background: #fef3c7;
color: #92400e;
}
.rx-cart-badge.rx-backorder {
background: #ffedd5;
color: #9a3412;
}
.rx-cart-badge.rx-out-stock {
background: #f3f4f6;
color: #374151;
}
.rx-cart-quantity-wrap {
display: inline-flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.rx-qty-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border-radius: 8px;
border: 1px solid #d1d5db;
background: #ffffff;
cursor: pointer;
font-size: 18px;
line-height: 1;
}
.rx-qty-btn:hover {
background: #f3f4f6;
}
.rx-qty-field input.qty {
min-width: 64px;
height: 34px;
text-align: center;
}
.rx-stock-note {
flex-basis: 100%;
color: #64748b;
font-size: 12px;
}
.rx-cart-remove {
display: inline-flex !important;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 50%;
text-decoration: none;
}
.rx-continue-shopping {
margin-left: 8px;
}
.rx-checkout-microcopy,
.rx-order-total-note {
display: block;
margin: 8px 0;
color: #64748b;
font-size: 13px;
line-height: 1.5;
}
.rx-secure-checkout-box h3,
.rx-cart-help h2,
.rx-empty-cart-extra h2 {
margin-top: 0;
}
.rx-secure-checkout-box ul {
margin: 0;
padding-left: 20px;
}
.rx-header-cart-link {
display: inline-flex;
align-items: center;
gap: 6px;
text-decoration: none;
}
.rx-cart-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 22px;
height: 22px;
padding: 0 6px;
border-radius: 999px;
background: #111827;
color: #ffffff;
font-size: 12px;
font-weight: 700;
}
.rx-cart-subtotal {
font-weight: 600;
}
.rx-cart-thumbnail-fallback {
display: inline-flex;
align-items: center;
justify-content: center;
width: 56px;
height: 56px;
border-radius: 10px;
background: #f3f4f6;
}
@media (max-width: 768px) {
.rx-cart-container {
padding: 16px 12px;
}
.rx-cart-header {
padding: 18px;
}
.rx-continue-shopping {
display: block;
margin: 10px 0 0;
text-align: center;
}
}
';
}
/**
* Inline JS.
*
* You can move this to assets/js/woocommerce-cart.js later.
*
* @return string
*/
private function inline_js() {
return '
(function($) {
"use strict";
function rxUpdateCartButtonState() {
var $button = $("[name=\'update_cart\']");
if ($button.length) {
$button.prop("disabled", false);
}
}
$(document).on("click", ".rx-qty-plus, .rx-qty-minus", function(e) {
e.preventDefault();
var $button = $(this);
var $wrap = $button.closest(".rx-cart-quantity-wrap");
var $input = $wrap.find("input.qty");
if (!$input.length) {
return;
}
var current = parseFloat($input.val()) || 0;
var max = parseFloat($input.attr("max"));
var min = parseFloat($input.attr("min")) || 0;
var step = parseFloat($input.attr("step")) || 1;
if ($button.hasClass("rx-qty-plus")) {
current = current + step;
if (!isNaN(max) && current > max) {
current = max;
}
} else {
current = current - step;
if (current < min) {
current = min;
}
}
$input.val(current).trigger("change");
rxUpdateCartButtonState();
});
$(document).on("change input", "form.woocommerce-cart-form input.qty", function() {
rxUpdateCartButtonState();
});
$(document.body).on("updated_cart_totals wc_fragments_refreshed", function() {
rxUpdateCartButtonState();
});
})(jQuery);
';
}
/**
* Get cart count safely.
*
* @return int
*/
private function get_cart_count() {
$cart = $this->cart();
if ( ! $cart ) {
return 0;
}
return absint( $cart->get_cart_contents_count() );
}
/**
* Get cart subtotal safely.
*
* @return string
*/
private function get_cart_subtotal() {
$cart = $this->cart();
if ( ! $cart ) {
return wc_price( 0 );
}
return $cart->get_cart_subtotal();
}
/**
* Cart count shortcode.
*
* Usage: [rx_cart_count]
*
* @return string
*/
public function shortcode_cart_count() {
return '<span class="rx-cart-count">' . esc_html( $this->get_cart_count() ) . '</span>';
}
/**
* Cart subtotal shortcode.
*
* Usage: [rx_cart_subtotal]
*
* @return string
*/
public function shortcode_cart_subtotal() {
return '<span class="rx-cart-subtotal">' . wp_kses_post( $this->get_cart_subtotal() ) . '</span>';
}
/**
* Cart link shortcode.
*
* Usage: [rx_cart_link]
*
* @return string
*/
public function shortcode_cart_link() {
return sprintf(
'<a class="rx-header-cart-link" href="%1$s" aria-label="%2$s"><span class="rx-header-cart-icon" aria-hidden="true">🛒</span><span class="rx-cart-count">%3$s</span><span class="rx-cart-subtotal">%4$s</span></a>',
esc_url( wc_get_cart_url() ),
esc_attr__( 'View cart', 'rx-theme' ),
esc_html( $this->get_cart_count() ),
wp_kses_post( $this->get_cart_subtotal() )
);
}
}
endif;
/**
* Initialize RX cart class.
*/
add_action(
'after_setup_theme',
function() {
RX_WooCommerce_Cart::instance();
}
);
/**
* Optional helper:
* Enable free shipping progress amount.
*
* Change 100 to your target amount.
*/
add_filter(
'rx_cart_free_shipping_threshold',
function( $amount ) {
return 100;
}
);
/**
* Optional helper:
* Change cart support/contact URL.
*/
add_filter(
'rx_cart_contact_url',
function( $url ) {
return home_url( '/contact/' );
}
);
/**
* Optional helper:
* Add custom cart notice.
*
* Keep empty if you do not need it.
*/
add_filter(
'rx_cart_custom_notice',
function( $notice ) {
return '';
}
);
/**
* Optional helper:
* Enable small order fee.
*
* By default this returns false.
* Change false to true only if your store policy allows it.
*/
add_filter(
'rx_cart_enable_small_order_fee',
function( $enabled ) {
return false;
}
);
/**
* Optional helper:
* Enable large cart discount.
*
* By default this returns false.
* Change false to true only if you want an automatic discount.
*/
add_filter(
'rx_cart_enable_large_cart_discount',
function( $enabled ) {
return false;
}
);
Important note: this file is for the classic WooCommerce cart shortcode/template system. WooCommerce also has newer Cart and Checkout Blocks, and not every classic hook appears in the same way inside block-based cart pages. WooCommerce has separate documentation for block cart/checkout customization and hook alternatives.