PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.6
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.6
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
← All changes | app/Services/Renderer/ProductRenderer.php +72 -38 1.6.2 → 1.6.6 View file →
@@ -13,8 +13,9 @@
13 13 use FluentCart\App\Http\Routes\WebRoutes;
14 14 use FluentCart\App\Models\ProductVariation;
15 15 use FluentCart\Framework\Support\Collection;
16 16 use FluentCart\App\Modules\Templating\AssetLoader;
17 +use FluentCart\App\Modules\FluentPlayer\ProductVideoRenderer;
17 18
18 19 class ProductRenderer
19 20 {
20 21 protected $product;
@@ -38,8 +39,10 @@
38 39 protected $defaultGalleryImageId = 0;
39 40
40 41 protected $galleryActiveSet = false;
41 42
43 + protected $productVideoRenderer = null;
44 +
42 45 protected $paymentTypes = [];
43 46
44 47 protected $variantsByPaymentTypes = [];
45 48
@@ -432,11 +435,16 @@
432 435 if (empty($this->defaultImageUrl)) {
433 436 $this->defaultImageUrl = $featuredMedia;
434 437 }
435 438
439 + $videoRenderer = $this->getProductVideoRenderer();
440 + $videoRenderer->showFirstByDefault(!$this->hasGalleryImages());
441 + $defaultVideoId = $videoRenderer->getDefaultMediaId();
442 +
436 443 ?>
437 - <div class="fct-product-gallery-thumb" role="region"
438 - aria-label="<?php echo esc_attr($this->product->post_title . ' gallery'); ?>">
444 + <div class="fct-product-gallery-thumb<?php echo $defaultVideoId ? ' is-video-active' : ''; ?>" role="region"
445 + aria-label="<?php echo esc_attr($this->product->post_title . ' gallery'); ?>"
446 + <?php echo $defaultVideoId ? 'data-fct-video-default="' . esc_attr((string) $defaultVideoId) . '"' : ''; ?>>
439 447 <img
440 448 src="<?php echo esc_url($this->defaultImageUrl ?? '') ?>"
441 449 alt="<?php echo esc_attr($this->defaultImageAlt) ?>"
442 450 data-fluent-cart-single-product-page-product-thumbnail
@@ -441,21 +449,54 @@
441 449 alt="<?php echo esc_attr($this->defaultImageAlt) ?>"
442 450 data-fluent-cart-single-product-page-product-thumbnail
443 451 data-default-image-url="<?php echo esc_url($featuredMedia) ?>"
444 452 />
453 + <?php $this->getProductVideoRenderer()->renderInlinePlayers(); ?>
445 454 </div>
446 455 <?php
447 456 }
448 457
458 + /**
459 + * Whether any gallery / variant image exists to show in the main area.
460 + * Only meaningful after renderGalleryThumb() has built $this->images.
461 + */
462 + protected function hasGalleryImages(): bool
463 + {
464 + foreach ($this->images as $image) {
465 + foreach ((array) Arr::get($image, 'media', []) as $item) {
466 + if (!empty(Arr::get($item, 'url'))) {
467 + return true;
468 + }
469 + }
470 + }
471 +
472 + return false;
473 + }
474 +
475 + public function getProductVideoRenderer(): ProductVideoRenderer
476 + {
477 + if ($this->productVideoRenderer === null) {
478 + $this->productVideoRenderer = new ProductVideoRenderer($this->product);
479 + }
480 +
481 + return $this->productVideoRenderer;
482 + }
483 +
449 484 public function renderGalleryThumbControls($maxThumbnails = null)
450 485 {
451 486 $totalThumbImages = Arr::pluck($this->images, 'media.*.url');
452 487
453 - if(count($totalThumbImages) == 1 && is_countable($totalThumbImages[0]) && count($totalThumbImages[0]) == 1){
488 + // A lone image needs no strip, but a video thumb still has to be reachable.
489 + if(count($totalThumbImages) == 1 && is_countable($totalThumbImages[0]) && count($totalThumbImages[0]) == 1 && !$this->getProductVideoRenderer()->isAvailable()){
454 490
455 491 return '';
456 492 }
457 493
494 + // A lone video without images is already showing in the main area.
495 + if (!$this->hasGalleryImages() && count($this->getProductVideoRenderer()->getVideos()) === 1) {
496 + return '';
497 + }
498 +
458 499 // Build variantTermMap and variantFirstMediaMap.
459 500 // For advanced variations, Pro builds both maps via the gallery_variation_data
460 501 // filter — it has access to AttributeGroup types (color/image) that free cannot
461 502 // query directly. For all other product types, free builds variantFirstMediaMap
@@ -548,9 +589,16 @@
548 589 $isAdvVariation = !empty($this->variantTermMap);
549 590 $countedMediaKeys = [];
550 591 $count = 0;
551 592 $totalImages = 0;
593 + $videoRenderer = $this->getProductVideoRenderer();
552 594
595 + // The gallery opens on a video the admin put in front of every image,
596 + // so no image thumb takes the selected slot in that case.
597 + if ($videoRenderer->getDefaultMediaId()) {
598 + $this->galleryActiveSet = true;
599 + }
600 +
553 601 // Count unique images to render. For advanced variations, deduplicate by WP media ID
554 602 // when available, or by URL for externally imported images (media ID = 0).
555 603 foreach ($this->images as $imageId => $image) {
556 604 if (empty($image['media']) || !is_array($image['media'])) {
@@ -592,16 +640,21 @@
592 640 }
593 641 $renderedMediaKeys[$mediaDedupeKey] = true;
594 642 }
595 643 if ($maxThumbnails !== null && $count >= (int) $maxThumbnails) {
644 + $videoRenderer->renderThumbControls(!$this->galleryActiveSet);
596 645 $this->renderGallerySeeMoreButton($totalImages - (int) $maxThumbnails);
597 646 return;
598 647 }
648 + // Videos the admin dragged in front of this image come first.
649 + $videoRenderer->renderThumbControlsBefore($count, !$this->galleryActiveSet);
599 650 $termId = (int) ($this->variantTermMap[(int) $imageId] ?? 0);
600 651 $this->renderGalleryThumbControlButton($item, $imageId, $termId, $mediaId);
601 652 $count++;
602 653 }
603 654 }
655 +
656 + $videoRenderer->renderThumbControls(!$this->galleryActiveSet);
604 657 }
605 658
606 659 public function renderGallerySeeMoreButton($remainingCount)
607 660 {
@@ -1003,41 +1056,26 @@
1003 1056 'current_price' => $itemPrice,
1004 1057 'scope' => 'price_range'
1005 1058 ]));
1006 1059 ?>
1007 - <?php
1060 + <div class="fct-price-range fct-product-prices">
1008 1061
1009 - if ($comparePrice) {
1010 - $aria_label = sprintf(
1011 - /* translators: 1: Original price, 2: Current item price */
1012 - __('Original Price: %1$s, Price: %2$s', 'fluent-cart'),
1013 - Helper::toDecimal($comparePrice),
1014 - Helper::toDecimal($itemPrice)
1015 - );
1016 - } else {
1017 - $aria_label = sprintf(
1018 - /* translators: 1: Current item price */
1019 - __('Price: %1$s', 'fluent-cart'),
1020 - Helper::toDecimal($itemPrice)
1021 - );
1022 - }
1023 -
1024 - ?>
1025 - <div class="fct-price-range fct-product-prices" role="term"
1026 - aria-label="<?php echo esc_attr($aria_label); ?>">
1027 -
1028 1062 <?php if ($comparePrice): ?>
1029 1063 <span class="fct-compare-price">
1030 - <del aria-label="<?php echo esc_attr(__('Original price', 'fluent-cart')); ?>"><?php echo esc_html(Helper::toDecimal($comparePrice)); ?></del>
1064 + <span class="fct-sr-only"><?php echo esc_html__('Original price:', 'fluent-cart'); ?></span>
1065 + <del><?php echo esc_html(Helper::toDecimal($comparePrice)); ?></del>
1031 1066 </span>
1032 1067 <?php endif; ?>
1033 - <span class="fct-item-price" aria-label="<?php echo esc_attr(__('Current price', 'fluent-cart')); ?>">
1068 + <span class="fct-item-price">
1069 + <span class="fct-sr-only"><?php echo $comparePrice ? esc_html__('Sale price:', 'fluent-cart') : esc_html__('Price:', 'fluent-cart'); ?></span>
1034 1070 <?php echo esc_html(Helper::toDecimal($itemPrice)); ?>
1035 1071 <?php do_action('fluent_cart/product/after_price', RenderContext::decorate([
1036 1072 'product' => $this->product,
1073 + 'variant' => $first_price,
1037 1074 'current_price' => $itemPrice,
1038 1075 'scope' => 'price_range'
1039 1076 ])); ?>
1077 + <?php RenderHelper::renderPriceSuffix($this->product, $first_price, 'price_range'); ?>
1040 1078 </span>
1041 1079 </div>
1042 1080 <?php
1043 1081 do_action('fluent_cart/product/single/after_price_block', RenderContext::decorate([
@@ -1055,21 +1093,15 @@
1055 1093 'current_price' => $min_price,
1056 1094 'scope' => 'price_range'
1057 1095 ]));
1058 1096 ?>
1059 - <?php
1060 - $aria_label = sprintf(
1061 - /* translators: 1: Minimum price, 2: Maximum price */
1062 - __('Price range: %1$s - %2$s', 'fluent-cart'),
1063 - Helper::toDecimal($min_price),
1064 - Helper::toDecimal($max_price)
1065 - );
1066 - ?>
1067 - <div class="fct-product-prices fct-price-range" role="term" aria-label="<?php echo esc_attr($aria_label); ?>">
1097 + <div class="fct-product-prices fct-price-range">
1068 1098
1069 1099 <?php if ($max_price && $max_price != $min_price && $max_price > $min_price): ?>
1100 + <span class="fct-sr-only"><?php echo esc_html__('Price range:', 'fluent-cart'); ?></span>
1070 1101 <span class="fct-min-price"><?php echo esc_html(Helper::toDecimal($min_price)); ?></span>
1071 1102 <span class="fct-price-separator" aria-hidden="true">-</span>
1103 + <span class="fct-sr-only"><?php echo esc_html__('to', 'fluent-cart'); ?></span>
1072 1104 <?php endif; ?>
1073 1105 <span class="fct-max-price">
1074 1106 <?php echo esc_html(Helper::toDecimal($max_price)); ?>
1075 1107 </span>
@@ -1244,8 +1276,9 @@
1244 1276 return;
1245 1277 } ?>
1246 1278
1247 1279 <span class="fct-compare-price">
1280 + <span class="fct-sr-only"><?php echo esc_html__('Original price:', 'fluent-cart'); ?></span>
1248 1281 <del><?php echo esc_html(Helper::toDecimal($variant->compare_price)); ?></del>
1249 1282 </span>
1250 1283 <?php
1251 1284 }
@@ -1916,9 +1949,9 @@
1916 1949 }
1917 1950 ?>
1918 1951 <?php if ($this->viewType === 'both' || $this->viewType === 'text'): ?>
1919 1952 <div class="fct-product-variant-text">
1920 - <div class="fct-product-variant-title" aria-label="<?php echo esc_attr(__('Variant title', 'fluent-cart')); ?>"><?php echo esc_html($variant->variation_title); ?></div>
1953 + <div class="fct-product-variant-title"><?php echo esc_html($variant->variation_title); ?></div>
1921 1954 <?php if (!$this->shouldRenderPriceInPriceSection() && $paymentType === 'subscription'): ?>
1922 1955 <?php $this->renderSubscriptionInfo($variant); ?>
1923 1956 <?php endif; ?>
1924 1957 </div>
@@ -1928,14 +1961,15 @@
1928 1961 <?php if (!$this->shouldRenderPriceInPriceSection()): ?>
1929 1962 <div class="fct-product-variant-price">
1930 1963 <?php if ($comparePrice): ?>
1931 1964 <div class="fct-product-variant-compare-price">
1932 - <del aria-label="<?php echo esc_attr(__('Original price', 'fluent-cart')); ?>">
1965 + <span class="fct-sr-only"><?php echo esc_html__('Original price:', 'fluent-cart'); ?></span>
1966 + <del>
1933 1967 <span><?php echo esc_html(Helper::toDecimal($comparePrice)); ?></span></del>
1934 1968 </div>
1935 1969 <?php endif; ?>
1936 - <div class="fct-product-variant-item-price"
1937 - aria-label="<?php echo esc_attr(__('Current price', 'fluent-cart')); ?>">
1970 + <div class="fct-product-variant-item-price">
1971 + <span class="fct-sr-only"><?php echo $comparePrice ? esc_html__('Sale price:', 'fluent-cart') : esc_html__('Price:', 'fluent-cart'); ?></span>
1938 1972 <span><?php echo esc_html(Helper::toDecimal($itemPrice)); ?></span>
1939 1973 </div>
1940 1974 </div>
1941 1975 <?php endif; ?>