PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
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 trunk 1.2.0 All 47 releases
fluent-cart / app / Modules / Templating / Bricks / Elements / ProductStock.php

ProductStock.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Modules/Templating/Bricks/Elements/ProductStock.php

273 lines 9.5 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\Modules\Templating\Bricks\Elements;
4
5 use Bricks\Element;
6 use FluentCart\App\Modules\Data\ProductDataSetup;
7 use FluentCart\App\Services\Renderer\ProductRenderer;
8 use FluentCart\App\Modules\Templating\Bricks\BricksLoader;
9 use FluentCart\Framework\Support\Arr;
10
11 if (!defined('ABSPATH')) exit; // Exit if accessed directly
12
13 class ProductStock extends Element
14 {
15 public $category = 'fluent-cart';
16 public $name = 'fct-product-stock';
17 public $icon = 'ti-package fluent-cart-element-icon';
18
19 public function get_label()
20 {
21 return esc_html__('Product Stock', 'fluent-cart');
22 }
23
24 public function set_control_groups()
25 {
26 $this->control_groups['inStock'] = [
27 'title' => esc_html__('In stock', 'fluent-cart'),
28 'tab' => 'content',
29 ];
30
31 //
32 // $this->control_groups['lowStock'] = [
33 // 'title' => esc_html__('Low stock', 'fluent-cart') . '/' . esc_html__('On backorder', 'fluent-cart'),
34 // 'tab' => 'content',
35 // ];
36
37 $this->control_groups['outOfStock'] = [
38 'title' => esc_html__('Out of stock', 'fluent-cart'),
39 'tab' => 'content',
40 ];
41 }
42
43 public function set_controls()
44 {
45 $this->controls['queryType'] = [
46 'tab' => 'content',
47 'type' => 'select',
48 'label' => esc_html__('Query Type', 'fluent-cart'),
49 'options' => [
50 'default' => esc_html__('Default', 'fluent-cart'),
51 'custom' => esc_html__('Custom', 'fluent-cart'),
52 ],
53 'default' => 'default',
54 'inline' => true,
55 ];
56
57 $this->controls['productId'] = [
58 'tab' => 'content',
59 'type' => 'select',
60 'label' => esc_html__('Product', 'fluent-cart'),
61 'options' => BricksLoader::getProductOptions(),
62 'placeholder' => esc_html__('Select a product', 'fluent-cart'),
63 'searchable' => true,
64 'rerender' => true,
65 'required' => ['queryType', '=', 'custom'],
66 ];
67
68 $this->controls['manualProductId'] = [
69 'tab' => 'content',
70 'type' => 'text',
71 'label' => esc_html__('Manual Product ID', 'fluent-cart'),
72 'description' => esc_html__('Use this if the product is not available in dropdown.', 'fluent-cart'),
73 'required' => [['queryType', '=', 'custom'], ['productId', '=', '']],
74 ];
75
76 // In Stock
77
78 $this->controls['inStockText'] = [
79 'tab' => 'content',
80 'group' => 'inStock',
81 'type' => 'text',
82 'hasDynamicData' => 'text',
83 'placeholder' => esc_html__('Custom text', 'fluent-cart'),
84 ];
85
86 $this->controls['inStockTypography'] = [
87 'tab' => 'content',
88 'group' => 'inStock',
89 'label' => esc_html__('Typography', 'fluent-cart'),
90 'type' => 'typography',
91 'css' => [
92 [
93 'property' => 'font',
94 'selector' => '.in-stock',
95 ],
96 ],
97 ];
98
99 $this->controls['inStockBackgroundColor'] = [
100 'tab' => 'style',
101 'group' => 'inStock',
102 'label' => esc_html__('Background color', 'fluent-cart'),
103 'type' => 'color',
104 'css' => [
105 [
106 'property' => 'background-color',
107 'selector' => '.in-stock',
108 ]
109 ],
110 ];
111
112 // Low Stock
113 if (false) {
114 $this->controls['lowStockText'] = [
115 'tab' => 'content',
116 'group' => 'lowStock',
117 'type' => 'text',
118 'hasDynamicData' => 'text',
119 'placeholder' => esc_html__('Custom text', 'fluent-cart'),
120 ];
121
122 $this->controls['lowStockTypography'] = [
123 'tab' => 'content',
124 'group' => 'lowStock',
125 'label' => esc_html__('Typography', 'fluent-cart'),
126 'type' => 'typography',
127 'css' => [
128 [
129 'property' => 'font',
130 'selector' => '.low-stock, .available-on-backorder',
131 ],
132 ],
133 ];
134
135 $this->controls['lowStockBackgroundColor'] = [
136 'tab' => 'style',
137 'group' => 'lowStock',
138 'label' => esc_html__('Background color', 'fluent-cart'),
139 'type' => 'color',
140 'css' => [
141 [
142 'property' => 'background-color',
143 'selector' => '.low-stock, .available-on-backorder',
144 ]
145 ],
146 ];
147 }
148
149 // Out of Stock
150 $this->controls['outOfStockText'] = [
151 'tab' => 'content',
152 'group' => 'outOfStock',
153 'type' => 'text',
154 'hasDynamicData' => 'text',
155 'placeholder' => esc_html__('Custom text', 'fluent-cart'),
156 ];
157
158 $this->controls['outOfStockTypography'] = [
159 'tab' => 'content',
160 'group' => 'outOfStock',
161 'label' => esc_html__('Typography', 'fluent-cart'),
162 'type' => 'typography',
163 'css' => [
164 [
165 'property' => 'font',
166 'selector' => '.out-of-stock',
167 ],
168 ],
169 ];
170
171 $this->controls['outOfStockBackgroundColor'] = [
172 'tab' => 'style',
173 'group' => 'outOfStock',
174 'label' => esc_html__('Background color', 'fluent-cart'),
175 'type' => 'color',
176 'css' => [
177 [
178 'property' => 'background-color',
179 'selector' => '.out-of-stock',
180 ]
181 ],
182 ];
183 }
184
185 public function render()
186 {
187 $settings = $this->settings;
188 $queryType = $settings['queryType'] ?? 'default';
189
190 if ($queryType === 'default') {
191 $productId = $this->post_id;
192 } else {
193 $productId = !empty($settings['productId']) ? \intval($settings['productId']) : 0;
194 $manualProductId = !empty($settings['manualProductId']) ? \intval($settings['manualProductId']) : 0;
195
196 if (!$productId && $manualProductId) {
197 $productId = $manualProductId;
198 }
199 }
200
201 $product = ProductDataSetup::getProductModel($productId);
202
203 if (!$product) {
204 return $this->render_element_placeholder([
205 'title' => esc_html__(
206 'Select a product',
207 'fluent-cart'
208 ),
209 ]);
210 }
211
212 add_filter('fluent_cart/product_stock_availability', [$this, 'simulateAvailability'], 10, 2);
213
214 $productRender = new ProductRenderer($product);
215
216 ob_start();
217 $productRender->renderStockAvailability();
218 $stock_html = ob_get_clean();
219 remove_filter('fluent_cart/product_stock_availability', [$this, 'simulateAvailability'], 10);
220
221 if (!$stock_html) {
222 return $this->render_element_placeholder(
223 [
224 'title' => esc_html__('Stock management not enabled for this product.', 'fluent-cart'),
225 ]
226 );
227 }
228
229 echo "<div {$this->render_attributes( '_root' )}>" . wp_kses_post($stock_html) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- render_attributes() handles escaping
230 }
231
232 public function simulateAvailability($availability, $data)
233 {
234 $settings = $this->settings;
235 $is_manage_stock = Arr::get($availability, 'manage_stock');
236 if (!$is_manage_stock) {
237 return $availability;
238 }
239
240 // Get stock via helper function if we don't manage stock on product level (to enable low stock for example)
241 // $stock_quantity = Arr::get($productDetail, 'available_quantity');
242
243 // Set availability text based on user input
244 switch ($availability['class']) {
245 case 'in-stock':
246 $availability['availability'] = !empty($settings['inStockText']) ? $settings['inStockText'] : $availability['availability'];
247 break;
248
249 case 'available-on-backorder':
250 case 'low-stock':
251 $availability['availability'] = !empty($settings['lowStockText']) ? $settings['lowStockText'] : $availability['availability'];
252 break;
253
254 case 'out-of-stock':
255 $availability['availability'] = !empty($settings['outOfStockText']) ? $settings['outOfStockText'] : $availability['availability'];
256 break;
257 }
258
259 // Expose the configured custom labels for BOTH statuses (not just the one
260 // rendered on load) so the frontend JS — which re-derives the badge text on
261 // load and on every variant switch — can prefer them over its generic label
262 // map instead of clobbering the server-rendered custom text.
263 if (!empty($settings['inStockText'])) {
264 $availability['in_stock_text'] = $settings['inStockText'];
265 }
266 if (!empty($settings['outOfStockText'])) {
267 $availability['out_of_stock_text'] = $settings['outOfStockText'];
268 }
269
270 return $availability;
271 }
272 }
273