PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / stripe / helpers / FrmStrpLiteSubscriptionHelper.php

FrmStrpLiteSubscriptionHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More trunk, at stripe/helpers/FrmStrpLiteSubscriptionHelper.php

260 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 /**
7 * Handles shared Stripe subscription logic between FrmStrpLiteActionsController and FrmStrpLiteLinkController.
8 *
9 * @since 6.5, introduced in v3.0 of the Stripe add on.
10 */
11 class FrmStrpLiteSubscriptionHelper {
12
13 /**
14 * Prepare a charge object for a Stripe subscription.
15 *
16 * @since 6.5, introduced in v3.0 of the Stripe add on.
17 *
18 * @param object $subscription A Stripe Subscription object.
19 * @param string $amount
20 *
21 * @return stdClass
22 */
23 public static function prepare_charge_object_for_subscription( $subscription, $amount ) {
24 $charge_object = new stdClass();
25 $charge_object->sub_id = $subscription->id;
26 $charge_object->id = null;
27 $charge_object->amount = $amount;
28 $charge_object->current_period_start = $subscription->current_period_start;
29 $charge_object->current_period_end = $subscription->current_period_end;
30 return $charge_object;
31 }
32
33 /**
34 * Create a Formidable subscription object with the nested payments submodule.
35 *
36 * @since 6.5
37 *
38 * @param array $atts
39 *
40 * @return int|string Sub ID.
41 */
42 public static function create_new_subscription( $atts ) {
43 $atts['charge'] = (object) $atts['charge'];
44
45 $new_values = array(
46 'amount' => FrmTransLiteAppHelper::get_formatted_amount_for_currency( $atts['charge']->amount, $atts['action'] ),
47 'paysys' => 'stripe',
48 'item_id' => $atts['entry']->id,
49 'action_id' => $atts['action']->ID,
50 'sub_id' => $atts['charge']->sub_id ?? '',
51 'interval_count' => $atts['action']->post_content['interval_count'],
52 'time_interval' => $atts['action']->post_content['interval'],
53 'status' => 'active',
54 'next_bill_date' => gmdate( 'Y-m-d' ),
55 'test' => 'test' === FrmStrpLiteAppHelper::active_mode() ? 1 : 0,
56 );
57
58 if ( ! empty( $atts['action']->post_content['payment_limit'] ) ) {
59 $end_count = self::prepare_payment_limit(
60 $atts['action']->post_content['payment_limit'],
61 (int) $atts['entry']->form_id,
62 (int) $atts['entry']->id
63 );
64
65 if ( is_int( $end_count ) ) {
66 $new_values['end_count'] = $end_count;
67 }
68 }
69
70 $frm_sub = new FrmTransLiteSubscription();
71 return $frm_sub->create( $new_values );
72 }
73
74 /**
75 * Get a plan for Stripe subscription.
76 *
77 * @since 6.5, introduced in v3.0 of the Stripe add on.
78 *
79 * @param array $atts {
80 * The plan details.
81 *
82 * @type WP_Post $action
83 * @type string $amount
84 * }
85 *
86 * @return false|string Plan id.
87 */
88 public static function get_plan_from_atts( $atts ) {
89 $action = $atts['action'];
90 $action->post_content['amount'] = $atts['amount'];
91 return self::get_plan_for_action( $action );
92 }
93
94 /**
95 * @since 6.5
96 *
97 * @param WP_Post $action
98 *
99 * @return false|string
100 */
101 private static function get_plan_for_action( $action ) {
102 $plan_id = $action->post_content['plan_id'];
103
104 if ( $plan_id ) {
105 return $plan_id;
106 }
107
108 // The amount has already been formatted, so add the decimal back in.
109 $amount = $action->post_content['amount'];
110 $action->post_content['amount'] = number_format( $amount / 100, 2, '.', '' );
111 $plan_opts = self::prepare_plan_options( $action->post_content );
112 return self::maybe_create_plan( $plan_opts );
113 }
114
115 /**
116 * @since 6.5
117 *
118 * @param array $settings
119 *
120 * @return array
121 */
122 public static function prepare_plan_options( $settings ) {
123 $amount = FrmStrpLiteActionsController::prepare_amount( $settings['amount'], $settings );
124 $default_description = number_format( $amount / 100, 2 ) . '/' . $settings['interval'];
125 $plan_opts = array(
126 'amount' => $amount,
127 'interval' => $settings['interval'],
128 'interval_count' => $settings['interval_count'],
129 'currency' => $settings['currency'],
130 'name' => ! empty( $settings['description'] ) ? $settings['description'] : $default_description,
131 );
132
133 if ( ! empty( $settings['trial_interval_count'] ) ) {
134 $plan_opts['trial_period_days'] = self::get_trial_with_default( $settings['trial_interval_count'] );
135 }
136
137 $plan_opts['id'] = FrmStrpLiteActionsController::create_plan_id( $settings );
138
139 return $plan_opts;
140 }
141
142 /**
143 * @since 3.0 This was moved from FrmStrpLiteActionsController.
144 *
145 * @param array $plan
146 *
147 * @return mixed
148 */
149 public static function maybe_create_plan( $plan ) {
150 return FrmStrpLiteAppHelper::call_stripe_helper_class( 'maybe_create_plan', $plan );
151 }
152
153 /**
154 * Since the trial period can come from an entry, use a default value
155 * when creating the plan. This is overridden when the subscription
156 * is created.
157 *
158 * @since 6.5
159 *
160 * @param mixed $trial
161 *
162 * @return int
163 */
164 private static function get_trial_with_default( $trial ) {
165 if ( ! is_numeric( $trial ) ) {
166 // Use 0 as this is only ever overwritten when it is non-zero.
167 $trial = 0;
168 }
169 return absint( $trial );
170 }
171
172 /**
173 * If a subscription fails because the plan does not exist, create the plan and try again.
174 *
175 * @since 6.5.1
176 *
177 * @param false|object|string $subscription
178 * @param array $charge_data
179 * @param WP_Post $action
180 * @param int $amount
181 *
182 * @return false|object|string
183 */
184 public static function maybe_create_missing_plan_and_create_subscription( $subscription, $charge_data, $action, $amount ) {
185 if ( ! is_string( $subscription ) || ! str_starts_with( $subscription, 'No such plan: ' ) ) {
186 // Only retry when there is a No such plan string error.
187 return $subscription;
188 }
189
190 // The full error message looks like "No such plan: '_399_1month_usd".
191 $action->post_content['plan_id'] = '';
192 $charge_data['plan'] = self::get_plan_from_atts( compact( 'action', 'amount' ) );
193 return FrmStrpLiteAppHelper::call_stripe_helper_class( 'create_subscription', $charge_data );
194 }
195
196 /**
197 * When this is filtered and returns false, the subscription will be canceled immediately instead.
198 *
199 * @since 6.8
200 *
201 * @return bool
202 */
203 public static function should_cancel_at_period_end() {
204 /**
205 * @param bool $cancel_at_period_end
206 */
207 return (bool) apply_filters( 'frm_stripe_cancel_subscription_at_period_end', true );
208 }
209
210 /**
211 * Get an end_count value to use for our subscription.
212 *
213 * @since 6.11
214 *
215 * @param string $payment_limit The raw payment value string. It is not empty.
216 * @param int $form_id Required for processing shortcodes.
217 * @param int $entry_id Required for processing shortcodes.
218 *
219 * @return int|WP_Error
220 */
221 public static function prepare_payment_limit( $payment_limit, $form_id, $entry_id ) {
222 if ( is_numeric( $payment_limit ) ) {
223 return (int) $payment_limit;
224 }
225
226 if ( ! str_contains( $payment_limit, '[' ) ) {
227 return self::get_invalid_payment_limit_error( $payment_limit );
228 }
229
230 $payment_limit = FrmTransLiteAppHelper::process_shortcodes(
231 array(
232 'value' => $payment_limit,
233 'form' => $form_id,
234 'entry' => $entry_id,
235 )
236 );
237
238 if ( ! is_numeric( $payment_limit ) ) {
239 return self::get_invalid_payment_limit_error( $payment_limit );
240 }
241
242 return (int) $payment_limit;
243 }
244
245 /**
246 * @since 6.11
247 *
248 * @param string $payment_limit
249 *
250 * @return WP_Error
251 */
252 private static function get_invalid_payment_limit_error( $payment_limit ) {
253 return new WP_Error(
254 'invalid_payment_limit',
255 /* translators: %s: Invalid payment limit value title */
256 sprintf( __( 'Invalid payment limit value %s', 'formidable' ), $payment_limit )
257 );
258 }
259 }
260