Files
wc-bootstrap/templates/single-product/product-image.html.twig
magdev 784b400c46
All checks were successful
Create Release Package / PHP Lint (push) Successful in 44s
Create Release Package / Build Release (push) Successful in 52s
Fix 10 known bugs: catalog, single product, and account pages (v0.1.5)
Catalog: page title via woocommerce_page_title(), breadcrumbs, category
template rename (underscore), 3-column grid, single chevron on sort.

Single product: variable form data attributes + disabled CSS class fix
(WC JS only toggles CSS classes, not HTML disabled attribute), dark mode
select specificity (0,5,1) to beat WC's (0,4,3) background shorthand,
gallery main image in thumbnail strip with empty URL guard, related/
upsells setup_postdata for correct global $product, grouped product
loop logic rewrite.

Account: downloads via wc_get_customer_available_downloads().

New: product-gallery.js, sanitize_title filter, wc_setup_product_data()
and wp_reset_postdata() Twig functions, product-thumbnails.html.twig
suppressor. Removed obsolete PLAN.md and SETUP.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:33:31 +01:00

72 lines
3.3 KiB
Twig

{#
# Product Image Gallery (Bootstrap 5 Override)
#
# Renders the product image gallery with main image and thumbnail strip.
#
# Expected context:
# product - WC_Product object
# post_thumbnail_id - Main image attachment ID
# columns - Number of thumbnail columns
# gallery_image_ids - Array of gallery attachment IDs
# main_image_html - Pre-rendered main image HTML
#
# WooCommerce PHP equivalent: single-product/product-image.php
#
# @package WcBootstrap
# @since 0.1.0
#}
{# Compute image data from the product object (PHP template does this locally). #}
{% set post_thumbnail_id = product.get_image_id() %}
{% set gallery_image_ids = product.get_gallery_image_ids() %}
{% set cols = apply_filters('woocommerce_product_thumbnails_columns', 4) %}
{% set has_images = post_thumbnail_id %}
{% set gallery_classes = 'woocommerce-product-gallery woocommerce-product-gallery--columns-' ~ cols %}
{% if has_images %}
{% set gallery_classes = gallery_classes ~ ' woocommerce-product-gallery--with-images' %}
{% else %}
{% set gallery_classes = gallery_classes ~ ' woocommerce-product-gallery--without-images' %}
{% endif %}
<div class="{{ gallery_classes }}" data-columns="{{ cols }}" style="opacity: 0; transition: opacity .25s ease-in-out;">
<div class="woocommerce-product-gallery__wrapper">
{# Main product image #}
{% if post_thumbnail_id %}
<div class="woocommerce-product-gallery__image mb-3">
<img src="{{ wp_get_attachment_url(post_thumbnail_id)|esc_url }}"
class="img-fluid rounded wp-post-image"
alt="{{ product.get_name()|esc_attr }}" />
</div>
{% else %}
<div class="woocommerce-product-gallery__image woocommerce-product-gallery__image--placeholder mb-3">
<img src="{{ wc_placeholder_img_src()|esc_url }}"
class="img-fluid rounded wp-post-image"
alt="{{ __('Awaiting product image')|esc_attr }}" />
</div>
{% endif %}
{# Thumbnail gallery strip — includes main image so user can switch back.
Build a combined list: main image first, then gallery images.
Skip any IDs that don't resolve to a valid attachment URL. #}
{% if gallery_image_ids|length > 0 and post_thumbnail_id %}
{% set all_thumb_ids = [post_thumbnail_id]|merge(gallery_image_ids) %}
<div class="row row-cols-{{ cols }} g-2 mt-2">
{% for image_id in all_thumb_ids %}
{% set thumb_url = wp_get_attachment_url(image_id) %}
{% if thumb_url %}
<div class="col">
<img src="{{ thumb_url|esc_url }}"
class="img-fluid rounded border wc-gallery-thumb{% if loop.first %} border-primary active{% endif %}"
alt="{{ product.get_name()|esc_attr }}"
data-full-src="{{ thumb_url|esc_url }}"
style="{% if loop.first %}opacity: 1{% else %}opacity: 0.6{% endif %}" />
</div>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{{ do_action('woocommerce_product_thumbnails') }}
</div>