Completed
Branch BUG/add-limits-to-cron-queries (332e37)
by
unknown
08:43 queued 50s
created
core/db_models/EEM_Message.model.php 1 patch
Indentation   +617 added lines, -617 removed lines patch added patch discarded remove patch
@@ -9,628 +9,628 @@
 block discarded – undo
9 9
 class EEM_Message extends EEM_Base implements EEI_Query_Filter
10 10
 {
11 11
 
12
-    // private instance of the Message object
13
-    protected static $_instance = null;
12
+	// private instance of the Message object
13
+	protected static $_instance = null;
14 14
 
15 15
 
16
-    /**
17
-     * This priority indicates a message should be generated and sent ASAP
18
-     *
19
-     * @type int
20
-     */
21
-    const priority_high = 10;
22
-
23
-
24
-    /**
25
-     * This priority indicates a message should be generated ASAP and queued for sending.
26
-     *
27
-     * @type
28
-     */
29
-    const priority_medium = 20;
30
-
31
-
32
-    /**
33
-     * This priority indicates a message should be queued for generating.
34
-     *
35
-     * @type int
36
-     */
37
-    const priority_low = 30;
38
-
39
-
40
-    /**
41
-     * indicates this message was sent at the time modified
42
-     */
43
-    const status_sent = 'MSN';
44
-
45
-
46
-    /**
47
-     * indicates this message is waiting to be sent
48
-     */
49
-    const status_idle = 'MID';
50
-
51
-
52
-    /**
53
-     * indicates an attempt was a made to send this message
54
-     * at the scheduled time, but it failed at the time modified.  This differs from MDO status in that it will ALWAYS
55
-     * appear to the end user.
56
-     */
57
-    const status_failed = 'MFL';
58
-
59
-
60
-    /**
61
-     * indicates the message has been flagged for resending (at the time modified).
62
-     */
63
-    const status_resend = 'MRS';
64
-
65
-
66
-    /**
67
-     * indicates the message has been flagged for generation but has not been generated yet.  Messages always start as
68
-     * this status when added to the queue.
69
-     */
70
-    const status_incomplete = 'MIC';
71
-
72
-
73
-    /**
74
-     * Indicates everything was generated fine for the message, however, the messenger was unable to send.
75
-     * This status means that its possible to retry sending the message.
76
-     */
77
-    const status_retry = 'MRT';
78
-
79
-
80
-    /**
81
-     * This is used for more informational messages that may not indicate anything is broken but still cannot be
82
-     * generated or sent correctly. An example of a message that would get flagged this way would be when a not
83
-     * approved message was queued for generation, but at time of generation, the attached registration(s) are
84
-     * approved. So the message queued for generation is no longer valid.  Messages for this status will only persist
85
-     * in the db and be viewable in the message activity list table when the messages system is in debug mode.
86
-     *
87
-     * @see EEM_Message::debug()
88
-     */
89
-    const status_debug_only = 'MDO';
90
-
91
-
92
-    /**
93
-     * This status is given to messages it is processed by the messenger send method.
94
-     * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually
95
-     * indicative of a PHP timeout or memory limit issue.
96
-     */
97
-    const status_messenger_executing = 'MEX';
98
-
99
-
100
-    /**
101
-     *    Private constructor to prevent direct creation.
102
-     *
103
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and
104
-     *                         any incoming timezone data that gets saved).  Note this just sends the timezone info to
105
-     *                         the date time model field objects.  Default is null (and will be assumed using the set
106
-     *                         timezone in the 'timezone_string' wp option)
107
-     * @return EEM_Message
108
-     */
109
-    protected function __construct($timezone = null)
110
-    {
111
-        $this->singular_item = __('Message', 'event_espresso');
112
-        $this->plural_item   = __('Messages', 'event_espresso');
113
-
114
-        // used for token generator
115
-        EE_Registry::instance()->load_helper('URL');
116
-
117
-        $this->_tables = array(
118
-            'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'),
119
-        );
120
-
121
-        $allowed_priority = array(
122
-            self::priority_high   => __('high', 'event_espresso'),
123
-            self::priority_medium => __('medium', 'event_espresso'),
124
-            self::priority_low    => __('low', 'event_espresso'),
125
-        );
126
-
127
-        $this->_fields          = array(
128
-            'Message' => array(
129
-                'MSG_ID'             => new EE_Primary_Key_Int_Field('MSG_ID', __('Message ID', 'event_espresso')),
130
-                'MSG_token'          => new EE_Plain_Text_Field(
131
-                    'MSG_token',
132
-                    __(
133
-                        'Unique Token used to represent this row in publicly viewable contexts (eg. a url).',
134
-                        'event_espresso'
135
-                    ),
136
-                    false,
137
-                    EEH_URL::generate_unique_token()
138
-                ),
139
-                'GRP_ID'             => new EE_Foreign_Key_Int_Field(
140
-                    'GRP_ID',
141
-                    __('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'),
142
-                    true,
143
-                    0,
144
-                    'Message_Template_Group'
145
-                ),
146
-                'TXN_ID'             => new EE_Foreign_Key_Int_Field(
147
-                    'TXN_ID',
148
-                    __(
149
-                        'Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message',
150
-                        'event_espresso'
151
-                    ),
152
-                    true,
153
-                    0,
154
-                    'Transaction'
155
-                ),
156
-                'MSG_messenger'      => new EE_Plain_Text_Field(
157
-                    'MSG_messenger',
158
-                    __(
159
-                        'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.',
160
-                        'event_espresso'
161
-                    ),
162
-                    false,
163
-                    'email'
164
-                ),
165
-                'MSG_message_type'   => new EE_Plain_Text_Field(
166
-                    'MSG_message_type',
167
-                    __('Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso'),
168
-                    false,
169
-                    'receipt'
170
-                ),
171
-                'MSG_context'        => new EE_Plain_Text_Field('MSG_context', __('Context', 'event_espresso'), false),
172
-                'MSG_recipient_ID'   => new EE_Foreign_Key_Int_Field(
173
-                    'MSG_recipient_ID',
174
-                    __('Recipient ID', 'event_espresso'),
175
-                    true,
176
-                    null,
177
-                    array('Registration', 'Attendee', 'WP_User')
178
-                ),
179
-                'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field(
180
-                    'MSG_recipient_type',
181
-                    __('Recipient Type', 'event_espresso'),
182
-                    true,
183
-                    null,
184
-                    array('Registration', 'Attendee', 'WP_User')
185
-                ),
186
-                'MSG_content'        => new EE_Maybe_Serialized_Text_Field(
187
-                    'MSG_content',
188
-                    __('Content', 'event_espresso'),
189
-                    true,
190
-                    ''
191
-                ),
192
-                'MSG_to'             => new EE_Maybe_Serialized_Text_Field(
193
-                    'MSG_to',
194
-                    __('Address To', 'event_espresso'),
195
-                    true
196
-                ),
197
-                'MSG_from'           => new EE_Maybe_Serialized_Text_Field(
198
-                    'MSG_from',
199
-                    __('Address From', 'event_espresso'),
200
-                    true
201
-                ),
202
-                'MSG_subject'        => new EE_Maybe_Serialized_Text_Field(
203
-                    'MSG_subject',
204
-                    __('Subject', 'event_espresso'),
205
-                    true,
206
-                    ''
207
-                ),
208
-                'MSG_priority'       => new EE_Enum_Integer_Field(
209
-                    'MSG_priority',
210
-                    __('Priority', 'event_espresso'),
211
-                    false,
212
-                    self::priority_low,
213
-                    $allowed_priority
214
-                ),
215
-                'STS_ID'             => new EE_Foreign_Key_String_Field(
216
-                    'STS_ID',
217
-                    __('Status', 'event_espresso'),
218
-                    false,
219
-                    self::status_incomplete,
220
-                    'Status'
221
-                ),
222
-                'MSG_created'        => new EE_Datetime_Field(
223
-                    'MSG_created',
224
-                    __('Created', 'event_espresso'),
225
-                    false,
226
-                    EE_Datetime_Field::now
227
-                ),
228
-                'MSG_modified'       => new EE_Datetime_Field(
229
-                    'MSG_modified',
230
-                    __('Modified', 'event_espresso'),
231
-                    true,
232
-                    EE_Datetime_Field::now
233
-                ),
234
-            ),
235
-        );
236
-        $this->_model_relations = array(
237
-            'Attendee'               => new EE_Belongs_To_Any_Relation(),
238
-            'Registration'           => new EE_Belongs_To_Any_Relation(),
239
-            'WP_User'                => new EE_Belongs_To_Any_Relation(),
240
-            'Message_Template_Group' => new EE_Belongs_To_Relation(),
241
-            'Transaction'            => new EE_Belongs_To_Relation(),
242
-        );
243
-        parent::__construct($timezone);
244
-    }
245
-
246
-
247
-    /**
248
-     * @return \EE_Message
249
-     */
250
-    public function create_default_object()
251
-    {
252
-        /** @type EE_Message $message */
253
-        $message = parent::create_default_object();
254
-        if ($message instanceof EE_Message) {
255
-            return EE_Message_Factory::set_messenger_and_message_type($message);
256
-        }
257
-        return null;
258
-    }
259
-
260
-
261
-    /**
262
-     * @param mixed $cols_n_values
263
-     * @return \EE_Message
264
-     */
265
-    public function instantiate_class_from_array_or_object($cols_n_values)
266
-    {
267
-        /** @type EE_Message $message */
268
-        $message = parent::instantiate_class_from_array_or_object($cols_n_values);
269
-        if ($message instanceof EE_Message) {
270
-            return EE_Message_Factory::set_messenger_and_message_type($message);
271
-        }
272
-        return null;
273
-    }
274
-
275
-
276
-    /**
277
-     * Returns whether or not a message of that type was sent for a given attendee.
278
-     *
279
-     * @param EE_Attendee|int $attendee
280
-     * @param string          $message_type the message type slug
281
-     * @return boolean
282
-     */
283
-    public function message_sent_for_attendee($attendee, $message_type)
284
-    {
285
-        $attendee_ID = EEM_Attendee::instance()->ensure_is_ID($attendee);
286
-        return $this->exists(array(
287
-            array(
288
-                'Attendee.ATT_ID'  => $attendee_ID,
289
-                'MSG_message_type' => $message_type,
290
-                'STS_ID'           => array('IN', $this->stati_indicating_sent()),
291
-            ),
292
-        ));
293
-    }
294
-
295
-
296
-    /**
297
-     * Returns whether or not a message of that type was sent for a given registration
298
-     *
299
-     * @param EE_Registration|int $registration
300
-     * @param string              $message_type the message type slug
301
-     * @return boolean
302
-     */
303
-    public function message_sent_for_registration($registration, $message_type)
304
-    {
305
-        $registrationID = EEM_Registration::instance()->ensure_is_ID($registration);
306
-        return $this->exists(array(
307
-            array(
308
-                'Registration.REG_ID' => $registrationID,
309
-                'MSG_message_type'    => $message_type,
310
-                'STS_ID'              => array('IN', $this->stati_indicating_sent()),
311
-            ),
312
-        ));
313
-    }
314
-
315
-
316
-    /**
317
-     * This retrieves an EE_Message object from the db matching the given token string.
318
-     *
319
-     * @param string $token
320
-     * @return EE_Message
321
-     */
322
-    public function get_one_by_token($token)
323
-    {
324
-        return $this->get_one(array(
325
-            array(
326
-                'MSG_token' => $token,
327
-            ),
328
-        ));
329
-    }
330
-
331
-
332
-    /**
333
-     * Returns stati that indicate the message HAS been sent
334
-     *
335
-     * @return array of strings for possible stati
336
-     */
337
-    public function stati_indicating_sent()
338
-    {
339
-        return apply_filters('FHEE__EEM_Message__stati_indicating_sent', array(self::status_sent));
340
-    }
341
-
342
-
343
-    /**
344
-     * Returns stati that indicate the message is waiting to be sent.
345
-     *
346
-     * @return array of strings for possible stati.
347
-     */
348
-    public function stati_indicating_to_send()
349
-    {
350
-        return apply_filters(
351
-            'FHEE__EEM_Message__stati_indicating_to_send',
352
-            array(self::status_idle, self::status_resend)
353
-        );
354
-    }
355
-
356
-
357
-    /**
358
-     * Returns stati that indicate the message has failed sending
359
-     *
360
-     * @return array  array of strings for possible stati.
361
-     */
362
-    public function stati_indicating_failed_sending()
363
-    {
364
-        $failed_stati = array(
365
-            self::status_failed,
366
-            self::status_retry,
367
-            self::status_messenger_executing,
368
-        );
369
-        // if WP_DEBUG is set, then let's include debug_only fails
370
-        if (WP_DEBUG) {
371
-            $failed_stati[] = self::status_debug_only;
372
-        }
373
-        return apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati);
374
-    }
375
-
376
-
377
-    /**
378
-     * Returns filterable array of all EEM_Message statuses.
379
-     *
380
-     * @return array
381
-     */
382
-    public function all_statuses()
383
-    {
384
-        return apply_filters(
385
-            'FHEE__EEM_Message__all_statuses',
386
-            array(
387
-                EEM_Message::status_sent,
388
-                EEM_Message::status_incomplete,
389
-                EEM_Message::status_idle,
390
-                EEM_Message::status_resend,
391
-                EEM_Message::status_retry,
392
-                EEM_Message::status_failed,
393
-                EEM_Message::status_messenger_executing,
394
-                EEM_Message::status_debug_only,
395
-            )
396
-        );
397
-    }
398
-
399
-    /**
400
-     * Detects any specific query variables in the request and uses those to setup appropriate
401
-     * filter for any queries.
402
-     *
403
-     * @return array
404
-     */
405
-    public function filter_by_query_params()
406
-    {
407
-        // expected possible query_vars, the key in this array matches an expected key in the request,
408
-        // the value, matches the corresponding EEM_Base child reference.
409
-        $expected_vars   = $this->_expected_vars_for_query_inject();
410
-        $query_params[0] = array();
411
-        foreach ($expected_vars as $request_key => $model_name) {
412
-            $request_value = EE_Registry::instance()->REQ->get($request_key);
413
-            if ($request_value) {
414
-                // special case
415
-                switch ($request_key) {
416
-                    case '_REG_ID':
417
-                        $query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array(
418
-                            'Transaction.Registration.REG_ID' => $request_value,
419
-                        );
420
-                        break;
421
-                    case 'EVT_ID':
422
-                        $query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array(
423
-                            'Transaction.Registration.EVT_ID' => $request_value,
424
-                        );
425
-                        break;
426
-                    default:
427
-                        $query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] = $request_value;
428
-                        break;
429
-                }
430
-            }
431
-        }
432
-        return $query_params;
433
-    }
434
-
435
-
436
-    /**
437
-     * @return string
438
-     */
439
-    public function get_pretty_label_for_results()
440
-    {
441
-        $expected_vars = $this->_expected_vars_for_query_inject();
442
-        $pretty_label  = '';
443
-        $label_parts   = array();
444
-        foreach ($expected_vars as $request_key => $model_name) {
445
-            $model = EE_Registry::instance()->load_model($model_name);
446
-            if ($model_field_value = EE_Registry::instance()->REQ->get($request_key)) {
447
-                switch ($request_key) {
448
-                    case '_REG_ID':
449
-                        $label_parts[] = sprintf(
450
-                            esc_html__('Registration with the ID: %s', 'event_espresso'),
451
-                            $model_field_value
452
-                        );
453
-                        break;
454
-                    case 'ATT_ID':
455
-                        /** @var EE_Attendee $attendee */
456
-                        $attendee      = $model->get_one_by_ID($model_field_value);
457
-                        $label_parts[] = $attendee instanceof EE_Attendee
458
-                            ? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name())
459
-                            : sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value);
460
-                        break;
461
-                    case 'ID':
462
-                        /** @var EE_WP_User $wpUser */
463
-                        $wpUser        = $model->get_one_by_ID($model_field_value);
464
-                        $label_parts[] = $wpUser instanceof EE_WP_User
465
-                            ? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name())
466
-                            : sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value);
467
-                        break;
468
-                    case 'TXN_ID':
469
-                        $label_parts[] = sprintf(
470
-                            esc_html__('Transaction with the ID: %s', 'event_espresso'),
471
-                            $model_field_value
472
-                        );
473
-                        break;
474
-                    case 'EVT_ID':
475
-                        /** @var EE_Event $Event */
476
-                        $Event         = $model->get_one_by_ID($model_field_value);
477
-                        $label_parts[] = $Event instanceof EE_Event
478
-                            ? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name())
479
-                            : sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value);
480
-                        break;
481
-                }
482
-            }
483
-        }
484
-
485
-        if ($label_parts) {
486
-            // prepend to the last element of $label_parts an "and".
487
-            if (count($label_parts) > 1) {
488
-                $label_parts_index_to_prepend               = count($label_parts) - 1;
489
-                $label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ];
490
-            }
491
-
492
-            $pretty_label .= sprintf(
493
-                esc_html_x(
494
-                    'Showing messages for %s',
495
-                    'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
496
-                    'event_espresso'
497
-                ),
498
-                implode(', ', $label_parts)
499
-            );
500
-        }
501
-        return $pretty_label;
502
-    }
503
-
504
-
505
-    /**
506
-     * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
507
-     * The array is in the format:
508
-     * array(
509
-     *  {$field_name} => {$model_name}
510
-     * );
511
-     *
512
-     * @since 4.9.0
513
-     * @return array
514
-     */
515
-    protected function _expected_vars_for_query_inject()
516
-    {
517
-        return array(
518
-            '_REG_ID' => 'Registration',
519
-            'ATT_ID'  => 'Attendee',
520
-            'ID'      => 'WP_User',
521
-            'TXN_ID'  => 'Transaction',
522
-            'EVT_ID'  => 'Event',
523
-        );
524
-    }
525
-
526
-
527
-    /**
528
-     * This returns whether EEM_Message is in debug mode or not.
529
-     * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when
530
-     * generating/sending messages. Debug mode can be set by either:
531
-     * 1. Sending in a value for the $set_debug argument
532
-     * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php
533
-     * 3. Overriding the above via the provided filter.
534
-     *
535
-     * @param bool|null $set_debug      If provided, then the debug mode will be set internally until reset via the
536
-     *                                  provided boolean. When no argument is provided (default null) then the debug
537
-     *                                  mode will be returned.
538
-     * @return bool         true means Messages is in debug mode.  false means messages system is not in debug mode.
539
-     */
540
-    public static function debug($set_debug = null)
541
-    {
542
-        static $is_debugging = null;
543
-
544
-        // initialize (use constant if set).
545
-        if (is_null($set_debug) && is_null($is_debugging)) {
546
-            $is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES;
547
-        }
548
-
549
-        if (! is_null($set_debug)) {
550
-            $is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN);
551
-        }
552
-
553
-        // return filtered value
554
-        return apply_filters('FHEE__EEM_Message__debug', $is_debugging);
555
-    }
556
-
557
-
558
-    /**
559
-     * Deletes old messages meeting certain criteria for removal from the database.
560
-     * By default, this will delete messages that:
561
-     * - are older than the value of the delete_threshold in months.
562
-     * - have a STS_ID other than EEM_Message::status_idle
563
-     *
564
-     * @param int $delete_threshold  This integer will be used to set the boundary for what messages are deleted in months.
565
-     * @return bool|false|int Either the number of records affected or false if there was an error (you can call
566
-     *                         $wpdb->last_error to find out what the error was.
567
-     */
568
-    public function delete_old_messages($delete_threshold = 6)
569
-    {
570
-        $number_deleted = 0;
571
-        /**
572
-         * Allows code to change the boundary for what messages are kept.
573
-         * Uses the value of the `delete_threshold` variable by default.
574
-         *
575
-         * @param int $seconds seconds that will be subtracted from the timestamp for now.
576
-         * @return int
577
-         */
578
-        $time_to_leave_alone = absint(
579
-            apply_filters(
580
-                'FHEE__EEM_Message__delete_old_messages__time_to_leave_alone',
581
-                ((int) $delete_threshold) * MONTH_IN_SECONDS
582
-            )
583
-        );
584
-
585
-
586
-        /**
587
-         * Allows code to change what message stati are ignored when deleting.
588
-         * Defaults to only ignore EEM_Message::status_idle messages.
589
-         *
590
-         * @param string $message_stati_to_keep  An array of message statuses that will be ignored when deleting.
591
-         */
592
-        $message_stati_to_keep = (array) apply_filters(
593
-            'FHEE__EEM_Message__delete_old_messages__message_stati_to_keep',
594
-            array(
595
-                EEM_Message::status_idle
596
-            )
597
-        );
598
-
599
-        // first get all the ids of messages being deleted
600
-        $message_ids_to_delete = EEM_Message::instance()->get_col(
601
-            array(
602
-                0 => array(
603
-                    'STS_ID' => array('NOT_IN', $message_stati_to_keep),
604
-                    'MSG_modified' => array('<', time() - $time_to_leave_alone)
605
-                ),
606
-                'limit' => apply_filters(
607
-                    'EEM_Message__delete_old_messages__limit',
608
-                    2000,
609
-                    $delete_threshold
610
-                )
611
-            )
612
-        );
613
-
614
-        if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) {
615
-            global $wpdb;
616
-            $number_deleted = $wpdb->query('
16
+	/**
17
+	 * This priority indicates a message should be generated and sent ASAP
18
+	 *
19
+	 * @type int
20
+	 */
21
+	const priority_high = 10;
22
+
23
+
24
+	/**
25
+	 * This priority indicates a message should be generated ASAP and queued for sending.
26
+	 *
27
+	 * @type
28
+	 */
29
+	const priority_medium = 20;
30
+
31
+
32
+	/**
33
+	 * This priority indicates a message should be queued for generating.
34
+	 *
35
+	 * @type int
36
+	 */
37
+	const priority_low = 30;
38
+
39
+
40
+	/**
41
+	 * indicates this message was sent at the time modified
42
+	 */
43
+	const status_sent = 'MSN';
44
+
45
+
46
+	/**
47
+	 * indicates this message is waiting to be sent
48
+	 */
49
+	const status_idle = 'MID';
50
+
51
+
52
+	/**
53
+	 * indicates an attempt was a made to send this message
54
+	 * at the scheduled time, but it failed at the time modified.  This differs from MDO status in that it will ALWAYS
55
+	 * appear to the end user.
56
+	 */
57
+	const status_failed = 'MFL';
58
+
59
+
60
+	/**
61
+	 * indicates the message has been flagged for resending (at the time modified).
62
+	 */
63
+	const status_resend = 'MRS';
64
+
65
+
66
+	/**
67
+	 * indicates the message has been flagged for generation but has not been generated yet.  Messages always start as
68
+	 * this status when added to the queue.
69
+	 */
70
+	const status_incomplete = 'MIC';
71
+
72
+
73
+	/**
74
+	 * Indicates everything was generated fine for the message, however, the messenger was unable to send.
75
+	 * This status means that its possible to retry sending the message.
76
+	 */
77
+	const status_retry = 'MRT';
78
+
79
+
80
+	/**
81
+	 * This is used for more informational messages that may not indicate anything is broken but still cannot be
82
+	 * generated or sent correctly. An example of a message that would get flagged this way would be when a not
83
+	 * approved message was queued for generation, but at time of generation, the attached registration(s) are
84
+	 * approved. So the message queued for generation is no longer valid.  Messages for this status will only persist
85
+	 * in the db and be viewable in the message activity list table when the messages system is in debug mode.
86
+	 *
87
+	 * @see EEM_Message::debug()
88
+	 */
89
+	const status_debug_only = 'MDO';
90
+
91
+
92
+	/**
93
+	 * This status is given to messages it is processed by the messenger send method.
94
+	 * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually
95
+	 * indicative of a PHP timeout or memory limit issue.
96
+	 */
97
+	const status_messenger_executing = 'MEX';
98
+
99
+
100
+	/**
101
+	 *    Private constructor to prevent direct creation.
102
+	 *
103
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and
104
+	 *                         any incoming timezone data that gets saved).  Note this just sends the timezone info to
105
+	 *                         the date time model field objects.  Default is null (and will be assumed using the set
106
+	 *                         timezone in the 'timezone_string' wp option)
107
+	 * @return EEM_Message
108
+	 */
109
+	protected function __construct($timezone = null)
110
+	{
111
+		$this->singular_item = __('Message', 'event_espresso');
112
+		$this->plural_item   = __('Messages', 'event_espresso');
113
+
114
+		// used for token generator
115
+		EE_Registry::instance()->load_helper('URL');
116
+
117
+		$this->_tables = array(
118
+			'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'),
119
+		);
120
+
121
+		$allowed_priority = array(
122
+			self::priority_high   => __('high', 'event_espresso'),
123
+			self::priority_medium => __('medium', 'event_espresso'),
124
+			self::priority_low    => __('low', 'event_espresso'),
125
+		);
126
+
127
+		$this->_fields          = array(
128
+			'Message' => array(
129
+				'MSG_ID'             => new EE_Primary_Key_Int_Field('MSG_ID', __('Message ID', 'event_espresso')),
130
+				'MSG_token'          => new EE_Plain_Text_Field(
131
+					'MSG_token',
132
+					__(
133
+						'Unique Token used to represent this row in publicly viewable contexts (eg. a url).',
134
+						'event_espresso'
135
+					),
136
+					false,
137
+					EEH_URL::generate_unique_token()
138
+				),
139
+				'GRP_ID'             => new EE_Foreign_Key_Int_Field(
140
+					'GRP_ID',
141
+					__('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'),
142
+					true,
143
+					0,
144
+					'Message_Template_Group'
145
+				),
146
+				'TXN_ID'             => new EE_Foreign_Key_Int_Field(
147
+					'TXN_ID',
148
+					__(
149
+						'Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message',
150
+						'event_espresso'
151
+					),
152
+					true,
153
+					0,
154
+					'Transaction'
155
+				),
156
+				'MSG_messenger'      => new EE_Plain_Text_Field(
157
+					'MSG_messenger',
158
+					__(
159
+						'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.',
160
+						'event_espresso'
161
+					),
162
+					false,
163
+					'email'
164
+				),
165
+				'MSG_message_type'   => new EE_Plain_Text_Field(
166
+					'MSG_message_type',
167
+					__('Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso'),
168
+					false,
169
+					'receipt'
170
+				),
171
+				'MSG_context'        => new EE_Plain_Text_Field('MSG_context', __('Context', 'event_espresso'), false),
172
+				'MSG_recipient_ID'   => new EE_Foreign_Key_Int_Field(
173
+					'MSG_recipient_ID',
174
+					__('Recipient ID', 'event_espresso'),
175
+					true,
176
+					null,
177
+					array('Registration', 'Attendee', 'WP_User')
178
+				),
179
+				'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field(
180
+					'MSG_recipient_type',
181
+					__('Recipient Type', 'event_espresso'),
182
+					true,
183
+					null,
184
+					array('Registration', 'Attendee', 'WP_User')
185
+				),
186
+				'MSG_content'        => new EE_Maybe_Serialized_Text_Field(
187
+					'MSG_content',
188
+					__('Content', 'event_espresso'),
189
+					true,
190
+					''
191
+				),
192
+				'MSG_to'             => new EE_Maybe_Serialized_Text_Field(
193
+					'MSG_to',
194
+					__('Address To', 'event_espresso'),
195
+					true
196
+				),
197
+				'MSG_from'           => new EE_Maybe_Serialized_Text_Field(
198
+					'MSG_from',
199
+					__('Address From', 'event_espresso'),
200
+					true
201
+				),
202
+				'MSG_subject'        => new EE_Maybe_Serialized_Text_Field(
203
+					'MSG_subject',
204
+					__('Subject', 'event_espresso'),
205
+					true,
206
+					''
207
+				),
208
+				'MSG_priority'       => new EE_Enum_Integer_Field(
209
+					'MSG_priority',
210
+					__('Priority', 'event_espresso'),
211
+					false,
212
+					self::priority_low,
213
+					$allowed_priority
214
+				),
215
+				'STS_ID'             => new EE_Foreign_Key_String_Field(
216
+					'STS_ID',
217
+					__('Status', 'event_espresso'),
218
+					false,
219
+					self::status_incomplete,
220
+					'Status'
221
+				),
222
+				'MSG_created'        => new EE_Datetime_Field(
223
+					'MSG_created',
224
+					__('Created', 'event_espresso'),
225
+					false,
226
+					EE_Datetime_Field::now
227
+				),
228
+				'MSG_modified'       => new EE_Datetime_Field(
229
+					'MSG_modified',
230
+					__('Modified', 'event_espresso'),
231
+					true,
232
+					EE_Datetime_Field::now
233
+				),
234
+			),
235
+		);
236
+		$this->_model_relations = array(
237
+			'Attendee'               => new EE_Belongs_To_Any_Relation(),
238
+			'Registration'           => new EE_Belongs_To_Any_Relation(),
239
+			'WP_User'                => new EE_Belongs_To_Any_Relation(),
240
+			'Message_Template_Group' => new EE_Belongs_To_Relation(),
241
+			'Transaction'            => new EE_Belongs_To_Relation(),
242
+		);
243
+		parent::__construct($timezone);
244
+	}
245
+
246
+
247
+	/**
248
+	 * @return \EE_Message
249
+	 */
250
+	public function create_default_object()
251
+	{
252
+		/** @type EE_Message $message */
253
+		$message = parent::create_default_object();
254
+		if ($message instanceof EE_Message) {
255
+			return EE_Message_Factory::set_messenger_and_message_type($message);
256
+		}
257
+		return null;
258
+	}
259
+
260
+
261
+	/**
262
+	 * @param mixed $cols_n_values
263
+	 * @return \EE_Message
264
+	 */
265
+	public function instantiate_class_from_array_or_object($cols_n_values)
266
+	{
267
+		/** @type EE_Message $message */
268
+		$message = parent::instantiate_class_from_array_or_object($cols_n_values);
269
+		if ($message instanceof EE_Message) {
270
+			return EE_Message_Factory::set_messenger_and_message_type($message);
271
+		}
272
+		return null;
273
+	}
274
+
275
+
276
+	/**
277
+	 * Returns whether or not a message of that type was sent for a given attendee.
278
+	 *
279
+	 * @param EE_Attendee|int $attendee
280
+	 * @param string          $message_type the message type slug
281
+	 * @return boolean
282
+	 */
283
+	public function message_sent_for_attendee($attendee, $message_type)
284
+	{
285
+		$attendee_ID = EEM_Attendee::instance()->ensure_is_ID($attendee);
286
+		return $this->exists(array(
287
+			array(
288
+				'Attendee.ATT_ID'  => $attendee_ID,
289
+				'MSG_message_type' => $message_type,
290
+				'STS_ID'           => array('IN', $this->stati_indicating_sent()),
291
+			),
292
+		));
293
+	}
294
+
295
+
296
+	/**
297
+	 * Returns whether or not a message of that type was sent for a given registration
298
+	 *
299
+	 * @param EE_Registration|int $registration
300
+	 * @param string              $message_type the message type slug
301
+	 * @return boolean
302
+	 */
303
+	public function message_sent_for_registration($registration, $message_type)
304
+	{
305
+		$registrationID = EEM_Registration::instance()->ensure_is_ID($registration);
306
+		return $this->exists(array(
307
+			array(
308
+				'Registration.REG_ID' => $registrationID,
309
+				'MSG_message_type'    => $message_type,
310
+				'STS_ID'              => array('IN', $this->stati_indicating_sent()),
311
+			),
312
+		));
313
+	}
314
+
315
+
316
+	/**
317
+	 * This retrieves an EE_Message object from the db matching the given token string.
318
+	 *
319
+	 * @param string $token
320
+	 * @return EE_Message
321
+	 */
322
+	public function get_one_by_token($token)
323
+	{
324
+		return $this->get_one(array(
325
+			array(
326
+				'MSG_token' => $token,
327
+			),
328
+		));
329
+	}
330
+
331
+
332
+	/**
333
+	 * Returns stati that indicate the message HAS been sent
334
+	 *
335
+	 * @return array of strings for possible stati
336
+	 */
337
+	public function stati_indicating_sent()
338
+	{
339
+		return apply_filters('FHEE__EEM_Message__stati_indicating_sent', array(self::status_sent));
340
+	}
341
+
342
+
343
+	/**
344
+	 * Returns stati that indicate the message is waiting to be sent.
345
+	 *
346
+	 * @return array of strings for possible stati.
347
+	 */
348
+	public function stati_indicating_to_send()
349
+	{
350
+		return apply_filters(
351
+			'FHEE__EEM_Message__stati_indicating_to_send',
352
+			array(self::status_idle, self::status_resend)
353
+		);
354
+	}
355
+
356
+
357
+	/**
358
+	 * Returns stati that indicate the message has failed sending
359
+	 *
360
+	 * @return array  array of strings for possible stati.
361
+	 */
362
+	public function stati_indicating_failed_sending()
363
+	{
364
+		$failed_stati = array(
365
+			self::status_failed,
366
+			self::status_retry,
367
+			self::status_messenger_executing,
368
+		);
369
+		// if WP_DEBUG is set, then let's include debug_only fails
370
+		if (WP_DEBUG) {
371
+			$failed_stati[] = self::status_debug_only;
372
+		}
373
+		return apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati);
374
+	}
375
+
376
+
377
+	/**
378
+	 * Returns filterable array of all EEM_Message statuses.
379
+	 *
380
+	 * @return array
381
+	 */
382
+	public function all_statuses()
383
+	{
384
+		return apply_filters(
385
+			'FHEE__EEM_Message__all_statuses',
386
+			array(
387
+				EEM_Message::status_sent,
388
+				EEM_Message::status_incomplete,
389
+				EEM_Message::status_idle,
390
+				EEM_Message::status_resend,
391
+				EEM_Message::status_retry,
392
+				EEM_Message::status_failed,
393
+				EEM_Message::status_messenger_executing,
394
+				EEM_Message::status_debug_only,
395
+			)
396
+		);
397
+	}
398
+
399
+	/**
400
+	 * Detects any specific query variables in the request and uses those to setup appropriate
401
+	 * filter for any queries.
402
+	 *
403
+	 * @return array
404
+	 */
405
+	public function filter_by_query_params()
406
+	{
407
+		// expected possible query_vars, the key in this array matches an expected key in the request,
408
+		// the value, matches the corresponding EEM_Base child reference.
409
+		$expected_vars   = $this->_expected_vars_for_query_inject();
410
+		$query_params[0] = array();
411
+		foreach ($expected_vars as $request_key => $model_name) {
412
+			$request_value = EE_Registry::instance()->REQ->get($request_key);
413
+			if ($request_value) {
414
+				// special case
415
+				switch ($request_key) {
416
+					case '_REG_ID':
417
+						$query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array(
418
+							'Transaction.Registration.REG_ID' => $request_value,
419
+						);
420
+						break;
421
+					case 'EVT_ID':
422
+						$query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array(
423
+							'Transaction.Registration.EVT_ID' => $request_value,
424
+						);
425
+						break;
426
+					default:
427
+						$query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] = $request_value;
428
+						break;
429
+				}
430
+			}
431
+		}
432
+		return $query_params;
433
+	}
434
+
435
+
436
+	/**
437
+	 * @return string
438
+	 */
439
+	public function get_pretty_label_for_results()
440
+	{
441
+		$expected_vars = $this->_expected_vars_for_query_inject();
442
+		$pretty_label  = '';
443
+		$label_parts   = array();
444
+		foreach ($expected_vars as $request_key => $model_name) {
445
+			$model = EE_Registry::instance()->load_model($model_name);
446
+			if ($model_field_value = EE_Registry::instance()->REQ->get($request_key)) {
447
+				switch ($request_key) {
448
+					case '_REG_ID':
449
+						$label_parts[] = sprintf(
450
+							esc_html__('Registration with the ID: %s', 'event_espresso'),
451
+							$model_field_value
452
+						);
453
+						break;
454
+					case 'ATT_ID':
455
+						/** @var EE_Attendee $attendee */
456
+						$attendee      = $model->get_one_by_ID($model_field_value);
457
+						$label_parts[] = $attendee instanceof EE_Attendee
458
+							? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name())
459
+							: sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value);
460
+						break;
461
+					case 'ID':
462
+						/** @var EE_WP_User $wpUser */
463
+						$wpUser        = $model->get_one_by_ID($model_field_value);
464
+						$label_parts[] = $wpUser instanceof EE_WP_User
465
+							? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name())
466
+							: sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value);
467
+						break;
468
+					case 'TXN_ID':
469
+						$label_parts[] = sprintf(
470
+							esc_html__('Transaction with the ID: %s', 'event_espresso'),
471
+							$model_field_value
472
+						);
473
+						break;
474
+					case 'EVT_ID':
475
+						/** @var EE_Event $Event */
476
+						$Event         = $model->get_one_by_ID($model_field_value);
477
+						$label_parts[] = $Event instanceof EE_Event
478
+							? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name())
479
+							: sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value);
480
+						break;
481
+				}
482
+			}
483
+		}
484
+
485
+		if ($label_parts) {
486
+			// prepend to the last element of $label_parts an "and".
487
+			if (count($label_parts) > 1) {
488
+				$label_parts_index_to_prepend               = count($label_parts) - 1;
489
+				$label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ];
490
+			}
491
+
492
+			$pretty_label .= sprintf(
493
+				esc_html_x(
494
+					'Showing messages for %s',
495
+					'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
496
+					'event_espresso'
497
+				),
498
+				implode(', ', $label_parts)
499
+			);
500
+		}
501
+		return $pretty_label;
502
+	}
503
+
504
+
505
+	/**
506
+	 * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
507
+	 * The array is in the format:
508
+	 * array(
509
+	 *  {$field_name} => {$model_name}
510
+	 * );
511
+	 *
512
+	 * @since 4.9.0
513
+	 * @return array
514
+	 */
515
+	protected function _expected_vars_for_query_inject()
516
+	{
517
+		return array(
518
+			'_REG_ID' => 'Registration',
519
+			'ATT_ID'  => 'Attendee',
520
+			'ID'      => 'WP_User',
521
+			'TXN_ID'  => 'Transaction',
522
+			'EVT_ID'  => 'Event',
523
+		);
524
+	}
525
+
526
+
527
+	/**
528
+	 * This returns whether EEM_Message is in debug mode or not.
529
+	 * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when
530
+	 * generating/sending messages. Debug mode can be set by either:
531
+	 * 1. Sending in a value for the $set_debug argument
532
+	 * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php
533
+	 * 3. Overriding the above via the provided filter.
534
+	 *
535
+	 * @param bool|null $set_debug      If provided, then the debug mode will be set internally until reset via the
536
+	 *                                  provided boolean. When no argument is provided (default null) then the debug
537
+	 *                                  mode will be returned.
538
+	 * @return bool         true means Messages is in debug mode.  false means messages system is not in debug mode.
539
+	 */
540
+	public static function debug($set_debug = null)
541
+	{
542
+		static $is_debugging = null;
543
+
544
+		// initialize (use constant if set).
545
+		if (is_null($set_debug) && is_null($is_debugging)) {
546
+			$is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES;
547
+		}
548
+
549
+		if (! is_null($set_debug)) {
550
+			$is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN);
551
+		}
552
+
553
+		// return filtered value
554
+		return apply_filters('FHEE__EEM_Message__debug', $is_debugging);
555
+	}
556
+
557
+
558
+	/**
559
+	 * Deletes old messages meeting certain criteria for removal from the database.
560
+	 * By default, this will delete messages that:
561
+	 * - are older than the value of the delete_threshold in months.
562
+	 * - have a STS_ID other than EEM_Message::status_idle
563
+	 *
564
+	 * @param int $delete_threshold  This integer will be used to set the boundary for what messages are deleted in months.
565
+	 * @return bool|false|int Either the number of records affected or false if there was an error (you can call
566
+	 *                         $wpdb->last_error to find out what the error was.
567
+	 */
568
+	public function delete_old_messages($delete_threshold = 6)
569
+	{
570
+		$number_deleted = 0;
571
+		/**
572
+		 * Allows code to change the boundary for what messages are kept.
573
+		 * Uses the value of the `delete_threshold` variable by default.
574
+		 *
575
+		 * @param int $seconds seconds that will be subtracted from the timestamp for now.
576
+		 * @return int
577
+		 */
578
+		$time_to_leave_alone = absint(
579
+			apply_filters(
580
+				'FHEE__EEM_Message__delete_old_messages__time_to_leave_alone',
581
+				((int) $delete_threshold) * MONTH_IN_SECONDS
582
+			)
583
+		);
584
+
585
+
586
+		/**
587
+		 * Allows code to change what message stati are ignored when deleting.
588
+		 * Defaults to only ignore EEM_Message::status_idle messages.
589
+		 *
590
+		 * @param string $message_stati_to_keep  An array of message statuses that will be ignored when deleting.
591
+		 */
592
+		$message_stati_to_keep = (array) apply_filters(
593
+			'FHEE__EEM_Message__delete_old_messages__message_stati_to_keep',
594
+			array(
595
+				EEM_Message::status_idle
596
+			)
597
+		);
598
+
599
+		// first get all the ids of messages being deleted
600
+		$message_ids_to_delete = EEM_Message::instance()->get_col(
601
+			array(
602
+				0 => array(
603
+					'STS_ID' => array('NOT_IN', $message_stati_to_keep),
604
+					'MSG_modified' => array('<', time() - $time_to_leave_alone)
605
+				),
606
+				'limit' => apply_filters(
607
+					'EEM_Message__delete_old_messages__limit',
608
+					2000,
609
+					$delete_threshold
610
+				)
611
+			)
612
+		);
613
+
614
+		if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) {
615
+			global $wpdb;
616
+			$number_deleted = $wpdb->query('
617 617
                 DELETE
618 618
                 FROM ' . $this->table() . '
619 619
                 WHERE
620 620
                     MSG_ID IN (' . implode(",", $message_ids_to_delete) . ')
621 621
             ');
622
-        }
623
-
624
-        /**
625
-         * This will get called if the number of records deleted 0 or greater.  So a successful deletion is one where
626
-         * there were no errors.  An unsuccessful deletion is where there were errors.  Keep that in mind for the actions
627
-         * below.
628
-         */
629
-        if ($number_deleted !== false) {
630
-            do_action('AHEE__EEM_Message__delete_old_messages__after_successful_deletion', $message_ids_to_delete, $number_deleted);
631
-        } else {
632
-            do_action('AHEE__EEM_Message__delete_old_messages__after_deletion_fail', $message_ids_to_delete, $number_deleted);
633
-        }
634
-        return $number_deleted;
635
-    }
622
+		}
623
+
624
+		/**
625
+		 * This will get called if the number of records deleted 0 or greater.  So a successful deletion is one where
626
+		 * there were no errors.  An unsuccessful deletion is where there were errors.  Keep that in mind for the actions
627
+		 * below.
628
+		 */
629
+		if ($number_deleted !== false) {
630
+			do_action('AHEE__EEM_Message__delete_old_messages__after_successful_deletion', $message_ids_to_delete, $number_deleted);
631
+		} else {
632
+			do_action('AHEE__EEM_Message__delete_old_messages__after_deletion_fail', $message_ids_to_delete, $number_deleted);
633
+		}
634
+		return $number_deleted;
635
+	}
636 636
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Transaction.model.php 2 patches
Indentation   +452 added lines, -452 removed lines patch added patch discarded remove patch
@@ -16,230 +16,230 @@  discard block
 block discarded – undo
16 16
 class EEM_Transaction extends EEM_Base
17 17
 {
18 18
 
19
-    // private instance of the Transaction object
20
-    protected static $_instance;
21
-
22
-    /**
23
-     * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
24
-     * but payment is pending. This is the state for transactions where payment is promised
25
-     * from an offline gateway.
26
-     */
27
-    //  const open_status_code = 'TPN';
28
-
29
-    /**
30
-     * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
31
-     * either due to a technical reason (server or computer crash during registration),
32
-     *  or some other reason that prevent the collection of any useful contact information from any of the registrants
33
-     */
34
-    const failed_status_code = 'TFL';
35
-
36
-    /**
37
-     * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
38
-     * either due to a technical reason (server or computer crash during registration),
39
-     * or due to an abandoned cart after registrant chose not to complete the registration process
40
-     * HOWEVER...
41
-     * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
42
-     * registrant
43
-     */
44
-    const abandoned_status_code = 'TAB';
45
-
46
-    /**
47
-     * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
48
-     * meaning that monies are still owing: TXN_paid < TXN_total
49
-     */
50
-    const incomplete_status_code = 'TIN';
51
-
52
-    /**
53
-     * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
54
-     * meaning that NO monies are owing: TXN_paid == TXN_total
55
-     */
56
-    const complete_status_code = 'TCM';
57
-
58
-    /**
59
-     *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
60
-     *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
61
-     */
62
-    const overpaid_status_code = 'TOP';
63
-
64
-
65
-    /**
66
-     *    private constructor to prevent direct creation
67
-     *
68
-     * @Constructor
69
-     * @access protected
70
-     *
71
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
72
-     *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
73
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
74
-     *                         timezone in the 'timezone_string' wp option)
75
-     *
76
-     * @return EEM_Transaction
77
-     * @throws \EE_Error
78
-     */
79
-    protected function __construct($timezone)
80
-    {
81
-        $this->singular_item = __('Transaction', 'event_espresso');
82
-        $this->plural_item   = __('Transactions', 'event_espresso');
83
-
84
-        $this->_tables                 = array(
85
-            'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID')
86
-        );
87
-        $this->_fields                 = array(
88
-            'TransactionTable' => array(
89
-                'TXN_ID'           => new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID', 'event_espresso')),
90
-                'TXN_timestamp'    => new EE_Datetime_Field(
91
-                    'TXN_timestamp',
92
-                    __('date when transaction was created', 'event_espresso'),
93
-                    false,
94
-                    EE_Datetime_Field::now,
95
-                    $timezone
96
-                ),
97
-                'TXN_total'        => new EE_Money_Field(
98
-                    'TXN_total',
99
-                    __('Total value of Transaction', 'event_espresso'),
100
-                    false,
101
-                    0
102
-                ),
103
-                'TXN_paid'         => new EE_Money_Field(
104
-                    'TXN_paid',
105
-                    __('Amount paid towards transaction to date', 'event_espresso'),
106
-                    false,
107
-                    0
108
-                ),
109
-                'STS_ID'           => new EE_Foreign_Key_String_Field(
110
-                    'STS_ID',
111
-                    __('Status ID', 'event_espresso'),
112
-                    false,
113
-                    EEM_Transaction::failed_status_code,
114
-                    'Status'
115
-                ),
116
-                'TXN_session_data' => new EE_Serialized_Text_Field(
117
-                    'TXN_session_data',
118
-                    __('Serialized session data', 'event_espresso'),
119
-                    true,
120
-                    ''
121
-                ),
122
-                'TXN_hash_salt'    => new EE_Plain_Text_Field(
123
-                    'TXN_hash_salt',
124
-                    __('Transaction Hash Salt', 'event_espresso'),
125
-                    true,
126
-                    ''
127
-                ),
128
-                'PMD_ID'           => new EE_Foreign_Key_Int_Field(
129
-                    'PMD_ID',
130
-                    __("Last Used Payment Method", 'event_espresso'),
131
-                    true,
132
-                    null,
133
-                    'Payment_Method'
134
-                ),
135
-                'TXN_reg_steps'    => new EE_Serialized_Text_Field(
136
-                    'TXN_reg_steps',
137
-                    __('Registration Steps', 'event_espresso'),
138
-                    false,
139
-                    array()
140
-                ),
141
-            )
142
-        );
143
-        $this->_model_relations        = array(
144
-            'Registration'   => new EE_Has_Many_Relation(),
145
-            'Payment'        => new EE_Has_Many_Relation(),
146
-            'Status'         => new EE_Belongs_To_Relation(),
147
-            'Line_Item'      => new EE_Has_Many_Relation(false),
148
-            // you can delete a transaction without needing to delete its line items
149
-            'Payment_Method' => new EE_Belongs_To_Relation(),
150
-            'Message'        => new EE_Has_Many_Relation()
151
-        );
152
-        $this->_model_chain_to_wp_user = 'Registration.Event';
153
-        parent::__construct($timezone);
154
-    }
155
-
156
-
157
-    /**
158
-     *    txn_status_array
159
-     * get list of transaction statuses
160
-     *
161
-     * @access public
162
-     * @return array
163
-     */
164
-    public static function txn_status_array()
165
-    {
166
-        return apply_filters(
167
-            'FHEE__EEM_Transaction__txn_status_array',
168
-            array(
169
-                EEM_Transaction::overpaid_status_code,
170
-                EEM_Transaction::complete_status_code,
171
-                EEM_Transaction::incomplete_status_code,
172
-                EEM_Transaction::abandoned_status_code,
173
-                EEM_Transaction::failed_status_code,
174
-            )
175
-        );
176
-    }
177
-
178
-    /**
179
-     *        get the revenue per day  for the Transaction Admin page Reports Tab
180
-     *
181
-     * @access        public
182
-     *
183
-     * @param string $period
184
-     *
185
-     * @return \stdClass[]
186
-     */
187
-    public function get_revenue_per_day_report($period = '-1 month')
188
-    {
189
-        $sql_date = $this->convert_datetime_for_query(
190
-            'TXN_timestamp',
191
-            date('Y-m-d H:i:s', strtotime($period)),
192
-            'Y-m-d H:i:s',
193
-            'UTC'
194
-        );
195
-
196
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'TXN_timestamp');
197
-
198
-        return $this->_get_all_wpdb_results(
199
-            array(
200
-                array(
201
-                    'TXN_timestamp' => array('>=', $sql_date)
202
-                ),
203
-                'group_by' => 'txnDate',
204
-                'order_by' => array('TXN_timestamp' => 'ASC')
205
-            ),
206
-            OBJECT,
207
-            array(
208
-                'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
209
-                'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
210
-            )
211
-        );
212
-    }
213
-
214
-
215
-    /**
216
-     *        get the revenue per event  for the Transaction Admin page Reports Tab
217
-     *
218
-     * @access        public
219
-     *
220
-     * @param string $period
221
-     *
222
-     * @throws \EE_Error
223
-     * @return mixed
224
-     */
225
-    public function get_revenue_per_event_report($period = '-1 month')
226
-    {
227
-        global $wpdb;
228
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
229
-        $registration_table         = $wpdb->prefix . 'esp_registration';
230
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
231
-        $event_table                = $wpdb->posts;
232
-        $payment_table              = $wpdb->prefix . 'esp_payment';
233
-        $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
234
-        $approved_payment_status    = EEM_Payment::status_id_approved;
235
-        $extra_event_on_join        = '';
236
-        // exclude events not authored by user if permissions in effect
237
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
238
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
239
-        }
240
-
241
-        return $wpdb->get_results(
242
-            "SELECT
19
+	// private instance of the Transaction object
20
+	protected static $_instance;
21
+
22
+	/**
23
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
24
+	 * but payment is pending. This is the state for transactions where payment is promised
25
+	 * from an offline gateway.
26
+	 */
27
+	//  const open_status_code = 'TPN';
28
+
29
+	/**
30
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
31
+	 * either due to a technical reason (server or computer crash during registration),
32
+	 *  or some other reason that prevent the collection of any useful contact information from any of the registrants
33
+	 */
34
+	const failed_status_code = 'TFL';
35
+
36
+	/**
37
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
38
+	 * either due to a technical reason (server or computer crash during registration),
39
+	 * or due to an abandoned cart after registrant chose not to complete the registration process
40
+	 * HOWEVER...
41
+	 * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
42
+	 * registrant
43
+	 */
44
+	const abandoned_status_code = 'TAB';
45
+
46
+	/**
47
+	 * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
48
+	 * meaning that monies are still owing: TXN_paid < TXN_total
49
+	 */
50
+	const incomplete_status_code = 'TIN';
51
+
52
+	/**
53
+	 * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
54
+	 * meaning that NO monies are owing: TXN_paid == TXN_total
55
+	 */
56
+	const complete_status_code = 'TCM';
57
+
58
+	/**
59
+	 *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
60
+	 *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
61
+	 */
62
+	const overpaid_status_code = 'TOP';
63
+
64
+
65
+	/**
66
+	 *    private constructor to prevent direct creation
67
+	 *
68
+	 * @Constructor
69
+	 * @access protected
70
+	 *
71
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
72
+	 *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
73
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
74
+	 *                         timezone in the 'timezone_string' wp option)
75
+	 *
76
+	 * @return EEM_Transaction
77
+	 * @throws \EE_Error
78
+	 */
79
+	protected function __construct($timezone)
80
+	{
81
+		$this->singular_item = __('Transaction', 'event_espresso');
82
+		$this->plural_item   = __('Transactions', 'event_espresso');
83
+
84
+		$this->_tables                 = array(
85
+			'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID')
86
+		);
87
+		$this->_fields                 = array(
88
+			'TransactionTable' => array(
89
+				'TXN_ID'           => new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID', 'event_espresso')),
90
+				'TXN_timestamp'    => new EE_Datetime_Field(
91
+					'TXN_timestamp',
92
+					__('date when transaction was created', 'event_espresso'),
93
+					false,
94
+					EE_Datetime_Field::now,
95
+					$timezone
96
+				),
97
+				'TXN_total'        => new EE_Money_Field(
98
+					'TXN_total',
99
+					__('Total value of Transaction', 'event_espresso'),
100
+					false,
101
+					0
102
+				),
103
+				'TXN_paid'         => new EE_Money_Field(
104
+					'TXN_paid',
105
+					__('Amount paid towards transaction to date', 'event_espresso'),
106
+					false,
107
+					0
108
+				),
109
+				'STS_ID'           => new EE_Foreign_Key_String_Field(
110
+					'STS_ID',
111
+					__('Status ID', 'event_espresso'),
112
+					false,
113
+					EEM_Transaction::failed_status_code,
114
+					'Status'
115
+				),
116
+				'TXN_session_data' => new EE_Serialized_Text_Field(
117
+					'TXN_session_data',
118
+					__('Serialized session data', 'event_espresso'),
119
+					true,
120
+					''
121
+				),
122
+				'TXN_hash_salt'    => new EE_Plain_Text_Field(
123
+					'TXN_hash_salt',
124
+					__('Transaction Hash Salt', 'event_espresso'),
125
+					true,
126
+					''
127
+				),
128
+				'PMD_ID'           => new EE_Foreign_Key_Int_Field(
129
+					'PMD_ID',
130
+					__("Last Used Payment Method", 'event_espresso'),
131
+					true,
132
+					null,
133
+					'Payment_Method'
134
+				),
135
+				'TXN_reg_steps'    => new EE_Serialized_Text_Field(
136
+					'TXN_reg_steps',
137
+					__('Registration Steps', 'event_espresso'),
138
+					false,
139
+					array()
140
+				),
141
+			)
142
+		);
143
+		$this->_model_relations        = array(
144
+			'Registration'   => new EE_Has_Many_Relation(),
145
+			'Payment'        => new EE_Has_Many_Relation(),
146
+			'Status'         => new EE_Belongs_To_Relation(),
147
+			'Line_Item'      => new EE_Has_Many_Relation(false),
148
+			// you can delete a transaction without needing to delete its line items
149
+			'Payment_Method' => new EE_Belongs_To_Relation(),
150
+			'Message'        => new EE_Has_Many_Relation()
151
+		);
152
+		$this->_model_chain_to_wp_user = 'Registration.Event';
153
+		parent::__construct($timezone);
154
+	}
155
+
156
+
157
+	/**
158
+	 *    txn_status_array
159
+	 * get list of transaction statuses
160
+	 *
161
+	 * @access public
162
+	 * @return array
163
+	 */
164
+	public static function txn_status_array()
165
+	{
166
+		return apply_filters(
167
+			'FHEE__EEM_Transaction__txn_status_array',
168
+			array(
169
+				EEM_Transaction::overpaid_status_code,
170
+				EEM_Transaction::complete_status_code,
171
+				EEM_Transaction::incomplete_status_code,
172
+				EEM_Transaction::abandoned_status_code,
173
+				EEM_Transaction::failed_status_code,
174
+			)
175
+		);
176
+	}
177
+
178
+	/**
179
+	 *        get the revenue per day  for the Transaction Admin page Reports Tab
180
+	 *
181
+	 * @access        public
182
+	 *
183
+	 * @param string $period
184
+	 *
185
+	 * @return \stdClass[]
186
+	 */
187
+	public function get_revenue_per_day_report($period = '-1 month')
188
+	{
189
+		$sql_date = $this->convert_datetime_for_query(
190
+			'TXN_timestamp',
191
+			date('Y-m-d H:i:s', strtotime($period)),
192
+			'Y-m-d H:i:s',
193
+			'UTC'
194
+		);
195
+
196
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'TXN_timestamp');
197
+
198
+		return $this->_get_all_wpdb_results(
199
+			array(
200
+				array(
201
+					'TXN_timestamp' => array('>=', $sql_date)
202
+				),
203
+				'group_by' => 'txnDate',
204
+				'order_by' => array('TXN_timestamp' => 'ASC')
205
+			),
206
+			OBJECT,
207
+			array(
208
+				'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
209
+				'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
210
+			)
211
+		);
212
+	}
213
+
214
+
215
+	/**
216
+	 *        get the revenue per event  for the Transaction Admin page Reports Tab
217
+	 *
218
+	 * @access        public
219
+	 *
220
+	 * @param string $period
221
+	 *
222
+	 * @throws \EE_Error
223
+	 * @return mixed
224
+	 */
225
+	public function get_revenue_per_event_report($period = '-1 month')
226
+	{
227
+		global $wpdb;
228
+		$transaction_table          = $wpdb->prefix . 'esp_transaction';
229
+		$registration_table         = $wpdb->prefix . 'esp_registration';
230
+		$registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
231
+		$event_table                = $wpdb->posts;
232
+		$payment_table              = $wpdb->prefix . 'esp_payment';
233
+		$sql_date                   = date('Y-m-d H:i:s', strtotime($period));
234
+		$approved_payment_status    = EEM_Payment::status_id_approved;
235
+		$extra_event_on_join        = '';
236
+		// exclude events not authored by user if permissions in effect
237
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
238
+			$extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
239
+		}
240
+
241
+		return $wpdb->get_results(
242
+			"SELECT
243 243
 			Transaction_Event.event_name AS event_name,
244 244
 			SUM(Transaction_Event.paid) AS revenue
245 245
 			FROM
@@ -267,233 +267,233 @@  discard block
 block discarded – undo
267 267
 					$extra_event_on_join
268 268
 				) AS Transaction_Event
269 269
 			GROUP BY event_name",
270
-            OBJECT
271
-        );
272
-    }
273
-
274
-
275
-    /**
276
-     * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
277
-     * $_REQUEST global variable. Either way, tries to find the current transaction (through
278
-     * the registration pointed to by reg_url_link), if not returns null
279
-     *
280
-     * @param string $reg_url_link
281
-     *
282
-     * @return EE_Transaction
283
-     */
284
-    public function get_transaction_from_reg_url_link($reg_url_link = '')
285
-    {
286
-        return $this->get_one(array(
287
-            array(
288
-                'Registration.REG_url_link' => ! empty($reg_url_link) ? $reg_url_link : EE_Registry::instance()->REQ->get(
289
-                    'e_reg_url_link',
290
-                    ''
291
-                )
292
-            )
293
-        ));
294
-    }
295
-
296
-
297
-    /**
298
-     * Updates the provided EE_Transaction with all the applicable payments
299
-     * (or fetch the EE_Transaction from its ID)
300
-     *
301
-     * @deprecated
302
-     *
303
-     * @param EE_Transaction|int $transaction_obj_or_id
304
-     * @param boolean            $save_txn whether or not to save the transaction during this function call
305
-     *
306
-     * @return boolean
307
-     * @throws \EE_Error
308
-     */
309
-    public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
310
-    {
311
-        EE_Error::doing_it_wrong(
312
-            __CLASS__ . '::' . __FUNCTION__,
313
-            sprintf(
314
-                __('This method is deprecated. Please use "%s" instead', 'event_espresso'),
315
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
316
-            ),
317
-            '4.6.0'
318
-        );
319
-        /** @type EE_Transaction_Processor $transaction_processor */
320
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
321
-
322
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
323
-            $this->ensure_is_obj($transaction_obj_or_id)
324
-        );
325
-    }
326
-
327
-    /**
328
-     * Deletes "junk" transactions that were probably added by bots. There might be TONS
329
-     * of these, so we are very careful to NOT select (which the models do even when deleting),
330
-     * and so we only use wpdb directly and only do minimal joins.
331
-     * Transactions are considered "junk" if they're failed for longer than a week.
332
-     * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
333
-     * it, it's probably not junk (regardless of what status it has).
334
-     * The downside to this approach is that is addons are listening for object deletions
335
-     * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
336
-     * to catch these types of deletions.
337
-     *
338
-     * @global WPDB $wpdb
339
-     * @return mixed
340
-     */
341
-    public function delete_junk_transactions()
342
-    {
343
-        /** @type WPDB $wpdb */
344
-        global $wpdb;
345
-        $deleted             = false;
346
-        $time_to_leave_alone = apply_filters(
347
-            'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone',
348
-            WEEK_IN_SECONDS
349
-        );
350
-
351
-
352
-        /**
353
-         * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
354
-         * Useful for plugins that want to exclude transactions matching certain query parameters.
355
-         * The query parameters should be in the format accepted by the EEM_Base model queries.
356
-         */
357
-        $ids_query = apply_filters(
358
-            'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
359
-            array(
360
-                0 => array(
361
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
362
-                    'Payment.PAY_ID' => array( 'IS NULL' ),
363
-                    'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
364
-                ),
365
-                'order_by' => ['TXN_timestamp' => 'ASC'],
366
-                'limit' => 1000
367
-            ),
368
-            $time_to_leave_alone
369
-        );
370
-
371
-
372
-        /**
373
-         * This filter is for when code needs to filter the list of transaction ids that represent transactions
374
-         * about to be deleted based on some other criteria that isn't easily done via the query args filter.
375
-         */
376
-        $txn_ids = apply_filters(
377
-            'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
378
-            EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
379
-            $time_to_leave_alone
380
-        );
381
-        // now that we have the ids to delete
382
-        if (! empty($txn_ids) && is_array($txn_ids)) {
383
-            // first, make sure these TXN's are removed the "ee_locked_transactions" array
384
-            EEM_Transaction::unset_locked_transactions($txn_ids);
385
-
386
-            // Create IDs placeholder.
387
-            $placeholders = array_fill(0, count($txn_ids), '%d');
270
+			OBJECT
271
+		);
272
+	}
273
+
274
+
275
+	/**
276
+	 * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
277
+	 * $_REQUEST global variable. Either way, tries to find the current transaction (through
278
+	 * the registration pointed to by reg_url_link), if not returns null
279
+	 *
280
+	 * @param string $reg_url_link
281
+	 *
282
+	 * @return EE_Transaction
283
+	 */
284
+	public function get_transaction_from_reg_url_link($reg_url_link = '')
285
+	{
286
+		return $this->get_one(array(
287
+			array(
288
+				'Registration.REG_url_link' => ! empty($reg_url_link) ? $reg_url_link : EE_Registry::instance()->REQ->get(
289
+					'e_reg_url_link',
290
+					''
291
+				)
292
+			)
293
+		));
294
+	}
295
+
296
+
297
+	/**
298
+	 * Updates the provided EE_Transaction with all the applicable payments
299
+	 * (or fetch the EE_Transaction from its ID)
300
+	 *
301
+	 * @deprecated
302
+	 *
303
+	 * @param EE_Transaction|int $transaction_obj_or_id
304
+	 * @param boolean            $save_txn whether or not to save the transaction during this function call
305
+	 *
306
+	 * @return boolean
307
+	 * @throws \EE_Error
308
+	 */
309
+	public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
310
+	{
311
+		EE_Error::doing_it_wrong(
312
+			__CLASS__ . '::' . __FUNCTION__,
313
+			sprintf(
314
+				__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
315
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
316
+			),
317
+			'4.6.0'
318
+		);
319
+		/** @type EE_Transaction_Processor $transaction_processor */
320
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
321
+
322
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
323
+			$this->ensure_is_obj($transaction_obj_or_id)
324
+		);
325
+	}
326
+
327
+	/**
328
+	 * Deletes "junk" transactions that were probably added by bots. There might be TONS
329
+	 * of these, so we are very careful to NOT select (which the models do even when deleting),
330
+	 * and so we only use wpdb directly and only do minimal joins.
331
+	 * Transactions are considered "junk" if they're failed for longer than a week.
332
+	 * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
333
+	 * it, it's probably not junk (regardless of what status it has).
334
+	 * The downside to this approach is that is addons are listening for object deletions
335
+	 * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
336
+	 * to catch these types of deletions.
337
+	 *
338
+	 * @global WPDB $wpdb
339
+	 * @return mixed
340
+	 */
341
+	public function delete_junk_transactions()
342
+	{
343
+		/** @type WPDB $wpdb */
344
+		global $wpdb;
345
+		$deleted             = false;
346
+		$time_to_leave_alone = apply_filters(
347
+			'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone',
348
+			WEEK_IN_SECONDS
349
+		);
350
+
351
+
352
+		/**
353
+		 * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
354
+		 * Useful for plugins that want to exclude transactions matching certain query parameters.
355
+		 * The query parameters should be in the format accepted by the EEM_Base model queries.
356
+		 */
357
+		$ids_query = apply_filters(
358
+			'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
359
+			array(
360
+				0 => array(
361
+					'STS_ID'        => EEM_Transaction::failed_status_code,
362
+					'Payment.PAY_ID' => array( 'IS NULL' ),
363
+					'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
364
+				),
365
+				'order_by' => ['TXN_timestamp' => 'ASC'],
366
+				'limit' => 1000
367
+			),
368
+			$time_to_leave_alone
369
+		);
370
+
371
+
372
+		/**
373
+		 * This filter is for when code needs to filter the list of transaction ids that represent transactions
374
+		 * about to be deleted based on some other criteria that isn't easily done via the query args filter.
375
+		 */
376
+		$txn_ids = apply_filters(
377
+			'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
378
+			EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
379
+			$time_to_leave_alone
380
+		);
381
+		// now that we have the ids to delete
382
+		if (! empty($txn_ids) && is_array($txn_ids)) {
383
+			// first, make sure these TXN's are removed the "ee_locked_transactions" array
384
+			EEM_Transaction::unset_locked_transactions($txn_ids);
385
+
386
+			// Create IDs placeholder.
387
+			$placeholders = array_fill(0, count($txn_ids), '%d');
388 388
             
389
-            // Glue it together to use inside $wpdb->prepare.
390
-            $format = implode(', ', $placeholders);
391
-
392
-            // let's get deletin'...
393
-            // We got the ids from the original query to get them FROM
394
-            // the db (which is sanitized) so no need to prepare them again.
395
-            $query   = $wpdb->prepare("DELETE FROM " . $this->table() . " WHERE TXN_ID IN ( $format )", $txn_ids);
396
-            $deleted = $wpdb->query($query);
397
-        }
398
-        if ($deleted) {
399
-            /**
400
-             * Allows code to do something after the transactions have been deleted.
401
-             */
402
-            do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
403
-        }
404
-
405
-        return $deleted;
406
-    }
407
-
408
-
409
-    /**
410
-     * @param array $transaction_IDs
411
-     *
412
-     * @return bool
413
-     */
414
-    public static function unset_locked_transactions(array $transaction_IDs)
415
-    {
416
-        $locked_transactions = get_option('ee_locked_transactions', array());
417
-        $update              = false;
418
-        foreach ($transaction_IDs as $TXN_ID) {
419
-            if (isset($locked_transactions[ $TXN_ID ])) {
420
-                unset($locked_transactions[ $TXN_ID ]);
421
-                $update = true;
422
-            }
423
-        }
424
-        if ($update) {
425
-            update_option('ee_locked_transactions', $locked_transactions);
426
-        }
427
-
428
-        return $update;
429
-    }
430
-
431
-
432
-
433
-    /**
434
-     * returns an array of EE_Transaction objects whose timestamp is greater than
435
-     * the current time minus the session lifespan, which defaults to 60 minutes
436
-     *
437
-     * @return EE_Base_Class[]|EE_Transaction[]
438
-     * @throws EE_Error
439
-     * @throws InvalidArgumentException
440
-     * @throws InvalidDataTypeException
441
-     * @throws InvalidInterfaceException
442
-     */
443
-    public function get_transactions_in_progress()
444
-    {
445
-        return $this->_get_transactions_in_progress();
446
-    }
447
-
448
-
449
-
450
-    /**
451
-     * returns an array of EE_Transaction objects whose timestamp is less than
452
-     * the current time minus the session lifespan, which defaults to 60 minutes
453
-     *
454
-     * @return EE_Base_Class[]|EE_Transaction[]
455
-     * @throws EE_Error
456
-     * @throws InvalidArgumentException
457
-     * @throws InvalidDataTypeException
458
-     * @throws InvalidInterfaceException
459
-     */
460
-    public function get_transactions_not_in_progress()
461
-    {
462
-        return $this->_get_transactions_in_progress('<=');
463
-    }
464
-
465
-
466
-
467
-    /**
468
-     * @param string $comparison
469
-     * @return EE_Base_Class[]|EE_Transaction[]
470
-     * @throws EE_Error
471
-     * @throws InvalidArgumentException
472
-     * @throws InvalidDataTypeException
473
-     * @throws InvalidInterfaceException
474
-     */
475
-    private function _get_transactions_in_progress($comparison = '>=')
476
-    {
477
-        $comparison = $comparison === '>=' || $comparison === '<='
478
-            ? $comparison
479
-            : '>=';
480
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
481
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
482
-            'EventEspresso\core\domain\values\session\SessionLifespan'
483
-        );
484
-        return $this->get_all(
485
-            array(
486
-                array(
487
-                    'TXN_timestamp' => array(
488
-                        $comparison,
489
-                        $session_lifespan->expiration()
490
-                    ),
491
-                    'STS_ID' => array(
492
-                        '!=',
493
-                        EEM_Transaction::complete_status_code
494
-                    ),
495
-                )
496
-            )
497
-        );
498
-    }
389
+			// Glue it together to use inside $wpdb->prepare.
390
+			$format = implode(', ', $placeholders);
391
+
392
+			// let's get deletin'...
393
+			// We got the ids from the original query to get them FROM
394
+			// the db (which is sanitized) so no need to prepare them again.
395
+			$query   = $wpdb->prepare("DELETE FROM " . $this->table() . " WHERE TXN_ID IN ( $format )", $txn_ids);
396
+			$deleted = $wpdb->query($query);
397
+		}
398
+		if ($deleted) {
399
+			/**
400
+			 * Allows code to do something after the transactions have been deleted.
401
+			 */
402
+			do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
403
+		}
404
+
405
+		return $deleted;
406
+	}
407
+
408
+
409
+	/**
410
+	 * @param array $transaction_IDs
411
+	 *
412
+	 * @return bool
413
+	 */
414
+	public static function unset_locked_transactions(array $transaction_IDs)
415
+	{
416
+		$locked_transactions = get_option('ee_locked_transactions', array());
417
+		$update              = false;
418
+		foreach ($transaction_IDs as $TXN_ID) {
419
+			if (isset($locked_transactions[ $TXN_ID ])) {
420
+				unset($locked_transactions[ $TXN_ID ]);
421
+				$update = true;
422
+			}
423
+		}
424
+		if ($update) {
425
+			update_option('ee_locked_transactions', $locked_transactions);
426
+		}
427
+
428
+		return $update;
429
+	}
430
+
431
+
432
+
433
+	/**
434
+	 * returns an array of EE_Transaction objects whose timestamp is greater than
435
+	 * the current time minus the session lifespan, which defaults to 60 minutes
436
+	 *
437
+	 * @return EE_Base_Class[]|EE_Transaction[]
438
+	 * @throws EE_Error
439
+	 * @throws InvalidArgumentException
440
+	 * @throws InvalidDataTypeException
441
+	 * @throws InvalidInterfaceException
442
+	 */
443
+	public function get_transactions_in_progress()
444
+	{
445
+		return $this->_get_transactions_in_progress();
446
+	}
447
+
448
+
449
+
450
+	/**
451
+	 * returns an array of EE_Transaction objects whose timestamp is less than
452
+	 * the current time minus the session lifespan, which defaults to 60 minutes
453
+	 *
454
+	 * @return EE_Base_Class[]|EE_Transaction[]
455
+	 * @throws EE_Error
456
+	 * @throws InvalidArgumentException
457
+	 * @throws InvalidDataTypeException
458
+	 * @throws InvalidInterfaceException
459
+	 */
460
+	public function get_transactions_not_in_progress()
461
+	{
462
+		return $this->_get_transactions_in_progress('<=');
463
+	}
464
+
465
+
466
+
467
+	/**
468
+	 * @param string $comparison
469
+	 * @return EE_Base_Class[]|EE_Transaction[]
470
+	 * @throws EE_Error
471
+	 * @throws InvalidArgumentException
472
+	 * @throws InvalidDataTypeException
473
+	 * @throws InvalidInterfaceException
474
+	 */
475
+	private function _get_transactions_in_progress($comparison = '>=')
476
+	{
477
+		$comparison = $comparison === '>=' || $comparison === '<='
478
+			? $comparison
479
+			: '>=';
480
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
481
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
482
+			'EventEspresso\core\domain\values\session\SessionLifespan'
483
+		);
484
+		return $this->get_all(
485
+			array(
486
+				array(
487
+					'TXN_timestamp' => array(
488
+						$comparison,
489
+						$session_lifespan->expiration()
490
+					),
491
+					'STS_ID' => array(
492
+						'!=',
493
+						EEM_Transaction::complete_status_code
494
+					),
495
+				)
496
+			)
497
+		);
498
+	}
499 499
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
                 ),
141 141
             )
142 142
         );
143
-        $this->_model_relations        = array(
143
+        $this->_model_relations = array(
144 144
             'Registration'   => new EE_Has_Many_Relation(),
145 145
             'Payment'        => new EE_Has_Many_Relation(),
146 146
             'Status'         => new EE_Belongs_To_Relation(),
@@ -205,7 +205,7 @@  discard block
 block discarded – undo
205 205
             ),
206 206
             OBJECT,
207 207
             array(
208
-                'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
208
+                'txnDate' => array('DATE('.$query_interval.')', '%s'),
209 209
                 'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
210 210
             )
211 211
         );
@@ -225,17 +225,17 @@  discard block
 block discarded – undo
225 225
     public function get_revenue_per_event_report($period = '-1 month')
226 226
     {
227 227
         global $wpdb;
228
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
229
-        $registration_table         = $wpdb->prefix . 'esp_registration';
230
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
228
+        $transaction_table          = $wpdb->prefix.'esp_transaction';
229
+        $registration_table         = $wpdb->prefix.'esp_registration';
230
+        $registration_payment_table = $wpdb->prefix.'esp_registration_payment';
231 231
         $event_table                = $wpdb->posts;
232
-        $payment_table              = $wpdb->prefix . 'esp_payment';
232
+        $payment_table              = $wpdb->prefix.'esp_payment';
233 233
         $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
234 234
         $approved_payment_status    = EEM_Payment::status_id_approved;
235 235
         $extra_event_on_join        = '';
236 236
         // exclude events not authored by user if permissions in effect
237
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
238
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
237
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
238
+            $extra_event_on_join = ' AND Event.post_author = '.get_current_user_id();
239 239
         }
240 240
 
241 241
         return $wpdb->get_results(
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
     public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
310 310
     {
311 311
         EE_Error::doing_it_wrong(
312
-            __CLASS__ . '::' . __FUNCTION__,
312
+            __CLASS__.'::'.__FUNCTION__,
313 313
             sprintf(
314 314
                 __('This method is deprecated. Please use "%s" instead', 'event_espresso'),
315 315
                 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
             array(
360 360
                 0 => array(
361 361
                     'STS_ID'        => EEM_Transaction::failed_status_code,
362
-                    'Payment.PAY_ID' => array( 'IS NULL' ),
362
+                    'Payment.PAY_ID' => array('IS NULL'),
363 363
                     'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
364 364
                 ),
365 365
                 'order_by' => ['TXN_timestamp' => 'ASC'],
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
             $time_to_leave_alone
380 380
         );
381 381
         // now that we have the ids to delete
382
-        if (! empty($txn_ids) && is_array($txn_ids)) {
382
+        if ( ! empty($txn_ids) && is_array($txn_ids)) {
383 383
             // first, make sure these TXN's are removed the "ee_locked_transactions" array
384 384
             EEM_Transaction::unset_locked_transactions($txn_ids);
385 385
 
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
             // let's get deletin'...
393 393
             // We got the ids from the original query to get them FROM
394 394
             // the db (which is sanitized) so no need to prepare them again.
395
-            $query   = $wpdb->prepare("DELETE FROM " . $this->table() . " WHERE TXN_ID IN ( $format )", $txn_ids);
395
+            $query   = $wpdb->prepare("DELETE FROM ".$this->table()." WHERE TXN_ID IN ( $format )", $txn_ids);
396 396
             $deleted = $wpdb->query($query);
397 397
         }
398 398
         if ($deleted) {
@@ -416,8 +416,8 @@  discard block
 block discarded – undo
416 416
         $locked_transactions = get_option('ee_locked_transactions', array());
417 417
         $update              = false;
418 418
         foreach ($transaction_IDs as $TXN_ID) {
419
-            if (isset($locked_transactions[ $TXN_ID ])) {
420
-                unset($locked_transactions[ $TXN_ID ]);
419
+            if (isset($locked_transactions[$TXN_ID])) {
420
+                unset($locked_transactions[$TXN_ID]);
421 421
                 $update = true;
422 422
             }
423 423
         }
Please login to merge, or discard this patch.