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

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

158 lines 6.2 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 class WriteAReviewButtonBlockEditor extends BlockEditor
11 {
12 protected static string $editorName = 'write-a-review-button';
13
14 public function supports(): array
15 {
16 return [
17 'html' => false,
18 'align' => true,
19 'typography' => [
20 'fontSize' => true,
21 'lineHeight' => true,
22 '__experimentalFontFamily' => true,
23 '__experimentalFontWeight' => true,
24 '__experimentalDefaultControls' => [
25 'fontSize' => true,
26 ],
27 ],
28 'color' => [
29 'text' => true,
30 'background' => true,
31 ],
32 'spacing' => [
33 'margin' => true,
34 'padding' => true,
35 ],
36 '__experimentalBorder' => [
37 'color' => true,
38 'radius' => true,
39 'style' => true,
40 'width' => true,
41 ],
42 ];
43 }
44
45 public function blockAttributes(): array
46 {
47 return [
48 // Must mirror the JS registration — WordPress prepares dynamic
49 // block attributes against this server-side schema, so an
50 // attribute missing here never reaches the render callback.
51 // starColor was dropped with the trigger-button redesign, so it
52 // is deliberately absent here too.
53 'query_type' => ['type' => 'string', 'default' => 'default'],
54 'product_id' => ['type' => ['string', 'number'], 'default' => ''],
55 // The block is the trigger; these two decide what it opens.
56 // 'container' is where the form appears, 'layout' is how it
57 // paces the fields once it is there.
58 'container' => ['type' => 'string', 'default' => 'drawer'],
59 'layout' => ['type' => 'string', 'default' => 'inline'],
60 'addReviewButtonText' => ['type' => 'string', 'default' => ''],
61 'editReviewButtonText' => ['type' => 'string', 'default' => ''],
62 'loginReviewButtonText' => ['type' => 'string', 'default' => ''],
63 ];
64 }
65
66 public function getScripts(): array
67 {
68 return [
69 [
70 'source' => 'admin/BlockEditor/WriteAReviewButton/WriteAReviewButtonBlockEditor.jsx',
71 'dependencies' => ['wp-blocks', 'wp-components', 'wp-data', 'wp-block-editor', 'wp-element']
72 ]
73 ];
74 }
75
76 public function getStyles(): array
77 {
78 return [
79 'admin/BlockEditor/WriteAReviewButton/style/write-a-review-button-block-editor.scss',
80 // Shared review-block preview stylesheet — the standalone
81 // skeleton preview uses its classes.
82 'admin/BlockEditor/ProductReviews/style/product-reviews-block-editor.scss'
83 ];
84 }
85
86 public function localizeData(): array
87 {
88 return [
89 $this->getLocalizationKey() => [
90 'slug' => $this->slugPrefix,
91 'name' => static::getEditorName(),
92 'title' => __('Write a Review', 'fluent-cart'),
93 'description' => __('A button that opens the review submission drawer for a product.', 'fluent-cart'),
94 ],
95 'fluent_cart_block_translation' => TransStrings::blockStrings(),
96 ];
97 }
98
99 public function useContext()
100 {
101 return ['fluent-cart/review_container_query'];
102 }
103
104 public function render(array $shortCodeAttribute, $block = null)
105 {
106 // Nested under a review container (server-visible via the provided
107 // context key) the parent owns the product — a stale custom pick
108 // saved on this child must not win. Standalone, the block resolves
109 // its own query.
110 $insideContainer = $block instanceof \WP_Block
111 && isset($block->context['fluent-cart/review_container_query']);
112
113 $product = $insideContainer ? fluent_cart_get_current_product() : $this->resolveProduct($shortCodeAttribute);
114
115 if (!$product) {
116 return '';
117 }
118
119 // The form's own script and stylesheet: the block is a trigger and
120 // the form it opens, and needs none of the gallery, product card or
121 // review list the full single-product bundle carries. On a product
122 // page that bundle is enqueued anyway, under the same form handle.
123 AssetLoader::loadReviewSubmissionFormAssets();
124
125 $wrapper_attributes = get_block_wrapper_attributes([
126 'class' => 'fct-write-a-review-button-block',
127 ]);
128
129 $container = Arr::get($shortCodeAttribute, 'container', 'drawer');
130 if (!\in_array($container, ['drawer', 'modal'], true)) {
131 $container = 'drawer';
132 }
133
134 $layout = Arr::get($shortCodeAttribute, 'layout', 'inline');
135 if (!\in_array($layout, ['steps', 'inline'], true)) {
136 $layout = 'inline';
137 }
138
139 ob_start();
140 // The block is a button plus the overlay it opens: the trigger always
141 // renders (it is the block's whole purpose), and the section below
142 // carries the drawer or modal — clicking any CTA opens it via
143 // delegation. The form itself, standalone, is its own block.
144 $renderer = new ProductReviewRenderer($product->ID, [
145 'container' => $container,
146 'layout' => $layout,
147 'ctaAddText' => sanitize_text_field(Arr::get($shortCodeAttribute, 'addReviewButtonText', '')),
148 'ctaEditText' => sanitize_text_field(Arr::get($shortCodeAttribute, 'editReviewButtonText', '')),
149 'ctaLoginText' => sanitize_text_field(Arr::get($shortCodeAttribute, 'loginReviewButtonText', '')),
150 ]);
151 $renderer->renderWriteReviewCta();
152 $renderer->renderForm();
153 $inner = ob_get_clean();
154
155 return static::wrapUnlessEmpty($wrapper_attributes, $inner);
156 }
157 }
158