PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.0
1.7.0 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 All 50 releases
← All changes | app/Modules/Templating/TemplateActions.php +66 -3 1.6.5 → 1.7.0 View file →
@@ -12,8 +12,9 @@
12 12 use FluentCart\App\Modules\Data\ProductQuery;
13 13 use FluentCart\App\Services\Renderer\ProductListRenderer;
14 14 use FluentCart\App\Services\Renderer\ProductRenderer;
15 15 use FluentCart\App\Services\Renderer\ShopAppRenderer;
16 +use FluentCart\App\Services\Schema\ProductSchema;
16 17 use FluentCart\App\Services\TemplateService;
17 18 use FluentCart\Framework\Support\Arr;
18 19
19 20 class TemplateActions
@@ -22,8 +23,16 @@
22 23 {
23 24 add_action('fluent_cart/template/main_content', [$this, 'renderMainContent']);
24 25 add_action('fluent_cart/template/product_archive', [$this, 'renderProductArchive']);
25 26 add_action('fluent_cart/product/render_product_header', [$this, 'renderProductHeader']);
27 + // Block themes render reviews from the product template, so the
28 + // built-in listener is not attached there — the hook still fires for
29 + // third-party listeners. Safe to decide here: the theme is resolved
30 + // at after_setup_theme, before init runs this.
31 + if (!function_exists('wp_is_block_theme') || !wp_is_block_theme()) {
32 + add_action('fluent_cart/product/after_product_content', [$this, 'renderProductReviews']);
33 + }
34 + add_action('wp_head', [$this, 'renderProductJsonLd']);
26 35
27 36 // Universal hook for after_product_content — fires on both classic and block themes
28 37 // Block themes render <!-- wp:post-content --> which runs the_content filter
29 38 add_filter('the_content', function ($content) {
@@ -46,9 +55,9 @@
46 55 }
47 56
48 57 return $content;
49 58 }, 999);
50 -
59 +
51 60 add_shortcode('fluent_cart_product_header', function ($atts = []) {
52 61 $atts = shortcode_atts([
53 62 'id' => 0,
54 63 ], $atts);
@@ -120,9 +129,10 @@
120 129 ob_start();
121 130 (new ProductListRenderer(
122 131 $products,
123 132 __('Related Products', 'fluent-cart'),
124 - 'fct-similar-product-list-container'
133 + 'fct-similar-product-list-container',
134 + ['rating_context' => 'relevant']
125 135 ))->render();
126 136
127 137 $content = ob_get_clean();
128 138
@@ -299,9 +309,10 @@
299 309 ob_start();
300 310 (new ProductListRenderer(
301 311 $products,
302 312 __('Related Products', 'fluent-cart'),
303 - 'fct-similar-product-list-container'
313 + 'fct-similar-product-list-container',
314 + ['rating_context' => 'relevant']
304 315 ))->render();
305 316
306 317 $relevantProducts = ob_get_clean();
307 318 $content .= $relevantProducts;
@@ -348,7 +359,59 @@
348 359 ], '', $content);
349 360
350 361 // Remove extra whitespace between tags to clean up the output
351 362 return preg_replace('/>\s+</', '><', $cleaned);
363 + }
364 +
365 + /**
366 + * Whether the product page should carry its review section at all.
367 + *
368 + * Sits beside the relevant-products switch in Product Page settings and
369 + * works the same way, so one control governs the section wherever it is
370 + * rendered from — a review block, or the append below.
371 + *
372 + * @param int $postId
373 + * @return bool
374 + */
375 + public static function shouldShowReviewsOnProductPage($postId): bool
376 + {
377 + $show = (new StoreSettings())->get('show_reviews_in_single_page', 'yes') == 'yes';
378 +
379 + return (bool) apply_filters('fluent_cart/single_product_page/show_reviews', $show, $postId);
380 + }
381 +
382 + private function isReviewModuleAvailable()
383 + {
384 + return \FluentCart\Api\ModuleSettings::isActive('reviews')
385 + && class_exists(\FluentCart\App\Services\ProductReviewService::class);
386 + }
387 +
388 + public function renderProductReviews($postId)
389 + {
390 + if (!$postId || !$this->isReviewModuleAvailable()) {
391 + return;
392 + }
393 +
394 + $renderer = new \FluentCart\App\Services\Renderer\ProductReviewRenderer($postId);
395 + $renderer->render();
396 + $renderer->renderForm();
397 + }
398 +
399 + public function renderProductJsonLd()
400 + {
401 + if (!is_singular(\FluentCart\App\CPT\FluentProducts::CPT_NAME)) {
402 + return;
403 + }
404 +
405 + $postId = get_the_ID();
406 + if (!$postId) {
407 + return;
408 + }
409 +
410 + // The node itself — product, offers, aggregate rating, the reviews
411 + // the page shows — is ProductSchema's; this is only the page gate.
412 + // The reviews module gate lives there too, on the review parts
413 + // alone: a product is for sale whether or not it takes reviews.
414 + ProductSchema::render($postId);
352 415 }
353 416
354 417 }