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 / ProductReviewFormBlockEditor.php

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

157 lines 5.9 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\Renderer\ProductReviewRenderer;
7 use FluentCart\App\Services\Translations\TransStrings;
8 use FluentCart\Framework\Support\Arr;
9
10 /**
11 * The review submission form on its own — no trigger, no overlay, just the
12 * fields printed where the block is placed.
13 *
14 * The sibling "Write a Review" block (write-a-review-button) is the trigger
15 * half: a button that opens the same form in a drawer or a modal. Splitting
16 * them lets a store put the button on a product page and the bare form on a
17 * dedicated review page, each paced independently.
18 */
19 class ProductReviewFormBlockEditor extends BlockEditor
20 {
21 /**
22 * Reused on purpose: this slug was the button-and-drawer block during
23 * development (now write-a-review-button). Reviews have not shipped, so
24 * no saved content carries the old block.
25 */
26 protected static string $editorName = 'product-review-form';
27
28 public function supports(): array
29 {
30 return [
31 'html' => false,
32 'align' => true,
33 'typography' => [
34 'fontSize' => true,
35 'lineHeight' => true,
36 '__experimentalFontFamily' => true,
37 '__experimentalFontWeight' => true,
38 '__experimentalDefaultControls' => [
39 'fontSize' => true,
40 ],
41 ],
42 'color' => [
43 'text' => true,
44 'background' => true,
45 ],
46 'spacing' => [
47 'margin' => true,
48 'padding' => true,
49 ],
50 '__experimentalBorder' => [
51 'color' => true,
52 'radius' => true,
53 'style' => true,
54 'width' => true,
55 ],
56 ];
57 }
58
59 public function blockAttributes(): array
60 {
61 return [
62 // Must mirror the JS registration — WordPress prepares dynamic
63 // block attributes against this server-side schema, so an
64 // attribute missing here never reaches the render callback.
65 'query_type' => ['type' => 'string', 'default' => 'default'],
66 'product_id' => ['type' => ['string', 'number'], 'default' => ''],
67 // 'steps' walks the same wizard the drawer does, in place;
68 // 'inline' puts every field on screen at once.
69 'layout' => ['type' => 'string', 'default' => 'inline'],
70 'starColor' => ['type' => 'string', 'default' => '#f59e0b'],
71 ];
72 }
73
74 public function getScripts(): array
75 {
76 return [
77 [
78 'source' => 'admin/BlockEditor/ProductReviewForm/ProductReviewFormBlockEditor.jsx',
79 'dependencies' => ['wp-blocks', 'wp-components', 'wp-data', 'wp-block-editor', 'wp-element', 'wp-server-side-render']
80 ]
81 ];
82 }
83
84 public function getStyles(): array
85 {
86 return [
87 'admin/BlockEditor/ProductReviewForm/style/product-review-form-block-editor.scss',
88 // The canvas renders the block's own markup, so it needs the
89 // storefront stylesheet that markup is written against. The base
90 // class re-enqueues styles on enqueue_block_assets, which is what
91 // carries them into the WP 6.3+ editor iframe.
92 'public/single-product/reviews.scss',
93 ];
94 }
95
96 public function localizeData(): array
97 {
98 return [
99 $this->getLocalizationKey() => [
100 'slug' => $this->slugPrefix,
101 'name' => static::getEditorName(),
102 'title' => __('Review Form', 'fluent-cart'),
103 'description' => __('The review submission form itself, printed on the page.', 'fluent-cart'),
104 ],
105 'fluent_cart_block_translation' => TransStrings::blockStrings(),
106 ];
107 }
108
109 public function useContext()
110 {
111 return ['fluent-cart/review_container_query'];
112 }
113
114 public function render(array $shortCodeAttribute, $block = null)
115 {
116 // Nested under a review container (server-visible via the provided
117 // context key) the parent owns the product — a stale custom pick
118 // saved on this child must not win. Standalone, the block resolves
119 // its own query.
120 $insideContainer = $block instanceof \WP_Block
121 && isset($block->context['fluent-cart/review_container_query']);
122
123 $product = $insideContainer ? fluent_cart_get_current_product() : $this->resolveProduct($shortCodeAttribute);
124
125 if (!$product) {
126 return '';
127 }
128
129 // Just the form's own assets. This block is the whole reason a review
130 // page exists; it has no gallery, no product card and no review list
131 // to serve, and loading their scripts and styles would cost every
132 // visitor to that page for nothing.
133 AssetLoader::loadReviewSubmissionFormAssets();
134
135 $layout = Arr::get($shortCodeAttribute, 'layout', 'inline');
136 if (!\in_array($layout, ['steps', 'inline'], true)) {
137 $layout = 'inline';
138 }
139
140 $wrapper_attributes = get_block_wrapper_attributes([
141 'class' => 'fct-review-form-block',
142 ]);
143
144 ob_start();
145 // container 'none' is what makes this block the form rather than a
146 // trigger: no CTA is rendered and nothing is hidden behind an overlay.
147 (new ProductReviewRenderer($product->ID, [
148 'container' => 'none',
149 'layout' => $layout,
150 'starColor' => sanitize_hex_color(Arr::get($shortCodeAttribute, 'starColor', '')) ?: '#f59e0b',
151 ]))->renderForm();
152 $inner = ob_get_clean();
153
154 return static::wrapUnlessEmpty($wrapper_attributes, $inner);
155 }
156 }
157