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/Helpers/CouponHelper.php +61 -5 1.3.20 → 1.6.5 View file →
@@ -299,16 +299,72 @@
299 299 ];
300 300
301 301 }
302 302
303 + /**
304 + * Coupon restriction lists live inside the JSON `conditions` column. The model accessor
305 + * decodes them to arrays, but rows written before that accessor existed can still hold a
306 + * JSON string, so accept both shapes.
307 + *
308 + * @param mixed $value
309 + * @return array
310 + */
311 + protected static function normalizeConditionList($value): array
312 + {
313 + if (is_array($value)) {
314 + return array_values($value);
315 + }
316 +
317 + if (is_string($value) && $value !== '') {
318 + $decoded = json_decode($value, true);
319 + return is_array($decoded) ? array_values($decoded) : [];
320 + }
321 +
322 + return [];
323 + }
324 +
303 325 public static function checkProductEligibility($productId, $couponCode, $origin)
304 326 {
305 327 $coupon = static::getQuery()->where('code', $couponCode)->first();
306 - $excludedCategories = json_decode(Arr::get($coupon, 'excluded_categories', '[]'), true) ?? [];
307 - $includedCategories = json_decode(Arr::get($coupon, 'included_categories', '[]'), true) ?? [];
308 - $excludedProducts = json_decode(Arr::get($coupon, 'excluded_products', '[]'), true) ?? [];
309 - $includedProducts = json_decode(Arr::get($coupon, 'included_products', '[]'), true) ?? [];
310 - $product = Product::with('wp_terms')->find($productId)->toArray();
328 +
329 + if (!$coupon) {
330 + return [
331 + 'isApplicable' => false,
332 + 'message' => __('This coupon is no longer available.', 'fluent-cart'),
333 + ];
334 + }
335 +
336 + $productModel = Product::with('wp_terms')->find($productId);
337 +
338 + if (!$productModel) {
339 + return [
340 + 'isApplicable' => false,
341 + 'message' => __('Product not found.', 'fluent-cart'),
342 + ];
343 + }
344 +
345 + return static::evaluateProductEligibility($productModel, $coupon);
346 + }
347 +
348 + /**
349 + * Verdict for one already-loaded product/coupon pair, so a caller checking several
350 + * coupons at once hydrates the product and the coupon rows a single time.
351 + *
352 + * @param \FluentCart\App\Models\Product $productModel
353 + * @param \FluentCart\App\Models\Coupon $coupon
354 + * @return array
355 + */
356 + public static function evaluateProductEligibility($productModel, $coupon): array
357 + {
358 + $productId = $productModel->getKey();
359 + $couponCode = $coupon->code;
360 + $conditions = $coupon->conditions;
361 + $excludedCategories = static::normalizeConditionList(Arr::get($conditions, 'excluded_categories'));
362 + $includedCategories = static::normalizeConditionList(Arr::get($conditions, 'included_categories'));
363 + $excludedProducts = static::normalizeConditionList(Arr::get($conditions, 'excluded_products'));
364 + $includedProducts = static::normalizeConditionList(Arr::get($conditions, 'included_products'));
365 +
366 + $product = $productModel->toArray();
311 367
312 368 $productCategories = array_map(function ($productCategories) {
313 369 return $productCategories['term_taxonomy_id'];
314 370 }, $product['wp_terms']);