Woocommerce support
Chisel provides first‑class WooCommerce integration via custom Twig templates, helper utilities, and selective hook overrides.
Overview
- Theme support:
woocommerce, product gallery zoom/lightbox/slider enabled. Source:core/WP/Woocommerce.php::add_woocommerce_support() - Custom templates:
- Archive:
views/woocommerce/archive-product.twig - Single:
views/woocommerce/single-product.twig - Loop item:
views/woocommerce/content-product.twig - Category item:
views/woocommerce/content-product-cat.twig - Linked products (upsells/related):
views/woocommerce/linked-products.twig - Entry point:
woocommerce.php
- Archive:
- Twig hooks preserved: Templates call Woo hooks (e.g.,
woocommerce_before_main_content,woocommerce_single_product_summary) viado_action(...), but the theme removes some default outputs to replace layout/markup. - Sidebar: Dedicated “WooCommerce” sidebar registered via filter. Source:
core/WP/Woocommerce.php::register_sidebars()
Hook customizations
- Removed default actions (theme reimplements layout/markup):
- Wrapper and breadcrumb around main content. Removed:
woocommerce_output_content_wrapper,woocommerce_output_content_wrapper_end,woocommerce_breadcrumb - Loop product/category link wrappers and default thumbnails. Removed:
woocommerce_template_loop_product_link_open/close,woocommerce_subcategory_thumbnail,woocommerce_template_loop_product_thumbnail - Archive pagination (theme may use its Load More). Removed:
woocommerce_pagination - Single product upsells/related default placement (theme renders via Twig). Removed:
woocommerce_upsell_display,woocommerce_output_related_products. Source:core/WP/Woocommerce.php::remove_actions()
- Wrapper and breadcrumb around main content. Removed:
- Sort bar container: Injected before/after shop loop to wrap count/order controls. Source:
core/WP/Woocommerce.php::before_shop_loop_div_open()/before_shop_loop_div_close(). Triggered by Woo hook:woocommerce_before_shop_loop - Customizer: Removes “both” display choice for shop/category archives. Source:
core/WP/Woocommerce.php::modify_customizer()
Assets
- Removes Woo’s
woocommerce-layoutstylesheet to avoid conflicts. Filter:woocommerce_enqueue_stylesincore/WP/Woocommerce.php::enqueue_styles() - Registers theme style handle
woocommerceviachisel_frontend_styles. Source:core/WP/Woocommerce.php::register_custom_styles()
Custom Timber classes
Chisel provides extended Timber classes specifically for WooCommerce products and product categories, offering enhanced thumbnail handling with automatic placeholder fallback support.
ChiselProduct
Located in core/Timber/ChiselProduct.php, this class extends Timber\Post and provides WooCommerce-specific functionality for products.
Properties:
$thumbnail_html(string|null) – Cached product thumbnail HTML$thumbnail_id(int|null) – Cached thumbnail attachment ID
Methods:
get_thumbnail( string $size = 'woocommerce_thumbnail', array $attrs = array() ): string
Returns the product thumbnail as responsive image HTML. Applies the single_product_archive_thumbnail_size filter to allow customization of the thumbnail size. If no thumbnail is set, automatically falls back to the WooCommerce placeholder image configured in WooCommerce → Settings → Products → Placeholder image.
Parameters:
$size– Thumbnail size (default:'woocommerce_thumbnail')$attrs– Image attributes array passed toImageHelpers::get_responsive_image()
Returns: Responsive <img> HTML, or empty string if no thumbnail or placeholder exists
get_thumbnail_id(): int
Returns the product thumbnail attachment ID. Falls back to the WooCommerce placeholder image option (woocommerce_placeholder_image) if no product thumbnail is set.
Returns: Thumbnail attachment ID (int)
Usage in templates:
{% for product in products %}
<div class="c-product">
{{ product.get_thumbnail('woocommerce_thumbnail') }}
<h3>{{ product.title }}</h3>
<span class="c-product__price">{{ product.price }}</span>
</div>
{% endfor %}TwigChiselProductCategory
Located in core/Timber/ChiselProductCategory.php, this class extends Timber\Term for WooCommerce product category taxonomy.
Properties:
$thumbnail_html(string|null) – Cached category thumbnail HTML$thumbnail_id(int|null) – Cached thumbnail attachment ID
Methods:
get_thumbnail( string $size = 'woocommerce_thumbnail', array $attrs = array() ): string
Returns the category thumbnail as responsive image HTML. Applies the subcategory_archive_thumbnail_size filter. Falls back to WooCommerce placeholder image if no category thumbnail is set.
Parameters:
$size– Thumbnail size (default:'woocommerce_thumbnail')$attrs– Image attributes array
Returns: Responsive <img> HTML, or empty string
get_thumbnail_id(): int
Returns the category thumbnail attachment ID from term meta (thumbnail_id). Falls back to the WooCommerce placeholder image option if no category thumbnail is set.
Returns: Thumbnail attachment ID (int)
Usage in templates:
{% for category in categories %}
<div class="c-category">
{{ category.get_thumbnail('woocommerce_thumbnail') }}
<h3>{{ category.name }}</h3>
</div>
{% endfor %}TwigHelpers
WoocommerceHelpers (core/Helpers/WoocommerceHelpers.php)
is_woocommerce_active()
is_woocommerce_active(): bool
Checks if the WooCommerce plugin is active. Use this to guard WooCommerce-specific code paths.
Returns: true if WooCommerce class exists, false otherwise
Usage:
<?php
use Chisel\Helpers\WoocommerceHelpers;
if ( WoocommerceHelpers::is_woocommerce_active() ) {
// WooCommerce-specific code
}PHPtimber_set_product()
timber_set_product( object $post ): void
Sets the global $product object for WooCommerce products. This is essential for product loops where WooCommerce templates and functions expect the global $product to be correctly set. The method checks if the post type is 'product' and uses wc_get_product() to set the global product object.
Parameters:
$post– Timber Post object
Usage:
<?php
use Chisel\Helpers\WoocommerceHelpers;
foreach ( $posts as $post ) {
if ( $post->post_type === 'product' ) {
WoocommerceHelpers::timber_set_product( $post );
}
}PHPExposed to Twig as: timber_set_product(post)
This method is automatically used internally by Chisel when rendering product templates, ensuring that $product is always available in the correct context.
get_products_grid_classnames()
get_products_grid_classnames( bool $products, bool $has_sidebar ): string
Generates responsive grid CSS classnames for WooCommerce product layouts based on the number of columns configured in WooCommerce settings. Returns ITCSS object-layer grid classes (o-grid) with responsive modifiers.
Parameters:
$products– Whether there are products to render$has_sidebar– Whether the layout includes a sidebar
Returns: String of CSS classnames for the grid container
Behavior:
- Reads the WooCommerce loop columns setting via
wc_get_loop_prop('columns') - Limits maximum columns to 4 for optimal layout
- Generates responsive grid classes:
- Base:
o-grid o-grid--cols-1(mobile/default) - Small breakpoint:
o-grid--cols-{n}-smallwhere n is columns or columns-1 - Medium breakpoint: Adjusts based on sidebar presence (uses
smallcolumn count if sidebar exists, otherwise uses full column count)
- Base:
Example output:
- Without sidebar, 3 columns:
o-grid o-grid--cols-1 o-grid--cols-2-small o-grid--cols-3-medium - With sidebar, 3 columns:
o-grid o-grid--cols-1 o-grid--cols-2-small o-grid--cols-2-medium
Usage in Twig:
<div class="{{ fn('Chisel\\Helpers\\WoocommerceHelpers::get_products_grid_classnames', products|length > 0, has_sidebar) }}">
{% for product in products %}
<div class="o-grid__item">
{% include 'components/product-card.twig' with { product: product } %}
</div>
{% endfor %}
</div>TwigExample usage in PHP (archive context):
woocommerce.php computes and passes:
items(posts or terms),categories,show_productsloop_columns_classviaWoocommerceHelpers::get_products_grid_classnames($products, $has_sidebar)load_moreconfig for AJAX pagination:{ per_page, post_type: 'product' }
Templates: data flow and extension
Archive
views/woocommerce/archive-product.twig
- Uses Woo hooks (
woocommerce_before_main_content,woocommerce_before_shop_loop, etc.) - Renders either
content-product.twigorcontent-product-cat.twigbased onshow_products - Appends Load More control when products present:
- Includes
components/pagination.twigwith{ type: 'load-more' } - Front‑end JS module
src/scripts/modules/load-more.jsuses REST endpointload-more
- Includes
- Grid classes injected via
loop_columns_class
Single
views/woocommerce/single-product.twig
- Uses standard Woo hooks for gallery/summary/tabs
- Theme renders custom linked products sections via
linked-products.twigusing:- Context vars from
woocommerce.php:upsells_products,related_products
- Context vars from
post_classes(post.class)andwrapper_classused for consistent BEM classes
Entry logic
woocommerce.php
Single product:
- Sets
post,product - Controls upsells/related via filters:
chisel_woocommerce_upsell_display(bool)chisel_woocommerce_output_related_products(bool)
- Computes
grid_classnamesand renderssingle-product.twig
Archive:
- Honors Woo “display type” (products vs subcategories)
- Builds
items(posts or terms),categories,show_products - Computes
loop_columns_class, andload_moreper page viawc_get_loop_prop('columns') * wc_get_default_product_rows_per_page() - Renders
archive-product.twig
Theme filters for Woo behavior
Toggle upsells/related on single (in woocommerce.php):
chisel_woocommerce_upsell_display→ defaulttruechisel_woocommerce_output_related_products→ defaulttrue
Example:
<?php
add_filter( 'chisel_woocommerce_output_related_products', '__return_false' );
add_filter( 'chisel_woocommerce_upsell_display', '__return_false' );PHPAJAX “Load more” for products
Archive integrates with the theme’s REST AJAX pattern:
- Client:
src/scripts/modules/load-more.jscallsUtils.ajaxRequest('load-more', { post_type: 'product', ... }) - Server:
core/WP/Ajax/LoadMoreEndpoints.php::load_more()prepends Woo templateviews/woocommerce/content-product.twigforpost_type === 'product'
Sidebars
- Add a “WooCommerce” sidebar via filter
chisel_sidebars(merged in inc/Plugin/Woocommerce.php).Twig includessidebar-woocommerce.twigorsidebar-woocommerce-product.twigwhensidebaris present in the context.
How to extend
- Override markup: Copy any
views/woocommerce/*.twigfile into a child theme with the same path/name to customize. - Grid/tile layout: Adjust columns via Woo settings; helper caps at 4 columns. For custom breakpoints, adapt WoocommerceHelpers::get_products_grid_classnames().
- Disable/enable pieces via filters listed above.
- Register extra CSS/JS for shop pages via asset filters.