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

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

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