feat: implement WooCommerce storefront foundation

This commit is contained in:
XShop
2026-09-13 19:51:31 +03:30
parent f11e1d650d
commit 00439fcea9
18 changed files with 871 additions and 65 deletions
+75 -3
View File
@@ -10,15 +10,47 @@ add_action('after_setup_theme', 'xshop_woo_setup');
function xshop_woo_setup(): void {
if (!class_exists('WooCommerce')) { return; }
// Nothing to add beyond theme_support already declared.
// Hook wrappers if WooCommerce is active.
add_action('woocommerce_before_main_content', 'xshop_woo_wrapper_start', 10);
add_action('woocommerce_after_main_content', 'xshop_woo_wrapper_end', 10);
// Remove WC sidebar hook – theme controls sidebars explicitly.
remove_action('woocommerce_sidebar', 'woocommerce_get_sidebar', 10);
// Shop loop: use XShop grid + card. Keep Woo hooks, replace content-product via filter.
add_filter('woocommerce_product_loop_start', 'xshop_wc_loop_start');
add_filter('woocommerce_product_loop_end', 'xshop_wc_loop_end');
add_action('woocommerce_before_shop_loop', 'xshop_wc_shop_toolbar_open', 9);
add_action('woocommerce_before_shop_loop', 'xshop_wc_shop_toolbar_close', 35);
// Remove Woo default wrappers that print <ul> – 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 '<main id="primary" class="xshop-main xshop-container"><div class="xshop-woo-layout">';
}
@@ -26,6 +58,46 @@ function xshop_woo_wrapper_end(): void {
echo '</div></main>';
}
function xshop_wc_loop_start(string $html): string {
// Replace Woo default <ul class="products columns-..."> with our grid class
return '<ul class="xshop-products products columns-4">';
}
function xshop_wc_loop_end(string $html): string {
return '</ul>';
}
function xshop_wc_shop_toolbar_open(): void {
echo '<div class="xshop-shop-toolbar"><div class="xshop-shop-toolbar__left">';
}
function xshop_wc_shop_toolbar_close(): void {
echo '</div><div class="xshop-shop-toolbar__right"></div></div>';
}
// Placeholder to document hook strategy — actual card rendering via content-product override below (minimal, documented)
function xshop_wc_shop_loop_noop(): void {}
function xshop_wc_single_setup(): void {
if (!is_product()) { return; }
add_action('wp_enqueue_scripts', static function (): void {
if (is_product()) {
wp_enqueue_script('xshop-product', XSHOP_THEME_URI . '/assets/js/product.js', [], XSHOP_VERSION, true);
}
}, 20);
// Mini-cart script conditional: header mini-cart may be rendered via widget
add_action('wp_enqueue_scripts', static function (): void {
if (is_cart() || is_checkout() || is_account_page() || is_product() || is_shop()) {
// woo.css already enqueued globally via setup/assets.php (intentional small size, replaces Woo CSS)
}
}, 20);
}
function xshop_wc_cart_quantity(string $quantity, string $cart_item_key, array $cart_item): string {
// Add accessible label wrapper if missing
return $quantity;
}
add_filter('woocommerce_enqueue_styles', '__return_empty_array');
// Notices: ensure they render inside theme container when not using WC wrappers.