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.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
← All changes | app/Helpers/Helper.php +286 -119 1.5.5 → 1.6.5 View file →
@@ -11,8 +11,9 @@
11 11 use FluentCart\App\Models\Customer;
12 12 use FluentCart\App\Models\ProductVariation;
13 13 use FluentCart\App\Models\User;
14 14 use FluentCart\App\Services\DateTime\DateTime;
15 +use FluentCart\App\Services\Payments\PaymentHelper;
15 16 use FluentCart\App\Services\Localization\LocalizationManager;
16 17 use FluentCart\App\Services\Translations\TransStrings;
17 18 use FluentCart\App\Services\URL;
18 19 use FluentCart\Framework\Http\URL as BaseUrl;
@@ -67,8 +68,46 @@
67 68 return $id;
68 69
69 70 }
70 71
72 + /**
73 + * Build a spec-compliant "Upgrade to Pro" URL.
74 + *
75 + * Follows the shared Fluent* UTM spec:
76 + * utm_source = fluent-cart (fixed vocabulary, never the wp.org slug)
77 + * utm_medium = free_plugin | pro_plugin (acquisition vs cross-sell)
78 + * utm_campaign= upgrade_pro (override for xsell_<target> / license_*)
79 + * utm_content = the exact placement, e.g. feature_lock_advanced_inventory
80 + * utm_term = plugin version that generated the link
81 + * utm_id = promo id, blank normally (omit unless passed)
82 + *
83 + * @param string $content The utm_content placement.
84 + * @param array $overrides Override any utm_* param (e.g. utm_campaign for cross-sell).
85 + * @return string
86 + */
87 + public static function getUpgradeUrl($content = 'upgrade_page', $overrides = []): string
88 + {
89 + $baseUrl = (string) apply_filters(
90 + 'fluent_cart/pro_upgrade_base_url',
91 + 'https://fluentcart.com/discount-deal/'
92 + );
93 +
94 + $params = wp_parse_args($overrides, [
95 + 'utm_source' => 'fluent-cart',
96 + 'utm_medium' => App::isProActive() ? 'pro_plugin' : 'free_plugin',
97 + 'utm_campaign' => 'upgrade_pro',
98 + 'utm_content' => $content,
99 + 'utm_term' => defined('FLUENTCART_VERSION') ? FLUENTCART_VERSION : '',
100 + ]);
101 +
102 + // Drop any blank params (e.g. an unset utm_id) so they never hit the URL.
103 + $params = array_filter($params, function ($value) {
104 + return $value !== '' && $value !== null;
105 + });
106 +
107 + return add_query_arg($params, $baseUrl);
108 + }
109 +
71 110 public static function getRestInfo()
72 111 {
73 112 $app = App::getInstance();
74 113
@@ -240,17 +279,15 @@
240 279 }
241 280
242 281 public static function getOrderStatuses()
243 282 {
244 - $statuses = apply_filters_deprecated('fluent-cart/order_statuses', [
245 - [
246 - 'on-hold' => __('On Hold', 'fluent-cart'),
247 - 'processing' => __('Processing', 'fluent-cart'),
248 - 'completed' => __('Completed', 'fluent-cart'),
249 - //'archived' => __('Archived', 'fluent-cart'),
250 - 'cancelled' => __('Cancelled', 'fluent-cart'),
251 - ], []
252 - ], '1.3.16', 'fluent_cart/order_statuses', 'Use fluent_cart/order_statuses instead of fluent-cart/order_statuses. It will be removed in v1.4.3.');
283 + $statuses = [
284 + 'on-hold' => __('On Hold', 'fluent-cart'),
285 + 'processing' => __('Processing', 'fluent-cart'),
286 + 'completed' => __('Completed', 'fluent-cart'),
287 + //'archived' => __('Archived', 'fluent-cart'),
288 + 'cancelled' => __('Cancelled', 'fluent-cart'),
289 + ];
253 290
254 291 return apply_filters('fluent_cart/order_statuses', $statuses, []);
255 292 }
256 293
@@ -255,17 +292,15 @@
255 292 }
256 293
257 294 public static function getEditableOrderStatuses()
258 295 {
259 - $statuses = apply_filters_deprecated('fluent-cart/editable_order_statuses', [
260 - [
261 - 'on-hold' => __('On Hold', 'fluent-cart'),
262 - 'processing' => __('Processing', 'fluent-cart'),
263 - 'completed' => __('Completed', 'fluent-cart'),
264 - // 'archived' => __('Archived', 'fluent-cart'),
265 - 'cancelled' => __('Cancelled', 'fluent-cart')
266 - ], []
267 - ], '1.3.16', 'fluent_cart/editable_order_statuses', 'Use fluent_cart/editable_order_statuses instead of fluent-cart/editable_order_statuses. It will be removed in v1.4.3.');
296 + $statuses = [
297 + 'on-hold' => __('On Hold', 'fluent-cart'),
298 + 'processing' => __('Processing', 'fluent-cart'),
299 + 'completed' => __('Completed', 'fluent-cart'),
300 + // 'archived' => __('Archived', 'fluent-cart'),
301 + 'cancelled' => __('Cancelled', 'fluent-cart')
302 + ];
268 303
269 304 return apply_filters('fluent_cart/editable_order_statuses', $statuses, []);
270 305 }
271 306
@@ -270,14 +305,12 @@
270 305 }
271 306
272 307 public static function getEditableCustomerStatuses()
273 308 {
274 - $statuses = apply_filters_deprecated('fluent-cart/editable_customer_statuses', [
275 - [
276 - 'active' => __('Active', 'fluent-cart'),
277 - 'inactive' => __('Inactive', 'fluent-cart'),
278 - ], []
279 - ], '1.3.16', 'fluent_cart/editable_customer_statuses', 'Use fluent_cart/editable_customer_statuses instead of fluent-cart/editable_customer_statuses. It will be removed in v1.4.3.');
309 + $statuses = [
310 + 'active' => __('Active', 'fluent-cart'),
311 + 'inactive' => __('Inactive', 'fluent-cart'),
312 + ];
280 313
281 314 return apply_filters('fluent_cart/editable_customer_statuses', $statuses, []);
282 315 }
283 316
@@ -282,16 +315,14 @@
282 315 }
283 316
284 317 public static function getShippingStatuses()
285 318 {
286 - $statuses = apply_filters_deprecated('fluent-cart/shipping_statuses', [
287 - [
288 - 'unshipped' => __('Unshipped', 'fluent-cart'),
289 - 'shipped' => __('Shipped', 'fluent-cart'),
290 - 'delivered' => __('Delivered', 'fluent-cart'),
291 - 'unshippable' => __('Unshippable', 'fluent-cart'),
292 - ], []
293 - ], '1.3.16', 'fluent_cart/shipping_statuses', 'Use fluent_cart/shipping_statuses instead of fluent-cart/shipping_statuses. It will be removed in v1.4.3.');
319 + $statuses = [
320 + 'unshipped' => __('Unshipped', 'fluent-cart'),
321 + 'shipped' => __('Shipped', 'fluent-cart'),
322 + 'delivered' => __('Delivered', 'fluent-cart'),
323 + 'unshippable' => __('Unshippable', 'fluent-cart'),
324 + ];
294 325
295 326 return apply_filters('fluent_cart/shipping_statuses', $statuses, []);
296 327 }
297 328
@@ -296,16 +327,14 @@
296 327 }
297 328
298 329 public static function getEditableShippingStatuses()
299 330 {
300 - $statuses = apply_filters_deprecated('fluent-cart/editable_order_statuses', [
301 - [
302 - 'unshipped' => __('Unshipped', 'fluent-cart'),
303 - 'shipped' => __('Shipped', 'fluent-cart'),
304 - 'delivered' => __('Delivered', 'fluent-cart'),
305 - 'unshippable' => __('Unshippable', 'fluent-cart'),
306 - ], []
307 - ], '1.3.16', 'fluent_cart/editable_shipping_statuses', 'Use fluent_cart/editable_shipping_statuses instead of fluent-cart/editable_order_statuses. It will be removed in v1.4.3.');
331 + $statuses = [
332 + 'unshipped' => __('Unshipped', 'fluent-cart'),
333 + 'shipped' => __('Shipped', 'fluent-cart'),
334 + 'delivered' => __('Delivered', 'fluent-cart'),
335 + 'unshippable' => __('Unshippable', 'fluent-cart'),
336 + ];
308 337
309 338 return apply_filters('fluent_cart/editable_shipping_statuses', $statuses, []);
310 339 }
311 340
@@ -335,18 +364,16 @@
335 364 }
336 365
337 366 public static function getTransactionStatuses($withLabel = true)
338 367 {
339 - $statuses = apply_filters_deprecated('fluent-cart/transaction_statuses', [
340 - [
341 - 'pending' => __('Pending', 'fluent-cart'),
342 - 'paid' => __('Paid', 'fluent-cart'),
343 - 'require_capture' => __('Authorized (Require Capture)', 'fluent-cart'),
344 - 'failed' => __('Failed', 'fluent-cart'),
345 - 'refunded' => __('Refunded', 'fluent-cart'),
346 - 'active' => __('Active', 'fluent-cart'),
347 - ], []
348 - ], '1.3.16', 'fluent_cart/transaction_statuses', 'Use fluent_cart/transaction_statuses instead of fluent-cart/transaction_statuses. It will be removed in v1.4.3.');
368 + $statuses = [
369 + 'pending' => __('Pending', 'fluent-cart'),
370 + 'paid' => __('Paid', 'fluent-cart'),
371 + 'require_capture' => __('Authorized (Require Capture)', 'fluent-cart'),
372 + 'failed' => __('Failed', 'fluent-cart'),
373 + 'refunded' => __('Refunded', 'fluent-cart'),
374 + 'active' => __('Active', 'fluent-cart'),
375 + ];
349 376
350 377 $statuses = apply_filters('fluent_cart/transaction_statuses', $statuses, []);
351 378
352 379 if ($withLabel) {
@@ -357,16 +384,14 @@
357 384 }
358 385
359 386 public static function getEditableTransactionStatuses($withLabel = true)
360 387 {
361 - $statuses = apply_filters_deprecated('fluent-cart/editable_transaction_statuses', [
362 - [
363 - 'pending' => __('Pending', 'fluent-cart'),
364 - 'paid' => __('Paid', 'fluent-cart'),
365 - 'failed' => __('Failed', 'fluent-cart'),
366 - 'refunded' => __('Refunded', 'fluent-cart'),
367 - ], []
368 - ], '1.3.16', 'fluent_cart/editable_transaction_statuses', 'Use fluent_cart/editable_transaction_statuses instead of fluent-cart/editable_transaction_statuses. It will be removed in v1.4.3.');
388 + $statuses = [
389 + 'pending' => __('Pending', 'fluent-cart'),
390 + 'paid' => __('Paid', 'fluent-cart'),
391 + 'failed' => __('Failed', 'fluent-cart'),
392 + 'refunded' => __('Refunded', 'fluent-cart'),
393 + ];
369 394
370 395 $statuses = apply_filters('fluent_cart/editable_transaction_statuses', $statuses, []);
371 396
372 397 if ($withLabel) {
@@ -375,21 +400,8 @@
375 400
376 401 return array_keys($statuses);
377 402 }
378 403
379 - public static function loadSpoutLib()
380 - {
381 - static $loaded;
382 -
383 - if ($loaded) {
384 - return $loaded;
385 - }
386 -
387 - require_once FLUENTCART_PLUGIN_PATH . 'app/Services/Libs/Spout/Autoloader/autoload.php';
388 -
389 - return true;
390 - }
391 -
392 404 public static function productStatuses($withLabel = true): array
393 405 {
394 406 $statues = [
395 407 'publish' => __('Publish', 'fluent-cart'),
@@ -540,8 +552,41 @@
540 552 $amount = (int)round($amount); // Round to nearest integer, then cast
541 553 return $amount;
542 554 }
543 555
556 + /**
557 + * Normalize a value that is ALREADY in cents to a whole-cent int.
558 + *
559 + * Unlike toCent(), this does not scale — use it when the incoming value is a
560 + * cents amount that may have arrived as a float. Clients computing cents in
561 + * JavaScript send artifacts like 1998.9999999999998 for 1999, and a bare
562 + * (int) cast truncates those, silently undercharging by a cent. Non-numeric
563 + * input (including the null the request pipeline injects for omitted keys)
564 + * normalizes to 0.
565 + *
566 + * Magnitudes beyond float's exact-integer range (2^53) are REJECTED, not
567 + * coerced: is_numeric() accepts exponential notation like 1e19, and casting
568 + * that float to int wraps to -8446744073709551616 — a VALID signed BIGINT —
569 + * so the corrupt value would persist silently where an un-normalized float
570 + * used to fail loudly at MySQL. No real cents amount approaches this bound.
571 + */
572 + public static function roundCent($amount): int
573 + {
574 + if (!is_numeric($amount)) {
575 + return 0;
576 + }
577 +
578 + $amount = (float) $amount;
579 +
580 + if (!is_finite($amount) || $amount > 9.0e15 || $amount < -9.0e15) {
581 + throw new \InvalidArgumentException(
582 + 'Value is out of the representable cents range: ' . var_export($amount, true)
583 + );
584 + }
585 +
586 + return (int) round($amount);
587 + }
588 +
544 589 public static function toDecimalWithoutComma($amount)
545 590 {
546 591
547 592 if (!is_numeric($amount)) {
@@ -564,10 +609,12 @@
564 609 if (!$user) {
565 610 return null;
566 611 }
567 612
613 + // Identity only — see CustomerResource::getCurrentCustomer() for why an
614 + // email match must never reach a customer row.
568 615 return Customer::query()->where('user_id', $user->ID)
569 - ->orWhere('email', $user->user_email)
616 + ->orderBy('id', 'ASC')
570 617 ->first();
571 618 }
572 619
573 620 /**
@@ -595,27 +642,25 @@
595 642 }
596 643
597 644 public static function getAvailableCurrencyList()
598 645 {
599 - $currencies = apply_filters_deprecated('fluent-cart/available_currencies', [
600 - [
601 - 'BDT' => [
602 - "label" => __('Bangladeshi Taka', 'fluent-cart'),
603 - "value" => 'BDT',
604 - "symbol" => '৳',
605 - ],
606 - 'USD' => [
607 - "label" => __('United State Dollar', 'fluent-cart'),
608 - "value" => 'USD',
609 - "symbol" => '$',
610 - ],
611 - 'GBP' => [
612 - "label" => __('United Kingdom', 'fluent-cart'),
613 - "value" => 'GBP',
614 - "symbol" => '£',
615 - ],
616 - ], []
617 - ], '1.3.16', 'fluent_cart/available_currencies', 'Use fluent_cart/available_currencies instead of fluent-cart/available_currencies. It will be removed in v1.4.3.');
646 + $currencies = [
647 + 'BDT' => [
648 + "label" => __('Bangladeshi Taka', 'fluent-cart'),
649 + "value" => 'BDT',
650 + "symbol" => '৳',
651 + ],
652 + 'USD' => [
653 + "label" => __('United State Dollar', 'fluent-cart'),
654 + "value" => 'USD',
655 + "symbol" => '$',
656 + ],
657 + 'GBP' => [
658 + "label" => __('United Kingdom', 'fluent-cart'),
659 + "value" => 'GBP',
660 + "symbol" => '£',
661 + ],
662 + ];
618 663
619 664 return apply_filters('fluent_cart/available_currencies', $currencies, []);
620 665 }
621 666
@@ -962,15 +1007,13 @@
962 1007 }
963 1008
964 1009 public static function getCouponStatuses()
965 1010 {
966 - $statuses = apply_filters_deprecated('fluent-cart/coupon_statuses', [
967 - [
968 - 'active' => __('Active', 'fluent-cart'),
969 - 'expired' => __('Expired', 'fluent-cart'),
970 - 'disabled' => __('Disabled', 'fluent-cart'),
971 - ], []
972 - ], '1.3.16', 'fluent_cart/coupon_statuses', 'Use fluent_cart/coupon_statuses instead of fluent-cart/coupon_statuses. It will be removed in v1.4.3.');
1011 + $statuses = [
1012 + 'active' => __('Active', 'fluent-cart'),
1013 + 'expired' => __('Expired', 'fluent-cart'),
1014 + 'disabled' => __('Disabled', 'fluent-cart'),
1015 + ];
973 1016
974 1017 return apply_filters('fluent_cart/coupon_statuses', $statuses, []);
975 1018 }
976 1019
@@ -1236,8 +1279,150 @@
1236 1279
1237 1280 return !empty($otherInfo) ? $paymentInfo : null;
1238 1281 }
1239 1282
1283 + /**
1284 + * Billing-cycle text for a subscription with a config-defined schedule
1285 + * (see SubscriptionHelper::getBillingSchedule()) — cadences the
1286 + * billing_interval enum cannot express, e.g. "$100 per 3 years on Aug 19".
1287 + * Subscriptions without a schedule keep generateSubscriptionInfo().
1288 + */
1289 + public static function generateScheduleSubscriptionInfo(array $schedule, $otherInfo, $itemPrice, $currencyCode = null): ?string
1290 + {
1291 + if (is_object($otherInfo)) {
1292 + $otherInfo = json_decode(json_encode($otherInfo), true);
1293 + }
1294 +
1295 + $count = max(1, (int) Arr::get($schedule, 'interval', 1));
1296 +
1297 + switch (Arr::get($schedule, 'period')) {
1298 + case 'day':
1299 + $unitLabel = _n('day', 'days', $count, 'fluent-cart');
1300 + break;
1301 + case 'week':
1302 + $unitLabel = _n('week', 'weeks', $count, 'fluent-cart');
1303 + break;
1304 + case 'month':
1305 + $unitLabel = _n('month', 'months', $count, 'fluent-cart');
1306 + break;
1307 + case 'year':
1308 + $unitLabel = _n('year', 'years', $count, 'fluent-cart');
1309 + break;
1310 + default:
1311 + return self::generateSubscriptionInfo($otherInfo, $itemPrice, $currencyCode);
1312 + }
1313 +
1314 + $price = self::toDecimal($itemPrice, true, $currencyCode);
1315 + $recurringDiscountAmount = Arr::get($otherInfo, 'recurring_discounts.amount', 0);
1316 +
1317 + if ($recurringDiscountAmount) {
1318 + $newRecurringAmount = $itemPrice - $recurringDiscountAmount;
1319 + $price = "<del>" . $price . "</del> " . self::toDecimal($newRecurringAmount, true, $currencyCode);
1320 + }
1321 +
1322 + $interval = $count === 1
1323 + ? sprintf(
1324 + /* translators: %s is the interval unit (e.g., day, week, month, year) */
1325 + __('per %s', 'fluent-cart'),
1326 + $unitLabel
1327 + )
1328 + : sprintf(
1329 + /* translators: %1$d is the count number, %2$s is the plural unit name (e.g., days, months, years) */
1330 + __('per %1$d %2$s', 'fluent-cart'),
1331 + $count,
1332 + $unitLabel
1333 + );
1334 +
1335 + if ($anchorText = self::getScheduleAnchorText($schedule['period'], Arr::get($schedule, 'anchor', []))) {
1336 + $interval .= ' ' . $anchorText;
1337 + }
1338 +
1339 + $occurrence = (int) Arr::get($otherInfo, 'times', 0);
1340 +
1341 + if (empty($occurrence)) {
1342 + return sprintf(
1343 + /* translators: %1$s is the price, %2$s is the interval, %3$s is "until cancel" text */
1344 + __('%1$s %2$s %3$s', 'fluent-cart'),
1345 + $price,
1346 + $interval,
1347 + __('until cancel', 'fluent-cart')
1348 + );
1349 + }
1350 +
1351 + return sprintf(
1352 + /* translators: %1$s is the price, %2$s is the interval, %3$s is the occurrence count, %4$s is "cycle(s)" */
1353 + __('%1$s %2$s, for %3$s %4$s', 'fluent-cart'),
1354 + $price,
1355 + $interval,
1356 + $occurrence,
1357 + _n('cycle', 'cycles', $occurrence, 'fluent-cart')
1358 + );
1359 + }
1360 +
1361 + /**
1362 + * Human-readable billing anchor, e.g. "on Friday", "on the 10th",
1363 + * "on the last day", "on Aug 19". Anchor day 31 encodes "last day of
1364 + * the month" (see SubscriptionHelper::getBillingSchedule()).
1365 + */
1366 + private static function getScheduleAnchorText(string $period, $anchor): string
1367 + {
1368 + if (!is_array($anchor) || !$anchor) {
1369 + return '';
1370 + }
1371 +
1372 + if ($period === 'week' && !empty($anchor['weekday'])) {
1373 + $weekdays = [
1374 + 1 => __('Monday', 'fluent-cart'),
1375 + 2 => __('Tuesday', 'fluent-cart'),
1376 + 3 => __('Wednesday', 'fluent-cart'),
1377 + 4 => __('Thursday', 'fluent-cart'),
1378 + 5 => __('Friday', 'fluent-cart'),
1379 + 6 => __('Saturday', 'fluent-cart'),
1380 + 7 => __('Sunday', 'fluent-cart'),
1381 + ];
1382 +
1383 + if (isset($weekdays[$anchor['weekday']])) {
1384 + /* translators: %s is a weekday name, e.g. "on Friday" */
1385 + return sprintf(__('on %s', 'fluent-cart'), $weekdays[$anchor['weekday']]);
1386 + }
1387 +
1388 + return '';
1389 + }
1390 +
1391 + if ($period === 'month' && !empty($anchor['day'])) {
1392 + $day = (int) $anchor['day'];
1393 +
1394 + if ($day === 31) {
1395 + return __('on the last day', 'fluent-cart');
1396 + }
1397 +
1398 + /* translators: %s is an ordinal day of month, e.g. "on the 10th" */
1399 + return sprintf(__('on the %s', 'fluent-cart'), gmdate('jS', gmmktime(12, 0, 0, 1, $day, 2001)));
1400 + }
1401 +
1402 + if ($period === 'year' && (!empty($anchor['day']) || !empty($anchor['month']))) {
1403 + $day = (int) Arr::get($anchor, 'day', 0);
1404 + $month = (int) Arr::get($anchor, 'month', 0);
1405 +
1406 + if ($month && $day) {
1407 + /* translators: %s is a date, e.g. "on Aug 19" */
1408 + // wp_date(), not gmdate(): gmdate() has no locale, so this month
1409 + // name stayed English inside an otherwise translated sentence.
1410 + return sprintf(__('on %s', 'fluent-cart'), wp_date('M', gmmktime(12, 0, 0, $month, 1, 2001), new \DateTimeZone('UTC')) . ' ' . $day);
1411 + }
1412 +
1413 + if ($month) {
1414 + /* translators: %s is a month name, e.g. "in August" */
1415 + return sprintf(__('in %s', 'fluent-cart'), wp_date('F', gmmktime(12, 0, 0, $month, 1, 2001), new \DateTimeZone('UTC')));
1416 + }
1417 +
1418 + /* translators: %s is an ordinal day of month, e.g. "on the 10th" */
1419 + return sprintf(__('on the %s', 'fluent-cart'), gmdate('jS', gmmktime(12, 0, 0, 1, $day, 2001)));
1420 + }
1421 +
1422 + return '';
1423 + }
1424 +
1240 1425 public static function generateSetupFeeInfo($otherInfo, $asArray = false)
1241 1426 {
1242 1427 // Convert to array if it's an object
1243 1428 if (is_object($otherInfo)) {
@@ -1302,9 +1487,8 @@
1302 1487
1303 1488 public static function getCountryList(): array
1304 1489 {
1305 1490 $options = App::getInstance('localization')->countriesOptions();
1306 - $options = apply_filters_deprecated('fluent-cart/util/countries', [$options, []], '1.3.16', 'fluent_cart/util/countries', 'Use fluent_cart/util/countries instead of fluent-cart/util/countries. It will be removed in v1.4.3.');
1307 1491
1308 1492 return apply_filters('fluent_cart/util/countries', $options, []);
1309 1493 }
1310 1494
@@ -1744,26 +1928,9 @@
1744 1928 }
1745 1929
1746 1930 public static function subscriptionIntervalInDays($interval)
1747 1931 {
1748 - switch ($interval) {
1749 - case 'daily':
1750 - return 1;
1751 - case 'weekly':
1752 - return 7;
1753 - case 'monthly':
1754 - return 30;
1755 - case 'quarterly':
1756 - return 90;
1757 - case 'half_yearly':
1758 - return 182;
1759 - case 'yearly':
1760 - return 365;
1761 - default:
1762 - return apply_filters('fluent_cart/subscription_interval_in_days', 0, [
1763 - 'interval' => $interval,
1764 - ]);
1765 - }
1932 + return PaymentHelper::getIntervalDays($interval);
1766 1933 }
1767 1934
1768 1935 public static function parseTermIdsForFilter($filters): array
1769 1936 {
@@ -1818,12 +1985,12 @@
1818 1985 {
1819 1986 $allChildVariants = Arr::pluck($variants, 'other_info.bundle_child_ids');
1820 1987
1821 1988 $allChildVariants = array_unique(Arr::flatten($allChildVariants));
1822 - $allChildVariants = Arr::except(
1989 + $allChildVariants = array_values(array_diff(
1823 1990 $allChildVariants,
1824 1991 Arr::pluck($variants, 'id')
1825 - );
1992 + ));
1826 1993 $allChildVariants = array_filter($allChildVariants);
1827 1994 $childVariants = ProductVariation::query()
1828 1995 ->whereIn('id', $allChildVariants)
1829 1996 ->with('product:ID,post_title')