PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.0
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 / Http / Requests / ProductVariationRequest.php

ProductVariationRequest.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.0, at app/Http/Requests/ProductVariationRequest.php

288 lines 13.7 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\Http\Requests;
4
5 use FluentCart\App\Helpers\Helper;
6 use FluentCart\Framework\Foundation\RequestGuard;
7 use FluentCart\Framework\Support\Arr;
8
9 class ProductVariationRequest extends RequestGuard
10 {
11 /**
12 * Normalize variant data before validation.
13 *
14 * This method is primarily used to ensure that the `variants` array contains
15 * the required structure, especially during data migration or when
16 * optional fields like `other_info` are not provided.
17 *
18 * Key operations:
19 * - Sets a default `fulfillment_type` (fallback to 'physical') if missing.
20 * - Sets a default `payment_type` (fallback to 'onetime') if missing.
21 * - Ensures `other_info` exists and assigns default billing/setup fee-related values if it's empty.
22 *
23 * This helps avoid issues during validation or processing by guaranteeing a consistent data structure.
24 *
25 * @return array The normalized data ready for validation.
26 */
27 public function beforeValidation()
28 {
29 $data = $this->all();
30 $fulfilmentType = Arr::get(
31 $data,
32 'variants.fulfillment_type',
33 Arr::get($data, 'variants.fulfillment_type', 'physical')
34 );
35 $paymentType = Arr::get($data, 'variants.payment_type', 'onetime');
36 $manageCost = Arr::get($data, 'variants.manage_cost');
37 if (empty($manageCost)) {
38 $manageCost = 'false';
39 }
40 $data['variants']['fulfillment_type'] = $fulfilmentType;
41 $data['variants']['manage_cost'] = $manageCost;
42
43 $variantOtherInfo = Arr::wrap(Arr::get($data, 'variants.other_info'));
44
45 // Ensure other_info is an array
46 if (empty($variantOtherInfo)) {
47 $variantOtherInfo = [
48 'payment_type' => $paymentType,
49 'times' => '',
50 'trial_days' => '',
51 'repeat_interval' => 'yearly',
52 'billing_summary' => '',
53 'manage_setup_fee' => 'no',
54 'signup_fee_name' => '',
55 'signup_fee' => '',
56 'setup_fee_per_item' => 'no',
57 //'purchasable' => 'yes',
58
59 ];
60 }
61 $data['variants']['other_info'] = $variantOtherInfo;
62
63 if (Arr::get($variantOtherInfo, 'payment_type') === 'onetime') {
64 $subscriptionFields = ['trial_days', 'times', 'repeat_interval', 'billing_summary', 'manage_setup_fee', 'signup_fee', 'signup_fee_name', 'setup_fee_per_item'];
65 foreach ($subscriptionFields as $field) {
66 unset($data['variants']['other_info'][$field]);
67 }
68 }
69
70 return $data;
71 }
72
73 /**
74 * @return array
75 */
76 public function rules()
77 {
78 return [
79 'variants.variation_title' => 'required|sanitizeText|maxLength:200',
80 'variants.sku' => 'nullable|sanitizeText|maxLength:30|unique:fct_product_variations,sku' . ($this->get('variants.id') ? ',' . $this->get('variants.id') : ''),
81 'variants.item_price' => 'nullable|numeric|min:0',
82 'variants.compare_price' => [
83 'nullable',
84 'numeric',
85 function ($attribute, $value) {
86 $itemPrice = $this->get("variants.item_price");
87 if (empty($itemPrice)) {
88 $itemPrice = 0;
89 }
90 if ($value !== null && $value < $itemPrice) {
91 return sprintf(__("Compare price must be greater than or equal to item price.", 'fluent-cart'));
92 }
93 return null;
94 },
95 ],
96 'variants.manage_cost' => 'nullable|sanitizeText|maxLength:10',
97 'variants.item_cost' => 'required_if:variants.manage_cost,true',
98 'variants.fulfillment_type' => 'required|sanitizeText|maxLength:100',
99 'variants.shipping_class' => function ($attr, $value) {
100 if ($value && !(\FluentCart\App\Models\ShippingClass::find(intval($value)))) {
101 return __('The selected shipping class does not exist.', 'fluent-cart');
102 }
103 return null;
104 },
105
106 'variants.manage_stock' => 'nullable|numeric',
107 'variants.stock_status' => 'required_if:variants.manage_stock,1|sanitizeText|maxLength:50',
108 'variants.total_stock' => 'required|numeric',
109 'variants.available' => 'required|numeric',
110 // 'variants.available' => [
111 // 'required',
112 // 'numeric',
113 // function ($attribute, $value, $fail) {
114 // if ($this->variants['stock_status'] == 'in-stock' && $value <= 0) {
115 // return __("The available stock must be greater than 0 when stock is set to in stock", 'fluent-cart');
116 // }
117 // return null;
118 // },
119 // ],
120 'variants.committed' => 'required|numeric',
121 'variants.on_hold' => 'required|numeric',
122
123 'variants.serial_index' => 'nullable|numeric',
124
125 'variants.other_info' => 'required|array',
126 'variants.other_info.description' => 'nullable|sanitizeTextArea|maxLength:255',
127 'variants.other_info.payment_type' => 'required|sanitizeText|in:onetime,subscription',
128 'variants.other_info.times' => [
129 function ($attribute, $value) {
130 if ($this->get('variants.other_info.payment_type') !== 'subscription') {
131 return null;
132 }
133 if (!empty($value) && !is_numeric($value)) {
134 return __('Times must be a number.', 'fluent-cart');
135 }
136 return Helper::installmentTimesError($this->get('variants.other_info'));
137 },
138 ],
139 'variants.other_info.trial_days' => [
140 function ($attribute, $value) {
141 if ($this->get('variants.other_info.payment_type') !== 'subscription') {
142 return null;
143 }
144 if (!empty($value) && !is_numeric($value)) {
145 return __('Trial days must be a number.', 'fluent-cart');
146 }
147 if (!empty($value) && $value > 365) {
148 return __('Trial period cannot exceed 365 days.', 'fluent-cart');
149 }
150 return null;
151 },
152 ],
153 'variants.other_info.repeat_interval' => 'required_if:variants.other_info.payment_type,subscription|sanitizeText|maxLength:100',
154 'variants.other_info.billing_summary' => 'nullable|sanitizeTextArea|maxLength:255',
155 'variants.other_info.manage_setup_fee' => 'required_if:variants.other_info.payment_type,subscription|sanitizeText|maxLength:100',
156 'variants.other_info.signup_fee' => 'required_if:variants.other_info.manage_setup_fee,yes',
157 'variants.other_info.signup_fee_name' => 'required_if:variants.other_info.manage_setup_fee,yes|sanitizeText|maxLength:100',
158 'variants.other_info.package_slug' => 'nullable|sanitizeText|maxLength:100',
159 'variants.other_info.weight' => 'nullable|numeric',
160 'variants.other_info.weight_unit' => 'nullable|sanitizeText|maxLength:10',
161 'variants.other_info.length' => 'nullable|numeric',
162 'variants.other_info.width' => 'nullable|numeric',
163 'variants.other_info.height' => 'nullable|numeric',
164 'variants.other_info.tax_class' => ['nullable', function ($attribute, $value) {
165 if (empty($value)) {
166 return null;
167 }
168
169 return empty(\FluentCart\App\Models\TaxClass::query()->where('slug', sanitize_text_field($value))->first())
170 ? __('Invalid Tax Class.', 'fluent-cart')
171 : null;
172 }],
173 'variants.other_info.tax_exempt' => 'nullable|sanitizeText|in:yes,no',
174
175 'variants.downloadable' => 'nullable|sanitizeText|maxLength:10',
176 ];
177 }
178
179
180 public function afterValidation($validator): array
181 {
182
183 $data = $this->get();
184
185 $price = $data['variants']['item_price'];
186
187 if (empty($price)) {
188 $data['variants']['item_price'] = 0;
189 }
190
191 return $data;
192 }
193
194
195 /**
196 * @return array
197 */
198 public function messages()
199 {
200 return [
201 'variants.variation_title.required' => esc_html__('Title is required.', 'fluent-cart'),
202 'variants.variation_title.max' => esc_html__('Title may not be greater than 200 characters.', 'fluent-cart'),
203 'variants.sku.max' => esc_html__('SKU may not be greater than 30 characters.', 'fluent-cart'),
204 'variants.sku.unique' => esc_html__('The SKU must be unique.', 'fluent-cart'),
205 'variants.item_price.required' => esc_html__('Price is required.', 'fluent-cart'),
206 'variants.item_price.numeric' => esc_html__('Price must be a number.', 'fluent-cart'),
207 'variants.item_price.min' => esc_html__('Price must be a positive number greater than 0.', 'fluent-cart'),
208 'variants.stock_status.required_if' => esc_html__('Stock status is required.', 'fluent-cart'),
209 'variants.item_cost.required_if' => esc_html__('Item cost is required.', 'fluent-cart'),
210 'variants.fulfillment_type.required' => esc_html__('Fulfilment Type is required.', 'fluent-cart'),
211
212 'variants.other_info.description.max' => esc_html__('Description may not be greater than 255 characters.', 'fluent-cart'),
213 'variants.other_info.payment_type.required' => esc_html__('Payment Type is required.', 'fluent-cart'),
214 'variants.other_info.times.required_if' => esc_html__('Times is required.', 'fluent-cart'),
215 'variants.other_info.repeat_interval.required_if' => esc_html__('Interval is required.', 'fluent-cart'),
216 'variants.other_info.signup_fee.required_if' => esc_html__('Setup Fee Amount is required.', 'fluent-cart'),
217 'variants.other_info.signup_fee_name.required_if' => esc_html__('Setup Fee Name is required.', 'fluent-cart'),
218 'variants.other_info.trial_days.numeric' => esc_html__('Trial days must be a number.', 'fluent-cart'),
219 'variants.other_info.trial_days.max' => esc_html__('Trial period cannot exceed 365 days.', 'fluent-cart'),
220 ];
221 }
222
223
224 /**
225 * @return array
226 */
227 public function sanitize()
228 {
229
230 return [
231 'variants.id' => 'intval',
232 'variants.rowId' => 'intval',
233 'variants.post_id' => 'intval',
234 'variants.variation_title' => 'sanitize_text_field',
235 'variants.sku' => 'sanitize_text_field',
236 'variants.item_price' => 'floatval',
237 'variants.compare_price' => 'floatval',
238 'variants.manage_cost' => 'sanitize_text_field',
239 'variants.fulfillment_type' => 'sanitize_text_field',
240 'variants.item_cost' => 'floatval',
241 'variants.total_stock' => 'intval',
242 'variants.available' => 'intval',
243 'variants.committed' => 'intval',
244 'variants.on_hold' => 'intval',
245 'variants.manage_stock' => 'intval',
246 'variants.shipping_class' => function ($value) {
247 return $value ? intval($value) : null;
248 },
249 'variants.stock_status' => 'sanitize_key',
250 'variants.serial_index' => 'intval',
251 'variants.media.*.id' => 'intval',
252 'variants.media.*.url' => function ($value) {
253 if (empty($value)) {
254 return '';
255 }
256
257 return sanitize_url($value);
258 },
259 'variants.media.*.title' => 'sanitize_text_field',
260
261 'variants.downloadable' => 'sanitize_text_field',
262
263 'variants.other_info' => function ($value) {
264 return is_array($value) ? $value : [];
265 },
266 'variants.other_info.description' => 'sanitize_text_field',
267 'variants.other_info.payment_type' => 'sanitize_text_field',
268 'variants.other_info.times' => 'sanitize_text_field',
269 'variants.other_info.trial_days' => 'sanitize_text_field',
270 'variants.other_info.repeat_interval' => 'sanitize_text_field',
271 'variants.other_info.billing_summary' => 'sanitize_text_field',
272 'variants.other_info.manage_setup_fee' => 'sanitize_text_field',
273 'variants.other_info.signup_fee' => 'floatval',
274 'variants.other_info.signup_fee_name' => 'sanitize_text_field',
275 'variants.other_info.package_slug' => 'sanitize_text_field',
276 'variants.other_info.weight' => 'floatval',
277 'variants.other_info.weight_unit' => 'sanitize_text_field',
278 'variants.other_info.length' => 'floatval',
279 'variants.other_info.width' => 'floatval',
280 'variants.other_info.height' => 'floatval',
281 'variants.other_info.tax_class' => 'sanitize_text_field',
282 'variants.other_info.tax_exempt' => 'sanitize_text_field',
283 //'variants.other_info.purchasable' => 'sanitize_text_field',
284 ];
285
286 }
287 }
288