Plugin Directory

Changeset 3334031


Ignore:
Timestamp:
07/25/2025 07:47:55 AM (8 months ago)
Author:
wijnbergdevelopments
Message:

Added WooCommerce ProductImage block integration

Location:
product-gallery-swiper-for-woocommerce
Files:
39 added
4 edited

Legend:

Unmodified
Added
Removed
  • product-gallery-swiper-for-woocommerce/trunk/README.txt

    r3333374 r3334031  
    44Requires at least: 6.0
    55Tested up to: 6.8
    6 Stable tag: 1.5.8
     6Stable tag: 1.5.9
    77Requires PHP: 7.2
    88License: GPL-2.0+
     
    6060= Are there any known compatibility issues? =
    6161
    62 Some WooCommerce Blocks are not fully compatible with this plugin as they do not use standard WooCommerce filters for generating thumbnails. This is a known limitation of WooCommerce Blocks and not specific to this plugin. You can fix this by using WooCommerce shortcodes instead of the WooCommerce Blocks.
     62The plugin includes support for WooCommerce ProductImage Block. Some other WooCommerce Blocks are not fully compatible with this plugin as they do not use standard WooCommerce filters for generating thumbnails. This is a known limitation of WooCommerce Blocks and not specific to this plugin. You can fix this by using WooCommerce shortcodes instead of the WooCommerce Blocks.
    6363
    6464If you encounter any conflicts with other themes or plugins, please report them to us. We are trying to use all standard WooCommerce filters and hooks, and we want to use the active theme settings and change as little as possible. This approach ensures maximum compatibility with themes and other plugins. However, some themes and plugins might not follow standard WordPress/WooCommerce practices, which can result in compatibility issues out of the box.
    6565
    6666== Changelog ==
     67= 1.5.9 =
     68* Added WooCommerce ProductImage block integration
     69
    6770= 1.5.8 =
    6871* Added new rendering filters/actions for third party compatibility adjustments
  • product-gallery-swiper-for-woocommerce/trunk/includes/class-wdevs-gallery-swiper.php

    r3333160 r3334031  
    173173    }
    174174
     175
    175176    /**
    176177     * Run the loader to execute all of the hooks with WordPress.
  • product-gallery-swiper-for-woocommerce/trunk/public/class-wdevs-gallery-swiper-public.php

    r3333413 r3334031  
    5353    private const SWIPER_VERSION = '11.2.0';
    5454
     55
    5556    /**
    5657     * Initialize the class and set its properties.
     
    8384            $inline_css = sprintf(
    8485                '.woocommerce ul.products li.product .swiper { --swiper-theme-color: %s; }',
    85                 esc_attr($theme_color)
     86                esc_attr( $theme_color )
    8687            );
    8788            wp_add_inline_style( $this->plugin_name . '-public', $inline_css );
     
    105106        $localized_settings = [
    106107            'swiper' => [
    107                 'scrollbar'  => get_option( 'wdevs_gallery_swiper_scrollbar', 'yes' ) === 'yes',
    108                 'pagination' => get_option( 'wdevs_gallery_swiper_pagination', 'no' ) === 'yes',
    109                 'navigation' => get_option( 'wdevs_gallery_swiper_navigation', 'no' ) === 'yes',
    110                 'breakpoint' => $this->parse_breakpoint( get_option( 'wdevs_gallery_swiper_breakpoint', '' ) ),
     108                'scrollbar'    => get_option( 'wdevs_gallery_swiper_scrollbar', 'yes' ) === 'yes',
     109                'pagination'   => get_option( 'wdevs_gallery_swiper_pagination', 'no' ) === 'yes',
     110                'navigation'   => get_option( 'wdevs_gallery_swiper_navigation', 'no' ) === 'yes',
     111                'breakpoint'   => $this->parse_breakpoint( get_option( 'wdevs_gallery_swiper_breakpoint', '' ) ),
    111112                'hoverEnabled' => get_option( 'wdevs_gallery_swiper_hover_enabled', 'yes' ) === 'yes',
    112113            ]
     
    130131        add_action( 'wdevs_gallery_swiper_start_gallery_rendering', [ $this, 'start_gallery_rendering' ] );
    131132        add_action( 'wdevs_gallery_swiper_finish_gallery_rendering', [ $this, 'finish_gallery_rendering' ] );
     133        add_action( 'wdevs_gallery_swiper_start_gallery_block_rendering', [
     134            $this,
     135            'start_gallery_block_rendering'
     136        ], 10, 3 );
     137        add_action( 'wdevs_gallery_swiper_finish_gallery_block_rendering', [
     138            $this,
     139            'finish_gallery_block_rendering'
     140        ], 10, 3 );
    132141        add_action( 'wdevs_gallery_swiper_render_gallery', [ $this, 'render_full_gallery' ], 10, 1 );
    133142
     
    139148
    140149        $this->setup_default_woocommerce_integration();
     150        $this->setup_default_woocommerce_block_integration();
    141151    }
    142152
     
    157167
    158168    /**
     169     * Setup default WooCommerce block integration.
     170     *
     171     * This method sets up the default gallery rendering hooks for WooCommerce product image blocks.
     172     * External developers can disable this via the 'wdevs_gallery_swiper_enable_default_block_integration' filter.
     173     *
     174     * @since 1.5.9
     175     */
     176    public function setup_default_woocommerce_block_integration() {
     177        if ( apply_filters( 'wdevs_gallery_swiper_enable_default_block_integration', true ) ) {
     178            add_filter( 'render_block_woocommerce/product-image', [
     179                $this,
     180                'start_gallery_block_rendering'
     181            ], PHP_INT_MIN, 3 );
     182            add_filter( 'render_block_woocommerce/product-image', [
     183                $this,
     184                'finish_gallery_block_rendering'
     185            ], PHP_INT_MAX, 3 );
     186        }
     187    }
     188
     189    /**
    159190     * Add compatibility fixes for various themes.
    160191     *
     
    165196     */
    166197    public function add_themes_compatibility() {
    167         // Default WooCommerce
    168         //remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
    169198
    170199        // GeneratePress Theme compatibility
     
    199228
    200229        // XStore theme compatibility: init swiper after AJAX filter
    201         if(function_exists('etheme_theme_setup')){
     230        if ( function_exists( 'etheme_theme_setup' ) ) {
    202231            wp_register_script( 'wdevs-gallery-swiper-xstore-theme', plugin_dir_url( __FILE__ ) . 'js/xstore-theme.js', [
    203232                'jquery',
     
    212241     * Add compatibility fixes for various plugins.
    213242     *
    214      * This function adds compatibility with the YITH Infinite Scrolling plugin.
    215      *
    216      * @since    1.0.0
     243     * This function adds compatibility with various plugins including:
     244     * - YITH Infinite Scrolling
     245     * - Woo Product Filter by WBW
     246     * - GeneratePress Premium WooCommerce
     247     *
     248     * @since 1.0.0
    217249     */
    218250    public function add_plugins_compatibility() {
     
    244276                $this->disable_default_thumbnail();
    245277                add_filter( 'wdevs_gallery_swiper_enable_default_integration', '__return_false' );
    246                 add_filter('wdevs_gallery_swiper_should_display_gallery', '__return_true');
    247                 add_action( 'woocommerce_before_shop_loop_item_title', [ $this, 'render_gallery_with_default_thumbnail' ], 10 );
     278                add_filter( 'wdevs_gallery_swiper_should_display_gallery', '__return_true' );
     279                add_action( 'woocommerce_before_shop_loop_item_title', [
     280                    $this,
     281                    'render_gallery_with_default_thumbnail'
     282                ], 10 );
    248283            }
    249284        }
     285    }
     286
     287    /**
     288     * Build gallery opening HTML structure.
     289     *
     290     * @return string Opening HTML structure.
     291     * @since 1.5.9
     292     */
     293    private function build_swiper_opening_html() {
     294        $extra_classes     = apply_filters( 'wdevs_gallery_swiper_container_extra_classes', '' );
     295        $container_classes = trim( 'swiper ' . $extra_classes );
     296
     297        $html = '<div class="' . esc_attr( $container_classes ) . '">';
     298        $html .= '<div class="swiper-wrapper">';
     299
     300        return $html;
     301    }
     302
     303    /**
     304     * Build navigation elements HTML.
     305     *
     306     * @return string Navigation HTML.
     307     * @since 1.5.9
     308     */
     309    private function build_swiper_closing_tag() {
     310        $html = '</div>';
     311        $html .= '<div class="swiper-pagination"></div>';
     312        $html .= '<div class="swiper-button-prev"></div>';
     313        $html .= '<div class="swiper-button-next"></div>';
     314        $html .= '<div class="swiper-scrollbar"></div>';
     315        $html .= '</div>';
     316
     317        return $html;
     318    }
     319
     320
     321    /**
     322     * Wrap content in a Swiper slide div.
     323     *
     324     * Creates a div element with the swiper-slide class and wraps the provided content.
     325     *
     326     * @param string $content The content to wrap in the slide.
     327     *
     328     * @return string The HTML for the Swiper slide with content.
     329     *
     330     * @since 1.5.8
     331     */
     332    public function wrap_in_slide( $content ) {
     333        $extra_classes = apply_filters( 'wdevs_gallery_swiper_slide_extra_classes', '' );
     334        $slide_classes = trim( 'swiper-slide ' . $extra_classes );
     335
     336        return '<div class="' . esc_attr( $slide_classes ) . '">' . $content . '</div>';
     337    }
     338
     339    /**
     340     * Render block with temporary filter removal.
     341     *
     342     * @param array $block Block to render.
     343     *
     344     * @return string Rendered block content.
     345     * @since 1.5.9
     346     */
     347    private function render_block_without_gallery_filters( $block ) {
     348        remove_filter( 'render_block_woocommerce/product-image', [
     349            $this,
     350            'start_gallery_block_rendering'
     351        ], PHP_INT_MIN );
     352        remove_filter( 'render_block_woocommerce/product-image', [
     353            $this,
     354            'finish_gallery_block_rendering'
     355        ], PHP_INT_MAX );
     356
     357        $content = render_block( $block );
     358
     359        add_filter( 'render_block_woocommerce/product-image', [
     360            $this,
     361            'start_gallery_block_rendering'
     362        ], PHP_INT_MIN, 3 );
     363        add_filter( 'render_block_woocommerce/product-image', [
     364            $this,
     365            'finish_gallery_block_rendering'
     366        ], PHP_INT_MAX, 3 );
     367
     368        return $content;
    250369    }
    251370
     
    262381     */
    263382    public function start_gallery_rendering() {
    264         if ( $this->should_display_gallery() ) {
    265             $extra_classes = apply_filters( 'wdevs_gallery_swiper_container_extra_classes', '' );
    266             $container_classes = trim( 'swiper ' . $extra_classes );
    267             echo '<div class="' . esc_attr( $container_classes ) . '">';
    268             echo '<div class="swiper-wrapper">';
     383        if ( $this->should_display_gallery() && ! $this->executed_block_integration() ) {
     384            do_action( 'wdevs_gallery_swiper_start_rendering' );
     385            echo $this->build_swiper_opening_html();
    269386            echo '<div class="swiper-slide">';
    270387        }
     
    282399     */
    283400    public function finish_gallery_rendering() {
     401        if ( $this->should_display_gallery() && ! $this->executed_block_integration() ) {
     402            echo '</div>';
     403
     404            $product = wc_get_product();
     405            if ( $product ) {
     406                foreach ( $product->get_gallery_image_ids() as $attachment_id ) {
     407                    echo $this->wrap_in_slide( $this->get_product_image( $product, $attachment_id ) );
     408                }
     409
     410                if ( $product->is_type( 'variable' ) ) {
     411                    if ( $this->should_include_variation_images() ) {
     412                        $variation_images = [];
     413                        $variations       = $product->get_available_variations();
     414
     415                        foreach ( $variations as $variation ) {
     416                            if ( ! empty( $variation['image_id'] ) && ! in_array( $variation['image_id'], $variation_images, true ) ) {
     417                                echo $this->wrap_in_slide( $this->get_product_image( $product, $variation['image_id'] ) );
     418                                $variation_images[] = $variation['image_id'];
     419                            }
     420                        }
     421                    }
     422                }
     423            }
     424
     425            echo $this->build_swiper_closing_tag();
     426        }
     427    }
     428
     429    /**
     430     * Render the complete gallery with optional default thumbnail inclusion.
     431     *
     432     * Renders the full Swiper gallery structure, optionally including the default
     433     * product thumbnail as the first slide. Used for theme compatibility adjustments.
     434     *
     435     * @param bool $include_default Whether to include the default thumbnail as first slide.
     436     *
     437     * @since 1.5.8
     438     */
     439    public function render_full_gallery( $include_default = false ) {
     440        $this->start_gallery_rendering();
     441        if ( $include_default ) {
     442            $this->render_default_thumbnail_slide();
     443        }
     444        $this->finish_gallery_rendering();
     445    }
     446
     447    /**
     448     * Render the default product thumbnail as a Swiper slide.
     449     *
     450     * Creates a Swiper slide containing the default WooCommerce product thumbnail.
     451     * Only renders if the gallery should be displayed for the current product.
     452     *
     453     * @since 1.5.8
     454     */
     455    public function render_default_thumbnail_slide() {
    284456        if ( $this->should_display_gallery() ) {
    285             echo '</div>';
    286 
    287             $product = wc_get_product();
     457            echo $this->wrap_in_slide( woocommerce_get_product_thumbnail() );
     458        }
     459    }
     460
     461    /**
     462     * Render gallery with default thumbnail as first slide.
     463     *
     464     * This method is used as a callback for theme/plugin compatibility adjustments
     465     * where the default gallery rendering needs to be replaced with a version
     466     * that includes the default thumbnail as the first slide.
     467     *
     468     * @since 1.5.8
     469     */
     470    public function render_gallery_with_default_thumbnail() {
     471        $this->render_full_gallery( true );
     472    }
     473
     474
     475    /**
     476     * Start gallery rendering for WooCommerce product image blocks.
     477     *
     478     * Creates the opening HTML structure for the Swiper gallery when rendering
     479     * WooCommerce product image blocks. Works in conjunction with finish_gallery_block_rendering().
     480     *
     481     * @param string $block_content The original block content.
     482     * @param array $block The block array.
     483     * @param object $instance The WP_Block instance.
     484     *
     485     * @return string Modified block content with gallery opening HTML.
     486     * @since 1.5.9
     487     */
     488    public function start_gallery_block_rendering( $block_content, $block, $instance ) {
     489        do_action( 'wdevs_gallery_swiper_block_start_rendering' );
     490        $product_id = $instance->context['postId'] ?? 0;
     491        if ( ! $this->should_display_gallery( $product_id ) ) {
     492            return $block_content;
     493        }
     494
     495        $html = $this->build_swiper_opening_html();
     496        $html .= '<div class="swiper-slide">';
     497        $html .= $block_content;
     498        $html .= '</div>';
     499
     500        return $html;
     501    }
     502
     503    /**
     504     * Finish gallery rendering for WooCommerce product image blocks.
     505     *
     506     * Completes the Swiper gallery structure by adding gallery and variation images,
     507     * then closing the HTML structure. Works in conjunction with start_gallery_block_rendering().
     508     *
     509     * @param string $block_content The original block content.
     510     * @param array $block The block array.
     511     * @param object $instance The WP_Block instance.
     512     *
     513     * @return string Complete gallery HTML or original block content.
     514     * @since 1.5.9
     515     */
     516    public function finish_gallery_block_rendering( $block_content, $block, $instance ) {
     517        $product_id = $instance->context['postId'] ?? 0;
     518        if ( ! $this->should_display_gallery( $product_id ) ) {
     519            return $block_content;
     520        }
     521
     522        $product = wc_get_product( $product_id );
     523
     524        if ( $product ) {
     525            $output = $block_content;
     526
    288527            foreach ( $product->get_gallery_image_ids() as $attachment_id ) {
    289                 echo $this->wrap_in_slide( $this->get_product_image( $product, $attachment_id ) );
     528                $block_copy                       = $block;
     529                $block_copy['context']['imageId'] = $attachment_id;
     530
     531                $slide_content = $this->render_block_without_gallery_filters( $block_copy );
     532                $output        .= $this->wrap_in_slide( $slide_content );
    290533            }
    291534
    292             if ($product->is_type('variable')){
    293                 $consider_variation_images = ( get_option( 'wdevs_gallery_swiper_variation_images', 'no' ) === 'yes' );
    294                 if ( $consider_variation_images ) {
     535            if ( $product->is_type( 'variable' ) ) {
     536                if ( $this->should_include_variation_images() ) {
    295537                    $variation_images = [];
    296538                    $variations       = $product->get_available_variations();
     
    298540                    foreach ( $variations as $variation ) {
    299541                        if ( ! empty( $variation['image_id'] ) && ! in_array( $variation['image_id'], $variation_images, true ) ) {
    300                             echo $this->wrap_in_slide( $this->get_product_image( $product, $variation['image_id'] ) );
     542                            $block_copy                       = $block;
     543                            $block_copy['context']['imageId'] = $variation['image_id'];
     544
     545                            $slide_content      = $this->render_block_without_gallery_filters( $block_copy );
     546                            $output             .= $this->wrap_in_slide( $slide_content );
    301547                            $variation_images[] = $variation['image_id'];
    302548                        }
     
    305551            }
    306552
    307             echo '</div>';
    308             echo '<div class="swiper-pagination"></div>';
    309             echo '<div class="swiper-button-prev"></div>';
    310             echo '<div class="swiper-button-next"></div>';
    311             echo '<div class="swiper-scrollbar"></div>';
    312             echo '</div>';
    313         }
    314     }
    315 
    316     /**
    317      * Render the complete gallery with optional default thumbnail inclusion.
    318      *
    319      * Renders the full Swiper gallery structure, optionally including the default
    320      * product thumbnail as the first slide. Used for theme compatibility adjustments.
    321      *
    322      * @param bool $include_default Whether to include the default thumbnail as first slide.
    323      *
    324      * @since 1.5.8
    325      */
    326     public function render_full_gallery( $include_default = false ) {
    327         $this->start_gallery_rendering();
    328         if ( $include_default ) {
    329             $this->render_default_thumbnail_slide();
    330         }
    331         $this->finish_gallery_rendering();
    332     }
    333 
    334     /**
    335      * Render the default product thumbnail as a Swiper slide.
    336      *
    337      * Creates a Swiper slide containing the default WooCommerce product thumbnail.
    338      * Only renders if the gallery should be displayed for the current product.
    339      *
    340      * @since 1.5.8
    341      */
    342     public function render_default_thumbnail_slide() {
    343         if ( $this->should_display_gallery() ) {
    344             echo $this->wrap_in_slide( woocommerce_get_product_thumbnail() );
    345         }
     553            $output .= $this->build_swiper_closing_tag();
     554
     555            return $output;
     556        }
     557
     558        return $block_content;
    346559    }
    347560
     
    352565     * contains gallery images, and has a featured thumbnail.
    353566     *
     567     * @param int|null $product_id Optional product ID to check. Uses current post if null.
     568     *
    354569     * @return bool True if gallery should be displayed, false otherwise.
    355      * @since    1.4.0
    356      */
    357     public function should_display_gallery(): bool {
    358         if ('product' !== get_post_type()) {
     570     * @since 1.4.0
     571     */
     572    public function should_display_gallery( $product_id = null ): bool {
     573
     574        if ( ! isset( $product_id ) ) {
     575            $product_id = get_the_ID();
     576        }
     577
     578        if ( 'product' !== get_post_type( $product_id ) ) {
    359579            return false;
    360580        }
    361581
    362         $has_featured_image = has_post_thumbnail();
    363 
    364         if(!$has_featured_image){
     582        $has_featured_image = has_post_thumbnail( $product_id );
     583
     584        if ( ! $has_featured_image ) {
    365585            return false;
    366586        }
    367587
    368         $product = wc_get_product();
    369         if (!$product) {
     588        $product = wc_get_product( $product_id );
     589        if ( ! $product ) {
    370590            return false;
    371591        }
    372592
    373593        $gallery_images = $product->get_gallery_image_ids();
    374         if(count($gallery_images) > 0){
     594        if ( count( $gallery_images ) > 0 ) {
    375595            return true;
    376596        }
    377597
    378         $consider_variation_images = (get_option('wdevs_gallery_swiper_variation_images', 'no') === 'yes');
    379         if($consider_variation_images){
    380             return apply_filters( 'wdevs_gallery_swiper_should_display_gallery', $this->product_has_variation_images($product) );
     598        $consider_variation_images = $this->should_include_variation_images();
     599        if ( $consider_variation_images ) {
     600            return apply_filters( 'wdevs_gallery_swiper_should_display_gallery', $this->product_has_variation_images( $product ) );
    381601        }
    382602
     
    391611     * @param WC_Product $product The product object.
    392612     * @param int $attachment_id The attachment ID of the image.
     613     *
    393614     * @return string The HTML for the product image.
    394615     *
     
    416637     * @param WC_Product $product The product object.
    417638     * @param int $attachment_id The attachment ID of the image.
     639     *
    418640     * @return mixed The HTML for the product image with Blocksy compatibility.
    419641     *
     
    472694     * @since 1.5.2
    473695     */
    474     private function product_has_variation_images($product): bool {
    475         if (!$product->is_type('variable')) {
     696    private function product_has_variation_images( $product ): bool {
     697        if ( ! $product->is_type( 'variable' ) ) {
    476698            return false;
    477699        }
    478700
    479         foreach ($product->get_available_variations() as $variation) {
    480             if (!empty($variation['image_id'])) {
     701        foreach ( $product->get_available_variations() as $variation ) {
     702            if ( ! empty( $variation['image_id'] ) ) {
    481703                return true;
    482704            }
     
    515737    }
    516738
    517     /**
    518      * Wrap content in a Swiper slide div.
    519      *
    520      * Creates a div element with the swiper-slide class and wraps the provided content.
    521      *
    522      * @param string $content The content to wrap in the slide.
    523      *
    524      * @return string The HTML for the Swiper slide with content.
    525      *
    526      * @since 1.5.8
    527      */
    528     public function wrap_in_slide( $content ) {
    529         $extra_classes = apply_filters( 'wdevs_gallery_swiper_slide_extra_classes', '' );
    530         $slide_classes = trim( 'swiper-slide ' . $extra_classes );
    531         return '<div class="' . esc_attr( $slide_classes ) . '">' . $content . '</div>';
    532     }
    533 
    534     /**
    535      * Render gallery with default thumbnail as first slide.
    536      *
    537      * This method is used as a callback for theme/plugin compatibility adjustments
    538      * where the default gallery rendering needs to be replaced with a version
    539      * that includes the default thumbnail as the first slide.
    540      *
    541      * @since 1.5.8
    542      */
    543     public function render_gallery_with_default_thumbnail() {
    544         $this->render_full_gallery( true );
     739
     740    /**
     741     * Check if block integration has been executed.
     742     *
     743     * Uses WordPress did_action() to check if the block integration
     744     * action has been triggered during the current request.
     745     *
     746     * @return bool True if block integration has been executed, false otherwise.
     747     * @since 1.5.9
     748     */
     749    private function executed_block_integration() {
     750        return did_action( 'wdevs_gallery_swiper_block_start_rendering' );
     751    }
     752
     753    /**
     754     * Check if variation images should be included in the gallery.
     755     *
     756     * Checks the plugin setting 'wdevs_gallery_swiper_variation_images'
     757     * to determine if variable product variation images should be displayed.
     758     *
     759     * @return bool True if variation images should be included, false otherwise.
     760     * @since 1.5.9
     761     */
     762    private function should_include_variation_images() {
     763        return ( get_option( 'wdevs_gallery_swiper_variation_images', 'no' ) === 'yes' );
    545764    }
    546765}
  • product-gallery-swiper-for-woocommerce/trunk/wdevs-gallery-swiper.php

    r3333374 r3334031  
    1717 * Plugin URI:           https://products.wijnberg.dev
    1818 * Description:          Enhances WooCommerce product images display on product listing sections, providing a responsive and touch-friendly swiper.
    19  * Version:              1.5.8
     19 * Version:              1.5.9
    2020 * Author:               Wijnberg Developments
    2121 * License:              GPL-2.0+
     
    4141 * Rename this for your plugin and update it as you release new versions.
    4242 */
    43 define( 'WDEVS_GALLERY_SWIPER_VERSION', '1.5.8' );
     43define( 'WDEVS_GALLERY_SWIPER_VERSION', '1.5.9' );
    4444
    4545/**
Note: See TracChangeset for help on using the changeset viewer.