PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / trunk
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler vtrunk
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
fluent-cart / app / Hooks / Handlers / BlockEditors / ProductReviewSummaryGroupBlockEditor.php

ProductReviewSummaryGroupBlockEditor.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler trunk, at app/Hooks/Handlers/BlockEditors/ProductReviewSummaryGroupBlockEditor.php

159 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Hooks\Handlers\BlockEditors;
4
5 use FluentCart\App\Modules\Templating\AssetLoader;
6 use FluentCart\App\Services\Translations\TransStrings;
7 use FluentCart\Framework\Support\Arr;
8
9 class ProductReviewSummaryGroupBlockEditor extends BlockEditor
10 {
11 protected static string $editorName = 'product-review-summary-group';
12
13 public function supports(): array
14 {
15 return [
16 'html' => false,
17 'align' => true,
18 'color' => [
19 'text' => true,
20 'background' => true,
21 ],
22 'spacing' => [
23 'margin' => true,
24 'padding' => true,
25 ],
26 '__experimentalBorder' => [
27 'color' => true,
28 'radius' => true,
29 'style' => true,
30 'width' => true,
31 ],
32 ];
33 }
34
35 /**
36 * Container pattern (same as ProductInfoBlockEditor): without this,
37 * WordPress renders the inner blocks before the callback runs, outside
38 * the custom-product context.
39 */
40 protected function skipInnerBlocks(): bool
41 {
42 return true;
43 }
44
45 /**
46 * Children detect nesting server-side by this key's presence (the
47 * related_product_ids pattern) and follow the group's product. The
48 * group also consumes the key itself: nested under Product Reviews it
49 * defers to that container's product the same way its children do.
50 */
51 public function provideContext()
52 {
53 return [
54 'fluent-cart/review_container_query' => 'query_type',
55 ];
56 }
57
58 public function useContext()
59 {
60 return ['fluent-cart/review_container_query'];
61 }
62
63 public function blockAttributes(): array
64 {
65 return [
66 // Must mirror the JS registration — WordPress prepares dynamic
67 // block attributes against this server-side schema, so an
68 // attribute missing here never reaches the render callback.
69 'query_type' => ['type' => 'string', 'default' => 'default'],
70 'product_id' => ['type' => ['string', 'number'], 'default' => ''],
71 ];
72 }
73
74 public function getScripts(): array
75 {
76 return [
77 [
78 'source' => 'admin/BlockEditor/ProductReviewSummaryGroup/ProductReviewSummaryGroupBlockEditor.jsx',
79 'dependencies' => ['wp-blocks', 'wp-components', 'wp-data', 'wp-block-editor', 'wp-element']
80 ]
81 ];
82 }
83
84 public function getStyles(): array
85 {
86 return [
87 // The review block editor previews share one stylesheet — it is
88 // scoped to every review block wrapper. Declaring it here keeps
89 // this block styled on production even if the Product Reviews
90 // container block ever stops enqueuing it.
91 'admin/BlockEditor/ProductReviews/style/product-reviews-block-editor.scss'
92 ];
93 }
94
95 public function localizeData(): array
96 {
97 return [
98 $this->getLocalizationKey() => [
99 'slug' => $this->slugPrefix,
100 'name' => static::getEditorName(),
101 'title' => __('Rating Summary with Review', 'fluent-cart'),
102 'description' => __('Rating summary card with a Write a Review button for a product.', 'fluent-cart'),
103 ],
104 'fluent_cart_block_translation' => TransStrings::blockStrings(),
105 ];
106 }
107
108 public function render(array $shortCodeAttribute, $block = null)
109 {
110 // Nested under a Product Reviews container (server-visible via the
111 // provided context key), the parent owns the product — the group's
112 // own saved query must not win.
113 $insideContainer = $block instanceof \WP_Block
114 && isset($block->context['fluent-cart/review_container_query']);
115
116 $product = $insideContainer ? fluent_cart_get_current_product() : $this->resolveProduct($shortCodeAttribute);
117
118 if (!$product) {
119 return '';
120 }
121
122 AssetLoader::loadSingleProductAssets();
123
124 // A custom pick swaps the product context through setup_postdata()
125 // and restores the previously current product the same way the
126 // Product Reviews container does, keeping nesting stack-safe with
127 // no globals written.
128 $isCustom = !$insideContainer && Arr::get($shortCodeAttribute, 'query_type', 'default') === 'custom';
129 $previousProduct = $isCustom ? fluent_cart_get_current_product() : null;
130
131 if ($isCustom) {
132 setup_postdata($product->ID);
133 }
134
135 $innerContent = '';
136 if ($block instanceof \WP_Block && !empty($block->inner_blocks)) {
137 foreach ($block->inner_blocks as $innerBlock) {
138 if (isset($innerBlock->parsed_block)) {
139 $innerContent .= $innerBlock->render();
140 }
141 }
142 }
143
144 if ($isCustom) {
145 if ($previousProduct) {
146 setup_postdata($previousProduct->ID);
147 } else {
148 wp_reset_postdata();
149 }
150 }
151
152 $wrapper_attributes = get_block_wrapper_attributes([
153 'class' => 'fct-review-summary-group',
154 ]);
155
156 return static::wrapUnlessEmpty($wrapper_attributes, $innerContent);
157 }
158 }
159