PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.0
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
fluent-cart / app / Services / Renderer / CartItemRenderer.php

CartItemRenderer.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.0, at app/Services/Renderer/CartItemRenderer.php

366 lines 14.8 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\Services\Renderer;
4
5 use FluentCart\App\Helpers\Helper;
6 use FluentCart\App\Models\Cart;
7 use FluentCart\Framework\Support\Arr;
8 use FluentCart\App\Vite;
9
10 class CartItemRenderer
11 {
12 protected $item = [];
13 protected $cart = null;
14
15 protected $product = null;
16
17 protected $variant = null;
18
19 public function __construct($item = [], ?Cart $cart = null)
20 {
21 $this->item = $item;
22 $this->cart = $cart;
23 }
24
25 protected function getEventInfo()
26 {
27 return [
28 'item' => $this->item,
29 'cart' => $this->cart,
30 'product' => $this->product,
31 'variant' => $this->variant,
32 ];
33 }
34
35 public function render()
36 {
37 $wrapperClassAttributes = [
38 'fct_line_item',
39 'fct_product_id_' . Arr::get($this->item, 'post_id', ''),
40 'fct_item_id_' . Arr::get($this->item, 'id', ''),
41 'fct_item_type_' . Arr::get($this->item, 'other_info.payment_type', ''),
42 ];
43
44 if (Arr::get($this->item, 'featured_media')) {
45 $wrapperClassAttributes[] = 'fct_has_image';
46 }
47
48 $promoPriceOriginal = Arr::get($this->item, 'other_info.promo_price_original', 0);
49 if ($promoPriceOriginal && $promoPriceOriginal > $this->item['unit_price']) {
50 $promoPriceOriginal = $promoPriceOriginal * Arr::get($this->item, 'quantity', 1);
51 } else {
52 $promoPriceOriginal = '';
53 }
54
55 $couponDiscount = (int) Arr::get($this->item, 'coupon_discount', 0);
56 $lineTotal = (int) Arr::get($this->item, 'line_total', 0);
57 $subtotal = (int) Arr::get($this->item, 'subtotal', 0);
58 $hasCouponDiscount = $couponDiscount > 0 && $lineTotal < $subtotal;
59 ?>
60 <div class="<?php $this->renderCssAtts($wrapperClassAttributes); ?>" role="listitem">
61 <div class="fct_line_item_body">
62 <div class="fct_line_item_info">
63 <?php $this->renderImage(); ?>
64 <div class="fct_item_content">
65 <?php $this->renderTitle(); ?>
66 <?php $this->renderChildVariants(); ?>
67 <?php do_action('fluent_cart/cart/line_item/line_meta', $this->getEventInfo()); ?>
68 </div>
69 </div><!-- .fct_line_item_info -->
70
71 <div class="fct_line_item_price" aria-label="<?php esc_attr_e('Price information', 'fluent-cart'); ?>">
72 <?php if($promoPriceOriginal) : ?>
73 <div style="text-decoration: line-through;" class="fct_line_item_total fct_promo_price" aria-label="<?php esc_attr_e('Original price', 'fluent-cart'); ?>">
74 <?php echo esc_html(Helper::toDecimal($promoPriceOriginal)); ?>
75 </div>
76 <?php endif; ?>
77 <div class="fct_item_price_wrapper">
78 <?php do_action('fluent_cart/cart/line_item/before_total', $this->getEventInfo()); ?>
79 <span class="fct_line_item_total<?php echo $hasCouponDiscount ? ' fct_coupon_original_price' : ''; ?>" aria-label="<?php esc_attr_e('Total price', 'fluent-cart'); ?>">
80 <?php echo esc_html(Helper::toDecimal($subtotal)); ?>
81 </span>
82 <?php if ($hasCouponDiscount) : ?>
83 <span class="fct_line_item_total fct_coupon_discounted_price" aria-label="<?php esc_attr_e('Discounted price', 'fluent-cart'); ?>">
84 <?php echo esc_html(Helper::toDecimal($lineTotal)); ?>
85 </span>
86 <?php endif; ?>
87 <?php do_action('fluent_cart/cart/line_item/after_total', $this->getEventInfo()); ?>
88 </div>
89 </div><!-- .fct_line_item_price -->
90 </div>
91 <div class="fct_line_item_footer">
92 <?php do_action('fluent_cart/cart/line_item/footer_start', $this->getEventInfo()); ?>
93
94 <?php $hasSetupFee = $this->maybeRenderSetupFeeInfo(); ?>
95 <?php if ($hasSetupFee) : ?>
96 <?php $this->renderSetupFeeInfo() ?>
97 <?php do_action('fluent_cart/cart/line_item/after_setup_fee_info', $this->getEventInfo()); ?>
98 <?php endif; ?>
99 <?php do_action('fluent_cart/cart/line_item/footer_end', $this->getEventInfo()); ?>
100 </div>
101 </div>
102 <?php
103 }
104
105 public function renderTitle()
106 {
107 $href = Arr::get($this->item, 'view_url', '');
108
109 $mainTitle = (string) Arr::get($this->item, 'post_title', '');
110 $subtitle = (string) Arr::get($this->item, 'title', '');
111
112 $quantity = Arr::get($this->item, 'quantity', 1);
113
114 ?>
115 <div class="fct_item_title">
116 <?php do_action('fluent_cart/cart/line_item/before_main_title', $this->getEventInfo()); ?>
117 <?php if ($quantity > 1): ?>
118 <span class="fct_item_quantity" aria-label="<?php echo esc_attr(sprintf(
119 /* translators: %d: quantity */
120 __('Quantity %d', 'fluent-cart'), $quantity)); ?>">
121 <?php echo esc_attr($quantity); ?> <span aria-hidden="true">x</span>
122 </span>
123 <?php endif; ?>
124 <?php if ($href): ?>
125 <a
126 href="<?php echo esc_url($href); ?>"
127 aria-label="<?php echo esc_attr(sprintf(
128 /* translators: %s: product title */
129 __('View details for %s', 'fluent-cart'), $mainTitle)); ?>"
130 >
131 <?php echo wp_kses_post($mainTitle); ?>
132 </a>
133 <?php else: ?>
134 <?php echo wp_kses_post($mainTitle); ?>
135 <?php endif; ?>
136
137 <?php if ($mainTitle != $subtitle && $subtitle): ?>
138 <div class="fct_item_variant_title" aria-label="<?php esc_attr_e('Variant', 'fluent-cart'); ?>">
139 - <?php echo wp_kses_post($subtitle); ?>
140 </div>
141 <?php endif; ?>
142 <?php $this->maybeRenderPaymentTypeInfo(); ?>
143 <?php $this->maybeRenderPackageInfo(); ?>
144
145 <?php do_action('fluent_cart/cart/line_item/after_main_title', $this->getEventInfo()); ?>
146 </div>
147 <?php
148 }
149
150 public function renderImage()
151 {
152 $image = Arr::get($this->item, 'featured_media');
153 if (!$image) {
154 $image = Vite::getAssetUrl('images/placeholder.svg');
155 }
156 $href = Arr::get($this->item, 'view_url', '');
157 $altText = sprintf(
158 /* translators: %s: product title */
159 __('Image of %s', 'fluent-cart'), Arr::get($this->item, 'title', __('product', 'fluent-cart')));
160 ?>
161 <div class="fct_item_image">
162 <?php if ($href): ?>
163 <a href="<?php echo esc_url($href); ?>">
164 <img src="<?php echo esc_url($image); ?>"
165 alt="<?php echo esc_attr($altText); ?>"/>
166 </a>
167 <?php else: ?>
168 <img src="<?php echo esc_url($image); ?>"
169 alt="<?php echo esc_attr($altText); ?>"/>
170 <?php endif; ?>
171 </div>
172 <?php
173 }
174
175 protected function renderCssAtts($atts)
176 {
177 echo esc_attr(implode(' ', $atts));
178 }
179
180 protected function maybeRenderPaymentTypeInfo()
181 {
182 $otherInfo = Arr::get($this->item, 'other_info', []);
183 $paymentType = Arr::get($otherInfo, 'payment_type', '');
184 $itemPrice = Arr::get($this->item, 'unit_price', 0);
185
186 if (isset($this->item['recurring_discounts'])) {
187 $otherInfo['recurring_discounts'] = $this->item['recurring_discounts'];
188 }
189
190 if ($paymentType === 'subscription') {
191 $subscriptionInfo = Helper::generateSubscriptionInfo($otherInfo, $itemPrice);
192 $trialInfo = Helper::generateTrialInfo($otherInfo);
193 ?>
194 <div class="fct_item_payment_info">
195 <span class="sr-only"><?php esc_html_e('Payment information', 'fluent-cart'); ?></span>
196
197 <span> <?php echo wp_kses($subscriptionInfo, ['del' => true]); ?> </span>
198 <?php if ($trialInfo): ?>
199 <span class="trial-days"> <?php echo esc_html($trialInfo); ?> </span>
200 <?php endif; ?>
201 </div>
202 <?php
203 return;
204 }
205
206 $quantity = Arr::get($this->item, 'quantity', 1);
207
208 if ($quantity < 2) {
209 return;
210 }
211 ?>
212 <div class="fct_item_payment_info">
213 <?php
214 /* translators: %1$s: formatted unit price */
215 printf(esc_html__('%1$s each', 'fluent-cart'), esc_html(Helper::toDecimal($itemPrice)));
216 ?>
217 <?php do_action('fluent_cart/cart/line_item/unit_price_hint', $this->getEventInfo()); ?>
218 </div>
219 <?php
220 }
221
222 protected function maybeRenderSetupFeeInfo()
223 {
224 $paymentType = Arr::get($this->item, 'other_info.payment_type', '');
225 if ($paymentType !== 'subscription') {
226 return false;
227 }
228
229 $otherInfo = Arr::get($this->item, 'other_info', []);
230 $setupFeeInfo = Helper::generateSetupFeeInfo($otherInfo);
231 if (empty($setupFeeInfo)) {
232 return false;
233 }
234 return true;
235 }
236
237 protected function renderSetupFeeInfo()
238 {
239
240 $otherInfo = Arr::get($this->item, 'other_info', []);
241 $setupFeeInfo = Helper::generateSetupFeeInfo($otherInfo, true);
242 $setupFeeName = Arr::get($setupFeeInfo, 'signup_fee_name', '');
243 $setupFeePrice = Arr::get($setupFeeInfo, 'signup_fee_formatted', 0);
244
245 ?>
246 <div class="fct_item_payment_info">
247 <div class="fct_setup_fee_info">
248 <span class="setup-fee"><?php esc_html_e($setupFeeName) ?></span>
249 <span class="setup-fee-amount">
250 <?php esc_html_e($setupFeePrice) ?>
251 <?php do_action('fluent_cart/cart/line_item/setup_fee_price_info', $this->getEventInfo()); ?>
252 </span>
253 </div>
254 </div>
255 <?php
256
257 return true;
258 }
259
260 protected function maybeRenderPackageInfo()
261 {
262 if (Arr::get($this->item, 'fulfillment_type') !== 'physical') {
263 return;
264 }
265
266 $otherInfo = Arr::get($this->item, 'other_info', []);
267 if (!is_array($otherInfo)) {
268 return;
269 }
270
271 $packageSlug = Arr::get($otherInfo, 'package_slug', '');
272 $package = Helper::getPackageBySlug($packageSlug);
273 if (!$package) {
274 return;
275 }
276
277 $name = Arr::get($package, 'name', '');
278 $type = Arr::get($package, 'type', '');
279
280 $parts = [];
281 if ($name) {
282 $parts[] = $name;
283 }
284
285 $storeWeightUnit = Helper::shopConfig('weight_unit') ?: 'kg';
286 $productWeight = floatval(Arr::get($otherInfo, 'weight', 0));
287 $productWeightUnit = Arr::get($otherInfo, 'weight_unit', $storeWeightUnit);
288 $convertedProductWeight = Helper::convertWeight($productWeight, $productWeightUnit, $storeWeightUnit);
289 $packageWeight = floatval(Arr::get($package, 'weight', 0));
290 $packageWeightUnit = Arr::get($package, 'weight_unit', $storeWeightUnit);
291 $convertedPackageWeight = Helper::convertWeight($packageWeight, $packageWeightUnit, $storeWeightUnit);
292 $totalWeight = $convertedProductWeight + $convertedPackageWeight;
293
294 if ($totalWeight) {
295 $formatted = rtrim(rtrim(number_format($totalWeight, 2), '0'), '.');
296 $parts[] = $formatted . ' ' . $storeWeightUnit;
297 }
298
299 if (!$parts) {
300 return;
301 }
302
303 $icon = ShippingMethodsRender::getPackageTypeIcon($type ?: 'box');
304 ?>
305 <div class="fct_item_package_info">
306 <?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
307 <span><?php echo esc_html(implode(' · ', $parts)); ?></span>
308 </div>
309 <?php
310 }
311
312 public function renderChildVariants(){
313 $childVariants = Arr::get($this->item, 'child_variants', []);
314
315 if (empty($childVariants)) {
316 return;
317 }
318
319 $total = count($childVariants);
320
321 ?>
322 <div class="fct-bundle-products" data-fluent-cart-collapsibles>
323 <h4 class="fct-bundle-products-title">
324 <?php echo esc_html__('Bundle of', 'fluent-cart') . ':'; ?>
325 </h4>
326 <div class="fct-bundle-products-list">
327 <?php foreach (array_slice($childVariants, 0, 2) as $childVariant): ?>
328 <p>
329 <?php echo esc_html(Arr::get($childVariant, 'post_title')) . ' - ' . esc_html(Arr::get($childVariant, 'variation_title')); ?>
330 </p>
331 <?php endforeach; ?>
332
333 <?php if ($total > 2): ?>
334 <div class="fct-bundle-products-more">
335 <div class="fct-bundle-products-more-list">
336 <?php foreach (array_slice($childVariants, 2) as $childVariant): ?>
337 <p>
338 <?php echo esc_html(Arr::get($childVariant, 'post_title')) . ' - ' . esc_html(Arr::get($childVariant, 'variation_title')); ?>
339 </p>
340 <?php endforeach; ?>
341 </div>
342 </div>
343 <?php endif;?>
344 </div>
345
346 <?php if ($total > 2) : ?>
347 <a href="#" class="fct-see-more-btn" data-fluent-cart-collapsible-toggle>
348 <span class="see-more-text">
349 <?php echo esc_html__('See More', 'fluent-cart'); ?>
350 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="7" viewBox="0 0 12 7" fill="none">
351 <path d="M0.75 0.75L5.04289 5.04289C5.37623 5.37623 5.54289 5.54289 5.75 5.54289C5.95711 5.54289 6.12377 5.37623 6.45711 5.04289L10.75 0.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
352 </svg>
353 </span>
354 <span class="see-less-text">
355 <?php echo esc_html__('See Less', 'fluent-cart'); ?>
356 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="7" viewBox="0 0 14 8" fill="none">
357 <path d="M0.75 6.54297L6.04289 1.25008C6.37623 0.916742 6.54289 0.750076 6.75 0.750076C6.95711 0.750076 7.12377 0.916742 7.45711 1.25008L12.75 6.54297" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
358 </svg>
359 </span>
360 </a>
361 <?php endif; ?>
362 </div>
363 <?php }
364
365 }
366