1
|
|
|
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('No direct script access allowed'); } |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
* Class EE_Cron_Tasks |
5
|
|
|
* |
6
|
|
|
* @package Event Espresso |
7
|
|
|
* @subpackage core |
8
|
|
|
* @author Brent Christensen |
9
|
|
|
* |
10
|
|
|
*/ |
11
|
|
|
class EE_Cron_Tasks extends EE_BASE { |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* WordPress doesn't allow duplicate crons within 10 minutes of the original, |
15
|
|
|
* so we'll set our retry time for just over 10 minutes to avoid that |
16
|
|
|
*/ |
17
|
|
|
const reschedule_timeout = 605; |
18
|
|
|
|
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var EE_Cron_Tasks |
22
|
|
|
*/ |
23
|
|
|
private static $_instance; |
24
|
|
|
|
25
|
|
|
|
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @return EE_Cron_Tasks |
29
|
|
|
*/ |
30
|
|
|
public static function instance() { |
31
|
|
|
if ( ! self::$_instance instanceof EE_Cron_Tasks ) { |
32
|
|
|
self::$_instance = new self(); |
33
|
|
|
} |
34
|
|
|
return self::$_instance; |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
|
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @access private |
41
|
|
|
* @return EE_Cron_Tasks |
|
|
|
|
42
|
|
|
*/ |
43
|
|
|
private function __construct() { |
44
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__ ); |
45
|
|
|
// verify that WP Cron is enabled |
46
|
|
|
if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON && is_admin() ) { |
47
|
|
|
EE_Error::add_persistent_admin_notice( |
48
|
|
|
'wp_cron_disabled', |
49
|
|
|
sprintf( |
50
|
|
|
__( |
51
|
|
|
'Event Espresso has detected that wp_cron is disabled. It\'s important that wp_cron is enabled because Event Espresso depends on wp_cron for critical scheduled tasks.%1$sSince it\'s possible that your site may have an alternative task scheduler set up, we strongly suggest that you inform the website host, or developer that set up the site, about this issue.', |
52
|
|
|
'event_espresso' |
53
|
|
|
), |
54
|
|
|
'<br />' |
55
|
|
|
) |
56
|
|
|
); |
57
|
|
|
} |
58
|
|
|
// UPDATE TRANSACTION WITH PAYMENT |
59
|
|
|
add_action( |
60
|
|
|
'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2', |
61
|
|
|
array( 'EE_Cron_Tasks', 'setup_update_for_transaction_with_payment' ), |
62
|
|
|
10, 2 |
63
|
|
|
); |
64
|
|
|
// FINALIZE ABANDONED TRANSACTIONS |
65
|
|
|
add_action( |
66
|
|
|
'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions', |
67
|
|
|
array( 'EE_Cron_Tasks', 'check_for_abandoned_transactions' ), |
68
|
|
|
10, 1 |
69
|
|
|
); |
70
|
|
|
// CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA |
71
|
|
|
add_action( |
72
|
|
|
'AHEE__EE_Cron_Tasks__clean_up_junk_transactions', |
73
|
|
|
array( 'EE_Cron_Tasks', 'clean_out_junk_transactions' ) |
74
|
|
|
); |
75
|
|
|
// logging |
76
|
|
|
add_action( |
77
|
|
|
'AHEE__EE_System__load_core_configuration__complete', |
78
|
|
|
array( 'EE_Cron_Tasks', 'log_scheduled_ee_crons' ) |
79
|
|
|
); |
80
|
|
|
EE_Registry::instance()->load_lib( 'Messages_Scheduler' ); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
|
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* @access protected |
87
|
|
|
* @return void |
88
|
|
|
*/ |
89
|
|
|
public static function log_scheduled_ee_crons() { |
90
|
|
|
$ee_crons = array( |
91
|
|
|
'AHEE__EE_Cron_Tasks__update_transaction_with_payment', |
92
|
|
|
'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions', |
93
|
|
|
'AHEE__EE_Cron_Tasks__clean_up_junk_transactions', |
94
|
|
|
); |
95
|
|
|
$crons = get_option( 'cron' ); |
96
|
|
|
if ( ! is_array( $crons ) ) { |
97
|
|
|
return; |
98
|
|
|
} |
99
|
|
|
foreach ( $crons as $timestamp => $cron ) { |
100
|
|
|
foreach ( $ee_crons as $ee_cron ) { |
101
|
|
|
if ( isset( $cron[ $ee_cron ] ) ) { |
102
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron' ); |
103
|
|
|
foreach ( $cron[ $ee_cron ] as $ee_cron_details ) { |
104
|
|
|
if ( ! empty( $ee_cron_details[ 'args' ] )) { |
105
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__, print_r( $ee_cron_details[ 'args' ], true ), "$ee_cron args" ); |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
|
114
|
|
|
|
115
|
|
|
|
116
|
|
|
/**************** UPDATE TRANSACTION WITH PAYMENT ****************/ |
117
|
|
|
|
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* array of TXN IDs and the payment |
121
|
|
|
* @var array |
122
|
|
|
*/ |
123
|
|
|
protected static $_update_transactions_with_payment = array(); |
124
|
|
|
|
125
|
|
|
|
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* schedule_update_transaction_with_payment |
129
|
|
|
* |
130
|
|
|
* sets a wp_schedule_single_event() for updating any TXNs that may |
131
|
|
|
* require updating due to recently received payments |
132
|
|
|
* |
133
|
|
|
* @param int $timestamp |
134
|
|
|
* @param int $TXN_ID |
135
|
|
|
* @param int $PAY_ID |
136
|
|
|
*/ |
137
|
|
View Code Duplication |
public static function schedule_update_transaction_with_payment( |
|
|
|
|
138
|
|
|
$timestamp, |
139
|
|
|
$TXN_ID, |
140
|
|
|
$PAY_ID |
141
|
|
|
) { |
142
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__ ); |
143
|
|
|
// validate $TXN_ID and $timestamp |
144
|
|
|
$TXN_ID = absint( $TXN_ID ); |
145
|
|
|
$timestamp = absint( $timestamp ); |
146
|
|
|
if ( $TXN_ID && $timestamp ) { |
147
|
|
|
wp_schedule_single_event( |
148
|
|
|
$timestamp, |
149
|
|
|
'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2', |
150
|
|
|
array( $TXN_ID, $PAY_ID ) |
151
|
|
|
); |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
|
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* setup_update_for_transaction_with_payment |
159
|
|
|
* |
160
|
|
|
* this is the callback for the action hook: |
161
|
|
|
* 'AHEE__EE_Cron_Tasks__update_transaction_with_payment' |
162
|
|
|
* which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment(). |
163
|
|
|
* The passed TXN_ID and associated payment gets added to an array, and then |
164
|
|
|
* the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into |
165
|
|
|
* 'shutdown' which will actually handle the processing of any |
166
|
|
|
* transactions requiring updating, because doing so now would be too early |
167
|
|
|
* and the required resources may not be available |
168
|
|
|
* |
169
|
|
|
* @param int $TXN_ID |
170
|
|
|
* @param int $PAY_ID |
171
|
|
|
*/ |
172
|
|
View Code Duplication |
public static function setup_update_for_transaction_with_payment( $TXN_ID = 0, $PAY_ID = 0 ) { |
|
|
|
|
173
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID' ); |
174
|
|
|
if ( absint( $TXN_ID )) { |
175
|
|
|
self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID; |
176
|
|
|
add_action( |
177
|
|
|
'shutdown', |
178
|
|
|
array( 'EE_Cron_Tasks', 'update_transaction_with_payment' ), |
179
|
|
|
5 |
180
|
|
|
); |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
|
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* update_transaction_with_payment |
188
|
|
|
* |
189
|
|
|
* loops through the self::$_abandoned_transactions array |
190
|
|
|
* and attempts to finalize any TXNs that have not been completed |
191
|
|
|
* but have had their sessions expired, most likely due to a user not |
192
|
|
|
* returning from an off-site payment gateway |
193
|
|
|
* |
194
|
|
|
* @throws \EE_Error |
195
|
|
|
*/ |
196
|
|
|
public static function update_transaction_with_payment() { |
197
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__ ); |
198
|
|
|
// are there any TXNs that need cleaning up ? |
199
|
|
|
if ( ! empty( self::$_update_transactions_with_payment ) ) { |
200
|
|
|
/** @type EE_Payment_Processor $payment_processor */ |
201
|
|
|
$payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); |
202
|
|
|
// set revisit flag for payment processor |
203
|
|
|
$payment_processor->set_revisit( false ); |
204
|
|
|
// load EEM_Transaction |
205
|
|
|
EE_Registry::instance()->load_model( 'Transaction' ); |
206
|
|
|
foreach ( self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID ) { |
207
|
|
|
// reschedule the cron if we can't hit the db right now |
208
|
|
|
if ( ! EE_Maintenance_Mode::instance()->models_can_query() ) { |
209
|
|
|
// reset cron job for updating the TXN |
210
|
|
|
EE_Cron_Tasks::schedule_update_transaction_with_payment( |
211
|
|
|
time() + EE_Cron_Tasks::reschedule_timeout, |
212
|
|
|
$TXN_ID, |
213
|
|
|
$PAY_ID |
214
|
|
|
); |
215
|
|
|
continue; |
216
|
|
|
} |
217
|
|
|
$transaction = EEM_Transaction::instance()->get_one_by_ID( $TXN_ID ); |
218
|
|
|
$payment = EEM_Payment::instance()->get_one_by_ID( $PAY_ID ); |
219
|
|
|
// verify transaction |
220
|
|
|
if ( $transaction instanceof EE_Transaction && $payment instanceof EE_Payment ) { |
221
|
|
|
// now try to update the TXN with any payments |
222
|
|
|
$payment_processor->update_txn_based_on_payment( $transaction, $payment, true, true ); |
223
|
|
|
} |
224
|
|
|
unset( self::$_update_transactions_with_payment[ $TXN_ID ] ); |
225
|
|
|
} |
226
|
|
|
} |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
|
230
|
|
|
|
231
|
|
|
/************ END OF UPDATE TRANSACTION WITH PAYMENT ************/ |
232
|
|
|
|
233
|
|
|
|
234
|
|
|
|
235
|
|
|
/***************** FINALIZE ABANDONED TRANSACTIONS *****************/ |
236
|
|
|
|
237
|
|
|
|
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* array of TXN IDs |
241
|
|
|
* @var array |
242
|
|
|
*/ |
243
|
|
|
protected static $_abandoned_transactions = array(); |
244
|
|
|
|
245
|
|
|
|
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* schedule_finalize_abandoned_transactions_check |
249
|
|
|
* |
250
|
|
|
* sets a wp_schedule_single_event() for finalizing any TXNs that may |
251
|
|
|
* have been abandoned during the registration process |
252
|
|
|
* |
253
|
|
|
* @param int $timestamp |
254
|
|
|
* @param int $TXN_ID |
255
|
|
|
*/ |
256
|
|
View Code Duplication |
public static function schedule_finalize_abandoned_transactions_check( |
|
|
|
|
257
|
|
|
$timestamp, |
258
|
|
|
$TXN_ID |
259
|
|
|
) { |
260
|
|
|
// validate $TXN_ID and $timestamp |
261
|
|
|
$TXN_ID = absint( $TXN_ID ); |
262
|
|
|
$timestamp = absint( $timestamp ); |
263
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID' ); |
264
|
|
|
if ( $TXN_ID && $timestamp ) { |
265
|
|
|
wp_schedule_single_event( |
266
|
|
|
$timestamp, |
267
|
|
|
'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions', |
268
|
|
|
array( $TXN_ID ) |
269
|
|
|
); |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
|
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* check_for_abandoned_transactions |
277
|
|
|
* |
278
|
|
|
* this is the callback for the action hook: |
279
|
|
|
* 'AHEE__EE_Cron_Tasks__espresso_finalize_abandoned_transactions' |
280
|
|
|
* which is utilized by wp_schedule_single_event() |
281
|
|
|
* in EE_SPCO_Reg_Step_Payment_Options::_post_payment_processing(). |
282
|
|
|
* The passed TXN_ID gets added to an array, and then the |
283
|
|
|
* espresso_finalize_abandoned_transactions() function is hooked into |
284
|
|
|
* 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the |
285
|
|
|
* processing of any abandoned transactions, because doing so now would be |
286
|
|
|
* too early and the required resources may not be available |
287
|
|
|
* |
288
|
|
|
* @param int $TXN_ID |
289
|
|
|
*/ |
290
|
|
View Code Duplication |
public static function check_for_abandoned_transactions( $TXN_ID = 0 ) { |
|
|
|
|
291
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID' ); |
292
|
|
|
if ( absint( $TXN_ID )) { |
293
|
|
|
self::$_abandoned_transactions[] = $TXN_ID; |
294
|
|
|
add_action( |
295
|
|
|
'shutdown', |
296
|
|
|
array( 'EE_Cron_Tasks', 'finalize_abandoned_transactions' ), |
297
|
|
|
5 |
298
|
|
|
); |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
|
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* finalize_abandoned_transactions |
306
|
|
|
|
307
|
|
|
* loops through the self::$_abandoned_transactions array |
308
|
|
|
* and attempts to finalize any TXNs that have not been completed |
309
|
|
|
* but have had their sessions expired, most likely due to a user not |
310
|
|
|
* returning from an off-site payment gateway |
311
|
|
|
* |
312
|
|
|
* @throws \EE_Error |
313
|
|
|
*/ |
314
|
|
|
public static function finalize_abandoned_transactions() { |
315
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__ ); |
316
|
|
|
// are there any TXNs that need cleaning up ? |
317
|
|
|
if ( ! empty( self::$_abandoned_transactions ) ) { |
318
|
|
|
/** @type EE_Transaction_Processor $transaction_processor */ |
319
|
|
|
$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' ); |
320
|
|
|
// set revisit flag for txn processor |
321
|
|
|
$transaction_processor->set_revisit( false ); |
322
|
|
|
/** @type EE_Payment_Processor $payment_processor */ |
323
|
|
|
$payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); |
324
|
|
|
// load EEM_Transaction |
325
|
|
|
EE_Registry::instance()->load_model( 'Transaction' ); |
326
|
|
|
foreach ( self::$_abandoned_transactions as $TXN_ID ) { |
327
|
|
|
do_action( 'AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID' ); |
328
|
|
|
// reschedule the cron if we can't hit the db right now |
329
|
|
|
if ( ! EE_Maintenance_Mode::instance()->models_can_query() ) { |
330
|
|
|
// reset cron job for finalizing the TXN |
331
|
|
|
EE_Cron_Tasks::schedule_finalize_abandoned_transactions_check( |
332
|
|
|
time() + EE_Cron_Tasks::reschedule_timeout, |
333
|
|
|
$TXN_ID |
334
|
|
|
); |
335
|
|
|
continue; |
336
|
|
|
} |
337
|
|
|
$transaction = EEM_Transaction::instance()->get_one_by_ID( $TXN_ID ); |
338
|
|
|
// verify transaction |
339
|
|
|
if ( $transaction instanceof EE_Transaction ) { |
340
|
|
|
// don't finalize the TXN if it has already been completed |
341
|
|
|
if ( $transaction_processor->all_reg_steps_completed( $transaction ) === true ) { |
342
|
|
|
continue; |
343
|
|
|
} |
344
|
|
|
// let's simulate an IPN here which will trigger any notifications that need to go out |
345
|
|
|
$payment_processor->update_txn_based_on_payment( $transaction, $transaction->last_payment(), true, true ); |
346
|
|
|
} |
347
|
|
|
unset( self::$_abandoned_transactions[ $TXN_ID ] ); |
348
|
|
|
} |
349
|
|
|
} |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
|
353
|
|
|
|
354
|
|
|
/************* END OF FINALIZE ABANDONED TRANSACTIONS *************/ |
355
|
|
|
|
356
|
|
|
|
357
|
|
|
|
358
|
|
|
/************* START CLEAN UP BOT TRANSACTIONS **********************/ |
359
|
|
|
|
360
|
|
|
//when a transaction is initially made, schedule this check. |
361
|
|
|
//if it has NO REG data by the time it has expired, forget about it |
362
|
|
|
public static function clean_out_junk_transactions() { |
363
|
|
|
if( EE_Maintenance_Mode::instance()->models_can_query() ) { |
364
|
|
|
EEM_Transaction::instance('')->delete_junk_transactions(); |
365
|
|
|
EEM_Registration::instance('')->delete_registrations_with_no_transaction(); |
366
|
|
|
EEM_Line_Item::instance('')->delete_line_items_with_no_transaction(); |
367
|
|
|
} |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
|
371
|
|
|
} |
372
|
|
|
// End of file EE_Cron_Tasks.core.php |
373
|
|
|
// Location: /EE_Cron_Tasks.core.php |
374
|
|
|
|
Adding a
@return
annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.Please refer to the PHP core documentation on constructors.