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 / Services / Renderer / PackageDescriptionRenderer.php

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

266 lines 10.0 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\Product;
7 use FluentCart\App\Models\ProductVariation;
8 use FluentCart\Framework\Support\Arr;
9
10 class PackageDescriptionRenderer
11 {
12 protected $product;
13
14 public function __construct(Product $product)
15 {
16 $this->product = $product;
17 }
18
19 /**
20 * Build package info string from snapshotted other_info fields.
21 *
22 * @param array $otherInfo Order item's other_info array
23 * @return string e.g. "Gift (Box) · 30 × 20 × 15 cm · Wt: 2 kg · Shipping: 2.5 kg"
24 */
25 public static function buildPackageInfoFromOtherInfo($otherInfo)
26 {
27 $storeWeightUnit = Helper::shopConfig('weight_unit') ?: 'kg';
28 $parts = [];
29
30 // Package name
31 $name = Arr::get($otherInfo, 'package_name', '');
32 if ($name) {
33 $parts[] = $name;
34 }
35
36 // Dimensions
37 $length = Arr::get($otherInfo, 'package_length', '');
38 $width = Arr::get($otherInfo, 'package_width', '');
39 $height = Arr::get($otherInfo, 'package_height', '');
40 $dimensionUnit = Arr::get($otherInfo, 'package_dimension_unit', 'cm');
41 $dimParts = array_filter([$length, $width, $height], function ($val) {
42 return $val !== '' && $val !== null && $val != 0;
43 });
44 if ($dimParts) {
45 $parts[] = implode(' × ', $dimParts) . ' ' . $dimensionUnit;
46 }
47
48 // Product weight
49 $productWeight = floatval(Arr::get($otherInfo, 'weight', 0));
50 $productWeightUnit = Arr::get($otherInfo, 'weight_unit', $storeWeightUnit);
51 $convertedProductWeight = Helper::convertWeight($productWeight, $productWeightUnit, $storeWeightUnit);
52 if ($convertedProductWeight) {
53 $formatted = rtrim(rtrim(number_format($convertedProductWeight, 2), '0'), '.');
54 $parts[] = sprintf(
55 /* translators: %1$s: formatted product weight, %2$s: weight unit */
56 __('Wt: %1$s %2$s', 'fluent-cart'),
57 $formatted,
58 $storeWeightUnit
59 );
60 }
61
62 // Shipping weight (product + package)
63 $packageWeight = floatval(Arr::get($otherInfo, 'package_weight', 0));
64 $packageWeightUnit = Arr::get($otherInfo, 'package_weight_unit', $storeWeightUnit);
65 $convertedPackageWeight = Helper::convertWeight($packageWeight, $packageWeightUnit, $storeWeightUnit);
66 $totalWeight = $convertedProductWeight + $convertedPackageWeight;
67 if ($totalWeight && $convertedPackageWeight) {
68 $formatted = rtrim(rtrim(number_format($totalWeight, 2), '0'), '.');
69 $parts[] = sprintf(
70 /* translators: %1$s: formatted shipping weight, %2$s: weight unit */
71 __('Shipping wt: %1$s %2$s', 'fluent-cart'),
72 $formatted,
73 $storeWeightUnit
74 );
75 }
76
77 $info = implode(' · ', $parts);
78
79 if (!$info) {
80 return '';
81 }
82
83 return sprintf(
84 /* translators: %1$s: package info summary */
85 __('Package: %1$s', 'fluent-cart'),
86 $info
87 );
88 }
89
90 public function renderPackageDescription(
91 $wrapper_attributes = '',
92 $showName = true,
93 $showDimensions = true,
94 $showProductWeight = true,
95 $showTotalWeight = true,
96 $variant = null,
97 $defaultVariant = null
98 ) {
99 if ($variant) {
100 if (!$wrapper_attributes) {
101 $wrapper_attributes = 'class="fct-package-description" data-fluent-cart-package-description';
102 }
103
104 $this->renderPackageDescriptionForVariant($variant, $wrapper_attributes, $showName, $showDimensions, $showProductWeight, $showTotalWeight);
105 return;
106 }
107
108 $variants = $this->product->variants;
109
110 if ($variants->isEmpty()) {
111 return;
112 }
113
114 $defaultVariant = $defaultVariant ?: $this->resolveDefaultVariant();
115
116 foreach ($variants as $v) {
117 $isHidden = ($defaultVariant && $defaultVariant->id != $v->id) ? ' is-hidden' : '';
118 $variantExtraAttributes = ' data-variation-id="' . esc_attr($v->id) . '"';
119
120 if ($wrapper_attributes) {
121 $variantWrapper = preg_replace(
122 '/class="([^"]*)"/',
123 'class="$1 fluent-cart-product-variation-content' . $isHidden . '"',
124 $wrapper_attributes,
125 1
126 ) . $variantExtraAttributes;
127 } else {
128 $variantWrapper = 'class="fct-package-description fluent-cart-product-variation-content' . $isHidden . '" data-fluent-cart-package-description' . $variantExtraAttributes;
129 }
130
131 $this->renderPackageDescriptionForVariant($v, $variantWrapper, $showName, $showDimensions, $showProductWeight, $showTotalWeight);
132 }
133 }
134
135 /**
136 * Query-free default-variant resolution mirroring ProductRenderer's
137 * constructor logic, so package-description rendering doesn't need to
138 * construct the heavyweight ProductRenderer just to know which variant
139 * should render visible initially.
140 */
141 private function resolveDefaultVariant()
142 {
143 $variants = $this->product->variants;
144 $defaultVariationId = Arr::get($this->product->detail, 'default_variation_id');
145
146 $isAdvanced = $this->product->detail
147 && Arr::get($this->product->detail, 'variation_type') === Helper::PRODUCT_TYPE_ADVANCE_VARIATION;
148 $eligibleVariants = $isAdvanced
149 ? $variants->where('item_status', 'active')
150 : $variants;
151
152 if ($eligibleVariants->isEmpty()) {
153 $eligibleVariants = $variants;
154 }
155
156 $eligibleIds = $eligibleVariants->pluck('id')->toArray();
157
158 if (!$defaultVariationId || !in_array($defaultVariationId, $eligibleIds)) {
159 $firstBySerial = $eligibleVariants
160 ->sortBy(function ($variant) {
161 return is_null($variant->serial_index) ? PHP_INT_MAX : (int) $variant->serial_index;
162 })
163 ->first();
164 $defaultVariationId = $firstBySerial ? $firstBySerial->id : Arr::get($eligibleIds, '0');
165 }
166
167 $resolved = $variants->first(function ($v) use ($defaultVariationId) {
168 return $v->id == $defaultVariationId;
169 });
170
171 return $resolved ?: $variants->first();
172 }
173
174 private function renderPackageDescriptionForVariant(
175 ProductVariation $variant,
176 $wrapper_attributes,
177 $showName,
178 $showDimensions,
179 $showProductWeight,
180 $showTotalWeight
181 ) {
182 if ($variant->fulfillment_type !== 'physical') {
183 return;
184 }
185
186 $packageSlug = Arr::get($variant->other_info, 'package_slug', '');
187 $package = Helper::getPackageBySlug($packageSlug);
188
189 if (!$package) {
190 return;
191 }
192
193 $name = Arr::get($package, 'name', '');
194 $length = Arr::get($package, 'length', '');
195 $width = Arr::get($package, 'width', '');
196 $height = Arr::get($package, 'height', '');
197 $dimensionUnit = Arr::get($package, 'dimension_unit', 'cm');
198 $packageWeight = floatval(Arr::get($package, 'weight', 0));
199 $packageWeightUnit = Arr::get($package, 'weight_unit', 'kg');
200
201 $storeWeightUnit = Helper::shopConfig('weight_unit') ?: 'kg';
202 $otherInfo = $variant->other_info ?: [];
203 $productWeight = floatval(Arr::get($otherInfo, 'weight', 0));
204 $productWeightUnit = Arr::get($otherInfo, 'weight_unit', $storeWeightUnit);
205
206 $convertedProductWeight = Helper::convertWeight($productWeight, $productWeightUnit, $storeWeightUnit);
207 $convertedPackageWeight = Helper::convertWeight($packageWeight, $packageWeightUnit, $storeWeightUnit);
208 $totalWeight = $convertedProductWeight + $convertedPackageWeight;
209
210 $hasVisibleContent = ($showName && $name)
211 || ($showDimensions && ($length || $width || $height))
212 || ($showProductWeight && $convertedProductWeight)
213 || ($showTotalWeight && $totalWeight);
214
215 if (!$hasVisibleContent) {
216 return;
217 }
218
219 echo sprintf('<div %s>', $wrapper_attributes); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
220 echo '<table class="fct-package-description__table" role="presentation"><tbody>';
221
222 if ($showName && $name) {
223 echo sprintf(
224 '<tr><th>%s</th><td>%s</td></tr>',
225 esc_html__('Package', 'fluent-cart'),
226 esc_html($name)
227 );
228 }
229
230 if ($showDimensions && ($length || $width || $height)) {
231 $dimensionParts = array_filter([$length, $width, $height], function ($val) {
232 return $val !== '' && $val !== null;
233 });
234 if ($dimensionParts) {
235 $formattedDimensions = implode(' × ', $dimensionParts) . ' ' . $dimensionUnit;
236 echo sprintf(
237 '<tr><th>%s</th><td>%s</td></tr>',
238 esc_html__('Dimensions', 'fluent-cart'),
239 esc_html($formattedDimensions)
240 );
241 }
242 }
243
244 if ($showProductWeight && $convertedProductWeight) {
245 $formattedProductWeight = rtrim(rtrim(number_format($convertedProductWeight, 2), '0'), '.');
246 echo sprintf(
247 '<tr><th>%s</th><td>%s</td></tr>',
248 esc_html__('Weight', 'fluent-cart'),
249 esc_html($formattedProductWeight . ' ' . $storeWeightUnit)
250 );
251 }
252
253 if ($showTotalWeight && $totalWeight && $convertedPackageWeight) {
254 $formattedTotalWeight = rtrim(rtrim(number_format($totalWeight, 2), '0'), '.');
255 echo sprintf(
256 '<tr><th>%s</th><td>%s</td></tr>',
257 esc_html__('Shipping Weight', 'fluent-cart'),
258 esc_html($formattedTotalWeight . ' ' . $storeWeightUnit)
259 );
260 }
261
262 echo '</tbody></table>';
263 echo '</div>';
264 }
265 }
266