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

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

193 lines 7.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\RelatedProduct\InnerBlocks;
4
5 use FluentCart\Api\Resource\ShopResource;
6 use FluentCart\App\Models\Product;
7 use FluentCart\App\Models\ProductDetail;
8 use FluentCart\Framework\Support\Arr;
9
10 class InnerBlocks
11 {
12 public static $parentBlock = 'fluent-cart/related-product';
13
14 private const MIN_COLUMNS = 1;
15
16 private const MAX_COLUMNS = 6;
17
18 public static function register()
19 {
20 $self = new self();
21 $blocks = $self->getInnerBlocks();
22
23 foreach ($blocks as $block) {
24 $args = [
25 'apiVersion' => 3,
26 'api_version' => 3,
27 'version' => 3,
28 'title' => $block['title'],
29 'category' => 'fluent-cart',
30 'parent' => array_merge($block['parent'] ?? [], [static::$parentBlock]),
31 'supports' => Arr::get($block, 'supports', []),
32 'attributes' => Arr::get($block, 'attributes', []),
33 'uses_context' => Arr::get($block, 'uses_context', []),
34 ];
35
36 // Only add render_callback if it exists
37 if (!empty($block['callback']) && is_callable($block['callback'])) {
38 $args['render_callback'] = $block['callback'];
39 }
40
41 register_block_type($block['slug'], $args);
42 }
43 }
44
45 public function getInnerBlocks(): array
46 {
47 return [
48 [
49 'title' => __('Product Template', 'fluent-cart'),
50 'slug' => 'fluent-cart/product-template',
51 'callback' => [$this, 'renderProductTemplate'],
52 'component' => 'ProductTemplateBlock',
53 'icon' => 'screenoptions',
54 'parent' => ['fluent-cart/related-product'],
55 'supports' => [
56 'reusable' => false,
57 'html' => false,
58 ],
59 'attributes' => [],
60 'uses_context' => [
61 'fluent-cart/related_product_ids',
62 'fluent-cart/order_by',
63 'fluent-cart/query_type',
64 'fluent-cart/product_id',
65 'fluent-cart/related_by_categories',
66 'fluent-cart/related_by_brands',
67 'fluent-cart/columns',
68 'fluent-cart/posts_per_page',
69 'fluent-cart/show_image',
70 'fluent-cart/show_title',
71 'fluent-cart/show_price',
72 'fluent-cart/show_button',
73 ],
74 ],
75 ];
76 }
77
78 public function renderProductTemplate($attributes, $content, $block): string
79 {
80 $queryType = Arr::get($block->context, 'fluent-cart/query_type', 'custom');
81 $orderBy = Arr::get($block->context, 'fluent-cart/order_by', 'title_asc');
82 $postsPerPage = absint(Arr::get($block->context, 'fluent-cart/posts_per_page', 6));
83
84 // Build relatedBy taxonomies from context
85 $relatedBy = [];
86 if (Arr::get($block->context, 'fluent-cart/related_by_categories', true)) {
87 $relatedBy[] = 'product-categories';
88 }
89 if (Arr::get($block->context, 'fluent-cart/related_by_brands', true)) {
90 $relatedBy[] = 'product-brands';
91 }
92
93 if ($queryType === 'default') {
94 // Default mode: get related products from the current product context
95 $currentProduct = fluent_cart_get_current_product();
96
97 if (!$currentProduct) {
98 return '<div class="fct-no-related-products"><p>' .
99 __('No related products found.', 'fluent-cart') .
100 '</p></div>';
101 }
102
103 $relatedProducts = ShopResource::getSimilarProducts(
104 $currentProduct->ID,
105 false,
106 [
107 'related_by' => $relatedBy,
108 'order_by' => $orderBy,
109 'posts_per_page' => $postsPerPage,
110 ]
111 );
112 } else {
113 // Custom mode: get related products from the user-picked product_id
114 $productId = absint(Arr::get($block->context, 'fluent-cart/product_id', 0));
115
116 if (!$productId) {
117 return '<div class="fct-no-related-products"><p>' .
118 __('No related products found.', 'fluent-cart') .
119 '</p></div>';
120 }
121
122 $relatedProducts = ShopResource::getSimilarProducts(
123 $productId,
124 false,
125 [
126 'related_by' => $relatedBy,
127 'order_by' => $orderBy,
128 'posts_per_page' => $postsPerPage,
129 ]
130 );
131 }
132
133 if (empty($relatedProducts)) {
134 return '<div class="fct-no-related-products"><p>' .
135 __('No related products found.', 'fluent-cart') .
136 '</p></div>';
137 }
138
139 $blockContext = $block->context;
140 $columns = absint(Arr::get($block->context, 'fluent-cart/columns', 4));
141 $columns = max(self::MIN_COLUMNS, min(self::MAX_COLUMNS, $columns));
142
143 // Build list of hidden block slugs based on show/hide toggles
144 $hiddenBlocks = [];
145 if (!Arr::get($block->context, 'fluent-cart/show_image', true)) {
146 $hiddenBlocks[] = 'fluent-cart/shopapp-product-image';
147 }
148 if (!Arr::get($block->context, 'fluent-cart/show_title', true)) {
149 $hiddenBlocks[] = 'fluent-cart/shopapp-product-title';
150 }
151 if (!Arr::get($block->context, 'fluent-cart/show_price', true)) {
152 $hiddenBlocks[] = 'fluent-cart/shopapp-product-price';
153 }
154 if (!Arr::get($block->context, 'fluent-cart/show_button', true)) {
155 $hiddenBlocks[] = 'fluent-cart/shopapp-product-buttons';
156 }
157 $innerBlocksContent = '';
158
159 // Wrap products in a grid
160 $innerBlocksContent .= '<div class="fct-related-products-grid" style="' . '--fct-related-product-columns: ' . $columns . '">';
161
162 foreach ($relatedProducts as $product) {
163 setup_postdata($product->ID);
164
165 if ($block instanceof \WP_Block && !empty($block->inner_blocks)) {
166 $innerBlocksContent .= '<div class="fct-product-card">';
167
168 // Render each inner block with the product context
169 foreach ($block->inner_blocks as $inner_block) {
170 if (isset($inner_block->parsed_block)) {
171 $blockName = Arr::get($inner_block->parsed_block, 'blockName', '');
172 if (in_array($blockName, $hiddenBlocks, true)) {
173 continue;
174 }
175
176 $innerContext = array_merge($inner_block->context, $blockContext);
177 $instance = new \WP_Block($inner_block->parsed_block, $innerContext);
178 $innerBlocksContent .= $instance->render();
179 }
180 }
181
182 $innerBlocksContent .= '</div>';
183 }
184 }
185
186 $innerBlocksContent .= '</div>';
187
188 wp_reset_postdata();
189
190 return $innerBlocksContent;
191 }
192 }
193