PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
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 trunk All 48 releases
← All changes | app/Services/Renderer/PricingTableRenderer.php +155 -12 1.3.21 → 1.6.5 View file →
@@ -1,16 +1,12 @@
1 1 <?php
2 2
3 3 namespace FluentCart\App\Services\Renderer;
4 4
5 -use FluentCart\Api\CurrencySettings;
5 +
6 6 use FluentCart\Api\StoreSettings;
7 7 use FluentCart\App\Helpers\Helper;
8 -use FluentCart\App\Models\Product;
9 -use FluentCart\App\Models\ProductVariation;
10 -use FluentCart\App\Vite;
11 8 use FluentCart\Framework\Support\Arr;
12 -use FluentCart\App\App;
13 9 use FluentCart\Framework\Support\Str;
14 10 use FluentCart\App\Helpers\CurrenciesHelper;
15 11 use FluentCart\App\Hooks\Handlers\ShortCodes\Buttons\AddToCartShortcode;
16 12 use FluentCart\App\Hooks\Handlers\ShortCodes\Buttons\DirectCheckoutShortcode;
@@ -43,8 +39,11 @@
43 39
44 40 protected $licenseEnable = 'no';
45 41
46 42
43 + protected $productPerRow = 4;
44 +
45 +
47 46 public function __construct($viewData)
48 47 {
49 48 $this->viewData = $viewData;
50 49 $this->variants = $this->viewData['variants'];
@@ -54,30 +53,156 @@
54 53
55 54 $this->sign = CurrenciesHelper::getCurrencySign($signName);
56 55
57 56 $this->showCartButton = Arr::get($this->viewData, 'show_cart_button', 1);
58 -
59 -
57 + $productPerRow = absint(Arr::get($this->viewData, 'product_per_row', 4));
58 + $this->productPerRow = $productPerRow > 0 ? $productPerRow : 4;
60 59 }
61 60
62 61 public function render()
63 62 {
63 + $groupBy = Arr::get($this->viewData, 'group_by', 'repeat_interval');
64 + $groups = $this->groupVariants($groupBy);
65 + $useTabs = $groupBy !== 'none' && count($groups) > 1;
64 66
65 67 ?>
66 68 <div class="fluent-cart-pricing-table" data-fluent-cart-pricing-table role="region"
67 69 aria-label="<?php esc_attr_e('Pricing table', 'fluent-cart'); ?>">
68 - <div class="fluent-cart-pricing-table-variants-iterator" role="list">
69 - <?php $this->renderVariant(); ?>
70 + <?php if ($useTabs) : ?>
71 + <?php $this->renderTabs($groups); ?>
72 + <?php else : ?>
73 + <div
74 + class="fluent-cart-pricing-table-variants-iterator"
75 + role="list"
76 + style="--fluent-cart-pricing-table-product-per-row: <?php echo esc_attr($this->productPerRow); ?>;"
77 + >
78 + <?php $this->renderVariant($this->variants); ?>
79 + </div>
80 + <?php endif; ?>
81 + </div>
82 + <?php
83 + }
84 +
85 + protected function groupVariants(string $groupBy): array
86 + {
87 + if ($groupBy === 'none') {
88 + return ['onetime' => $this->variants];
89 + }
90 +
91 + $key = $groupBy === 'payment_type' ? 'payment_type' : 'repeat_interval';
92 +
93 + $groups = [];
94 + foreach ($this->variants as $variant) {
95 + $bucket = Arr::get($variant, "other_info.{$key}") ?: 'onetime';
96 + if (Arr::get($variant, 'other_info.installment') === 'yes') {
97 + $bucket = 'installment';
98 + }
99 + $groups[$bucket][] = $variant;
100 + }
101 +
102 + return $groups;
103 + }
104 +
105 + protected function renderTabs(array $groups)
106 + {
107 + $groupKeys = array_keys($groups);
108 + $activeIndex = (int) Arr::get($this->viewData, 'active_tab', 0);
109 + if (!isset($groupKeys[$activeIndex])) {
110 + $activeIndex = 0;
111 + }
112 + $activeKey = $groupKeys[$activeIndex];
113 + $activeVariantMap = Arr::get($this->viewData, 'active_variant', []);
114 + if (!\is_array($activeVariantMap)) {
115 + $activeVariantMap = [];
116 + }
117 +
118 + ?>
119 + <div class="fluent-cart-pricing-table-tab" data-fluent-cart-pricing-table-tab>
120 + <div class="fluent-cart-pricing-table-tab-nav">
121 + <div class="fluent-cart-pricing-table-tab-nav-inner-wrap">
122 + <div class="fluent-cart-pricing-table-tab-nav-inner" role="tablist">
123 + <div class="tab-active-bar" data-tab-active-bar></div>
124 + <?php foreach ($groupKeys as $key) :
125 + $isActive = $key === $activeKey;
126 + ?>
127 + <div class="fluent-cart-pricing-table-tab-nav-item<?php echo $isActive ? ' active' : ''; ?>"
128 + data-tab="<?php echo esc_attr($key); ?>">
129 + <?php echo esc_html($this->getTabLabel($key)); ?>
130 + </div>
131 + <?php endforeach; ?>
132 + </div>
133 + </div>
70 134 </div>
135 + <div class="fluent-cart-pricing-table-tab-content" data-tab-contents>
136 + <?php foreach ($groups as $key => $groupVariants) :
137 + $isActive = $key === $activeKey;
138 + $currentActiveVariant = Arr::get($activeVariantMap, $key, '');
139 + ?>
140 + <div id="<?php echo esc_attr($key); ?>"
141 + class="fluent-cart-pricing-table-tab-pane<?php echo $isActive ? ' active' : ''; ?>"
142 + data-tab-content
143 + data-active_variant="<?php echo esc_attr($currentActiveVariant); ?>"
144 + role="tabpanel">
145 + <div
146 + class="fluent-cart-pricing-table-variants-iterator"
147 + role="list"
148 + style="--fluent-cart-pricing-table-product-per-row: <?php echo esc_attr($this->productPerRow); ?>;"
149 + >
150 + <?php $this->renderVariant($groupVariants); ?>
151 + </div>
152 + </div>
153 + <?php endforeach; ?>
154 + </div>
71 155 </div>
72 156 <?php
73 157 }
74 158
75 - public function renderVariant()
159 + protected function getTabLabel(string $key): string
76 160 {
161 + $labels = [
162 + 'daily' => __('Daily', 'fluent-cart'),
163 + 'weekly' => __('Weekly', 'fluent-cart'),
164 + 'monthly' => __('Monthly', 'fluent-cart'),
165 + 'yearly' => __('Yearly', 'fluent-cart'),
166 + 'onetime' => __('One Time', 'fluent-cart'),
167 + 'subscription' => __('Subscription', 'fluent-cart'),
168 + 'installment' => __('Installment', 'fluent-cart'),
169 + ];
77 170
171 + return $labels[$key] ?? ucfirst(str_replace('_', ' ', $key));
172 + }
78 173
79 - foreach ($this->variants as $index => $variant) {
174 + protected function isVariantActive($variant): bool
175 + {
176 + $groupBy = Arr::get($this->viewData, 'group_by', 'repeat_interval');
177 +
178 + if ($groupBy === 'none') {
179 + $variantGroupKey = 'onetime';
180 + } else {
181 + $groupKey = $groupBy === 'payment_type' ? 'payment_type' : 'repeat_interval';
182 +
183 + $variantGroupKey = Arr::get($variant, "other_info.{$groupKey}") ?: 'onetime';
184 +
185 + if (Arr::get($variant, 'other_info.installment') === 'yes') {
186 + $variantGroupKey = 'installment';
187 + }
188 + }
189 +
190 + $activeVariantMap = Arr::get($this->viewData, 'active_variant', []);
191 + if (!\is_array($activeVariantMap)) {
192 + $activeVariantMap = [];
193 + }
194 +
195 + $variantId = Arr::get($variant, 'id');
196 +
197 + return isset($activeVariantMap[$variantGroupKey]) && $activeVariantMap[$variantGroupKey] == $variantId;
198 + }
199 +
200 + public function renderVariant(?array $variants = null)
201 + {
202 + $variants = $variants ?? $this->variants;
203 +
204 + foreach ($variants as $index => $variant) {
80 205 $this->repeatInterval = Arr::get($variant, 'other_info.repeat_interval', null);
81 206
82 207 $this->itemPrice = esc_html(Helper::toDecimal(Arr::get($variant, 'item_price', 0), false, false, false));
83 208
@@ -98,11 +223,24 @@
98 223 $licenseMeta = Arr::get($variant, 'product.licenses_meta.meta_value', null);
99 224
100 225 $this->licenseEnable = Arr::get($licenseMeta, 'enabled', 'no');
101 226
227 + $isActiveVariant = $this->isVariantActive($variant);
228 +
229 + // Parse badge settings from viewData
230 + $badgeData = Arr::get($this->viewData, 'badge', '');
231 + $badgeConfig = is_string($badgeData) ? self::stringToAssocArray($badgeData) : (is_array($badgeData) ? $badgeData : []);
232 + $badgeText = Arr::get($badgeConfig, 'text', __('Recommended', 'fluent-cart'));
233 + $badgePosition = Arr::get($badgeConfig, 'position', 'right');
234 +
102 235 ?>
103 236
104 - <div class="fluent-cart-pricing-table-variant" data-fluent-cart-pricing-table-variant role="listitem">
237 + <div class="fluent-cart-pricing-table-variant<?php echo $isActiveVariant ? ' active' : ''; ?>" data-fluent-cart-pricing-table-variant role="listitem">
238 + <?php if ($isActiveVariant) : ?>
239 + <div class="fluent-cart-pricing-table-variant-badge <?php echo esc_attr($badgePosition); ?>">
240 + <?php echo esc_html($badgeText); ?>
241 + </div>
242 + <?php endif; ?>
105 243
106 244 <div class="fluent-cart-pricing-table-variant-contents">
107 245 <div class="fluent-cart-pricing-table-variant-title">
108 246 <?php echo esc_html(Arr::get($variant, 'product.post_title', '')); ?>
@@ -235,8 +373,9 @@
235 373 'product_id' => Arr::get($variant, 'id', ''),
236 374 'quantity' => 1,
237 375 'variation_type' => Arr::get($variant, 'variation_type', ''),
238 376 'payment_type' => Arr::get($variant, 'payment_type', ''),
377 + 'variation_id' => Arr::get($variant, 'id', ''),
239 378 ];
240 379
241 380 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped in view template
242 381 echo AddToCartShortcode::make()->enqueueAssets()->render($data);
@@ -312,9 +451,13 @@
312 451 'is_pricing_table' => true,
313 452 'quantity' => 1,
314 453 'variation_type' => Arr::get($variant, 'variation_type', ''),
315 454 'stock_availability' => Arr::get($variant, 'stock_status', ''),
455 + 'variation_id' => Arr::get($variant, 'id', ''),
316 456 ];
457 +
458 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped in view template
459 + echo DirectCheckoutShortcode::make()->enqueueAssets()->render($data);
317 460 }
318 461 }
319 462
320 463 private static function stringToAssocArray($string): array