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 / Modules / Subscriptions / Services / SubscriptionManagementMode.php

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

176 lines 5.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\Modules\Subscriptions\Services;
4
5 use FluentCart\App\App;
6 use FluentCart\App\Helpers\CartHelper;
7 use FluentCart\App\Models\Order;
8 use FluentCart\App\Models\Subscription;
9 use FluentCart\Framework\Support\Arr;
10
11 /**
12 * Store-level choice of WHO manages subscription renewals: gateway_managed
13 * (default, pre-feature behavior) vs store_managed (manual invoicing, no
14 * vendor subscriptions). Stamped into a subscription at checkout, so changing
15 * the setting later never mutates existing subscriptions.
16 */
17 class SubscriptionManagementMode
18 {
19 const SETTING_KEY = 'subscription_management_mode';
20 const GATEWAY_MANAGED = 'gateway_managed';
21 const STORE_MANAGED = 'store_managed';
22
23 /** Store setting: auto-charge renewal invoices under store-managed mode (collection_method `system`)? */
24 const SYSTEM_CHARGE_KEY = 'subscription_system_charge';
25
26 /** Store setting: under gateway-managed mode, also admit gateways without native subscription support? */
27 const MANUAL_FALLBACK_KEY = 'subscription_manual_fallback';
28
29 /** Config key stamped at checkout — the durable per-subscription record of the mode it was born under. */
30 const CONFIG_KEY = 'management_mode';
31
32 public static function getMode(): string
33 {
34 $mode = App::storeSettings()->get(self::SETTING_KEY, self::GATEWAY_MANAGED);
35
36 $mode = apply_filters('fluent_cart/subscription/management_mode', $mode);
37
38 // Whitelist — any unexpected stored/filtered value reads as the safe default.
39 return $mode === self::STORE_MANAGED ? self::STORE_MANAGED : self::GATEWAY_MANAGED;
40 }
41
42 public static function isStoreManaged(): bool
43 {
44 return self::getMode() === self::STORE_MANAGED;
45 }
46
47 public static function isSystemChargeEnabled(): bool
48 {
49 if (!self::isStoreManaged()) {
50 return false;
51 }
52
53 $enabled = App::storeSettings()->get(self::SYSTEM_CHARGE_KEY, 'no') === 'yes';
54
55 return (bool) apply_filters('fluent_cart/subscriptions/system_collection_enabled', $enabled);
56 }
57
58 public static function isManualFallbackEnabled(): bool
59 {
60 if (self::isStoreManaged()) {
61 return false;
62 }
63
64 return App::storeSettings()->get(self::MANUAL_FALLBACK_KEY, 'no') === 'yes';
65 }
66
67 public static function resolveCollectionMethodFor($gateway): string
68 {
69 if (self::isSystemChargeEnabled() && $gateway && $gateway->has('system_subscription')) {
70 return 'system';
71 }
72
73 return 'manual';
74 }
75
76 /**
77 * `system` may only be stored on a gateway that can actually charge it — guards
78 * the `fluent_cart/subscription_collection_method_{gateway}` filter's return value.
79 */
80 public static function sanitizeCollectionMethod($method, $gateway): string
81 {
82 if (!in_array($method, ['automatic', 'manual', 'system'], true)) {
83 return 'manual';
84 }
85
86 if ($method === 'system' && !($gateway && $gateway->has('system_subscription'))) {
87 return 'manual';
88 }
89
90 return $method;
91 }
92
93 public static function isSubscriptionStoreManaged($subscription): bool
94 {
95 if (!$subscription) {
96 return false;
97 }
98
99 $config = $subscription->config;
100
101 return is_array($config) && Arr::get($config, self::CONFIG_KEY) === self::STORE_MANAGED;
102 }
103
104 /**
105 * A renewal/reactivation cart resolves via the existing subscription's
106 * collection_method; only a new subscription cart reads the store setting.
107 */
108 public static function currentCheckoutIsSystem($gateway): bool
109 {
110 $cart = CartHelper::getCart();
111 if (!$cart || !$cart->hasSubscription()) {
112 return false;
113 }
114
115 $subscription = self::resolveRenewalSubscription($cart)
116 ?: self::resolveReactivationSubscription($cart);
117
118 if ($subscription) {
119 return $subscription->collection_method === 'system';
120 }
121
122 return self::isSystemChargeEnabled() && $gateway && $gateway->has('system_subscription');
123 }
124
125 /**
126 * Mirrors AbstractPaymentGateway::shouldChargeSubscriptionAsOneTime() so the
127 * client payment UI matches what makePaymentFromPaymentInstance will do.
128 */
129 public static function currentCheckoutChargesOneTime(): bool
130 {
131 $cart = CartHelper::getCart();
132
133 $subscription = self::resolveRenewalSubscription($cart)
134 ?: self::resolveReactivationSubscription($cart);
135
136 if ($subscription) {
137 if (!in_array($subscription->collection_method, ['manual', 'system'], true)) {
138 return false;
139 }
140
141 return self::isSubscriptionStoreManaged($subscription) || self::isStoreManaged();
142 }
143
144 return self::isStoreManaged();
145 }
146
147 public static function resolveRenewalSubscription($cart)
148 {
149 if (!$cart || !$cart->order_id || !Arr::get((array) $cart->checkout_data, 'renewal_order')) {
150 return null;
151 }
152
153 $order = Order::query()->find($cart->order_id);
154 if (!$order || !$order->parent_id) {
155 return null;
156 }
157
158 return Subscription::query()->where('parent_order_id', $order->parent_id)->first();
159 }
160
161 /** Reads `renew_data.subscription_hash`, set by fluent-cart-pro's instant-cart builder. */
162 public static function resolveReactivationSubscription($cart)
163 {
164 if (!$cart) {
165 return null;
166 }
167
168 $hash = Arr::get((array) $cart->checkout_data, 'renew_data.subscription_hash');
169 if (!$hash) {
170 return null;
171 }
172
173 return Subscription::query()->where('uuid', $hash)->first();
174 }
175 }
176