– we control via loop_start // Do not override templates; use hooks for card rendering. add_action('woocommerce_shop_loop', 'xshop_wc_shop_loop_noop', 10); // Sale badge handled inside product-card; single product gallery replaces default add_action('init', 'xshop_wc_remove_default_gallery'); add_action('wp', 'xshop_wc_single_setup'); // Cart: ensure quantity wrappers accessible add_filter('woocommerce_cart_item_quantity', 'xshop_wc_cart_quantity', 10, 3); // Related/upsells: ensure they use product-card grid (filter columns) add_filter('woocommerce_output_related_products_args', 'xshop_wc_related_args'); add_filter('woocommerce_upsells_total', '__return_false'); // keep? actually we keep upsells - no filter, just ensure columns via CSS grid } function xshop_wc_remove_default_gallery(): void { // Replace Woo's product images with XShop gallery component remove_action('woocommerce_before_single_product_summary', 'woocommerce_show_product_sale_flash', 10); remove_action('woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20); // Re-add sale flash inside summary? Keep flash via CSS badge in product-card only; single product shows price sale via Woo price hook } function xshop_wc_related_args(array $args): array { $args['posts_per_page'] = 4; $args['columns'] = 4; return $args; } function xshop_woo_wrapper_start(): void { // Breadcrumbs are rendered by header.php for most pages; for Woo we keep Woo breadcrumb but styled as xshop-breadcrumbs echo '
'; } function xshop_woo_wrapper_end(): void { echo '
'; } function xshop_wc_loop_start(string $html): string { // Replace Woo default