cart.php

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">&times;<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.

Leave a Reply

Your email address will not be published. Required fields are marked *