PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.6.0
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.6.0
3.6.0 3.5.3 3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / includes / traits / trait-evf-subscription-schedule-choices.php
everest-forms / includes / traits Last commit date
trait-evf-subscription-schedule-choices.php 2 months ago
trait-evf-subscription-schedule-choices.php
216 lines
1 <?php
2 /**
3 * Shared trial/expiry parsing and proration helpers for gateway subscription schedules.
4 *
5 * Used by Stripe, PayPal Standard, Authorize.Net, Mollie, and Square schedule builders.
6 *
7 * @package EverestForms\Traits
8 * @since 3.4.8
9 */
10
11 defined( 'ABSPATH' ) || exit;
12
13 /**
14 * Subscription plan choice settings shared across payment gateways.
15 */
16 trait EVF_Subscription_Schedule_Choices {
17
18 /**
19 * Parse trial/expiry settings from a plan choice row.
20 *
21 * @since 3.4.8
22 *
23 * @param array $choice Plan choice from form_fields.
24 * @return array
25 */
26 public static function parse_choice_settings( $choice ) {
27 $choice = is_array( $choice ) ? $choice : array();
28
29 $trial_enabled = isset( $choice['trail_period_enable'] ) && evf_string_to_bool( $choice['trail_period_enable'] );
30
31 $expiry_enabled = isset( $choice['subscription_expiry_enable'] ) && evf_string_to_bool( $choice['subscription_expiry_enable'] );
32 if ( ! $expiry_enabled && ! empty( $choice['subscription_expiry_date'] ) ) {
33 $expiry_enabled = true;
34 }
35
36 $settings = array(
37 'plan_amount' => isset( $choice['value'] ) ? (float) evf_sanitize_amount( $choice['value'] ) : 0,
38 'period' => isset( $choice['recurring_period'] ) ? sanitize_key( (string) $choice['recurring_period'] ) : 'month',
39 'interval_count' => isset( $choice['interval_count'] ) ? max( 1, absint( $choice['interval_count'] ) ) : 1,
40 'trial_enabled' => $trial_enabled,
41 'expiry_enabled' => $expiry_enabled,
42 'expiry_date' => isset( $choice['subscription_expiry_date'] ) ? sanitize_text_field( $choice['subscription_expiry_date'] ) : '',
43 );
44
45 if ( $trial_enabled ) {
46 $settings['trial_period'] = isset( $choice['trail_recurring_period'] ) ? sanitize_text_field( $choice['trail_recurring_period'] ) : 'week';
47 $settings['trial_interval_count'] = isset( $choice['trail_interval_count'] ) ? max( 1, absint( $choice['trail_interval_count'] ) ) : 1;
48 }
49
50 return $settings;
51 }
52
53 /**
54 * Normalize EVF recurring period.
55 *
56 * @since 3.4.8
57 *
58 * @param string $period Raw period.
59 * @return string day|week|month|year
60 */
61 public static function normalize_period( $period ) {
62 $period = sanitize_key( (string) $period );
63 $aliases = array(
64 'daily' => 'day',
65 'weekly' => 'week',
66 'monthly' => 'month',
67 'yearly' => 'year',
68 'days' => 'day',
69 'weeks' => 'week',
70 'months' => 'month',
71 'years' => 'year',
72 );
73
74 if ( isset( $aliases[ $period ] ) ) {
75 return $aliases[ $period ];
76 }
77
78 if ( in_array( $period, array( 'day', 'week', 'month', 'year' ), true ) ) {
79 return $period;
80 }
81
82 return 'month';
83 }
84
85 /**
86 * End of expiry date as unix timestamp.
87 *
88 * @since 3.4.8
89 *
90 * @param string $expiry_date Y-m-d.
91 * @return int|null
92 */
93 public static function expiry_end_timestamp( $expiry_date ) {
94 if ( empty( $expiry_date ) ) {
95 return null;
96 }
97
98 $timestamp = strtotime( $expiry_date . ' 23:59:59' );
99
100 return $timestamp ? $timestamp : null;
101 }
102
103 /**
104 * Billing period length in seconds.
105 *
106 * @since 3.4.8
107 *
108 * @param string $period day|week|month|year.
109 * @param int $interval_count Interval multiplier.
110 * @return int
111 */
112 public static function billing_period_seconds( $period, $interval_count ) {
113 $interval_count = max( 1, absint( $interval_count ) );
114 $period = self::normalize_period( $period );
115
116 switch ( $period ) {
117 case 'day':
118 return DAY_IN_SECONDS * $interval_count;
119 case 'week':
120 return WEEK_IN_SECONDS * $interval_count;
121 case 'year':
122 return YEAR_IN_SECONDS * $interval_count;
123 case 'month':
124 default:
125 return MONTH_IN_SECONDS * $interval_count;
126 }
127 }
128
129 /**
130 * Trial end unix timestamp.
131 *
132 * @since 3.4.8
133 *
134 * @param array $settings Parsed settings.
135 * @return int|null
136 */
137 public static function trial_end_timestamp( $settings ) {
138 if ( empty( $settings['trial_enabled'] ) ) {
139 return null;
140 }
141
142 $period = self::normalize_period( isset( $settings['trial_period'] ) ? $settings['trial_period'] : 'week' );
143 $count = isset( $settings['trial_interval_count'] ) ? max( 1, absint( $settings['trial_interval_count'] ) ) : 1;
144 $ts = strtotime( '+' . $count . ' ' . $period );
145
146 if ( ! $ts || $ts <= time() + 60 ) {
147 $ts = time() + DAY_IN_SECONDS;
148 }
149
150 return $ts;
151 }
152
153 /**
154 * Unix timestamp when paid billing begins (after trial when applicable).
155 *
156 * @since 3.4.8
157 *
158 * @param array $settings Parsed settings.
159 * @return int
160 */
161 public static function billing_start_timestamp( $settings ) {
162 if ( ! empty( $settings['trial_enabled'] ) ) {
163 $trial_end = self::trial_end_timestamp( $settings );
164
165 return $trial_end ? $trial_end : time();
166 }
167
168 return time();
169 }
170
171 /**
172 * Whether the paid billing window through expiry fits within one plan period.
173 *
174 * @since 3.4.8
175 *
176 * @param int $billing_start_ts Billing start (after trial when applicable).
177 * @param int $expiry_end_ts Expiry end of day.
178 * @param string $period day|week|month|year.
179 * @param int $interval_count Interval count.
180 * @return bool
181 */
182 public static function is_short_billing_window( $billing_start_ts, $expiry_end_ts, $period, $interval_count ) {
183 if ( $expiry_end_ts <= $billing_start_ts ) {
184 return false;
185 }
186
187 $period_seconds = self::billing_period_seconds( $period, $interval_count );
188 $window = $expiry_end_ts - $billing_start_ts;
189
190 return $window <= $period_seconds;
191 }
192
193 /**
194 * Prorated amount for billing window through expiry (after trial when applicable).
195 *
196 * @since 3.4.8
197 *
198 * @param float $plan_amount Plan amount per period.
199 * @param int $billing_start_ts Billing start.
200 * @param int $expiry_end_ts Expiry end.
201 * @param string $period day|week|month|year.
202 * @param int $interval_count Interval count.
203 * @return float|null
204 */
205 public static function calculate_prorated_amount( $plan_amount, $billing_start_ts, $expiry_end_ts, $period, $interval_count ) {
206 if ( $plan_amount <= 0 || $expiry_end_ts <= $billing_start_ts ) {
207 return null;
208 }
209
210 $period_seconds = self::billing_period_seconds( $period, $interval_count );
211 $window = $expiry_end_ts - $billing_start_ts;
212
213 return ( $window / $period_seconds ) * $plan_amount;
214 }
215 }
216