PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.22.3
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.22.3
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 / square / controllers / FrmSquareLiteEventsController.php

FrmSquareLiteEventsController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.22.3, at square/controllers/FrmSquareLiteEventsController.php

289 lines 7.3 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 class FrmSquareLiteEventsController {
7
8 /**
9 * @var string
10 */
11 public static $events_to_skip_option_name = 'frm_square_events_to_skip';
12
13 private $event;
14
15 /**
16 * Tell Square Connect API that the request came through by flushing early before processing.
17 * Flushing early allows the API to end the request earlier.
18 *
19 * @since 6.22
20 *
21 * @return void
22 */
23 private function flush_response() {
24 ob_start();
25
26 // Get the size of the output.
27 $size = ob_get_length();
28
29 // Disable compression (in case content length is compressed).
30 header( 'Content-Encoding: none' );
31
32 // Set the content length of the response.
33 header( 'Content-Length: ' . $size );
34
35 // Close the connection.
36 header( 'Connection: close' );
37
38 // Flush all output.
39 ob_end_flush();
40 @ob_flush();
41 flush();
42 }
43
44 /**
45 * @return void
46 */
47 public function process_events() {
48 $this->flush_response();
49
50 $unprocessed_event_ids = FrmSquareLiteConnectHelper::get_unprocessed_event_ids();
51
52 if ( $unprocessed_event_ids ) {
53 $this->process_event_ids( $unprocessed_event_ids );
54 }
55 wp_send_json_success();
56 }
57
58 /**
59 * @since 6.22
60 *
61 * @param array<string> $event_ids
62 * @return void
63 */
64 private function process_event_ids( $event_ids ) {
65 foreach ( $event_ids as $event_id ) {
66 if ( $this->should_skip_event( $event_id ) ) {
67 continue;
68 }
69
70 set_transient( 'frm_square_last_process_' . $event_id, time(), 60 );
71
72 $this->event = FrmSquareLiteConnectHelper::get_event( $event_id );
73
74 if ( is_object( $this->event ) ) {
75 $this->handle_event();
76 $this->track_handled_event( $event_id );
77 FrmSquareLiteConnectHelper::process_event( $event_id );
78 } else {
79 $this->count_failed_event( $event_id );
80 }
81 }
82 }
83
84 /**
85 * @since 6.22
86 *
87 * @param string $event_id
88 * @return bool True if the event should be skipped.
89 */
90 private function should_skip_event( $event_id ) {
91 if ( $this->last_attempt_to_process_event_is_too_recent( $event_id ) ) {
92 return true;
93 }
94
95 $option = get_option( self::$events_to_skip_option_name );
96 if ( ! is_array( $option ) ) {
97 return false;
98 }
99
100 return in_array( $event_id, $option, true );
101 }
102
103 /**
104 * @param string $event_id
105 * @return bool
106 */
107 private function last_attempt_to_process_event_is_too_recent( $event_id ) {
108 $last_process_attempt = get_transient( 'frm_square_last_process_' . $event_id );
109 return is_numeric( $last_process_attempt ) && $last_process_attempt > time() - 60;
110 }
111
112 /**
113 * @since 6.22
114 *
115 * @param string $event_id
116 * @return void
117 */
118 private function count_failed_event( $event_id ) {
119 $transient_name = 'frm_square_failed_event_' . $event_id;
120 $transient = get_transient( $transient_name );
121 if ( is_int( $transient ) ) {
122 $failed_count = $transient + 1;
123 } else {
124 $failed_count = 1;
125 }
126
127 $maximum_retries = 3;
128 if ( $failed_count >= $maximum_retries ) {
129 $this->track_handled_event( $event_id );
130 } else {
131 set_transient( $transient_name, $failed_count, 4 * DAY_IN_SECONDS );
132 }
133 }
134
135 /**
136 * Track an event to no longer process.
137 * This is called for successful events, and also for failed events after a number of retries.
138 *
139 * @since 6.22
140 *
141 * @param string $event_id
142 * @return void
143 */
144 private function track_handled_event( $event_id ) {
145 $option = get_option( self::$events_to_skip_option_name );
146
147 if ( is_array( $option ) ) {
148 if ( count( $option ) > 1000 ) {
149 // Prevent the option from getting too big by removing the front item before adding the next.
150 array_shift( $option );
151 }
152 } else {
153 $option = array();
154 }
155
156 $option[] = $event_id;
157 update_option( self::$events_to_skip_option_name, $option, false );
158 }
159
160 /**
161 * @return void
162 */
163 private function handle_event() {
164 switch ( $this->event->type ) {
165 case 'payment.created':
166 $payment_id = $this->event->data->id;
167 $subscription = FrmSquareLiteConnectHelper::get_subscription_id_for_payment( $payment_id );
168
169 if ( is_object( $subscription ) && isset( $subscription->id ) ) {
170 $subscription_id = $subscription->id;
171 $this->add_subscription_payment( $subscription_id );
172 }
173 break;
174 case 'payment.updated':
175 $payment_id = $this->event->data->id;
176 $frm_payment = new FrmTransLitePayment();
177 $payment = $frm_payment->get_one_by( $payment_id, 'receipt_id' );
178
179 if ( $payment ) {
180 $status = $this->event->data->object->payment->status;
181
182 if ( 'COMPLETED' === $status && 'complete' !== $payment->status ) {
183 $payment_values = (array) $payment;
184 $payment_values['status'] = 'complete';
185
186 $frm_payment->update( $payment->id, $payment_values );
187
188 FrmTransLiteActionsController::trigger_payment_status_change(
189 array(
190 'status' => 'complete',
191 'payment' => $payment,
192 )
193 );
194 }
195 return;
196 }
197 break;
198 case 'subscription.updated':
199 $subscription_id = $this->event->data->id;
200 $frm_sub = new FrmTransLiteSubscription();
201 $sub = $frm_sub->get_one_by( $subscription_id, 'sub_id' );
202
203 if ( $sub ) {
204 $status = $this->event->data->object->subscription->status;
205
206 if ( 'DEACTIVATED' === $status ) {
207 $status = 'canceled';
208 FrmTransLiteSubscriptionsController::change_subscription_status(
209 array(
210 'status' => $status,
211 'sub' => $sub,
212 )
213 );
214 }
215 }
216 break;
217 }//end switch
218 }
219
220 /**
221 * Add a payment row for the payments table.
222 *
223 * @param string $subscription_id The Square ID for the current subscription.
224 * @return void
225 */
226 private function add_subscription_payment( $subscription_id ) {
227 $payment_id = $this->event->data->id;
228
229 $frm_payment = new FrmTransLitePayment();
230 $payment = $frm_payment->get_one_by( $payment_id, 'receipt_id' );
231
232 if ( $payment ) {
233 // Avoid adding the same payment twice.
234 return;
235 }
236
237 $frm_sub = new FrmTransLiteSubscription();
238 $sub = $frm_sub->get_one_by( $subscription_id, 'sub_id' );
239 if ( ! $sub ) {
240 return;
241 }
242
243 $payment_object = $this->event->data->object->payment;
244
245 if ( 'JPY' === $payment_object->amount_money->currency ) {
246 // Japanese does not include the additional 2 digits.
247 $amount = $payment_object->amount_money->amount;
248 } else {
249 $amount = number_format( floatval( $payment_object->amount_money->amount ) / 100, 2 );
250 }
251
252 $begin_date = gmdate( 'Y-m-d' );
253 $expire_date = '0000-00-00';
254 $subscription = FrmSquareLiteConnectHelper::get_subscription( $sub->sub_id );
255
256 if ( is_object( $subscription ) ) {
257 if ( ! empty( $subscription->start_date ) ) {
258 $begin_date = gmdate( 'Y-m-d', strtotime( $subscription->start_date ) );
259 }
260
261 if ( ! empty( $subscription->charged_through_date ) ) {
262 $expire_date = gmdate( 'Y-m-d', strtotime( $subscription->charged_through_date ) );
263
264 $frm_sub->update(
265 $sub->id,
266 array( 'next_bill_date' => gmdate( 'Y-m-d', strtotime( $expire_date ) ) )
267 );
268 }
269 }
270
271
272 $frm_payment = new FrmTransLitePayment();
273 $frm_payment->create(
274 array(
275 'paysys' => 'square',
276 'amount' => $amount,
277 'status' => 'authorized',
278 'item_id' => $sub->item_id,
279 'action_id' => $sub->action_id,
280 'receipt_id' => $payment_id,
281 'sub_id' => $sub->id,
282 'test' => 'test' === FrmSquareLiteAppHelper::active_mode() ? 1 : 0,
283 'begin_date' => $begin_date,
284 'expire_date' => $expire_date,
285 )
286 );
287 }
288 }
289