Completed
Branch FET/extra-logging-when-trashin... (2b4c72)
by
unknown
12:24 queued 10:15
created
core/db_classes/EE_Transaction.class.php 1 patch
Indentation   +1730 added lines, -1730 removed lines patch added patch discarded remove patch
@@ -14,1734 +14,1734 @@
 block discarded – undo
14 14
 class EE_Transaction extends EE_Base_Class implements EEI_Transaction
15 15
 {
16 16
 
17
-    /**
18
-     * The length of time in seconds that a lock is applied before being considered expired.
19
-     * It is not long because a transaction should only be locked for the duration of the request that locked it
20
-     */
21
-    const LOCK_EXPIRATION = 2;
22
-
23
-    /**
24
-     * extra meta key for tracking when transactions are deleted and by who
25
-     *
26
-     * @type string
27
-     */
28
-    const EXTRA_META_KEY_TXN_DELETED = 'transaction-deleted';
29
-
30
-    /**
31
-     * txn status upon initial construction.
32
-     *
33
-     * @var string
34
-     */
35
-    protected $_old_txn_status;
36
-
37
-
38
-    /**
39
-     * @param array  $props_n_values          incoming values
40
-     * @param string $timezone                incoming timezone
41
-     *                                        (if not set the timezone set for the website will be used.)
42
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
43
-     *                                        date_format and the second value is the time format
44
-     * @return EE_Transaction
45
-     * @throws EE_Error
46
-     * @throws InvalidArgumentException
47
-     * @throws InvalidDataTypeException
48
-     * @throws InvalidInterfaceException
49
-     * @throws ReflectionException
50
-     */
51
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
52
-    {
53
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
54
-        $txn = $has_object
55
-            ? $has_object
56
-            : new self($props_n_values, false, $timezone, $date_formats);
57
-        if (! $has_object) {
58
-            $txn->set_old_txn_status($txn->status_ID());
59
-        }
60
-        return $txn;
61
-    }
62
-
63
-
64
-    /**
65
-     * @param array  $props_n_values  incoming values from the database
66
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
67
-     *                                the website will be used.
68
-     * @return EE_Transaction
69
-     * @throws EE_Error
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidDataTypeException
72
-     * @throws InvalidInterfaceException
73
-     * @throws ReflectionException
74
-     */
75
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
76
-    {
77
-        $txn = new self($props_n_values, true, $timezone);
78
-        $txn->set_old_txn_status($txn->status_ID());
79
-        return $txn;
80
-    }
81
-
82
-
83
-    /**
84
-     * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
85
-     * If a lock has already been set, then we will attempt to remove it in case it has expired.
86
-     * If that also fails, then an exception is thrown.
87
-     *
88
-     * @throws EE_Error
89
-     * @throws InvalidArgumentException
90
-     * @throws InvalidDataTypeException
91
-     * @throws InvalidInterfaceException
92
-     * @throws ReflectionException
93
-     */
94
-    public function lock()
95
-    {
96
-        // attempt to set lock, but if that fails...
97
-        if (! $this->add_extra_meta('lock', time(), true)) {
98
-            // then attempt to remove the lock in case it is expired
99
-            if ($this->_remove_expired_lock()) {
100
-                // if removal was successful, then try setting lock again
101
-                $this->lock();
102
-            } else {
103
-                // but if the lock can not be removed, then throw an exception
104
-                throw new EE_Error(
105
-                    sprintf(
106
-                        esc_html__(
107
-                            'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
108
-                            'event_espresso'
109
-                        ),
110
-                        $this->ID()
111
-                    )
112
-                );
113
-            }
114
-        }
115
-    }
116
-
117
-
118
-    /**
119
-     * removes transaction lock applied in EE_Transaction::lock()
120
-     *
121
-     * @return int
122
-     * @throws EE_Error
123
-     * @throws InvalidArgumentException
124
-     * @throws InvalidDataTypeException
125
-     * @throws InvalidInterfaceException
126
-     * @throws ReflectionException
127
-     */
128
-    public function unlock()
129
-    {
130
-        return $this->delete_extra_meta('lock');
131
-    }
132
-
133
-
134
-    /**
135
-     * Decides whether or not now is the right time to update the transaction.
136
-     * This is useful because we don't always know if it is safe to update the transaction
137
-     * and its related data. why?
138
-     * because it's possible that the transaction is being used in another
139
-     * request and could overwrite anything we save.
140
-     * So we want to only update the txn once we know that won't happen.
141
-     * We also check that the lock isn't expired, and remove it if it is
142
-     *
143
-     * @return boolean
144
-     * @throws EE_Error
145
-     * @throws InvalidArgumentException
146
-     * @throws InvalidDataTypeException
147
-     * @throws InvalidInterfaceException
148
-     * @throws ReflectionException
149
-     */
150
-    public function is_locked()
151
-    {
152
-        // if TXN is not locked, then return false immediately
153
-        if (! $this->_get_lock()) {
154
-            return false;
155
-        }
156
-        // if not, then let's try and remove the lock in case it's expired...
157
-        // _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
158
-        // and a positive number if the lock was removed (ie: number of locks deleted),
159
-        // so we need to return the opposite
160
-        return ! $this->_remove_expired_lock() ? true : false;
161
-    }
162
-
163
-
164
-    /**
165
-     * Gets the meta field indicating that this TXN is locked
166
-     *
167
-     * @return int
168
-     * @throws EE_Error
169
-     * @throws InvalidArgumentException
170
-     * @throws InvalidDataTypeException
171
-     * @throws InvalidInterfaceException
172
-     * @throws ReflectionException
173
-     */
174
-    protected function _get_lock()
175
-    {
176
-        return (int) $this->get_extra_meta('lock', true, 0);
177
-    }
178
-
179
-
180
-    /**
181
-     * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
182
-     *
183
-     * @return int
184
-     * @throws EE_Error
185
-     * @throws InvalidArgumentException
186
-     * @throws InvalidDataTypeException
187
-     * @throws InvalidInterfaceException
188
-     * @throws ReflectionException
189
-     */
190
-    protected function _remove_expired_lock()
191
-    {
192
-        $locked = $this->_get_lock();
193
-        if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
194
-            return $this->unlock();
195
-        }
196
-        return 0;
197
-    }
198
-
199
-
200
-    /**
201
-     * Set transaction total
202
-     *
203
-     * @param float $total total value of transaction
204
-     * @throws EE_Error
205
-     * @throws InvalidArgumentException
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     * @throws ReflectionException
209
-     */
210
-    public function set_total($total = 0.00)
211
-    {
212
-        $this->set('TXN_total', (float) $total);
213
-    }
214
-
215
-
216
-    /**
217
-     * Set Total Amount Paid to Date
218
-     *
219
-     * @param float $total_paid total amount paid to date (sum of all payments)
220
-     * @throws EE_Error
221
-     * @throws InvalidArgumentException
222
-     * @throws InvalidDataTypeException
223
-     * @throws InvalidInterfaceException
224
-     * @throws ReflectionException
225
-     */
226
-    public function set_paid($total_paid = 0.00)
227
-    {
228
-        $this->set('TXN_paid', (float) $total_paid);
229
-    }
230
-
231
-
232
-    /**
233
-     * Set transaction status
234
-     *
235
-     * @param string $status        whether the transaction is open, declined, accepted,
236
-     *                              or any number of custom values that can be set
237
-     * @throws EE_Error
238
-     * @throws InvalidArgumentException
239
-     * @throws InvalidDataTypeException
240
-     * @throws InvalidInterfaceException
241
-     * @throws ReflectionException
242
-     */
243
-    public function set_status($status = '')
244
-    {
245
-        $this->set('STS_ID', $status);
246
-    }
247
-
248
-
249
-    /**
250
-     * Set hash salt
251
-     *
252
-     * @param string $hash_salt required for some payment gateways
253
-     * @throws EE_Error
254
-     * @throws InvalidArgumentException
255
-     * @throws InvalidDataTypeException
256
-     * @throws InvalidInterfaceException
257
-     * @throws ReflectionException
258
-     */
259
-    public function set_hash_salt($hash_salt = '')
260
-    {
261
-        $this->set('TXN_hash_salt', $hash_salt);
262
-    }
263
-
264
-
265
-    /**
266
-     * Sets TXN_reg_steps array
267
-     *
268
-     * @param array $txn_reg_steps
269
-     * @throws EE_Error
270
-     * @throws InvalidArgumentException
271
-     * @throws InvalidDataTypeException
272
-     * @throws InvalidInterfaceException
273
-     * @throws ReflectionException
274
-     */
275
-    public function set_reg_steps(array $txn_reg_steps)
276
-    {
277
-        $this->set('TXN_reg_steps', $txn_reg_steps);
278
-    }
279
-
280
-
281
-    /**
282
-     * Gets TXN_reg_steps
283
-     *
284
-     * @return array
285
-     * @throws EE_Error
286
-     * @throws InvalidArgumentException
287
-     * @throws InvalidDataTypeException
288
-     * @throws InvalidInterfaceException
289
-     * @throws ReflectionException
290
-     */
291
-    public function reg_steps()
292
-    {
293
-        $TXN_reg_steps = $this->get('TXN_reg_steps');
294
-        return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array();
295
-    }
296
-
297
-
298
-    /**
299
-     * @return string of transaction's total cost, with currency symbol and decimal
300
-     * @throws EE_Error
301
-     * @throws InvalidArgumentException
302
-     * @throws InvalidDataTypeException
303
-     * @throws InvalidInterfaceException
304
-     * @throws ReflectionException
305
-     */
306
-    public function pretty_total()
307
-    {
308
-        return $this->get_pretty('TXN_total');
309
-    }
310
-
311
-
312
-    /**
313
-     * Gets the amount paid in a pretty string (formatted and with currency symbol)
314
-     *
315
-     * @return string
316
-     * @throws EE_Error
317
-     * @throws InvalidArgumentException
318
-     * @throws InvalidDataTypeException
319
-     * @throws InvalidInterfaceException
320
-     * @throws ReflectionException
321
-     */
322
-    public function pretty_paid()
323
-    {
324
-        return $this->get_pretty('TXN_paid');
325
-    }
326
-
327
-
328
-    /**
329
-     * calculate the amount remaining for this transaction and return;
330
-     *
331
-     * @return float amount remaining
332
-     * @throws EE_Error
333
-     * @throws InvalidArgumentException
334
-     * @throws InvalidDataTypeException
335
-     * @throws InvalidInterfaceException
336
-     * @throws ReflectionException
337
-     */
338
-    public function remaining()
339
-    {
340
-        return $this->total() - $this->paid();
341
-    }
342
-
343
-
344
-    /**
345
-     * get Transaction Total
346
-     *
347
-     * @return float
348
-     * @throws EE_Error
349
-     * @throws InvalidArgumentException
350
-     * @throws InvalidDataTypeException
351
-     * @throws InvalidInterfaceException
352
-     * @throws ReflectionException
353
-     */
354
-    public function total()
355
-    {
356
-        return (float) $this->get('TXN_total');
357
-    }
358
-
359
-
360
-    /**
361
-     * get Total Amount Paid to Date
362
-     *
363
-     * @return float
364
-     * @throws EE_Error
365
-     * @throws InvalidArgumentException
366
-     * @throws InvalidDataTypeException
367
-     * @throws InvalidInterfaceException
368
-     * @throws ReflectionException
369
-     */
370
-    public function paid()
371
-    {
372
-        return (float) $this->get('TXN_paid');
373
-    }
374
-
375
-
376
-    /**
377
-     * @return mixed|null
378
-     * @throws EE_Error
379
-     * @throws InvalidArgumentException
380
-     * @throws InvalidDataTypeException
381
-     * @throws InvalidInterfaceException
382
-     * @throws ReflectionException
383
-     */
384
-    public function get_cart_session()
385
-    {
386
-        $session_data = (array) $this->get('TXN_session_data');
387
-        return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
388
-            ? $session_data['cart']
389
-            : null;
390
-    }
391
-
392
-
393
-    /**
394
-     * get Transaction session data
395
-     *
396
-     * @return array|mixed
397
-     * @throws EE_Error
398
-     * @throws InvalidArgumentException
399
-     * @throws InvalidDataTypeException
400
-     * @throws InvalidInterfaceException
401
-     * @throws ReflectionException
402
-     */
403
-    public function session_data()
404
-    {
405
-        $session_data = $this->get('TXN_session_data');
406
-        if (empty($session_data)) {
407
-            $session_data = array(
408
-                'id'            => null,
409
-                'user_id'       => null,
410
-                'ip_address'    => null,
411
-                'user_agent'    => null,
412
-                'init_access'   => null,
413
-                'last_access'   => null,
414
-                'pages_visited' => array(),
415
-            );
416
-        }
417
-        return $session_data;
418
-    }
419
-
420
-
421
-    /**
422
-     * Set session data within the TXN object
423
-     *
424
-     * @param EE_Session|array $session_data
425
-     * @throws EE_Error
426
-     * @throws InvalidArgumentException
427
-     * @throws InvalidDataTypeException
428
-     * @throws InvalidInterfaceException
429
-     * @throws ReflectionException
430
-     */
431
-    public function set_txn_session_data($session_data)
432
-    {
433
-        if ($session_data instanceof EE_Session) {
434
-            $this->set('TXN_session_data', $session_data->get_session_data(null, true));
435
-        } else {
436
-            $this->set('TXN_session_data', $session_data);
437
-        }
438
-    }
439
-
440
-
441
-    /**
442
-     * get Transaction hash salt
443
-     *
444
-     * @return mixed
445
-     * @throws EE_Error
446
-     * @throws InvalidArgumentException
447
-     * @throws InvalidDataTypeException
448
-     * @throws InvalidInterfaceException
449
-     * @throws ReflectionException
450
-     */
451
-    public function hash_salt_()
452
-    {
453
-        return $this->get('TXN_hash_salt');
454
-    }
455
-
456
-
457
-    /**
458
-     * Returns the transaction datetime as either:
459
-     *            - unix timestamp format ($format = false, $gmt = true)
460
-     *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
461
-     *              has no affect with this option)), this also may include a timezone abbreviation if the
462
-     *              set timezone in this class differs from what the timezone is on the blog.
463
-     *            - formatted date string including the UTC (timezone) offset (default).
464
-     *
465
-     * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
466
-     * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
467
-     *                          or no UTC offset applied
468
-     * @return string | int
469
-     * @throws EE_Error
470
-     * @throws InvalidArgumentException
471
-     * @throws InvalidDataTypeException
472
-     * @throws InvalidInterfaceException
473
-     * @throws ReflectionException
474
-     */
475
-    public function datetime($format = false, $gmt = false)
476
-    {
477
-        if ($format) {
478
-            return $this->get_pretty('TXN_timestamp');
479
-        }
480
-        if ($gmt) {
481
-            return $this->get_raw('TXN_timestamp');
482
-        }
483
-        return $this->get('TXN_timestamp');
484
-    }
485
-
486
-
487
-    /**
488
-     * Gets registrations on this transaction
489
-     *
490
-     * @param array   $query_params array of query parameters
491
-     * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
492
-     * @return EE_Base_Class[]|EE_Registration[]
493
-     * @throws EE_Error
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidDataTypeException
496
-     * @throws InvalidInterfaceException
497
-     * @throws ReflectionException
498
-     */
499
-    public function registrations($query_params = array(), $get_cached = false)
500
-    {
501
-        $query_params = (empty($query_params) || ! is_array($query_params))
502
-            ? array(
503
-                'order_by' => array(
504
-                    'Event.EVT_name'     => 'ASC',
505
-                    'Attendee.ATT_lname' => 'ASC',
506
-                    'Attendee.ATT_fname' => 'ASC',
507
-                ),
508
-            )
509
-            : $query_params;
510
-        $query_params = $get_cached ? array() : $query_params;
511
-        return $this->get_many_related('Registration', $query_params);
512
-    }
513
-
514
-
515
-    /**
516
-     * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
517
-     * function for getting attendees and how many registrations they each have for an event)
518
-     *
519
-     * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
520
-     * @throws EE_Error
521
-     * @throws InvalidArgumentException
522
-     * @throws InvalidDataTypeException
523
-     * @throws InvalidInterfaceException
524
-     * @throws ReflectionException
525
-     */
526
-    public function attendees()
527
-    {
528
-        return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID())));
529
-    }
530
-
531
-
532
-    /**
533
-     * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
534
-     *
535
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
536
-     * @return EE_Base_Class[]|EE_Payment[]
537
-     * @throws EE_Error
538
-     * @throws InvalidArgumentException
539
-     * @throws InvalidDataTypeException
540
-     * @throws InvalidInterfaceException
541
-     * @throws ReflectionException
542
-     */
543
-    public function payments($query_params = array())
544
-    {
545
-        return $this->get_many_related('Payment', $query_params);
546
-    }
547
-
548
-
549
-    /**
550
-     * gets only approved payments for this transaction
551
-     *
552
-     * @return EE_Base_Class[]|EE_Payment[]
553
-     * @throws EE_Error
554
-     * @throws InvalidArgumentException
555
-     * @throws ReflectionException
556
-     * @throws InvalidDataTypeException
557
-     * @throws InvalidInterfaceException
558
-     */
559
-    public function approved_payments()
560
-    {
561
-        EE_Registry::instance()->load_model('Payment');
562
-        return $this->get_many_related(
563
-            'Payment',
564
-            array(
565
-                array('STS_ID' => EEM_Payment::status_id_approved),
566
-                'order_by' => array('PAY_timestamp' => 'DESC'),
567
-            )
568
-        );
569
-    }
570
-
571
-
572
-    /**
573
-     * Gets all payments which have not been approved
574
-     *
575
-     * @return EE_Base_Class[]|EEI_Payment[]
576
-     * @throws EE_Error if a model is misconfigured somehow
577
-     * @throws InvalidArgumentException
578
-     * @throws InvalidDataTypeException
579
-     * @throws InvalidInterfaceException
580
-     * @throws ReflectionException
581
-     */
582
-    public function pending_payments()
583
-    {
584
-        return $this->get_many_related(
585
-            'Payment',
586
-            array(
587
-                array(
588
-                    'STS_ID' => EEM_Payment::status_id_pending,
589
-                ),
590
-                'order_by' => array(
591
-                    'PAY_timestamp' => 'DESC',
592
-                ),
593
-            )
594
-        );
595
-    }
596
-
597
-
598
-    /**
599
-     * echoes $this->pretty_status()
600
-     *
601
-     * @param bool $show_icons
602
-     * @throws EE_Error
603
-     * @throws InvalidArgumentException
604
-     * @throws InvalidDataTypeException
605
-     * @throws InvalidInterfaceException
606
-     * @throws ReflectionException
607
-     */
608
-    public function e_pretty_status($show_icons = false)
609
-    {
610
-        echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
611
-    }
612
-
613
-
614
-    /**
615
-     * returns a pretty version of the status, good for displaying to users
616
-     *
617
-     * @param bool $show_icons
618
-     * @return string
619
-     * @throws EE_Error
620
-     * @throws InvalidArgumentException
621
-     * @throws InvalidDataTypeException
622
-     * @throws InvalidInterfaceException
623
-     * @throws ReflectionException
624
-     */
625
-    public function pretty_status($show_icons = false)
626
-    {
627
-        $status = EEM_Status::instance()->localized_status(
628
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
629
-            false,
630
-            'sentence'
631
-        );
632
-        $icon = '';
633
-        switch ($this->status_ID()) {
634
-            case EEM_Transaction::complete_status_code:
635
-                $icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : '';
636
-                break;
637
-            case EEM_Transaction::incomplete_status_code:
638
-                $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
639
-                    : '';
640
-                break;
641
-            case EEM_Transaction::abandoned_status_code:
642
-                $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : '';
643
-                break;
644
-            case EEM_Transaction::failed_status_code:
645
-                $icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : '';
646
-                break;
647
-            case EEM_Transaction::overpaid_status_code:
648
-                $icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
649
-                break;
650
-        }
651
-        return $icon . $status[ $this->status_ID() ];
652
-    }
653
-
654
-
655
-    /**
656
-     * get Transaction Status
657
-     *
658
-     * @return mixed
659
-     * @throws EE_Error
660
-     * @throws InvalidArgumentException
661
-     * @throws InvalidDataTypeException
662
-     * @throws InvalidInterfaceException
663
-     * @throws ReflectionException
664
-     */
665
-    public function status_ID()
666
-    {
667
-        return $this->get('STS_ID');
668
-    }
669
-
670
-
671
-    /**
672
-     * Returns TRUE or FALSE for whether or not this transaction cost any money
673
-     *
674
-     * @return boolean
675
-     * @throws EE_Error
676
-     * @throws InvalidArgumentException
677
-     * @throws InvalidDataTypeException
678
-     * @throws InvalidInterfaceException
679
-     * @throws ReflectionException
680
-     */
681
-    public function is_free()
682
-    {
683
-        return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
684
-    }
685
-
686
-
687
-    /**
688
-     * Returns whether this transaction is complete
689
-     * Useful in templates and other logic for deciding if we should ask for another payment...
690
-     *
691
-     * @return boolean
692
-     * @throws EE_Error
693
-     * @throws InvalidArgumentException
694
-     * @throws InvalidDataTypeException
695
-     * @throws InvalidInterfaceException
696
-     * @throws ReflectionException
697
-     */
698
-    public function is_completed()
699
-    {
700
-        return $this->status_ID() === EEM_Transaction::complete_status_code;
701
-    }
702
-
703
-
704
-    /**
705
-     * Returns whether this transaction is incomplete
706
-     * Useful in templates and other logic for deciding if we should ask for another payment...
707
-     *
708
-     * @return boolean
709
-     * @throws EE_Error
710
-     * @throws InvalidArgumentException
711
-     * @throws InvalidDataTypeException
712
-     * @throws InvalidInterfaceException
713
-     * @throws ReflectionException
714
-     */
715
-    public function is_incomplete()
716
-    {
717
-        return $this->status_ID() === EEM_Transaction::incomplete_status_code;
718
-    }
719
-
720
-
721
-    /**
722
-     * Returns whether this transaction is overpaid
723
-     * Useful in templates and other logic for deciding if monies need to be refunded
724
-     *
725
-     * @return boolean
726
-     * @throws EE_Error
727
-     * @throws InvalidArgumentException
728
-     * @throws InvalidDataTypeException
729
-     * @throws InvalidInterfaceException
730
-     * @throws ReflectionException
731
-     */
732
-    public function is_overpaid()
733
-    {
734
-        return $this->status_ID() === EEM_Transaction::overpaid_status_code;
735
-    }
736
-
737
-
738
-    /**
739
-     * Returns whether this transaction was abandoned
740
-     * meaning that the transaction/registration process was somehow interrupted and never completed
741
-     * but that contact information exists for at least one registrant
742
-     *
743
-     * @return boolean
744
-     * @throws EE_Error
745
-     * @throws InvalidArgumentException
746
-     * @throws InvalidDataTypeException
747
-     * @throws InvalidInterfaceException
748
-     * @throws ReflectionException
749
-     */
750
-    public function is_abandoned()
751
-    {
752
-        return $this->status_ID() === EEM_Transaction::abandoned_status_code;
753
-    }
754
-
755
-
756
-    /**
757
-     * Returns whether this transaction failed
758
-     * meaning that the transaction/registration process was somehow interrupted and never completed
759
-     * and that NO contact information exists for any registrants
760
-     *
761
-     * @return boolean
762
-     * @throws EE_Error
763
-     * @throws InvalidArgumentException
764
-     * @throws InvalidDataTypeException
765
-     * @throws InvalidInterfaceException
766
-     * @throws ReflectionException
767
-     */
768
-    public function failed()
769
-    {
770
-        return $this->status_ID() === EEM_Transaction::failed_status_code;
771
-    }
772
-
773
-
774
-    /**
775
-     * This returns the url for the invoice of this transaction
776
-     *
777
-     * @param string $type 'html' or 'pdf' (default is pdf)
778
-     * @return string
779
-     * @throws DomainException
780
-     * @throws EE_Error
781
-     * @throws InvalidArgumentException
782
-     * @throws InvalidDataTypeException
783
-     * @throws InvalidInterfaceException
784
-     * @throws ReflectionException
785
-     */
786
-    public function invoice_url($type = 'html')
787
-    {
788
-        $REG = $this->primary_registration();
789
-        if (! $REG instanceof EE_Registration) {
790
-            return '';
791
-        }
792
-        return $REG->invoice_url($type);
793
-    }
794
-
795
-
796
-    /**
797
-     * Gets the primary registration only
798
-     *
799
-     * @return EE_Base_Class|EE_Registration
800
-     * @throws EE_Error
801
-     * @throws InvalidArgumentException
802
-     * @throws InvalidDataTypeException
803
-     * @throws InvalidInterfaceException
804
-     * @throws ReflectionException
805
-     */
806
-    public function primary_registration()
807
-    {
808
-        $registrations = (array) $this->get_many_related(
809
-            'Registration',
810
-            array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT))
811
-        );
812
-        foreach ($registrations as $registration) {
813
-            // valid registration that is NOT cancelled or declined ?
814
-            if (
815
-                $registration instanceof EE_Registration
816
-                && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
817
-            ) {
818
-                return $registration;
819
-            }
820
-        }
821
-        // nothing valid found, so just return first thing from array of results
822
-        return reset($registrations);
823
-    }
824
-
825
-
826
-    /**
827
-     * Gets the URL for viewing the receipt
828
-     *
829
-     * @param string $type 'pdf' or 'html' (default is 'html')
830
-     * @return string
831
-     * @throws DomainException
832
-     * @throws EE_Error
833
-     * @throws InvalidArgumentException
834
-     * @throws InvalidDataTypeException
835
-     * @throws InvalidInterfaceException
836
-     * @throws ReflectionException
837
-     */
838
-    public function receipt_url($type = 'html')
839
-    {
840
-        $REG = $this->primary_registration();
841
-        if (! $REG instanceof EE_Registration) {
842
-            return '';
843
-        }
844
-        return $REG->receipt_url($type);
845
-    }
846
-
847
-
848
-    /**
849
-     * Gets the URL of the thank you page with this registration REG_url_link added as
850
-     * a query parameter
851
-     *
852
-     * @return string
853
-     * @throws EE_Error
854
-     * @throws InvalidArgumentException
855
-     * @throws InvalidDataTypeException
856
-     * @throws InvalidInterfaceException
857
-     * @throws ReflectionException
858
-     */
859
-    public function payment_overview_url()
860
-    {
861
-        $primary_registration = $this->primary_registration();
862
-        return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
863
-    }
864
-
865
-
866
-    /**
867
-     * @return string
868
-     * @throws EE_Error
869
-     * @throws InvalidArgumentException
870
-     * @throws InvalidDataTypeException
871
-     * @throws InvalidInterfaceException
872
-     * @throws ReflectionException
873
-     */
874
-    public function gateway_response_on_transaction()
875
-    {
876
-        $payment = $this->get_first_related('Payment');
877
-        return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
878
-    }
879
-
880
-
881
-    /**
882
-     * Get the status object of this object
883
-     *
884
-     * @return EE_Base_Class|EE_Status
885
-     * @throws EE_Error
886
-     * @throws InvalidArgumentException
887
-     * @throws InvalidDataTypeException
888
-     * @throws InvalidInterfaceException
889
-     * @throws ReflectionException
890
-     */
891
-    public function status_obj()
892
-    {
893
-        return $this->get_first_related('Status');
894
-    }
895
-
896
-
897
-    /**
898
-     * Gets all the extra meta info on this payment
899
-     *
900
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
901
-     * @return EE_Base_Class[]|EE_Extra_Meta
902
-     * @throws EE_Error
903
-     * @throws InvalidArgumentException
904
-     * @throws InvalidDataTypeException
905
-     * @throws InvalidInterfaceException
906
-     * @throws ReflectionException
907
-     */
908
-    public function extra_meta($query_params = array())
909
-    {
910
-        return $this->get_many_related('Extra_Meta', $query_params);
911
-    }
912
-
913
-
914
-    /**
915
-     * Wrapper for _add_relation_to
916
-     *
917
-     * @param EE_Registration $registration
918
-     * @return EE_Base_Class the relation was added to
919
-     * @throws EE_Error
920
-     * @throws InvalidArgumentException
921
-     * @throws InvalidDataTypeException
922
-     * @throws InvalidInterfaceException
923
-     * @throws ReflectionException
924
-     */
925
-    public function add_registration(EE_Registration $registration)
926
-    {
927
-        return $this->_add_relation_to($registration, 'Registration');
928
-    }
929
-
930
-
931
-    /**
932
-     * Removes the given registration from being related (even before saving this transaction).
933
-     * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
934
-     *
935
-     * @param int $registration_or_id
936
-     * @return EE_Base_Class that was removed from being related
937
-     * @throws EE_Error
938
-     * @throws InvalidArgumentException
939
-     * @throws InvalidDataTypeException
940
-     * @throws InvalidInterfaceException
941
-     * @throws ReflectionException
942
-     */
943
-    public function remove_registration_with_id($registration_or_id)
944
-    {
945
-        return $this->_remove_relation_to($registration_or_id, 'Registration');
946
-    }
947
-
948
-
949
-    /**
950
-     * Gets all the line items which are for ACTUAL items
951
-     *
952
-     * @return EE_Line_Item[]
953
-     * @throws EE_Error
954
-     * @throws InvalidArgumentException
955
-     * @throws InvalidDataTypeException
956
-     * @throws InvalidInterfaceException
957
-     * @throws ReflectionException
958
-     */
959
-    public function items_purchased()
960
-    {
961
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
962
-    }
963
-
964
-
965
-    /**
966
-     * Wrapper for _add_relation_to
967
-     *
968
-     * @param EE_Line_Item $line_item
969
-     * @return EE_Base_Class the relation was added to
970
-     * @throws EE_Error
971
-     * @throws InvalidArgumentException
972
-     * @throws InvalidDataTypeException
973
-     * @throws InvalidInterfaceException
974
-     * @throws ReflectionException
975
-     */
976
-    public function add_line_item(EE_Line_Item $line_item)
977
-    {
978
-        return $this->_add_relation_to($line_item, 'Line_Item');
979
-    }
980
-
981
-
982
-    /**
983
-     * Gets ALL the line items related to this transaction (unstructured)
984
-     *
985
-     * @param array $query_params
986
-     * @return EE_Base_Class[]|EE_Line_Item[]
987
-     * @throws EE_Error
988
-     * @throws InvalidArgumentException
989
-     * @throws InvalidDataTypeException
990
-     * @throws InvalidInterfaceException
991
-     * @throws ReflectionException
992
-     */
993
-    public function line_items($query_params = array())
994
-    {
995
-        return $this->get_many_related('Line_Item', $query_params);
996
-    }
997
-
998
-
999
-    /**
1000
-     * Gets all the line items which are taxes on the total
1001
-     *
1002
-     * @return EE_Line_Item[]
1003
-     * @throws EE_Error
1004
-     * @throws InvalidArgumentException
1005
-     * @throws InvalidDataTypeException
1006
-     * @throws InvalidInterfaceException
1007
-     * @throws ReflectionException
1008
-     */
1009
-    public function tax_items()
1010
-    {
1011
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     * Gets the total line item (which is a parent of all other related line items,
1017
-     * meaning it takes them all into account on its total)
1018
-     *
1019
-     * @param bool $create_if_not_found
1020
-     * @return \EE_Line_Item
1021
-     * @throws EE_Error
1022
-     * @throws InvalidArgumentException
1023
-     * @throws InvalidDataTypeException
1024
-     * @throws InvalidInterfaceException
1025
-     * @throws ReflectionException
1026
-     */
1027
-    public function total_line_item($create_if_not_found = true)
1028
-    {
1029
-        $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1030
-        if (! $item && $create_if_not_found) {
1031
-            $item = EEH_Line_Item::create_total_line_item($this);
1032
-        }
1033
-        return $item;
1034
-    }
1035
-
1036
-
1037
-    /**
1038
-     * Returns the total amount of tax on this transaction
1039
-     * (assumes there's only one tax subtotal line item)
1040
-     *
1041
-     * @return float
1042
-     * @throws EE_Error
1043
-     * @throws InvalidArgumentException
1044
-     * @throws InvalidDataTypeException
1045
-     * @throws InvalidInterfaceException
1046
-     * @throws ReflectionException
1047
-     */
1048
-    public function tax_total()
1049
-    {
1050
-        $tax_line_item = $this->tax_total_line_item();
1051
-        if ($tax_line_item) {
1052
-            return (float) $tax_line_item->total();
1053
-        }
1054
-        return (float) 0;
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * Gets the tax subtotal line item (assumes there's only one)
1060
-     *
1061
-     * @return EE_Line_Item
1062
-     * @throws EE_Error
1063
-     * @throws InvalidArgumentException
1064
-     * @throws InvalidDataTypeException
1065
-     * @throws InvalidInterfaceException
1066
-     * @throws ReflectionException
1067
-     */
1068
-    public function tax_total_line_item()
1069
-    {
1070
-        return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1076
-     *
1077
-     * @return EE_Form_Section_Proper
1078
-     * @throws EE_Error
1079
-     * @throws InvalidArgumentException
1080
-     * @throws InvalidDataTypeException
1081
-     * @throws InvalidInterfaceException
1082
-     * @throws ReflectionException
1083
-     */
1084
-    public function billing_info()
1085
-    {
1086
-        $payment_method = $this->payment_method();
1087
-        if (! $payment_method) {
1088
-            EE_Error::add_error(
1089
-                esc_html__(
1090
-                    'Could not find billing info for transaction because no gateway has been used for it yet',
1091
-                    'event_espresso'
1092
-                ),
1093
-                __FILE__,
1094
-                __FUNCTION__,
1095
-                __LINE__
1096
-            );
1097
-            return null;
1098
-        }
1099
-        $primary_reg = $this->primary_registration();
1100
-        if (! $primary_reg) {
1101
-            EE_Error::add_error(
1102
-                esc_html__(
1103
-                    'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1104
-                    'event_espresso'
1105
-                ),
1106
-                __FILE__,
1107
-                __FUNCTION__,
1108
-                __LINE__
1109
-            );
1110
-            return null;
1111
-        }
1112
-        $attendee = $primary_reg->attendee();
1113
-        if (! $attendee) {
1114
-            EE_Error::add_error(
1115
-                esc_html__(
1116
-                    'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1117
-                    'event_espresso'
1118
-                ),
1119
-                __FILE__,
1120
-                __FUNCTION__,
1121
-                __LINE__
1122
-            );
1123
-            return null;
1124
-        }
1125
-        return $attendee->billing_info_for_payment_method($payment_method);
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * Gets PMD_ID
1131
-     *
1132
-     * @return int
1133
-     * @throws EE_Error
1134
-     * @throws InvalidArgumentException
1135
-     * @throws InvalidDataTypeException
1136
-     * @throws InvalidInterfaceException
1137
-     * @throws ReflectionException
1138
-     */
1139
-    public function payment_method_ID()
1140
-    {
1141
-        return $this->get('PMD_ID');
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     * Sets PMD_ID
1147
-     *
1148
-     * @param int $PMD_ID
1149
-     * @throws EE_Error
1150
-     * @throws InvalidArgumentException
1151
-     * @throws InvalidDataTypeException
1152
-     * @throws InvalidInterfaceException
1153
-     * @throws ReflectionException
1154
-     */
1155
-    public function set_payment_method_ID($PMD_ID)
1156
-    {
1157
-        $this->set('PMD_ID', $PMD_ID);
1158
-    }
1159
-
1160
-
1161
-    /**
1162
-     * Gets the last-used payment method on this transaction
1163
-     * (we COULD just use the last-made payment, but some payment methods, namely
1164
-     * offline ones, dont' create payments)
1165
-     *
1166
-     * @return EE_Payment_Method
1167
-     * @throws EE_Error
1168
-     * @throws InvalidArgumentException
1169
-     * @throws InvalidDataTypeException
1170
-     * @throws InvalidInterfaceException
1171
-     * @throws ReflectionException
1172
-     */
1173
-    public function payment_method()
1174
-    {
1175
-        $pm = $this->get_first_related('Payment_Method');
1176
-        if ($pm instanceof EE_Payment_Method) {
1177
-            return $pm;
1178
-        }
1179
-        $last_payment = $this->last_payment();
1180
-        if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1181
-            return $last_payment->payment_method();
1182
-        }
1183
-        return null;
1184
-    }
1185
-
1186
-
1187
-    /**
1188
-     * Gets the last payment made
1189
-     *
1190
-     * @return EE_Base_Class|EE_Payment
1191
-     * @throws EE_Error
1192
-     * @throws InvalidArgumentException
1193
-     * @throws InvalidDataTypeException
1194
-     * @throws InvalidInterfaceException
1195
-     * @throws ReflectionException
1196
-     */
1197
-    public function last_payment()
1198
-    {
1199
-        return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1200
-    }
1201
-
1202
-
1203
-    /**
1204
-     * Gets all the line items which are unrelated to tickets on this transaction
1205
-     *
1206
-     * @return EE_Line_Item[]
1207
-     * @throws EE_Error
1208
-     * @throws InvalidArgumentException
1209
-     * @throws InvalidDataTypeException
1210
-     * @throws InvalidInterfaceException
1211
-     * @throws ReflectionException
1212
-     */
1213
-    public function non_ticket_line_items()
1214
-    {
1215
-        return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1216
-    }
1217
-
1218
-
1219
-    /**
1220
-     * possibly toggles TXN status
1221
-     *
1222
-     * @param  boolean $update whether to save the TXN
1223
-     * @return bool whether the TXN was saved
1224
-     * @throws EE_Error
1225
-     * @throws InvalidArgumentException
1226
-     * @throws InvalidDataTypeException
1227
-     * @throws InvalidInterfaceException
1228
-     * @throws ReflectionException
1229
-     * @throws RuntimeException
1230
-     */
1231
-    public function update_status_based_on_total_paid($update = true)
1232
-    {
1233
-        // set transaction status based on comparison of TXN_paid vs TXN_total
1234
-        if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1235
-            $new_txn_status = EEM_Transaction::overpaid_status_code;
1236
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1237
-            $new_txn_status = EEM_Transaction::complete_status_code;
1238
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1239
-            $new_txn_status = EEM_Transaction::incomplete_status_code;
1240
-        } else {
1241
-            throw new RuntimeException(
1242
-                esc_html__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1243
-            );
1244
-        }
1245
-        if ($new_txn_status !== $this->status_ID()) {
1246
-            $this->set_status($new_txn_status);
1247
-            if ($update) {
1248
-                return $this->save() ? true : false;
1249
-            }
1250
-        }
1251
-        return false;
1252
-    }
1253
-
1254
-
1255
-    /**
1256
-     * Updates the transaction's status and total_paid based on all the payments
1257
-     * that apply to it
1258
-     *
1259
-     * @deprecated
1260
-     * @return array|bool
1261
-     * @throws EE_Error
1262
-     * @throws InvalidArgumentException
1263
-     * @throws ReflectionException
1264
-     * @throws InvalidDataTypeException
1265
-     * @throws InvalidInterfaceException
1266
-     */
1267
-    public function update_based_on_payments()
1268
-    {
1269
-        EE_Error::doing_it_wrong(
1270
-            __CLASS__ . '::' . __FUNCTION__,
1271
-            sprintf(
1272
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1273
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1274
-            ),
1275
-            '4.6.0'
1276
-        );
1277
-        /** @type EE_Transaction_Processor $transaction_processor */
1278
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1279
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1280
-    }
1281
-
1282
-
1283
-    /**
1284
-     * @return string
1285
-     */
1286
-    public function old_txn_status()
1287
-    {
1288
-        return $this->_old_txn_status;
1289
-    }
1290
-
1291
-
1292
-    /**
1293
-     * @param string $old_txn_status
1294
-     */
1295
-    public function set_old_txn_status($old_txn_status)
1296
-    {
1297
-        // only set the first time
1298
-        if ($this->_old_txn_status === null) {
1299
-            $this->_old_txn_status = $old_txn_status;
1300
-        }
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * reg_status_updated
1306
-     *
1307
-     * @return bool
1308
-     * @throws EE_Error
1309
-     * @throws InvalidArgumentException
1310
-     * @throws InvalidDataTypeException
1311
-     * @throws InvalidInterfaceException
1312
-     * @throws ReflectionException
1313
-     */
1314
-    public function txn_status_updated()
1315
-    {
1316
-        return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1317
-    }
1318
-
1319
-
1320
-    /**
1321
-     * _reg_steps_completed
1322
-     * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1323
-     * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1324
-     * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1325
-     *
1326
-     * @param string $reg_step_slug
1327
-     * @param bool   $check_all
1328
-     * @return bool|int
1329
-     * @throws EE_Error
1330
-     * @throws InvalidArgumentException
1331
-     * @throws InvalidDataTypeException
1332
-     * @throws InvalidInterfaceException
1333
-     * @throws ReflectionException
1334
-     */
1335
-    private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1336
-    {
1337
-        $reg_steps = $this->reg_steps();
1338
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1339
-            return false;
1340
-        }
1341
-        // loop thru reg steps array)
1342
-        foreach ($reg_steps as $slug => $reg_step_completed) {
1343
-            // if NOT checking ALL steps (only checking one step)
1344
-            if (! $check_all) {
1345
-                // and this is the one
1346
-                if ($slug === $reg_step_slug) {
1347
-                    return $reg_step_completed;
1348
-                }
1349
-                // skip to next reg step in loop
1350
-                continue;
1351
-            }
1352
-            // $check_all must be true, else we would never have gotten to this point
1353
-            if ($slug === $reg_step_slug) {
1354
-                // if we reach this point, then we are testing either:
1355
-                // all_reg_steps_completed_except() or
1356
-                // all_reg_steps_completed_except_final_step(),
1357
-                // and since this is the reg step EXCEPTION being tested
1358
-                // we want to return true (yes true) if this reg step is NOT completed
1359
-                // ie: "is everything completed except the final step?"
1360
-                // "that is correct... the final step is not completed, but all others are."
1361
-                return $reg_step_completed !== true;
1362
-            }
1363
-            if ($reg_step_completed !== true) {
1364
-                // if any reg step is NOT completed, then ALL steps are not completed
1365
-                return false;
1366
-            }
1367
-        }
1368
-        return true;
1369
-    }
1370
-
1371
-
1372
-    /**
1373
-     * all_reg_steps_completed
1374
-     * returns:
1375
-     *    true if ALL reg steps have been marked as completed
1376
-     *        or false if any step is not completed
1377
-     *
1378
-     * @return bool
1379
-     * @throws EE_Error
1380
-     * @throws InvalidArgumentException
1381
-     * @throws InvalidDataTypeException
1382
-     * @throws InvalidInterfaceException
1383
-     * @throws ReflectionException
1384
-     */
1385
-    public function all_reg_steps_completed()
1386
-    {
1387
-        return $this->_reg_steps_completed();
1388
-    }
1389
-
1390
-
1391
-    /**
1392
-     * all_reg_steps_completed_except
1393
-     * returns:
1394
-     *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1395
-     *        or false if any other step is not completed
1396
-     *        or false if ALL steps are completed including the exception you are testing !!!
1397
-     *
1398
-     * @param string $exception
1399
-     * @return bool
1400
-     * @throws EE_Error
1401
-     * @throws InvalidArgumentException
1402
-     * @throws InvalidDataTypeException
1403
-     * @throws InvalidInterfaceException
1404
-     * @throws ReflectionException
1405
-     */
1406
-    public function all_reg_steps_completed_except($exception = '')
1407
-    {
1408
-        return $this->_reg_steps_completed($exception);
1409
-    }
1410
-
1411
-
1412
-    /**
1413
-     * all_reg_steps_completed_except
1414
-     * returns:
1415
-     *        true if ALL reg steps, except the final step, have been marked as completed
1416
-     *        or false if any step is not completed
1417
-     *    or false if ALL steps are completed including the final step !!!
1418
-     *
1419
-     * @return bool
1420
-     * @throws EE_Error
1421
-     * @throws InvalidArgumentException
1422
-     * @throws InvalidDataTypeException
1423
-     * @throws InvalidInterfaceException
1424
-     * @throws ReflectionException
1425
-     */
1426
-    public function all_reg_steps_completed_except_final_step()
1427
-    {
1428
-        return $this->_reg_steps_completed('finalize_registration');
1429
-    }
1430
-
1431
-
1432
-    /**
1433
-     * reg_step_completed
1434
-     * returns:
1435
-     *    true if a specific reg step has been marked as completed
1436
-     *    a Unix timestamp if it has been initialized but not yet completed,
1437
-     *    or false if it has not yet been initialized
1438
-     *
1439
-     * @param string $reg_step_slug
1440
-     * @return bool|int
1441
-     * @throws EE_Error
1442
-     * @throws InvalidArgumentException
1443
-     * @throws InvalidDataTypeException
1444
-     * @throws InvalidInterfaceException
1445
-     * @throws ReflectionException
1446
-     */
1447
-    public function reg_step_completed($reg_step_slug)
1448
-    {
1449
-        return $this->_reg_steps_completed($reg_step_slug, false);
1450
-    }
1451
-
1452
-
1453
-    /**
1454
-     * completed_final_reg_step
1455
-     * returns:
1456
-     *    true if the finalize_registration reg step has been marked as completed
1457
-     *    a Unix timestamp if it has been initialized but not yet completed,
1458
-     *    or false if it has not yet been initialized
1459
-     *
1460
-     * @return bool|int
1461
-     * @throws EE_Error
1462
-     * @throws InvalidArgumentException
1463
-     * @throws InvalidDataTypeException
1464
-     * @throws InvalidInterfaceException
1465
-     * @throws ReflectionException
1466
-     */
1467
-    public function final_reg_step_completed()
1468
-    {
1469
-        return $this->_reg_steps_completed('finalize_registration', false);
1470
-    }
1471
-
1472
-
1473
-    /**
1474
-     * set_reg_step_initiated
1475
-     * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1476
-     *
1477
-     * @param string $reg_step_slug
1478
-     * @return boolean
1479
-     * @throws EE_Error
1480
-     * @throws InvalidArgumentException
1481
-     * @throws InvalidDataTypeException
1482
-     * @throws InvalidInterfaceException
1483
-     * @throws ReflectionException
1484
-     */
1485
-    public function set_reg_step_initiated($reg_step_slug)
1486
-    {
1487
-        return $this->_set_reg_step_completed_status($reg_step_slug, time());
1488
-    }
1489
-
1490
-
1491
-    /**
1492
-     * set_reg_step_completed
1493
-     * given a valid TXN_reg_step, this sets the step as completed
1494
-     *
1495
-     * @param string $reg_step_slug
1496
-     * @return boolean
1497
-     * @throws EE_Error
1498
-     * @throws InvalidArgumentException
1499
-     * @throws InvalidDataTypeException
1500
-     * @throws InvalidInterfaceException
1501
-     * @throws ReflectionException
1502
-     */
1503
-    public function set_reg_step_completed($reg_step_slug)
1504
-    {
1505
-        return $this->_set_reg_step_completed_status($reg_step_slug, true);
1506
-    }
1507
-
1508
-
1509
-    /**
1510
-     * set_reg_step_completed
1511
-     * given a valid TXN_reg_step slug, this sets the step as NOT completed
1512
-     *
1513
-     * @param string $reg_step_slug
1514
-     * @return boolean
1515
-     * @throws EE_Error
1516
-     * @throws InvalidArgumentException
1517
-     * @throws InvalidDataTypeException
1518
-     * @throws InvalidInterfaceException
1519
-     * @throws ReflectionException
1520
-     */
1521
-    public function set_reg_step_not_completed($reg_step_slug)
1522
-    {
1523
-        return $this->_set_reg_step_completed_status($reg_step_slug, false);
1524
-    }
1525
-
1526
-
1527
-    /**
1528
-     * set_reg_step_completed
1529
-     * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1530
-     *
1531
-     * @param  string      $reg_step_slug
1532
-     * @param  boolean|int $status
1533
-     * @return boolean
1534
-     * @throws EE_Error
1535
-     * @throws InvalidArgumentException
1536
-     * @throws InvalidDataTypeException
1537
-     * @throws InvalidInterfaceException
1538
-     * @throws ReflectionException
1539
-     */
1540
-    private function _set_reg_step_completed_status($reg_step_slug, $status)
1541
-    {
1542
-        // validate status
1543
-        $status = is_bool($status) || is_int($status) ? $status : false;
1544
-        // get reg steps array
1545
-        $txn_reg_steps = $this->reg_steps();
1546
-        // if reg step does NOT exist
1547
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1548
-            return false;
1549
-        }
1550
-        // if  we're trying to complete a step that is already completed
1551
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1552
-            return true;
1553
-        }
1554
-        // if  we're trying to complete a step that hasn't even started
1555
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1556
-            return false;
1557
-        }
1558
-        // if current status value matches the incoming value (no change)
1559
-        // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1560
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1561
-            // this will happen in cases where multiple AJAX requests occur during the same step
1562
-            return true;
1563
-        }
1564
-        // if we're trying to set a start time, but it has already been set...
1565
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1566
-            // skip the update below, but don't return FALSE so that errors won't be displayed
1567
-            return true;
1568
-        }
1569
-        // update completed status
1570
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1571
-        $this->set_reg_steps($txn_reg_steps);
1572
-        $this->save();
1573
-        return true;
1574
-    }
1575
-
1576
-
1577
-    /**
1578
-     * remove_reg_step
1579
-     * given a valid TXN_reg_step slug, this will remove (unset)
1580
-     * the reg step from the TXN reg step array
1581
-     *
1582
-     * @param string $reg_step_slug
1583
-     * @return void
1584
-     * @throws EE_Error
1585
-     * @throws InvalidArgumentException
1586
-     * @throws InvalidDataTypeException
1587
-     * @throws InvalidInterfaceException
1588
-     * @throws ReflectionException
1589
-     */
1590
-    public function remove_reg_step($reg_step_slug)
1591
-    {
1592
-        // get reg steps array
1593
-        $txn_reg_steps = $this->reg_steps();
1594
-        unset($txn_reg_steps[ $reg_step_slug ]);
1595
-        $this->set_reg_steps($txn_reg_steps);
1596
-    }
1597
-
1598
-
1599
-    /**
1600
-     * toggle_failed_transaction_status
1601
-     * upgrades a TXNs status from failed to abandoned,
1602
-     * meaning that contact information has been captured for at least one registrant
1603
-     *
1604
-     * @param bool $save
1605
-     * @return bool
1606
-     * @throws EE_Error
1607
-     * @throws InvalidArgumentException
1608
-     * @throws InvalidDataTypeException
1609
-     * @throws InvalidInterfaceException
1610
-     * @throws ReflectionException
1611
-     */
1612
-    public function toggle_failed_transaction_status($save = true)
1613
-    {
1614
-        // if TXN status is still set as "failed"...
1615
-        if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1616
-            $this->set_status(EEM_Transaction::abandoned_status_code);
1617
-            if ($save) {
1618
-                $this->save();
1619
-            }
1620
-            return true;
1621
-        }
1622
-        return false;
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * toggle_abandoned_transaction_status
1628
-     * upgrades a TXNs status from failed or abandoned to incomplete
1629
-     *
1630
-     * @return bool
1631
-     * @throws EE_Error
1632
-     * @throws InvalidArgumentException
1633
-     * @throws InvalidDataTypeException
1634
-     * @throws InvalidInterfaceException
1635
-     * @throws ReflectionException
1636
-     */
1637
-    public function toggle_abandoned_transaction_status()
1638
-    {
1639
-        // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1640
-        $txn_status = $this->status_ID();
1641
-        if (
1642
-            $txn_status === EEM_Transaction::failed_status_code
1643
-            || $txn_status === EEM_Transaction::abandoned_status_code
1644
-        ) {
1645
-            // if a contact record for the primary registrant has been created
1646
-            if (
1647
-                $this->primary_registration() instanceof EE_Registration
1648
-                && $this->primary_registration()->attendee() instanceof EE_Attendee
1649
-            ) {
1650
-                $this->set_status(EEM_Transaction::incomplete_status_code);
1651
-            } else {
1652
-                // no contact record? yer abandoned!
1653
-                $this->set_status(EEM_Transaction::abandoned_status_code);
1654
-            }
1655
-            return true;
1656
-        }
1657
-        return false;
1658
-    }
1659
-
1660
-
1661
-    /**
1662
-     * checks if an Abandoned TXN has any related payments, and if so,
1663
-     * updates the TXN status based on the amount paid
1664
-     *
1665
-     * @throws EE_Error
1666
-     * @throws InvalidArgumentException
1667
-     * @throws InvalidDataTypeException
1668
-     * @throws InvalidInterfaceException
1669
-     * @throws ReflectionException
1670
-     * @throws RuntimeException
1671
-     * @throws ReflectionException
1672
-     */
1673
-    public function verify_abandoned_transaction_status()
1674
-    {
1675
-        if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1676
-            return;
1677
-        }
1678
-        $payments = $this->get_many_related('Payment');
1679
-        if (! empty($payments)) {
1680
-            foreach ($payments as $payment) {
1681
-                if ($payment instanceof EE_Payment) {
1682
-                    // kk this TXN should NOT be abandoned
1683
-                    $this->update_status_based_on_total_paid();
1684
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1685
-                        EE_Error::add_attention(
1686
-                            sprintf(
1687
-                                esc_html__(
1688
-                                    'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1689
-                                    'event_espresso'
1690
-                                ),
1691
-                                $this->ID(),
1692
-                                $this->pretty_status()
1693
-                            )
1694
-                        );
1695
-                    }
1696
-                    // get final reg step status
1697
-                    $finalized = $this->final_reg_step_completed();
1698
-                    // if the 'finalize_registration' step has been initiated (has a timestamp)
1699
-                    // but has not yet been fully completed (TRUE)
1700
-                    if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1701
-                        $this->set_reg_step_completed('finalize_registration');
1702
-                        $this->save();
1703
-                    }
1704
-                }
1705
-            }
1706
-        }
1707
-    }
1708
-
1709
-
1710
-    /**
1711
-     * @since 4.10.4.p
1712
-     * @throws EE_Error
1713
-     * @throws InvalidArgumentException
1714
-     * @throws InvalidDataTypeException
1715
-     * @throws InvalidInterfaceException
1716
-     * @throws ReflectionException
1717
-     * @throws RuntimeException
1718
-     */
1719
-    public function recalculateLineItems()
1720
-    {
1721
-        $total_line_item = $this->total_line_item(false);
1722
-        if ($total_line_item instanceof EE_Line_Item) {
1723
-            EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1724
-            return EEH_Line_Item::apply_taxes($total_line_item, true);
1725
-        }
1726
-        return false;
1727
-	}
1728
-
1729
-
1730
-    /**
1731
-     * @param string $source function name that called this method
1732
-     * @return boolean | int
1733
-     */
1734
-    public function delete($source = 'unknown')
1735
-    {
1736
-        $current_user = wp_get_current_user();
1737
-        $this->add_extra_meta(
1738
-            EE_Transaction::EXTRA_META_KEY_TXN_DELETED,
1739
-            array(
1740
-                'deleted-by' => $current_user->ID ? $current_user->display_name : 'unauthed user',
1741
-                'timestamp'  => time(),
1742
-                'source'     => $source,
1743
-            )
1744
-        );
1745
-        return parent::delete();
1746
-    }
17
+	/**
18
+	 * The length of time in seconds that a lock is applied before being considered expired.
19
+	 * It is not long because a transaction should only be locked for the duration of the request that locked it
20
+	 */
21
+	const LOCK_EXPIRATION = 2;
22
+
23
+	/**
24
+	 * extra meta key for tracking when transactions are deleted and by who
25
+	 *
26
+	 * @type string
27
+	 */
28
+	const EXTRA_META_KEY_TXN_DELETED = 'transaction-deleted';
29
+
30
+	/**
31
+	 * txn status upon initial construction.
32
+	 *
33
+	 * @var string
34
+	 */
35
+	protected $_old_txn_status;
36
+
37
+
38
+	/**
39
+	 * @param array  $props_n_values          incoming values
40
+	 * @param string $timezone                incoming timezone
41
+	 *                                        (if not set the timezone set for the website will be used.)
42
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
43
+	 *                                        date_format and the second value is the time format
44
+	 * @return EE_Transaction
45
+	 * @throws EE_Error
46
+	 * @throws InvalidArgumentException
47
+	 * @throws InvalidDataTypeException
48
+	 * @throws InvalidInterfaceException
49
+	 * @throws ReflectionException
50
+	 */
51
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
52
+	{
53
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
54
+		$txn = $has_object
55
+			? $has_object
56
+			: new self($props_n_values, false, $timezone, $date_formats);
57
+		if (! $has_object) {
58
+			$txn->set_old_txn_status($txn->status_ID());
59
+		}
60
+		return $txn;
61
+	}
62
+
63
+
64
+	/**
65
+	 * @param array  $props_n_values  incoming values from the database
66
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
67
+	 *                                the website will be used.
68
+	 * @return EE_Transaction
69
+	 * @throws EE_Error
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidDataTypeException
72
+	 * @throws InvalidInterfaceException
73
+	 * @throws ReflectionException
74
+	 */
75
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
76
+	{
77
+		$txn = new self($props_n_values, true, $timezone);
78
+		$txn->set_old_txn_status($txn->status_ID());
79
+		return $txn;
80
+	}
81
+
82
+
83
+	/**
84
+	 * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
85
+	 * If a lock has already been set, then we will attempt to remove it in case it has expired.
86
+	 * If that also fails, then an exception is thrown.
87
+	 *
88
+	 * @throws EE_Error
89
+	 * @throws InvalidArgumentException
90
+	 * @throws InvalidDataTypeException
91
+	 * @throws InvalidInterfaceException
92
+	 * @throws ReflectionException
93
+	 */
94
+	public function lock()
95
+	{
96
+		// attempt to set lock, but if that fails...
97
+		if (! $this->add_extra_meta('lock', time(), true)) {
98
+			// then attempt to remove the lock in case it is expired
99
+			if ($this->_remove_expired_lock()) {
100
+				// if removal was successful, then try setting lock again
101
+				$this->lock();
102
+			} else {
103
+				// but if the lock can not be removed, then throw an exception
104
+				throw new EE_Error(
105
+					sprintf(
106
+						esc_html__(
107
+							'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
108
+							'event_espresso'
109
+						),
110
+						$this->ID()
111
+					)
112
+				);
113
+			}
114
+		}
115
+	}
116
+
117
+
118
+	/**
119
+	 * removes transaction lock applied in EE_Transaction::lock()
120
+	 *
121
+	 * @return int
122
+	 * @throws EE_Error
123
+	 * @throws InvalidArgumentException
124
+	 * @throws InvalidDataTypeException
125
+	 * @throws InvalidInterfaceException
126
+	 * @throws ReflectionException
127
+	 */
128
+	public function unlock()
129
+	{
130
+		return $this->delete_extra_meta('lock');
131
+	}
132
+
133
+
134
+	/**
135
+	 * Decides whether or not now is the right time to update the transaction.
136
+	 * This is useful because we don't always know if it is safe to update the transaction
137
+	 * and its related data. why?
138
+	 * because it's possible that the transaction is being used in another
139
+	 * request and could overwrite anything we save.
140
+	 * So we want to only update the txn once we know that won't happen.
141
+	 * We also check that the lock isn't expired, and remove it if it is
142
+	 *
143
+	 * @return boolean
144
+	 * @throws EE_Error
145
+	 * @throws InvalidArgumentException
146
+	 * @throws InvalidDataTypeException
147
+	 * @throws InvalidInterfaceException
148
+	 * @throws ReflectionException
149
+	 */
150
+	public function is_locked()
151
+	{
152
+		// if TXN is not locked, then return false immediately
153
+		if (! $this->_get_lock()) {
154
+			return false;
155
+		}
156
+		// if not, then let's try and remove the lock in case it's expired...
157
+		// _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
158
+		// and a positive number if the lock was removed (ie: number of locks deleted),
159
+		// so we need to return the opposite
160
+		return ! $this->_remove_expired_lock() ? true : false;
161
+	}
162
+
163
+
164
+	/**
165
+	 * Gets the meta field indicating that this TXN is locked
166
+	 *
167
+	 * @return int
168
+	 * @throws EE_Error
169
+	 * @throws InvalidArgumentException
170
+	 * @throws InvalidDataTypeException
171
+	 * @throws InvalidInterfaceException
172
+	 * @throws ReflectionException
173
+	 */
174
+	protected function _get_lock()
175
+	{
176
+		return (int) $this->get_extra_meta('lock', true, 0);
177
+	}
178
+
179
+
180
+	/**
181
+	 * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
182
+	 *
183
+	 * @return int
184
+	 * @throws EE_Error
185
+	 * @throws InvalidArgumentException
186
+	 * @throws InvalidDataTypeException
187
+	 * @throws InvalidInterfaceException
188
+	 * @throws ReflectionException
189
+	 */
190
+	protected function _remove_expired_lock()
191
+	{
192
+		$locked = $this->_get_lock();
193
+		if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
194
+			return $this->unlock();
195
+		}
196
+		return 0;
197
+	}
198
+
199
+
200
+	/**
201
+	 * Set transaction total
202
+	 *
203
+	 * @param float $total total value of transaction
204
+	 * @throws EE_Error
205
+	 * @throws InvalidArgumentException
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 * @throws ReflectionException
209
+	 */
210
+	public function set_total($total = 0.00)
211
+	{
212
+		$this->set('TXN_total', (float) $total);
213
+	}
214
+
215
+
216
+	/**
217
+	 * Set Total Amount Paid to Date
218
+	 *
219
+	 * @param float $total_paid total amount paid to date (sum of all payments)
220
+	 * @throws EE_Error
221
+	 * @throws InvalidArgumentException
222
+	 * @throws InvalidDataTypeException
223
+	 * @throws InvalidInterfaceException
224
+	 * @throws ReflectionException
225
+	 */
226
+	public function set_paid($total_paid = 0.00)
227
+	{
228
+		$this->set('TXN_paid', (float) $total_paid);
229
+	}
230
+
231
+
232
+	/**
233
+	 * Set transaction status
234
+	 *
235
+	 * @param string $status        whether the transaction is open, declined, accepted,
236
+	 *                              or any number of custom values that can be set
237
+	 * @throws EE_Error
238
+	 * @throws InvalidArgumentException
239
+	 * @throws InvalidDataTypeException
240
+	 * @throws InvalidInterfaceException
241
+	 * @throws ReflectionException
242
+	 */
243
+	public function set_status($status = '')
244
+	{
245
+		$this->set('STS_ID', $status);
246
+	}
247
+
248
+
249
+	/**
250
+	 * Set hash salt
251
+	 *
252
+	 * @param string $hash_salt required for some payment gateways
253
+	 * @throws EE_Error
254
+	 * @throws InvalidArgumentException
255
+	 * @throws InvalidDataTypeException
256
+	 * @throws InvalidInterfaceException
257
+	 * @throws ReflectionException
258
+	 */
259
+	public function set_hash_salt($hash_salt = '')
260
+	{
261
+		$this->set('TXN_hash_salt', $hash_salt);
262
+	}
263
+
264
+
265
+	/**
266
+	 * Sets TXN_reg_steps array
267
+	 *
268
+	 * @param array $txn_reg_steps
269
+	 * @throws EE_Error
270
+	 * @throws InvalidArgumentException
271
+	 * @throws InvalidDataTypeException
272
+	 * @throws InvalidInterfaceException
273
+	 * @throws ReflectionException
274
+	 */
275
+	public function set_reg_steps(array $txn_reg_steps)
276
+	{
277
+		$this->set('TXN_reg_steps', $txn_reg_steps);
278
+	}
279
+
280
+
281
+	/**
282
+	 * Gets TXN_reg_steps
283
+	 *
284
+	 * @return array
285
+	 * @throws EE_Error
286
+	 * @throws InvalidArgumentException
287
+	 * @throws InvalidDataTypeException
288
+	 * @throws InvalidInterfaceException
289
+	 * @throws ReflectionException
290
+	 */
291
+	public function reg_steps()
292
+	{
293
+		$TXN_reg_steps = $this->get('TXN_reg_steps');
294
+		return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array();
295
+	}
296
+
297
+
298
+	/**
299
+	 * @return string of transaction's total cost, with currency symbol and decimal
300
+	 * @throws EE_Error
301
+	 * @throws InvalidArgumentException
302
+	 * @throws InvalidDataTypeException
303
+	 * @throws InvalidInterfaceException
304
+	 * @throws ReflectionException
305
+	 */
306
+	public function pretty_total()
307
+	{
308
+		return $this->get_pretty('TXN_total');
309
+	}
310
+
311
+
312
+	/**
313
+	 * Gets the amount paid in a pretty string (formatted and with currency symbol)
314
+	 *
315
+	 * @return string
316
+	 * @throws EE_Error
317
+	 * @throws InvalidArgumentException
318
+	 * @throws InvalidDataTypeException
319
+	 * @throws InvalidInterfaceException
320
+	 * @throws ReflectionException
321
+	 */
322
+	public function pretty_paid()
323
+	{
324
+		return $this->get_pretty('TXN_paid');
325
+	}
326
+
327
+
328
+	/**
329
+	 * calculate the amount remaining for this transaction and return;
330
+	 *
331
+	 * @return float amount remaining
332
+	 * @throws EE_Error
333
+	 * @throws InvalidArgumentException
334
+	 * @throws InvalidDataTypeException
335
+	 * @throws InvalidInterfaceException
336
+	 * @throws ReflectionException
337
+	 */
338
+	public function remaining()
339
+	{
340
+		return $this->total() - $this->paid();
341
+	}
342
+
343
+
344
+	/**
345
+	 * get Transaction Total
346
+	 *
347
+	 * @return float
348
+	 * @throws EE_Error
349
+	 * @throws InvalidArgumentException
350
+	 * @throws InvalidDataTypeException
351
+	 * @throws InvalidInterfaceException
352
+	 * @throws ReflectionException
353
+	 */
354
+	public function total()
355
+	{
356
+		return (float) $this->get('TXN_total');
357
+	}
358
+
359
+
360
+	/**
361
+	 * get Total Amount Paid to Date
362
+	 *
363
+	 * @return float
364
+	 * @throws EE_Error
365
+	 * @throws InvalidArgumentException
366
+	 * @throws InvalidDataTypeException
367
+	 * @throws InvalidInterfaceException
368
+	 * @throws ReflectionException
369
+	 */
370
+	public function paid()
371
+	{
372
+		return (float) $this->get('TXN_paid');
373
+	}
374
+
375
+
376
+	/**
377
+	 * @return mixed|null
378
+	 * @throws EE_Error
379
+	 * @throws InvalidArgumentException
380
+	 * @throws InvalidDataTypeException
381
+	 * @throws InvalidInterfaceException
382
+	 * @throws ReflectionException
383
+	 */
384
+	public function get_cart_session()
385
+	{
386
+		$session_data = (array) $this->get('TXN_session_data');
387
+		return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
388
+			? $session_data['cart']
389
+			: null;
390
+	}
391
+
392
+
393
+	/**
394
+	 * get Transaction session data
395
+	 *
396
+	 * @return array|mixed
397
+	 * @throws EE_Error
398
+	 * @throws InvalidArgumentException
399
+	 * @throws InvalidDataTypeException
400
+	 * @throws InvalidInterfaceException
401
+	 * @throws ReflectionException
402
+	 */
403
+	public function session_data()
404
+	{
405
+		$session_data = $this->get('TXN_session_data');
406
+		if (empty($session_data)) {
407
+			$session_data = array(
408
+				'id'            => null,
409
+				'user_id'       => null,
410
+				'ip_address'    => null,
411
+				'user_agent'    => null,
412
+				'init_access'   => null,
413
+				'last_access'   => null,
414
+				'pages_visited' => array(),
415
+			);
416
+		}
417
+		return $session_data;
418
+	}
419
+
420
+
421
+	/**
422
+	 * Set session data within the TXN object
423
+	 *
424
+	 * @param EE_Session|array $session_data
425
+	 * @throws EE_Error
426
+	 * @throws InvalidArgumentException
427
+	 * @throws InvalidDataTypeException
428
+	 * @throws InvalidInterfaceException
429
+	 * @throws ReflectionException
430
+	 */
431
+	public function set_txn_session_data($session_data)
432
+	{
433
+		if ($session_data instanceof EE_Session) {
434
+			$this->set('TXN_session_data', $session_data->get_session_data(null, true));
435
+		} else {
436
+			$this->set('TXN_session_data', $session_data);
437
+		}
438
+	}
439
+
440
+
441
+	/**
442
+	 * get Transaction hash salt
443
+	 *
444
+	 * @return mixed
445
+	 * @throws EE_Error
446
+	 * @throws InvalidArgumentException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws InvalidInterfaceException
449
+	 * @throws ReflectionException
450
+	 */
451
+	public function hash_salt_()
452
+	{
453
+		return $this->get('TXN_hash_salt');
454
+	}
455
+
456
+
457
+	/**
458
+	 * Returns the transaction datetime as either:
459
+	 *            - unix timestamp format ($format = false, $gmt = true)
460
+	 *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
461
+	 *              has no affect with this option)), this also may include a timezone abbreviation if the
462
+	 *              set timezone in this class differs from what the timezone is on the blog.
463
+	 *            - formatted date string including the UTC (timezone) offset (default).
464
+	 *
465
+	 * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
466
+	 * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
467
+	 *                          or no UTC offset applied
468
+	 * @return string | int
469
+	 * @throws EE_Error
470
+	 * @throws InvalidArgumentException
471
+	 * @throws InvalidDataTypeException
472
+	 * @throws InvalidInterfaceException
473
+	 * @throws ReflectionException
474
+	 */
475
+	public function datetime($format = false, $gmt = false)
476
+	{
477
+		if ($format) {
478
+			return $this->get_pretty('TXN_timestamp');
479
+		}
480
+		if ($gmt) {
481
+			return $this->get_raw('TXN_timestamp');
482
+		}
483
+		return $this->get('TXN_timestamp');
484
+	}
485
+
486
+
487
+	/**
488
+	 * Gets registrations on this transaction
489
+	 *
490
+	 * @param array   $query_params array of query parameters
491
+	 * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
492
+	 * @return EE_Base_Class[]|EE_Registration[]
493
+	 * @throws EE_Error
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws InvalidInterfaceException
497
+	 * @throws ReflectionException
498
+	 */
499
+	public function registrations($query_params = array(), $get_cached = false)
500
+	{
501
+		$query_params = (empty($query_params) || ! is_array($query_params))
502
+			? array(
503
+				'order_by' => array(
504
+					'Event.EVT_name'     => 'ASC',
505
+					'Attendee.ATT_lname' => 'ASC',
506
+					'Attendee.ATT_fname' => 'ASC',
507
+				),
508
+			)
509
+			: $query_params;
510
+		$query_params = $get_cached ? array() : $query_params;
511
+		return $this->get_many_related('Registration', $query_params);
512
+	}
513
+
514
+
515
+	/**
516
+	 * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
517
+	 * function for getting attendees and how many registrations they each have for an event)
518
+	 *
519
+	 * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
520
+	 * @throws EE_Error
521
+	 * @throws InvalidArgumentException
522
+	 * @throws InvalidDataTypeException
523
+	 * @throws InvalidInterfaceException
524
+	 * @throws ReflectionException
525
+	 */
526
+	public function attendees()
527
+	{
528
+		return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID())));
529
+	}
530
+
531
+
532
+	/**
533
+	 * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
534
+	 *
535
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
536
+	 * @return EE_Base_Class[]|EE_Payment[]
537
+	 * @throws EE_Error
538
+	 * @throws InvalidArgumentException
539
+	 * @throws InvalidDataTypeException
540
+	 * @throws InvalidInterfaceException
541
+	 * @throws ReflectionException
542
+	 */
543
+	public function payments($query_params = array())
544
+	{
545
+		return $this->get_many_related('Payment', $query_params);
546
+	}
547
+
548
+
549
+	/**
550
+	 * gets only approved payments for this transaction
551
+	 *
552
+	 * @return EE_Base_Class[]|EE_Payment[]
553
+	 * @throws EE_Error
554
+	 * @throws InvalidArgumentException
555
+	 * @throws ReflectionException
556
+	 * @throws InvalidDataTypeException
557
+	 * @throws InvalidInterfaceException
558
+	 */
559
+	public function approved_payments()
560
+	{
561
+		EE_Registry::instance()->load_model('Payment');
562
+		return $this->get_many_related(
563
+			'Payment',
564
+			array(
565
+				array('STS_ID' => EEM_Payment::status_id_approved),
566
+				'order_by' => array('PAY_timestamp' => 'DESC'),
567
+			)
568
+		);
569
+	}
570
+
571
+
572
+	/**
573
+	 * Gets all payments which have not been approved
574
+	 *
575
+	 * @return EE_Base_Class[]|EEI_Payment[]
576
+	 * @throws EE_Error if a model is misconfigured somehow
577
+	 * @throws InvalidArgumentException
578
+	 * @throws InvalidDataTypeException
579
+	 * @throws InvalidInterfaceException
580
+	 * @throws ReflectionException
581
+	 */
582
+	public function pending_payments()
583
+	{
584
+		return $this->get_many_related(
585
+			'Payment',
586
+			array(
587
+				array(
588
+					'STS_ID' => EEM_Payment::status_id_pending,
589
+				),
590
+				'order_by' => array(
591
+					'PAY_timestamp' => 'DESC',
592
+				),
593
+			)
594
+		);
595
+	}
596
+
597
+
598
+	/**
599
+	 * echoes $this->pretty_status()
600
+	 *
601
+	 * @param bool $show_icons
602
+	 * @throws EE_Error
603
+	 * @throws InvalidArgumentException
604
+	 * @throws InvalidDataTypeException
605
+	 * @throws InvalidInterfaceException
606
+	 * @throws ReflectionException
607
+	 */
608
+	public function e_pretty_status($show_icons = false)
609
+	{
610
+		echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
611
+	}
612
+
613
+
614
+	/**
615
+	 * returns a pretty version of the status, good for displaying to users
616
+	 *
617
+	 * @param bool $show_icons
618
+	 * @return string
619
+	 * @throws EE_Error
620
+	 * @throws InvalidArgumentException
621
+	 * @throws InvalidDataTypeException
622
+	 * @throws InvalidInterfaceException
623
+	 * @throws ReflectionException
624
+	 */
625
+	public function pretty_status($show_icons = false)
626
+	{
627
+		$status = EEM_Status::instance()->localized_status(
628
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
629
+			false,
630
+			'sentence'
631
+		);
632
+		$icon = '';
633
+		switch ($this->status_ID()) {
634
+			case EEM_Transaction::complete_status_code:
635
+				$icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : '';
636
+				break;
637
+			case EEM_Transaction::incomplete_status_code:
638
+				$icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
639
+					: '';
640
+				break;
641
+			case EEM_Transaction::abandoned_status_code:
642
+				$icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : '';
643
+				break;
644
+			case EEM_Transaction::failed_status_code:
645
+				$icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : '';
646
+				break;
647
+			case EEM_Transaction::overpaid_status_code:
648
+				$icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
649
+				break;
650
+		}
651
+		return $icon . $status[ $this->status_ID() ];
652
+	}
653
+
654
+
655
+	/**
656
+	 * get Transaction Status
657
+	 *
658
+	 * @return mixed
659
+	 * @throws EE_Error
660
+	 * @throws InvalidArgumentException
661
+	 * @throws InvalidDataTypeException
662
+	 * @throws InvalidInterfaceException
663
+	 * @throws ReflectionException
664
+	 */
665
+	public function status_ID()
666
+	{
667
+		return $this->get('STS_ID');
668
+	}
669
+
670
+
671
+	/**
672
+	 * Returns TRUE or FALSE for whether or not this transaction cost any money
673
+	 *
674
+	 * @return boolean
675
+	 * @throws EE_Error
676
+	 * @throws InvalidArgumentException
677
+	 * @throws InvalidDataTypeException
678
+	 * @throws InvalidInterfaceException
679
+	 * @throws ReflectionException
680
+	 */
681
+	public function is_free()
682
+	{
683
+		return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
684
+	}
685
+
686
+
687
+	/**
688
+	 * Returns whether this transaction is complete
689
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
690
+	 *
691
+	 * @return boolean
692
+	 * @throws EE_Error
693
+	 * @throws InvalidArgumentException
694
+	 * @throws InvalidDataTypeException
695
+	 * @throws InvalidInterfaceException
696
+	 * @throws ReflectionException
697
+	 */
698
+	public function is_completed()
699
+	{
700
+		return $this->status_ID() === EEM_Transaction::complete_status_code;
701
+	}
702
+
703
+
704
+	/**
705
+	 * Returns whether this transaction is incomplete
706
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
707
+	 *
708
+	 * @return boolean
709
+	 * @throws EE_Error
710
+	 * @throws InvalidArgumentException
711
+	 * @throws InvalidDataTypeException
712
+	 * @throws InvalidInterfaceException
713
+	 * @throws ReflectionException
714
+	 */
715
+	public function is_incomplete()
716
+	{
717
+		return $this->status_ID() === EEM_Transaction::incomplete_status_code;
718
+	}
719
+
720
+
721
+	/**
722
+	 * Returns whether this transaction is overpaid
723
+	 * Useful in templates and other logic for deciding if monies need to be refunded
724
+	 *
725
+	 * @return boolean
726
+	 * @throws EE_Error
727
+	 * @throws InvalidArgumentException
728
+	 * @throws InvalidDataTypeException
729
+	 * @throws InvalidInterfaceException
730
+	 * @throws ReflectionException
731
+	 */
732
+	public function is_overpaid()
733
+	{
734
+		return $this->status_ID() === EEM_Transaction::overpaid_status_code;
735
+	}
736
+
737
+
738
+	/**
739
+	 * Returns whether this transaction was abandoned
740
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
741
+	 * but that contact information exists for at least one registrant
742
+	 *
743
+	 * @return boolean
744
+	 * @throws EE_Error
745
+	 * @throws InvalidArgumentException
746
+	 * @throws InvalidDataTypeException
747
+	 * @throws InvalidInterfaceException
748
+	 * @throws ReflectionException
749
+	 */
750
+	public function is_abandoned()
751
+	{
752
+		return $this->status_ID() === EEM_Transaction::abandoned_status_code;
753
+	}
754
+
755
+
756
+	/**
757
+	 * Returns whether this transaction failed
758
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
759
+	 * and that NO contact information exists for any registrants
760
+	 *
761
+	 * @return boolean
762
+	 * @throws EE_Error
763
+	 * @throws InvalidArgumentException
764
+	 * @throws InvalidDataTypeException
765
+	 * @throws InvalidInterfaceException
766
+	 * @throws ReflectionException
767
+	 */
768
+	public function failed()
769
+	{
770
+		return $this->status_ID() === EEM_Transaction::failed_status_code;
771
+	}
772
+
773
+
774
+	/**
775
+	 * This returns the url for the invoice of this transaction
776
+	 *
777
+	 * @param string $type 'html' or 'pdf' (default is pdf)
778
+	 * @return string
779
+	 * @throws DomainException
780
+	 * @throws EE_Error
781
+	 * @throws InvalidArgumentException
782
+	 * @throws InvalidDataTypeException
783
+	 * @throws InvalidInterfaceException
784
+	 * @throws ReflectionException
785
+	 */
786
+	public function invoice_url($type = 'html')
787
+	{
788
+		$REG = $this->primary_registration();
789
+		if (! $REG instanceof EE_Registration) {
790
+			return '';
791
+		}
792
+		return $REG->invoice_url($type);
793
+	}
794
+
795
+
796
+	/**
797
+	 * Gets the primary registration only
798
+	 *
799
+	 * @return EE_Base_Class|EE_Registration
800
+	 * @throws EE_Error
801
+	 * @throws InvalidArgumentException
802
+	 * @throws InvalidDataTypeException
803
+	 * @throws InvalidInterfaceException
804
+	 * @throws ReflectionException
805
+	 */
806
+	public function primary_registration()
807
+	{
808
+		$registrations = (array) $this->get_many_related(
809
+			'Registration',
810
+			array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT))
811
+		);
812
+		foreach ($registrations as $registration) {
813
+			// valid registration that is NOT cancelled or declined ?
814
+			if (
815
+				$registration instanceof EE_Registration
816
+				&& ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
817
+			) {
818
+				return $registration;
819
+			}
820
+		}
821
+		// nothing valid found, so just return first thing from array of results
822
+		return reset($registrations);
823
+	}
824
+
825
+
826
+	/**
827
+	 * Gets the URL for viewing the receipt
828
+	 *
829
+	 * @param string $type 'pdf' or 'html' (default is 'html')
830
+	 * @return string
831
+	 * @throws DomainException
832
+	 * @throws EE_Error
833
+	 * @throws InvalidArgumentException
834
+	 * @throws InvalidDataTypeException
835
+	 * @throws InvalidInterfaceException
836
+	 * @throws ReflectionException
837
+	 */
838
+	public function receipt_url($type = 'html')
839
+	{
840
+		$REG = $this->primary_registration();
841
+		if (! $REG instanceof EE_Registration) {
842
+			return '';
843
+		}
844
+		return $REG->receipt_url($type);
845
+	}
846
+
847
+
848
+	/**
849
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
850
+	 * a query parameter
851
+	 *
852
+	 * @return string
853
+	 * @throws EE_Error
854
+	 * @throws InvalidArgumentException
855
+	 * @throws InvalidDataTypeException
856
+	 * @throws InvalidInterfaceException
857
+	 * @throws ReflectionException
858
+	 */
859
+	public function payment_overview_url()
860
+	{
861
+		$primary_registration = $this->primary_registration();
862
+		return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
863
+	}
864
+
865
+
866
+	/**
867
+	 * @return string
868
+	 * @throws EE_Error
869
+	 * @throws InvalidArgumentException
870
+	 * @throws InvalidDataTypeException
871
+	 * @throws InvalidInterfaceException
872
+	 * @throws ReflectionException
873
+	 */
874
+	public function gateway_response_on_transaction()
875
+	{
876
+		$payment = $this->get_first_related('Payment');
877
+		return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
878
+	}
879
+
880
+
881
+	/**
882
+	 * Get the status object of this object
883
+	 *
884
+	 * @return EE_Base_Class|EE_Status
885
+	 * @throws EE_Error
886
+	 * @throws InvalidArgumentException
887
+	 * @throws InvalidDataTypeException
888
+	 * @throws InvalidInterfaceException
889
+	 * @throws ReflectionException
890
+	 */
891
+	public function status_obj()
892
+	{
893
+		return $this->get_first_related('Status');
894
+	}
895
+
896
+
897
+	/**
898
+	 * Gets all the extra meta info on this payment
899
+	 *
900
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
901
+	 * @return EE_Base_Class[]|EE_Extra_Meta
902
+	 * @throws EE_Error
903
+	 * @throws InvalidArgumentException
904
+	 * @throws InvalidDataTypeException
905
+	 * @throws InvalidInterfaceException
906
+	 * @throws ReflectionException
907
+	 */
908
+	public function extra_meta($query_params = array())
909
+	{
910
+		return $this->get_many_related('Extra_Meta', $query_params);
911
+	}
912
+
913
+
914
+	/**
915
+	 * Wrapper for _add_relation_to
916
+	 *
917
+	 * @param EE_Registration $registration
918
+	 * @return EE_Base_Class the relation was added to
919
+	 * @throws EE_Error
920
+	 * @throws InvalidArgumentException
921
+	 * @throws InvalidDataTypeException
922
+	 * @throws InvalidInterfaceException
923
+	 * @throws ReflectionException
924
+	 */
925
+	public function add_registration(EE_Registration $registration)
926
+	{
927
+		return $this->_add_relation_to($registration, 'Registration');
928
+	}
929
+
930
+
931
+	/**
932
+	 * Removes the given registration from being related (even before saving this transaction).
933
+	 * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
934
+	 *
935
+	 * @param int $registration_or_id
936
+	 * @return EE_Base_Class that was removed from being related
937
+	 * @throws EE_Error
938
+	 * @throws InvalidArgumentException
939
+	 * @throws InvalidDataTypeException
940
+	 * @throws InvalidInterfaceException
941
+	 * @throws ReflectionException
942
+	 */
943
+	public function remove_registration_with_id($registration_or_id)
944
+	{
945
+		return $this->_remove_relation_to($registration_or_id, 'Registration');
946
+	}
947
+
948
+
949
+	/**
950
+	 * Gets all the line items which are for ACTUAL items
951
+	 *
952
+	 * @return EE_Line_Item[]
953
+	 * @throws EE_Error
954
+	 * @throws InvalidArgumentException
955
+	 * @throws InvalidDataTypeException
956
+	 * @throws InvalidInterfaceException
957
+	 * @throws ReflectionException
958
+	 */
959
+	public function items_purchased()
960
+	{
961
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
962
+	}
963
+
964
+
965
+	/**
966
+	 * Wrapper for _add_relation_to
967
+	 *
968
+	 * @param EE_Line_Item $line_item
969
+	 * @return EE_Base_Class the relation was added to
970
+	 * @throws EE_Error
971
+	 * @throws InvalidArgumentException
972
+	 * @throws InvalidDataTypeException
973
+	 * @throws InvalidInterfaceException
974
+	 * @throws ReflectionException
975
+	 */
976
+	public function add_line_item(EE_Line_Item $line_item)
977
+	{
978
+		return $this->_add_relation_to($line_item, 'Line_Item');
979
+	}
980
+
981
+
982
+	/**
983
+	 * Gets ALL the line items related to this transaction (unstructured)
984
+	 *
985
+	 * @param array $query_params
986
+	 * @return EE_Base_Class[]|EE_Line_Item[]
987
+	 * @throws EE_Error
988
+	 * @throws InvalidArgumentException
989
+	 * @throws InvalidDataTypeException
990
+	 * @throws InvalidInterfaceException
991
+	 * @throws ReflectionException
992
+	 */
993
+	public function line_items($query_params = array())
994
+	{
995
+		return $this->get_many_related('Line_Item', $query_params);
996
+	}
997
+
998
+
999
+	/**
1000
+	 * Gets all the line items which are taxes on the total
1001
+	 *
1002
+	 * @return EE_Line_Item[]
1003
+	 * @throws EE_Error
1004
+	 * @throws InvalidArgumentException
1005
+	 * @throws InvalidDataTypeException
1006
+	 * @throws InvalidInterfaceException
1007
+	 * @throws ReflectionException
1008
+	 */
1009
+	public function tax_items()
1010
+	{
1011
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 * Gets the total line item (which is a parent of all other related line items,
1017
+	 * meaning it takes them all into account on its total)
1018
+	 *
1019
+	 * @param bool $create_if_not_found
1020
+	 * @return \EE_Line_Item
1021
+	 * @throws EE_Error
1022
+	 * @throws InvalidArgumentException
1023
+	 * @throws InvalidDataTypeException
1024
+	 * @throws InvalidInterfaceException
1025
+	 * @throws ReflectionException
1026
+	 */
1027
+	public function total_line_item($create_if_not_found = true)
1028
+	{
1029
+		$item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1030
+		if (! $item && $create_if_not_found) {
1031
+			$item = EEH_Line_Item::create_total_line_item($this);
1032
+		}
1033
+		return $item;
1034
+	}
1035
+
1036
+
1037
+	/**
1038
+	 * Returns the total amount of tax on this transaction
1039
+	 * (assumes there's only one tax subtotal line item)
1040
+	 *
1041
+	 * @return float
1042
+	 * @throws EE_Error
1043
+	 * @throws InvalidArgumentException
1044
+	 * @throws InvalidDataTypeException
1045
+	 * @throws InvalidInterfaceException
1046
+	 * @throws ReflectionException
1047
+	 */
1048
+	public function tax_total()
1049
+	{
1050
+		$tax_line_item = $this->tax_total_line_item();
1051
+		if ($tax_line_item) {
1052
+			return (float) $tax_line_item->total();
1053
+		}
1054
+		return (float) 0;
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * Gets the tax subtotal line item (assumes there's only one)
1060
+	 *
1061
+	 * @return EE_Line_Item
1062
+	 * @throws EE_Error
1063
+	 * @throws InvalidArgumentException
1064
+	 * @throws InvalidDataTypeException
1065
+	 * @throws InvalidInterfaceException
1066
+	 * @throws ReflectionException
1067
+	 */
1068
+	public function tax_total_line_item()
1069
+	{
1070
+		return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1076
+	 *
1077
+	 * @return EE_Form_Section_Proper
1078
+	 * @throws EE_Error
1079
+	 * @throws InvalidArgumentException
1080
+	 * @throws InvalidDataTypeException
1081
+	 * @throws InvalidInterfaceException
1082
+	 * @throws ReflectionException
1083
+	 */
1084
+	public function billing_info()
1085
+	{
1086
+		$payment_method = $this->payment_method();
1087
+		if (! $payment_method) {
1088
+			EE_Error::add_error(
1089
+				esc_html__(
1090
+					'Could not find billing info for transaction because no gateway has been used for it yet',
1091
+					'event_espresso'
1092
+				),
1093
+				__FILE__,
1094
+				__FUNCTION__,
1095
+				__LINE__
1096
+			);
1097
+			return null;
1098
+		}
1099
+		$primary_reg = $this->primary_registration();
1100
+		if (! $primary_reg) {
1101
+			EE_Error::add_error(
1102
+				esc_html__(
1103
+					'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1104
+					'event_espresso'
1105
+				),
1106
+				__FILE__,
1107
+				__FUNCTION__,
1108
+				__LINE__
1109
+			);
1110
+			return null;
1111
+		}
1112
+		$attendee = $primary_reg->attendee();
1113
+		if (! $attendee) {
1114
+			EE_Error::add_error(
1115
+				esc_html__(
1116
+					'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1117
+					'event_espresso'
1118
+				),
1119
+				__FILE__,
1120
+				__FUNCTION__,
1121
+				__LINE__
1122
+			);
1123
+			return null;
1124
+		}
1125
+		return $attendee->billing_info_for_payment_method($payment_method);
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * Gets PMD_ID
1131
+	 *
1132
+	 * @return int
1133
+	 * @throws EE_Error
1134
+	 * @throws InvalidArgumentException
1135
+	 * @throws InvalidDataTypeException
1136
+	 * @throws InvalidInterfaceException
1137
+	 * @throws ReflectionException
1138
+	 */
1139
+	public function payment_method_ID()
1140
+	{
1141
+		return $this->get('PMD_ID');
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 * Sets PMD_ID
1147
+	 *
1148
+	 * @param int $PMD_ID
1149
+	 * @throws EE_Error
1150
+	 * @throws InvalidArgumentException
1151
+	 * @throws InvalidDataTypeException
1152
+	 * @throws InvalidInterfaceException
1153
+	 * @throws ReflectionException
1154
+	 */
1155
+	public function set_payment_method_ID($PMD_ID)
1156
+	{
1157
+		$this->set('PMD_ID', $PMD_ID);
1158
+	}
1159
+
1160
+
1161
+	/**
1162
+	 * Gets the last-used payment method on this transaction
1163
+	 * (we COULD just use the last-made payment, but some payment methods, namely
1164
+	 * offline ones, dont' create payments)
1165
+	 *
1166
+	 * @return EE_Payment_Method
1167
+	 * @throws EE_Error
1168
+	 * @throws InvalidArgumentException
1169
+	 * @throws InvalidDataTypeException
1170
+	 * @throws InvalidInterfaceException
1171
+	 * @throws ReflectionException
1172
+	 */
1173
+	public function payment_method()
1174
+	{
1175
+		$pm = $this->get_first_related('Payment_Method');
1176
+		if ($pm instanceof EE_Payment_Method) {
1177
+			return $pm;
1178
+		}
1179
+		$last_payment = $this->last_payment();
1180
+		if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1181
+			return $last_payment->payment_method();
1182
+		}
1183
+		return null;
1184
+	}
1185
+
1186
+
1187
+	/**
1188
+	 * Gets the last payment made
1189
+	 *
1190
+	 * @return EE_Base_Class|EE_Payment
1191
+	 * @throws EE_Error
1192
+	 * @throws InvalidArgumentException
1193
+	 * @throws InvalidDataTypeException
1194
+	 * @throws InvalidInterfaceException
1195
+	 * @throws ReflectionException
1196
+	 */
1197
+	public function last_payment()
1198
+	{
1199
+		return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1200
+	}
1201
+
1202
+
1203
+	/**
1204
+	 * Gets all the line items which are unrelated to tickets on this transaction
1205
+	 *
1206
+	 * @return EE_Line_Item[]
1207
+	 * @throws EE_Error
1208
+	 * @throws InvalidArgumentException
1209
+	 * @throws InvalidDataTypeException
1210
+	 * @throws InvalidInterfaceException
1211
+	 * @throws ReflectionException
1212
+	 */
1213
+	public function non_ticket_line_items()
1214
+	{
1215
+		return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1216
+	}
1217
+
1218
+
1219
+	/**
1220
+	 * possibly toggles TXN status
1221
+	 *
1222
+	 * @param  boolean $update whether to save the TXN
1223
+	 * @return bool whether the TXN was saved
1224
+	 * @throws EE_Error
1225
+	 * @throws InvalidArgumentException
1226
+	 * @throws InvalidDataTypeException
1227
+	 * @throws InvalidInterfaceException
1228
+	 * @throws ReflectionException
1229
+	 * @throws RuntimeException
1230
+	 */
1231
+	public function update_status_based_on_total_paid($update = true)
1232
+	{
1233
+		// set transaction status based on comparison of TXN_paid vs TXN_total
1234
+		if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1235
+			$new_txn_status = EEM_Transaction::overpaid_status_code;
1236
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1237
+			$new_txn_status = EEM_Transaction::complete_status_code;
1238
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1239
+			$new_txn_status = EEM_Transaction::incomplete_status_code;
1240
+		} else {
1241
+			throw new RuntimeException(
1242
+				esc_html__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1243
+			);
1244
+		}
1245
+		if ($new_txn_status !== $this->status_ID()) {
1246
+			$this->set_status($new_txn_status);
1247
+			if ($update) {
1248
+				return $this->save() ? true : false;
1249
+			}
1250
+		}
1251
+		return false;
1252
+	}
1253
+
1254
+
1255
+	/**
1256
+	 * Updates the transaction's status and total_paid based on all the payments
1257
+	 * that apply to it
1258
+	 *
1259
+	 * @deprecated
1260
+	 * @return array|bool
1261
+	 * @throws EE_Error
1262
+	 * @throws InvalidArgumentException
1263
+	 * @throws ReflectionException
1264
+	 * @throws InvalidDataTypeException
1265
+	 * @throws InvalidInterfaceException
1266
+	 */
1267
+	public function update_based_on_payments()
1268
+	{
1269
+		EE_Error::doing_it_wrong(
1270
+			__CLASS__ . '::' . __FUNCTION__,
1271
+			sprintf(
1272
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1273
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1274
+			),
1275
+			'4.6.0'
1276
+		);
1277
+		/** @type EE_Transaction_Processor $transaction_processor */
1278
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1279
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1280
+	}
1281
+
1282
+
1283
+	/**
1284
+	 * @return string
1285
+	 */
1286
+	public function old_txn_status()
1287
+	{
1288
+		return $this->_old_txn_status;
1289
+	}
1290
+
1291
+
1292
+	/**
1293
+	 * @param string $old_txn_status
1294
+	 */
1295
+	public function set_old_txn_status($old_txn_status)
1296
+	{
1297
+		// only set the first time
1298
+		if ($this->_old_txn_status === null) {
1299
+			$this->_old_txn_status = $old_txn_status;
1300
+		}
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * reg_status_updated
1306
+	 *
1307
+	 * @return bool
1308
+	 * @throws EE_Error
1309
+	 * @throws InvalidArgumentException
1310
+	 * @throws InvalidDataTypeException
1311
+	 * @throws InvalidInterfaceException
1312
+	 * @throws ReflectionException
1313
+	 */
1314
+	public function txn_status_updated()
1315
+	{
1316
+		return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1317
+	}
1318
+
1319
+
1320
+	/**
1321
+	 * _reg_steps_completed
1322
+	 * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1323
+	 * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1324
+	 * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1325
+	 *
1326
+	 * @param string $reg_step_slug
1327
+	 * @param bool   $check_all
1328
+	 * @return bool|int
1329
+	 * @throws EE_Error
1330
+	 * @throws InvalidArgumentException
1331
+	 * @throws InvalidDataTypeException
1332
+	 * @throws InvalidInterfaceException
1333
+	 * @throws ReflectionException
1334
+	 */
1335
+	private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1336
+	{
1337
+		$reg_steps = $this->reg_steps();
1338
+		if (! is_array($reg_steps) || empty($reg_steps)) {
1339
+			return false;
1340
+		}
1341
+		// loop thru reg steps array)
1342
+		foreach ($reg_steps as $slug => $reg_step_completed) {
1343
+			// if NOT checking ALL steps (only checking one step)
1344
+			if (! $check_all) {
1345
+				// and this is the one
1346
+				if ($slug === $reg_step_slug) {
1347
+					return $reg_step_completed;
1348
+				}
1349
+				// skip to next reg step in loop
1350
+				continue;
1351
+			}
1352
+			// $check_all must be true, else we would never have gotten to this point
1353
+			if ($slug === $reg_step_slug) {
1354
+				// if we reach this point, then we are testing either:
1355
+				// all_reg_steps_completed_except() or
1356
+				// all_reg_steps_completed_except_final_step(),
1357
+				// and since this is the reg step EXCEPTION being tested
1358
+				// we want to return true (yes true) if this reg step is NOT completed
1359
+				// ie: "is everything completed except the final step?"
1360
+				// "that is correct... the final step is not completed, but all others are."
1361
+				return $reg_step_completed !== true;
1362
+			}
1363
+			if ($reg_step_completed !== true) {
1364
+				// if any reg step is NOT completed, then ALL steps are not completed
1365
+				return false;
1366
+			}
1367
+		}
1368
+		return true;
1369
+	}
1370
+
1371
+
1372
+	/**
1373
+	 * all_reg_steps_completed
1374
+	 * returns:
1375
+	 *    true if ALL reg steps have been marked as completed
1376
+	 *        or false if any step is not completed
1377
+	 *
1378
+	 * @return bool
1379
+	 * @throws EE_Error
1380
+	 * @throws InvalidArgumentException
1381
+	 * @throws InvalidDataTypeException
1382
+	 * @throws InvalidInterfaceException
1383
+	 * @throws ReflectionException
1384
+	 */
1385
+	public function all_reg_steps_completed()
1386
+	{
1387
+		return $this->_reg_steps_completed();
1388
+	}
1389
+
1390
+
1391
+	/**
1392
+	 * all_reg_steps_completed_except
1393
+	 * returns:
1394
+	 *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1395
+	 *        or false if any other step is not completed
1396
+	 *        or false if ALL steps are completed including the exception you are testing !!!
1397
+	 *
1398
+	 * @param string $exception
1399
+	 * @return bool
1400
+	 * @throws EE_Error
1401
+	 * @throws InvalidArgumentException
1402
+	 * @throws InvalidDataTypeException
1403
+	 * @throws InvalidInterfaceException
1404
+	 * @throws ReflectionException
1405
+	 */
1406
+	public function all_reg_steps_completed_except($exception = '')
1407
+	{
1408
+		return $this->_reg_steps_completed($exception);
1409
+	}
1410
+
1411
+
1412
+	/**
1413
+	 * all_reg_steps_completed_except
1414
+	 * returns:
1415
+	 *        true if ALL reg steps, except the final step, have been marked as completed
1416
+	 *        or false if any step is not completed
1417
+	 *    or false if ALL steps are completed including the final step !!!
1418
+	 *
1419
+	 * @return bool
1420
+	 * @throws EE_Error
1421
+	 * @throws InvalidArgumentException
1422
+	 * @throws InvalidDataTypeException
1423
+	 * @throws InvalidInterfaceException
1424
+	 * @throws ReflectionException
1425
+	 */
1426
+	public function all_reg_steps_completed_except_final_step()
1427
+	{
1428
+		return $this->_reg_steps_completed('finalize_registration');
1429
+	}
1430
+
1431
+
1432
+	/**
1433
+	 * reg_step_completed
1434
+	 * returns:
1435
+	 *    true if a specific reg step has been marked as completed
1436
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1437
+	 *    or false if it has not yet been initialized
1438
+	 *
1439
+	 * @param string $reg_step_slug
1440
+	 * @return bool|int
1441
+	 * @throws EE_Error
1442
+	 * @throws InvalidArgumentException
1443
+	 * @throws InvalidDataTypeException
1444
+	 * @throws InvalidInterfaceException
1445
+	 * @throws ReflectionException
1446
+	 */
1447
+	public function reg_step_completed($reg_step_slug)
1448
+	{
1449
+		return $this->_reg_steps_completed($reg_step_slug, false);
1450
+	}
1451
+
1452
+
1453
+	/**
1454
+	 * completed_final_reg_step
1455
+	 * returns:
1456
+	 *    true if the finalize_registration reg step has been marked as completed
1457
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1458
+	 *    or false if it has not yet been initialized
1459
+	 *
1460
+	 * @return bool|int
1461
+	 * @throws EE_Error
1462
+	 * @throws InvalidArgumentException
1463
+	 * @throws InvalidDataTypeException
1464
+	 * @throws InvalidInterfaceException
1465
+	 * @throws ReflectionException
1466
+	 */
1467
+	public function final_reg_step_completed()
1468
+	{
1469
+		return $this->_reg_steps_completed('finalize_registration', false);
1470
+	}
1471
+
1472
+
1473
+	/**
1474
+	 * set_reg_step_initiated
1475
+	 * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1476
+	 *
1477
+	 * @param string $reg_step_slug
1478
+	 * @return boolean
1479
+	 * @throws EE_Error
1480
+	 * @throws InvalidArgumentException
1481
+	 * @throws InvalidDataTypeException
1482
+	 * @throws InvalidInterfaceException
1483
+	 * @throws ReflectionException
1484
+	 */
1485
+	public function set_reg_step_initiated($reg_step_slug)
1486
+	{
1487
+		return $this->_set_reg_step_completed_status($reg_step_slug, time());
1488
+	}
1489
+
1490
+
1491
+	/**
1492
+	 * set_reg_step_completed
1493
+	 * given a valid TXN_reg_step, this sets the step as completed
1494
+	 *
1495
+	 * @param string $reg_step_slug
1496
+	 * @return boolean
1497
+	 * @throws EE_Error
1498
+	 * @throws InvalidArgumentException
1499
+	 * @throws InvalidDataTypeException
1500
+	 * @throws InvalidInterfaceException
1501
+	 * @throws ReflectionException
1502
+	 */
1503
+	public function set_reg_step_completed($reg_step_slug)
1504
+	{
1505
+		return $this->_set_reg_step_completed_status($reg_step_slug, true);
1506
+	}
1507
+
1508
+
1509
+	/**
1510
+	 * set_reg_step_completed
1511
+	 * given a valid TXN_reg_step slug, this sets the step as NOT completed
1512
+	 *
1513
+	 * @param string $reg_step_slug
1514
+	 * @return boolean
1515
+	 * @throws EE_Error
1516
+	 * @throws InvalidArgumentException
1517
+	 * @throws InvalidDataTypeException
1518
+	 * @throws InvalidInterfaceException
1519
+	 * @throws ReflectionException
1520
+	 */
1521
+	public function set_reg_step_not_completed($reg_step_slug)
1522
+	{
1523
+		return $this->_set_reg_step_completed_status($reg_step_slug, false);
1524
+	}
1525
+
1526
+
1527
+	/**
1528
+	 * set_reg_step_completed
1529
+	 * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1530
+	 *
1531
+	 * @param  string      $reg_step_slug
1532
+	 * @param  boolean|int $status
1533
+	 * @return boolean
1534
+	 * @throws EE_Error
1535
+	 * @throws InvalidArgumentException
1536
+	 * @throws InvalidDataTypeException
1537
+	 * @throws InvalidInterfaceException
1538
+	 * @throws ReflectionException
1539
+	 */
1540
+	private function _set_reg_step_completed_status($reg_step_slug, $status)
1541
+	{
1542
+		// validate status
1543
+		$status = is_bool($status) || is_int($status) ? $status : false;
1544
+		// get reg steps array
1545
+		$txn_reg_steps = $this->reg_steps();
1546
+		// if reg step does NOT exist
1547
+		if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1548
+			return false;
1549
+		}
1550
+		// if  we're trying to complete a step that is already completed
1551
+		if ($txn_reg_steps[ $reg_step_slug ] === true) {
1552
+			return true;
1553
+		}
1554
+		// if  we're trying to complete a step that hasn't even started
1555
+		if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1556
+			return false;
1557
+		}
1558
+		// if current status value matches the incoming value (no change)
1559
+		// type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1560
+		if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1561
+			// this will happen in cases where multiple AJAX requests occur during the same step
1562
+			return true;
1563
+		}
1564
+		// if we're trying to set a start time, but it has already been set...
1565
+		if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1566
+			// skip the update below, but don't return FALSE so that errors won't be displayed
1567
+			return true;
1568
+		}
1569
+		// update completed status
1570
+		$txn_reg_steps[ $reg_step_slug ] = $status;
1571
+		$this->set_reg_steps($txn_reg_steps);
1572
+		$this->save();
1573
+		return true;
1574
+	}
1575
+
1576
+
1577
+	/**
1578
+	 * remove_reg_step
1579
+	 * given a valid TXN_reg_step slug, this will remove (unset)
1580
+	 * the reg step from the TXN reg step array
1581
+	 *
1582
+	 * @param string $reg_step_slug
1583
+	 * @return void
1584
+	 * @throws EE_Error
1585
+	 * @throws InvalidArgumentException
1586
+	 * @throws InvalidDataTypeException
1587
+	 * @throws InvalidInterfaceException
1588
+	 * @throws ReflectionException
1589
+	 */
1590
+	public function remove_reg_step($reg_step_slug)
1591
+	{
1592
+		// get reg steps array
1593
+		$txn_reg_steps = $this->reg_steps();
1594
+		unset($txn_reg_steps[ $reg_step_slug ]);
1595
+		$this->set_reg_steps($txn_reg_steps);
1596
+	}
1597
+
1598
+
1599
+	/**
1600
+	 * toggle_failed_transaction_status
1601
+	 * upgrades a TXNs status from failed to abandoned,
1602
+	 * meaning that contact information has been captured for at least one registrant
1603
+	 *
1604
+	 * @param bool $save
1605
+	 * @return bool
1606
+	 * @throws EE_Error
1607
+	 * @throws InvalidArgumentException
1608
+	 * @throws InvalidDataTypeException
1609
+	 * @throws InvalidInterfaceException
1610
+	 * @throws ReflectionException
1611
+	 */
1612
+	public function toggle_failed_transaction_status($save = true)
1613
+	{
1614
+		// if TXN status is still set as "failed"...
1615
+		if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1616
+			$this->set_status(EEM_Transaction::abandoned_status_code);
1617
+			if ($save) {
1618
+				$this->save();
1619
+			}
1620
+			return true;
1621
+		}
1622
+		return false;
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * toggle_abandoned_transaction_status
1628
+	 * upgrades a TXNs status from failed or abandoned to incomplete
1629
+	 *
1630
+	 * @return bool
1631
+	 * @throws EE_Error
1632
+	 * @throws InvalidArgumentException
1633
+	 * @throws InvalidDataTypeException
1634
+	 * @throws InvalidInterfaceException
1635
+	 * @throws ReflectionException
1636
+	 */
1637
+	public function toggle_abandoned_transaction_status()
1638
+	{
1639
+		// if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1640
+		$txn_status = $this->status_ID();
1641
+		if (
1642
+			$txn_status === EEM_Transaction::failed_status_code
1643
+			|| $txn_status === EEM_Transaction::abandoned_status_code
1644
+		) {
1645
+			// if a contact record for the primary registrant has been created
1646
+			if (
1647
+				$this->primary_registration() instanceof EE_Registration
1648
+				&& $this->primary_registration()->attendee() instanceof EE_Attendee
1649
+			) {
1650
+				$this->set_status(EEM_Transaction::incomplete_status_code);
1651
+			} else {
1652
+				// no contact record? yer abandoned!
1653
+				$this->set_status(EEM_Transaction::abandoned_status_code);
1654
+			}
1655
+			return true;
1656
+		}
1657
+		return false;
1658
+	}
1659
+
1660
+
1661
+	/**
1662
+	 * checks if an Abandoned TXN has any related payments, and if so,
1663
+	 * updates the TXN status based on the amount paid
1664
+	 *
1665
+	 * @throws EE_Error
1666
+	 * @throws InvalidArgumentException
1667
+	 * @throws InvalidDataTypeException
1668
+	 * @throws InvalidInterfaceException
1669
+	 * @throws ReflectionException
1670
+	 * @throws RuntimeException
1671
+	 * @throws ReflectionException
1672
+	 */
1673
+	public function verify_abandoned_transaction_status()
1674
+	{
1675
+		if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1676
+			return;
1677
+		}
1678
+		$payments = $this->get_many_related('Payment');
1679
+		if (! empty($payments)) {
1680
+			foreach ($payments as $payment) {
1681
+				if ($payment instanceof EE_Payment) {
1682
+					// kk this TXN should NOT be abandoned
1683
+					$this->update_status_based_on_total_paid();
1684
+					if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1685
+						EE_Error::add_attention(
1686
+							sprintf(
1687
+								esc_html__(
1688
+									'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1689
+									'event_espresso'
1690
+								),
1691
+								$this->ID(),
1692
+								$this->pretty_status()
1693
+							)
1694
+						);
1695
+					}
1696
+					// get final reg step status
1697
+					$finalized = $this->final_reg_step_completed();
1698
+					// if the 'finalize_registration' step has been initiated (has a timestamp)
1699
+					// but has not yet been fully completed (TRUE)
1700
+					if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1701
+						$this->set_reg_step_completed('finalize_registration');
1702
+						$this->save();
1703
+					}
1704
+				}
1705
+			}
1706
+		}
1707
+	}
1708
+
1709
+
1710
+	/**
1711
+	 * @since 4.10.4.p
1712
+	 * @throws EE_Error
1713
+	 * @throws InvalidArgumentException
1714
+	 * @throws InvalidDataTypeException
1715
+	 * @throws InvalidInterfaceException
1716
+	 * @throws ReflectionException
1717
+	 * @throws RuntimeException
1718
+	 */
1719
+	public function recalculateLineItems()
1720
+	{
1721
+		$total_line_item = $this->total_line_item(false);
1722
+		if ($total_line_item instanceof EE_Line_Item) {
1723
+			EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1724
+			return EEH_Line_Item::apply_taxes($total_line_item, true);
1725
+		}
1726
+		return false;
1727
+	}
1728
+
1729
+
1730
+	/**
1731
+	 * @param string $source function name that called this method
1732
+	 * @return boolean | int
1733
+	 */
1734
+	public function delete($source = 'unknown')
1735
+	{
1736
+		$current_user = wp_get_current_user();
1737
+		$this->add_extra_meta(
1738
+			EE_Transaction::EXTRA_META_KEY_TXN_DELETED,
1739
+			array(
1740
+				'deleted-by' => $current_user->ID ? $current_user->display_name : 'unauthed user',
1741
+				'timestamp'  => time(),
1742
+				'source'     => $source,
1743
+			)
1744
+		);
1745
+		return parent::delete();
1746
+	}
1747 1747
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 2 patches
Indentation   +2531 added lines, -2531 removed lines patch added patch discarded remove patch
@@ -17,2535 +17,2535 @@
 block discarded – undo
17 17
 class EE_Registration extends EE_Soft_Delete_Base_Class implements EEI_Registration, EEI_Admin_Links
18 18
 {
19 19
 
20
-    /**
21
-     * Used to reference when a registration has never been checked in.
22
-     *
23
-     * @deprecated use \EE_Checkin::status_checked_never instead
24
-     * @type int
25
-     */
26
-    const checkin_status_never = 2;
27
-
28
-    /**
29
-     * Used to reference when a registration has been checked in.
30
-     *
31
-     * @deprecated use \EE_Checkin::status_checked_in instead
32
-     * @type int
33
-     */
34
-    const checkin_status_in = 1;
35
-
36
-    /**
37
-     * Used to reference when a registration has been checked out.
38
-     *
39
-     * @deprecated use \EE_Checkin::status_checked_out instead
40
-     * @type int
41
-     */
42
-    const checkin_status_out = 0;
43
-
44
-    /**
45
-     * extra meta key for tracking reg status os trashed registrations
46
-     *
47
-     * @type string
48
-     */
49
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
50
-
51
-    /**
52
-     * extra meta key for tracking if registration has reserved ticket
53
-     *
54
-     * @type string
55
-     */
56
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
57
-
58
-    /**
59
-     * extra meta key for tracking when registrations are trashed and by who
60
-     *
61
-     * @type string
62
-     */
63
-    const EXTRA_META_KEY_REG_TRASHED = 'registration-trashed';
64
-
65
-    /**
66
-     * extra meta key for tracking when registrations are restored and by who
67
-     *
68
-     * @type string
69
-     */
70
-    const EXTRA_META_KEY_REG_RESTORED = 'registration-restored';
71
-
72
-
73
-    /**
74
-     * @param array  $props_n_values          incoming values
75
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
76
-     *                                        used.)
77
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
78
-     *                                        date_format and the second value is the time format
79
-     * @return EE_Registration
80
-     * @throws EE_Error
81
-     * @throws InvalidArgumentException
82
-     * @throws InvalidDataTypeException
83
-     * @throws InvalidInterfaceException
84
-     * @throws ReflectionException
85
-     */
86
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
87
-    {
88
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
89
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
90
-    }
91
-
92
-
93
-    /**
94
-     * @param array  $props_n_values  incoming values from the database
95
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
96
-     *                                the website will be used.
97
-     * @return EE_Registration
98
-     * @throws EE_Error
99
-     * @throws InvalidArgumentException
100
-     * @throws InvalidDataTypeException
101
-     * @throws InvalidInterfaceException
102
-     * @throws ReflectionException
103
-     */
104
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
105
-    {
106
-        return new self($props_n_values, true, $timezone);
107
-    }
108
-
109
-
110
-    /**
111
-     *        Set Event ID
112
-     *
113
-     * @param        int $EVT_ID Event ID
114
-     * @throws DomainException
115
-     * @throws EE_Error
116
-     * @throws EntityNotFoundException
117
-     * @throws InvalidArgumentException
118
-     * @throws InvalidDataTypeException
119
-     * @throws InvalidInterfaceException
120
-     * @throws ReflectionException
121
-     * @throws RuntimeException
122
-     * @throws UnexpectedEntityException
123
-     */
124
-    public function set_event($EVT_ID = 0)
125
-    {
126
-        $this->set('EVT_ID', $EVT_ID);
127
-    }
128
-
129
-
130
-    /**
131
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
132
-     * be routed to internal methods
133
-     *
134
-     * @param string $field_name
135
-     * @param mixed  $field_value
136
-     * @param bool   $use_default
137
-     * @throws DomainException
138
-     * @throws EE_Error
139
-     * @throws EntityNotFoundException
140
-     * @throws InvalidArgumentException
141
-     * @throws InvalidDataTypeException
142
-     * @throws InvalidInterfaceException
143
-     * @throws ReflectionException
144
-     * @throws RuntimeException
145
-     * @throws UnexpectedEntityException
146
-     */
147
-    public function set($field_name, $field_value, $use_default = false)
148
-    {
149
-        switch ($field_name) {
150
-            case 'REG_code':
151
-                if (! empty($field_value) && $this->reg_code() === null) {
152
-                    $this->set_reg_code($field_value, $use_default);
153
-                }
154
-                break;
155
-            case 'STS_ID':
156
-                $this->set_status($field_value, $use_default);
157
-                break;
158
-            default:
159
-                parent::set($field_name, $field_value, $use_default);
160
-        }
161
-    }
162
-
163
-
164
-    /**
165
-     * Set Status ID
166
-     * updates the registration status and ALSO...
167
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
168
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
169
-     *
170
-     * @param string                $new_STS_ID
171
-     * @param boolean               $use_default
172
-     * @param ContextInterface|null $context
173
-     * @return bool
174
-     * @throws DomainException
175
-     * @throws EE_Error
176
-     * @throws EntityNotFoundException
177
-     * @throws InvalidArgumentException
178
-     * @throws InvalidDataTypeException
179
-     * @throws InvalidInterfaceException
180
-     * @throws ReflectionException
181
-     * @throws RuntimeException
182
-     * @throws UnexpectedEntityException
183
-     */
184
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
185
-    {
186
-        // get current REG_Status
187
-        $old_STS_ID = $this->status_ID();
188
-        // if status has changed
189
-        if (
190
-            $old_STS_ID !== $new_STS_ID // and that status has actually changed
191
-            && ! empty($old_STS_ID) // and that old status is actually set
192
-            && ! empty($new_STS_ID) // as well as the new status
193
-            && $this->ID() // ensure registration is in the db
194
-        ) {
195
-            // update internal status first
196
-            parent::set('STS_ID', $new_STS_ID, $use_default);
197
-            // THEN handle other changes that occur when reg status changes
198
-            // TO approved
199
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
200
-                // reserve a space by incrementing ticket and datetime sold values
201
-                $this->reserveRegistrationSpace();
202
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
203
-                // OR FROM  approved
204
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
205
-                // release a space by decrementing ticket and datetime sold values
206
-                $this->releaseRegistrationSpace();
207
-                do_action(
208
-                    'AHEE__EE_Registration__set_status__from_approved',
209
-                    $this,
210
-                    $old_STS_ID,
211
-                    $new_STS_ID,
212
-                    $context
213
-                );
214
-            }
215
-            // update status
216
-            parent::set('STS_ID', $new_STS_ID, $use_default);
217
-            $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
218
-            if ($this->statusChangeUpdatesTransaction($context)) {
219
-                $this->updateTransactionAfterStatusChange();
220
-            }
221
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
222
-            return true;
223
-        }
224
-        // even though the old value matches the new value, it's still good to
225
-        // allow the parent set method to have a say
226
-        parent::set('STS_ID', $new_STS_ID, $use_default);
227
-        return true;
228
-    }
229
-
230
-
231
-    /**
232
-     * update REGs and TXN when cancelled or declined registrations involved
233
-     *
234
-     * @param string                $new_STS_ID
235
-     * @param string                $old_STS_ID
236
-     * @param ContextInterface|null $context
237
-     * @throws EE_Error
238
-     * @throws InvalidArgumentException
239
-     * @throws InvalidDataTypeException
240
-     * @throws InvalidInterfaceException
241
-     * @throws ReflectionException
242
-     * @throws RuntimeException
243
-     */
244
-    private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
245
-    {
246
-        // these reg statuses should not be considered in any calculations involving monies owing
247
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
248
-        // true if registration has been cancelled or declined
249
-        $this->updateIfCanceled(
250
-            $closed_reg_statuses,
251
-            $new_STS_ID,
252
-            $old_STS_ID,
253
-            $context
254
-        );
255
-        $this->updateIfReinstated(
256
-            $closed_reg_statuses,
257
-            $new_STS_ID,
258
-            $old_STS_ID,
259
-            $context
260
-        );
261
-    }
262
-
263
-
264
-    /**
265
-     * update REGs and TXN when cancelled or declined registrations involved
266
-     *
267
-     * @param array                 $closed_reg_statuses
268
-     * @param string                $new_STS_ID
269
-     * @param string                $old_STS_ID
270
-     * @param ContextInterface|null $context
271
-     * @throws EE_Error
272
-     * @throws InvalidArgumentException
273
-     * @throws InvalidDataTypeException
274
-     * @throws InvalidInterfaceException
275
-     * @throws ReflectionException
276
-     * @throws RuntimeException
277
-     */
278
-    private function updateIfCanceled(
279
-        array $closed_reg_statuses,
280
-        $new_STS_ID,
281
-        $old_STS_ID,
282
-        ContextInterface $context = null
283
-    ) {
284
-        // true if registration has been cancelled or declined
285
-        if (
286
-            in_array($new_STS_ID, $closed_reg_statuses, true)
287
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
288
-        ) {
289
-            /** @type EE_Registration_Processor $registration_processor */
290
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
291
-            /** @type EE_Transaction_Processor $transaction_processor */
292
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
293
-            // cancelled or declined registration
294
-            $registration_processor->update_registration_after_being_canceled_or_declined(
295
-                $this,
296
-                $closed_reg_statuses
297
-            );
298
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
299
-                $this,
300
-                $closed_reg_statuses,
301
-                false
302
-            );
303
-            do_action(
304
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
305
-                $this,
306
-                $old_STS_ID,
307
-                $new_STS_ID,
308
-                $context
309
-            );
310
-            return;
311
-        }
312
-    }
313
-
314
-
315
-    /**
316
-     * update REGs and TXN when cancelled or declined registrations involved
317
-     *
318
-     * @param array                 $closed_reg_statuses
319
-     * @param string                $new_STS_ID
320
-     * @param string                $old_STS_ID
321
-     * @param ContextInterface|null $context
322
-     * @throws EE_Error
323
-     * @throws InvalidArgumentException
324
-     * @throws InvalidDataTypeException
325
-     * @throws InvalidInterfaceException
326
-     * @throws ReflectionException
327
-     * @throws RuntimeException
328
-     */
329
-    private function updateIfReinstated(
330
-        array $closed_reg_statuses,
331
-        $new_STS_ID,
332
-        $old_STS_ID,
333
-        ContextInterface $context = null
334
-    ) {
335
-        // true if reinstating cancelled or declined registration
336
-        if (
337
-            in_array($old_STS_ID, $closed_reg_statuses, true)
338
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
339
-        ) {
340
-            /** @type EE_Registration_Processor $registration_processor */
341
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
342
-            /** @type EE_Transaction_Processor $transaction_processor */
343
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
344
-            // reinstating cancelled or declined registration
345
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
346
-                $this,
347
-                $closed_reg_statuses
348
-            );
349
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
350
-                $this,
351
-                $closed_reg_statuses,
352
-                false
353
-            );
354
-            do_action(
355
-                'AHEE__EE_Registration__set_status__after_reinstated',
356
-                $this,
357
-                $old_STS_ID,
358
-                $new_STS_ID,
359
-                $context
360
-            );
361
-        }
362
-    }
363
-
364
-
365
-    /**
366
-     * @param ContextInterface|null $context
367
-     * @return bool
368
-     */
369
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
370
-    {
371
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
372
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
373
-            array('spco_reg_step_attendee_information_process_registrations'),
374
-            $context,
375
-            $this
376
-        );
377
-        return ! (
378
-            $context instanceof ContextInterface
379
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
380
-        );
381
-    }
382
-
383
-
384
-    /**
385
-     * @throws EE_Error
386
-     * @throws EntityNotFoundException
387
-     * @throws InvalidArgumentException
388
-     * @throws InvalidDataTypeException
389
-     * @throws InvalidInterfaceException
390
-     * @throws ReflectionException
391
-     * @throws RuntimeException
392
-     */
393
-    private function updateTransactionAfterStatusChange()
394
-    {
395
-        /** @type EE_Transaction_Payments $transaction_payments */
396
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
397
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
398
-        $this->transaction()->update_status_based_on_total_paid();
399
-    }
400
-
401
-
402
-    /**
403
-     * get Status ID
404
-     *
405
-     * @throws EE_Error
406
-     * @throws InvalidArgumentException
407
-     * @throws InvalidDataTypeException
408
-     * @throws InvalidInterfaceException
409
-     * @throws ReflectionException
410
-     */
411
-    public function status_ID()
412
-    {
413
-        return $this->get('STS_ID');
414
-    }
415
-
416
-
417
-    /**
418
-     * Gets the ticket this registration is for
419
-     *
420
-     * @param boolean $include_archived whether to include archived tickets or not.
421
-     * @return EE_Ticket|EE_Base_Class
422
-     * @throws EE_Error
423
-     * @throws InvalidArgumentException
424
-     * @throws InvalidDataTypeException
425
-     * @throws InvalidInterfaceException
426
-     * @throws ReflectionException
427
-     */
428
-    public function ticket($include_archived = true)
429
-    {
430
-        $query_params = array();
431
-        if ($include_archived) {
432
-            $query_params['default_where_conditions'] = 'none';
433
-        }
434
-        return $this->get_first_related('Ticket', $query_params);
435
-    }
436
-
437
-
438
-    /**
439
-     * Gets the event this registration is for
440
-     *
441
-     * @return EE_Event
442
-     * @throws EE_Error
443
-     * @throws EntityNotFoundException
444
-     * @throws InvalidArgumentException
445
-     * @throws InvalidDataTypeException
446
-     * @throws InvalidInterfaceException
447
-     * @throws ReflectionException
448
-     */
449
-    public function event()
450
-    {
451
-        $event = $this->get_first_related('Event');
452
-        if (! $event instanceof \EE_Event) {
453
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
454
-        }
455
-        return $event;
456
-    }
457
-
458
-
459
-    /**
460
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
461
-     * with the author of the event this registration is for.
462
-     *
463
-     * @since 4.5.0
464
-     * @return int
465
-     * @throws EE_Error
466
-     * @throws EntityNotFoundException
467
-     * @throws InvalidArgumentException
468
-     * @throws InvalidDataTypeException
469
-     * @throws InvalidInterfaceException
470
-     * @throws ReflectionException
471
-     */
472
-    public function wp_user()
473
-    {
474
-        $event = $this->event();
475
-        if ($event instanceof EE_Event) {
476
-            return $event->wp_user();
477
-        }
478
-        return 0;
479
-    }
480
-
481
-
482
-    /**
483
-     * increments this registration's related ticket sold and corresponding datetime sold values
484
-     *
485
-     * @return void
486
-     * @throws DomainException
487
-     * @throws EE_Error
488
-     * @throws EntityNotFoundException
489
-     * @throws InvalidArgumentException
490
-     * @throws InvalidDataTypeException
491
-     * @throws InvalidInterfaceException
492
-     * @throws ReflectionException
493
-     * @throws UnexpectedEntityException
494
-     */
495
-    private function reserveRegistrationSpace()
496
-    {
497
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
498
-        // so stop tracking that this reg has a ticket reserved
499
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
500
-        $ticket = $this->ticket();
501
-        $ticket->increaseSold();
502
-        // possibly set event status to sold out
503
-        $this->event()->perform_sold_out_status_check();
504
-    }
505
-
506
-
507
-    /**
508
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
509
-     *
510
-     * @return void
511
-     * @throws DomainException
512
-     * @throws EE_Error
513
-     * @throws EntityNotFoundException
514
-     * @throws InvalidArgumentException
515
-     * @throws InvalidDataTypeException
516
-     * @throws InvalidInterfaceException
517
-     * @throws ReflectionException
518
-     * @throws UnexpectedEntityException
519
-     */
520
-    private function releaseRegistrationSpace()
521
-    {
522
-        $ticket = $this->ticket();
523
-        $ticket->decreaseSold();
524
-        // possibly change event status from sold out back to previous status
525
-        $this->event()->perform_sold_out_status_check();
526
-    }
527
-
528
-
529
-    /**
530
-     * tracks this registration's ticket reservation in extra meta
531
-     * and can increment related ticket reserved and corresponding datetime reserved values
532
-     *
533
-     * @param bool   $update_ticket if true, will increment ticket and datetime reserved count
534
-     * @param string $source
535
-     * @return void
536
-     * @throws EE_Error
537
-     * @throws InvalidArgumentException
538
-     * @throws InvalidDataTypeException
539
-     * @throws InvalidInterfaceException
540
-     * @throws ReflectionException
541
-     */
542
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
543
-    {
544
-        // only reserve ticket if space is not currently reserved
545
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
546
-            $reserved = $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
547
-            if ($reserved && $update_ticket) {
548
-                $ticket = $this->ticket();
549
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
550
-                $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
551
-                $ticket->save();
552
-            }
553
-        }
554
-    }
555
-
556
-
557
-    /**
558
-     * stops tracking this registration's ticket reservation in extra meta
559
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
560
-     *
561
-     * @param bool   $update_ticket if true, will decrement ticket and datetime reserved count
562
-     * @param string $source
563
-     * @return void
564
-     * @throws EE_Error
565
-     * @throws InvalidArgumentException
566
-     * @throws InvalidDataTypeException
567
-     * @throws InvalidInterfaceException
568
-     * @throws ReflectionException
569
-     */
570
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
571
-    {
572
-        // only release ticket if space is currently reserved
573
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
574
-            $reserved = $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false);
575
-            if ($reserved && $update_ticket) {
576
-                $ticket = $this->ticket();
577
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
578
-                $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
579
-            }
580
-        }
581
-    }
582
-
583
-
584
-    /**
585
-     * Set Attendee ID
586
-     *
587
-     * @param        int $ATT_ID Attendee ID
588
-     * @throws DomainException
589
-     * @throws EE_Error
590
-     * @throws EntityNotFoundException
591
-     * @throws InvalidArgumentException
592
-     * @throws InvalidDataTypeException
593
-     * @throws InvalidInterfaceException
594
-     * @throws ReflectionException
595
-     * @throws RuntimeException
596
-     * @throws UnexpectedEntityException
597
-     */
598
-    public function set_attendee_id($ATT_ID = 0)
599
-    {
600
-        $this->set('ATT_ID', $ATT_ID);
601
-    }
602
-
603
-
604
-    /**
605
-     *        Set Transaction ID
606
-     *
607
-     * @param        int $TXN_ID Transaction ID
608
-     * @throws DomainException
609
-     * @throws EE_Error
610
-     * @throws EntityNotFoundException
611
-     * @throws InvalidArgumentException
612
-     * @throws InvalidDataTypeException
613
-     * @throws InvalidInterfaceException
614
-     * @throws ReflectionException
615
-     * @throws RuntimeException
616
-     * @throws UnexpectedEntityException
617
-     */
618
-    public function set_transaction_id($TXN_ID = 0)
619
-    {
620
-        $this->set('TXN_ID', $TXN_ID);
621
-    }
622
-
623
-
624
-    /**
625
-     *        Set Session
626
-     *
627
-     * @param    string $REG_session PHP Session ID
628
-     * @throws DomainException
629
-     * @throws EE_Error
630
-     * @throws EntityNotFoundException
631
-     * @throws InvalidArgumentException
632
-     * @throws InvalidDataTypeException
633
-     * @throws InvalidInterfaceException
634
-     * @throws ReflectionException
635
-     * @throws RuntimeException
636
-     * @throws UnexpectedEntityException
637
-     */
638
-    public function set_session($REG_session = '')
639
-    {
640
-        $this->set('REG_session', $REG_session);
641
-    }
642
-
643
-
644
-    /**
645
-     *        Set Registration URL Link
646
-     *
647
-     * @param    string $REG_url_link Registration URL Link
648
-     * @throws DomainException
649
-     * @throws EE_Error
650
-     * @throws EntityNotFoundException
651
-     * @throws InvalidArgumentException
652
-     * @throws InvalidDataTypeException
653
-     * @throws InvalidInterfaceException
654
-     * @throws ReflectionException
655
-     * @throws RuntimeException
656
-     * @throws UnexpectedEntityException
657
-     */
658
-    public function set_reg_url_link($REG_url_link = '')
659
-    {
660
-        $this->set('REG_url_link', $REG_url_link);
661
-    }
662
-
663
-
664
-    /**
665
-     *        Set Attendee Counter
666
-     *
667
-     * @param        int $REG_count Primary Attendee
668
-     * @throws DomainException
669
-     * @throws EE_Error
670
-     * @throws EntityNotFoundException
671
-     * @throws InvalidArgumentException
672
-     * @throws InvalidDataTypeException
673
-     * @throws InvalidInterfaceException
674
-     * @throws ReflectionException
675
-     * @throws RuntimeException
676
-     * @throws UnexpectedEntityException
677
-     */
678
-    public function set_count($REG_count = 1)
679
-    {
680
-        $this->set('REG_count', $REG_count);
681
-    }
682
-
683
-
684
-    /**
685
-     *        Set Group Size
686
-     *
687
-     * @param        boolean $REG_group_size Group Registration
688
-     * @throws DomainException
689
-     * @throws EE_Error
690
-     * @throws EntityNotFoundException
691
-     * @throws InvalidArgumentException
692
-     * @throws InvalidDataTypeException
693
-     * @throws InvalidInterfaceException
694
-     * @throws ReflectionException
695
-     * @throws RuntimeException
696
-     * @throws UnexpectedEntityException
697
-     */
698
-    public function set_group_size($REG_group_size = false)
699
-    {
700
-        $this->set('REG_group_size', $REG_group_size);
701
-    }
702
-
703
-
704
-    /**
705
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
706
-     *    EEM_Registration::status_id_not_approved
707
-     *
708
-     * @return        boolean
709
-     * @throws EE_Error
710
-     * @throws InvalidArgumentException
711
-     * @throws InvalidDataTypeException
712
-     * @throws InvalidInterfaceException
713
-     * @throws ReflectionException
714
-     */
715
-    public function is_not_approved()
716
-    {
717
-        return $this->status_ID() === EEM_Registration::status_id_not_approved;
718
-    }
719
-
720
-
721
-    /**
722
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
723
-     *    EEM_Registration::status_id_pending_payment
724
-     *
725
-     * @return        boolean
726
-     * @throws EE_Error
727
-     * @throws InvalidArgumentException
728
-     * @throws InvalidDataTypeException
729
-     * @throws InvalidInterfaceException
730
-     * @throws ReflectionException
731
-     */
732
-    public function is_pending_payment()
733
-    {
734
-        return $this->status_ID() === EEM_Registration::status_id_pending_payment;
735
-    }
736
-
737
-
738
-    /**
739
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
740
-     *
741
-     * @return        boolean
742
-     * @throws EE_Error
743
-     * @throws InvalidArgumentException
744
-     * @throws InvalidDataTypeException
745
-     * @throws InvalidInterfaceException
746
-     * @throws ReflectionException
747
-     */
748
-    public function is_approved()
749
-    {
750
-        return $this->status_ID() === EEM_Registration::status_id_approved;
751
-    }
752
-
753
-
754
-    /**
755
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
756
-     *
757
-     * @return        boolean
758
-     * @throws EE_Error
759
-     * @throws InvalidArgumentException
760
-     * @throws InvalidDataTypeException
761
-     * @throws InvalidInterfaceException
762
-     * @throws ReflectionException
763
-     */
764
-    public function is_cancelled()
765
-    {
766
-        return $this->status_ID() === EEM_Registration::status_id_cancelled;
767
-    }
768
-
769
-
770
-    /**
771
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
772
-     *
773
-     * @return        boolean
774
-     * @throws EE_Error
775
-     * @throws InvalidArgumentException
776
-     * @throws InvalidDataTypeException
777
-     * @throws InvalidInterfaceException
778
-     * @throws ReflectionException
779
-     */
780
-    public function is_declined()
781
-    {
782
-        return $this->status_ID() === EEM_Registration::status_id_declined;
783
-    }
784
-
785
-
786
-    /**
787
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
788
-     *    EEM_Registration::status_id_incomplete
789
-     *
790
-     * @return        boolean
791
-     * @throws EE_Error
792
-     * @throws InvalidArgumentException
793
-     * @throws InvalidDataTypeException
794
-     * @throws InvalidInterfaceException
795
-     * @throws ReflectionException
796
-     */
797
-    public function is_incomplete()
798
-    {
799
-        return $this->status_ID() === EEM_Registration::status_id_incomplete;
800
-    }
801
-
802
-
803
-    /**
804
-     *        Set Registration Date
805
-     *
806
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
807
-     *                                                 Date
808
-     * @throws DomainException
809
-     * @throws EE_Error
810
-     * @throws EntityNotFoundException
811
-     * @throws InvalidArgumentException
812
-     * @throws InvalidDataTypeException
813
-     * @throws InvalidInterfaceException
814
-     * @throws ReflectionException
815
-     * @throws RuntimeException
816
-     * @throws UnexpectedEntityException
817
-     */
818
-    public function set_reg_date($REG_date = false)
819
-    {
820
-        $this->set('REG_date', $REG_date);
821
-    }
822
-
823
-
824
-    /**
825
-     *    Set final price owing for this registration after all ticket/price modifications
826
-     *
827
-     * @param    float $REG_final_price
828
-     * @throws DomainException
829
-     * @throws EE_Error
830
-     * @throws EntityNotFoundException
831
-     * @throws InvalidArgumentException
832
-     * @throws InvalidDataTypeException
833
-     * @throws InvalidInterfaceException
834
-     * @throws ReflectionException
835
-     * @throws RuntimeException
836
-     * @throws UnexpectedEntityException
837
-     */
838
-    public function set_final_price($REG_final_price = 0.00)
839
-    {
840
-        $this->set('REG_final_price', $REG_final_price);
841
-    }
842
-
843
-
844
-    /**
845
-     *    Set amount paid towards this registration's final price
846
-     *
847
-     * @param    float $REG_paid
848
-     * @throws DomainException
849
-     * @throws EE_Error
850
-     * @throws EntityNotFoundException
851
-     * @throws InvalidArgumentException
852
-     * @throws InvalidDataTypeException
853
-     * @throws InvalidInterfaceException
854
-     * @throws ReflectionException
855
-     * @throws RuntimeException
856
-     * @throws UnexpectedEntityException
857
-     */
858
-    public function set_paid($REG_paid = 0.00)
859
-    {
860
-        $this->set('REG_paid', $REG_paid);
861
-    }
862
-
863
-
864
-    /**
865
-     *        Attendee Is Going
866
-     *
867
-     * @param        boolean $REG_att_is_going Attendee Is Going
868
-     * @throws DomainException
869
-     * @throws EE_Error
870
-     * @throws EntityNotFoundException
871
-     * @throws InvalidArgumentException
872
-     * @throws InvalidDataTypeException
873
-     * @throws InvalidInterfaceException
874
-     * @throws ReflectionException
875
-     * @throws RuntimeException
876
-     * @throws UnexpectedEntityException
877
-     */
878
-    public function set_att_is_going($REG_att_is_going = false)
879
-    {
880
-        $this->set('REG_att_is_going', $REG_att_is_going);
881
-    }
882
-
883
-
884
-    /**
885
-     * Gets the related attendee
886
-     *
887
-     * @return EE_Attendee|EE_Base_Class
888
-     * @throws EE_Error
889
-     * @throws InvalidArgumentException
890
-     * @throws InvalidDataTypeException
891
-     * @throws InvalidInterfaceException
892
-     * @throws ReflectionException
893
-     */
894
-    public function attendee()
895
-    {
896
-        return $this->get_first_related('Attendee');
897
-    }
898
-
899
-    /**
900
-     * Gets the name of the attendee.
901
-     * @since 4.10.12.p
902
-     * @param bool $apply_html_entities set to true if you want to use HTML entities.
903
-     * @return string
904
-     * @throws EE_Error
905
-     * @throws InvalidArgumentException
906
-     * @throws InvalidDataTypeException
907
-     * @throws InvalidInterfaceException
908
-     * @throws ReflectionException
909
-     */
910
-    public function attendeeName($apply_html_entities = false)
911
-    {
912
-        $attendee = $this->get_first_related('Attendee');
913
-        if ($attendee instanceof EE_Attendee) {
914
-            $attendee_name = $attendee->full_name($apply_html_entities);
915
-        } else {
916
-            $attendee_name = esc_html__('Unknown', 'event_espresso');
917
-        }
918
-        return $attendee_name;
919
-    }
920
-
921
-
922
-    /**
923
-     *        get Event ID
924
-     */
925
-    public function event_ID()
926
-    {
927
-        return $this->get('EVT_ID');
928
-    }
929
-
930
-
931
-    /**
932
-     *        get Event ID
933
-     */
934
-    public function event_name()
935
-    {
936
-        $event = $this->event_obj();
937
-        if ($event) {
938
-            return $event->name();
939
-        } else {
940
-            return null;
941
-        }
942
-    }
943
-
944
-
945
-    /**
946
-     * Fetches the event this registration is for
947
-     *
948
-     * @return EE_Base_Class|EE_Event
949
-     * @throws EE_Error
950
-     * @throws InvalidArgumentException
951
-     * @throws InvalidDataTypeException
952
-     * @throws InvalidInterfaceException
953
-     * @throws ReflectionException
954
-     */
955
-    public function event_obj()
956
-    {
957
-        return $this->get_first_related('Event');
958
-    }
959
-
960
-
961
-    /**
962
-     *        get Attendee ID
963
-     */
964
-    public function attendee_ID()
965
-    {
966
-        return $this->get('ATT_ID');
967
-    }
968
-
969
-
970
-    /**
971
-     *        get PHP Session ID
972
-     */
973
-    public function session_ID()
974
-    {
975
-        return $this->get('REG_session');
976
-    }
977
-
978
-
979
-    /**
980
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
981
-     *
982
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
983
-     * @return string
984
-     * @throws DomainException
985
-     * @throws EE_Error
986
-     * @throws InvalidArgumentException
987
-     * @throws InvalidDataTypeException
988
-     * @throws InvalidInterfaceException
989
-     * @throws ReflectionException
990
-     */
991
-    public function receipt_url($messenger = 'html')
992
-    {
993
-
994
-        /**
995
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
996
-         * already in use on old system.  If there is then we just return the standard url for it.
997
-         *
998
-         * @since 4.5.0
999
-         */
1000
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
1001
-        $has_custom = EEH_Template::locate_template(
1002
-            $template_relative_path,
1003
-            array(),
1004
-            true,
1005
-            true,
1006
-            true
1007
-        );
1008
-
1009
-        if ($has_custom) {
1010
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
1011
-        }
1012
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
1013
-    }
1014
-
1015
-
1016
-    /**
1017
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
1018
-     *
1019
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
1020
-     * @return string
1021
-     * @throws DomainException
1022
-     * @throws EE_Error
1023
-     * @throws InvalidArgumentException
1024
-     * @throws InvalidDataTypeException
1025
-     * @throws InvalidInterfaceException
1026
-     * @throws ReflectionException
1027
-     */
1028
-    public function invoice_url($messenger = 'html')
1029
-    {
1030
-        /**
1031
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
1032
-         * already in use on old system.  If there is then we just return the standard url for it.
1033
-         *
1034
-         * @since 4.5.0
1035
-         */
1036
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
1037
-        $has_custom = EEH_Template::locate_template(
1038
-            $template_relative_path,
1039
-            array(),
1040
-            true,
1041
-            true,
1042
-            true
1043
-        );
1044
-
1045
-        if ($has_custom) {
1046
-            if ($messenger == 'html') {
1047
-                return $this->invoice_url('launch');
1048
-            }
1049
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
1050
-
1051
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
1052
-            if ($messenger == 'html') {
1053
-                $query_args['html'] = true;
1054
-            }
1055
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
1056
-        }
1057
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
1058
-    }
1059
-
1060
-
1061
-    /**
1062
-     * get Registration URL Link
1063
-     *
1064
-     * @return string
1065
-     * @throws EE_Error
1066
-     * @throws InvalidArgumentException
1067
-     * @throws InvalidDataTypeException
1068
-     * @throws InvalidInterfaceException
1069
-     * @throws ReflectionException
1070
-     */
1071
-    public function reg_url_link()
1072
-    {
1073
-        return (string) $this->get('REG_url_link');
1074
-    }
1075
-
1076
-
1077
-    /**
1078
-     * Echoes out invoice_url()
1079
-     *
1080
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
1081
-     * @return void
1082
-     * @throws DomainException
1083
-     * @throws EE_Error
1084
-     * @throws InvalidArgumentException
1085
-     * @throws InvalidDataTypeException
1086
-     * @throws InvalidInterfaceException
1087
-     * @throws ReflectionException
1088
-     */
1089
-    public function e_invoice_url($type = 'launch')
1090
-    {
1091
-        echo esc_url_raw($this->invoice_url($type));
1092
-    }
1093
-
1094
-
1095
-    /**
1096
-     * Echoes out payment_overview_url
1097
-     */
1098
-    public function e_payment_overview_url()
1099
-    {
1100
-        echo esc_url_raw($this->payment_overview_url());
1101
-    }
1102
-
1103
-
1104
-    /**
1105
-     * Gets the URL for the checkout payment options reg step
1106
-     * with this registration's REG_url_link added as a query parameter
1107
-     *
1108
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
1109
-     *                            payment overview url.
1110
-     * @return string
1111
-     * @throws EE_Error
1112
-     * @throws InvalidArgumentException
1113
-     * @throws InvalidDataTypeException
1114
-     * @throws InvalidInterfaceException
1115
-     * @throws ReflectionException
1116
-     */
1117
-    public function payment_overview_url($clear_session = false)
1118
-    {
1119
-        return add_query_arg(
1120
-            (array) apply_filters(
1121
-                'FHEE__EE_Registration__payment_overview_url__query_args',
1122
-                array(
1123
-                    'e_reg_url_link' => $this->reg_url_link(),
1124
-                    'step'           => 'payment_options',
1125
-                    'revisit'        => true,
1126
-                    'clear_session'  => (bool) $clear_session,
1127
-                ),
1128
-                $this
1129
-            ),
1130
-            EE_Registry::instance()->CFG->core->reg_page_url()
1131
-        );
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * Gets the URL for the checkout attendee information reg step
1137
-     * with this registration's REG_url_link added as a query parameter
1138
-     *
1139
-     * @return string
1140
-     * @throws EE_Error
1141
-     * @throws InvalidArgumentException
1142
-     * @throws InvalidDataTypeException
1143
-     * @throws InvalidInterfaceException
1144
-     * @throws ReflectionException
1145
-     */
1146
-    public function edit_attendee_information_url()
1147
-    {
1148
-        return add_query_arg(
1149
-            (array) apply_filters(
1150
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
1151
-                array(
1152
-                    'e_reg_url_link' => $this->reg_url_link(),
1153
-                    'step'           => 'attendee_information',
1154
-                    'revisit'        => true,
1155
-                ),
1156
-                $this
1157
-            ),
1158
-            EE_Registry::instance()->CFG->core->reg_page_url()
1159
-        );
1160
-    }
1161
-
1162
-
1163
-    /**
1164
-     * Simply generates and returns the appropriate admin_url link to edit this registration
1165
-     *
1166
-     * @return string
1167
-     * @throws EE_Error
1168
-     * @throws InvalidArgumentException
1169
-     * @throws InvalidDataTypeException
1170
-     * @throws InvalidInterfaceException
1171
-     * @throws ReflectionException
1172
-     */
1173
-    public function get_admin_edit_url()
1174
-    {
1175
-        return EEH_URL::add_query_args_and_nonce(
1176
-            array(
1177
-                'page'    => 'espresso_registrations',
1178
-                'action'  => 'view_registration',
1179
-                '_REG_ID' => $this->ID(),
1180
-            ),
1181
-            admin_url('admin.php')
1182
-        );
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * is_primary_registrant?
1188
-     *
1189
-     * @throws EE_Error
1190
-     * @throws InvalidArgumentException
1191
-     * @throws InvalidDataTypeException
1192
-     * @throws InvalidInterfaceException
1193
-     * @throws ReflectionException
1194
-     */
1195
-    public function is_primary_registrant()
1196
-    {
1197
-        return (int) $this->get('REG_count') === 1;
1198
-    }
1199
-
1200
-
1201
-    /**
1202
-     * This returns the primary registration object for this registration group (which may be this object).
1203
-     *
1204
-     * @return EE_Registration
1205
-     * @throws EE_Error
1206
-     * @throws InvalidArgumentException
1207
-     * @throws InvalidDataTypeException
1208
-     * @throws InvalidInterfaceException
1209
-     * @throws ReflectionException
1210
-     */
1211
-    public function get_primary_registration()
1212
-    {
1213
-        if ($this->is_primary_registrant()) {
1214
-            return $this;
1215
-        }
1216
-
1217
-        // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1218
-        /** @var EE_Registration $primary_registrant */
1219
-        $primary_registrant = EEM_Registration::instance()->get_one(
1220
-            array(
1221
-                array(
1222
-                    'TXN_ID'    => $this->transaction_ID(),
1223
-                    'REG_count' => 1,
1224
-                ),
1225
-            )
1226
-        );
1227
-        return $primary_registrant;
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * get  Attendee Number
1233
-     *
1234
-     * @throws EE_Error
1235
-     * @throws InvalidArgumentException
1236
-     * @throws InvalidDataTypeException
1237
-     * @throws InvalidInterfaceException
1238
-     * @throws ReflectionException
1239
-     */
1240
-    public function count()
1241
-    {
1242
-        return $this->get('REG_count');
1243
-    }
1244
-
1245
-
1246
-    /**
1247
-     * get Group Size
1248
-     *
1249
-     * @throws EE_Error
1250
-     * @throws InvalidArgumentException
1251
-     * @throws InvalidDataTypeException
1252
-     * @throws InvalidInterfaceException
1253
-     * @throws ReflectionException
1254
-     */
1255
-    public function group_size()
1256
-    {
1257
-        return $this->get('REG_group_size');
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * get Registration Date
1263
-     *
1264
-     * @throws EE_Error
1265
-     * @throws InvalidArgumentException
1266
-     * @throws InvalidDataTypeException
1267
-     * @throws InvalidInterfaceException
1268
-     * @throws ReflectionException
1269
-     */
1270
-    public function date()
1271
-    {
1272
-        return $this->get('REG_date');
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * gets a pretty date
1278
-     *
1279
-     * @param string $date_format
1280
-     * @param string $time_format
1281
-     * @return string
1282
-     * @throws EE_Error
1283
-     * @throws InvalidArgumentException
1284
-     * @throws InvalidDataTypeException
1285
-     * @throws InvalidInterfaceException
1286
-     * @throws ReflectionException
1287
-     */
1288
-    public function pretty_date($date_format = null, $time_format = null)
1289
-    {
1290
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * final_price
1296
-     * the registration's share of the transaction total, so that the
1297
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1298
-     *
1299
-     * @return float
1300
-     * @throws EE_Error
1301
-     * @throws InvalidArgumentException
1302
-     * @throws InvalidDataTypeException
1303
-     * @throws InvalidInterfaceException
1304
-     * @throws ReflectionException
1305
-     */
1306
-    public function final_price()
1307
-    {
1308
-        return $this->get('REG_final_price');
1309
-    }
1310
-
1311
-
1312
-    /**
1313
-     * pretty_final_price
1314
-     *  final price as formatted string, with correct decimal places and currency symbol
1315
-     *
1316
-     * @return string
1317
-     * @throws EE_Error
1318
-     * @throws InvalidArgumentException
1319
-     * @throws InvalidDataTypeException
1320
-     * @throws InvalidInterfaceException
1321
-     * @throws ReflectionException
1322
-     */
1323
-    public function pretty_final_price()
1324
-    {
1325
-        return $this->get_pretty('REG_final_price');
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     * get paid (yeah)
1331
-     *
1332
-     * @return float
1333
-     * @throws EE_Error
1334
-     * @throws InvalidArgumentException
1335
-     * @throws InvalidDataTypeException
1336
-     * @throws InvalidInterfaceException
1337
-     * @throws ReflectionException
1338
-     */
1339
-    public function paid()
1340
-    {
1341
-        return $this->get('REG_paid');
1342
-    }
1343
-
1344
-
1345
-    /**
1346
-     * pretty_paid
1347
-     *
1348
-     * @return float
1349
-     * @throws EE_Error
1350
-     * @throws InvalidArgumentException
1351
-     * @throws InvalidDataTypeException
1352
-     * @throws InvalidInterfaceException
1353
-     * @throws ReflectionException
1354
-     */
1355
-    public function pretty_paid()
1356
-    {
1357
-        return $this->get_pretty('REG_paid');
1358
-    }
1359
-
1360
-
1361
-    /**
1362
-     * owes_monies_and_can_pay
1363
-     * whether or not this registration has monies owing and it's' status allows payment
1364
-     *
1365
-     * @param array $requires_payment
1366
-     * @return bool
1367
-     * @throws EE_Error
1368
-     * @throws InvalidArgumentException
1369
-     * @throws InvalidDataTypeException
1370
-     * @throws InvalidInterfaceException
1371
-     * @throws ReflectionException
1372
-     */
1373
-    public function owes_monies_and_can_pay($requires_payment = array())
1374
-    {
1375
-        // these reg statuses require payment (if event is not free)
1376
-        $requires_payment = ! empty($requires_payment)
1377
-            ? $requires_payment
1378
-            : EEM_Registration::reg_statuses_that_allow_payment();
1379
-        if (
1380
-            $this->final_price() !== 0 &&
1381
-            $this->final_price() !== $this->paid() &&
1382
-            in_array($this->status_ID(), $requires_payment)
1383
-        ) {
1384
-            return true;
1385
-        }
1386
-        return false;
1387
-    }
1388
-
1389
-
1390
-    /**
1391
-     * Prints out the return value of $this->pretty_status()
1392
-     *
1393
-     * @param bool $show_icons
1394
-     * @return void
1395
-     * @throws EE_Error
1396
-     * @throws InvalidArgumentException
1397
-     * @throws InvalidDataTypeException
1398
-     * @throws InvalidInterfaceException
1399
-     * @throws ReflectionException
1400
-     */
1401
-    public function e_pretty_status($show_icons = false)
1402
-    {
1403
-        echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * Returns a nice version of the status for displaying to customers
1409
-     *
1410
-     * @param bool $show_icons
1411
-     * @return string
1412
-     * @throws EE_Error
1413
-     * @throws InvalidArgumentException
1414
-     * @throws InvalidDataTypeException
1415
-     * @throws InvalidInterfaceException
1416
-     * @throws ReflectionException
1417
-     */
1418
-    public function pretty_status($show_icons = false)
1419
-    {
1420
-        $status = EEM_Status::instance()->localized_status(
1421
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1422
-            false,
1423
-            'sentence'
1424
-        );
1425
-        $icon = '';
1426
-        switch ($this->status_ID()) {
1427
-            case EEM_Registration::status_id_approved:
1428
-                $icon = $show_icons
1429
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1430
-                    : '';
1431
-                break;
1432
-            case EEM_Registration::status_id_pending_payment:
1433
-                $icon = $show_icons
1434
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1435
-                    : '';
1436
-                break;
1437
-            case EEM_Registration::status_id_not_approved:
1438
-                $icon = $show_icons
1439
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1440
-                    : '';
1441
-                break;
1442
-            case EEM_Registration::status_id_cancelled:
1443
-                $icon = $show_icons
1444
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1445
-                    : '';
1446
-                break;
1447
-            case EEM_Registration::status_id_incomplete:
1448
-                $icon = $show_icons
1449
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1450
-                    : '';
1451
-                break;
1452
-            case EEM_Registration::status_id_declined:
1453
-                $icon = $show_icons
1454
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1455
-                    : '';
1456
-                break;
1457
-            case EEM_Registration::status_id_wait_list:
1458
-                $icon = $show_icons
1459
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1460
-                    : '';
1461
-                break;
1462
-        }
1463
-        return $icon . $status[ $this->status_ID() ];
1464
-    }
1465
-
1466
-
1467
-    /**
1468
-     *        get Attendee Is Going
1469
-     */
1470
-    public function att_is_going()
1471
-    {
1472
-        return $this->get('REG_att_is_going');
1473
-    }
1474
-
1475
-
1476
-    /**
1477
-     * Gets related answers
1478
-     *
1479
-     * @param array $query_params @see
1480
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1481
-     * @return EE_Answer[]|EE_Base_Class[]
1482
-     * @throws EE_Error
1483
-     * @throws InvalidArgumentException
1484
-     * @throws InvalidDataTypeException
1485
-     * @throws InvalidInterfaceException
1486
-     * @throws ReflectionException
1487
-     */
1488
-    public function answers($query_params = null)
1489
-    {
1490
-        return $this->get_many_related('Answer', $query_params);
1491
-    }
1492
-
1493
-
1494
-    /**
1495
-     * Gets the registration's answer value to the specified question
1496
-     * (either the question's ID or a question object)
1497
-     *
1498
-     * @param EE_Question|int $question
1499
-     * @param bool            $pretty_value
1500
-     * @return array|string if pretty_value= true, the result will always be a string
1501
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1502
-     * will convert it into some kind of string)
1503
-     * @throws EE_Error
1504
-     * @throws InvalidArgumentException
1505
-     * @throws InvalidDataTypeException
1506
-     * @throws InvalidInterfaceException
1507
-     */
1508
-    public function answer_value_to_question($question, $pretty_value = true)
1509
-    {
1510
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1511
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1512
-    }
1513
-
1514
-
1515
-    /**
1516
-     * question_groups
1517
-     * returns an array of EE_Question_Group objects for this registration
1518
-     *
1519
-     * @return EE_Question_Group[]
1520
-     * @throws EE_Error
1521
-     * @throws InvalidArgumentException
1522
-     * @throws InvalidDataTypeException
1523
-     * @throws InvalidInterfaceException
1524
-     * @throws ReflectionException
1525
-     */
1526
-    public function question_groups()
1527
-    {
1528
-        return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     * count_question_groups
1534
-     * returns a count of the number of EE_Question_Group objects for this registration
1535
-     *
1536
-     * @return int
1537
-     * @throws EE_Error
1538
-     * @throws EntityNotFoundException
1539
-     * @throws InvalidArgumentException
1540
-     * @throws InvalidDataTypeException
1541
-     * @throws InvalidInterfaceException
1542
-     * @throws ReflectionException
1543
-     */
1544
-    public function count_question_groups()
1545
-    {
1546
-        return EEM_Event::instance()->count_related(
1547
-            $this->event_ID(),
1548
-            'Question_Group',
1549
-            [
1550
-                [
1551
-                    'Event_Question_Group.'
1552
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1553
-                ]
1554
-            ]
1555
-        );
1556
-    }
1557
-
1558
-
1559
-    /**
1560
-     * Returns the registration date in the 'standard' string format
1561
-     * (function may be improved in the future to allow for different formats and timezones)
1562
-     *
1563
-     * @return string
1564
-     * @throws EE_Error
1565
-     * @throws InvalidArgumentException
1566
-     * @throws InvalidDataTypeException
1567
-     * @throws InvalidInterfaceException
1568
-     * @throws ReflectionException
1569
-     */
1570
-    public function reg_date()
1571
-    {
1572
-        return $this->get_datetime('REG_date');
1573
-    }
1574
-
1575
-
1576
-    /**
1577
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1578
-     * the ticket this registration purchased, or the datetime they have registered
1579
-     * to attend)
1580
-     *
1581
-     * @return EE_Base_Class|EE_Datetime_Ticket
1582
-     * @throws EE_Error
1583
-     * @throws InvalidArgumentException
1584
-     * @throws InvalidDataTypeException
1585
-     * @throws InvalidInterfaceException
1586
-     * @throws ReflectionException
1587
-     */
1588
-    public function datetime_ticket()
1589
-    {
1590
-        return $this->get_first_related('Datetime_Ticket');
1591
-    }
1592
-
1593
-
1594
-    /**
1595
-     * Sets the registration's datetime_ticket.
1596
-     *
1597
-     * @param EE_Datetime_Ticket $datetime_ticket
1598
-     * @return EE_Base_Class|EE_Datetime_Ticket
1599
-     * @throws EE_Error
1600
-     * @throws InvalidArgumentException
1601
-     * @throws InvalidDataTypeException
1602
-     * @throws InvalidInterfaceException
1603
-     * @throws ReflectionException
1604
-     */
1605
-    public function set_datetime_ticket($datetime_ticket)
1606
-    {
1607
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1608
-    }
1609
-
1610
-
1611
-    /**
1612
-     * Gets deleted
1613
-     *
1614
-     * @return bool
1615
-     * @throws EE_Error
1616
-     * @throws InvalidArgumentException
1617
-     * @throws InvalidDataTypeException
1618
-     * @throws InvalidInterfaceException
1619
-     * @throws ReflectionException
1620
-     */
1621
-    public function deleted()
1622
-    {
1623
-        return $this->get('REG_deleted');
1624
-    }
1625
-
1626
-
1627
-    /**
1628
-     * Sets deleted
1629
-     *
1630
-     * @param boolean $deleted
1631
-     * @return void
1632
-     * @throws DomainException
1633
-     * @throws EE_Error
1634
-     * @throws EntityNotFoundException
1635
-     * @throws InvalidArgumentException
1636
-     * @throws InvalidDataTypeException
1637
-     * @throws InvalidInterfaceException
1638
-     * @throws ReflectionException
1639
-     * @throws RuntimeException
1640
-     * @throws UnexpectedEntityException
1641
-     */
1642
-    public function set_deleted($deleted)
1643
-    {
1644
-        if ($deleted) {
1645
-            $this->delete(__METHOD__);
1646
-        } else {
1647
-            $this->restore(__METHOD__);
1648
-        }
1649
-    }
1650
-
1651
-
1652
-    /**
1653
-     * Get the status object of this object
1654
-     *
1655
-     * @return EE_Base_Class|EE_Status
1656
-     * @throws EE_Error
1657
-     * @throws InvalidArgumentException
1658
-     * @throws InvalidDataTypeException
1659
-     * @throws InvalidInterfaceException
1660
-     * @throws ReflectionException
1661
-     */
1662
-    public function status_obj()
1663
-    {
1664
-        return $this->get_first_related('Status');
1665
-    }
1666
-
1667
-
1668
-    /**
1669
-     * Returns the number of times this registration has checked into any of the datetimes
1670
-     * its available for
1671
-     *
1672
-     * @return int
1673
-     * @throws EE_Error
1674
-     * @throws InvalidArgumentException
1675
-     * @throws InvalidDataTypeException
1676
-     * @throws InvalidInterfaceException
1677
-     * @throws ReflectionException
1678
-     */
1679
-    public function count_checkins()
1680
-    {
1681
-        return $this->get_model()->count_related($this, 'Checkin');
1682
-    }
1683
-
1684
-
1685
-    /**
1686
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1687
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1688
-     *
1689
-     * @return int
1690
-     * @throws EE_Error
1691
-     * @throws InvalidArgumentException
1692
-     * @throws InvalidDataTypeException
1693
-     * @throws InvalidInterfaceException
1694
-     * @throws ReflectionException
1695
-     */
1696
-    public function count_checkins_not_checkedout()
1697
-    {
1698
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1699
-    }
1700
-
1701
-
1702
-    /**
1703
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1704
-     *
1705
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1706
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1707
-     *                                          consider registration status as well as datetime access.
1708
-     * @return bool
1709
-     * @throws EE_Error
1710
-     * @throws InvalidArgumentException
1711
-     * @throws InvalidDataTypeException
1712
-     * @throws InvalidInterfaceException
1713
-     * @throws ReflectionException
1714
-     */
1715
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1716
-    {
1717
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1718
-        // first check registration status
1719
-        if (! $DTT_ID || ($check_approved && ! $this->is_approved())) {
1720
-            return false;
1721
-        }
1722
-        // is there a datetime ticket that matches this dtt_ID?
1723
-        if (
1724
-            ! (EEM_Datetime_Ticket::instance()->exists(
1725
-                array(
1726
-                    array(
1727
-                        'TKT_ID' => $this->get('TKT_ID'),
1728
-                        'DTT_ID' => $DTT_ID,
1729
-                    ),
1730
-                )
1731
-            ))
1732
-        ) {
1733
-            return false;
1734
-        }
1735
-
1736
-        // final check is against TKT_uses
1737
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1743
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1744
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1745
-     * then return false.  Otherwise return true.
1746
-     *
1747
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1748
-     * @return bool true means can checkin.  false means cannot checkin.
1749
-     * @throws EE_Error
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws ReflectionException
1754
-     */
1755
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1756
-    {
1757
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1758
-
1759
-        if (! $DTT_ID) {
1760
-            return false;
1761
-        }
1762
-
1763
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1764
-
1765
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1766
-        // check-in or not.
1767
-        if (! $max_uses || $max_uses === EE_INF) {
1768
-            return true;
1769
-        }
1770
-
1771
-        // does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1772
-        // go ahead and toggle.
1773
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1774
-            return true;
1775
-        }
1776
-
1777
-        // made it here so the last check is whether the number of checkins per unique datetime on this registration
1778
-        // disallows further check-ins.
1779
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1780
-            array(
1781
-                array(
1782
-                    'REG_ID' => $this->ID(),
1783
-                    'CHK_in' => true,
1784
-                ),
1785
-            ),
1786
-            'DTT_ID',
1787
-            true
1788
-        );
1789
-        // checkins have already reached their max number of uses
1790
-        // so registrant can NOT checkin
1791
-        if ($count_unique_dtt_checkins >= $max_uses) {
1792
-            EE_Error::add_error(
1793
-                esc_html__(
1794
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1795
-                    'event_espresso'
1796
-                ),
1797
-                __FILE__,
1798
-                __FUNCTION__,
1799
-                __LINE__
1800
-            );
1801
-            return false;
1802
-        }
1803
-        return true;
1804
-    }
1805
-
1806
-
1807
-    /**
1808
-     * toggle Check-in status for this registration
1809
-     * Check-ins are toggled in the following order:
1810
-     * never checked in -> checked in
1811
-     * checked in -> checked out
1812
-     * checked out -> checked in
1813
-     *
1814
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1815
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1816
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1817
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1818
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1819
-     * @throws EE_Error
1820
-     * @throws InvalidArgumentException
1821
-     * @throws InvalidDataTypeException
1822
-     * @throws InvalidInterfaceException
1823
-     * @throws ReflectionException
1824
-     */
1825
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1826
-    {
1827
-        if (empty($DTT_ID)) {
1828
-            $datetime = $this->get_latest_related_datetime();
1829
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1830
-            // verify the registration can checkin for the given DTT_ID
1831
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1832
-            EE_Error::add_error(
1833
-                sprintf(
1834
-                    esc_html__(
1835
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1836
-                        'event_espresso'
1837
-                    ),
1838
-                    $this->ID(),
1839
-                    $DTT_ID
1840
-                ),
1841
-                __FILE__,
1842
-                __FUNCTION__,
1843
-                __LINE__
1844
-            );
1845
-            return false;
1846
-        }
1847
-        $status_paths = array(
1848
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1849
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1850
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1851
-        );
1852
-        // start by getting the current status so we know what status we'll be changing to.
1853
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1854
-        $status_to = $status_paths[ $cur_status ];
1855
-        // database only records true for checked IN or false for checked OUT
1856
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1857
-        $new_status = $status_to === EE_Checkin::status_checked_in;
1858
-        // add relation - note Check-ins are always creating new rows
1859
-        // because we are keeping track of Check-ins over time.
1860
-        // Eventually we'll probably want to show a list table
1861
-        // for the individual Check-ins so that they can be managed.
1862
-        $checkin = EE_Checkin::new_instance(
1863
-            array(
1864
-                'REG_ID' => $this->ID(),
1865
-                'DTT_ID' => $DTT_ID,
1866
-                'CHK_in' => $new_status,
1867
-            )
1868
-        );
1869
-        // if the record could not be saved then return false
1870
-        if ($checkin->save() === 0) {
1871
-            if (WP_DEBUG) {
1872
-                global $wpdb;
1873
-                $error = sprintf(
1874
-                    esc_html__(
1875
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1876
-                        'event_espresso'
1877
-                    ),
1878
-                    '<br />',
1879
-                    $wpdb->last_error
1880
-                );
1881
-            } else {
1882
-                $error = esc_html__(
1883
-                    'Registration check in update failed because of an unknown database error',
1884
-                    'event_espresso'
1885
-                );
1886
-            }
1887
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1888
-            return false;
1889
-        }
1890
-        // Fire a checked_in and checkout_out action.
1891
-        $checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1892
-        do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1893
-        return $status_to;
1894
-    }
1895
-
1896
-
1897
-    /**
1898
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1899
-     * "Latest" is defined by the `DTT_EVT_start` column.
1900
-     *
1901
-     * @return EE_Datetime|null
1902
-     * @throws EE_Error
1903
-     * @throws InvalidArgumentException
1904
-     * @throws InvalidDataTypeException
1905
-     * @throws InvalidInterfaceException
1906
-     * @throws ReflectionException
1907
-     */
1908
-    public function get_latest_related_datetime()
1909
-    {
1910
-        return EEM_Datetime::instance()->get_one(
1911
-            array(
1912
-                array(
1913
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1914
-                ),
1915
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1916
-            )
1917
-        );
1918
-    }
1919
-
1920
-
1921
-    /**
1922
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1923
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1924
-     *
1925
-     * @return EE_Base_Class|EE_Soft_Delete_Base_Class|NULL
1926
-     * @throws EE_Error
1927
-     * @throws InvalidArgumentException
1928
-     * @throws InvalidDataTypeException
1929
-     * @throws InvalidInterfaceException
1930
-     * @throws ReflectionException
1931
-     */
1932
-    public function get_earliest_related_datetime()
1933
-    {
1934
-        return EEM_Datetime::instance()->get_one(
1935
-            array(
1936
-                array(
1937
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1938
-                ),
1939
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1940
-            )
1941
-        );
1942
-    }
1943
-
1944
-
1945
-    /**
1946
-     * This method simply returns the check-in status for this registration and the given datetime.
1947
-     * If neither the datetime nor the checkin values are provided as arguments,
1948
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1949
-     *
1950
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1951
-     *                            (if empty we'll get the primary datetime for
1952
-     *                            this registration (via event) and use it's ID);
1953
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1954
-     * @return int                Integer representing Check-in status.
1955
-     * @throws EE_Error
1956
-     * @throws InvalidArgumentException
1957
-     * @throws InvalidDataTypeException
1958
-     * @throws InvalidInterfaceException
1959
-     * @throws ReflectionException
1960
-     */
1961
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1962
-    {
1963
-        $checkin_query_params = array(
1964
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1965
-        );
1966
-
1967
-        if ($DTT_ID > 0) {
1968
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1969
-        }
1970
-
1971
-        // get checkin object (if exists)
1972
-        $checkin = $checkin instanceof EE_Checkin
1973
-            ? $checkin
1974
-            : $this->get_first_related('Checkin', $checkin_query_params);
1975
-        if ($checkin instanceof EE_Checkin) {
1976
-            if ($checkin->get('CHK_in')) {
1977
-                return EE_Checkin::status_checked_in; // checked in
1978
-            }
1979
-            return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1980
-        }
1981
-        return EE_Checkin::status_checked_never; // never been checked in
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * This method returns a localized message for the toggled Check-in message.
1987
-     *
1988
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1989
-     *                     then it is assumed Check-in for primary datetime was toggled.
1990
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1991
-     *                     message can be customized with the attendee name.
1992
-     * @return string internationalized message
1993
-     * @throws EE_Error
1994
-     * @throws InvalidArgumentException
1995
-     * @throws InvalidDataTypeException
1996
-     * @throws InvalidInterfaceException
1997
-     * @throws ReflectionException
1998
-     */
1999
-    public function get_checkin_msg($DTT_ID, $error = false)
2000
-    {
2001
-        // let's get the attendee first so we can include the name of the attendee
2002
-        $attendee = $this->get_first_related('Attendee');
2003
-        if ($attendee instanceof EE_Attendee) {
2004
-            if ($error) {
2005
-                return sprintf(
2006
-                    esc_html__("%s's check-in status was not changed.", "event_espresso"),
2007
-                    $attendee->full_name()
2008
-                );
2009
-            }
2010
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
2011
-            // what is the status message going to be?
2012
-            switch ($cur_status) {
2013
-                case EE_Checkin::status_checked_never:
2014
-                    return sprintf(
2015
-                        esc_html__('%s has been removed from Check-in records', 'event_espresso'),
2016
-                        $attendee->full_name()
2017
-                    );
2018
-                    break;
2019
-                case EE_Checkin::status_checked_in:
2020
-                    return sprintf(esc_html__('%s has been checked in', 'event_espresso'), $attendee->full_name());
2021
-                    break;
2022
-                case EE_Checkin::status_checked_out:
2023
-                    return sprintf(esc_html__('%s has been checked out', 'event_espresso'), $attendee->full_name());
2024
-                    break;
2025
-            }
2026
-        }
2027
-        return esc_html__('The check-in status could not be determined.', 'event_espresso');
2028
-    }
2029
-
2030
-
2031
-    /**
2032
-     * Returns the related EE_Transaction to this registration
2033
-     *
2034
-     * @return EE_Transaction
2035
-     * @throws EE_Error
2036
-     * @throws EntityNotFoundException
2037
-     * @throws InvalidArgumentException
2038
-     * @throws InvalidDataTypeException
2039
-     * @throws InvalidInterfaceException
2040
-     * @throws ReflectionException
2041
-     */
2042
-    public function transaction()
2043
-    {
2044
-        $transaction = $this->get_first_related('Transaction');
2045
-        if (! $transaction instanceof \EE_Transaction) {
2046
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
2047
-        }
2048
-        return $transaction;
2049
-    }
2050
-
2051
-
2052
-    /**
2053
-     * get Registration Code
2054
-     *
2055
-     * @return mixed
2056
-     * @throws EE_Error
2057
-     * @throws InvalidArgumentException
2058
-     * @throws InvalidDataTypeException
2059
-     * @throws InvalidInterfaceException
2060
-     * @throws ReflectionException
2061
-     */
2062
-    public function reg_code()
2063
-    {
2064
-        return $this->get('REG_code');
2065
-    }
2066
-
2067
-
2068
-    /**
2069
-     * @return mixed
2070
-     * @throws EE_Error
2071
-     * @throws InvalidArgumentException
2072
-     * @throws InvalidDataTypeException
2073
-     * @throws InvalidInterfaceException
2074
-     * @throws ReflectionException
2075
-     */
2076
-    public function transaction_ID()
2077
-    {
2078
-        return $this->get('TXN_ID');
2079
-    }
2080
-
2081
-
2082
-    /**
2083
-     * @return int
2084
-     * @throws EE_Error
2085
-     * @throws InvalidArgumentException
2086
-     * @throws InvalidDataTypeException
2087
-     * @throws InvalidInterfaceException
2088
-     * @throws ReflectionException
2089
-     */
2090
-    public function ticket_ID()
2091
-    {
2092
-        return $this->get('TKT_ID');
2093
-    }
2094
-
2095
-
2096
-    /**
2097
-     * Set Registration Code
2098
-     *
2099
-     * @param    string  $REG_code Registration Code
2100
-     * @param    boolean $use_default
2101
-     * @throws EE_Error
2102
-     * @throws InvalidArgumentException
2103
-     * @throws InvalidDataTypeException
2104
-     * @throws InvalidInterfaceException
2105
-     * @throws ReflectionException
2106
-     */
2107
-    public function set_reg_code($REG_code, $use_default = false)
2108
-    {
2109
-        if (empty($REG_code)) {
2110
-            EE_Error::add_error(
2111
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
2112
-                __FILE__,
2113
-                __FUNCTION__,
2114
-                __LINE__
2115
-            );
2116
-            return;
2117
-        }
2118
-        if (! $this->reg_code()) {
2119
-            parent::set('REG_code', $REG_code, $use_default);
2120
-        } else {
2121
-            EE_Error::doing_it_wrong(
2122
-                __CLASS__ . '::' . __FUNCTION__,
2123
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
2124
-                '4.6.0'
2125
-            );
2126
-        }
2127
-    }
2128
-
2129
-
2130
-    /**
2131
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
2132
-     * Note, if you want to just get all registrations in the same transaction (group), use:
2133
-     *    $registration->transaction()->registrations();
2134
-     *
2135
-     * @since 4.5.0
2136
-     * @return EE_Registration[] or empty array if this isn't a group registration.
2137
-     * @throws EE_Error
2138
-     * @throws InvalidArgumentException
2139
-     * @throws InvalidDataTypeException
2140
-     * @throws InvalidInterfaceException
2141
-     * @throws ReflectionException
2142
-     */
2143
-    public function get_all_other_registrations_in_group()
2144
-    {
2145
-        if ($this->group_size() < 2) {
2146
-            return array();
2147
-        }
2148
-
2149
-        $query[0] = array(
2150
-            'TXN_ID' => $this->transaction_ID(),
2151
-            'REG_ID' => array('!=', $this->ID()),
2152
-            'TKT_ID' => $this->ticket_ID(),
2153
-        );
2154
-        /** @var EE_Registration[] $registrations */
2155
-        $registrations = $this->get_model()->get_all($query);
2156
-        return $registrations;
2157
-    }
2158
-
2159
-
2160
-    /**
2161
-     * Return the link to the admin details for the object.
2162
-     *
2163
-     * @return string
2164
-     * @throws EE_Error
2165
-     * @throws InvalidArgumentException
2166
-     * @throws InvalidDataTypeException
2167
-     * @throws InvalidInterfaceException
2168
-     * @throws ReflectionException
2169
-     */
2170
-    public function get_admin_details_link()
2171
-    {
2172
-        EE_Registry::instance()->load_helper('URL');
2173
-        return EEH_URL::add_query_args_and_nonce(
2174
-            array(
2175
-                'page'    => 'espresso_registrations',
2176
-                'action'  => 'view_registration',
2177
-                '_REG_ID' => $this->ID(),
2178
-            ),
2179
-            admin_url('admin.php')
2180
-        );
2181
-    }
2182
-
2183
-
2184
-    /**
2185
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
2186
-     *
2187
-     * @return string
2188
-     * @throws EE_Error
2189
-     * @throws InvalidArgumentException
2190
-     * @throws InvalidDataTypeException
2191
-     * @throws InvalidInterfaceException
2192
-     * @throws ReflectionException
2193
-     */
2194
-    public function get_admin_edit_link()
2195
-    {
2196
-        return $this->get_admin_details_link();
2197
-    }
2198
-
2199
-
2200
-    /**
2201
-     * Returns the link to a settings page for the object.
2202
-     *
2203
-     * @return string
2204
-     * @throws EE_Error
2205
-     * @throws InvalidArgumentException
2206
-     * @throws InvalidDataTypeException
2207
-     * @throws InvalidInterfaceException
2208
-     * @throws ReflectionException
2209
-     */
2210
-    public function get_admin_settings_link()
2211
-    {
2212
-        return $this->get_admin_details_link();
2213
-    }
2214
-
2215
-
2216
-    /**
2217
-     * Returns the link to the "overview" for the object (typically the "list table" view).
2218
-     *
2219
-     * @return string
2220
-     * @throws EE_Error
2221
-     * @throws InvalidArgumentException
2222
-     * @throws InvalidDataTypeException
2223
-     * @throws InvalidInterfaceException
2224
-     * @throws ReflectionException
2225
-     */
2226
-    public function get_admin_overview_link()
2227
-    {
2228
-        EE_Registry::instance()->load_helper('URL');
2229
-        return EEH_URL::add_query_args_and_nonce(
2230
-            array(
2231
-                'page' => 'espresso_registrations',
2232
-            ),
2233
-            admin_url('admin.php')
2234
-        );
2235
-    }
2236
-
2237
-
2238
-    /**
2239
-     * @param array $query_params
2240
-     * @return EE_Base_Class[]|EE_Registration[]
2241
-     * @throws EE_Error
2242
-     * @throws InvalidArgumentException
2243
-     * @throws InvalidDataTypeException
2244
-     * @throws InvalidInterfaceException
2245
-     * @throws ReflectionException
2246
-     */
2247
-    public function payments($query_params = array())
2248
-    {
2249
-        return $this->get_many_related('Payment', $query_params);
2250
-    }
2251
-
2252
-
2253
-    /**
2254
-     * @param array $query_params
2255
-     * @return EE_Base_Class[]|EE_Registration_Payment[]
2256
-     * @throws EE_Error
2257
-     * @throws InvalidArgumentException
2258
-     * @throws InvalidDataTypeException
2259
-     * @throws InvalidInterfaceException
2260
-     * @throws ReflectionException
2261
-     */
2262
-    public function registration_payments($query_params = array())
2263
-    {
2264
-        return $this->get_many_related('Registration_Payment', $query_params);
2265
-    }
2266
-
2267
-
2268
-    /**
2269
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
2270
-     * Note: if there are no payments on the registration there will be no payment method returned.
2271
-     *
2272
-     * @return EE_Payment|EE_Payment_Method|null
2273
-     * @throws EE_Error
2274
-     * @throws InvalidArgumentException
2275
-     * @throws InvalidDataTypeException
2276
-     * @throws InvalidInterfaceException
2277
-     */
2278
-    public function payment_method()
2279
-    {
2280
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
2281
-    }
2282
-
2283
-
2284
-    /**
2285
-     * @return \EE_Line_Item
2286
-     * @throws EE_Error
2287
-     * @throws EntityNotFoundException
2288
-     * @throws InvalidArgumentException
2289
-     * @throws InvalidDataTypeException
2290
-     * @throws InvalidInterfaceException
2291
-     * @throws ReflectionException
2292
-     */
2293
-    public function ticket_line_item()
2294
-    {
2295
-        $ticket = $this->ticket();
2296
-        $transaction = $this->transaction();
2297
-        $line_item = null;
2298
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
2299
-            $transaction->total_line_item(),
2300
-            'Ticket',
2301
-            array($ticket->ID())
2302
-        );
2303
-        foreach ($ticket_line_items as $ticket_line_item) {
2304
-            if (
2305
-                $ticket_line_item instanceof \EE_Line_Item
2306
-                && $ticket_line_item->OBJ_type() === 'Ticket'
2307
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
2308
-            ) {
2309
-                $line_item = $ticket_line_item;
2310
-                break;
2311
-            }
2312
-        }
2313
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
2314
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
2315
-        }
2316
-        return $line_item;
2317
-    }
2318
-
2319
-
2320
-    /**
2321
-     * Soft Deletes this model object.
2322
-     *
2323
-     * @param string $source function name that called this method
2324
-     * @return boolean | int
2325
-     * @throws DomainException
2326
-     * @throws EE_Error
2327
-     * @throws EntityNotFoundException
2328
-     * @throws InvalidArgumentException
2329
-     * @throws InvalidDataTypeException
2330
-     * @throws InvalidInterfaceException
2331
-     * @throws ReflectionException
2332
-     * @throws RuntimeException
2333
-     * @throws UnexpectedEntityException
2334
-     */
2335
-    public function delete($source = 'unknown')
2336
-    {
2337
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
2338
-            $current_user = wp_get_current_user();
2339
-            $this->add_extra_meta(
2340
-                EE_Registration::EXTRA_META_KEY_REG_TRASHED,
2341
-                array(
2342
-                    'trashed-by' => $current_user->ID ? $current_user->display_name : 'unauthed user',
2343
-                    'timestamp'  => time(),
2344
-                    'source'     => $source,
2345
-                )
2346
-            );
2347
-            $this->set_status(EEM_Registration::status_id_cancelled);
2348
-        }
2349
-        return parent::delete();
2350
-    }
2351
-
2352
-
2353
-    /**
2354
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
2355
-     *
2356
-     * @param string $source function name that called this method
2357
-     * @return bool|int
2358
-     * @throws DomainException
2359
-     * @throws EE_Error
2360
-     * @throws EntityNotFoundException
2361
-     * @throws InvalidArgumentException
2362
-     * @throws InvalidDataTypeException
2363
-     * @throws InvalidInterfaceException
2364
-     * @throws ReflectionException
2365
-     * @throws RuntimeException
2366
-     * @throws UnexpectedEntityException
2367
-     */
2368
-    public function restore($source = 'unknown')
2369
-    {
2370
-        $previous_status = $this->get_extra_meta(
2371
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
2372
-            true,
2373
-            EEM_Registration::status_id_cancelled
2374
-        );
2375
-        if ($previous_status) {
2376
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
2377
-            $this->set_status($previous_status);
2378
-        }
2379
-        $current_user = wp_get_current_user();
2380
-        $this->add_extra_meta(
2381
-            EE_Registration::EXTRA_META_KEY_REG_RESTORED,
2382
-            array(
2383
-                'restored-by' => $current_user->ID ? $current_user->display_name : 'unauthed user',
2384
-                'timestamp'   => time(),
2385
-                'source'      => $source,
2386
-            )
2387
-        );
2388
-        return parent::restore();
2389
-    }
2390
-
2391
-
2392
-    /**
2393
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
2394
-     *
2395
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
2396
-     *                                           depending on whether the reg status changes to or from "Approved"
2397
-     * @return boolean whether the Registration status was updated
2398
-     * @throws DomainException
2399
-     * @throws EE_Error
2400
-     * @throws EntityNotFoundException
2401
-     * @throws InvalidArgumentException
2402
-     * @throws InvalidDataTypeException
2403
-     * @throws InvalidInterfaceException
2404
-     * @throws ReflectionException
2405
-     * @throws RuntimeException
2406
-     * @throws UnexpectedEntityException
2407
-     */
2408
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
2409
-    {
2410
-        $paid = $this->paid();
2411
-        $price = $this->final_price();
2412
-        switch (true) {
2413
-            // overpaid or paid
2414
-            case EEH_Money::compare_floats($paid, $price, '>'):
2415
-            case EEH_Money::compare_floats($paid, $price):
2416
-                $new_status = EEM_Registration::status_id_approved;
2417
-                break;
2418
-            //  underpaid
2419
-            case EEH_Money::compare_floats($paid, $price, '<'):
2420
-                $new_status = EEM_Registration::status_id_pending_payment;
2421
-                break;
2422
-            // uhhh Houston...
2423
-            default:
2424
-                throw new RuntimeException(
2425
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2426
-                );
2427
-        }
2428
-        if ($new_status !== $this->status_ID()) {
2429
-            if ($trigger_set_status_logic) {
2430
-                return $this->set_status($new_status);
2431
-            }
2432
-            parent::set('STS_ID', $new_status);
2433
-            return true;
2434
-        }
2435
-        return false;
2436
-    }
2437
-
2438
-
2439
-    /*************************** DEPRECATED ***************************/
2440
-
2441
-
2442
-    /**
2443
-     * @deprecated
2444
-     * @since     4.7.0
2445
-     */
2446
-    public function price_paid()
2447
-    {
2448
-        EE_Error::doing_it_wrong(
2449
-            'EE_Registration::price_paid()',
2450
-            esc_html__(
2451
-                'This method is deprecated, please use EE_Registration::final_price() instead.',
2452
-                'event_espresso'
2453
-            ),
2454
-            '4.7.0'
2455
-        );
2456
-        return $this->final_price();
2457
-    }
2458
-
2459
-
2460
-    /**
2461
-     * @deprecated
2462
-     * @since     4.7.0
2463
-     * @param    float $REG_final_price
2464
-     * @throws EE_Error
2465
-     * @throws EntityNotFoundException
2466
-     * @throws InvalidArgumentException
2467
-     * @throws InvalidDataTypeException
2468
-     * @throws InvalidInterfaceException
2469
-     * @throws ReflectionException
2470
-     * @throws RuntimeException
2471
-     * @throws DomainException
2472
-     */
2473
-    public function set_price_paid($REG_final_price = 0.00)
2474
-    {
2475
-        EE_Error::doing_it_wrong(
2476
-            'EE_Registration::set_price_paid()',
2477
-            esc_html__(
2478
-                'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2479
-                'event_espresso'
2480
-            ),
2481
-            '4.7.0'
2482
-        );
2483
-        $this->set_final_price($REG_final_price);
2484
-    }
2485
-
2486
-
2487
-    /**
2488
-     * @deprecated
2489
-     * @since 4.7.0
2490
-     * @return string
2491
-     * @throws EE_Error
2492
-     * @throws InvalidArgumentException
2493
-     * @throws InvalidDataTypeException
2494
-     * @throws InvalidInterfaceException
2495
-     * @throws ReflectionException
2496
-     */
2497
-    public function pretty_price_paid()
2498
-    {
2499
-        EE_Error::doing_it_wrong(
2500
-            'EE_Registration::pretty_price_paid()',
2501
-            esc_html__(
2502
-                'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2503
-                'event_espresso'
2504
-            ),
2505
-            '4.7.0'
2506
-        );
2507
-        return $this->pretty_final_price();
2508
-    }
2509
-
2510
-
2511
-    /**
2512
-     * Gets the primary datetime related to this registration via the related Event to this registration
2513
-     *
2514
-     * @deprecated 4.9.17
2515
-     * @return EE_Datetime
2516
-     * @throws EE_Error
2517
-     * @throws EntityNotFoundException
2518
-     * @throws InvalidArgumentException
2519
-     * @throws InvalidDataTypeException
2520
-     * @throws InvalidInterfaceException
2521
-     * @throws ReflectionException
2522
-     */
2523
-    public function get_related_primary_datetime()
2524
-    {
2525
-        EE_Error::doing_it_wrong(
2526
-            __METHOD__,
2527
-            esc_html__(
2528
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2529
-                'event_espresso'
2530
-            ),
2531
-            '4.9.17',
2532
-            '5.0.0'
2533
-        );
2534
-        return $this->event()->primary_datetime();
2535
-    }
2536
-
2537
-    /**
2538
-     * Returns the contact's name (or "Unknown" if there is no contact.)
2539
-     * @since 4.10.12.p
2540
-     * @return string
2541
-     * @throws EE_Error
2542
-     * @throws InvalidArgumentException
2543
-     * @throws InvalidDataTypeException
2544
-     * @throws InvalidInterfaceException
2545
-     * @throws ReflectionException
2546
-     */
2547
-    public function name()
2548
-    {
2549
-        return $this->attendeeName();
2550
-    }
20
+	/**
21
+	 * Used to reference when a registration has never been checked in.
22
+	 *
23
+	 * @deprecated use \EE_Checkin::status_checked_never instead
24
+	 * @type int
25
+	 */
26
+	const checkin_status_never = 2;
27
+
28
+	/**
29
+	 * Used to reference when a registration has been checked in.
30
+	 *
31
+	 * @deprecated use \EE_Checkin::status_checked_in instead
32
+	 * @type int
33
+	 */
34
+	const checkin_status_in = 1;
35
+
36
+	/**
37
+	 * Used to reference when a registration has been checked out.
38
+	 *
39
+	 * @deprecated use \EE_Checkin::status_checked_out instead
40
+	 * @type int
41
+	 */
42
+	const checkin_status_out = 0;
43
+
44
+	/**
45
+	 * extra meta key for tracking reg status os trashed registrations
46
+	 *
47
+	 * @type string
48
+	 */
49
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
50
+
51
+	/**
52
+	 * extra meta key for tracking if registration has reserved ticket
53
+	 *
54
+	 * @type string
55
+	 */
56
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
57
+
58
+	/**
59
+	 * extra meta key for tracking when registrations are trashed and by who
60
+	 *
61
+	 * @type string
62
+	 */
63
+	const EXTRA_META_KEY_REG_TRASHED = 'registration-trashed';
64
+
65
+	/**
66
+	 * extra meta key for tracking when registrations are restored and by who
67
+	 *
68
+	 * @type string
69
+	 */
70
+	const EXTRA_META_KEY_REG_RESTORED = 'registration-restored';
71
+
72
+
73
+	/**
74
+	 * @param array  $props_n_values          incoming values
75
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
76
+	 *                                        used.)
77
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
78
+	 *                                        date_format and the second value is the time format
79
+	 * @return EE_Registration
80
+	 * @throws EE_Error
81
+	 * @throws InvalidArgumentException
82
+	 * @throws InvalidDataTypeException
83
+	 * @throws InvalidInterfaceException
84
+	 * @throws ReflectionException
85
+	 */
86
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
87
+	{
88
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
89
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
90
+	}
91
+
92
+
93
+	/**
94
+	 * @param array  $props_n_values  incoming values from the database
95
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
96
+	 *                                the website will be used.
97
+	 * @return EE_Registration
98
+	 * @throws EE_Error
99
+	 * @throws InvalidArgumentException
100
+	 * @throws InvalidDataTypeException
101
+	 * @throws InvalidInterfaceException
102
+	 * @throws ReflectionException
103
+	 */
104
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
105
+	{
106
+		return new self($props_n_values, true, $timezone);
107
+	}
108
+
109
+
110
+	/**
111
+	 *        Set Event ID
112
+	 *
113
+	 * @param        int $EVT_ID Event ID
114
+	 * @throws DomainException
115
+	 * @throws EE_Error
116
+	 * @throws EntityNotFoundException
117
+	 * @throws InvalidArgumentException
118
+	 * @throws InvalidDataTypeException
119
+	 * @throws InvalidInterfaceException
120
+	 * @throws ReflectionException
121
+	 * @throws RuntimeException
122
+	 * @throws UnexpectedEntityException
123
+	 */
124
+	public function set_event($EVT_ID = 0)
125
+	{
126
+		$this->set('EVT_ID', $EVT_ID);
127
+	}
128
+
129
+
130
+	/**
131
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
132
+	 * be routed to internal methods
133
+	 *
134
+	 * @param string $field_name
135
+	 * @param mixed  $field_value
136
+	 * @param bool   $use_default
137
+	 * @throws DomainException
138
+	 * @throws EE_Error
139
+	 * @throws EntityNotFoundException
140
+	 * @throws InvalidArgumentException
141
+	 * @throws InvalidDataTypeException
142
+	 * @throws InvalidInterfaceException
143
+	 * @throws ReflectionException
144
+	 * @throws RuntimeException
145
+	 * @throws UnexpectedEntityException
146
+	 */
147
+	public function set($field_name, $field_value, $use_default = false)
148
+	{
149
+		switch ($field_name) {
150
+			case 'REG_code':
151
+				if (! empty($field_value) && $this->reg_code() === null) {
152
+					$this->set_reg_code($field_value, $use_default);
153
+				}
154
+				break;
155
+			case 'STS_ID':
156
+				$this->set_status($field_value, $use_default);
157
+				break;
158
+			default:
159
+				parent::set($field_name, $field_value, $use_default);
160
+		}
161
+	}
162
+
163
+
164
+	/**
165
+	 * Set Status ID
166
+	 * updates the registration status and ALSO...
167
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
168
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
169
+	 *
170
+	 * @param string                $new_STS_ID
171
+	 * @param boolean               $use_default
172
+	 * @param ContextInterface|null $context
173
+	 * @return bool
174
+	 * @throws DomainException
175
+	 * @throws EE_Error
176
+	 * @throws EntityNotFoundException
177
+	 * @throws InvalidArgumentException
178
+	 * @throws InvalidDataTypeException
179
+	 * @throws InvalidInterfaceException
180
+	 * @throws ReflectionException
181
+	 * @throws RuntimeException
182
+	 * @throws UnexpectedEntityException
183
+	 */
184
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
185
+	{
186
+		// get current REG_Status
187
+		$old_STS_ID = $this->status_ID();
188
+		// if status has changed
189
+		if (
190
+			$old_STS_ID !== $new_STS_ID // and that status has actually changed
191
+			&& ! empty($old_STS_ID) // and that old status is actually set
192
+			&& ! empty($new_STS_ID) // as well as the new status
193
+			&& $this->ID() // ensure registration is in the db
194
+		) {
195
+			// update internal status first
196
+			parent::set('STS_ID', $new_STS_ID, $use_default);
197
+			// THEN handle other changes that occur when reg status changes
198
+			// TO approved
199
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
200
+				// reserve a space by incrementing ticket and datetime sold values
201
+				$this->reserveRegistrationSpace();
202
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
203
+				// OR FROM  approved
204
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
205
+				// release a space by decrementing ticket and datetime sold values
206
+				$this->releaseRegistrationSpace();
207
+				do_action(
208
+					'AHEE__EE_Registration__set_status__from_approved',
209
+					$this,
210
+					$old_STS_ID,
211
+					$new_STS_ID,
212
+					$context
213
+				);
214
+			}
215
+			// update status
216
+			parent::set('STS_ID', $new_STS_ID, $use_default);
217
+			$this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
218
+			if ($this->statusChangeUpdatesTransaction($context)) {
219
+				$this->updateTransactionAfterStatusChange();
220
+			}
221
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
222
+			return true;
223
+		}
224
+		// even though the old value matches the new value, it's still good to
225
+		// allow the parent set method to have a say
226
+		parent::set('STS_ID', $new_STS_ID, $use_default);
227
+		return true;
228
+	}
229
+
230
+
231
+	/**
232
+	 * update REGs and TXN when cancelled or declined registrations involved
233
+	 *
234
+	 * @param string                $new_STS_ID
235
+	 * @param string                $old_STS_ID
236
+	 * @param ContextInterface|null $context
237
+	 * @throws EE_Error
238
+	 * @throws InvalidArgumentException
239
+	 * @throws InvalidDataTypeException
240
+	 * @throws InvalidInterfaceException
241
+	 * @throws ReflectionException
242
+	 * @throws RuntimeException
243
+	 */
244
+	private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
245
+	{
246
+		// these reg statuses should not be considered in any calculations involving monies owing
247
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
248
+		// true if registration has been cancelled or declined
249
+		$this->updateIfCanceled(
250
+			$closed_reg_statuses,
251
+			$new_STS_ID,
252
+			$old_STS_ID,
253
+			$context
254
+		);
255
+		$this->updateIfReinstated(
256
+			$closed_reg_statuses,
257
+			$new_STS_ID,
258
+			$old_STS_ID,
259
+			$context
260
+		);
261
+	}
262
+
263
+
264
+	/**
265
+	 * update REGs and TXN when cancelled or declined registrations involved
266
+	 *
267
+	 * @param array                 $closed_reg_statuses
268
+	 * @param string                $new_STS_ID
269
+	 * @param string                $old_STS_ID
270
+	 * @param ContextInterface|null $context
271
+	 * @throws EE_Error
272
+	 * @throws InvalidArgumentException
273
+	 * @throws InvalidDataTypeException
274
+	 * @throws InvalidInterfaceException
275
+	 * @throws ReflectionException
276
+	 * @throws RuntimeException
277
+	 */
278
+	private function updateIfCanceled(
279
+		array $closed_reg_statuses,
280
+		$new_STS_ID,
281
+		$old_STS_ID,
282
+		ContextInterface $context = null
283
+	) {
284
+		// true if registration has been cancelled or declined
285
+		if (
286
+			in_array($new_STS_ID, $closed_reg_statuses, true)
287
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
288
+		) {
289
+			/** @type EE_Registration_Processor $registration_processor */
290
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
291
+			/** @type EE_Transaction_Processor $transaction_processor */
292
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
293
+			// cancelled or declined registration
294
+			$registration_processor->update_registration_after_being_canceled_or_declined(
295
+				$this,
296
+				$closed_reg_statuses
297
+			);
298
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
299
+				$this,
300
+				$closed_reg_statuses,
301
+				false
302
+			);
303
+			do_action(
304
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
305
+				$this,
306
+				$old_STS_ID,
307
+				$new_STS_ID,
308
+				$context
309
+			);
310
+			return;
311
+		}
312
+	}
313
+
314
+
315
+	/**
316
+	 * update REGs and TXN when cancelled or declined registrations involved
317
+	 *
318
+	 * @param array                 $closed_reg_statuses
319
+	 * @param string                $new_STS_ID
320
+	 * @param string                $old_STS_ID
321
+	 * @param ContextInterface|null $context
322
+	 * @throws EE_Error
323
+	 * @throws InvalidArgumentException
324
+	 * @throws InvalidDataTypeException
325
+	 * @throws InvalidInterfaceException
326
+	 * @throws ReflectionException
327
+	 * @throws RuntimeException
328
+	 */
329
+	private function updateIfReinstated(
330
+		array $closed_reg_statuses,
331
+		$new_STS_ID,
332
+		$old_STS_ID,
333
+		ContextInterface $context = null
334
+	) {
335
+		// true if reinstating cancelled or declined registration
336
+		if (
337
+			in_array($old_STS_ID, $closed_reg_statuses, true)
338
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
339
+		) {
340
+			/** @type EE_Registration_Processor $registration_processor */
341
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
342
+			/** @type EE_Transaction_Processor $transaction_processor */
343
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
344
+			// reinstating cancelled or declined registration
345
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
346
+				$this,
347
+				$closed_reg_statuses
348
+			);
349
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
350
+				$this,
351
+				$closed_reg_statuses,
352
+				false
353
+			);
354
+			do_action(
355
+				'AHEE__EE_Registration__set_status__after_reinstated',
356
+				$this,
357
+				$old_STS_ID,
358
+				$new_STS_ID,
359
+				$context
360
+			);
361
+		}
362
+	}
363
+
364
+
365
+	/**
366
+	 * @param ContextInterface|null $context
367
+	 * @return bool
368
+	 */
369
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
370
+	{
371
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
372
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
373
+			array('spco_reg_step_attendee_information_process_registrations'),
374
+			$context,
375
+			$this
376
+		);
377
+		return ! (
378
+			$context instanceof ContextInterface
379
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
380
+		);
381
+	}
382
+
383
+
384
+	/**
385
+	 * @throws EE_Error
386
+	 * @throws EntityNotFoundException
387
+	 * @throws InvalidArgumentException
388
+	 * @throws InvalidDataTypeException
389
+	 * @throws InvalidInterfaceException
390
+	 * @throws ReflectionException
391
+	 * @throws RuntimeException
392
+	 */
393
+	private function updateTransactionAfterStatusChange()
394
+	{
395
+		/** @type EE_Transaction_Payments $transaction_payments */
396
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
397
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
398
+		$this->transaction()->update_status_based_on_total_paid();
399
+	}
400
+
401
+
402
+	/**
403
+	 * get Status ID
404
+	 *
405
+	 * @throws EE_Error
406
+	 * @throws InvalidArgumentException
407
+	 * @throws InvalidDataTypeException
408
+	 * @throws InvalidInterfaceException
409
+	 * @throws ReflectionException
410
+	 */
411
+	public function status_ID()
412
+	{
413
+		return $this->get('STS_ID');
414
+	}
415
+
416
+
417
+	/**
418
+	 * Gets the ticket this registration is for
419
+	 *
420
+	 * @param boolean $include_archived whether to include archived tickets or not.
421
+	 * @return EE_Ticket|EE_Base_Class
422
+	 * @throws EE_Error
423
+	 * @throws InvalidArgumentException
424
+	 * @throws InvalidDataTypeException
425
+	 * @throws InvalidInterfaceException
426
+	 * @throws ReflectionException
427
+	 */
428
+	public function ticket($include_archived = true)
429
+	{
430
+		$query_params = array();
431
+		if ($include_archived) {
432
+			$query_params['default_where_conditions'] = 'none';
433
+		}
434
+		return $this->get_first_related('Ticket', $query_params);
435
+	}
436
+
437
+
438
+	/**
439
+	 * Gets the event this registration is for
440
+	 *
441
+	 * @return EE_Event
442
+	 * @throws EE_Error
443
+	 * @throws EntityNotFoundException
444
+	 * @throws InvalidArgumentException
445
+	 * @throws InvalidDataTypeException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function event()
450
+	{
451
+		$event = $this->get_first_related('Event');
452
+		if (! $event instanceof \EE_Event) {
453
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
454
+		}
455
+		return $event;
456
+	}
457
+
458
+
459
+	/**
460
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
461
+	 * with the author of the event this registration is for.
462
+	 *
463
+	 * @since 4.5.0
464
+	 * @return int
465
+	 * @throws EE_Error
466
+	 * @throws EntityNotFoundException
467
+	 * @throws InvalidArgumentException
468
+	 * @throws InvalidDataTypeException
469
+	 * @throws InvalidInterfaceException
470
+	 * @throws ReflectionException
471
+	 */
472
+	public function wp_user()
473
+	{
474
+		$event = $this->event();
475
+		if ($event instanceof EE_Event) {
476
+			return $event->wp_user();
477
+		}
478
+		return 0;
479
+	}
480
+
481
+
482
+	/**
483
+	 * increments this registration's related ticket sold and corresponding datetime sold values
484
+	 *
485
+	 * @return void
486
+	 * @throws DomainException
487
+	 * @throws EE_Error
488
+	 * @throws EntityNotFoundException
489
+	 * @throws InvalidArgumentException
490
+	 * @throws InvalidDataTypeException
491
+	 * @throws InvalidInterfaceException
492
+	 * @throws ReflectionException
493
+	 * @throws UnexpectedEntityException
494
+	 */
495
+	private function reserveRegistrationSpace()
496
+	{
497
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
498
+		// so stop tracking that this reg has a ticket reserved
499
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
500
+		$ticket = $this->ticket();
501
+		$ticket->increaseSold();
502
+		// possibly set event status to sold out
503
+		$this->event()->perform_sold_out_status_check();
504
+	}
505
+
506
+
507
+	/**
508
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
509
+	 *
510
+	 * @return void
511
+	 * @throws DomainException
512
+	 * @throws EE_Error
513
+	 * @throws EntityNotFoundException
514
+	 * @throws InvalidArgumentException
515
+	 * @throws InvalidDataTypeException
516
+	 * @throws InvalidInterfaceException
517
+	 * @throws ReflectionException
518
+	 * @throws UnexpectedEntityException
519
+	 */
520
+	private function releaseRegistrationSpace()
521
+	{
522
+		$ticket = $this->ticket();
523
+		$ticket->decreaseSold();
524
+		// possibly change event status from sold out back to previous status
525
+		$this->event()->perform_sold_out_status_check();
526
+	}
527
+
528
+
529
+	/**
530
+	 * tracks this registration's ticket reservation in extra meta
531
+	 * and can increment related ticket reserved and corresponding datetime reserved values
532
+	 *
533
+	 * @param bool   $update_ticket if true, will increment ticket and datetime reserved count
534
+	 * @param string $source
535
+	 * @return void
536
+	 * @throws EE_Error
537
+	 * @throws InvalidArgumentException
538
+	 * @throws InvalidDataTypeException
539
+	 * @throws InvalidInterfaceException
540
+	 * @throws ReflectionException
541
+	 */
542
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
543
+	{
544
+		// only reserve ticket if space is not currently reserved
545
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
546
+			$reserved = $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
547
+			if ($reserved && $update_ticket) {
548
+				$ticket = $this->ticket();
549
+				$ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
550
+				$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
551
+				$ticket->save();
552
+			}
553
+		}
554
+	}
555
+
556
+
557
+	/**
558
+	 * stops tracking this registration's ticket reservation in extra meta
559
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
560
+	 *
561
+	 * @param bool   $update_ticket if true, will decrement ticket and datetime reserved count
562
+	 * @param string $source
563
+	 * @return void
564
+	 * @throws EE_Error
565
+	 * @throws InvalidArgumentException
566
+	 * @throws InvalidDataTypeException
567
+	 * @throws InvalidInterfaceException
568
+	 * @throws ReflectionException
569
+	 */
570
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
571
+	{
572
+		// only release ticket if space is currently reserved
573
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
574
+			$reserved = $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false);
575
+			if ($reserved && $update_ticket) {
576
+				$ticket = $this->ticket();
577
+				$ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
578
+				$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
579
+			}
580
+		}
581
+	}
582
+
583
+
584
+	/**
585
+	 * Set Attendee ID
586
+	 *
587
+	 * @param        int $ATT_ID Attendee ID
588
+	 * @throws DomainException
589
+	 * @throws EE_Error
590
+	 * @throws EntityNotFoundException
591
+	 * @throws InvalidArgumentException
592
+	 * @throws InvalidDataTypeException
593
+	 * @throws InvalidInterfaceException
594
+	 * @throws ReflectionException
595
+	 * @throws RuntimeException
596
+	 * @throws UnexpectedEntityException
597
+	 */
598
+	public function set_attendee_id($ATT_ID = 0)
599
+	{
600
+		$this->set('ATT_ID', $ATT_ID);
601
+	}
602
+
603
+
604
+	/**
605
+	 *        Set Transaction ID
606
+	 *
607
+	 * @param        int $TXN_ID Transaction ID
608
+	 * @throws DomainException
609
+	 * @throws EE_Error
610
+	 * @throws EntityNotFoundException
611
+	 * @throws InvalidArgumentException
612
+	 * @throws InvalidDataTypeException
613
+	 * @throws InvalidInterfaceException
614
+	 * @throws ReflectionException
615
+	 * @throws RuntimeException
616
+	 * @throws UnexpectedEntityException
617
+	 */
618
+	public function set_transaction_id($TXN_ID = 0)
619
+	{
620
+		$this->set('TXN_ID', $TXN_ID);
621
+	}
622
+
623
+
624
+	/**
625
+	 *        Set Session
626
+	 *
627
+	 * @param    string $REG_session PHP Session ID
628
+	 * @throws DomainException
629
+	 * @throws EE_Error
630
+	 * @throws EntityNotFoundException
631
+	 * @throws InvalidArgumentException
632
+	 * @throws InvalidDataTypeException
633
+	 * @throws InvalidInterfaceException
634
+	 * @throws ReflectionException
635
+	 * @throws RuntimeException
636
+	 * @throws UnexpectedEntityException
637
+	 */
638
+	public function set_session($REG_session = '')
639
+	{
640
+		$this->set('REG_session', $REG_session);
641
+	}
642
+
643
+
644
+	/**
645
+	 *        Set Registration URL Link
646
+	 *
647
+	 * @param    string $REG_url_link Registration URL Link
648
+	 * @throws DomainException
649
+	 * @throws EE_Error
650
+	 * @throws EntityNotFoundException
651
+	 * @throws InvalidArgumentException
652
+	 * @throws InvalidDataTypeException
653
+	 * @throws InvalidInterfaceException
654
+	 * @throws ReflectionException
655
+	 * @throws RuntimeException
656
+	 * @throws UnexpectedEntityException
657
+	 */
658
+	public function set_reg_url_link($REG_url_link = '')
659
+	{
660
+		$this->set('REG_url_link', $REG_url_link);
661
+	}
662
+
663
+
664
+	/**
665
+	 *        Set Attendee Counter
666
+	 *
667
+	 * @param        int $REG_count Primary Attendee
668
+	 * @throws DomainException
669
+	 * @throws EE_Error
670
+	 * @throws EntityNotFoundException
671
+	 * @throws InvalidArgumentException
672
+	 * @throws InvalidDataTypeException
673
+	 * @throws InvalidInterfaceException
674
+	 * @throws ReflectionException
675
+	 * @throws RuntimeException
676
+	 * @throws UnexpectedEntityException
677
+	 */
678
+	public function set_count($REG_count = 1)
679
+	{
680
+		$this->set('REG_count', $REG_count);
681
+	}
682
+
683
+
684
+	/**
685
+	 *        Set Group Size
686
+	 *
687
+	 * @param        boolean $REG_group_size Group Registration
688
+	 * @throws DomainException
689
+	 * @throws EE_Error
690
+	 * @throws EntityNotFoundException
691
+	 * @throws InvalidArgumentException
692
+	 * @throws InvalidDataTypeException
693
+	 * @throws InvalidInterfaceException
694
+	 * @throws ReflectionException
695
+	 * @throws RuntimeException
696
+	 * @throws UnexpectedEntityException
697
+	 */
698
+	public function set_group_size($REG_group_size = false)
699
+	{
700
+		$this->set('REG_group_size', $REG_group_size);
701
+	}
702
+
703
+
704
+	/**
705
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
706
+	 *    EEM_Registration::status_id_not_approved
707
+	 *
708
+	 * @return        boolean
709
+	 * @throws EE_Error
710
+	 * @throws InvalidArgumentException
711
+	 * @throws InvalidDataTypeException
712
+	 * @throws InvalidInterfaceException
713
+	 * @throws ReflectionException
714
+	 */
715
+	public function is_not_approved()
716
+	{
717
+		return $this->status_ID() === EEM_Registration::status_id_not_approved;
718
+	}
719
+
720
+
721
+	/**
722
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
723
+	 *    EEM_Registration::status_id_pending_payment
724
+	 *
725
+	 * @return        boolean
726
+	 * @throws EE_Error
727
+	 * @throws InvalidArgumentException
728
+	 * @throws InvalidDataTypeException
729
+	 * @throws InvalidInterfaceException
730
+	 * @throws ReflectionException
731
+	 */
732
+	public function is_pending_payment()
733
+	{
734
+		return $this->status_ID() === EEM_Registration::status_id_pending_payment;
735
+	}
736
+
737
+
738
+	/**
739
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
740
+	 *
741
+	 * @return        boolean
742
+	 * @throws EE_Error
743
+	 * @throws InvalidArgumentException
744
+	 * @throws InvalidDataTypeException
745
+	 * @throws InvalidInterfaceException
746
+	 * @throws ReflectionException
747
+	 */
748
+	public function is_approved()
749
+	{
750
+		return $this->status_ID() === EEM_Registration::status_id_approved;
751
+	}
752
+
753
+
754
+	/**
755
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
756
+	 *
757
+	 * @return        boolean
758
+	 * @throws EE_Error
759
+	 * @throws InvalidArgumentException
760
+	 * @throws InvalidDataTypeException
761
+	 * @throws InvalidInterfaceException
762
+	 * @throws ReflectionException
763
+	 */
764
+	public function is_cancelled()
765
+	{
766
+		return $this->status_ID() === EEM_Registration::status_id_cancelled;
767
+	}
768
+
769
+
770
+	/**
771
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
772
+	 *
773
+	 * @return        boolean
774
+	 * @throws EE_Error
775
+	 * @throws InvalidArgumentException
776
+	 * @throws InvalidDataTypeException
777
+	 * @throws InvalidInterfaceException
778
+	 * @throws ReflectionException
779
+	 */
780
+	public function is_declined()
781
+	{
782
+		return $this->status_ID() === EEM_Registration::status_id_declined;
783
+	}
784
+
785
+
786
+	/**
787
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
788
+	 *    EEM_Registration::status_id_incomplete
789
+	 *
790
+	 * @return        boolean
791
+	 * @throws EE_Error
792
+	 * @throws InvalidArgumentException
793
+	 * @throws InvalidDataTypeException
794
+	 * @throws InvalidInterfaceException
795
+	 * @throws ReflectionException
796
+	 */
797
+	public function is_incomplete()
798
+	{
799
+		return $this->status_ID() === EEM_Registration::status_id_incomplete;
800
+	}
801
+
802
+
803
+	/**
804
+	 *        Set Registration Date
805
+	 *
806
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
807
+	 *                                                 Date
808
+	 * @throws DomainException
809
+	 * @throws EE_Error
810
+	 * @throws EntityNotFoundException
811
+	 * @throws InvalidArgumentException
812
+	 * @throws InvalidDataTypeException
813
+	 * @throws InvalidInterfaceException
814
+	 * @throws ReflectionException
815
+	 * @throws RuntimeException
816
+	 * @throws UnexpectedEntityException
817
+	 */
818
+	public function set_reg_date($REG_date = false)
819
+	{
820
+		$this->set('REG_date', $REG_date);
821
+	}
822
+
823
+
824
+	/**
825
+	 *    Set final price owing for this registration after all ticket/price modifications
826
+	 *
827
+	 * @param    float $REG_final_price
828
+	 * @throws DomainException
829
+	 * @throws EE_Error
830
+	 * @throws EntityNotFoundException
831
+	 * @throws InvalidArgumentException
832
+	 * @throws InvalidDataTypeException
833
+	 * @throws InvalidInterfaceException
834
+	 * @throws ReflectionException
835
+	 * @throws RuntimeException
836
+	 * @throws UnexpectedEntityException
837
+	 */
838
+	public function set_final_price($REG_final_price = 0.00)
839
+	{
840
+		$this->set('REG_final_price', $REG_final_price);
841
+	}
842
+
843
+
844
+	/**
845
+	 *    Set amount paid towards this registration's final price
846
+	 *
847
+	 * @param    float $REG_paid
848
+	 * @throws DomainException
849
+	 * @throws EE_Error
850
+	 * @throws EntityNotFoundException
851
+	 * @throws InvalidArgumentException
852
+	 * @throws InvalidDataTypeException
853
+	 * @throws InvalidInterfaceException
854
+	 * @throws ReflectionException
855
+	 * @throws RuntimeException
856
+	 * @throws UnexpectedEntityException
857
+	 */
858
+	public function set_paid($REG_paid = 0.00)
859
+	{
860
+		$this->set('REG_paid', $REG_paid);
861
+	}
862
+
863
+
864
+	/**
865
+	 *        Attendee Is Going
866
+	 *
867
+	 * @param        boolean $REG_att_is_going Attendee Is Going
868
+	 * @throws DomainException
869
+	 * @throws EE_Error
870
+	 * @throws EntityNotFoundException
871
+	 * @throws InvalidArgumentException
872
+	 * @throws InvalidDataTypeException
873
+	 * @throws InvalidInterfaceException
874
+	 * @throws ReflectionException
875
+	 * @throws RuntimeException
876
+	 * @throws UnexpectedEntityException
877
+	 */
878
+	public function set_att_is_going($REG_att_is_going = false)
879
+	{
880
+		$this->set('REG_att_is_going', $REG_att_is_going);
881
+	}
882
+
883
+
884
+	/**
885
+	 * Gets the related attendee
886
+	 *
887
+	 * @return EE_Attendee|EE_Base_Class
888
+	 * @throws EE_Error
889
+	 * @throws InvalidArgumentException
890
+	 * @throws InvalidDataTypeException
891
+	 * @throws InvalidInterfaceException
892
+	 * @throws ReflectionException
893
+	 */
894
+	public function attendee()
895
+	{
896
+		return $this->get_first_related('Attendee');
897
+	}
898
+
899
+	/**
900
+	 * Gets the name of the attendee.
901
+	 * @since 4.10.12.p
902
+	 * @param bool $apply_html_entities set to true if you want to use HTML entities.
903
+	 * @return string
904
+	 * @throws EE_Error
905
+	 * @throws InvalidArgumentException
906
+	 * @throws InvalidDataTypeException
907
+	 * @throws InvalidInterfaceException
908
+	 * @throws ReflectionException
909
+	 */
910
+	public function attendeeName($apply_html_entities = false)
911
+	{
912
+		$attendee = $this->get_first_related('Attendee');
913
+		if ($attendee instanceof EE_Attendee) {
914
+			$attendee_name = $attendee->full_name($apply_html_entities);
915
+		} else {
916
+			$attendee_name = esc_html__('Unknown', 'event_espresso');
917
+		}
918
+		return $attendee_name;
919
+	}
920
+
921
+
922
+	/**
923
+	 *        get Event ID
924
+	 */
925
+	public function event_ID()
926
+	{
927
+		return $this->get('EVT_ID');
928
+	}
929
+
930
+
931
+	/**
932
+	 *        get Event ID
933
+	 */
934
+	public function event_name()
935
+	{
936
+		$event = $this->event_obj();
937
+		if ($event) {
938
+			return $event->name();
939
+		} else {
940
+			return null;
941
+		}
942
+	}
943
+
944
+
945
+	/**
946
+	 * Fetches the event this registration is for
947
+	 *
948
+	 * @return EE_Base_Class|EE_Event
949
+	 * @throws EE_Error
950
+	 * @throws InvalidArgumentException
951
+	 * @throws InvalidDataTypeException
952
+	 * @throws InvalidInterfaceException
953
+	 * @throws ReflectionException
954
+	 */
955
+	public function event_obj()
956
+	{
957
+		return $this->get_first_related('Event');
958
+	}
959
+
960
+
961
+	/**
962
+	 *        get Attendee ID
963
+	 */
964
+	public function attendee_ID()
965
+	{
966
+		return $this->get('ATT_ID');
967
+	}
968
+
969
+
970
+	/**
971
+	 *        get PHP Session ID
972
+	 */
973
+	public function session_ID()
974
+	{
975
+		return $this->get('REG_session');
976
+	}
977
+
978
+
979
+	/**
980
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
981
+	 *
982
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
983
+	 * @return string
984
+	 * @throws DomainException
985
+	 * @throws EE_Error
986
+	 * @throws InvalidArgumentException
987
+	 * @throws InvalidDataTypeException
988
+	 * @throws InvalidInterfaceException
989
+	 * @throws ReflectionException
990
+	 */
991
+	public function receipt_url($messenger = 'html')
992
+	{
993
+
994
+		/**
995
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
996
+		 * already in use on old system.  If there is then we just return the standard url for it.
997
+		 *
998
+		 * @since 4.5.0
999
+		 */
1000
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
1001
+		$has_custom = EEH_Template::locate_template(
1002
+			$template_relative_path,
1003
+			array(),
1004
+			true,
1005
+			true,
1006
+			true
1007
+		);
1008
+
1009
+		if ($has_custom) {
1010
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
1011
+		}
1012
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
1013
+	}
1014
+
1015
+
1016
+	/**
1017
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
1018
+	 *
1019
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
1020
+	 * @return string
1021
+	 * @throws DomainException
1022
+	 * @throws EE_Error
1023
+	 * @throws InvalidArgumentException
1024
+	 * @throws InvalidDataTypeException
1025
+	 * @throws InvalidInterfaceException
1026
+	 * @throws ReflectionException
1027
+	 */
1028
+	public function invoice_url($messenger = 'html')
1029
+	{
1030
+		/**
1031
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
1032
+		 * already in use on old system.  If there is then we just return the standard url for it.
1033
+		 *
1034
+		 * @since 4.5.0
1035
+		 */
1036
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
1037
+		$has_custom = EEH_Template::locate_template(
1038
+			$template_relative_path,
1039
+			array(),
1040
+			true,
1041
+			true,
1042
+			true
1043
+		);
1044
+
1045
+		if ($has_custom) {
1046
+			if ($messenger == 'html') {
1047
+				return $this->invoice_url('launch');
1048
+			}
1049
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
1050
+
1051
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
1052
+			if ($messenger == 'html') {
1053
+				$query_args['html'] = true;
1054
+			}
1055
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
1056
+		}
1057
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
1058
+	}
1059
+
1060
+
1061
+	/**
1062
+	 * get Registration URL Link
1063
+	 *
1064
+	 * @return string
1065
+	 * @throws EE_Error
1066
+	 * @throws InvalidArgumentException
1067
+	 * @throws InvalidDataTypeException
1068
+	 * @throws InvalidInterfaceException
1069
+	 * @throws ReflectionException
1070
+	 */
1071
+	public function reg_url_link()
1072
+	{
1073
+		return (string) $this->get('REG_url_link');
1074
+	}
1075
+
1076
+
1077
+	/**
1078
+	 * Echoes out invoice_url()
1079
+	 *
1080
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
1081
+	 * @return void
1082
+	 * @throws DomainException
1083
+	 * @throws EE_Error
1084
+	 * @throws InvalidArgumentException
1085
+	 * @throws InvalidDataTypeException
1086
+	 * @throws InvalidInterfaceException
1087
+	 * @throws ReflectionException
1088
+	 */
1089
+	public function e_invoice_url($type = 'launch')
1090
+	{
1091
+		echo esc_url_raw($this->invoice_url($type));
1092
+	}
1093
+
1094
+
1095
+	/**
1096
+	 * Echoes out payment_overview_url
1097
+	 */
1098
+	public function e_payment_overview_url()
1099
+	{
1100
+		echo esc_url_raw($this->payment_overview_url());
1101
+	}
1102
+
1103
+
1104
+	/**
1105
+	 * Gets the URL for the checkout payment options reg step
1106
+	 * with this registration's REG_url_link added as a query parameter
1107
+	 *
1108
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
1109
+	 *                            payment overview url.
1110
+	 * @return string
1111
+	 * @throws EE_Error
1112
+	 * @throws InvalidArgumentException
1113
+	 * @throws InvalidDataTypeException
1114
+	 * @throws InvalidInterfaceException
1115
+	 * @throws ReflectionException
1116
+	 */
1117
+	public function payment_overview_url($clear_session = false)
1118
+	{
1119
+		return add_query_arg(
1120
+			(array) apply_filters(
1121
+				'FHEE__EE_Registration__payment_overview_url__query_args',
1122
+				array(
1123
+					'e_reg_url_link' => $this->reg_url_link(),
1124
+					'step'           => 'payment_options',
1125
+					'revisit'        => true,
1126
+					'clear_session'  => (bool) $clear_session,
1127
+				),
1128
+				$this
1129
+			),
1130
+			EE_Registry::instance()->CFG->core->reg_page_url()
1131
+		);
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * Gets the URL for the checkout attendee information reg step
1137
+	 * with this registration's REG_url_link added as a query parameter
1138
+	 *
1139
+	 * @return string
1140
+	 * @throws EE_Error
1141
+	 * @throws InvalidArgumentException
1142
+	 * @throws InvalidDataTypeException
1143
+	 * @throws InvalidInterfaceException
1144
+	 * @throws ReflectionException
1145
+	 */
1146
+	public function edit_attendee_information_url()
1147
+	{
1148
+		return add_query_arg(
1149
+			(array) apply_filters(
1150
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
1151
+				array(
1152
+					'e_reg_url_link' => $this->reg_url_link(),
1153
+					'step'           => 'attendee_information',
1154
+					'revisit'        => true,
1155
+				),
1156
+				$this
1157
+			),
1158
+			EE_Registry::instance()->CFG->core->reg_page_url()
1159
+		);
1160
+	}
1161
+
1162
+
1163
+	/**
1164
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
1165
+	 *
1166
+	 * @return string
1167
+	 * @throws EE_Error
1168
+	 * @throws InvalidArgumentException
1169
+	 * @throws InvalidDataTypeException
1170
+	 * @throws InvalidInterfaceException
1171
+	 * @throws ReflectionException
1172
+	 */
1173
+	public function get_admin_edit_url()
1174
+	{
1175
+		return EEH_URL::add_query_args_and_nonce(
1176
+			array(
1177
+				'page'    => 'espresso_registrations',
1178
+				'action'  => 'view_registration',
1179
+				'_REG_ID' => $this->ID(),
1180
+			),
1181
+			admin_url('admin.php')
1182
+		);
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * is_primary_registrant?
1188
+	 *
1189
+	 * @throws EE_Error
1190
+	 * @throws InvalidArgumentException
1191
+	 * @throws InvalidDataTypeException
1192
+	 * @throws InvalidInterfaceException
1193
+	 * @throws ReflectionException
1194
+	 */
1195
+	public function is_primary_registrant()
1196
+	{
1197
+		return (int) $this->get('REG_count') === 1;
1198
+	}
1199
+
1200
+
1201
+	/**
1202
+	 * This returns the primary registration object for this registration group (which may be this object).
1203
+	 *
1204
+	 * @return EE_Registration
1205
+	 * @throws EE_Error
1206
+	 * @throws InvalidArgumentException
1207
+	 * @throws InvalidDataTypeException
1208
+	 * @throws InvalidInterfaceException
1209
+	 * @throws ReflectionException
1210
+	 */
1211
+	public function get_primary_registration()
1212
+	{
1213
+		if ($this->is_primary_registrant()) {
1214
+			return $this;
1215
+		}
1216
+
1217
+		// k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1218
+		/** @var EE_Registration $primary_registrant */
1219
+		$primary_registrant = EEM_Registration::instance()->get_one(
1220
+			array(
1221
+				array(
1222
+					'TXN_ID'    => $this->transaction_ID(),
1223
+					'REG_count' => 1,
1224
+				),
1225
+			)
1226
+		);
1227
+		return $primary_registrant;
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * get  Attendee Number
1233
+	 *
1234
+	 * @throws EE_Error
1235
+	 * @throws InvalidArgumentException
1236
+	 * @throws InvalidDataTypeException
1237
+	 * @throws InvalidInterfaceException
1238
+	 * @throws ReflectionException
1239
+	 */
1240
+	public function count()
1241
+	{
1242
+		return $this->get('REG_count');
1243
+	}
1244
+
1245
+
1246
+	/**
1247
+	 * get Group Size
1248
+	 *
1249
+	 * @throws EE_Error
1250
+	 * @throws InvalidArgumentException
1251
+	 * @throws InvalidDataTypeException
1252
+	 * @throws InvalidInterfaceException
1253
+	 * @throws ReflectionException
1254
+	 */
1255
+	public function group_size()
1256
+	{
1257
+		return $this->get('REG_group_size');
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * get Registration Date
1263
+	 *
1264
+	 * @throws EE_Error
1265
+	 * @throws InvalidArgumentException
1266
+	 * @throws InvalidDataTypeException
1267
+	 * @throws InvalidInterfaceException
1268
+	 * @throws ReflectionException
1269
+	 */
1270
+	public function date()
1271
+	{
1272
+		return $this->get('REG_date');
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * gets a pretty date
1278
+	 *
1279
+	 * @param string $date_format
1280
+	 * @param string $time_format
1281
+	 * @return string
1282
+	 * @throws EE_Error
1283
+	 * @throws InvalidArgumentException
1284
+	 * @throws InvalidDataTypeException
1285
+	 * @throws InvalidInterfaceException
1286
+	 * @throws ReflectionException
1287
+	 */
1288
+	public function pretty_date($date_format = null, $time_format = null)
1289
+	{
1290
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * final_price
1296
+	 * the registration's share of the transaction total, so that the
1297
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1298
+	 *
1299
+	 * @return float
1300
+	 * @throws EE_Error
1301
+	 * @throws InvalidArgumentException
1302
+	 * @throws InvalidDataTypeException
1303
+	 * @throws InvalidInterfaceException
1304
+	 * @throws ReflectionException
1305
+	 */
1306
+	public function final_price()
1307
+	{
1308
+		return $this->get('REG_final_price');
1309
+	}
1310
+
1311
+
1312
+	/**
1313
+	 * pretty_final_price
1314
+	 *  final price as formatted string, with correct decimal places and currency symbol
1315
+	 *
1316
+	 * @return string
1317
+	 * @throws EE_Error
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws InvalidDataTypeException
1320
+	 * @throws InvalidInterfaceException
1321
+	 * @throws ReflectionException
1322
+	 */
1323
+	public function pretty_final_price()
1324
+	{
1325
+		return $this->get_pretty('REG_final_price');
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 * get paid (yeah)
1331
+	 *
1332
+	 * @return float
1333
+	 * @throws EE_Error
1334
+	 * @throws InvalidArgumentException
1335
+	 * @throws InvalidDataTypeException
1336
+	 * @throws InvalidInterfaceException
1337
+	 * @throws ReflectionException
1338
+	 */
1339
+	public function paid()
1340
+	{
1341
+		return $this->get('REG_paid');
1342
+	}
1343
+
1344
+
1345
+	/**
1346
+	 * pretty_paid
1347
+	 *
1348
+	 * @return float
1349
+	 * @throws EE_Error
1350
+	 * @throws InvalidArgumentException
1351
+	 * @throws InvalidDataTypeException
1352
+	 * @throws InvalidInterfaceException
1353
+	 * @throws ReflectionException
1354
+	 */
1355
+	public function pretty_paid()
1356
+	{
1357
+		return $this->get_pretty('REG_paid');
1358
+	}
1359
+
1360
+
1361
+	/**
1362
+	 * owes_monies_and_can_pay
1363
+	 * whether or not this registration has monies owing and it's' status allows payment
1364
+	 *
1365
+	 * @param array $requires_payment
1366
+	 * @return bool
1367
+	 * @throws EE_Error
1368
+	 * @throws InvalidArgumentException
1369
+	 * @throws InvalidDataTypeException
1370
+	 * @throws InvalidInterfaceException
1371
+	 * @throws ReflectionException
1372
+	 */
1373
+	public function owes_monies_and_can_pay($requires_payment = array())
1374
+	{
1375
+		// these reg statuses require payment (if event is not free)
1376
+		$requires_payment = ! empty($requires_payment)
1377
+			? $requires_payment
1378
+			: EEM_Registration::reg_statuses_that_allow_payment();
1379
+		if (
1380
+			$this->final_price() !== 0 &&
1381
+			$this->final_price() !== $this->paid() &&
1382
+			in_array($this->status_ID(), $requires_payment)
1383
+		) {
1384
+			return true;
1385
+		}
1386
+		return false;
1387
+	}
1388
+
1389
+
1390
+	/**
1391
+	 * Prints out the return value of $this->pretty_status()
1392
+	 *
1393
+	 * @param bool $show_icons
1394
+	 * @return void
1395
+	 * @throws EE_Error
1396
+	 * @throws InvalidArgumentException
1397
+	 * @throws InvalidDataTypeException
1398
+	 * @throws InvalidInterfaceException
1399
+	 * @throws ReflectionException
1400
+	 */
1401
+	public function e_pretty_status($show_icons = false)
1402
+	{
1403
+		echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * Returns a nice version of the status for displaying to customers
1409
+	 *
1410
+	 * @param bool $show_icons
1411
+	 * @return string
1412
+	 * @throws EE_Error
1413
+	 * @throws InvalidArgumentException
1414
+	 * @throws InvalidDataTypeException
1415
+	 * @throws InvalidInterfaceException
1416
+	 * @throws ReflectionException
1417
+	 */
1418
+	public function pretty_status($show_icons = false)
1419
+	{
1420
+		$status = EEM_Status::instance()->localized_status(
1421
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1422
+			false,
1423
+			'sentence'
1424
+		);
1425
+		$icon = '';
1426
+		switch ($this->status_ID()) {
1427
+			case EEM_Registration::status_id_approved:
1428
+				$icon = $show_icons
1429
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1430
+					: '';
1431
+				break;
1432
+			case EEM_Registration::status_id_pending_payment:
1433
+				$icon = $show_icons
1434
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1435
+					: '';
1436
+				break;
1437
+			case EEM_Registration::status_id_not_approved:
1438
+				$icon = $show_icons
1439
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1440
+					: '';
1441
+				break;
1442
+			case EEM_Registration::status_id_cancelled:
1443
+				$icon = $show_icons
1444
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1445
+					: '';
1446
+				break;
1447
+			case EEM_Registration::status_id_incomplete:
1448
+				$icon = $show_icons
1449
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1450
+					: '';
1451
+				break;
1452
+			case EEM_Registration::status_id_declined:
1453
+				$icon = $show_icons
1454
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1455
+					: '';
1456
+				break;
1457
+			case EEM_Registration::status_id_wait_list:
1458
+				$icon = $show_icons
1459
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1460
+					: '';
1461
+				break;
1462
+		}
1463
+		return $icon . $status[ $this->status_ID() ];
1464
+	}
1465
+
1466
+
1467
+	/**
1468
+	 *        get Attendee Is Going
1469
+	 */
1470
+	public function att_is_going()
1471
+	{
1472
+		return $this->get('REG_att_is_going');
1473
+	}
1474
+
1475
+
1476
+	/**
1477
+	 * Gets related answers
1478
+	 *
1479
+	 * @param array $query_params @see
1480
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1481
+	 * @return EE_Answer[]|EE_Base_Class[]
1482
+	 * @throws EE_Error
1483
+	 * @throws InvalidArgumentException
1484
+	 * @throws InvalidDataTypeException
1485
+	 * @throws InvalidInterfaceException
1486
+	 * @throws ReflectionException
1487
+	 */
1488
+	public function answers($query_params = null)
1489
+	{
1490
+		return $this->get_many_related('Answer', $query_params);
1491
+	}
1492
+
1493
+
1494
+	/**
1495
+	 * Gets the registration's answer value to the specified question
1496
+	 * (either the question's ID or a question object)
1497
+	 *
1498
+	 * @param EE_Question|int $question
1499
+	 * @param bool            $pretty_value
1500
+	 * @return array|string if pretty_value= true, the result will always be a string
1501
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1502
+	 * will convert it into some kind of string)
1503
+	 * @throws EE_Error
1504
+	 * @throws InvalidArgumentException
1505
+	 * @throws InvalidDataTypeException
1506
+	 * @throws InvalidInterfaceException
1507
+	 */
1508
+	public function answer_value_to_question($question, $pretty_value = true)
1509
+	{
1510
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1511
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1512
+	}
1513
+
1514
+
1515
+	/**
1516
+	 * question_groups
1517
+	 * returns an array of EE_Question_Group objects for this registration
1518
+	 *
1519
+	 * @return EE_Question_Group[]
1520
+	 * @throws EE_Error
1521
+	 * @throws InvalidArgumentException
1522
+	 * @throws InvalidDataTypeException
1523
+	 * @throws InvalidInterfaceException
1524
+	 * @throws ReflectionException
1525
+	 */
1526
+	public function question_groups()
1527
+	{
1528
+		return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 * count_question_groups
1534
+	 * returns a count of the number of EE_Question_Group objects for this registration
1535
+	 *
1536
+	 * @return int
1537
+	 * @throws EE_Error
1538
+	 * @throws EntityNotFoundException
1539
+	 * @throws InvalidArgumentException
1540
+	 * @throws InvalidDataTypeException
1541
+	 * @throws InvalidInterfaceException
1542
+	 * @throws ReflectionException
1543
+	 */
1544
+	public function count_question_groups()
1545
+	{
1546
+		return EEM_Event::instance()->count_related(
1547
+			$this->event_ID(),
1548
+			'Question_Group',
1549
+			[
1550
+				[
1551
+					'Event_Question_Group.'
1552
+					. EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1553
+				]
1554
+			]
1555
+		);
1556
+	}
1557
+
1558
+
1559
+	/**
1560
+	 * Returns the registration date in the 'standard' string format
1561
+	 * (function may be improved in the future to allow for different formats and timezones)
1562
+	 *
1563
+	 * @return string
1564
+	 * @throws EE_Error
1565
+	 * @throws InvalidArgumentException
1566
+	 * @throws InvalidDataTypeException
1567
+	 * @throws InvalidInterfaceException
1568
+	 * @throws ReflectionException
1569
+	 */
1570
+	public function reg_date()
1571
+	{
1572
+		return $this->get_datetime('REG_date');
1573
+	}
1574
+
1575
+
1576
+	/**
1577
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1578
+	 * the ticket this registration purchased, or the datetime they have registered
1579
+	 * to attend)
1580
+	 *
1581
+	 * @return EE_Base_Class|EE_Datetime_Ticket
1582
+	 * @throws EE_Error
1583
+	 * @throws InvalidArgumentException
1584
+	 * @throws InvalidDataTypeException
1585
+	 * @throws InvalidInterfaceException
1586
+	 * @throws ReflectionException
1587
+	 */
1588
+	public function datetime_ticket()
1589
+	{
1590
+		return $this->get_first_related('Datetime_Ticket');
1591
+	}
1592
+
1593
+
1594
+	/**
1595
+	 * Sets the registration's datetime_ticket.
1596
+	 *
1597
+	 * @param EE_Datetime_Ticket $datetime_ticket
1598
+	 * @return EE_Base_Class|EE_Datetime_Ticket
1599
+	 * @throws EE_Error
1600
+	 * @throws InvalidArgumentException
1601
+	 * @throws InvalidDataTypeException
1602
+	 * @throws InvalidInterfaceException
1603
+	 * @throws ReflectionException
1604
+	 */
1605
+	public function set_datetime_ticket($datetime_ticket)
1606
+	{
1607
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1608
+	}
1609
+
1610
+
1611
+	/**
1612
+	 * Gets deleted
1613
+	 *
1614
+	 * @return bool
1615
+	 * @throws EE_Error
1616
+	 * @throws InvalidArgumentException
1617
+	 * @throws InvalidDataTypeException
1618
+	 * @throws InvalidInterfaceException
1619
+	 * @throws ReflectionException
1620
+	 */
1621
+	public function deleted()
1622
+	{
1623
+		return $this->get('REG_deleted');
1624
+	}
1625
+
1626
+
1627
+	/**
1628
+	 * Sets deleted
1629
+	 *
1630
+	 * @param boolean $deleted
1631
+	 * @return void
1632
+	 * @throws DomainException
1633
+	 * @throws EE_Error
1634
+	 * @throws EntityNotFoundException
1635
+	 * @throws InvalidArgumentException
1636
+	 * @throws InvalidDataTypeException
1637
+	 * @throws InvalidInterfaceException
1638
+	 * @throws ReflectionException
1639
+	 * @throws RuntimeException
1640
+	 * @throws UnexpectedEntityException
1641
+	 */
1642
+	public function set_deleted($deleted)
1643
+	{
1644
+		if ($deleted) {
1645
+			$this->delete(__METHOD__);
1646
+		} else {
1647
+			$this->restore(__METHOD__);
1648
+		}
1649
+	}
1650
+
1651
+
1652
+	/**
1653
+	 * Get the status object of this object
1654
+	 *
1655
+	 * @return EE_Base_Class|EE_Status
1656
+	 * @throws EE_Error
1657
+	 * @throws InvalidArgumentException
1658
+	 * @throws InvalidDataTypeException
1659
+	 * @throws InvalidInterfaceException
1660
+	 * @throws ReflectionException
1661
+	 */
1662
+	public function status_obj()
1663
+	{
1664
+		return $this->get_first_related('Status');
1665
+	}
1666
+
1667
+
1668
+	/**
1669
+	 * Returns the number of times this registration has checked into any of the datetimes
1670
+	 * its available for
1671
+	 *
1672
+	 * @return int
1673
+	 * @throws EE_Error
1674
+	 * @throws InvalidArgumentException
1675
+	 * @throws InvalidDataTypeException
1676
+	 * @throws InvalidInterfaceException
1677
+	 * @throws ReflectionException
1678
+	 */
1679
+	public function count_checkins()
1680
+	{
1681
+		return $this->get_model()->count_related($this, 'Checkin');
1682
+	}
1683
+
1684
+
1685
+	/**
1686
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1687
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1688
+	 *
1689
+	 * @return int
1690
+	 * @throws EE_Error
1691
+	 * @throws InvalidArgumentException
1692
+	 * @throws InvalidDataTypeException
1693
+	 * @throws InvalidInterfaceException
1694
+	 * @throws ReflectionException
1695
+	 */
1696
+	public function count_checkins_not_checkedout()
1697
+	{
1698
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1699
+	}
1700
+
1701
+
1702
+	/**
1703
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1704
+	 *
1705
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1706
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1707
+	 *                                          consider registration status as well as datetime access.
1708
+	 * @return bool
1709
+	 * @throws EE_Error
1710
+	 * @throws InvalidArgumentException
1711
+	 * @throws InvalidDataTypeException
1712
+	 * @throws InvalidInterfaceException
1713
+	 * @throws ReflectionException
1714
+	 */
1715
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1716
+	{
1717
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1718
+		// first check registration status
1719
+		if (! $DTT_ID || ($check_approved && ! $this->is_approved())) {
1720
+			return false;
1721
+		}
1722
+		// is there a datetime ticket that matches this dtt_ID?
1723
+		if (
1724
+			! (EEM_Datetime_Ticket::instance()->exists(
1725
+				array(
1726
+					array(
1727
+						'TKT_ID' => $this->get('TKT_ID'),
1728
+						'DTT_ID' => $DTT_ID,
1729
+					),
1730
+				)
1731
+			))
1732
+		) {
1733
+			return false;
1734
+		}
1735
+
1736
+		// final check is against TKT_uses
1737
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1743
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1744
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1745
+	 * then return false.  Otherwise return true.
1746
+	 *
1747
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1748
+	 * @return bool true means can checkin.  false means cannot checkin.
1749
+	 * @throws EE_Error
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws ReflectionException
1754
+	 */
1755
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1756
+	{
1757
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1758
+
1759
+		if (! $DTT_ID) {
1760
+			return false;
1761
+		}
1762
+
1763
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1764
+
1765
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1766
+		// check-in or not.
1767
+		if (! $max_uses || $max_uses === EE_INF) {
1768
+			return true;
1769
+		}
1770
+
1771
+		// does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1772
+		// go ahead and toggle.
1773
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1774
+			return true;
1775
+		}
1776
+
1777
+		// made it here so the last check is whether the number of checkins per unique datetime on this registration
1778
+		// disallows further check-ins.
1779
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1780
+			array(
1781
+				array(
1782
+					'REG_ID' => $this->ID(),
1783
+					'CHK_in' => true,
1784
+				),
1785
+			),
1786
+			'DTT_ID',
1787
+			true
1788
+		);
1789
+		// checkins have already reached their max number of uses
1790
+		// so registrant can NOT checkin
1791
+		if ($count_unique_dtt_checkins >= $max_uses) {
1792
+			EE_Error::add_error(
1793
+				esc_html__(
1794
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1795
+					'event_espresso'
1796
+				),
1797
+				__FILE__,
1798
+				__FUNCTION__,
1799
+				__LINE__
1800
+			);
1801
+			return false;
1802
+		}
1803
+		return true;
1804
+	}
1805
+
1806
+
1807
+	/**
1808
+	 * toggle Check-in status for this registration
1809
+	 * Check-ins are toggled in the following order:
1810
+	 * never checked in -> checked in
1811
+	 * checked in -> checked out
1812
+	 * checked out -> checked in
1813
+	 *
1814
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1815
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1816
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1817
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1818
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1819
+	 * @throws EE_Error
1820
+	 * @throws InvalidArgumentException
1821
+	 * @throws InvalidDataTypeException
1822
+	 * @throws InvalidInterfaceException
1823
+	 * @throws ReflectionException
1824
+	 */
1825
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1826
+	{
1827
+		if (empty($DTT_ID)) {
1828
+			$datetime = $this->get_latest_related_datetime();
1829
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1830
+			// verify the registration can checkin for the given DTT_ID
1831
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1832
+			EE_Error::add_error(
1833
+				sprintf(
1834
+					esc_html__(
1835
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1836
+						'event_espresso'
1837
+					),
1838
+					$this->ID(),
1839
+					$DTT_ID
1840
+				),
1841
+				__FILE__,
1842
+				__FUNCTION__,
1843
+				__LINE__
1844
+			);
1845
+			return false;
1846
+		}
1847
+		$status_paths = array(
1848
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1849
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1850
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1851
+		);
1852
+		// start by getting the current status so we know what status we'll be changing to.
1853
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1854
+		$status_to = $status_paths[ $cur_status ];
1855
+		// database only records true for checked IN or false for checked OUT
1856
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1857
+		$new_status = $status_to === EE_Checkin::status_checked_in;
1858
+		// add relation - note Check-ins are always creating new rows
1859
+		// because we are keeping track of Check-ins over time.
1860
+		// Eventually we'll probably want to show a list table
1861
+		// for the individual Check-ins so that they can be managed.
1862
+		$checkin = EE_Checkin::new_instance(
1863
+			array(
1864
+				'REG_ID' => $this->ID(),
1865
+				'DTT_ID' => $DTT_ID,
1866
+				'CHK_in' => $new_status,
1867
+			)
1868
+		);
1869
+		// if the record could not be saved then return false
1870
+		if ($checkin->save() === 0) {
1871
+			if (WP_DEBUG) {
1872
+				global $wpdb;
1873
+				$error = sprintf(
1874
+					esc_html__(
1875
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1876
+						'event_espresso'
1877
+					),
1878
+					'<br />',
1879
+					$wpdb->last_error
1880
+				);
1881
+			} else {
1882
+				$error = esc_html__(
1883
+					'Registration check in update failed because of an unknown database error',
1884
+					'event_espresso'
1885
+				);
1886
+			}
1887
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1888
+			return false;
1889
+		}
1890
+		// Fire a checked_in and checkout_out action.
1891
+		$checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1892
+		do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1893
+		return $status_to;
1894
+	}
1895
+
1896
+
1897
+	/**
1898
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1899
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1900
+	 *
1901
+	 * @return EE_Datetime|null
1902
+	 * @throws EE_Error
1903
+	 * @throws InvalidArgumentException
1904
+	 * @throws InvalidDataTypeException
1905
+	 * @throws InvalidInterfaceException
1906
+	 * @throws ReflectionException
1907
+	 */
1908
+	public function get_latest_related_datetime()
1909
+	{
1910
+		return EEM_Datetime::instance()->get_one(
1911
+			array(
1912
+				array(
1913
+					'Ticket.Registration.REG_ID' => $this->ID(),
1914
+				),
1915
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1916
+			)
1917
+		);
1918
+	}
1919
+
1920
+
1921
+	/**
1922
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1923
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1924
+	 *
1925
+	 * @return EE_Base_Class|EE_Soft_Delete_Base_Class|NULL
1926
+	 * @throws EE_Error
1927
+	 * @throws InvalidArgumentException
1928
+	 * @throws InvalidDataTypeException
1929
+	 * @throws InvalidInterfaceException
1930
+	 * @throws ReflectionException
1931
+	 */
1932
+	public function get_earliest_related_datetime()
1933
+	{
1934
+		return EEM_Datetime::instance()->get_one(
1935
+			array(
1936
+				array(
1937
+					'Ticket.Registration.REG_ID' => $this->ID(),
1938
+				),
1939
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1940
+			)
1941
+		);
1942
+	}
1943
+
1944
+
1945
+	/**
1946
+	 * This method simply returns the check-in status for this registration and the given datetime.
1947
+	 * If neither the datetime nor the checkin values are provided as arguments,
1948
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1949
+	 *
1950
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1951
+	 *                            (if empty we'll get the primary datetime for
1952
+	 *                            this registration (via event) and use it's ID);
1953
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1954
+	 * @return int                Integer representing Check-in status.
1955
+	 * @throws EE_Error
1956
+	 * @throws InvalidArgumentException
1957
+	 * @throws InvalidDataTypeException
1958
+	 * @throws InvalidInterfaceException
1959
+	 * @throws ReflectionException
1960
+	 */
1961
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1962
+	{
1963
+		$checkin_query_params = array(
1964
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1965
+		);
1966
+
1967
+		if ($DTT_ID > 0) {
1968
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1969
+		}
1970
+
1971
+		// get checkin object (if exists)
1972
+		$checkin = $checkin instanceof EE_Checkin
1973
+			? $checkin
1974
+			: $this->get_first_related('Checkin', $checkin_query_params);
1975
+		if ($checkin instanceof EE_Checkin) {
1976
+			if ($checkin->get('CHK_in')) {
1977
+				return EE_Checkin::status_checked_in; // checked in
1978
+			}
1979
+			return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1980
+		}
1981
+		return EE_Checkin::status_checked_never; // never been checked in
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * This method returns a localized message for the toggled Check-in message.
1987
+	 *
1988
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1989
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1990
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1991
+	 *                     message can be customized with the attendee name.
1992
+	 * @return string internationalized message
1993
+	 * @throws EE_Error
1994
+	 * @throws InvalidArgumentException
1995
+	 * @throws InvalidDataTypeException
1996
+	 * @throws InvalidInterfaceException
1997
+	 * @throws ReflectionException
1998
+	 */
1999
+	public function get_checkin_msg($DTT_ID, $error = false)
2000
+	{
2001
+		// let's get the attendee first so we can include the name of the attendee
2002
+		$attendee = $this->get_first_related('Attendee');
2003
+		if ($attendee instanceof EE_Attendee) {
2004
+			if ($error) {
2005
+				return sprintf(
2006
+					esc_html__("%s's check-in status was not changed.", "event_espresso"),
2007
+					$attendee->full_name()
2008
+				);
2009
+			}
2010
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
2011
+			// what is the status message going to be?
2012
+			switch ($cur_status) {
2013
+				case EE_Checkin::status_checked_never:
2014
+					return sprintf(
2015
+						esc_html__('%s has been removed from Check-in records', 'event_espresso'),
2016
+						$attendee->full_name()
2017
+					);
2018
+					break;
2019
+				case EE_Checkin::status_checked_in:
2020
+					return sprintf(esc_html__('%s has been checked in', 'event_espresso'), $attendee->full_name());
2021
+					break;
2022
+				case EE_Checkin::status_checked_out:
2023
+					return sprintf(esc_html__('%s has been checked out', 'event_espresso'), $attendee->full_name());
2024
+					break;
2025
+			}
2026
+		}
2027
+		return esc_html__('The check-in status could not be determined.', 'event_espresso');
2028
+	}
2029
+
2030
+
2031
+	/**
2032
+	 * Returns the related EE_Transaction to this registration
2033
+	 *
2034
+	 * @return EE_Transaction
2035
+	 * @throws EE_Error
2036
+	 * @throws EntityNotFoundException
2037
+	 * @throws InvalidArgumentException
2038
+	 * @throws InvalidDataTypeException
2039
+	 * @throws InvalidInterfaceException
2040
+	 * @throws ReflectionException
2041
+	 */
2042
+	public function transaction()
2043
+	{
2044
+		$transaction = $this->get_first_related('Transaction');
2045
+		if (! $transaction instanceof \EE_Transaction) {
2046
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
2047
+		}
2048
+		return $transaction;
2049
+	}
2050
+
2051
+
2052
+	/**
2053
+	 * get Registration Code
2054
+	 *
2055
+	 * @return mixed
2056
+	 * @throws EE_Error
2057
+	 * @throws InvalidArgumentException
2058
+	 * @throws InvalidDataTypeException
2059
+	 * @throws InvalidInterfaceException
2060
+	 * @throws ReflectionException
2061
+	 */
2062
+	public function reg_code()
2063
+	{
2064
+		return $this->get('REG_code');
2065
+	}
2066
+
2067
+
2068
+	/**
2069
+	 * @return mixed
2070
+	 * @throws EE_Error
2071
+	 * @throws InvalidArgumentException
2072
+	 * @throws InvalidDataTypeException
2073
+	 * @throws InvalidInterfaceException
2074
+	 * @throws ReflectionException
2075
+	 */
2076
+	public function transaction_ID()
2077
+	{
2078
+		return $this->get('TXN_ID');
2079
+	}
2080
+
2081
+
2082
+	/**
2083
+	 * @return int
2084
+	 * @throws EE_Error
2085
+	 * @throws InvalidArgumentException
2086
+	 * @throws InvalidDataTypeException
2087
+	 * @throws InvalidInterfaceException
2088
+	 * @throws ReflectionException
2089
+	 */
2090
+	public function ticket_ID()
2091
+	{
2092
+		return $this->get('TKT_ID');
2093
+	}
2094
+
2095
+
2096
+	/**
2097
+	 * Set Registration Code
2098
+	 *
2099
+	 * @param    string  $REG_code Registration Code
2100
+	 * @param    boolean $use_default
2101
+	 * @throws EE_Error
2102
+	 * @throws InvalidArgumentException
2103
+	 * @throws InvalidDataTypeException
2104
+	 * @throws InvalidInterfaceException
2105
+	 * @throws ReflectionException
2106
+	 */
2107
+	public function set_reg_code($REG_code, $use_default = false)
2108
+	{
2109
+		if (empty($REG_code)) {
2110
+			EE_Error::add_error(
2111
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
2112
+				__FILE__,
2113
+				__FUNCTION__,
2114
+				__LINE__
2115
+			);
2116
+			return;
2117
+		}
2118
+		if (! $this->reg_code()) {
2119
+			parent::set('REG_code', $REG_code, $use_default);
2120
+		} else {
2121
+			EE_Error::doing_it_wrong(
2122
+				__CLASS__ . '::' . __FUNCTION__,
2123
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
2124
+				'4.6.0'
2125
+			);
2126
+		}
2127
+	}
2128
+
2129
+
2130
+	/**
2131
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
2132
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
2133
+	 *    $registration->transaction()->registrations();
2134
+	 *
2135
+	 * @since 4.5.0
2136
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
2137
+	 * @throws EE_Error
2138
+	 * @throws InvalidArgumentException
2139
+	 * @throws InvalidDataTypeException
2140
+	 * @throws InvalidInterfaceException
2141
+	 * @throws ReflectionException
2142
+	 */
2143
+	public function get_all_other_registrations_in_group()
2144
+	{
2145
+		if ($this->group_size() < 2) {
2146
+			return array();
2147
+		}
2148
+
2149
+		$query[0] = array(
2150
+			'TXN_ID' => $this->transaction_ID(),
2151
+			'REG_ID' => array('!=', $this->ID()),
2152
+			'TKT_ID' => $this->ticket_ID(),
2153
+		);
2154
+		/** @var EE_Registration[] $registrations */
2155
+		$registrations = $this->get_model()->get_all($query);
2156
+		return $registrations;
2157
+	}
2158
+
2159
+
2160
+	/**
2161
+	 * Return the link to the admin details for the object.
2162
+	 *
2163
+	 * @return string
2164
+	 * @throws EE_Error
2165
+	 * @throws InvalidArgumentException
2166
+	 * @throws InvalidDataTypeException
2167
+	 * @throws InvalidInterfaceException
2168
+	 * @throws ReflectionException
2169
+	 */
2170
+	public function get_admin_details_link()
2171
+	{
2172
+		EE_Registry::instance()->load_helper('URL');
2173
+		return EEH_URL::add_query_args_and_nonce(
2174
+			array(
2175
+				'page'    => 'espresso_registrations',
2176
+				'action'  => 'view_registration',
2177
+				'_REG_ID' => $this->ID(),
2178
+			),
2179
+			admin_url('admin.php')
2180
+		);
2181
+	}
2182
+
2183
+
2184
+	/**
2185
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
2186
+	 *
2187
+	 * @return string
2188
+	 * @throws EE_Error
2189
+	 * @throws InvalidArgumentException
2190
+	 * @throws InvalidDataTypeException
2191
+	 * @throws InvalidInterfaceException
2192
+	 * @throws ReflectionException
2193
+	 */
2194
+	public function get_admin_edit_link()
2195
+	{
2196
+		return $this->get_admin_details_link();
2197
+	}
2198
+
2199
+
2200
+	/**
2201
+	 * Returns the link to a settings page for the object.
2202
+	 *
2203
+	 * @return string
2204
+	 * @throws EE_Error
2205
+	 * @throws InvalidArgumentException
2206
+	 * @throws InvalidDataTypeException
2207
+	 * @throws InvalidInterfaceException
2208
+	 * @throws ReflectionException
2209
+	 */
2210
+	public function get_admin_settings_link()
2211
+	{
2212
+		return $this->get_admin_details_link();
2213
+	}
2214
+
2215
+
2216
+	/**
2217
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
2218
+	 *
2219
+	 * @return string
2220
+	 * @throws EE_Error
2221
+	 * @throws InvalidArgumentException
2222
+	 * @throws InvalidDataTypeException
2223
+	 * @throws InvalidInterfaceException
2224
+	 * @throws ReflectionException
2225
+	 */
2226
+	public function get_admin_overview_link()
2227
+	{
2228
+		EE_Registry::instance()->load_helper('URL');
2229
+		return EEH_URL::add_query_args_and_nonce(
2230
+			array(
2231
+				'page' => 'espresso_registrations',
2232
+			),
2233
+			admin_url('admin.php')
2234
+		);
2235
+	}
2236
+
2237
+
2238
+	/**
2239
+	 * @param array $query_params
2240
+	 * @return EE_Base_Class[]|EE_Registration[]
2241
+	 * @throws EE_Error
2242
+	 * @throws InvalidArgumentException
2243
+	 * @throws InvalidDataTypeException
2244
+	 * @throws InvalidInterfaceException
2245
+	 * @throws ReflectionException
2246
+	 */
2247
+	public function payments($query_params = array())
2248
+	{
2249
+		return $this->get_many_related('Payment', $query_params);
2250
+	}
2251
+
2252
+
2253
+	/**
2254
+	 * @param array $query_params
2255
+	 * @return EE_Base_Class[]|EE_Registration_Payment[]
2256
+	 * @throws EE_Error
2257
+	 * @throws InvalidArgumentException
2258
+	 * @throws InvalidDataTypeException
2259
+	 * @throws InvalidInterfaceException
2260
+	 * @throws ReflectionException
2261
+	 */
2262
+	public function registration_payments($query_params = array())
2263
+	{
2264
+		return $this->get_many_related('Registration_Payment', $query_params);
2265
+	}
2266
+
2267
+
2268
+	/**
2269
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
2270
+	 * Note: if there are no payments on the registration there will be no payment method returned.
2271
+	 *
2272
+	 * @return EE_Payment|EE_Payment_Method|null
2273
+	 * @throws EE_Error
2274
+	 * @throws InvalidArgumentException
2275
+	 * @throws InvalidDataTypeException
2276
+	 * @throws InvalidInterfaceException
2277
+	 */
2278
+	public function payment_method()
2279
+	{
2280
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
2281
+	}
2282
+
2283
+
2284
+	/**
2285
+	 * @return \EE_Line_Item
2286
+	 * @throws EE_Error
2287
+	 * @throws EntityNotFoundException
2288
+	 * @throws InvalidArgumentException
2289
+	 * @throws InvalidDataTypeException
2290
+	 * @throws InvalidInterfaceException
2291
+	 * @throws ReflectionException
2292
+	 */
2293
+	public function ticket_line_item()
2294
+	{
2295
+		$ticket = $this->ticket();
2296
+		$transaction = $this->transaction();
2297
+		$line_item = null;
2298
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
2299
+			$transaction->total_line_item(),
2300
+			'Ticket',
2301
+			array($ticket->ID())
2302
+		);
2303
+		foreach ($ticket_line_items as $ticket_line_item) {
2304
+			if (
2305
+				$ticket_line_item instanceof \EE_Line_Item
2306
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
2307
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
2308
+			) {
2309
+				$line_item = $ticket_line_item;
2310
+				break;
2311
+			}
2312
+		}
2313
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
2314
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
2315
+		}
2316
+		return $line_item;
2317
+	}
2318
+
2319
+
2320
+	/**
2321
+	 * Soft Deletes this model object.
2322
+	 *
2323
+	 * @param string $source function name that called this method
2324
+	 * @return boolean | int
2325
+	 * @throws DomainException
2326
+	 * @throws EE_Error
2327
+	 * @throws EntityNotFoundException
2328
+	 * @throws InvalidArgumentException
2329
+	 * @throws InvalidDataTypeException
2330
+	 * @throws InvalidInterfaceException
2331
+	 * @throws ReflectionException
2332
+	 * @throws RuntimeException
2333
+	 * @throws UnexpectedEntityException
2334
+	 */
2335
+	public function delete($source = 'unknown')
2336
+	{
2337
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
2338
+			$current_user = wp_get_current_user();
2339
+			$this->add_extra_meta(
2340
+				EE_Registration::EXTRA_META_KEY_REG_TRASHED,
2341
+				array(
2342
+					'trashed-by' => $current_user->ID ? $current_user->display_name : 'unauthed user',
2343
+					'timestamp'  => time(),
2344
+					'source'     => $source,
2345
+				)
2346
+			);
2347
+			$this->set_status(EEM_Registration::status_id_cancelled);
2348
+		}
2349
+		return parent::delete();
2350
+	}
2351
+
2352
+
2353
+	/**
2354
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
2355
+	 *
2356
+	 * @param string $source function name that called this method
2357
+	 * @return bool|int
2358
+	 * @throws DomainException
2359
+	 * @throws EE_Error
2360
+	 * @throws EntityNotFoundException
2361
+	 * @throws InvalidArgumentException
2362
+	 * @throws InvalidDataTypeException
2363
+	 * @throws InvalidInterfaceException
2364
+	 * @throws ReflectionException
2365
+	 * @throws RuntimeException
2366
+	 * @throws UnexpectedEntityException
2367
+	 */
2368
+	public function restore($source = 'unknown')
2369
+	{
2370
+		$previous_status = $this->get_extra_meta(
2371
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
2372
+			true,
2373
+			EEM_Registration::status_id_cancelled
2374
+		);
2375
+		if ($previous_status) {
2376
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
2377
+			$this->set_status($previous_status);
2378
+		}
2379
+		$current_user = wp_get_current_user();
2380
+		$this->add_extra_meta(
2381
+			EE_Registration::EXTRA_META_KEY_REG_RESTORED,
2382
+			array(
2383
+				'restored-by' => $current_user->ID ? $current_user->display_name : 'unauthed user',
2384
+				'timestamp'   => time(),
2385
+				'source'      => $source,
2386
+			)
2387
+		);
2388
+		return parent::restore();
2389
+	}
2390
+
2391
+
2392
+	/**
2393
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
2394
+	 *
2395
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
2396
+	 *                                           depending on whether the reg status changes to or from "Approved"
2397
+	 * @return boolean whether the Registration status was updated
2398
+	 * @throws DomainException
2399
+	 * @throws EE_Error
2400
+	 * @throws EntityNotFoundException
2401
+	 * @throws InvalidArgumentException
2402
+	 * @throws InvalidDataTypeException
2403
+	 * @throws InvalidInterfaceException
2404
+	 * @throws ReflectionException
2405
+	 * @throws RuntimeException
2406
+	 * @throws UnexpectedEntityException
2407
+	 */
2408
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
2409
+	{
2410
+		$paid = $this->paid();
2411
+		$price = $this->final_price();
2412
+		switch (true) {
2413
+			// overpaid or paid
2414
+			case EEH_Money::compare_floats($paid, $price, '>'):
2415
+			case EEH_Money::compare_floats($paid, $price):
2416
+				$new_status = EEM_Registration::status_id_approved;
2417
+				break;
2418
+			//  underpaid
2419
+			case EEH_Money::compare_floats($paid, $price, '<'):
2420
+				$new_status = EEM_Registration::status_id_pending_payment;
2421
+				break;
2422
+			// uhhh Houston...
2423
+			default:
2424
+				throw new RuntimeException(
2425
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2426
+				);
2427
+		}
2428
+		if ($new_status !== $this->status_ID()) {
2429
+			if ($trigger_set_status_logic) {
2430
+				return $this->set_status($new_status);
2431
+			}
2432
+			parent::set('STS_ID', $new_status);
2433
+			return true;
2434
+		}
2435
+		return false;
2436
+	}
2437
+
2438
+
2439
+	/*************************** DEPRECATED ***************************/
2440
+
2441
+
2442
+	/**
2443
+	 * @deprecated
2444
+	 * @since     4.7.0
2445
+	 */
2446
+	public function price_paid()
2447
+	{
2448
+		EE_Error::doing_it_wrong(
2449
+			'EE_Registration::price_paid()',
2450
+			esc_html__(
2451
+				'This method is deprecated, please use EE_Registration::final_price() instead.',
2452
+				'event_espresso'
2453
+			),
2454
+			'4.7.0'
2455
+		);
2456
+		return $this->final_price();
2457
+	}
2458
+
2459
+
2460
+	/**
2461
+	 * @deprecated
2462
+	 * @since     4.7.0
2463
+	 * @param    float $REG_final_price
2464
+	 * @throws EE_Error
2465
+	 * @throws EntityNotFoundException
2466
+	 * @throws InvalidArgumentException
2467
+	 * @throws InvalidDataTypeException
2468
+	 * @throws InvalidInterfaceException
2469
+	 * @throws ReflectionException
2470
+	 * @throws RuntimeException
2471
+	 * @throws DomainException
2472
+	 */
2473
+	public function set_price_paid($REG_final_price = 0.00)
2474
+	{
2475
+		EE_Error::doing_it_wrong(
2476
+			'EE_Registration::set_price_paid()',
2477
+			esc_html__(
2478
+				'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2479
+				'event_espresso'
2480
+			),
2481
+			'4.7.0'
2482
+		);
2483
+		$this->set_final_price($REG_final_price);
2484
+	}
2485
+
2486
+
2487
+	/**
2488
+	 * @deprecated
2489
+	 * @since 4.7.0
2490
+	 * @return string
2491
+	 * @throws EE_Error
2492
+	 * @throws InvalidArgumentException
2493
+	 * @throws InvalidDataTypeException
2494
+	 * @throws InvalidInterfaceException
2495
+	 * @throws ReflectionException
2496
+	 */
2497
+	public function pretty_price_paid()
2498
+	{
2499
+		EE_Error::doing_it_wrong(
2500
+			'EE_Registration::pretty_price_paid()',
2501
+			esc_html__(
2502
+				'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2503
+				'event_espresso'
2504
+			),
2505
+			'4.7.0'
2506
+		);
2507
+		return $this->pretty_final_price();
2508
+	}
2509
+
2510
+
2511
+	/**
2512
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2513
+	 *
2514
+	 * @deprecated 4.9.17
2515
+	 * @return EE_Datetime
2516
+	 * @throws EE_Error
2517
+	 * @throws EntityNotFoundException
2518
+	 * @throws InvalidArgumentException
2519
+	 * @throws InvalidDataTypeException
2520
+	 * @throws InvalidInterfaceException
2521
+	 * @throws ReflectionException
2522
+	 */
2523
+	public function get_related_primary_datetime()
2524
+	{
2525
+		EE_Error::doing_it_wrong(
2526
+			__METHOD__,
2527
+			esc_html__(
2528
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2529
+				'event_espresso'
2530
+			),
2531
+			'4.9.17',
2532
+			'5.0.0'
2533
+		);
2534
+		return $this->event()->primary_datetime();
2535
+	}
2536
+
2537
+	/**
2538
+	 * Returns the contact's name (or "Unknown" if there is no contact.)
2539
+	 * @since 4.10.12.p
2540
+	 * @return string
2541
+	 * @throws EE_Error
2542
+	 * @throws InvalidArgumentException
2543
+	 * @throws InvalidDataTypeException
2544
+	 * @throws InvalidInterfaceException
2545
+	 * @throws ReflectionException
2546
+	 */
2547
+	public function name()
2548
+	{
2549
+		return $this->attendeeName();
2550
+	}
2551 2551
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
     {
149 149
         switch ($field_name) {
150 150
             case 'REG_code':
151
-                if (! empty($field_value) && $this->reg_code() === null) {
151
+                if ( ! empty($field_value) && $this->reg_code() === null) {
152 152
                     $this->set_reg_code($field_value, $use_default);
153 153
                 }
154 154
                 break;
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
     public function event()
450 450
     {
451 451
         $event = $this->get_first_related('Event');
452
-        if (! $event instanceof \EE_Event) {
452
+        if ( ! $event instanceof \EE_Event) {
453 453
             throw new EntityNotFoundException('Event ID', $this->event_ID());
454 454
         }
455 455
         return $event;
@@ -496,7 +496,7 @@  discard block
 block discarded – undo
496 496
     {
497 497
         // reserved ticket and datetime counts will be decremented as sold counts are incremented
498 498
         // so stop tracking that this reg has a ticket reserved
499
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
499
+        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:".__LINE__.')');
500 500
         $ticket = $this->ticket();
501 501
         $ticket->increaseSold();
502 502
         // possibly set event status to sold out
@@ -546,7 +546,7 @@  discard block
 block discarded – undo
546 546
             $reserved = $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
547 547
             if ($reserved && $update_ticket) {
548 548
                 $ticket = $this->ticket();
549
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
549
+                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:".__LINE__.')');
550 550
                 $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
551 551
                 $ticket->save();
552 552
             }
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
             $reserved = $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false);
575 575
             if ($reserved && $update_ticket) {
576 576
                 $ticket = $this->ticket();
577
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
577
+                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:".__LINE__.')');
578 578
                 $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
579 579
             }
580 580
         }
@@ -1460,7 +1460,7 @@  discard block
 block discarded – undo
1460 1460
                     : '';
1461 1461
                 break;
1462 1462
         }
1463
-        return $icon . $status[ $this->status_ID() ];
1463
+        return $icon.$status[$this->status_ID()];
1464 1464
     }
1465 1465
 
1466 1466
 
@@ -1716,7 +1716,7 @@  discard block
 block discarded – undo
1716 1716
     {
1717 1717
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1718 1718
         // first check registration status
1719
-        if (! $DTT_ID || ($check_approved && ! $this->is_approved())) {
1719
+        if ( ! $DTT_ID || ($check_approved && ! $this->is_approved())) {
1720 1720
             return false;
1721 1721
         }
1722 1722
         // is there a datetime ticket that matches this dtt_ID?
@@ -1756,7 +1756,7 @@  discard block
 block discarded – undo
1756 1756
     {
1757 1757
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1758 1758
 
1759
-        if (! $DTT_ID) {
1759
+        if ( ! $DTT_ID) {
1760 1760
             return false;
1761 1761
         }
1762 1762
 
@@ -1764,7 +1764,7 @@  discard block
 block discarded – undo
1764 1764
 
1765 1765
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1766 1766
         // check-in or not.
1767
-        if (! $max_uses || $max_uses === EE_INF) {
1767
+        if ( ! $max_uses || $max_uses === EE_INF) {
1768 1768
             return true;
1769 1769
         }
1770 1770
 
@@ -1828,7 +1828,7 @@  discard block
 block discarded – undo
1828 1828
             $datetime = $this->get_latest_related_datetime();
1829 1829
             $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1830 1830
             // verify the registration can checkin for the given DTT_ID
1831
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1831
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1832 1832
             EE_Error::add_error(
1833 1833
                 sprintf(
1834 1834
                     esc_html__(
@@ -1851,7 +1851,7 @@  discard block
 block discarded – undo
1851 1851
         );
1852 1852
         // start by getting the current status so we know what status we'll be changing to.
1853 1853
         $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1854
-        $status_to = $status_paths[ $cur_status ];
1854
+        $status_to = $status_paths[$cur_status];
1855 1855
         // database only records true for checked IN or false for checked OUT
1856 1856
         // no record ( null ) means checked in NEVER, but we obviously don't save that
1857 1857
         $new_status = $status_to === EE_Checkin::status_checked_in;
@@ -2042,7 +2042,7 @@  discard block
 block discarded – undo
2042 2042
     public function transaction()
2043 2043
     {
2044 2044
         $transaction = $this->get_first_related('Transaction');
2045
-        if (! $transaction instanceof \EE_Transaction) {
2045
+        if ( ! $transaction instanceof \EE_Transaction) {
2046 2046
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
2047 2047
         }
2048 2048
         return $transaction;
@@ -2115,11 +2115,11 @@  discard block
 block discarded – undo
2115 2115
             );
2116 2116
             return;
2117 2117
         }
2118
-        if (! $this->reg_code()) {
2118
+        if ( ! $this->reg_code()) {
2119 2119
             parent::set('REG_code', $REG_code, $use_default);
2120 2120
         } else {
2121 2121
             EE_Error::doing_it_wrong(
2122
-                __CLASS__ . '::' . __FUNCTION__,
2122
+                __CLASS__.'::'.__FUNCTION__,
2123 2123
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
2124 2124
                 '4.6.0'
2125 2125
             );
@@ -2310,7 +2310,7 @@  discard block
 block discarded – undo
2310 2310
                 break;
2311 2311
             }
2312 2312
         }
2313
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
2313
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
2314 2314
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
2315 2315
         }
2316 2316
         return $line_item;
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 1 patch
Indentation   +3686 added lines, -3686 removed lines patch added patch discarded remove patch
@@ -22,2225 +22,2225 @@  discard block
 block discarded – undo
22 22
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
23 23
 {
24 24
 
25
-    /**
26
-     * @var EE_Registration
27
-     */
28
-    private $_registration;
29
-
30
-    /**
31
-     * @var EE_Event
32
-     */
33
-    private $_reg_event;
34
-
35
-    /**
36
-     * @var EE_Session
37
-     */
38
-    private $_session;
39
-
40
-    /**
41
-     * @var array
42
-     */
43
-    private static $_reg_status;
44
-
45
-    /**
46
-     * Form for displaying the custom questions for this registration.
47
-     * This gets used a few times throughout the request so its best to cache it
48
-     *
49
-     * @var EE_Registration_Custom_Questions_Form
50
-     */
51
-    protected $_reg_custom_questions_form = null;
52
-
53
-    /**
54
-     * @var EEM_Registration $registration_model
55
-     */
56
-    private $registration_model;
57
-
58
-    /**
59
-     * @var EEM_Attendee $attendee_model
60
-     */
61
-    private $attendee_model;
62
-
63
-    /**
64
-     * @var EEM_Event $event_model
65
-     */
66
-    private $event_model;
67
-
68
-    /**
69
-     * @var EEM_Status $status_model
70
-     */
71
-    private $status_model;
72
-
73
-
74
-    /**
75
-     * @param bool $routing
76
-     * @throws EE_Error
77
-     * @throws InvalidArgumentException
78
-     * @throws InvalidDataTypeException
79
-     * @throws InvalidInterfaceException
80
-     * @throws ReflectionException
81
-     */
82
-    public function __construct($routing = true)
83
-    {
84
-        parent::__construct($routing);
85
-        add_action('wp_loaded', [$this, 'wp_loaded']);
86
-    }
87
-
88
-
89
-    /**
90
-     * @return EEM_Registration
91
-     * @throws InvalidArgumentException
92
-     * @throws InvalidDataTypeException
93
-     * @throws InvalidInterfaceException
94
-     * @since 4.10.2.p
95
-     */
96
-    protected function getRegistrationModel()
97
-    {
98
-        if (! $this->registration_model instanceof EEM_Registration) {
99
-            $this->registration_model = $this->getLoader()->getShared('EEM_Registration');
100
-        }
101
-        return $this->registration_model;
102
-    }
103
-
104
-
105
-    /**
106
-     * @return EEM_Attendee
107
-     * @throws InvalidArgumentException
108
-     * @throws InvalidDataTypeException
109
-     * @throws InvalidInterfaceException
110
-     * @since 4.10.2.p
111
-     */
112
-    protected function getAttendeeModel()
113
-    {
114
-        if (! $this->attendee_model instanceof EEM_Attendee) {
115
-            $this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
116
-        }
117
-        return $this->attendee_model;
118
-    }
119
-
120
-
121
-    /**
122
-     * @return EEM_Event
123
-     * @throws InvalidArgumentException
124
-     * @throws InvalidDataTypeException
125
-     * @throws InvalidInterfaceException
126
-     * @since 4.10.2.p
127
-     */
128
-    protected function getEventModel()
129
-    {
130
-        if (! $this->event_model instanceof EEM_Event) {
131
-            $this->event_model = $this->getLoader()->getShared('EEM_Event');
132
-        }
133
-        return $this->event_model;
134
-    }
135
-
136
-
137
-    /**
138
-     * @return EEM_Status
139
-     * @throws InvalidArgumentException
140
-     * @throws InvalidDataTypeException
141
-     * @throws InvalidInterfaceException
142
-     * @since 4.10.2.p
143
-     */
144
-    protected function getStatusModel()
145
-    {
146
-        if (! $this->status_model instanceof EEM_Status) {
147
-            $this->status_model = $this->getLoader()->getShared('EEM_Status');
148
-        }
149
-        return $this->status_model;
150
-    }
151
-
152
-
153
-    public function wp_loaded()
154
-    {
155
-        // when adding a new registration...
156
-        $action = $this->request->getRequestParam('action');
157
-        if ($action === 'new_registration') {
158
-            EE_System::do_not_cache();
159
-            if ($this->request->getRequestParam('processing_registration', 0, 'int') !== 1) {
160
-                // and it's NOT the attendee information reg step
161
-                // force cookie expiration by setting time to last week
162
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
163
-                // and update the global
164
-                $_COOKIE['ee_registration_added'] = 0;
165
-            }
166
-        }
167
-    }
168
-
169
-
170
-    protected function _init_page_props()
171
-    {
172
-        $this->page_slug        = REG_PG_SLUG;
173
-        $this->_admin_base_url  = REG_ADMIN_URL;
174
-        $this->_admin_base_path = REG_ADMIN;
175
-        $this->page_label       = esc_html__('Registrations', 'event_espresso');
176
-        $this->_cpt_routes      = [
177
-            'add_new_attendee' => 'espresso_attendees',
178
-            'edit_attendee'    => 'espresso_attendees',
179
-            'insert_attendee'  => 'espresso_attendees',
180
-            'update_attendee'  => 'espresso_attendees',
181
-        ];
182
-        $this->_cpt_model_names = [
183
-            'add_new_attendee' => 'EEM_Attendee',
184
-            'edit_attendee'    => 'EEM_Attendee',
185
-        ];
186
-        $this->_cpt_edit_routes = [
187
-            'espresso_attendees' => 'edit_attendee',
188
-        ];
189
-        $this->_pagenow_map     = [
190
-            'add_new_attendee' => 'post-new.php',
191
-            'edit_attendee'    => 'post.php',
192
-            'trash'            => 'post.php',
193
-        ];
194
-        add_action('edit_form_after_title', [$this, 'after_title_form_fields'], 10);
195
-        // add filters so that the comment urls don't take users to a confusing 404 page
196
-        add_filter('get_comment_link', [$this, 'clear_comment_link'], 10, 2);
197
-    }
198
-
199
-
200
-    /**
201
-     * @param string     $link    The comment permalink with '#comment-$id' appended.
202
-     * @param WP_Comment $comment The current comment object.
203
-     * @return string
204
-     */
205
-    public function clear_comment_link($link, WP_Comment $comment)
206
-    {
207
-        // gotta make sure this only happens on this route
208
-        $post_type = get_post_type($comment->comment_post_ID);
209
-        if ($post_type === 'espresso_attendees') {
210
-            return '#commentsdiv';
211
-        }
212
-        return $link;
213
-    }
214
-
215
-
216
-    protected function _ajax_hooks()
217
-    {
218
-        // todo: all hooks for registrations ajax goes in here
219
-        add_action('wp_ajax_toggle_checkin_status', [$this, 'toggle_checkin_status']);
220
-    }
221
-
222
-
223
-    protected function _define_page_props()
224
-    {
225
-        $this->_admin_page_title = $this->page_label;
226
-        $this->_labels           = [
227
-            'buttons'                      => [
228
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
229
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
230
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
231
-                'csv_reg_report'      => esc_html__('Registrations CSV Report', 'event_espresso'),
232
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
233
-                'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
234
-            ],
235
-            'publishbox'                   => [
236
-                'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
237
-                'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
238
-            ],
239
-            'hide_add_button_on_cpt_route' => [
240
-                'edit_attendee' => true,
241
-            ],
242
-        ];
243
-    }
244
-
245
-
246
-    /**
247
-     * grab url requests and route them
248
-     *
249
-     * @return void
250
-     * @throws EE_Error
251
-     */
252
-    public function _set_page_routes()
253
-    {
254
-        $this->_get_registration_status_array();
255
-        $REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
256
-        $REG_ID             = $this->request->getRequestParam('reg_status_change_form[REG_ID]', $REG_ID, 'int');
257
-        $ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
258
-        $ATT_ID             = $this->request->getRequestParam('post', $ATT_ID, 'int');
259
-        $this->_page_routes = [
260
-            'default'                             => [
261
-                'func'       => [$this, '_registrations_overview_list_table'],
262
-                'capability' => 'ee_read_registrations',
263
-            ],
264
-            'view_registration'                   => [
265
-                'func'       => '_registration_details',
266
-                'capability' => 'ee_read_registration',
267
-                'obj_id'     => $REG_ID,
268
-            ],
269
-            'edit_registration'                   => [
270
-                'func'               => '_update_attendee_registration_form',
271
-                'noheader'           => true,
272
-                'headers_sent_route' => 'view_registration',
273
-                'capability'         => 'ee_edit_registration',
274
-                'obj_id'             => $REG_ID,
275
-                '_REG_ID'            => $REG_ID,
276
-            ],
277
-            'trash_registrations'                 => [
278
-                'func'       => '_trash_or_restore_registrations',
279
-                'args'       => ['trash' => true],
280
-                'noheader'   => true,
281
-                'capability' => 'ee_delete_registrations',
282
-            ],
283
-            'restore_registrations'               => [
284
-                'func'       => '_trash_or_restore_registrations',
285
-                'args'       => ['trash' => false],
286
-                'noheader'   => true,
287
-                'capability' => 'ee_delete_registrations',
288
-            ],
289
-            'delete_registrations'                => [
290
-                'func'       => '_delete_registrations',
291
-                'noheader'   => true,
292
-                'capability' => 'ee_delete_registrations',
293
-            ],
294
-            'new_registration'                    => [
295
-                'func'       => 'new_registration',
296
-                'capability' => 'ee_edit_registrations',
297
-            ],
298
-            'process_reg_step'                    => [
299
-                'func'       => 'process_reg_step',
300
-                'noheader'   => true,
301
-                'capability' => 'ee_edit_registrations',
302
-            ],
303
-            'redirect_to_txn'                     => [
304
-                'func'       => 'redirect_to_txn',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registrations',
307
-            ],
308
-            'change_reg_status'                   => [
309
-                'func'       => '_change_reg_status',
310
-                'noheader'   => true,
311
-                'capability' => 'ee_edit_registration',
312
-                'obj_id'     => $REG_ID,
313
-            ],
314
-            'approve_registration'                => [
315
-                'func'       => 'approve_registration',
316
-                'noheader'   => true,
317
-                'capability' => 'ee_edit_registration',
318
-                'obj_id'     => $REG_ID,
319
-            ],
320
-            'approve_and_notify_registration'     => [
321
-                'func'       => 'approve_registration',
322
-                'noheader'   => true,
323
-                'args'       => [true],
324
-                'capability' => 'ee_edit_registration',
325
-                'obj_id'     => $REG_ID,
326
-            ],
327
-            'approve_registrations'               => [
328
-                'func'       => 'bulk_action_on_registrations',
329
-                'noheader'   => true,
330
-                'capability' => 'ee_edit_registrations',
331
-                'args'       => ['approve'],
332
-            ],
333
-            'approve_and_notify_registrations'    => [
334
-                'func'       => 'bulk_action_on_registrations',
335
-                'noheader'   => true,
336
-                'capability' => 'ee_edit_registrations',
337
-                'args'       => ['approve', true],
338
-            ],
339
-            'decline_registration'                => [
340
-                'func'       => 'decline_registration',
341
-                'noheader'   => true,
342
-                'capability' => 'ee_edit_registration',
343
-                'obj_id'     => $REG_ID,
344
-            ],
345
-            'decline_and_notify_registration'     => [
346
-                'func'       => 'decline_registration',
347
-                'noheader'   => true,
348
-                'args'       => [true],
349
-                'capability' => 'ee_edit_registration',
350
-                'obj_id'     => $REG_ID,
351
-            ],
352
-            'decline_registrations'               => [
353
-                'func'       => 'bulk_action_on_registrations',
354
-                'noheader'   => true,
355
-                'capability' => 'ee_edit_registrations',
356
-                'args'       => ['decline'],
357
-            ],
358
-            'decline_and_notify_registrations'    => [
359
-                'func'       => 'bulk_action_on_registrations',
360
-                'noheader'   => true,
361
-                'capability' => 'ee_edit_registrations',
362
-                'args'       => ['decline', true],
363
-            ],
364
-            'pending_registration'                => [
365
-                'func'       => 'pending_registration',
366
-                'noheader'   => true,
367
-                'capability' => 'ee_edit_registration',
368
-                'obj_id'     => $REG_ID,
369
-            ],
370
-            'pending_and_notify_registration'     => [
371
-                'func'       => 'pending_registration',
372
-                'noheader'   => true,
373
-                'args'       => [true],
374
-                'capability' => 'ee_edit_registration',
375
-                'obj_id'     => $REG_ID,
376
-            ],
377
-            'pending_registrations'               => [
378
-                'func'       => 'bulk_action_on_registrations',
379
-                'noheader'   => true,
380
-                'capability' => 'ee_edit_registrations',
381
-                'args'       => ['pending'],
382
-            ],
383
-            'pending_and_notify_registrations'    => [
384
-                'func'       => 'bulk_action_on_registrations',
385
-                'noheader'   => true,
386
-                'capability' => 'ee_edit_registrations',
387
-                'args'       => ['pending', true],
388
-            ],
389
-            'no_approve_registration'             => [
390
-                'func'       => 'not_approve_registration',
391
-                'noheader'   => true,
392
-                'capability' => 'ee_edit_registration',
393
-                'obj_id'     => $REG_ID,
394
-            ],
395
-            'no_approve_and_notify_registration'  => [
396
-                'func'       => 'not_approve_registration',
397
-                'noheader'   => true,
398
-                'args'       => [true],
399
-                'capability' => 'ee_edit_registration',
400
-                'obj_id'     => $REG_ID,
401
-            ],
402
-            'no_approve_registrations'            => [
403
-                'func'       => 'bulk_action_on_registrations',
404
-                'noheader'   => true,
405
-                'capability' => 'ee_edit_registrations',
406
-                'args'       => ['not_approve'],
407
-            ],
408
-            'no_approve_and_notify_registrations' => [
409
-                'func'       => 'bulk_action_on_registrations',
410
-                'noheader'   => true,
411
-                'capability' => 'ee_edit_registrations',
412
-                'args'       => ['not_approve', true],
413
-            ],
414
-            'cancel_registration'                 => [
415
-                'func'       => 'cancel_registration',
416
-                'noheader'   => true,
417
-                'capability' => 'ee_edit_registration',
418
-                'obj_id'     => $REG_ID,
419
-            ],
420
-            'cancel_and_notify_registration'      => [
421
-                'func'       => 'cancel_registration',
422
-                'noheader'   => true,
423
-                'args'       => [true],
424
-                'capability' => 'ee_edit_registration',
425
-                'obj_id'     => $REG_ID,
426
-            ],
427
-            'cancel_registrations'                => [
428
-                'func'       => 'bulk_action_on_registrations',
429
-                'noheader'   => true,
430
-                'capability' => 'ee_edit_registrations',
431
-                'args'       => ['cancel'],
432
-            ],
433
-            'cancel_and_notify_registrations'     => [
434
-                'func'       => 'bulk_action_on_registrations',
435
-                'noheader'   => true,
436
-                'capability' => 'ee_edit_registrations',
437
-                'args'       => ['cancel', true],
438
-            ],
439
-            'wait_list_registration'              => [
440
-                'func'       => 'wait_list_registration',
441
-                'noheader'   => true,
442
-                'capability' => 'ee_edit_registration',
443
-                'obj_id'     => $REG_ID,
444
-            ],
445
-            'wait_list_and_notify_registration'   => [
446
-                'func'       => 'wait_list_registration',
447
-                'noheader'   => true,
448
-                'args'       => [true],
449
-                'capability' => 'ee_edit_registration',
450
-                'obj_id'     => $REG_ID,
451
-            ],
452
-            'contact_list'                        => [
453
-                'func'       => '_attendee_contact_list_table',
454
-                'capability' => 'ee_read_contacts',
455
-            ],
456
-            'add_new_attendee'                    => [
457
-                'func' => '_create_new_cpt_item',
458
-                'args' => [
459
-                    'new_attendee' => true,
460
-                    'capability'   => 'ee_edit_contacts',
461
-                ],
462
-            ],
463
-            'edit_attendee'                       => [
464
-                'func'       => '_edit_cpt_item',
465
-                'capability' => 'ee_edit_contacts',
466
-                'obj_id'     => $ATT_ID,
467
-            ],
468
-            'duplicate_attendee'                  => [
469
-                'func'       => '_duplicate_attendee',
470
-                'noheader'   => true,
471
-                'capability' => 'ee_edit_contacts',
472
-                'obj_id'     => $ATT_ID,
473
-            ],
474
-            'insert_attendee'                     => [
475
-                'func'       => '_insert_or_update_attendee',
476
-                'args'       => [
477
-                    'new_attendee' => true,
478
-                ],
479
-                'noheader'   => true,
480
-                'capability' => 'ee_edit_contacts',
481
-            ],
482
-            'update_attendee'                     => [
483
-                'func'       => '_insert_or_update_attendee',
484
-                'args'       => [
485
-                    'new_attendee' => false,
486
-                ],
487
-                'noheader'   => true,
488
-                'capability' => 'ee_edit_contacts',
489
-                'obj_id'     => $ATT_ID,
490
-            ],
491
-            'trash_attendees'                     => [
492
-                'func'       => '_trash_or_restore_attendees',
493
-                'args'       => [
494
-                    'trash' => 'true',
495
-                ],
496
-                'noheader'   => true,
497
-                'capability' => 'ee_delete_contacts',
498
-            ],
499
-            'trash_attendee'                      => [
500
-                'func'       => '_trash_or_restore_attendees',
501
-                'args'       => [
502
-                    'trash' => true,
503
-                ],
504
-                'noheader'   => true,
505
-                'capability' => 'ee_delete_contacts',
506
-                'obj_id'     => $ATT_ID,
507
-            ],
508
-            'restore_attendees'                   => [
509
-                'func'       => '_trash_or_restore_attendees',
510
-                'args'       => [
511
-                    'trash' => false,
512
-                ],
513
-                'noheader'   => true,
514
-                'capability' => 'ee_delete_contacts',
515
-                'obj_id'     => $ATT_ID,
516
-            ],
517
-            'resend_registration'                 => [
518
-                'func'       => '_resend_registration',
519
-                'noheader'   => true,
520
-                'capability' => 'ee_send_message',
521
-            ],
522
-            'registrations_report'                => [
523
-                'func'       => [$this, '_registrations_report'],
524
-                'noheader'   => true,
525
-                'capability' => 'ee_read_registrations',
526
-            ],
527
-            'contact_list_export'                 => [
528
-                'func'       => '_contact_list_export',
529
-                'noheader'   => true,
530
-                'capability' => 'export',
531
-            ],
532
-            'contact_list_report'                 => [
533
-                'func'       => '_contact_list_report',
534
-                'noheader'   => true,
535
-                'capability' => 'ee_read_contacts',
536
-            ],
537
-        ];
538
-    }
539
-
540
-
541
-    protected function _set_page_config()
542
-    {
543
-        $REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
544
-        $ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
545
-        $this->_page_config = [
546
-            'default'           => [
547
-                'nav'           => [
548
-                    'label' => esc_html__('Overview', 'event_espresso'),
549
-                    'order' => 5,
550
-                ],
551
-                'help_tabs'     => [
552
-                    'registrations_overview_help_tab'                       => [
553
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
554
-                        'filename' => 'registrations_overview',
555
-                    ],
556
-                    'registrations_overview_table_column_headings_help_tab' => [
557
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
558
-                        'filename' => 'registrations_overview_table_column_headings',
559
-                    ],
560
-                    'registrations_overview_filters_help_tab'               => [
561
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
562
-                        'filename' => 'registrations_overview_filters',
563
-                    ],
564
-                    'registrations_overview_views_help_tab'                 => [
565
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
566
-                        'filename' => 'registrations_overview_views',
567
-                    ],
568
-                    'registrations_regoverview_other_help_tab'              => [
569
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
570
-                        'filename' => 'registrations_overview_other',
571
-                    ],
572
-                ],
573
-                'qtips'         => ['Registration_List_Table_Tips'],
574
-                'list_table'    => 'EE_Registrations_List_Table',
575
-                'require_nonce' => false,
576
-            ],
577
-            'view_registration' => [
578
-                'nav'           => [
579
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
580
-                    'order'      => 15,
581
-                    'url'        => $REG_ID
582
-                        ? add_query_arg(['_REG_ID' => $REG_ID], $this->_current_page_view_url)
583
-                        : $this->_admin_base_url,
584
-                    'persistent' => false,
585
-                ],
586
-                'help_tabs'     => [
587
-                    'registrations_details_help_tab'                    => [
588
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
589
-                        'filename' => 'registrations_details',
590
-                    ],
591
-                    'registrations_details_table_help_tab'              => [
592
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
593
-                        'filename' => 'registrations_details_table',
594
-                    ],
595
-                    'registrations_details_form_answers_help_tab'       => [
596
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
597
-                        'filename' => 'registrations_details_form_answers',
598
-                    ],
599
-                    'registrations_details_registrant_details_help_tab' => [
600
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
601
-                        'filename' => 'registrations_details_registrant_details',
602
-                    ],
603
-                ],
604
-                'metaboxes'     => array_merge(
605
-                    $this->_default_espresso_metaboxes,
606
-                    ['_registration_details_metaboxes']
607
-                ),
608
-                'require_nonce' => false,
609
-            ],
610
-            'new_registration'  => [
611
-                'nav'           => [
612
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
613
-                    'url'        => '#',
614
-                    'order'      => 15,
615
-                    'persistent' => false,
616
-                ],
617
-                'metaboxes'     => $this->_default_espresso_metaboxes,
618
-                'labels'        => [
619
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
620
-                ],
621
-                'require_nonce' => false,
622
-            ],
623
-            'add_new_attendee'  => [
624
-                'nav'           => [
625
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
626
-                    'order'      => 15,
627
-                    'persistent' => false,
628
-                ],
629
-                'metaboxes'     => array_merge(
630
-                    $this->_default_espresso_metaboxes,
631
-                    ['_publish_post_box', 'attendee_editor_metaboxes']
632
-                ),
633
-                'require_nonce' => false,
634
-            ],
635
-            'edit_attendee'     => [
636
-                'nav'           => [
637
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
638
-                    'order'      => 15,
639
-                    'persistent' => false,
640
-                    'url'        => $ATT_ID
641
-                        ? add_query_arg(['ATT_ID' => $ATT_ID], $this->_current_page_view_url)
642
-                        : $this->_admin_base_url,
643
-                ],
644
-                'metaboxes'     => ['attendee_editor_metaboxes'],
645
-                'require_nonce' => false,
646
-            ],
647
-            'contact_list'      => [
648
-                'nav'           => [
649
-                    'label' => esc_html__('Contact List', 'event_espresso'),
650
-                    'order' => 20,
651
-                ],
652
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
653
-                'help_tabs'     => [
654
-                    'registrations_contact_list_help_tab'                       => [
655
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
656
-                        'filename' => 'registrations_contact_list',
657
-                    ],
658
-                    'registrations_contact-list_table_column_headings_help_tab' => [
659
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
660
-                        'filename' => 'registrations_contact_list_table_column_headings',
661
-                    ],
662
-                    'registrations_contact_list_views_help_tab'                 => [
663
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
664
-                        'filename' => 'registrations_contact_list_views',
665
-                    ],
666
-                    'registrations_contact_list_other_help_tab'                 => [
667
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
668
-                        'filename' => 'registrations_contact_list_other',
669
-                    ],
670
-                ],
671
-                'metaboxes'     => [],
672
-                'require_nonce' => false,
673
-            ],
674
-            // override default cpt routes
675
-            'create_new'        => '',
676
-            'edit'              => '',
677
-        ];
678
-    }
679
-
680
-
681
-    /**
682
-     * The below methods aren't used by this class currently
683
-     */
684
-    protected function _add_screen_options()
685
-    {
686
-    }
687
-
688
-
689
-    protected function _add_feature_pointers()
690
-    {
691
-    }
692
-
693
-
694
-    public function admin_init()
695
-    {
696
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
697
-            'click "Update Registration Questions" to save your changes',
698
-            'event_espresso'
699
-        );
700
-    }
701
-
702
-
703
-    public function admin_notices()
704
-    {
705
-    }
706
-
707
-
708
-    public function admin_footer_scripts()
709
-    {
710
-    }
711
-
712
-
713
-    /**
714
-     * get list of registration statuses
715
-     *
716
-     * @return void
717
-     * @throws EE_Error
718
-     */
719
-    private function _get_registration_status_array()
720
-    {
721
-        self::$_reg_status = EEM_Registration::reg_status_array([], true);
722
-    }
723
-
724
-
725
-    /**
726
-     * @throws InvalidArgumentException
727
-     * @throws InvalidDataTypeException
728
-     * @throws InvalidInterfaceException
729
-     * @since 4.10.2.p
730
-     */
731
-    protected function _add_screen_options_default()
732
-    {
733
-        $this->_per_page_screen_option();
734
-    }
735
-
736
-
737
-    /**
738
-     * @throws InvalidArgumentException
739
-     * @throws InvalidDataTypeException
740
-     * @throws InvalidInterfaceException
741
-     * @since 4.10.2.p
742
-     */
743
-    protected function _add_screen_options_contact_list()
744
-    {
745
-        $page_title              = $this->_admin_page_title;
746
-        $this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
747
-        $this->_per_page_screen_option();
748
-        $this->_admin_page_title = $page_title;
749
-    }
750
-
751
-
752
-    public function load_scripts_styles()
753
-    {
754
-        // style
755
-        wp_register_style(
756
-            'espresso_reg',
757
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
758
-            ['ee-admin-css'],
759
-            EVENT_ESPRESSO_VERSION
760
-        );
761
-        wp_enqueue_style('espresso_reg');
762
-        // script
763
-        wp_register_script(
764
-            'espresso_reg',
765
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
766
-            ['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
767
-            EVENT_ESPRESSO_VERSION,
768
-            true
769
-        );
770
-        wp_enqueue_script('espresso_reg');
771
-    }
772
-
773
-
774
-    /**
775
-     * @throws EE_Error
776
-     * @throws InvalidArgumentException
777
-     * @throws InvalidDataTypeException
778
-     * @throws InvalidInterfaceException
779
-     * @throws ReflectionException
780
-     * @since 4.10.2.p
781
-     */
782
-    public function load_scripts_styles_edit_attendee()
783
-    {
784
-        // stuff to only show up on our attendee edit details page.
785
-        $attendee_details_translations = [
786
-            'att_publish_text' => sprintf(
787
-            /* translators: The date and time */
788
-                wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
789
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
790
-            ),
791
-        ];
792
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
793
-        wp_enqueue_script('jquery-validate');
794
-    }
795
-
796
-
797
-    /**
798
-     * @throws EE_Error
799
-     * @throws InvalidArgumentException
800
-     * @throws InvalidDataTypeException
801
-     * @throws InvalidInterfaceException
802
-     * @throws ReflectionException
803
-     * @since 4.10.2.p
804
-     */
805
-    public function load_scripts_styles_view_registration()
806
-    {
807
-        // styles
808
-        wp_enqueue_style('espresso-ui-theme');
809
-        // scripts
810
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
811
-        $this->_reg_custom_questions_form->wp_enqueue_scripts();
812
-    }
813
-
814
-
815
-    public function load_scripts_styles_contact_list()
816
-    {
817
-        wp_dequeue_style('espresso_reg');
818
-        wp_register_style(
819
-            'espresso_att',
820
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
821
-            ['ee-admin-css'],
822
-            EVENT_ESPRESSO_VERSION
823
-        );
824
-        wp_enqueue_style('espresso_att');
825
-    }
826
-
827
-
828
-    public function load_scripts_styles_new_registration()
829
-    {
830
-        wp_register_script(
831
-            'ee-spco-for-admin',
832
-            REG_ASSETS_URL . 'spco_for_admin.js',
833
-            ['underscore', 'jquery'],
834
-            EVENT_ESPRESSO_VERSION,
835
-            true
836
-        );
837
-        wp_enqueue_script('ee-spco-for-admin');
838
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
839
-        EE_Form_Section_Proper::wp_enqueue_scripts();
840
-        EED_Ticket_Selector::load_tckt_slctr_assets();
841
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
842
-    }
843
-
844
-
845
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
846
-    {
847
-        add_filter('FHEE_load_EE_messages', '__return_true');
848
-    }
849
-
850
-
851
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
852
-    {
853
-        add_filter('FHEE_load_EE_messages', '__return_true');
854
-    }
855
-
856
-
857
-    /**
858
-     * @throws EE_Error
859
-     * @throws InvalidArgumentException
860
-     * @throws InvalidDataTypeException
861
-     * @throws InvalidInterfaceException
862
-     * @throws ReflectionException
863
-     * @since 4.10.2.p
864
-     */
865
-    protected function _set_list_table_views_default()
866
-    {
867
-        // for notification related bulk actions we need to make sure only active messengers have an option.
868
-        EED_Messages::set_autoloaders();
869
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
870
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
871
-        $active_mts               = $message_resource_manager->list_of_active_message_types();
872
-        // key= bulk_action_slug, value= message type.
873
-        $match_array = [
874
-            'approve_registrations'    => 'registration',
875
-            'decline_registrations'    => 'declined_registration',
876
-            'pending_registrations'    => 'pending_approval',
877
-            'no_approve_registrations' => 'not_approved_registration',
878
-            'cancel_registrations'     => 'cancelled_registration',
879
-        ];
880
-        $can_send    = EE_Registry::instance()->CAP->current_user_can(
881
-            'ee_send_message',
882
-            'batch_send_messages'
883
-        );
884
-        /** setup reg status bulk actions **/
885
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
886
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
887
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
888
-                'Approve and Notify Registrations',
889
-                'event_espresso'
890
-            );
891
-        }
892
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
893
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
894
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
895
-                'Decline and Notify Registrations',
896
-                'event_espresso'
897
-            );
898
-        }
899
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
900
-            'Set Registrations to Pending Payment',
901
-            'event_espresso'
902
-        );
903
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
904
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
905
-                'Set Registrations to Pending Payment and Notify',
906
-                'event_espresso'
907
-            );
908
-        }
909
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
910
-            'Set Registrations to Not Approved',
911
-            'event_espresso'
912
-        );
913
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
914
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
915
-                'Set Registrations to Not Approved and Notify',
916
-                'event_espresso'
917
-            );
918
-        }
919
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
920
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
921
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
922
-                'Cancel Registrations and Notify',
923
-                'event_espresso'
924
-            );
925
-        }
926
-        $def_reg_status_actions = apply_filters(
927
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
928
-            $def_reg_status_actions,
929
-            $active_mts,
930
-            $can_send
931
-        );
932
-
933
-        $this->_views = [
934
-            'all'   => [
935
-                'slug'        => 'all',
936
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
937
-                'count'       => 0,
938
-                'bulk_action' => array_merge(
939
-                    $def_reg_status_actions,
940
-                    [
941
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
942
-                    ]
943
-                ),
944
-            ],
945
-            'month' => [
946
-                'slug'        => 'month',
947
-                'label'       => esc_html__('This Month', 'event_espresso'),
948
-                'count'       => 0,
949
-                'bulk_action' => array_merge(
950
-                    $def_reg_status_actions,
951
-                    [
952
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
953
-                    ]
954
-                ),
955
-            ],
956
-            'today' => [
957
-                'slug'        => 'today',
958
-                'label'       => sprintf(
959
-                    esc_html__('Today - %s', 'event_espresso'),
960
-                    date('M d, Y', current_time('timestamp'))
961
-                ),
962
-                'count'       => 0,
963
-                'bulk_action' => array_merge(
964
-                    $def_reg_status_actions,
965
-                    [
966
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
967
-                    ]
968
-                ),
969
-            ],
970
-        ];
971
-        if (
972
-            EE_Registry::instance()->CAP->current_user_can(
973
-                'ee_delete_registrations',
974
-                'espresso_registrations_delete_registration'
975
-            )
976
-        ) {
977
-            $this->_views['incomplete'] = [
978
-                'slug'        => 'incomplete',
979
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
980
-                'count'       => 0,
981
-                'bulk_action' => [
982
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
983
-                ],
984
-            ];
985
-            $this->_views['trash']      = [
986
-                'slug'        => 'trash',
987
-                'label'       => esc_html__('Trash', 'event_espresso'),
988
-                'count'       => 0,
989
-                'bulk_action' => [
990
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
991
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
992
-                ],
993
-            ];
994
-        }
995
-    }
996
-
997
-
998
-    protected function _set_list_table_views_contact_list()
999
-    {
1000
-        $this->_views = [
1001
-            'in_use' => [
1002
-                'slug'        => 'in_use',
1003
-                'label'       => esc_html__('In Use', 'event_espresso'),
1004
-                'count'       => 0,
1005
-                'bulk_action' => [
1006
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1007
-                ],
1008
-            ],
1009
-        ];
1010
-        if (
1011
-            EE_Registry::instance()->CAP->current_user_can(
1012
-                'ee_delete_contacts',
1013
-                'espresso_registrations_trash_attendees'
1014
-            )
1015
-        ) {
1016
-            $this->_views['trash'] = [
1017
-                'slug'        => 'trash',
1018
-                'label'       => esc_html__('Trash', 'event_espresso'),
1019
-                'count'       => 0,
1020
-                'bulk_action' => [
1021
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1022
-                ],
1023
-            ];
1024
-        }
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * @return array
1030
-     * @throws EE_Error
1031
-     */
1032
-    protected function _registration_legend_items()
1033
-    {
1034
-        $fc_items = [
1035
-            'star-icon'        => [
1036
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1037
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1038
-            ],
1039
-            'view_details'     => [
1040
-                'class' => 'dashicons dashicons-clipboard',
1041
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1042
-            ],
1043
-            'edit_attendee'    => [
1044
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
1045
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1046
-            ],
1047
-            'view_transaction' => [
1048
-                'class' => 'dashicons dashicons-cart',
1049
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1050
-            ],
1051
-            'view_invoice'     => [
1052
-                'class' => 'dashicons dashicons-media-spreadsheet',
1053
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1054
-            ],
1055
-        ];
1056
-        if (
1057
-            EE_Registry::instance()->CAP->current_user_can(
1058
-                'ee_send_message',
1059
-                'espresso_registrations_resend_registration'
1060
-            )
1061
-        ) {
1062
-            $fc_items['resend_registration'] = [
1063
-                'class' => 'dashicons dashicons-email-alt',
1064
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1065
-            ];
1066
-        } else {
1067
-            $fc_items['blank'] = ['class' => 'blank', 'desc' => ''];
1068
-        }
1069
-        if (
1070
-            EE_Registry::instance()->CAP->current_user_can(
1071
-                'ee_read_global_messages',
1072
-                'view_filtered_messages'
1073
-            )
1074
-        ) {
1075
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1076
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1077
-                $fc_items['view_related_messages'] = [
1078
-                    'class' => $related_for_icon['css_class'],
1079
-                    'desc'  => $related_for_icon['label'],
1080
-                ];
1081
-            }
1082
-        }
1083
-        $sc_items = [
1084
-            'approved_status'   => [
1085
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1086
-                'desc'  => EEH_Template::pretty_status(
1087
-                    EEM_Registration::status_id_approved,
1088
-                    false,
1089
-                    'sentence'
1090
-                ),
1091
-            ],
1092
-            'pending_status'    => [
1093
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1094
-                'desc'  => EEH_Template::pretty_status(
1095
-                    EEM_Registration::status_id_pending_payment,
1096
-                    false,
1097
-                    'sentence'
1098
-                ),
1099
-            ],
1100
-            'wait_list'         => [
1101
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1102
-                'desc'  => EEH_Template::pretty_status(
1103
-                    EEM_Registration::status_id_wait_list,
1104
-                    false,
1105
-                    'sentence'
1106
-                ),
1107
-            ],
1108
-            'incomplete_status' => [
1109
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1110
-                'desc'  => EEH_Template::pretty_status(
1111
-                    EEM_Registration::status_id_incomplete,
1112
-                    false,
1113
-                    'sentence'
1114
-                ),
1115
-            ],
1116
-            'not_approved'      => [
1117
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1118
-                'desc'  => EEH_Template::pretty_status(
1119
-                    EEM_Registration::status_id_not_approved,
1120
-                    false,
1121
-                    'sentence'
1122
-                ),
1123
-            ],
1124
-            'declined_status'   => [
1125
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1126
-                'desc'  => EEH_Template::pretty_status(
1127
-                    EEM_Registration::status_id_declined,
1128
-                    false,
1129
-                    'sentence'
1130
-                ),
1131
-            ],
1132
-            'cancelled_status'  => [
1133
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1134
-                'desc'  => EEH_Template::pretty_status(
1135
-                    EEM_Registration::status_id_cancelled,
1136
-                    false,
1137
-                    'sentence'
1138
-                ),
1139
-            ],
1140
-        ];
1141
-        return array_merge($fc_items, $sc_items);
1142
-    }
1143
-
1144
-
1145
-
1146
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1147
-
1148
-
1149
-    /**
1150
-     * @throws DomainException
1151
-     * @throws EE_Error
1152
-     * @throws InvalidArgumentException
1153
-     * @throws InvalidDataTypeException
1154
-     * @throws InvalidInterfaceException
1155
-     */
1156
-    protected function _registrations_overview_list_table()
1157
-    {
1158
-        $this->appendAddNewRegistrationButtonToPageTitle();
1159
-        $header_text                  = '';
1160
-        $admin_page_header_decorators = [
1161
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1162
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1163
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1164
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1165
-        ];
1166
-        foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1167
-            $filter_header_decorator = $this->getLoader()->getNew($admin_page_header_decorator);
1168
-            $header_text             = $filter_header_decorator->getHeaderText($header_text);
1169
-        }
1170
-        $this->_template_args['admin_page_header'] = $header_text;
1171
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_registration_legend_items());
1172
-        $this->display_admin_list_table_page_with_no_sidebar();
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * @throws EE_Error
1178
-     * @throws InvalidArgumentException
1179
-     * @throws InvalidDataTypeException
1180
-     * @throws InvalidInterfaceException
1181
-     */
1182
-    private function appendAddNewRegistrationButtonToPageTitle()
1183
-    {
1184
-        $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
1185
-        if (
1186
-            $EVT_ID
1187
-            && EE_Registry::instance()->CAP->current_user_can(
1188
-                'ee_edit_registrations',
1189
-                'espresso_registrations_new_registration',
1190
-                $EVT_ID
1191
-            )
1192
-        ) {
1193
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1194
-                'new_registration',
1195
-                'add-registrant',
1196
-                ['event_id' => $EVT_ID],
1197
-                'add-new-h2'
1198
-            );
1199
-        }
1200
-    }
1201
-
1202
-
1203
-    /**
1204
-     * This sets the _registration property for the registration details screen
1205
-     *
1206
-     * @return void
1207
-     * @throws EE_Error
1208
-     * @throws InvalidArgumentException
1209
-     * @throws InvalidDataTypeException
1210
-     * @throws InvalidInterfaceException
1211
-     */
1212
-    private function _set_registration_object()
1213
-    {
1214
-        // get out if we've already set the object
1215
-        if ($this->_registration instanceof EE_Registration) {
1216
-            return;
1217
-        }
1218
-        $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
1219
-        if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1220
-            return;
1221
-        }
1222
-        $error_msg = sprintf(
1223
-            esc_html__(
1224
-                'An error occurred and the details for Registration ID #%s could not be retrieved.',
1225
-                'event_espresso'
1226
-            ),
1227
-            $REG_ID
1228
-        );
1229
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1230
-        $this->_registration = null;
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     * Used to retrieve registrations for the list table.
1236
-     *
1237
-     * @param int  $per_page
1238
-     * @param bool $count
1239
-     * @param bool $this_month
1240
-     * @param bool $today
1241
-     * @return EE_Registration[]|int
1242
-     * @throws EE_Error
1243
-     * @throws InvalidArgumentException
1244
-     * @throws InvalidDataTypeException
1245
-     * @throws InvalidInterfaceException
1246
-     */
1247
-    public function get_registrations(
1248
-        $per_page = 10,
1249
-        $count = false,
1250
-        $this_month = false,
1251
-        $today = false
1252
-    ) {
1253
-        if ($this_month) {
1254
-            $this->request->setRequestParam('status', 'month');
1255
-        }
1256
-        if ($today) {
1257
-            $this->request->setRequestParam('status', 'today');
1258
-        }
1259
-        $query_params = $this->_get_registration_query_parameters([], $per_page, $count);
1260
-        /**
1261
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1262
-         *
1263
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1264
-         * @see  https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1265
-         *                      or if you have the development copy of EE you can view this at the path:
1266
-         *                      /docs/G--Model-System/model-query-params.md
1267
-         */
1268
-        $query_params['group_by'] = '';
1269
-
1270
-        return $count
1271
-            ? $this->getRegistrationModel()->count($query_params)
1272
-            /** @type EE_Registration[] */
1273
-            : $this->getRegistrationModel()->get_all($query_params);
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1279
-     * Note: this listens to values on the request for some of the query parameters.
1280
-     *
1281
-     * @param array $request
1282
-     * @param int   $per_page
1283
-     * @param bool  $count
1284
-     * @return array
1285
-     * @throws EE_Error
1286
-     * @throws InvalidArgumentException
1287
-     * @throws InvalidDataTypeException
1288
-     * @throws InvalidInterfaceException
1289
-     */
1290
-    protected function _get_registration_query_parameters(
1291
-        $request = [],
1292
-        $per_page = 10,
1293
-        $count = false
1294
-    ) {
1295
-        /** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1296
-        $list_table_query_builder = $this->getLoader()->getNew(
1297
-            'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1298
-            [null, null, $request]
1299
-        );
1300
-        return $list_table_query_builder->getQueryParams($per_page, $count);
1301
-    }
1302
-
1303
-
1304
-    public function get_registration_status_array()
1305
-    {
1306
-        return self::$_reg_status;
1307
-    }
1308
-
1309
-
1310
-
1311
-
1312
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1313
-    /**
1314
-     * generates HTML for the View Registration Details Admin page
1315
-     *
1316
-     * @return void
1317
-     * @throws DomainException
1318
-     * @throws EE_Error
1319
-     * @throws InvalidArgumentException
1320
-     * @throws InvalidDataTypeException
1321
-     * @throws InvalidInterfaceException
1322
-     * @throws EntityNotFoundException
1323
-     * @throws ReflectionException
1324
-     */
1325
-    protected function _registration_details()
1326
-    {
1327
-        $this->_template_args = [];
1328
-        $this->_set_registration_object();
1329
-        if (is_object($this->_registration)) {
1330
-            $transaction                                   = $this->_registration->transaction()
1331
-                ? $this->_registration->transaction()
1332
-                : EE_Transaction::new_instance();
1333
-            $this->_session                                = $transaction->session_data();
1334
-            $event_id                                      = $this->_registration->event_ID();
1335
-            $this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1336
-            $this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1337
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1338
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1339
-            $this->_template_args['grand_total']           = $transaction->total();
1340
-            $this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1341
-            // link back to overview
1342
-            $this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1343
-            $this->_template_args['registration']                = $this->_registration;
1344
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1345
-                [
1346
-                    'action'   => 'default',
1347
-                    'event_id' => $event_id,
1348
-                ],
1349
-                REG_ADMIN_URL
1350
-            );
1351
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1352
-                [
1353
-                    'action' => 'default',
1354
-                    'EVT_ID' => $event_id,
1355
-                    'page'   => 'espresso_transactions',
1356
-                ],
1357
-                admin_url('admin.php')
1358
-            );
1359
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1360
-                [
1361
-                    'page'   => 'espresso_events',
1362
-                    'action' => 'edit',
1363
-                    'post'   => $event_id,
1364
-                ],
1365
-                admin_url('admin.php')
1366
-            );
1367
-            // next and previous links
1368
-            $next_reg                                      = $this->_registration->next(
1369
-                null,
1370
-                [],
1371
-                'REG_ID'
1372
-            );
1373
-            $this->_template_args['next_registration']     = $next_reg
1374
-                ? $this->_next_link(
1375
-                    EE_Admin_Page::add_query_args_and_nonce(
1376
-                        [
1377
-                            'action'  => 'view_registration',
1378
-                            '_REG_ID' => $next_reg['REG_ID'],
1379
-                        ],
1380
-                        REG_ADMIN_URL
1381
-                    ),
1382
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1383
-                )
1384
-                : '';
1385
-            $previous_reg                                  = $this->_registration->previous(
1386
-                null,
1387
-                [],
1388
-                'REG_ID'
1389
-            );
1390
-            $this->_template_args['previous_registration'] = $previous_reg
1391
-                ? $this->_previous_link(
1392
-                    EE_Admin_Page::add_query_args_and_nonce(
1393
-                        [
1394
-                            'action'  => 'view_registration',
1395
-                            '_REG_ID' => $previous_reg['REG_ID'],
1396
-                        ],
1397
-                        REG_ADMIN_URL
1398
-                    ),
1399
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1400
-                )
1401
-                : '';
1402
-            // grab header
1403
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1404
-            $this->_template_args['REG_ID']            = $this->_registration->ID();
1405
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1406
-                $template_path,
1407
-                $this->_template_args,
1408
-                true
1409
-            );
1410
-        } else {
1411
-            $this->_template_args['admin_page_header'] = '';
1412
-            $this->_display_espresso_notices();
1413
-        }
1414
-        // the details template wrapper
1415
-        $this->display_admin_page_with_sidebar();
1416
-    }
1417
-
1418
-
1419
-    /**
1420
-     * @throws EE_Error
1421
-     * @throws InvalidArgumentException
1422
-     * @throws InvalidDataTypeException
1423
-     * @throws InvalidInterfaceException
1424
-     * @throws ReflectionException
1425
-     * @since 4.10.2.p
1426
-     */
1427
-    protected function _registration_details_metaboxes()
1428
-    {
1429
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1430
-        $this->_set_registration_object();
1431
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1432
-        add_meta_box(
1433
-            'edit-reg-status-mbox',
1434
-            esc_html__('Registration Status', 'event_espresso'),
1435
-            [$this, 'set_reg_status_buttons_metabox'],
1436
-            $this->_wp_page_slug,
1437
-            'normal',
1438
-            'high'
1439
-        );
1440
-        add_meta_box(
1441
-            'edit-reg-details-mbox',
1442
-            esc_html__('Registration Details', 'event_espresso'),
1443
-            [$this, '_reg_details_meta_box'],
1444
-            $this->_wp_page_slug,
1445
-            'normal',
1446
-            'high'
1447
-        );
1448
-        if (
1449
-            $attendee instanceof EE_Attendee
1450
-            && EE_Registry::instance()->CAP->current_user_can(
1451
-                'ee_read_registration',
1452
-                'edit-reg-questions-mbox',
1453
-                $this->_registration->ID()
1454
-            )
1455
-        ) {
1456
-            add_meta_box(
1457
-                'edit-reg-questions-mbox',
1458
-                esc_html__('Registration Form Answers', 'event_espresso'),
1459
-                [$this, '_reg_questions_meta_box'],
1460
-                $this->_wp_page_slug,
1461
-                'normal',
1462
-                'high'
1463
-            );
1464
-        }
1465
-        add_meta_box(
1466
-            'edit-reg-registrant-mbox',
1467
-            esc_html__('Contact Details', 'event_espresso'),
1468
-            [$this, '_reg_registrant_side_meta_box'],
1469
-            $this->_wp_page_slug,
1470
-            'side',
1471
-            'high'
1472
-        );
1473
-        if ($this->_registration->group_size() > 1) {
1474
-            add_meta_box(
1475
-                'edit-reg-attendees-mbox',
1476
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1477
-                [$this, '_reg_attendees_meta_box'],
1478
-                $this->_wp_page_slug,
1479
-                'normal',
1480
-                'high'
1481
-            );
1482
-        }
1483
-    }
1484
-
1485
-
1486
-    /**
1487
-     * set_reg_status_buttons_metabox
1488
-     *
1489
-     * @return void
1490
-     * @throws EE_Error
1491
-     * @throws EntityNotFoundException
1492
-     * @throws InvalidArgumentException
1493
-     * @throws InvalidDataTypeException
1494
-     * @throws InvalidInterfaceException
1495
-     * @throws ReflectionException
1496
-     */
1497
-    public function set_reg_status_buttons_metabox()
1498
-    {
1499
-        $this->_set_registration_object();
1500
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1501
-        $output                 = $change_reg_status_form->form_open(
1502
-            self::add_query_args_and_nonce(
1503
-                [
1504
-                    'action' => 'change_reg_status',
1505
-                ],
1506
-                REG_ADMIN_URL
1507
-            )
1508
-        );
1509
-        $output                 .= $change_reg_status_form->get_html();
1510
-        $output                 .= $change_reg_status_form->form_close();
1511
-        echo wp_kses($output, AllowedTags::getWithFormTags());
1512
-    }
1513
-
1514
-
1515
-    /**
1516
-     * @return EE_Form_Section_Proper
1517
-     * @throws EE_Error
1518
-     * @throws InvalidArgumentException
1519
-     * @throws InvalidDataTypeException
1520
-     * @throws InvalidInterfaceException
1521
-     * @throws EntityNotFoundException
1522
-     * @throws ReflectionException
1523
-     */
1524
-    protected function _generate_reg_status_change_form()
1525
-    {
1526
-        $reg_status_change_form_array = [
1527
-            'name'            => 'reg_status_change_form',
1528
-            'html_id'         => 'reg-status-change-form',
1529
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1530
-            'subsections'     => [
1531
-                'return'         => new EE_Hidden_Input(
1532
-                    [
1533
-                        'name'    => 'return',
1534
-                        'default' => 'view_registration',
1535
-                    ]
1536
-                ),
1537
-                'REG_ID'         => new EE_Hidden_Input(
1538
-                    [
1539
-                        'name'    => 'REG_ID',
1540
-                        'default' => $this->_registration->ID(),
1541
-                    ]
1542
-                ),
1543
-                'current_status' => new EE_Form_Section_HTML(
1544
-                    EEH_HTML::table(
1545
-                        EEH_HTML::tr(
1546
-                            EEH_HTML::th(
1547
-                                EEH_HTML::label(
1548
-                                    EEH_HTML::strong(
1549
-                                        esc_html__('Current Registration Status', 'event_espresso')
1550
-                                    )
1551
-                                )
1552
-                            )
1553
-                            . EEH_HTML::td(
1554
-                                EEH_HTML::strong(
1555
-                                    $this->_registration->pretty_status(),
1556
-                                    '',
1557
-                                    'status-' . $this->_registration->status_ID(),
1558
-                                    'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1559
-                                )
1560
-                            )
1561
-                        )
1562
-                    )
1563
-                ),
1564
-            ],
1565
-        ];
1566
-        if (
1567
-            EE_Registry::instance()->CAP->current_user_can(
1568
-                'ee_edit_registration',
1569
-                'toggle_registration_status',
1570
-                $this->_registration->ID()
1571
-            )
1572
-        ) {
1573
-            $reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1574
-                $this->_get_reg_statuses(),
1575
-                [
1576
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1577
-                    'default'         => $this->_registration->status_ID(),
1578
-                ]
1579
-            );
1580
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1581
-                [
1582
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1583
-                    'default'         => false,
1584
-                    'html_help_text'  => esc_html__(
1585
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1586
-                        'event_espresso'
1587
-                    ),
1588
-                ]
1589
-            );
1590
-            $reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1591
-                [
1592
-                    'html_class'      => 'button-primary',
1593
-                    'html_label_text' => '&nbsp;',
1594
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1595
-                ]
1596
-            );
1597
-        }
1598
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1599
-    }
1600
-
1601
-
1602
-    /**
1603
-     * Returns an array of all the buttons for the various statuses and switch status actions
1604
-     *
1605
-     * @return array
1606
-     * @throws EE_Error
1607
-     * @throws InvalidArgumentException
1608
-     * @throws InvalidDataTypeException
1609
-     * @throws InvalidInterfaceException
1610
-     * @throws EntityNotFoundException
1611
-     */
1612
-    protected function _get_reg_statuses()
1613
-    {
1614
-        $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1615
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1616
-        // get current reg status
1617
-        $current_status = $this->_registration->status_ID();
1618
-        // is registration for free event? This will determine whether to display the pending payment option
1619
-        if (
1620
-            $current_status !== EEM_Registration::status_id_pending_payment
1621
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1622
-        ) {
1623
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1624
-        }
1625
-        return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1626
-    }
1627
-
1628
-
1629
-    /**
1630
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1631
-     *
1632
-     * @param bool $status REG status given for changing registrations to.
1633
-     * @param bool $notify Whether to send messages notifications or not.
1634
-     * @return array (array with reg_id(s) updated and whether update was successful.
1635
-     * @throws DomainException
1636
-     * @throws EE_Error
1637
-     * @throws EntityNotFoundException
1638
-     * @throws InvalidArgumentException
1639
-     * @throws InvalidDataTypeException
1640
-     * @throws InvalidInterfaceException
1641
-     * @throws ReflectionException
1642
-     * @throws RuntimeException
1643
-     */
1644
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1645
-    {
1646
-        $REG_IDs = $this->request->requestParamIsSet('reg_status_change_form')
1647
-            ? $this->request->getRequestParam('reg_status_change_form[REG_ID]', [], 'int', true)
1648
-            : $this->request->getRequestParam('_REG_ID', [], 'int', true);
1649
-
1650
-        // sanitize $REG_IDs
1651
-        $REG_IDs = array_map('absint', $REG_IDs);
1652
-        // and remove empty entries
1653
-        $REG_IDs = array_filter($REG_IDs);
1654
-
1655
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1656
-
1657
-        /**
1658
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1659
-         * Currently this value is used downstream by the _process_resend_registration method.
1660
-         *
1661
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1662
-         * @param bool                     $status           The status registrations were changed to.
1663
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1664
-         * @param Registrations_Admin_Page $admin_page_object
1665
-         */
1666
-        $REG_ID = apply_filters(
1667
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1668
-            $result['REG_ID'],
1669
-            $status,
1670
-            $result['success'],
1671
-            $this
1672
-        );
1673
-        $this->request->setRequestParam('_REG_ID', $REG_ID);
1674
-
1675
-        // notify?
1676
-        if (
1677
-            $notify
1678
-            && $result['success']
1679
-            && ! empty($REG_ID)
1680
-            && EE_Registry::instance()->CAP->current_user_can(
1681
-                'ee_send_message',
1682
-                'espresso_registrations_resend_registration'
1683
-            )
1684
-        ) {
1685
-            $this->_process_resend_registration();
1686
-        }
1687
-        return $result;
1688
-    }
1689
-
1690
-
1691
-    /**
1692
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1693
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1694
-     *
1695
-     * @param array  $REG_IDs
1696
-     * @param string $status
1697
-     * @param bool   $notify Used to indicate whether notification was requested or not.  This determines the context
1698
-     *                       slug sent with setting the registration status.
1699
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1700
-     * @throws EE_Error
1701
-     * @throws InvalidArgumentException
1702
-     * @throws InvalidDataTypeException
1703
-     * @throws InvalidInterfaceException
1704
-     * @throws ReflectionException
1705
-     * @throws RuntimeException
1706
-     * @throws EntityNotFoundException
1707
-     * @throws DomainException
1708
-     */
1709
-    protected function _set_registration_status($REG_IDs = [], $status = '', $notify = false)
1710
-    {
1711
-        $success = false;
1712
-        // typecast $REG_IDs
1713
-        $REG_IDs = (array) $REG_IDs;
1714
-        if (! empty($REG_IDs)) {
1715
-            $success = true;
1716
-            // set default status if none is passed
1717
-            $status         = $status ?: EEM_Registration::status_id_pending_payment;
1718
-            $status_context = $notify
1719
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1720
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1721
-            // loop through REG_ID's and change status
1722
-            foreach ($REG_IDs as $REG_ID) {
1723
-                $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1724
-                if ($registration instanceof EE_Registration) {
1725
-                    $registration->set_status(
1726
-                        $status,
1727
-                        false,
1728
-                        new Context(
1729
-                            $status_context,
1730
-                            esc_html__(
1731
-                                'Manually triggered status change on a Registration Admin Page route.',
1732
-                                'event_espresso'
1733
-                            )
1734
-                        )
1735
-                    );
1736
-                    $result = $registration->save();
1737
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1738
-                    $success = $result !== false ? $success : false;
1739
-                }
1740
-            }
1741
-        }
1742
-
1743
-        // return $success and processed registrations
1744
-        return ['REG_ID' => $REG_IDs, 'success' => $success];
1745
-    }
1746
-
1747
-
1748
-    /**
1749
-     * Common logic for setting up success message and redirecting to appropriate route
1750
-     *
1751
-     * @param string $STS_ID status id for the registration changed to
1752
-     * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1753
-     * @return void
1754
-     * @throws DomainException
1755
-     * @throws EE_Error
1756
-     * @throws EntityNotFoundException
1757
-     * @throws InvalidArgumentException
1758
-     * @throws InvalidDataTypeException
1759
-     * @throws InvalidInterfaceException
1760
-     * @throws ReflectionException
1761
-     * @throws RuntimeException
1762
-     */
1763
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1764
-    {
1765
-        $result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1766
-            : ['success' => false];
1767
-        $success = isset($result['success']) && $result['success'];
1768
-        // setup success message
1769
-        if ($success) {
1770
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1771
-                $msg = sprintf(
1772
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1773
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1774
-                );
1775
-            } else {
1776
-                $msg = sprintf(
1777
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1778
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1779
-                );
1780
-            }
1781
-            EE_Error::add_success($msg);
1782
-        } else {
1783
-            EE_Error::add_error(
1784
-                esc_html__(
1785
-                    'Something went wrong, and the status was not changed',
1786
-                    'event_espresso'
1787
-                ),
1788
-                __FILE__,
1789
-                __LINE__,
1790
-                __FUNCTION__
1791
-            );
1792
-        }
1793
-        $return = $this->request->getRequestParam('return');
1794
-        $route  = $return === 'view_registration'
1795
-            ? ['action' => 'view_registration', '_REG_ID' => reset($result['REG_ID'])]
1796
-            : ['action' => 'default'];
1797
-        $route  = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1798
-        $this->_redirect_after_action($success, '', '', $route, true);
1799
-    }
1800
-
1801
-
1802
-    /**
1803
-     * incoming reg status change from reg details page.
1804
-     *
1805
-     * @return void
1806
-     * @throws EE_Error
1807
-     * @throws EntityNotFoundException
1808
-     * @throws InvalidArgumentException
1809
-     * @throws InvalidDataTypeException
1810
-     * @throws InvalidInterfaceException
1811
-     * @throws ReflectionException
1812
-     * @throws RuntimeException
1813
-     * @throws DomainException
1814
-     */
1815
-    protected function _change_reg_status()
1816
-    {
1817
-        $this->request->setRequestParam('return', 'view_registration');
1818
-        // set notify based on whether the send notifications toggle is set or not
1819
-        $notify     = $this->request->getRequestParam('reg_status_change_form[send_notifications]', false, 'bool');
1820
-        $reg_status = $this->request->getRequestParam('reg_status_change_form[reg_status]', '');
1821
-        $this->request->setRequestParam('reg_status_change_form[reg_status]', $reg_status);
1822
-        switch ($reg_status) {
1823
-            case EEM_Registration::status_id_approved:
1824
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1825
-                $this->approve_registration($notify);
1826
-                break;
1827
-            case EEM_Registration::status_id_pending_payment:
1828
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1829
-                $this->pending_registration($notify);
1830
-                break;
1831
-            case EEM_Registration::status_id_not_approved:
1832
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1833
-                $this->not_approve_registration($notify);
1834
-                break;
1835
-            case EEM_Registration::status_id_declined:
1836
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1837
-                $this->decline_registration($notify);
1838
-                break;
1839
-            case EEM_Registration::status_id_cancelled:
1840
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1841
-                $this->cancel_registration($notify);
1842
-                break;
1843
-            case EEM_Registration::status_id_wait_list:
1844
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1845
-                $this->wait_list_registration($notify);
1846
-                break;
1847
-            case EEM_Registration::status_id_incomplete:
1848
-            default:
1849
-                $this->request->unSetRequestParam('return');
1850
-                $this->_reg_status_change_return('');
1851
-                break;
1852
-        }
1853
-    }
1854
-
1855
-
1856
-    /**
1857
-     * Callback for bulk action routes.
1858
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1859
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
1860
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1861
-     * when an action is happening on just a single registration).
1862
-     *
1863
-     * @param      $action
1864
-     * @param bool $notify
1865
-     */
1866
-    protected function bulk_action_on_registrations($action, $notify = false)
1867
-    {
1868
-        do_action(
1869
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1870
-            $this,
1871
-            $action,
1872
-            $notify
1873
-        );
1874
-        $method = $action . '_registration';
1875
-        if (method_exists($this, $method)) {
1876
-            $this->$method($notify);
1877
-        }
1878
-    }
1879
-
1880
-
1881
-    /**
1882
-     * approve_registration
1883
-     *
1884
-     * @param bool $notify whether or not to notify the registrant about their approval.
1885
-     * @return void
1886
-     * @throws EE_Error
1887
-     * @throws EntityNotFoundException
1888
-     * @throws InvalidArgumentException
1889
-     * @throws InvalidDataTypeException
1890
-     * @throws InvalidInterfaceException
1891
-     * @throws ReflectionException
1892
-     * @throws RuntimeException
1893
-     * @throws DomainException
1894
-     */
1895
-    protected function approve_registration($notify = false)
1896
-    {
1897
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1898
-    }
1899
-
1900
-
1901
-    /**
1902
-     * decline_registration
1903
-     *
1904
-     * @param bool $notify whether or not to notify the registrant about their status change.
1905
-     * @return void
1906
-     * @throws EE_Error
1907
-     * @throws EntityNotFoundException
1908
-     * @throws InvalidArgumentException
1909
-     * @throws InvalidDataTypeException
1910
-     * @throws InvalidInterfaceException
1911
-     * @throws ReflectionException
1912
-     * @throws RuntimeException
1913
-     * @throws DomainException
1914
-     */
1915
-    protected function decline_registration($notify = false)
1916
-    {
1917
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1918
-    }
1919
-
1920
-
1921
-    /**
1922
-     * cancel_registration
1923
-     *
1924
-     * @param bool $notify whether or not to notify the registrant about their status change.
1925
-     * @return void
1926
-     * @throws EE_Error
1927
-     * @throws EntityNotFoundException
1928
-     * @throws InvalidArgumentException
1929
-     * @throws InvalidDataTypeException
1930
-     * @throws InvalidInterfaceException
1931
-     * @throws ReflectionException
1932
-     * @throws RuntimeException
1933
-     * @throws DomainException
1934
-     */
1935
-    protected function cancel_registration($notify = false)
1936
-    {
1937
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1938
-    }
1939
-
1940
-
1941
-    /**
1942
-     * not_approve_registration
1943
-     *
1944
-     * @param bool $notify whether or not to notify the registrant about their status change.
1945
-     * @return void
1946
-     * @throws EE_Error
1947
-     * @throws EntityNotFoundException
1948
-     * @throws InvalidArgumentException
1949
-     * @throws InvalidDataTypeException
1950
-     * @throws InvalidInterfaceException
1951
-     * @throws ReflectionException
1952
-     * @throws RuntimeException
1953
-     * @throws DomainException
1954
-     */
1955
-    protected function not_approve_registration($notify = false)
1956
-    {
1957
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1958
-    }
1959
-
1960
-
1961
-    /**
1962
-     * decline_registration
1963
-     *
1964
-     * @param bool $notify whether or not to notify the registrant about their status change.
1965
-     * @return void
1966
-     * @throws EE_Error
1967
-     * @throws EntityNotFoundException
1968
-     * @throws InvalidArgumentException
1969
-     * @throws InvalidDataTypeException
1970
-     * @throws InvalidInterfaceException
1971
-     * @throws ReflectionException
1972
-     * @throws RuntimeException
1973
-     * @throws DomainException
1974
-     */
1975
-    protected function pending_registration($notify = false)
1976
-    {
1977
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1978
-    }
1979
-
1980
-
1981
-    /**
1982
-     * waitlist_registration
1983
-     *
1984
-     * @param bool $notify whether or not to notify the registrant about their status change.
1985
-     * @return void
1986
-     * @throws EE_Error
1987
-     * @throws EntityNotFoundException
1988
-     * @throws InvalidArgumentException
1989
-     * @throws InvalidDataTypeException
1990
-     * @throws InvalidInterfaceException
1991
-     * @throws ReflectionException
1992
-     * @throws RuntimeException
1993
-     * @throws DomainException
1994
-     */
1995
-    protected function wait_list_registration($notify = false)
1996
-    {
1997
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1998
-    }
1999
-
2000
-
2001
-    /**
2002
-     * generates HTML for the Registration main meta box
2003
-     *
2004
-     * @return void
2005
-     * @throws DomainException
2006
-     * @throws EE_Error
2007
-     * @throws InvalidArgumentException
2008
-     * @throws InvalidDataTypeException
2009
-     * @throws InvalidInterfaceException
2010
-     * @throws ReflectionException
2011
-     * @throws EntityNotFoundException
2012
-     */
2013
-    public function _reg_details_meta_box()
2014
-    {
2015
-        EEH_Autoloader::register_line_item_display_autoloaders();
2016
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2017
-        EE_Registry::instance()->load_helper('Line_Item');
2018
-        $transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
2019
-            : EE_Transaction::new_instance();
2020
-        $this->_session = $transaction->session_data();
2021
-        $filters        = new EE_Line_Item_Filter_Collection();
2022
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2023
-        $filters->add(new EE_Non_Zero_Line_Item_Filter());
2024
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
2025
-            $filters,
2026
-            $transaction->total_line_item()
2027
-        );
2028
-        $filtered_line_item_tree                 = $line_item_filter_processor->process();
2029
-        $line_item_display                       = new EE_Line_Item_Display(
2030
-            'reg_admin_table',
2031
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2032
-        );
2033
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2034
-            $filtered_line_item_tree,
2035
-            ['EE_Registration' => $this->_registration]
2036
-        );
2037
-        $attendee                                = $this->_registration->attendee();
2038
-        if (
2039
-            EE_Registry::instance()->CAP->current_user_can(
2040
-                'ee_read_transaction',
2041
-                'espresso_transactions_view_transaction'
2042
-            )
2043
-        ) {
2044
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2045
-                EE_Admin_Page::add_query_args_and_nonce(
2046
-                    [
2047
-                        'action' => 'view_transaction',
2048
-                        'TXN_ID' => $transaction->ID(),
2049
-                    ],
2050
-                    TXN_ADMIN_URL
2051
-                ),
2052
-                esc_html__(' View Transaction', 'event_espresso'),
2053
-                'button secondary-button right',
2054
-                'dashicons dashicons-cart'
2055
-            );
2056
-        } else {
2057
-            $this->_template_args['view_transaction_button'] = '';
2058
-        }
2059
-        if (
2060
-            $attendee instanceof EE_Attendee
2061
-            && EE_Registry::instance()->CAP->current_user_can(
2062
-                'ee_send_message',
2063
-                'espresso_registrations_resend_registration'
2064
-            )
2065
-        ) {
2066
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2067
-                EE_Admin_Page::add_query_args_and_nonce(
2068
-                    [
2069
-                        'action'      => 'resend_registration',
2070
-                        '_REG_ID'     => $this->_registration->ID(),
2071
-                        'redirect_to' => 'view_registration',
2072
-                    ],
2073
-                    REG_ADMIN_URL
2074
-                ),
2075
-                esc_html__(' Resend Registration', 'event_espresso'),
2076
-                'button secondary-button right',
2077
-                'dashicons dashicons-email-alt'
2078
-            );
2079
-        } else {
2080
-            $this->_template_args['resend_registration_button'] = '';
2081
-        }
2082
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2083
-        $payment                               = $transaction->get_first_related('Payment');
2084
-        $payment                               = ! $payment instanceof EE_Payment
2085
-            ? EE_Payment::new_instance()
2086
-            : $payment;
2087
-        $payment_method                        = $payment->get_first_related('Payment_Method');
2088
-        $payment_method                        = ! $payment_method instanceof EE_Payment_Method
2089
-            ? EE_Payment_Method::new_instance()
2090
-            : $payment_method;
2091
-        $reg_details                           = [
2092
-            'payment_method'       => $payment_method->name(),
2093
-            'response_msg'         => $payment->gateway_response(),
2094
-            'registration_id'      => $this->_registration->get('REG_code'),
2095
-            'registration_session' => $this->_registration->session_ID(),
2096
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2097
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2098
-        ];
2099
-        if (isset($reg_details['registration_id'])) {
2100
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2101
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2102
-                'Registration ID',
2103
-                'event_espresso'
2104
-            );
2105
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2106
-        }
2107
-        if (isset($reg_details['payment_method'])) {
2108
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2109
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2110
-                'Most Recent Payment Method',
2111
-                'event_espresso'
2112
-            );
2113
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2114
-            $this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2115
-            $this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2116
-                'Payment method response',
2117
-                'event_espresso'
2118
-            );
2119
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2120
-        }
2121
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2122
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2123
-            'Registration Session',
2124
-            'event_espresso'
2125
-        );
2126
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2127
-        $this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2128
-        $this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2129
-            'Registration placed from IP',
2130
-            'event_espresso'
2131
-        );
2132
-        $this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2133
-        $this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2134
-        $this->_template_args['reg_details']['user_agent']['label']           = esc_html__(
2135
-            'Registrant User Agent',
2136
-            'event_espresso'
2137
-        );
2138
-        $this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2139
-        $this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2140
-            [
2141
-                'action'   => 'default',
2142
-                'event_id' => $this->_registration->event_ID(),
2143
-            ],
2144
-            REG_ADMIN_URL
2145
-        );
2146
-        $this->_template_args['REG_ID']                                       = $this->_registration->ID();
2147
-        $this->_template_args['event_id']                                     = $this->_registration->event_ID();
2148
-        $template_path                                                        =
2149
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2150
-        EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2151
-    }
2152
-
2153
-
2154
-    /**
2155
-     * generates HTML for the Registration Questions meta box.
2156
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2157
-     * otherwise uses new forms system
2158
-     *
2159
-     * @return void
2160
-     * @throws DomainException
2161
-     * @throws EE_Error
2162
-     * @throws InvalidArgumentException
2163
-     * @throws InvalidDataTypeException
2164
-     * @throws InvalidInterfaceException
2165
-     * @throws ReflectionException
2166
-     */
2167
-    public function _reg_questions_meta_box()
2168
-    {
2169
-        // allow someone to override this method entirely
2170
-        if (
2171
-            apply_filters(
2172
-                'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2173
-                true,
2174
-                $this,
2175
-                $this->_registration
2176
-            )
2177
-        ) {
2178
-            $form                                              = $this->_get_reg_custom_questions_form(
2179
-                $this->_registration->ID()
2180
-            );
2181
-            $this->_template_args['att_questions']             = count($form->subforms()) > 0
2182
-                ? $form->get_html_and_js()
2183
-                : '';
2184
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2185
-            $this->_template_args['REG_ID']                    = $this->_registration->ID();
2186
-            $template_path                                     =
2187
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2188
-            EEH_Template::display_template($template_path, $this->_template_args);
2189
-        }
2190
-    }
2191
-
2192
-
2193
-    /**
2194
-     * form_before_question_group
2195
-     *
2196
-     * @param string $output
2197
-     * @return        string
2198
-     * @deprecated    as of 4.8.32.rc.000
2199
-     */
2200
-    public function form_before_question_group($output)
2201
-    {
2202
-        EE_Error::doing_it_wrong(
2203
-            __CLASS__ . '::' . __FUNCTION__,
2204
-            esc_html__(
2205
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2206
-                'event_espresso'
2207
-            ),
2208
-            '4.8.32.rc.000'
2209
-        );
2210
-        return '
25
+	/**
26
+	 * @var EE_Registration
27
+	 */
28
+	private $_registration;
29
+
30
+	/**
31
+	 * @var EE_Event
32
+	 */
33
+	private $_reg_event;
34
+
35
+	/**
36
+	 * @var EE_Session
37
+	 */
38
+	private $_session;
39
+
40
+	/**
41
+	 * @var array
42
+	 */
43
+	private static $_reg_status;
44
+
45
+	/**
46
+	 * Form for displaying the custom questions for this registration.
47
+	 * This gets used a few times throughout the request so its best to cache it
48
+	 *
49
+	 * @var EE_Registration_Custom_Questions_Form
50
+	 */
51
+	protected $_reg_custom_questions_form = null;
52
+
53
+	/**
54
+	 * @var EEM_Registration $registration_model
55
+	 */
56
+	private $registration_model;
57
+
58
+	/**
59
+	 * @var EEM_Attendee $attendee_model
60
+	 */
61
+	private $attendee_model;
62
+
63
+	/**
64
+	 * @var EEM_Event $event_model
65
+	 */
66
+	private $event_model;
67
+
68
+	/**
69
+	 * @var EEM_Status $status_model
70
+	 */
71
+	private $status_model;
72
+
73
+
74
+	/**
75
+	 * @param bool $routing
76
+	 * @throws EE_Error
77
+	 * @throws InvalidArgumentException
78
+	 * @throws InvalidDataTypeException
79
+	 * @throws InvalidInterfaceException
80
+	 * @throws ReflectionException
81
+	 */
82
+	public function __construct($routing = true)
83
+	{
84
+		parent::__construct($routing);
85
+		add_action('wp_loaded', [$this, 'wp_loaded']);
86
+	}
87
+
88
+
89
+	/**
90
+	 * @return EEM_Registration
91
+	 * @throws InvalidArgumentException
92
+	 * @throws InvalidDataTypeException
93
+	 * @throws InvalidInterfaceException
94
+	 * @since 4.10.2.p
95
+	 */
96
+	protected function getRegistrationModel()
97
+	{
98
+		if (! $this->registration_model instanceof EEM_Registration) {
99
+			$this->registration_model = $this->getLoader()->getShared('EEM_Registration');
100
+		}
101
+		return $this->registration_model;
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return EEM_Attendee
107
+	 * @throws InvalidArgumentException
108
+	 * @throws InvalidDataTypeException
109
+	 * @throws InvalidInterfaceException
110
+	 * @since 4.10.2.p
111
+	 */
112
+	protected function getAttendeeModel()
113
+	{
114
+		if (! $this->attendee_model instanceof EEM_Attendee) {
115
+			$this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
116
+		}
117
+		return $this->attendee_model;
118
+	}
119
+
120
+
121
+	/**
122
+	 * @return EEM_Event
123
+	 * @throws InvalidArgumentException
124
+	 * @throws InvalidDataTypeException
125
+	 * @throws InvalidInterfaceException
126
+	 * @since 4.10.2.p
127
+	 */
128
+	protected function getEventModel()
129
+	{
130
+		if (! $this->event_model instanceof EEM_Event) {
131
+			$this->event_model = $this->getLoader()->getShared('EEM_Event');
132
+		}
133
+		return $this->event_model;
134
+	}
135
+
136
+
137
+	/**
138
+	 * @return EEM_Status
139
+	 * @throws InvalidArgumentException
140
+	 * @throws InvalidDataTypeException
141
+	 * @throws InvalidInterfaceException
142
+	 * @since 4.10.2.p
143
+	 */
144
+	protected function getStatusModel()
145
+	{
146
+		if (! $this->status_model instanceof EEM_Status) {
147
+			$this->status_model = $this->getLoader()->getShared('EEM_Status');
148
+		}
149
+		return $this->status_model;
150
+	}
151
+
152
+
153
+	public function wp_loaded()
154
+	{
155
+		// when adding a new registration...
156
+		$action = $this->request->getRequestParam('action');
157
+		if ($action === 'new_registration') {
158
+			EE_System::do_not_cache();
159
+			if ($this->request->getRequestParam('processing_registration', 0, 'int') !== 1) {
160
+				// and it's NOT the attendee information reg step
161
+				// force cookie expiration by setting time to last week
162
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
163
+				// and update the global
164
+				$_COOKIE['ee_registration_added'] = 0;
165
+			}
166
+		}
167
+	}
168
+
169
+
170
+	protected function _init_page_props()
171
+	{
172
+		$this->page_slug        = REG_PG_SLUG;
173
+		$this->_admin_base_url  = REG_ADMIN_URL;
174
+		$this->_admin_base_path = REG_ADMIN;
175
+		$this->page_label       = esc_html__('Registrations', 'event_espresso');
176
+		$this->_cpt_routes      = [
177
+			'add_new_attendee' => 'espresso_attendees',
178
+			'edit_attendee'    => 'espresso_attendees',
179
+			'insert_attendee'  => 'espresso_attendees',
180
+			'update_attendee'  => 'espresso_attendees',
181
+		];
182
+		$this->_cpt_model_names = [
183
+			'add_new_attendee' => 'EEM_Attendee',
184
+			'edit_attendee'    => 'EEM_Attendee',
185
+		];
186
+		$this->_cpt_edit_routes = [
187
+			'espresso_attendees' => 'edit_attendee',
188
+		];
189
+		$this->_pagenow_map     = [
190
+			'add_new_attendee' => 'post-new.php',
191
+			'edit_attendee'    => 'post.php',
192
+			'trash'            => 'post.php',
193
+		];
194
+		add_action('edit_form_after_title', [$this, 'after_title_form_fields'], 10);
195
+		// add filters so that the comment urls don't take users to a confusing 404 page
196
+		add_filter('get_comment_link', [$this, 'clear_comment_link'], 10, 2);
197
+	}
198
+
199
+
200
+	/**
201
+	 * @param string     $link    The comment permalink with '#comment-$id' appended.
202
+	 * @param WP_Comment $comment The current comment object.
203
+	 * @return string
204
+	 */
205
+	public function clear_comment_link($link, WP_Comment $comment)
206
+	{
207
+		// gotta make sure this only happens on this route
208
+		$post_type = get_post_type($comment->comment_post_ID);
209
+		if ($post_type === 'espresso_attendees') {
210
+			return '#commentsdiv';
211
+		}
212
+		return $link;
213
+	}
214
+
215
+
216
+	protected function _ajax_hooks()
217
+	{
218
+		// todo: all hooks for registrations ajax goes in here
219
+		add_action('wp_ajax_toggle_checkin_status', [$this, 'toggle_checkin_status']);
220
+	}
221
+
222
+
223
+	protected function _define_page_props()
224
+	{
225
+		$this->_admin_page_title = $this->page_label;
226
+		$this->_labels           = [
227
+			'buttons'                      => [
228
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
229
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
230
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
231
+				'csv_reg_report'      => esc_html__('Registrations CSV Report', 'event_espresso'),
232
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
233
+				'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
234
+			],
235
+			'publishbox'                   => [
236
+				'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
237
+				'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
238
+			],
239
+			'hide_add_button_on_cpt_route' => [
240
+				'edit_attendee' => true,
241
+			],
242
+		];
243
+	}
244
+
245
+
246
+	/**
247
+	 * grab url requests and route them
248
+	 *
249
+	 * @return void
250
+	 * @throws EE_Error
251
+	 */
252
+	public function _set_page_routes()
253
+	{
254
+		$this->_get_registration_status_array();
255
+		$REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
256
+		$REG_ID             = $this->request->getRequestParam('reg_status_change_form[REG_ID]', $REG_ID, 'int');
257
+		$ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
258
+		$ATT_ID             = $this->request->getRequestParam('post', $ATT_ID, 'int');
259
+		$this->_page_routes = [
260
+			'default'                             => [
261
+				'func'       => [$this, '_registrations_overview_list_table'],
262
+				'capability' => 'ee_read_registrations',
263
+			],
264
+			'view_registration'                   => [
265
+				'func'       => '_registration_details',
266
+				'capability' => 'ee_read_registration',
267
+				'obj_id'     => $REG_ID,
268
+			],
269
+			'edit_registration'                   => [
270
+				'func'               => '_update_attendee_registration_form',
271
+				'noheader'           => true,
272
+				'headers_sent_route' => 'view_registration',
273
+				'capability'         => 'ee_edit_registration',
274
+				'obj_id'             => $REG_ID,
275
+				'_REG_ID'            => $REG_ID,
276
+			],
277
+			'trash_registrations'                 => [
278
+				'func'       => '_trash_or_restore_registrations',
279
+				'args'       => ['trash' => true],
280
+				'noheader'   => true,
281
+				'capability' => 'ee_delete_registrations',
282
+			],
283
+			'restore_registrations'               => [
284
+				'func'       => '_trash_or_restore_registrations',
285
+				'args'       => ['trash' => false],
286
+				'noheader'   => true,
287
+				'capability' => 'ee_delete_registrations',
288
+			],
289
+			'delete_registrations'                => [
290
+				'func'       => '_delete_registrations',
291
+				'noheader'   => true,
292
+				'capability' => 'ee_delete_registrations',
293
+			],
294
+			'new_registration'                    => [
295
+				'func'       => 'new_registration',
296
+				'capability' => 'ee_edit_registrations',
297
+			],
298
+			'process_reg_step'                    => [
299
+				'func'       => 'process_reg_step',
300
+				'noheader'   => true,
301
+				'capability' => 'ee_edit_registrations',
302
+			],
303
+			'redirect_to_txn'                     => [
304
+				'func'       => 'redirect_to_txn',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registrations',
307
+			],
308
+			'change_reg_status'                   => [
309
+				'func'       => '_change_reg_status',
310
+				'noheader'   => true,
311
+				'capability' => 'ee_edit_registration',
312
+				'obj_id'     => $REG_ID,
313
+			],
314
+			'approve_registration'                => [
315
+				'func'       => 'approve_registration',
316
+				'noheader'   => true,
317
+				'capability' => 'ee_edit_registration',
318
+				'obj_id'     => $REG_ID,
319
+			],
320
+			'approve_and_notify_registration'     => [
321
+				'func'       => 'approve_registration',
322
+				'noheader'   => true,
323
+				'args'       => [true],
324
+				'capability' => 'ee_edit_registration',
325
+				'obj_id'     => $REG_ID,
326
+			],
327
+			'approve_registrations'               => [
328
+				'func'       => 'bulk_action_on_registrations',
329
+				'noheader'   => true,
330
+				'capability' => 'ee_edit_registrations',
331
+				'args'       => ['approve'],
332
+			],
333
+			'approve_and_notify_registrations'    => [
334
+				'func'       => 'bulk_action_on_registrations',
335
+				'noheader'   => true,
336
+				'capability' => 'ee_edit_registrations',
337
+				'args'       => ['approve', true],
338
+			],
339
+			'decline_registration'                => [
340
+				'func'       => 'decline_registration',
341
+				'noheader'   => true,
342
+				'capability' => 'ee_edit_registration',
343
+				'obj_id'     => $REG_ID,
344
+			],
345
+			'decline_and_notify_registration'     => [
346
+				'func'       => 'decline_registration',
347
+				'noheader'   => true,
348
+				'args'       => [true],
349
+				'capability' => 'ee_edit_registration',
350
+				'obj_id'     => $REG_ID,
351
+			],
352
+			'decline_registrations'               => [
353
+				'func'       => 'bulk_action_on_registrations',
354
+				'noheader'   => true,
355
+				'capability' => 'ee_edit_registrations',
356
+				'args'       => ['decline'],
357
+			],
358
+			'decline_and_notify_registrations'    => [
359
+				'func'       => 'bulk_action_on_registrations',
360
+				'noheader'   => true,
361
+				'capability' => 'ee_edit_registrations',
362
+				'args'       => ['decline', true],
363
+			],
364
+			'pending_registration'                => [
365
+				'func'       => 'pending_registration',
366
+				'noheader'   => true,
367
+				'capability' => 'ee_edit_registration',
368
+				'obj_id'     => $REG_ID,
369
+			],
370
+			'pending_and_notify_registration'     => [
371
+				'func'       => 'pending_registration',
372
+				'noheader'   => true,
373
+				'args'       => [true],
374
+				'capability' => 'ee_edit_registration',
375
+				'obj_id'     => $REG_ID,
376
+			],
377
+			'pending_registrations'               => [
378
+				'func'       => 'bulk_action_on_registrations',
379
+				'noheader'   => true,
380
+				'capability' => 'ee_edit_registrations',
381
+				'args'       => ['pending'],
382
+			],
383
+			'pending_and_notify_registrations'    => [
384
+				'func'       => 'bulk_action_on_registrations',
385
+				'noheader'   => true,
386
+				'capability' => 'ee_edit_registrations',
387
+				'args'       => ['pending', true],
388
+			],
389
+			'no_approve_registration'             => [
390
+				'func'       => 'not_approve_registration',
391
+				'noheader'   => true,
392
+				'capability' => 'ee_edit_registration',
393
+				'obj_id'     => $REG_ID,
394
+			],
395
+			'no_approve_and_notify_registration'  => [
396
+				'func'       => 'not_approve_registration',
397
+				'noheader'   => true,
398
+				'args'       => [true],
399
+				'capability' => 'ee_edit_registration',
400
+				'obj_id'     => $REG_ID,
401
+			],
402
+			'no_approve_registrations'            => [
403
+				'func'       => 'bulk_action_on_registrations',
404
+				'noheader'   => true,
405
+				'capability' => 'ee_edit_registrations',
406
+				'args'       => ['not_approve'],
407
+			],
408
+			'no_approve_and_notify_registrations' => [
409
+				'func'       => 'bulk_action_on_registrations',
410
+				'noheader'   => true,
411
+				'capability' => 'ee_edit_registrations',
412
+				'args'       => ['not_approve', true],
413
+			],
414
+			'cancel_registration'                 => [
415
+				'func'       => 'cancel_registration',
416
+				'noheader'   => true,
417
+				'capability' => 'ee_edit_registration',
418
+				'obj_id'     => $REG_ID,
419
+			],
420
+			'cancel_and_notify_registration'      => [
421
+				'func'       => 'cancel_registration',
422
+				'noheader'   => true,
423
+				'args'       => [true],
424
+				'capability' => 'ee_edit_registration',
425
+				'obj_id'     => $REG_ID,
426
+			],
427
+			'cancel_registrations'                => [
428
+				'func'       => 'bulk_action_on_registrations',
429
+				'noheader'   => true,
430
+				'capability' => 'ee_edit_registrations',
431
+				'args'       => ['cancel'],
432
+			],
433
+			'cancel_and_notify_registrations'     => [
434
+				'func'       => 'bulk_action_on_registrations',
435
+				'noheader'   => true,
436
+				'capability' => 'ee_edit_registrations',
437
+				'args'       => ['cancel', true],
438
+			],
439
+			'wait_list_registration'              => [
440
+				'func'       => 'wait_list_registration',
441
+				'noheader'   => true,
442
+				'capability' => 'ee_edit_registration',
443
+				'obj_id'     => $REG_ID,
444
+			],
445
+			'wait_list_and_notify_registration'   => [
446
+				'func'       => 'wait_list_registration',
447
+				'noheader'   => true,
448
+				'args'       => [true],
449
+				'capability' => 'ee_edit_registration',
450
+				'obj_id'     => $REG_ID,
451
+			],
452
+			'contact_list'                        => [
453
+				'func'       => '_attendee_contact_list_table',
454
+				'capability' => 'ee_read_contacts',
455
+			],
456
+			'add_new_attendee'                    => [
457
+				'func' => '_create_new_cpt_item',
458
+				'args' => [
459
+					'new_attendee' => true,
460
+					'capability'   => 'ee_edit_contacts',
461
+				],
462
+			],
463
+			'edit_attendee'                       => [
464
+				'func'       => '_edit_cpt_item',
465
+				'capability' => 'ee_edit_contacts',
466
+				'obj_id'     => $ATT_ID,
467
+			],
468
+			'duplicate_attendee'                  => [
469
+				'func'       => '_duplicate_attendee',
470
+				'noheader'   => true,
471
+				'capability' => 'ee_edit_contacts',
472
+				'obj_id'     => $ATT_ID,
473
+			],
474
+			'insert_attendee'                     => [
475
+				'func'       => '_insert_or_update_attendee',
476
+				'args'       => [
477
+					'new_attendee' => true,
478
+				],
479
+				'noheader'   => true,
480
+				'capability' => 'ee_edit_contacts',
481
+			],
482
+			'update_attendee'                     => [
483
+				'func'       => '_insert_or_update_attendee',
484
+				'args'       => [
485
+					'new_attendee' => false,
486
+				],
487
+				'noheader'   => true,
488
+				'capability' => 'ee_edit_contacts',
489
+				'obj_id'     => $ATT_ID,
490
+			],
491
+			'trash_attendees'                     => [
492
+				'func'       => '_trash_or_restore_attendees',
493
+				'args'       => [
494
+					'trash' => 'true',
495
+				],
496
+				'noheader'   => true,
497
+				'capability' => 'ee_delete_contacts',
498
+			],
499
+			'trash_attendee'                      => [
500
+				'func'       => '_trash_or_restore_attendees',
501
+				'args'       => [
502
+					'trash' => true,
503
+				],
504
+				'noheader'   => true,
505
+				'capability' => 'ee_delete_contacts',
506
+				'obj_id'     => $ATT_ID,
507
+			],
508
+			'restore_attendees'                   => [
509
+				'func'       => '_trash_or_restore_attendees',
510
+				'args'       => [
511
+					'trash' => false,
512
+				],
513
+				'noheader'   => true,
514
+				'capability' => 'ee_delete_contacts',
515
+				'obj_id'     => $ATT_ID,
516
+			],
517
+			'resend_registration'                 => [
518
+				'func'       => '_resend_registration',
519
+				'noheader'   => true,
520
+				'capability' => 'ee_send_message',
521
+			],
522
+			'registrations_report'                => [
523
+				'func'       => [$this, '_registrations_report'],
524
+				'noheader'   => true,
525
+				'capability' => 'ee_read_registrations',
526
+			],
527
+			'contact_list_export'                 => [
528
+				'func'       => '_contact_list_export',
529
+				'noheader'   => true,
530
+				'capability' => 'export',
531
+			],
532
+			'contact_list_report'                 => [
533
+				'func'       => '_contact_list_report',
534
+				'noheader'   => true,
535
+				'capability' => 'ee_read_contacts',
536
+			],
537
+		];
538
+	}
539
+
540
+
541
+	protected function _set_page_config()
542
+	{
543
+		$REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
544
+		$ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
545
+		$this->_page_config = [
546
+			'default'           => [
547
+				'nav'           => [
548
+					'label' => esc_html__('Overview', 'event_espresso'),
549
+					'order' => 5,
550
+				],
551
+				'help_tabs'     => [
552
+					'registrations_overview_help_tab'                       => [
553
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
554
+						'filename' => 'registrations_overview',
555
+					],
556
+					'registrations_overview_table_column_headings_help_tab' => [
557
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
558
+						'filename' => 'registrations_overview_table_column_headings',
559
+					],
560
+					'registrations_overview_filters_help_tab'               => [
561
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
562
+						'filename' => 'registrations_overview_filters',
563
+					],
564
+					'registrations_overview_views_help_tab'                 => [
565
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
566
+						'filename' => 'registrations_overview_views',
567
+					],
568
+					'registrations_regoverview_other_help_tab'              => [
569
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
570
+						'filename' => 'registrations_overview_other',
571
+					],
572
+				],
573
+				'qtips'         => ['Registration_List_Table_Tips'],
574
+				'list_table'    => 'EE_Registrations_List_Table',
575
+				'require_nonce' => false,
576
+			],
577
+			'view_registration' => [
578
+				'nav'           => [
579
+					'label'      => esc_html__('REG Details', 'event_espresso'),
580
+					'order'      => 15,
581
+					'url'        => $REG_ID
582
+						? add_query_arg(['_REG_ID' => $REG_ID], $this->_current_page_view_url)
583
+						: $this->_admin_base_url,
584
+					'persistent' => false,
585
+				],
586
+				'help_tabs'     => [
587
+					'registrations_details_help_tab'                    => [
588
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
589
+						'filename' => 'registrations_details',
590
+					],
591
+					'registrations_details_table_help_tab'              => [
592
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
593
+						'filename' => 'registrations_details_table',
594
+					],
595
+					'registrations_details_form_answers_help_tab'       => [
596
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
597
+						'filename' => 'registrations_details_form_answers',
598
+					],
599
+					'registrations_details_registrant_details_help_tab' => [
600
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
601
+						'filename' => 'registrations_details_registrant_details',
602
+					],
603
+				],
604
+				'metaboxes'     => array_merge(
605
+					$this->_default_espresso_metaboxes,
606
+					['_registration_details_metaboxes']
607
+				),
608
+				'require_nonce' => false,
609
+			],
610
+			'new_registration'  => [
611
+				'nav'           => [
612
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
613
+					'url'        => '#',
614
+					'order'      => 15,
615
+					'persistent' => false,
616
+				],
617
+				'metaboxes'     => $this->_default_espresso_metaboxes,
618
+				'labels'        => [
619
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
620
+				],
621
+				'require_nonce' => false,
622
+			],
623
+			'add_new_attendee'  => [
624
+				'nav'           => [
625
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
626
+					'order'      => 15,
627
+					'persistent' => false,
628
+				],
629
+				'metaboxes'     => array_merge(
630
+					$this->_default_espresso_metaboxes,
631
+					['_publish_post_box', 'attendee_editor_metaboxes']
632
+				),
633
+				'require_nonce' => false,
634
+			],
635
+			'edit_attendee'     => [
636
+				'nav'           => [
637
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
638
+					'order'      => 15,
639
+					'persistent' => false,
640
+					'url'        => $ATT_ID
641
+						? add_query_arg(['ATT_ID' => $ATT_ID], $this->_current_page_view_url)
642
+						: $this->_admin_base_url,
643
+				],
644
+				'metaboxes'     => ['attendee_editor_metaboxes'],
645
+				'require_nonce' => false,
646
+			],
647
+			'contact_list'      => [
648
+				'nav'           => [
649
+					'label' => esc_html__('Contact List', 'event_espresso'),
650
+					'order' => 20,
651
+				],
652
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
653
+				'help_tabs'     => [
654
+					'registrations_contact_list_help_tab'                       => [
655
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
656
+						'filename' => 'registrations_contact_list',
657
+					],
658
+					'registrations_contact-list_table_column_headings_help_tab' => [
659
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
660
+						'filename' => 'registrations_contact_list_table_column_headings',
661
+					],
662
+					'registrations_contact_list_views_help_tab'                 => [
663
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
664
+						'filename' => 'registrations_contact_list_views',
665
+					],
666
+					'registrations_contact_list_other_help_tab'                 => [
667
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
668
+						'filename' => 'registrations_contact_list_other',
669
+					],
670
+				],
671
+				'metaboxes'     => [],
672
+				'require_nonce' => false,
673
+			],
674
+			// override default cpt routes
675
+			'create_new'        => '',
676
+			'edit'              => '',
677
+		];
678
+	}
679
+
680
+
681
+	/**
682
+	 * The below methods aren't used by this class currently
683
+	 */
684
+	protected function _add_screen_options()
685
+	{
686
+	}
687
+
688
+
689
+	protected function _add_feature_pointers()
690
+	{
691
+	}
692
+
693
+
694
+	public function admin_init()
695
+	{
696
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
697
+			'click "Update Registration Questions" to save your changes',
698
+			'event_espresso'
699
+		);
700
+	}
701
+
702
+
703
+	public function admin_notices()
704
+	{
705
+	}
706
+
707
+
708
+	public function admin_footer_scripts()
709
+	{
710
+	}
711
+
712
+
713
+	/**
714
+	 * get list of registration statuses
715
+	 *
716
+	 * @return void
717
+	 * @throws EE_Error
718
+	 */
719
+	private function _get_registration_status_array()
720
+	{
721
+		self::$_reg_status = EEM_Registration::reg_status_array([], true);
722
+	}
723
+
724
+
725
+	/**
726
+	 * @throws InvalidArgumentException
727
+	 * @throws InvalidDataTypeException
728
+	 * @throws InvalidInterfaceException
729
+	 * @since 4.10.2.p
730
+	 */
731
+	protected function _add_screen_options_default()
732
+	{
733
+		$this->_per_page_screen_option();
734
+	}
735
+
736
+
737
+	/**
738
+	 * @throws InvalidArgumentException
739
+	 * @throws InvalidDataTypeException
740
+	 * @throws InvalidInterfaceException
741
+	 * @since 4.10.2.p
742
+	 */
743
+	protected function _add_screen_options_contact_list()
744
+	{
745
+		$page_title              = $this->_admin_page_title;
746
+		$this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
747
+		$this->_per_page_screen_option();
748
+		$this->_admin_page_title = $page_title;
749
+	}
750
+
751
+
752
+	public function load_scripts_styles()
753
+	{
754
+		// style
755
+		wp_register_style(
756
+			'espresso_reg',
757
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
758
+			['ee-admin-css'],
759
+			EVENT_ESPRESSO_VERSION
760
+		);
761
+		wp_enqueue_style('espresso_reg');
762
+		// script
763
+		wp_register_script(
764
+			'espresso_reg',
765
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
766
+			['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
767
+			EVENT_ESPRESSO_VERSION,
768
+			true
769
+		);
770
+		wp_enqueue_script('espresso_reg');
771
+	}
772
+
773
+
774
+	/**
775
+	 * @throws EE_Error
776
+	 * @throws InvalidArgumentException
777
+	 * @throws InvalidDataTypeException
778
+	 * @throws InvalidInterfaceException
779
+	 * @throws ReflectionException
780
+	 * @since 4.10.2.p
781
+	 */
782
+	public function load_scripts_styles_edit_attendee()
783
+	{
784
+		// stuff to only show up on our attendee edit details page.
785
+		$attendee_details_translations = [
786
+			'att_publish_text' => sprintf(
787
+			/* translators: The date and time */
788
+				wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
789
+				'<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
790
+			),
791
+		];
792
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
793
+		wp_enqueue_script('jquery-validate');
794
+	}
795
+
796
+
797
+	/**
798
+	 * @throws EE_Error
799
+	 * @throws InvalidArgumentException
800
+	 * @throws InvalidDataTypeException
801
+	 * @throws InvalidInterfaceException
802
+	 * @throws ReflectionException
803
+	 * @since 4.10.2.p
804
+	 */
805
+	public function load_scripts_styles_view_registration()
806
+	{
807
+		// styles
808
+		wp_enqueue_style('espresso-ui-theme');
809
+		// scripts
810
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
811
+		$this->_reg_custom_questions_form->wp_enqueue_scripts();
812
+	}
813
+
814
+
815
+	public function load_scripts_styles_contact_list()
816
+	{
817
+		wp_dequeue_style('espresso_reg');
818
+		wp_register_style(
819
+			'espresso_att',
820
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
821
+			['ee-admin-css'],
822
+			EVENT_ESPRESSO_VERSION
823
+		);
824
+		wp_enqueue_style('espresso_att');
825
+	}
826
+
827
+
828
+	public function load_scripts_styles_new_registration()
829
+	{
830
+		wp_register_script(
831
+			'ee-spco-for-admin',
832
+			REG_ASSETS_URL . 'spco_for_admin.js',
833
+			['underscore', 'jquery'],
834
+			EVENT_ESPRESSO_VERSION,
835
+			true
836
+		);
837
+		wp_enqueue_script('ee-spco-for-admin');
838
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
839
+		EE_Form_Section_Proper::wp_enqueue_scripts();
840
+		EED_Ticket_Selector::load_tckt_slctr_assets();
841
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
842
+	}
843
+
844
+
845
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
846
+	{
847
+		add_filter('FHEE_load_EE_messages', '__return_true');
848
+	}
849
+
850
+
851
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
852
+	{
853
+		add_filter('FHEE_load_EE_messages', '__return_true');
854
+	}
855
+
856
+
857
+	/**
858
+	 * @throws EE_Error
859
+	 * @throws InvalidArgumentException
860
+	 * @throws InvalidDataTypeException
861
+	 * @throws InvalidInterfaceException
862
+	 * @throws ReflectionException
863
+	 * @since 4.10.2.p
864
+	 */
865
+	protected function _set_list_table_views_default()
866
+	{
867
+		// for notification related bulk actions we need to make sure only active messengers have an option.
868
+		EED_Messages::set_autoloaders();
869
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
870
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
871
+		$active_mts               = $message_resource_manager->list_of_active_message_types();
872
+		// key= bulk_action_slug, value= message type.
873
+		$match_array = [
874
+			'approve_registrations'    => 'registration',
875
+			'decline_registrations'    => 'declined_registration',
876
+			'pending_registrations'    => 'pending_approval',
877
+			'no_approve_registrations' => 'not_approved_registration',
878
+			'cancel_registrations'     => 'cancelled_registration',
879
+		];
880
+		$can_send    = EE_Registry::instance()->CAP->current_user_can(
881
+			'ee_send_message',
882
+			'batch_send_messages'
883
+		);
884
+		/** setup reg status bulk actions **/
885
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
886
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
887
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
888
+				'Approve and Notify Registrations',
889
+				'event_espresso'
890
+			);
891
+		}
892
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
893
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
894
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
895
+				'Decline and Notify Registrations',
896
+				'event_espresso'
897
+			);
898
+		}
899
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
900
+			'Set Registrations to Pending Payment',
901
+			'event_espresso'
902
+		);
903
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
904
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
905
+				'Set Registrations to Pending Payment and Notify',
906
+				'event_espresso'
907
+			);
908
+		}
909
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
910
+			'Set Registrations to Not Approved',
911
+			'event_espresso'
912
+		);
913
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
914
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
915
+				'Set Registrations to Not Approved and Notify',
916
+				'event_espresso'
917
+			);
918
+		}
919
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
920
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
921
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
922
+				'Cancel Registrations and Notify',
923
+				'event_espresso'
924
+			);
925
+		}
926
+		$def_reg_status_actions = apply_filters(
927
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
928
+			$def_reg_status_actions,
929
+			$active_mts,
930
+			$can_send
931
+		);
932
+
933
+		$this->_views = [
934
+			'all'   => [
935
+				'slug'        => 'all',
936
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
937
+				'count'       => 0,
938
+				'bulk_action' => array_merge(
939
+					$def_reg_status_actions,
940
+					[
941
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
942
+					]
943
+				),
944
+			],
945
+			'month' => [
946
+				'slug'        => 'month',
947
+				'label'       => esc_html__('This Month', 'event_espresso'),
948
+				'count'       => 0,
949
+				'bulk_action' => array_merge(
950
+					$def_reg_status_actions,
951
+					[
952
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
953
+					]
954
+				),
955
+			],
956
+			'today' => [
957
+				'slug'        => 'today',
958
+				'label'       => sprintf(
959
+					esc_html__('Today - %s', 'event_espresso'),
960
+					date('M d, Y', current_time('timestamp'))
961
+				),
962
+				'count'       => 0,
963
+				'bulk_action' => array_merge(
964
+					$def_reg_status_actions,
965
+					[
966
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
967
+					]
968
+				),
969
+			],
970
+		];
971
+		if (
972
+			EE_Registry::instance()->CAP->current_user_can(
973
+				'ee_delete_registrations',
974
+				'espresso_registrations_delete_registration'
975
+			)
976
+		) {
977
+			$this->_views['incomplete'] = [
978
+				'slug'        => 'incomplete',
979
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
980
+				'count'       => 0,
981
+				'bulk_action' => [
982
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
983
+				],
984
+			];
985
+			$this->_views['trash']      = [
986
+				'slug'        => 'trash',
987
+				'label'       => esc_html__('Trash', 'event_espresso'),
988
+				'count'       => 0,
989
+				'bulk_action' => [
990
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
991
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
992
+				],
993
+			];
994
+		}
995
+	}
996
+
997
+
998
+	protected function _set_list_table_views_contact_list()
999
+	{
1000
+		$this->_views = [
1001
+			'in_use' => [
1002
+				'slug'        => 'in_use',
1003
+				'label'       => esc_html__('In Use', 'event_espresso'),
1004
+				'count'       => 0,
1005
+				'bulk_action' => [
1006
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1007
+				],
1008
+			],
1009
+		];
1010
+		if (
1011
+			EE_Registry::instance()->CAP->current_user_can(
1012
+				'ee_delete_contacts',
1013
+				'espresso_registrations_trash_attendees'
1014
+			)
1015
+		) {
1016
+			$this->_views['trash'] = [
1017
+				'slug'        => 'trash',
1018
+				'label'       => esc_html__('Trash', 'event_espresso'),
1019
+				'count'       => 0,
1020
+				'bulk_action' => [
1021
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1022
+				],
1023
+			];
1024
+		}
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * @return array
1030
+	 * @throws EE_Error
1031
+	 */
1032
+	protected function _registration_legend_items()
1033
+	{
1034
+		$fc_items = [
1035
+			'star-icon'        => [
1036
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1037
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1038
+			],
1039
+			'view_details'     => [
1040
+				'class' => 'dashicons dashicons-clipboard',
1041
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1042
+			],
1043
+			'edit_attendee'    => [
1044
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
1045
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1046
+			],
1047
+			'view_transaction' => [
1048
+				'class' => 'dashicons dashicons-cart',
1049
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1050
+			],
1051
+			'view_invoice'     => [
1052
+				'class' => 'dashicons dashicons-media-spreadsheet',
1053
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1054
+			],
1055
+		];
1056
+		if (
1057
+			EE_Registry::instance()->CAP->current_user_can(
1058
+				'ee_send_message',
1059
+				'espresso_registrations_resend_registration'
1060
+			)
1061
+		) {
1062
+			$fc_items['resend_registration'] = [
1063
+				'class' => 'dashicons dashicons-email-alt',
1064
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1065
+			];
1066
+		} else {
1067
+			$fc_items['blank'] = ['class' => 'blank', 'desc' => ''];
1068
+		}
1069
+		if (
1070
+			EE_Registry::instance()->CAP->current_user_can(
1071
+				'ee_read_global_messages',
1072
+				'view_filtered_messages'
1073
+			)
1074
+		) {
1075
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1076
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1077
+				$fc_items['view_related_messages'] = [
1078
+					'class' => $related_for_icon['css_class'],
1079
+					'desc'  => $related_for_icon['label'],
1080
+				];
1081
+			}
1082
+		}
1083
+		$sc_items = [
1084
+			'approved_status'   => [
1085
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1086
+				'desc'  => EEH_Template::pretty_status(
1087
+					EEM_Registration::status_id_approved,
1088
+					false,
1089
+					'sentence'
1090
+				),
1091
+			],
1092
+			'pending_status'    => [
1093
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1094
+				'desc'  => EEH_Template::pretty_status(
1095
+					EEM_Registration::status_id_pending_payment,
1096
+					false,
1097
+					'sentence'
1098
+				),
1099
+			],
1100
+			'wait_list'         => [
1101
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1102
+				'desc'  => EEH_Template::pretty_status(
1103
+					EEM_Registration::status_id_wait_list,
1104
+					false,
1105
+					'sentence'
1106
+				),
1107
+			],
1108
+			'incomplete_status' => [
1109
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1110
+				'desc'  => EEH_Template::pretty_status(
1111
+					EEM_Registration::status_id_incomplete,
1112
+					false,
1113
+					'sentence'
1114
+				),
1115
+			],
1116
+			'not_approved'      => [
1117
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1118
+				'desc'  => EEH_Template::pretty_status(
1119
+					EEM_Registration::status_id_not_approved,
1120
+					false,
1121
+					'sentence'
1122
+				),
1123
+			],
1124
+			'declined_status'   => [
1125
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1126
+				'desc'  => EEH_Template::pretty_status(
1127
+					EEM_Registration::status_id_declined,
1128
+					false,
1129
+					'sentence'
1130
+				),
1131
+			],
1132
+			'cancelled_status'  => [
1133
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1134
+				'desc'  => EEH_Template::pretty_status(
1135
+					EEM_Registration::status_id_cancelled,
1136
+					false,
1137
+					'sentence'
1138
+				),
1139
+			],
1140
+		];
1141
+		return array_merge($fc_items, $sc_items);
1142
+	}
1143
+
1144
+
1145
+
1146
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1147
+
1148
+
1149
+	/**
1150
+	 * @throws DomainException
1151
+	 * @throws EE_Error
1152
+	 * @throws InvalidArgumentException
1153
+	 * @throws InvalidDataTypeException
1154
+	 * @throws InvalidInterfaceException
1155
+	 */
1156
+	protected function _registrations_overview_list_table()
1157
+	{
1158
+		$this->appendAddNewRegistrationButtonToPageTitle();
1159
+		$header_text                  = '';
1160
+		$admin_page_header_decorators = [
1161
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1162
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1163
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1164
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1165
+		];
1166
+		foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1167
+			$filter_header_decorator = $this->getLoader()->getNew($admin_page_header_decorator);
1168
+			$header_text             = $filter_header_decorator->getHeaderText($header_text);
1169
+		}
1170
+		$this->_template_args['admin_page_header'] = $header_text;
1171
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_registration_legend_items());
1172
+		$this->display_admin_list_table_page_with_no_sidebar();
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * @throws EE_Error
1178
+	 * @throws InvalidArgumentException
1179
+	 * @throws InvalidDataTypeException
1180
+	 * @throws InvalidInterfaceException
1181
+	 */
1182
+	private function appendAddNewRegistrationButtonToPageTitle()
1183
+	{
1184
+		$EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
1185
+		if (
1186
+			$EVT_ID
1187
+			&& EE_Registry::instance()->CAP->current_user_can(
1188
+				'ee_edit_registrations',
1189
+				'espresso_registrations_new_registration',
1190
+				$EVT_ID
1191
+			)
1192
+		) {
1193
+			$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1194
+				'new_registration',
1195
+				'add-registrant',
1196
+				['event_id' => $EVT_ID],
1197
+				'add-new-h2'
1198
+			);
1199
+		}
1200
+	}
1201
+
1202
+
1203
+	/**
1204
+	 * This sets the _registration property for the registration details screen
1205
+	 *
1206
+	 * @return void
1207
+	 * @throws EE_Error
1208
+	 * @throws InvalidArgumentException
1209
+	 * @throws InvalidDataTypeException
1210
+	 * @throws InvalidInterfaceException
1211
+	 */
1212
+	private function _set_registration_object()
1213
+	{
1214
+		// get out if we've already set the object
1215
+		if ($this->_registration instanceof EE_Registration) {
1216
+			return;
1217
+		}
1218
+		$REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
1219
+		if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1220
+			return;
1221
+		}
1222
+		$error_msg = sprintf(
1223
+			esc_html__(
1224
+				'An error occurred and the details for Registration ID #%s could not be retrieved.',
1225
+				'event_espresso'
1226
+			),
1227
+			$REG_ID
1228
+		);
1229
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1230
+		$this->_registration = null;
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 * Used to retrieve registrations for the list table.
1236
+	 *
1237
+	 * @param int  $per_page
1238
+	 * @param bool $count
1239
+	 * @param bool $this_month
1240
+	 * @param bool $today
1241
+	 * @return EE_Registration[]|int
1242
+	 * @throws EE_Error
1243
+	 * @throws InvalidArgumentException
1244
+	 * @throws InvalidDataTypeException
1245
+	 * @throws InvalidInterfaceException
1246
+	 */
1247
+	public function get_registrations(
1248
+		$per_page = 10,
1249
+		$count = false,
1250
+		$this_month = false,
1251
+		$today = false
1252
+	) {
1253
+		if ($this_month) {
1254
+			$this->request->setRequestParam('status', 'month');
1255
+		}
1256
+		if ($today) {
1257
+			$this->request->setRequestParam('status', 'today');
1258
+		}
1259
+		$query_params = $this->_get_registration_query_parameters([], $per_page, $count);
1260
+		/**
1261
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1262
+		 *
1263
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1264
+		 * @see  https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1265
+		 *                      or if you have the development copy of EE you can view this at the path:
1266
+		 *                      /docs/G--Model-System/model-query-params.md
1267
+		 */
1268
+		$query_params['group_by'] = '';
1269
+
1270
+		return $count
1271
+			? $this->getRegistrationModel()->count($query_params)
1272
+			/** @type EE_Registration[] */
1273
+			: $this->getRegistrationModel()->get_all($query_params);
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1279
+	 * Note: this listens to values on the request for some of the query parameters.
1280
+	 *
1281
+	 * @param array $request
1282
+	 * @param int   $per_page
1283
+	 * @param bool  $count
1284
+	 * @return array
1285
+	 * @throws EE_Error
1286
+	 * @throws InvalidArgumentException
1287
+	 * @throws InvalidDataTypeException
1288
+	 * @throws InvalidInterfaceException
1289
+	 */
1290
+	protected function _get_registration_query_parameters(
1291
+		$request = [],
1292
+		$per_page = 10,
1293
+		$count = false
1294
+	) {
1295
+		/** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1296
+		$list_table_query_builder = $this->getLoader()->getNew(
1297
+			'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1298
+			[null, null, $request]
1299
+		);
1300
+		return $list_table_query_builder->getQueryParams($per_page, $count);
1301
+	}
1302
+
1303
+
1304
+	public function get_registration_status_array()
1305
+	{
1306
+		return self::$_reg_status;
1307
+	}
1308
+
1309
+
1310
+
1311
+
1312
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1313
+	/**
1314
+	 * generates HTML for the View Registration Details Admin page
1315
+	 *
1316
+	 * @return void
1317
+	 * @throws DomainException
1318
+	 * @throws EE_Error
1319
+	 * @throws InvalidArgumentException
1320
+	 * @throws InvalidDataTypeException
1321
+	 * @throws InvalidInterfaceException
1322
+	 * @throws EntityNotFoundException
1323
+	 * @throws ReflectionException
1324
+	 */
1325
+	protected function _registration_details()
1326
+	{
1327
+		$this->_template_args = [];
1328
+		$this->_set_registration_object();
1329
+		if (is_object($this->_registration)) {
1330
+			$transaction                                   = $this->_registration->transaction()
1331
+				? $this->_registration->transaction()
1332
+				: EE_Transaction::new_instance();
1333
+			$this->_session                                = $transaction->session_data();
1334
+			$event_id                                      = $this->_registration->event_ID();
1335
+			$this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1336
+			$this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1337
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1338
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1339
+			$this->_template_args['grand_total']           = $transaction->total();
1340
+			$this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1341
+			// link back to overview
1342
+			$this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1343
+			$this->_template_args['registration']                = $this->_registration;
1344
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1345
+				[
1346
+					'action'   => 'default',
1347
+					'event_id' => $event_id,
1348
+				],
1349
+				REG_ADMIN_URL
1350
+			);
1351
+			$this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1352
+				[
1353
+					'action' => 'default',
1354
+					'EVT_ID' => $event_id,
1355
+					'page'   => 'espresso_transactions',
1356
+				],
1357
+				admin_url('admin.php')
1358
+			);
1359
+			$this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1360
+				[
1361
+					'page'   => 'espresso_events',
1362
+					'action' => 'edit',
1363
+					'post'   => $event_id,
1364
+				],
1365
+				admin_url('admin.php')
1366
+			);
1367
+			// next and previous links
1368
+			$next_reg                                      = $this->_registration->next(
1369
+				null,
1370
+				[],
1371
+				'REG_ID'
1372
+			);
1373
+			$this->_template_args['next_registration']     = $next_reg
1374
+				? $this->_next_link(
1375
+					EE_Admin_Page::add_query_args_and_nonce(
1376
+						[
1377
+							'action'  => 'view_registration',
1378
+							'_REG_ID' => $next_reg['REG_ID'],
1379
+						],
1380
+						REG_ADMIN_URL
1381
+					),
1382
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1383
+				)
1384
+				: '';
1385
+			$previous_reg                                  = $this->_registration->previous(
1386
+				null,
1387
+				[],
1388
+				'REG_ID'
1389
+			);
1390
+			$this->_template_args['previous_registration'] = $previous_reg
1391
+				? $this->_previous_link(
1392
+					EE_Admin_Page::add_query_args_and_nonce(
1393
+						[
1394
+							'action'  => 'view_registration',
1395
+							'_REG_ID' => $previous_reg['REG_ID'],
1396
+						],
1397
+						REG_ADMIN_URL
1398
+					),
1399
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1400
+				)
1401
+				: '';
1402
+			// grab header
1403
+			$template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1404
+			$this->_template_args['REG_ID']            = $this->_registration->ID();
1405
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1406
+				$template_path,
1407
+				$this->_template_args,
1408
+				true
1409
+			);
1410
+		} else {
1411
+			$this->_template_args['admin_page_header'] = '';
1412
+			$this->_display_espresso_notices();
1413
+		}
1414
+		// the details template wrapper
1415
+		$this->display_admin_page_with_sidebar();
1416
+	}
1417
+
1418
+
1419
+	/**
1420
+	 * @throws EE_Error
1421
+	 * @throws InvalidArgumentException
1422
+	 * @throws InvalidDataTypeException
1423
+	 * @throws InvalidInterfaceException
1424
+	 * @throws ReflectionException
1425
+	 * @since 4.10.2.p
1426
+	 */
1427
+	protected function _registration_details_metaboxes()
1428
+	{
1429
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1430
+		$this->_set_registration_object();
1431
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1432
+		add_meta_box(
1433
+			'edit-reg-status-mbox',
1434
+			esc_html__('Registration Status', 'event_espresso'),
1435
+			[$this, 'set_reg_status_buttons_metabox'],
1436
+			$this->_wp_page_slug,
1437
+			'normal',
1438
+			'high'
1439
+		);
1440
+		add_meta_box(
1441
+			'edit-reg-details-mbox',
1442
+			esc_html__('Registration Details', 'event_espresso'),
1443
+			[$this, '_reg_details_meta_box'],
1444
+			$this->_wp_page_slug,
1445
+			'normal',
1446
+			'high'
1447
+		);
1448
+		if (
1449
+			$attendee instanceof EE_Attendee
1450
+			&& EE_Registry::instance()->CAP->current_user_can(
1451
+				'ee_read_registration',
1452
+				'edit-reg-questions-mbox',
1453
+				$this->_registration->ID()
1454
+			)
1455
+		) {
1456
+			add_meta_box(
1457
+				'edit-reg-questions-mbox',
1458
+				esc_html__('Registration Form Answers', 'event_espresso'),
1459
+				[$this, '_reg_questions_meta_box'],
1460
+				$this->_wp_page_slug,
1461
+				'normal',
1462
+				'high'
1463
+			);
1464
+		}
1465
+		add_meta_box(
1466
+			'edit-reg-registrant-mbox',
1467
+			esc_html__('Contact Details', 'event_espresso'),
1468
+			[$this, '_reg_registrant_side_meta_box'],
1469
+			$this->_wp_page_slug,
1470
+			'side',
1471
+			'high'
1472
+		);
1473
+		if ($this->_registration->group_size() > 1) {
1474
+			add_meta_box(
1475
+				'edit-reg-attendees-mbox',
1476
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1477
+				[$this, '_reg_attendees_meta_box'],
1478
+				$this->_wp_page_slug,
1479
+				'normal',
1480
+				'high'
1481
+			);
1482
+		}
1483
+	}
1484
+
1485
+
1486
+	/**
1487
+	 * set_reg_status_buttons_metabox
1488
+	 *
1489
+	 * @return void
1490
+	 * @throws EE_Error
1491
+	 * @throws EntityNotFoundException
1492
+	 * @throws InvalidArgumentException
1493
+	 * @throws InvalidDataTypeException
1494
+	 * @throws InvalidInterfaceException
1495
+	 * @throws ReflectionException
1496
+	 */
1497
+	public function set_reg_status_buttons_metabox()
1498
+	{
1499
+		$this->_set_registration_object();
1500
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1501
+		$output                 = $change_reg_status_form->form_open(
1502
+			self::add_query_args_and_nonce(
1503
+				[
1504
+					'action' => 'change_reg_status',
1505
+				],
1506
+				REG_ADMIN_URL
1507
+			)
1508
+		);
1509
+		$output                 .= $change_reg_status_form->get_html();
1510
+		$output                 .= $change_reg_status_form->form_close();
1511
+		echo wp_kses($output, AllowedTags::getWithFormTags());
1512
+	}
1513
+
1514
+
1515
+	/**
1516
+	 * @return EE_Form_Section_Proper
1517
+	 * @throws EE_Error
1518
+	 * @throws InvalidArgumentException
1519
+	 * @throws InvalidDataTypeException
1520
+	 * @throws InvalidInterfaceException
1521
+	 * @throws EntityNotFoundException
1522
+	 * @throws ReflectionException
1523
+	 */
1524
+	protected function _generate_reg_status_change_form()
1525
+	{
1526
+		$reg_status_change_form_array = [
1527
+			'name'            => 'reg_status_change_form',
1528
+			'html_id'         => 'reg-status-change-form',
1529
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1530
+			'subsections'     => [
1531
+				'return'         => new EE_Hidden_Input(
1532
+					[
1533
+						'name'    => 'return',
1534
+						'default' => 'view_registration',
1535
+					]
1536
+				),
1537
+				'REG_ID'         => new EE_Hidden_Input(
1538
+					[
1539
+						'name'    => 'REG_ID',
1540
+						'default' => $this->_registration->ID(),
1541
+					]
1542
+				),
1543
+				'current_status' => new EE_Form_Section_HTML(
1544
+					EEH_HTML::table(
1545
+						EEH_HTML::tr(
1546
+							EEH_HTML::th(
1547
+								EEH_HTML::label(
1548
+									EEH_HTML::strong(
1549
+										esc_html__('Current Registration Status', 'event_espresso')
1550
+									)
1551
+								)
1552
+							)
1553
+							. EEH_HTML::td(
1554
+								EEH_HTML::strong(
1555
+									$this->_registration->pretty_status(),
1556
+									'',
1557
+									'status-' . $this->_registration->status_ID(),
1558
+									'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1559
+								)
1560
+							)
1561
+						)
1562
+					)
1563
+				),
1564
+			],
1565
+		];
1566
+		if (
1567
+			EE_Registry::instance()->CAP->current_user_can(
1568
+				'ee_edit_registration',
1569
+				'toggle_registration_status',
1570
+				$this->_registration->ID()
1571
+			)
1572
+		) {
1573
+			$reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1574
+				$this->_get_reg_statuses(),
1575
+				[
1576
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1577
+					'default'         => $this->_registration->status_ID(),
1578
+				]
1579
+			);
1580
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1581
+				[
1582
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1583
+					'default'         => false,
1584
+					'html_help_text'  => esc_html__(
1585
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1586
+						'event_espresso'
1587
+					),
1588
+				]
1589
+			);
1590
+			$reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1591
+				[
1592
+					'html_class'      => 'button-primary',
1593
+					'html_label_text' => '&nbsp;',
1594
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1595
+				]
1596
+			);
1597
+		}
1598
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1599
+	}
1600
+
1601
+
1602
+	/**
1603
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1604
+	 *
1605
+	 * @return array
1606
+	 * @throws EE_Error
1607
+	 * @throws InvalidArgumentException
1608
+	 * @throws InvalidDataTypeException
1609
+	 * @throws InvalidInterfaceException
1610
+	 * @throws EntityNotFoundException
1611
+	 */
1612
+	protected function _get_reg_statuses()
1613
+	{
1614
+		$reg_status_array = $this->getRegistrationModel()->reg_status_array();
1615
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1616
+		// get current reg status
1617
+		$current_status = $this->_registration->status_ID();
1618
+		// is registration for free event? This will determine whether to display the pending payment option
1619
+		if (
1620
+			$current_status !== EEM_Registration::status_id_pending_payment
1621
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1622
+		) {
1623
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1624
+		}
1625
+		return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1626
+	}
1627
+
1628
+
1629
+	/**
1630
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1631
+	 *
1632
+	 * @param bool $status REG status given for changing registrations to.
1633
+	 * @param bool $notify Whether to send messages notifications or not.
1634
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1635
+	 * @throws DomainException
1636
+	 * @throws EE_Error
1637
+	 * @throws EntityNotFoundException
1638
+	 * @throws InvalidArgumentException
1639
+	 * @throws InvalidDataTypeException
1640
+	 * @throws InvalidInterfaceException
1641
+	 * @throws ReflectionException
1642
+	 * @throws RuntimeException
1643
+	 */
1644
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1645
+	{
1646
+		$REG_IDs = $this->request->requestParamIsSet('reg_status_change_form')
1647
+			? $this->request->getRequestParam('reg_status_change_form[REG_ID]', [], 'int', true)
1648
+			: $this->request->getRequestParam('_REG_ID', [], 'int', true);
1649
+
1650
+		// sanitize $REG_IDs
1651
+		$REG_IDs = array_map('absint', $REG_IDs);
1652
+		// and remove empty entries
1653
+		$REG_IDs = array_filter($REG_IDs);
1654
+
1655
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1656
+
1657
+		/**
1658
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1659
+		 * Currently this value is used downstream by the _process_resend_registration method.
1660
+		 *
1661
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1662
+		 * @param bool                     $status           The status registrations were changed to.
1663
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1664
+		 * @param Registrations_Admin_Page $admin_page_object
1665
+		 */
1666
+		$REG_ID = apply_filters(
1667
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1668
+			$result['REG_ID'],
1669
+			$status,
1670
+			$result['success'],
1671
+			$this
1672
+		);
1673
+		$this->request->setRequestParam('_REG_ID', $REG_ID);
1674
+
1675
+		// notify?
1676
+		if (
1677
+			$notify
1678
+			&& $result['success']
1679
+			&& ! empty($REG_ID)
1680
+			&& EE_Registry::instance()->CAP->current_user_can(
1681
+				'ee_send_message',
1682
+				'espresso_registrations_resend_registration'
1683
+			)
1684
+		) {
1685
+			$this->_process_resend_registration();
1686
+		}
1687
+		return $result;
1688
+	}
1689
+
1690
+
1691
+	/**
1692
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1693
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1694
+	 *
1695
+	 * @param array  $REG_IDs
1696
+	 * @param string $status
1697
+	 * @param bool   $notify Used to indicate whether notification was requested or not.  This determines the context
1698
+	 *                       slug sent with setting the registration status.
1699
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1700
+	 * @throws EE_Error
1701
+	 * @throws InvalidArgumentException
1702
+	 * @throws InvalidDataTypeException
1703
+	 * @throws InvalidInterfaceException
1704
+	 * @throws ReflectionException
1705
+	 * @throws RuntimeException
1706
+	 * @throws EntityNotFoundException
1707
+	 * @throws DomainException
1708
+	 */
1709
+	protected function _set_registration_status($REG_IDs = [], $status = '', $notify = false)
1710
+	{
1711
+		$success = false;
1712
+		// typecast $REG_IDs
1713
+		$REG_IDs = (array) $REG_IDs;
1714
+		if (! empty($REG_IDs)) {
1715
+			$success = true;
1716
+			// set default status if none is passed
1717
+			$status         = $status ?: EEM_Registration::status_id_pending_payment;
1718
+			$status_context = $notify
1719
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1720
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1721
+			// loop through REG_ID's and change status
1722
+			foreach ($REG_IDs as $REG_ID) {
1723
+				$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1724
+				if ($registration instanceof EE_Registration) {
1725
+					$registration->set_status(
1726
+						$status,
1727
+						false,
1728
+						new Context(
1729
+							$status_context,
1730
+							esc_html__(
1731
+								'Manually triggered status change on a Registration Admin Page route.',
1732
+								'event_espresso'
1733
+							)
1734
+						)
1735
+					);
1736
+					$result = $registration->save();
1737
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1738
+					$success = $result !== false ? $success : false;
1739
+				}
1740
+			}
1741
+		}
1742
+
1743
+		// return $success and processed registrations
1744
+		return ['REG_ID' => $REG_IDs, 'success' => $success];
1745
+	}
1746
+
1747
+
1748
+	/**
1749
+	 * Common logic for setting up success message and redirecting to appropriate route
1750
+	 *
1751
+	 * @param string $STS_ID status id for the registration changed to
1752
+	 * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1753
+	 * @return void
1754
+	 * @throws DomainException
1755
+	 * @throws EE_Error
1756
+	 * @throws EntityNotFoundException
1757
+	 * @throws InvalidArgumentException
1758
+	 * @throws InvalidDataTypeException
1759
+	 * @throws InvalidInterfaceException
1760
+	 * @throws ReflectionException
1761
+	 * @throws RuntimeException
1762
+	 */
1763
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1764
+	{
1765
+		$result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1766
+			: ['success' => false];
1767
+		$success = isset($result['success']) && $result['success'];
1768
+		// setup success message
1769
+		if ($success) {
1770
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1771
+				$msg = sprintf(
1772
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1773
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1774
+				);
1775
+			} else {
1776
+				$msg = sprintf(
1777
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1778
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1779
+				);
1780
+			}
1781
+			EE_Error::add_success($msg);
1782
+		} else {
1783
+			EE_Error::add_error(
1784
+				esc_html__(
1785
+					'Something went wrong, and the status was not changed',
1786
+					'event_espresso'
1787
+				),
1788
+				__FILE__,
1789
+				__LINE__,
1790
+				__FUNCTION__
1791
+			);
1792
+		}
1793
+		$return = $this->request->getRequestParam('return');
1794
+		$route  = $return === 'view_registration'
1795
+			? ['action' => 'view_registration', '_REG_ID' => reset($result['REG_ID'])]
1796
+			: ['action' => 'default'];
1797
+		$route  = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1798
+		$this->_redirect_after_action($success, '', '', $route, true);
1799
+	}
1800
+
1801
+
1802
+	/**
1803
+	 * incoming reg status change from reg details page.
1804
+	 *
1805
+	 * @return void
1806
+	 * @throws EE_Error
1807
+	 * @throws EntityNotFoundException
1808
+	 * @throws InvalidArgumentException
1809
+	 * @throws InvalidDataTypeException
1810
+	 * @throws InvalidInterfaceException
1811
+	 * @throws ReflectionException
1812
+	 * @throws RuntimeException
1813
+	 * @throws DomainException
1814
+	 */
1815
+	protected function _change_reg_status()
1816
+	{
1817
+		$this->request->setRequestParam('return', 'view_registration');
1818
+		// set notify based on whether the send notifications toggle is set or not
1819
+		$notify     = $this->request->getRequestParam('reg_status_change_form[send_notifications]', false, 'bool');
1820
+		$reg_status = $this->request->getRequestParam('reg_status_change_form[reg_status]', '');
1821
+		$this->request->setRequestParam('reg_status_change_form[reg_status]', $reg_status);
1822
+		switch ($reg_status) {
1823
+			case EEM_Registration::status_id_approved:
1824
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1825
+				$this->approve_registration($notify);
1826
+				break;
1827
+			case EEM_Registration::status_id_pending_payment:
1828
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1829
+				$this->pending_registration($notify);
1830
+				break;
1831
+			case EEM_Registration::status_id_not_approved:
1832
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1833
+				$this->not_approve_registration($notify);
1834
+				break;
1835
+			case EEM_Registration::status_id_declined:
1836
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1837
+				$this->decline_registration($notify);
1838
+				break;
1839
+			case EEM_Registration::status_id_cancelled:
1840
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1841
+				$this->cancel_registration($notify);
1842
+				break;
1843
+			case EEM_Registration::status_id_wait_list:
1844
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1845
+				$this->wait_list_registration($notify);
1846
+				break;
1847
+			case EEM_Registration::status_id_incomplete:
1848
+			default:
1849
+				$this->request->unSetRequestParam('return');
1850
+				$this->_reg_status_change_return('');
1851
+				break;
1852
+		}
1853
+	}
1854
+
1855
+
1856
+	/**
1857
+	 * Callback for bulk action routes.
1858
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1859
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
1860
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1861
+	 * when an action is happening on just a single registration).
1862
+	 *
1863
+	 * @param      $action
1864
+	 * @param bool $notify
1865
+	 */
1866
+	protected function bulk_action_on_registrations($action, $notify = false)
1867
+	{
1868
+		do_action(
1869
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1870
+			$this,
1871
+			$action,
1872
+			$notify
1873
+		);
1874
+		$method = $action . '_registration';
1875
+		if (method_exists($this, $method)) {
1876
+			$this->$method($notify);
1877
+		}
1878
+	}
1879
+
1880
+
1881
+	/**
1882
+	 * approve_registration
1883
+	 *
1884
+	 * @param bool $notify whether or not to notify the registrant about their approval.
1885
+	 * @return void
1886
+	 * @throws EE_Error
1887
+	 * @throws EntityNotFoundException
1888
+	 * @throws InvalidArgumentException
1889
+	 * @throws InvalidDataTypeException
1890
+	 * @throws InvalidInterfaceException
1891
+	 * @throws ReflectionException
1892
+	 * @throws RuntimeException
1893
+	 * @throws DomainException
1894
+	 */
1895
+	protected function approve_registration($notify = false)
1896
+	{
1897
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1898
+	}
1899
+
1900
+
1901
+	/**
1902
+	 * decline_registration
1903
+	 *
1904
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1905
+	 * @return void
1906
+	 * @throws EE_Error
1907
+	 * @throws EntityNotFoundException
1908
+	 * @throws InvalidArgumentException
1909
+	 * @throws InvalidDataTypeException
1910
+	 * @throws InvalidInterfaceException
1911
+	 * @throws ReflectionException
1912
+	 * @throws RuntimeException
1913
+	 * @throws DomainException
1914
+	 */
1915
+	protected function decline_registration($notify = false)
1916
+	{
1917
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1918
+	}
1919
+
1920
+
1921
+	/**
1922
+	 * cancel_registration
1923
+	 *
1924
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1925
+	 * @return void
1926
+	 * @throws EE_Error
1927
+	 * @throws EntityNotFoundException
1928
+	 * @throws InvalidArgumentException
1929
+	 * @throws InvalidDataTypeException
1930
+	 * @throws InvalidInterfaceException
1931
+	 * @throws ReflectionException
1932
+	 * @throws RuntimeException
1933
+	 * @throws DomainException
1934
+	 */
1935
+	protected function cancel_registration($notify = false)
1936
+	{
1937
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1938
+	}
1939
+
1940
+
1941
+	/**
1942
+	 * not_approve_registration
1943
+	 *
1944
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1945
+	 * @return void
1946
+	 * @throws EE_Error
1947
+	 * @throws EntityNotFoundException
1948
+	 * @throws InvalidArgumentException
1949
+	 * @throws InvalidDataTypeException
1950
+	 * @throws InvalidInterfaceException
1951
+	 * @throws ReflectionException
1952
+	 * @throws RuntimeException
1953
+	 * @throws DomainException
1954
+	 */
1955
+	protected function not_approve_registration($notify = false)
1956
+	{
1957
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1958
+	}
1959
+
1960
+
1961
+	/**
1962
+	 * decline_registration
1963
+	 *
1964
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1965
+	 * @return void
1966
+	 * @throws EE_Error
1967
+	 * @throws EntityNotFoundException
1968
+	 * @throws InvalidArgumentException
1969
+	 * @throws InvalidDataTypeException
1970
+	 * @throws InvalidInterfaceException
1971
+	 * @throws ReflectionException
1972
+	 * @throws RuntimeException
1973
+	 * @throws DomainException
1974
+	 */
1975
+	protected function pending_registration($notify = false)
1976
+	{
1977
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1978
+	}
1979
+
1980
+
1981
+	/**
1982
+	 * waitlist_registration
1983
+	 *
1984
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1985
+	 * @return void
1986
+	 * @throws EE_Error
1987
+	 * @throws EntityNotFoundException
1988
+	 * @throws InvalidArgumentException
1989
+	 * @throws InvalidDataTypeException
1990
+	 * @throws InvalidInterfaceException
1991
+	 * @throws ReflectionException
1992
+	 * @throws RuntimeException
1993
+	 * @throws DomainException
1994
+	 */
1995
+	protected function wait_list_registration($notify = false)
1996
+	{
1997
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1998
+	}
1999
+
2000
+
2001
+	/**
2002
+	 * generates HTML for the Registration main meta box
2003
+	 *
2004
+	 * @return void
2005
+	 * @throws DomainException
2006
+	 * @throws EE_Error
2007
+	 * @throws InvalidArgumentException
2008
+	 * @throws InvalidDataTypeException
2009
+	 * @throws InvalidInterfaceException
2010
+	 * @throws ReflectionException
2011
+	 * @throws EntityNotFoundException
2012
+	 */
2013
+	public function _reg_details_meta_box()
2014
+	{
2015
+		EEH_Autoloader::register_line_item_display_autoloaders();
2016
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2017
+		EE_Registry::instance()->load_helper('Line_Item');
2018
+		$transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
2019
+			: EE_Transaction::new_instance();
2020
+		$this->_session = $transaction->session_data();
2021
+		$filters        = new EE_Line_Item_Filter_Collection();
2022
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2023
+		$filters->add(new EE_Non_Zero_Line_Item_Filter());
2024
+		$line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
2025
+			$filters,
2026
+			$transaction->total_line_item()
2027
+		);
2028
+		$filtered_line_item_tree                 = $line_item_filter_processor->process();
2029
+		$line_item_display                       = new EE_Line_Item_Display(
2030
+			'reg_admin_table',
2031
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2032
+		);
2033
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2034
+			$filtered_line_item_tree,
2035
+			['EE_Registration' => $this->_registration]
2036
+		);
2037
+		$attendee                                = $this->_registration->attendee();
2038
+		if (
2039
+			EE_Registry::instance()->CAP->current_user_can(
2040
+				'ee_read_transaction',
2041
+				'espresso_transactions_view_transaction'
2042
+			)
2043
+		) {
2044
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2045
+				EE_Admin_Page::add_query_args_and_nonce(
2046
+					[
2047
+						'action' => 'view_transaction',
2048
+						'TXN_ID' => $transaction->ID(),
2049
+					],
2050
+					TXN_ADMIN_URL
2051
+				),
2052
+				esc_html__(' View Transaction', 'event_espresso'),
2053
+				'button secondary-button right',
2054
+				'dashicons dashicons-cart'
2055
+			);
2056
+		} else {
2057
+			$this->_template_args['view_transaction_button'] = '';
2058
+		}
2059
+		if (
2060
+			$attendee instanceof EE_Attendee
2061
+			&& EE_Registry::instance()->CAP->current_user_can(
2062
+				'ee_send_message',
2063
+				'espresso_registrations_resend_registration'
2064
+			)
2065
+		) {
2066
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2067
+				EE_Admin_Page::add_query_args_and_nonce(
2068
+					[
2069
+						'action'      => 'resend_registration',
2070
+						'_REG_ID'     => $this->_registration->ID(),
2071
+						'redirect_to' => 'view_registration',
2072
+					],
2073
+					REG_ADMIN_URL
2074
+				),
2075
+				esc_html__(' Resend Registration', 'event_espresso'),
2076
+				'button secondary-button right',
2077
+				'dashicons dashicons-email-alt'
2078
+			);
2079
+		} else {
2080
+			$this->_template_args['resend_registration_button'] = '';
2081
+		}
2082
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2083
+		$payment                               = $transaction->get_first_related('Payment');
2084
+		$payment                               = ! $payment instanceof EE_Payment
2085
+			? EE_Payment::new_instance()
2086
+			: $payment;
2087
+		$payment_method                        = $payment->get_first_related('Payment_Method');
2088
+		$payment_method                        = ! $payment_method instanceof EE_Payment_Method
2089
+			? EE_Payment_Method::new_instance()
2090
+			: $payment_method;
2091
+		$reg_details                           = [
2092
+			'payment_method'       => $payment_method->name(),
2093
+			'response_msg'         => $payment->gateway_response(),
2094
+			'registration_id'      => $this->_registration->get('REG_code'),
2095
+			'registration_session' => $this->_registration->session_ID(),
2096
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2097
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2098
+		];
2099
+		if (isset($reg_details['registration_id'])) {
2100
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2101
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2102
+				'Registration ID',
2103
+				'event_espresso'
2104
+			);
2105
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2106
+		}
2107
+		if (isset($reg_details['payment_method'])) {
2108
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2109
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2110
+				'Most Recent Payment Method',
2111
+				'event_espresso'
2112
+			);
2113
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2114
+			$this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2115
+			$this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2116
+				'Payment method response',
2117
+				'event_espresso'
2118
+			);
2119
+			$this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2120
+		}
2121
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2122
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2123
+			'Registration Session',
2124
+			'event_espresso'
2125
+		);
2126
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2127
+		$this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2128
+		$this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2129
+			'Registration placed from IP',
2130
+			'event_espresso'
2131
+		);
2132
+		$this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2133
+		$this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2134
+		$this->_template_args['reg_details']['user_agent']['label']           = esc_html__(
2135
+			'Registrant User Agent',
2136
+			'event_espresso'
2137
+		);
2138
+		$this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2139
+		$this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2140
+			[
2141
+				'action'   => 'default',
2142
+				'event_id' => $this->_registration->event_ID(),
2143
+			],
2144
+			REG_ADMIN_URL
2145
+		);
2146
+		$this->_template_args['REG_ID']                                       = $this->_registration->ID();
2147
+		$this->_template_args['event_id']                                     = $this->_registration->event_ID();
2148
+		$template_path                                                        =
2149
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2150
+		EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2151
+	}
2152
+
2153
+
2154
+	/**
2155
+	 * generates HTML for the Registration Questions meta box.
2156
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2157
+	 * otherwise uses new forms system
2158
+	 *
2159
+	 * @return void
2160
+	 * @throws DomainException
2161
+	 * @throws EE_Error
2162
+	 * @throws InvalidArgumentException
2163
+	 * @throws InvalidDataTypeException
2164
+	 * @throws InvalidInterfaceException
2165
+	 * @throws ReflectionException
2166
+	 */
2167
+	public function _reg_questions_meta_box()
2168
+	{
2169
+		// allow someone to override this method entirely
2170
+		if (
2171
+			apply_filters(
2172
+				'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2173
+				true,
2174
+				$this,
2175
+				$this->_registration
2176
+			)
2177
+		) {
2178
+			$form                                              = $this->_get_reg_custom_questions_form(
2179
+				$this->_registration->ID()
2180
+			);
2181
+			$this->_template_args['att_questions']             = count($form->subforms()) > 0
2182
+				? $form->get_html_and_js()
2183
+				: '';
2184
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2185
+			$this->_template_args['REG_ID']                    = $this->_registration->ID();
2186
+			$template_path                                     =
2187
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2188
+			EEH_Template::display_template($template_path, $this->_template_args);
2189
+		}
2190
+	}
2191
+
2192
+
2193
+	/**
2194
+	 * form_before_question_group
2195
+	 *
2196
+	 * @param string $output
2197
+	 * @return        string
2198
+	 * @deprecated    as of 4.8.32.rc.000
2199
+	 */
2200
+	public function form_before_question_group($output)
2201
+	{
2202
+		EE_Error::doing_it_wrong(
2203
+			__CLASS__ . '::' . __FUNCTION__,
2204
+			esc_html__(
2205
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2206
+				'event_espresso'
2207
+			),
2208
+			'4.8.32.rc.000'
2209
+		);
2210
+		return '
2211 2211
 	<table class="form-table ee-width-100">
2212 2212
 		<tbody>
2213 2213
 			';
2214
-    }
2215
-
2216
-
2217
-    /**
2218
-     * form_after_question_group
2219
-     *
2220
-     * @param string $output
2221
-     * @return        string
2222
-     * @deprecated    as of 4.8.32.rc.000
2223
-     */
2224
-    public function form_after_question_group($output)
2225
-    {
2226
-        EE_Error::doing_it_wrong(
2227
-            __CLASS__ . '::' . __FUNCTION__,
2228
-            esc_html__(
2229
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2230
-                'event_espresso'
2231
-            ),
2232
-            '4.8.32.rc.000'
2233
-        );
2234
-        return '
2214
+	}
2215
+
2216
+
2217
+	/**
2218
+	 * form_after_question_group
2219
+	 *
2220
+	 * @param string $output
2221
+	 * @return        string
2222
+	 * @deprecated    as of 4.8.32.rc.000
2223
+	 */
2224
+	public function form_after_question_group($output)
2225
+	{
2226
+		EE_Error::doing_it_wrong(
2227
+			__CLASS__ . '::' . __FUNCTION__,
2228
+			esc_html__(
2229
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2230
+				'event_espresso'
2231
+			),
2232
+			'4.8.32.rc.000'
2233
+		);
2234
+		return '
2235 2235
 			<tr class="hide-if-no-js">
2236 2236
 				<th> </th>
2237 2237
 				<td class="reg-admin-edit-attendee-question-td">
2238 2238
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2239
-               . esc_attr__('click to edit question', 'event_espresso')
2240
-               . '">
2239
+			   . esc_attr__('click to edit question', 'event_espresso')
2240
+			   . '">
2241 2241
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2242
-               . esc_html__('edit the above question group', 'event_espresso')
2243
-               . '</span>
2242
+			   . esc_html__('edit the above question group', 'event_espresso')
2243
+			   . '</span>
2244 2244
 						<div class="dashicons dashicons-edit"></div>
2245 2245
 					</a>
2246 2246
 				</td>
@@ -2248,641 +2248,641 @@  discard block
 block discarded – undo
2248 2248
 		</tbody>
2249 2249
 	</table>
2250 2250
 ';
2251
-    }
2252
-
2253
-
2254
-    /**
2255
-     * form_form_field_label_wrap
2256
-     *
2257
-     * @param string $label
2258
-     * @return        string
2259
-     * @deprecated    as of 4.8.32.rc.000
2260
-     */
2261
-    public function form_form_field_label_wrap($label)
2262
-    {
2263
-        EE_Error::doing_it_wrong(
2264
-            __CLASS__ . '::' . __FUNCTION__,
2265
-            esc_html__(
2266
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2267
-                'event_espresso'
2268
-            ),
2269
-            '4.8.32.rc.000'
2270
-        );
2271
-        return '
2251
+	}
2252
+
2253
+
2254
+	/**
2255
+	 * form_form_field_label_wrap
2256
+	 *
2257
+	 * @param string $label
2258
+	 * @return        string
2259
+	 * @deprecated    as of 4.8.32.rc.000
2260
+	 */
2261
+	public function form_form_field_label_wrap($label)
2262
+	{
2263
+		EE_Error::doing_it_wrong(
2264
+			__CLASS__ . '::' . __FUNCTION__,
2265
+			esc_html__(
2266
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2267
+				'event_espresso'
2268
+			),
2269
+			'4.8.32.rc.000'
2270
+		);
2271
+		return '
2272 2272
 			<tr>
2273 2273
 				<th>
2274 2274
 					' . $label . '
2275 2275
 				</th>';
2276
-    }
2277
-
2278
-
2279
-    /**
2280
-     * form_form_field_input__wrap
2281
-     *
2282
-     * @param string $input
2283
-     * @return        string
2284
-     * @deprecated    as of 4.8.32.rc.000
2285
-     */
2286
-    public function form_form_field_input__wrap($input)
2287
-    {
2288
-        EE_Error::doing_it_wrong(
2289
-            __CLASS__ . '::' . __FUNCTION__,
2290
-            esc_html__(
2291
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2292
-                'event_espresso'
2293
-            ),
2294
-            '4.8.32.rc.000'
2295
-        );
2296
-        return '
2276
+	}
2277
+
2278
+
2279
+	/**
2280
+	 * form_form_field_input__wrap
2281
+	 *
2282
+	 * @param string $input
2283
+	 * @return        string
2284
+	 * @deprecated    as of 4.8.32.rc.000
2285
+	 */
2286
+	public function form_form_field_input__wrap($input)
2287
+	{
2288
+		EE_Error::doing_it_wrong(
2289
+			__CLASS__ . '::' . __FUNCTION__,
2290
+			esc_html__(
2291
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2292
+				'event_espresso'
2293
+			),
2294
+			'4.8.32.rc.000'
2295
+		);
2296
+		return '
2297 2297
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2298 2298
 					' . $input . '
2299 2299
 				</td>
2300 2300
 			</tr>';
2301
-    }
2302
-
2303
-
2304
-    /**
2305
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2306
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2307
-     * to display the page
2308
-     *
2309
-     * @return void
2310
-     * @throws EE_Error
2311
-     * @throws InvalidArgumentException
2312
-     * @throws InvalidDataTypeException
2313
-     * @throws InvalidInterfaceException
2314
-     * @throws ReflectionException
2315
-     */
2316
-    protected function _update_attendee_registration_form()
2317
-    {
2318
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2319
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2320
-            $REG_ID  = $this->request->getRequestParam('_REG_ID', 0, 'int');
2321
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2322
-            if ($success) {
2323
-                $what  = esc_html__('Registration Form', 'event_espresso');
2324
-                $route = $REG_ID
2325
-                    ? ['action' => 'view_registration', '_REG_ID' => $REG_ID]
2326
-                    : ['action' => 'default'];
2327
-                $this->_redirect_after_action(true, $what, esc_html__('updated', 'event_espresso'), $route);
2328
-            }
2329
-        }
2330
-    }
2331
-
2332
-
2333
-    /**
2334
-     * Gets the form for saving registrations custom questions (if done
2335
-     * previously retrieves the cached form object, which may have validation errors in it)
2336
-     *
2337
-     * @param int $REG_ID
2338
-     * @return EE_Registration_Custom_Questions_Form
2339
-     * @throws EE_Error
2340
-     * @throws InvalidArgumentException
2341
-     * @throws InvalidDataTypeException
2342
-     * @throws InvalidInterfaceException
2343
-     * @throws ReflectionException
2344
-     */
2345
-    protected function _get_reg_custom_questions_form($REG_ID)
2346
-    {
2347
-        if (! $this->_reg_custom_questions_form) {
2348
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2349
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2350
-                $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2351
-            );
2352
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2353
-        }
2354
-        return $this->_reg_custom_questions_form;
2355
-    }
2356
-
2357
-
2358
-    /**
2359
-     * Saves
2360
-     *
2361
-     * @param bool $REG_ID
2362
-     * @return bool
2363
-     * @throws EE_Error
2364
-     * @throws InvalidArgumentException
2365
-     * @throws InvalidDataTypeException
2366
-     * @throws InvalidInterfaceException
2367
-     * @throws ReflectionException
2368
-     */
2369
-    private function _save_reg_custom_questions_form($REG_ID = 0)
2370
-    {
2371
-        if (! $REG_ID) {
2372
-            EE_Error::add_error(
2373
-                esc_html__(
2374
-                    'An error occurred. No registration ID was received.',
2375
-                    'event_espresso'
2376
-                ),
2377
-                __FILE__,
2378
-                __FUNCTION__,
2379
-                __LINE__
2380
-            );
2381
-        }
2382
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2383
-        $form->receive_form_submission($this->request->requestParams());
2384
-        $success = false;
2385
-        if ($form->is_valid()) {
2386
-            foreach ($form->subforms() as $question_group_form) {
2387
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2388
-                    $where_conditions    = [
2389
-                        'QST_ID' => $question_id,
2390
-                        'REG_ID' => $REG_ID,
2391
-                    ];
2392
-                    $possibly_new_values = [
2393
-                        'ANS_value' => $input->normalized_value(),
2394
-                    ];
2395
-                    $answer              = EEM_Answer::instance()->get_one([$where_conditions]);
2396
-                    if ($answer instanceof EE_Answer) {
2397
-                        $success = $answer->save($possibly_new_values);
2398
-                    } else {
2399
-                        // insert it then
2400
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2401
-                        $answer      = EE_Answer::new_instance($cols_n_vals);
2402
-                        $success     = $answer->save();
2403
-                    }
2404
-                }
2405
-            }
2406
-        } else {
2407
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2408
-        }
2409
-        return $success;
2410
-    }
2411
-
2412
-
2413
-    /**
2414
-     * generates HTML for the Registration main meta box
2415
-     *
2416
-     * @return void
2417
-     * @throws DomainException
2418
-     * @throws EE_Error
2419
-     * @throws InvalidArgumentException
2420
-     * @throws InvalidDataTypeException
2421
-     * @throws InvalidInterfaceException
2422
-     * @throws ReflectionException
2423
-     */
2424
-    public function _reg_attendees_meta_box()
2425
-    {
2426
-        $REG = $this->getRegistrationModel();
2427
-        // get all other registrations on this transaction, and cache
2428
-        // the attendees for them so we don't have to run another query using force_join
2429
-        $registrations                           = $REG->get_all(
2430
-            [
2431
-                [
2432
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2433
-                    'REG_ID' => ['!=', $this->_registration->ID()],
2434
-                ],
2435
-                'force_join'               => ['Attendee'],
2436
-                'default_where_conditions' => 'other_models_only',
2437
-            ]
2438
-        );
2439
-        $this->_template_args['attendees']       = [];
2440
-        $this->_template_args['attendee_notice'] = '';
2441
-        if (
2442
-            empty($registrations)
2443
-            || (is_array($registrations)
2444
-                && ! EEH_Array::get_one_item_from_array($registrations))
2445
-        ) {
2446
-            EE_Error::add_error(
2447
-                esc_html__(
2448
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2449
-                    'event_espresso'
2450
-                ),
2451
-                __FILE__,
2452
-                __FUNCTION__,
2453
-                __LINE__
2454
-            );
2455
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2456
-        } else {
2457
-            $att_nmbr = 1;
2458
-            foreach ($registrations as $registration) {
2459
-                /* @var $registration EE_Registration */
2460
-                $attendee                                                      = $registration->attendee()
2461
-                    ? $registration->attendee()
2462
-                    : $this->getAttendeeModel()->create_default_object();
2463
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2464
-                $this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2465
-                $this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2466
-                $this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2467
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2468
-                $this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2469
-                    ', ',
2470
-                    $attendee->full_address_as_array()
2471
-                );
2472
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2473
-                    [
2474
-                        'action' => 'edit_attendee',
2475
-                        'post'   => $attendee->ID(),
2476
-                    ],
2477
-                    REG_ADMIN_URL
2478
-                );
2479
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2480
-                    $registration->event_obj() instanceof EE_Event
2481
-                        ? $registration->event_obj()->name()
2482
-                        : '';
2483
-                $att_nmbr++;
2484
-            }
2485
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2486
-        }
2487
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2488
-        EEH_Template::display_template($template_path, $this->_template_args);
2489
-    }
2490
-
2491
-
2492
-    /**
2493
-     * generates HTML for the Edit Registration side meta box
2494
-     *
2495
-     * @return void
2496
-     * @throws DomainException
2497
-     * @throws EE_Error
2498
-     * @throws InvalidArgumentException
2499
-     * @throws InvalidDataTypeException
2500
-     * @throws InvalidInterfaceException
2501
-     * @throws ReflectionException
2502
-     */
2503
-    public function _reg_registrant_side_meta_box()
2504
-    {
2505
-        /*@var $attendee EE_Attendee */
2506
-        $att_check = $this->_registration->attendee();
2507
-        $attendee  = $att_check instanceof EE_Attendee
2508
-            ? $att_check
2509
-            : $this->getAttendeeModel()->create_default_object();
2510
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2511
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2512
-        // primary registration object (that way we know if we need to show create button or not)
2513
-        if (! $this->_registration->is_primary_registrant()) {
2514
-            $primary_registration = $this->_registration->get_primary_registration();
2515
-            $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2516
-                : null;
2517
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2518
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2519
-                // custom attendee object so let's not worry about the primary reg.
2520
-                $primary_registration = null;
2521
-            }
2522
-        } else {
2523
-            $primary_registration = null;
2524
-        }
2525
-        $this->_template_args['ATT_ID']            = $attendee->ID();
2526
-        $this->_template_args['fname']             = $attendee->fname();
2527
-        $this->_template_args['lname']             = $attendee->lname();
2528
-        $this->_template_args['email']             = $attendee->email();
2529
-        $this->_template_args['phone']             = $attendee->phone();
2530
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2531
-        // edit link
2532
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2533
-            [
2534
-                'action' => 'edit_attendee',
2535
-                'post'   => $attendee->ID(),
2536
-            ],
2537
-            REG_ADMIN_URL
2538
-        );
2539
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2540
-        // create link
2541
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2542
-            ? EE_Admin_Page::add_query_args_and_nonce(
2543
-                [
2544
-                    'action'  => 'duplicate_attendee',
2545
-                    '_REG_ID' => $this->_registration->ID(),
2546
-                ],
2547
-                REG_ADMIN_URL
2548
-            ) : '';
2549
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2550
-        $this->_template_args['att_check']    = $att_check;
2551
-        $template_path                        =
2552
-            REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2553
-        EEH_Template::display_template($template_path, $this->_template_args);
2554
-    }
2555
-
2556
-
2557
-    /**
2558
-     * trash or restore registrations
2559
-     *
2560
-     * @param boolean $trash whether to archive or restore
2561
-     * @return void
2562
-     * @throws DomainException
2563
-     * @throws EE_Error
2564
-     * @throws EntityNotFoundException
2565
-     * @throws InvalidArgumentException
2566
-     * @throws InvalidDataTypeException
2567
-     * @throws InvalidInterfaceException
2568
-     * @throws ReflectionException
2569
-     * @throws RuntimeException
2570
-     * @throws UnexpectedEntityException
2571
-     */
2572
-    protected function _trash_or_restore_registrations($trash = true)
2573
-    {
2574
-        // if empty _REG_ID then get out because there's nothing to do
2575
-        $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2576
-        if (empty($REG_IDs)) {
2577
-            EE_Error::add_error(
2578
-                sprintf(
2579
-                    esc_html__(
2580
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2581
-                        'event_espresso'
2582
-                    ),
2583
-                    $trash ? 'trash' : 'restore'
2584
-                ),
2585
-                __FILE__,
2586
-                __LINE__,
2587
-                __FUNCTION__
2588
-            );
2589
-            $this->_redirect_after_action(false, '', '', [], true);
2590
-        }
2591
-        $success        = 0;
2592
-        $overwrite_msgs = false;
2593
-        // Checkboxes
2594
-        $reg_count = count($REG_IDs);
2595
-        // cycle thru checkboxes
2596
-        foreach ($REG_IDs as $REG_ID) {
2597
-            /** @var EE_Registration $REG */
2598
-            $REG      = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2599
-            $payments = $REG->registration_payments();
2600
-            if (! empty($payments)) {
2601
-                $name           = $REG->attendee() instanceof EE_Attendee
2602
-                    ? $REG->attendee()->full_name()
2603
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2604
-                $overwrite_msgs = true;
2605
-                EE_Error::add_error(
2606
-                    sprintf(
2607
-                        esc_html__(
2608
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2609
-                            'event_espresso'
2610
-                        ),
2611
-                        $name
2612
-                    ),
2613
-                    __FILE__,
2614
-                    __FUNCTION__,
2615
-                    __LINE__
2616
-                );
2617
-                // can't trash this registration because it has payments.
2618
-                continue;
2619
-            }
2620
-            $updated = $trash ? $REG->delete(__METHOD__) : $REG->restore(__METHOD__);
2621
-            if ($updated) {
2622
-                $success++;
2623
-            }
2624
-        }
2625
-        $this->_redirect_after_action(
2626
-            $success === $reg_count, // were ALL registrations affected?
2627
-            $success > 1
2628
-                ? esc_html__('Registrations', 'event_espresso')
2629
-                : esc_html__('Registration', 'event_espresso'),
2630
-            $trash
2631
-                ? esc_html__('moved to the trash', 'event_espresso')
2632
-                : esc_html__('restored', 'event_espresso'),
2633
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2634
-            $overwrite_msgs
2635
-        );
2636
-    }
2637
-
2638
-
2639
-    /**
2640
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2641
-     * registration but also.
2642
-     * 1. Removing relations to EE_Attendee
2643
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2644
-     * ALSO trashed.
2645
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2646
-     * 4. Removing relationships between all tickets and the related registrations
2647
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2648
-     * 6. Deleting permanently any related Checkins.
2649
-     *
2650
-     * @return void
2651
-     * @throws EE_Error
2652
-     * @throws InvalidArgumentException
2653
-     * @throws InvalidDataTypeException
2654
-     * @throws InvalidInterfaceException
2655
-     * @throws ReflectionException
2656
-     */
2657
-    protected function _delete_registrations()
2658
-    {
2659
-        $REG_MDL = $this->getRegistrationModel();
2660
-        $success = 0;
2661
-        // Checkboxes
2662
-        $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2663
-
2664
-        if (! empty($REG_IDs)) {
2665
-            // if array has more than one element than success message should be plural
2666
-            $success = count($REG_IDs) > 1 ? 2 : 1;
2667
-            // cycle thru checkboxes
2668
-            foreach ($REG_IDs as $REG_ID) {
2669
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2670
-                if (! $REG instanceof EE_Registration) {
2671
-                    continue;
2672
-                }
2673
-                $deleted = $this->_delete_registration($REG);
2674
-                if (! $deleted) {
2675
-                    $success = 0;
2676
-                }
2677
-            }
2678
-        }
2679
-
2680
-        $what        = $success > 1
2681
-            ? esc_html__('Registrations', 'event_espresso')
2682
-            : esc_html__('Registration', 'event_espresso');
2683
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2684
-        $this->_redirect_after_action(
2685
-            $success,
2686
-            $what,
2687
-            $action_desc,
2688
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2689
-            true
2690
-        );
2691
-    }
2692
-
2693
-
2694
-    /**
2695
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2696
-     * models get affected.
2697
-     *
2698
-     * @param EE_Registration $REG registration to be deleted permanently
2699
-     * @return bool true = successful deletion, false = fail.
2700
-     * @throws EE_Error
2701
-     * @throws InvalidArgumentException
2702
-     * @throws InvalidDataTypeException
2703
-     * @throws InvalidInterfaceException
2704
-     * @throws ReflectionException
2705
-     */
2706
-    protected function _delete_registration(EE_Registration $REG)
2707
-    {
2708
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2709
-        // registrations on the transaction that are NOT trashed.
2710
-        $TXN = $REG->get_first_related('Transaction');
2711
-        if (! $TXN instanceof EE_Transaction) {
2712
-            EE_Error::add_error(
2713
-                sprintf(
2714
-                    esc_html__(
2715
-                        'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2716
-                        'event_espresso'
2717
-                    ),
2718
-                    $REG->id()
2719
-                ),
2720
-                __FILE__,
2721
-                __FUNCTION__,
2722
-                __LINE__
2723
-            );
2724
-            return false;
2725
-        }
2726
-        $REGS        = $TXN->get_many_related('Registration');
2727
-        $all_trashed = true;
2728
-        foreach ($REGS as $registration) {
2729
-            if (! $registration->get('REG_deleted')) {
2730
-                $all_trashed = false;
2731
-            }
2732
-        }
2733
-        if (! $all_trashed) {
2734
-            EE_Error::add_error(
2735
-                esc_html__(
2736
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2737
-                    'event_espresso'
2738
-                ),
2739
-                __FILE__,
2740
-                __FUNCTION__,
2741
-                __LINE__
2742
-            );
2743
-            return false;
2744
-        }
2745
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2746
-        // separately from THIS one).
2747
-        foreach ($REGS as $registration) {
2748
-            // delete related answers
2749
-            $registration->delete_related_permanently('Answer');
2750
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2751
-            $attendee = $registration->get_first_related('Attendee');
2752
-            if ($attendee instanceof EE_Attendee) {
2753
-                $registration->_remove_relation_to($attendee, 'Attendee');
2754
-            }
2755
-            // now remove relationships to tickets on this registration.
2756
-            $registration->_remove_relations('Ticket');
2757
-            // now delete permanently the checkins related to this registration.
2758
-            $registration->delete_related_permanently('Checkin');
2759
-            if ($registration->ID() === $REG->ID()) {
2760
-                continue;
2761
-            } //we don't want to delete permanently the existing registration just yet.
2762
-            // remove relation to transaction for these registrations if NOT the existing registrations
2763
-            $registration->_remove_relations('Transaction');
2764
-            // delete permanently any related messages.
2765
-            $registration->delete_related_permanently('Message');
2766
-            // now delete this registration permanently
2767
-            $registration->delete_permanently();
2768
-        }
2769
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2770
-        // (the transaction and line items should be all that's left).
2771
-        // delete the line items related to the transaction for this registration.
2772
-        $TXN->delete_related_permanently('Line_Item');
2773
-        // we need to remove all the relationships on the transaction
2774
-        $TXN->delete_related_permanently('Payment');
2775
-        $TXN->delete_related_permanently('Extra_Meta');
2776
-        $TXN->delete_related_permanently('Message');
2777
-        // now we can delete this REG permanently (and the transaction of course)
2778
-        $REG->delete_related_permanently('Transaction');
2779
-        return $REG->delete_permanently();
2780
-    }
2781
-
2782
-
2783
-    /**
2784
-     *    generates HTML for the Register New Attendee Admin page
2785
-     *
2786
-     * @throws DomainException
2787
-     * @throws EE_Error
2788
-     * @throws InvalidArgumentException
2789
-     * @throws InvalidDataTypeException
2790
-     * @throws InvalidInterfaceException
2791
-     * @throws ReflectionException
2792
-     */
2793
-    public function new_registration()
2794
-    {
2795
-        if (! $this->_set_reg_event()) {
2796
-            throw new EE_Error(
2797
-                esc_html__(
2798
-                    'Unable to continue with registering because there is no Event ID in the request',
2799
-                    'event_espresso'
2800
-                )
2801
-            );
2802
-        }
2803
-        /** @var CurrentPage $current_page */
2804
-        $current_page = $this->loader->getShared(CurrentPage::class);
2805
-        $current_page->setEspressoPage(true);
2806
-        // gotta start with a clean slate if we're not coming here via ajax
2807
-        if (
2808
-            ! $this->request->isAjax()
2809
-            && (
2810
-                ! $this->request->requestParamIsSet('processing_registration')
2811
-                || $this->request->requestParamIsSet('step_error')
2812
-            )
2813
-        ) {
2814
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2815
-        }
2816
-        $this->_template_args['event_name'] = '';
2817
-        // event name
2818
-        if ($this->_reg_event) {
2819
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2820
-            $edit_event_url                     = self::add_query_args_and_nonce(
2821
-                [
2822
-                    'action' => 'edit',
2823
-                    'post'   => $this->_reg_event->ID(),
2824
-                ],
2825
-                EVENTS_ADMIN_URL
2826
-            );
2827
-            $edit_event_lnk                     = '<a href="'
2828
-                                                  . $edit_event_url
2829
-                                                  . '" title="'
2830
-                                                  . esc_attr__('Edit ', 'event_espresso')
2831
-                                                  . $this->_reg_event->name()
2832
-                                                  . '">'
2833
-                                                  . esc_html__('Edit Event', 'event_espresso')
2834
-                                                  . '</a>';
2835
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2836
-                                                   . $edit_event_lnk
2837
-                                                   . '</span>';
2838
-        }
2839
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2840
-        if ($this->request->isAjax()) {
2841
-            $this->_return_json();
2842
-        }
2843
-        // grab header
2844
-        $template_path                              =
2845
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2846
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2847
-            $template_path,
2848
-            $this->_template_args,
2849
-            true
2850
-        );
2851
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2852
-        // the details template wrapper
2853
-        $this->display_admin_page_with_sidebar();
2854
-    }
2855
-
2856
-
2857
-    /**
2858
-     * This returns the content for a registration step
2859
-     *
2860
-     * @return string html
2861
-     * @throws DomainException
2862
-     * @throws EE_Error
2863
-     * @throws InvalidArgumentException
2864
-     * @throws InvalidDataTypeException
2865
-     * @throws InvalidInterfaceException
2866
-     * @throws ReflectionException
2867
-     */
2868
-    protected function _get_registration_step_content()
2869
-    {
2870
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2871
-            $warning_msg = sprintf(
2872
-                esc_html__(
2873
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2874
-                    'event_espresso'
2875
-                ),
2876
-                '<br />',
2877
-                '<h3 class="important-notice">',
2878
-                '</h3>',
2879
-                '<div class="float-right">',
2880
-                '<span id="redirect_timer" class="important-notice">30</span>',
2881
-                '</div>',
2882
-                '<b>',
2883
-                '</b>'
2884
-            );
2885
-            return '
2301
+	}
2302
+
2303
+
2304
+	/**
2305
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2306
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2307
+	 * to display the page
2308
+	 *
2309
+	 * @return void
2310
+	 * @throws EE_Error
2311
+	 * @throws InvalidArgumentException
2312
+	 * @throws InvalidDataTypeException
2313
+	 * @throws InvalidInterfaceException
2314
+	 * @throws ReflectionException
2315
+	 */
2316
+	protected function _update_attendee_registration_form()
2317
+	{
2318
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2319
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2320
+			$REG_ID  = $this->request->getRequestParam('_REG_ID', 0, 'int');
2321
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2322
+			if ($success) {
2323
+				$what  = esc_html__('Registration Form', 'event_espresso');
2324
+				$route = $REG_ID
2325
+					? ['action' => 'view_registration', '_REG_ID' => $REG_ID]
2326
+					: ['action' => 'default'];
2327
+				$this->_redirect_after_action(true, $what, esc_html__('updated', 'event_espresso'), $route);
2328
+			}
2329
+		}
2330
+	}
2331
+
2332
+
2333
+	/**
2334
+	 * Gets the form for saving registrations custom questions (if done
2335
+	 * previously retrieves the cached form object, which may have validation errors in it)
2336
+	 *
2337
+	 * @param int $REG_ID
2338
+	 * @return EE_Registration_Custom_Questions_Form
2339
+	 * @throws EE_Error
2340
+	 * @throws InvalidArgumentException
2341
+	 * @throws InvalidDataTypeException
2342
+	 * @throws InvalidInterfaceException
2343
+	 * @throws ReflectionException
2344
+	 */
2345
+	protected function _get_reg_custom_questions_form($REG_ID)
2346
+	{
2347
+		if (! $this->_reg_custom_questions_form) {
2348
+			require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2349
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2350
+				$this->getRegistrationModel()->get_one_by_ID($REG_ID)
2351
+			);
2352
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2353
+		}
2354
+		return $this->_reg_custom_questions_form;
2355
+	}
2356
+
2357
+
2358
+	/**
2359
+	 * Saves
2360
+	 *
2361
+	 * @param bool $REG_ID
2362
+	 * @return bool
2363
+	 * @throws EE_Error
2364
+	 * @throws InvalidArgumentException
2365
+	 * @throws InvalidDataTypeException
2366
+	 * @throws InvalidInterfaceException
2367
+	 * @throws ReflectionException
2368
+	 */
2369
+	private function _save_reg_custom_questions_form($REG_ID = 0)
2370
+	{
2371
+		if (! $REG_ID) {
2372
+			EE_Error::add_error(
2373
+				esc_html__(
2374
+					'An error occurred. No registration ID was received.',
2375
+					'event_espresso'
2376
+				),
2377
+				__FILE__,
2378
+				__FUNCTION__,
2379
+				__LINE__
2380
+			);
2381
+		}
2382
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2383
+		$form->receive_form_submission($this->request->requestParams());
2384
+		$success = false;
2385
+		if ($form->is_valid()) {
2386
+			foreach ($form->subforms() as $question_group_form) {
2387
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2388
+					$where_conditions    = [
2389
+						'QST_ID' => $question_id,
2390
+						'REG_ID' => $REG_ID,
2391
+					];
2392
+					$possibly_new_values = [
2393
+						'ANS_value' => $input->normalized_value(),
2394
+					];
2395
+					$answer              = EEM_Answer::instance()->get_one([$where_conditions]);
2396
+					if ($answer instanceof EE_Answer) {
2397
+						$success = $answer->save($possibly_new_values);
2398
+					} else {
2399
+						// insert it then
2400
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2401
+						$answer      = EE_Answer::new_instance($cols_n_vals);
2402
+						$success     = $answer->save();
2403
+					}
2404
+				}
2405
+			}
2406
+		} else {
2407
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2408
+		}
2409
+		return $success;
2410
+	}
2411
+
2412
+
2413
+	/**
2414
+	 * generates HTML for the Registration main meta box
2415
+	 *
2416
+	 * @return void
2417
+	 * @throws DomainException
2418
+	 * @throws EE_Error
2419
+	 * @throws InvalidArgumentException
2420
+	 * @throws InvalidDataTypeException
2421
+	 * @throws InvalidInterfaceException
2422
+	 * @throws ReflectionException
2423
+	 */
2424
+	public function _reg_attendees_meta_box()
2425
+	{
2426
+		$REG = $this->getRegistrationModel();
2427
+		// get all other registrations on this transaction, and cache
2428
+		// the attendees for them so we don't have to run another query using force_join
2429
+		$registrations                           = $REG->get_all(
2430
+			[
2431
+				[
2432
+					'TXN_ID' => $this->_registration->transaction_ID(),
2433
+					'REG_ID' => ['!=', $this->_registration->ID()],
2434
+				],
2435
+				'force_join'               => ['Attendee'],
2436
+				'default_where_conditions' => 'other_models_only',
2437
+			]
2438
+		);
2439
+		$this->_template_args['attendees']       = [];
2440
+		$this->_template_args['attendee_notice'] = '';
2441
+		if (
2442
+			empty($registrations)
2443
+			|| (is_array($registrations)
2444
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2445
+		) {
2446
+			EE_Error::add_error(
2447
+				esc_html__(
2448
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2449
+					'event_espresso'
2450
+				),
2451
+				__FILE__,
2452
+				__FUNCTION__,
2453
+				__LINE__
2454
+			);
2455
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2456
+		} else {
2457
+			$att_nmbr = 1;
2458
+			foreach ($registrations as $registration) {
2459
+				/* @var $registration EE_Registration */
2460
+				$attendee                                                      = $registration->attendee()
2461
+					? $registration->attendee()
2462
+					: $this->getAttendeeModel()->create_default_object();
2463
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2464
+				$this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2465
+				$this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2466
+				$this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2467
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2468
+				$this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2469
+					', ',
2470
+					$attendee->full_address_as_array()
2471
+				);
2472
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2473
+					[
2474
+						'action' => 'edit_attendee',
2475
+						'post'   => $attendee->ID(),
2476
+					],
2477
+					REG_ADMIN_URL
2478
+				);
2479
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2480
+					$registration->event_obj() instanceof EE_Event
2481
+						? $registration->event_obj()->name()
2482
+						: '';
2483
+				$att_nmbr++;
2484
+			}
2485
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2486
+		}
2487
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2488
+		EEH_Template::display_template($template_path, $this->_template_args);
2489
+	}
2490
+
2491
+
2492
+	/**
2493
+	 * generates HTML for the Edit Registration side meta box
2494
+	 *
2495
+	 * @return void
2496
+	 * @throws DomainException
2497
+	 * @throws EE_Error
2498
+	 * @throws InvalidArgumentException
2499
+	 * @throws InvalidDataTypeException
2500
+	 * @throws InvalidInterfaceException
2501
+	 * @throws ReflectionException
2502
+	 */
2503
+	public function _reg_registrant_side_meta_box()
2504
+	{
2505
+		/*@var $attendee EE_Attendee */
2506
+		$att_check = $this->_registration->attendee();
2507
+		$attendee  = $att_check instanceof EE_Attendee
2508
+			? $att_check
2509
+			: $this->getAttendeeModel()->create_default_object();
2510
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2511
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2512
+		// primary registration object (that way we know if we need to show create button or not)
2513
+		if (! $this->_registration->is_primary_registrant()) {
2514
+			$primary_registration = $this->_registration->get_primary_registration();
2515
+			$primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2516
+				: null;
2517
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2518
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2519
+				// custom attendee object so let's not worry about the primary reg.
2520
+				$primary_registration = null;
2521
+			}
2522
+		} else {
2523
+			$primary_registration = null;
2524
+		}
2525
+		$this->_template_args['ATT_ID']            = $attendee->ID();
2526
+		$this->_template_args['fname']             = $attendee->fname();
2527
+		$this->_template_args['lname']             = $attendee->lname();
2528
+		$this->_template_args['email']             = $attendee->email();
2529
+		$this->_template_args['phone']             = $attendee->phone();
2530
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2531
+		// edit link
2532
+		$this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2533
+			[
2534
+				'action' => 'edit_attendee',
2535
+				'post'   => $attendee->ID(),
2536
+			],
2537
+			REG_ADMIN_URL
2538
+		);
2539
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2540
+		// create link
2541
+		$this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2542
+			? EE_Admin_Page::add_query_args_and_nonce(
2543
+				[
2544
+					'action'  => 'duplicate_attendee',
2545
+					'_REG_ID' => $this->_registration->ID(),
2546
+				],
2547
+				REG_ADMIN_URL
2548
+			) : '';
2549
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2550
+		$this->_template_args['att_check']    = $att_check;
2551
+		$template_path                        =
2552
+			REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2553
+		EEH_Template::display_template($template_path, $this->_template_args);
2554
+	}
2555
+
2556
+
2557
+	/**
2558
+	 * trash or restore registrations
2559
+	 *
2560
+	 * @param boolean $trash whether to archive or restore
2561
+	 * @return void
2562
+	 * @throws DomainException
2563
+	 * @throws EE_Error
2564
+	 * @throws EntityNotFoundException
2565
+	 * @throws InvalidArgumentException
2566
+	 * @throws InvalidDataTypeException
2567
+	 * @throws InvalidInterfaceException
2568
+	 * @throws ReflectionException
2569
+	 * @throws RuntimeException
2570
+	 * @throws UnexpectedEntityException
2571
+	 */
2572
+	protected function _trash_or_restore_registrations($trash = true)
2573
+	{
2574
+		// if empty _REG_ID then get out because there's nothing to do
2575
+		$REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2576
+		if (empty($REG_IDs)) {
2577
+			EE_Error::add_error(
2578
+				sprintf(
2579
+					esc_html__(
2580
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2581
+						'event_espresso'
2582
+					),
2583
+					$trash ? 'trash' : 'restore'
2584
+				),
2585
+				__FILE__,
2586
+				__LINE__,
2587
+				__FUNCTION__
2588
+			);
2589
+			$this->_redirect_after_action(false, '', '', [], true);
2590
+		}
2591
+		$success        = 0;
2592
+		$overwrite_msgs = false;
2593
+		// Checkboxes
2594
+		$reg_count = count($REG_IDs);
2595
+		// cycle thru checkboxes
2596
+		foreach ($REG_IDs as $REG_ID) {
2597
+			/** @var EE_Registration $REG */
2598
+			$REG      = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2599
+			$payments = $REG->registration_payments();
2600
+			if (! empty($payments)) {
2601
+				$name           = $REG->attendee() instanceof EE_Attendee
2602
+					? $REG->attendee()->full_name()
2603
+					: esc_html__('Unknown Attendee', 'event_espresso');
2604
+				$overwrite_msgs = true;
2605
+				EE_Error::add_error(
2606
+					sprintf(
2607
+						esc_html__(
2608
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2609
+							'event_espresso'
2610
+						),
2611
+						$name
2612
+					),
2613
+					__FILE__,
2614
+					__FUNCTION__,
2615
+					__LINE__
2616
+				);
2617
+				// can't trash this registration because it has payments.
2618
+				continue;
2619
+			}
2620
+			$updated = $trash ? $REG->delete(__METHOD__) : $REG->restore(__METHOD__);
2621
+			if ($updated) {
2622
+				$success++;
2623
+			}
2624
+		}
2625
+		$this->_redirect_after_action(
2626
+			$success === $reg_count, // were ALL registrations affected?
2627
+			$success > 1
2628
+				? esc_html__('Registrations', 'event_espresso')
2629
+				: esc_html__('Registration', 'event_espresso'),
2630
+			$trash
2631
+				? esc_html__('moved to the trash', 'event_espresso')
2632
+				: esc_html__('restored', 'event_espresso'),
2633
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2634
+			$overwrite_msgs
2635
+		);
2636
+	}
2637
+
2638
+
2639
+	/**
2640
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2641
+	 * registration but also.
2642
+	 * 1. Removing relations to EE_Attendee
2643
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2644
+	 * ALSO trashed.
2645
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2646
+	 * 4. Removing relationships between all tickets and the related registrations
2647
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2648
+	 * 6. Deleting permanently any related Checkins.
2649
+	 *
2650
+	 * @return void
2651
+	 * @throws EE_Error
2652
+	 * @throws InvalidArgumentException
2653
+	 * @throws InvalidDataTypeException
2654
+	 * @throws InvalidInterfaceException
2655
+	 * @throws ReflectionException
2656
+	 */
2657
+	protected function _delete_registrations()
2658
+	{
2659
+		$REG_MDL = $this->getRegistrationModel();
2660
+		$success = 0;
2661
+		// Checkboxes
2662
+		$REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2663
+
2664
+		if (! empty($REG_IDs)) {
2665
+			// if array has more than one element than success message should be plural
2666
+			$success = count($REG_IDs) > 1 ? 2 : 1;
2667
+			// cycle thru checkboxes
2668
+			foreach ($REG_IDs as $REG_ID) {
2669
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2670
+				if (! $REG instanceof EE_Registration) {
2671
+					continue;
2672
+				}
2673
+				$deleted = $this->_delete_registration($REG);
2674
+				if (! $deleted) {
2675
+					$success = 0;
2676
+				}
2677
+			}
2678
+		}
2679
+
2680
+		$what        = $success > 1
2681
+			? esc_html__('Registrations', 'event_espresso')
2682
+			: esc_html__('Registration', 'event_espresso');
2683
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2684
+		$this->_redirect_after_action(
2685
+			$success,
2686
+			$what,
2687
+			$action_desc,
2688
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2689
+			true
2690
+		);
2691
+	}
2692
+
2693
+
2694
+	/**
2695
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2696
+	 * models get affected.
2697
+	 *
2698
+	 * @param EE_Registration $REG registration to be deleted permanently
2699
+	 * @return bool true = successful deletion, false = fail.
2700
+	 * @throws EE_Error
2701
+	 * @throws InvalidArgumentException
2702
+	 * @throws InvalidDataTypeException
2703
+	 * @throws InvalidInterfaceException
2704
+	 * @throws ReflectionException
2705
+	 */
2706
+	protected function _delete_registration(EE_Registration $REG)
2707
+	{
2708
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2709
+		// registrations on the transaction that are NOT trashed.
2710
+		$TXN = $REG->get_first_related('Transaction');
2711
+		if (! $TXN instanceof EE_Transaction) {
2712
+			EE_Error::add_error(
2713
+				sprintf(
2714
+					esc_html__(
2715
+						'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2716
+						'event_espresso'
2717
+					),
2718
+					$REG->id()
2719
+				),
2720
+				__FILE__,
2721
+				__FUNCTION__,
2722
+				__LINE__
2723
+			);
2724
+			return false;
2725
+		}
2726
+		$REGS        = $TXN->get_many_related('Registration');
2727
+		$all_trashed = true;
2728
+		foreach ($REGS as $registration) {
2729
+			if (! $registration->get('REG_deleted')) {
2730
+				$all_trashed = false;
2731
+			}
2732
+		}
2733
+		if (! $all_trashed) {
2734
+			EE_Error::add_error(
2735
+				esc_html__(
2736
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2737
+					'event_espresso'
2738
+				),
2739
+				__FILE__,
2740
+				__FUNCTION__,
2741
+				__LINE__
2742
+			);
2743
+			return false;
2744
+		}
2745
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2746
+		// separately from THIS one).
2747
+		foreach ($REGS as $registration) {
2748
+			// delete related answers
2749
+			$registration->delete_related_permanently('Answer');
2750
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2751
+			$attendee = $registration->get_first_related('Attendee');
2752
+			if ($attendee instanceof EE_Attendee) {
2753
+				$registration->_remove_relation_to($attendee, 'Attendee');
2754
+			}
2755
+			// now remove relationships to tickets on this registration.
2756
+			$registration->_remove_relations('Ticket');
2757
+			// now delete permanently the checkins related to this registration.
2758
+			$registration->delete_related_permanently('Checkin');
2759
+			if ($registration->ID() === $REG->ID()) {
2760
+				continue;
2761
+			} //we don't want to delete permanently the existing registration just yet.
2762
+			// remove relation to transaction for these registrations if NOT the existing registrations
2763
+			$registration->_remove_relations('Transaction');
2764
+			// delete permanently any related messages.
2765
+			$registration->delete_related_permanently('Message');
2766
+			// now delete this registration permanently
2767
+			$registration->delete_permanently();
2768
+		}
2769
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2770
+		// (the transaction and line items should be all that's left).
2771
+		// delete the line items related to the transaction for this registration.
2772
+		$TXN->delete_related_permanently('Line_Item');
2773
+		// we need to remove all the relationships on the transaction
2774
+		$TXN->delete_related_permanently('Payment');
2775
+		$TXN->delete_related_permanently('Extra_Meta');
2776
+		$TXN->delete_related_permanently('Message');
2777
+		// now we can delete this REG permanently (and the transaction of course)
2778
+		$REG->delete_related_permanently('Transaction');
2779
+		return $REG->delete_permanently();
2780
+	}
2781
+
2782
+
2783
+	/**
2784
+	 *    generates HTML for the Register New Attendee Admin page
2785
+	 *
2786
+	 * @throws DomainException
2787
+	 * @throws EE_Error
2788
+	 * @throws InvalidArgumentException
2789
+	 * @throws InvalidDataTypeException
2790
+	 * @throws InvalidInterfaceException
2791
+	 * @throws ReflectionException
2792
+	 */
2793
+	public function new_registration()
2794
+	{
2795
+		if (! $this->_set_reg_event()) {
2796
+			throw new EE_Error(
2797
+				esc_html__(
2798
+					'Unable to continue with registering because there is no Event ID in the request',
2799
+					'event_espresso'
2800
+				)
2801
+			);
2802
+		}
2803
+		/** @var CurrentPage $current_page */
2804
+		$current_page = $this->loader->getShared(CurrentPage::class);
2805
+		$current_page->setEspressoPage(true);
2806
+		// gotta start with a clean slate if we're not coming here via ajax
2807
+		if (
2808
+			! $this->request->isAjax()
2809
+			&& (
2810
+				! $this->request->requestParamIsSet('processing_registration')
2811
+				|| $this->request->requestParamIsSet('step_error')
2812
+			)
2813
+		) {
2814
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2815
+		}
2816
+		$this->_template_args['event_name'] = '';
2817
+		// event name
2818
+		if ($this->_reg_event) {
2819
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2820
+			$edit_event_url                     = self::add_query_args_and_nonce(
2821
+				[
2822
+					'action' => 'edit',
2823
+					'post'   => $this->_reg_event->ID(),
2824
+				],
2825
+				EVENTS_ADMIN_URL
2826
+			);
2827
+			$edit_event_lnk                     = '<a href="'
2828
+												  . $edit_event_url
2829
+												  . '" title="'
2830
+												  . esc_attr__('Edit ', 'event_espresso')
2831
+												  . $this->_reg_event->name()
2832
+												  . '">'
2833
+												  . esc_html__('Edit Event', 'event_espresso')
2834
+												  . '</a>';
2835
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2836
+												   . $edit_event_lnk
2837
+												   . '</span>';
2838
+		}
2839
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2840
+		if ($this->request->isAjax()) {
2841
+			$this->_return_json();
2842
+		}
2843
+		// grab header
2844
+		$template_path                              =
2845
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2846
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2847
+			$template_path,
2848
+			$this->_template_args,
2849
+			true
2850
+		);
2851
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2852
+		// the details template wrapper
2853
+		$this->display_admin_page_with_sidebar();
2854
+	}
2855
+
2856
+
2857
+	/**
2858
+	 * This returns the content for a registration step
2859
+	 *
2860
+	 * @return string html
2861
+	 * @throws DomainException
2862
+	 * @throws EE_Error
2863
+	 * @throws InvalidArgumentException
2864
+	 * @throws InvalidDataTypeException
2865
+	 * @throws InvalidInterfaceException
2866
+	 * @throws ReflectionException
2867
+	 */
2868
+	protected function _get_registration_step_content()
2869
+	{
2870
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2871
+			$warning_msg = sprintf(
2872
+				esc_html__(
2873
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2874
+					'event_espresso'
2875
+				),
2876
+				'<br />',
2877
+				'<h3 class="important-notice">',
2878
+				'</h3>',
2879
+				'<div class="float-right">',
2880
+				'<span id="redirect_timer" class="important-notice">30</span>',
2881
+				'</div>',
2882
+				'<b>',
2883
+				'</b>'
2884
+			);
2885
+			return '
2886 2886
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2887 2887
 	<script >
2888 2888
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2895,852 +2895,852 @@  discard block
 block discarded – undo
2895 2895
 	        }
2896 2896
 	    }, 800 );
2897 2897
 	</script >';
2898
-        }
2899
-        $template_args = [
2900
-            'title'                    => '',
2901
-            'content'                  => '',
2902
-            'step_button_text'         => '',
2903
-            'show_notification_toggle' => false,
2904
-        ];
2905
-        // to indicate we're processing a new registration
2906
-        $hidden_fields = [
2907
-            'processing_registration' => [
2908
-                'type'  => 'hidden',
2909
-                'value' => 0,
2910
-            ],
2911
-            'event_id'                => [
2912
-                'type'  => 'hidden',
2913
-                'value' => $this->_reg_event->ID(),
2914
-            ],
2915
-        ];
2916
-        // if the cart is empty then we know we're at step one, so we'll display the ticket selector
2917
-        $cart = EE_Registry::instance()->SSN->cart();
2918
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2919
-        switch ($step) {
2920
-            case 'ticket':
2921
-                $hidden_fields['processing_registration']['value'] = 1;
2922
-                $template_args['title']                            = esc_html__(
2923
-                    'Step One: Select the Ticket for this registration',
2924
-                    'event_espresso'
2925
-                );
2926
-                $template_args['content']                          =
2927
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2928
-                $template_args['content']                          .= '</div>';
2929
-                $template_args['step_button_text']                 = esc_html__(
2930
-                    'Add Tickets and Continue to Registrant Details',
2931
-                    'event_espresso'
2932
-                );
2933
-                $template_args['show_notification_toggle']         = false;
2934
-                break;
2935
-            case 'questions':
2936
-                $hidden_fields['processing_registration']['value'] = 2;
2937
-                $template_args['title']                            = esc_html__(
2938
-                    'Step Two: Add Registrant Details for this Registration',
2939
-                    'event_espresso'
2940
-                );
2941
-                // in theory, we should be able to run EED_SPCO at this point
2942
-                // because the cart should have been set up properly by the first process_reg_step run.
2943
-                $template_args['content']                  =
2944
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
2945
-                $template_args['step_button_text']         = esc_html__(
2946
-                    'Save Registration and Continue to Details',
2947
-                    'event_espresso'
2948
-                );
2949
-                $template_args['show_notification_toggle'] = true;
2950
-                break;
2951
-        }
2952
-        // we come back to the process_registration_step route.
2953
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2954
-        return EEH_Template::display_template(
2955
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2956
-            $template_args,
2957
-            true
2958
-        );
2959
-    }
2960
-
2961
-
2962
-    /**
2963
-     * set_reg_event
2964
-     *
2965
-     * @return bool
2966
-     * @throws EE_Error
2967
-     * @throws InvalidArgumentException
2968
-     * @throws InvalidDataTypeException
2969
-     * @throws InvalidInterfaceException
2970
-     */
2971
-    private function _set_reg_event()
2972
-    {
2973
-        if (is_object($this->_reg_event)) {
2974
-            return true;
2975
-        }
2976
-
2977
-        $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2978
-        if (! $EVT_ID) {
2979
-            return false;
2980
-        }
2981
-        $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2982
-        return true;
2983
-    }
2984
-
2985
-
2986
-    /**
2987
-     * process_reg_step
2988
-     *
2989
-     * @return void
2990
-     * @throws DomainException
2991
-     * @throws EE_Error
2992
-     * @throws InvalidArgumentException
2993
-     * @throws InvalidDataTypeException
2994
-     * @throws InvalidInterfaceException
2995
-     * @throws ReflectionException
2996
-     * @throws RuntimeException
2997
-     */
2998
-    public function process_reg_step()
2999
-    {
3000
-        EE_System::do_not_cache();
3001
-        $this->_set_reg_event();
3002
-        /** @var CurrentPage $current_page */
3003
-        $current_page = $this->loader->getShared(CurrentPage::class);
3004
-        $current_page->setEspressoPage(true);
3005
-        $this->request->setRequestParam('uts', time());
3006
-        // what step are we on?
3007
-        $cart = EE_Registry::instance()->SSN->cart();
3008
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3009
-        // if doing ajax then we need to verify the nonce
3010
-        if ($this->request->isAjax()) {
3011
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
3012
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3013
-        }
3014
-        switch ($step) {
3015
-            case 'ticket':
3016
-                // process ticket selection
3017
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3018
-                if ($success) {
3019
-                    EE_Error::add_success(
3020
-                        esc_html__(
3021
-                            'Tickets Selected. Now complete the registration.',
3022
-                            'event_espresso'
3023
-                        )
3024
-                    );
3025
-                } else {
3026
-                    $this->request->setRequestParam('step_error', true);
3027
-                    $query_args['step_error'] = $this->request->getRequestParam('step_error', true, 'bool');
3028
-                }
3029
-                if ($this->request->isAjax()) {
3030
-                    $this->new_registration(); // display next step
3031
-                } else {
3032
-                    $query_args = [
3033
-                        'action'                  => 'new_registration',
3034
-                        'processing_registration' => 1,
3035
-                        'event_id'                => $this->_reg_event->ID(),
3036
-                        'uts'                     => time(),
3037
-                    ];
3038
-                    $this->_redirect_after_action(
3039
-                        false,
3040
-                        '',
3041
-                        '',
3042
-                        $query_args,
3043
-                        true
3044
-                    );
3045
-                }
3046
-                break;
3047
-            case 'questions':
3048
-                if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3049
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3050
-                }
3051
-                // process registration
3052
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3053
-                if ($cart instanceof EE_Cart) {
3054
-                    $grand_total = $cart->get_grand_total();
3055
-                    if ($grand_total instanceof EE_Line_Item) {
3056
-                        $grand_total->save_this_and_descendants_to_txn();
3057
-                    }
3058
-                }
3059
-                if (! $transaction instanceof EE_Transaction) {
3060
-                    $query_args = [
3061
-                        'action'                  => 'new_registration',
3062
-                        'processing_registration' => 2,
3063
-                        'event_id'                => $this->_reg_event->ID(),
3064
-                        'uts'                     => time(),
3065
-                    ];
3066
-                    if ($this->request->isAjax()) {
3067
-                        // display registration form again because there are errors (maybe validation?)
3068
-                        $this->new_registration();
3069
-                        return;
3070
-                    }
3071
-                    $this->_redirect_after_action(
3072
-                        false,
3073
-                        '',
3074
-                        '',
3075
-                        $query_args,
3076
-                        true
3077
-                    );
3078
-                    return;
3079
-                }
3080
-                // maybe update status, and make sure to save transaction if not done already
3081
-                if (! $transaction->update_status_based_on_total_paid()) {
3082
-                    $transaction->save();
3083
-                }
3084
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3085
-                $query_args = [
3086
-                    'action'        => 'redirect_to_txn',
3087
-                    'TXN_ID'        => $transaction->ID(),
3088
-                    'EVT_ID'        => $this->_reg_event->ID(),
3089
-                    'event_name'    => urlencode($this->_reg_event->name()),
3090
-                    'redirect_from' => 'new_registration',
3091
-                ];
3092
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3093
-                break;
3094
-        }
3095
-        // what are you looking here for?  Should be nothing to do at this point.
3096
-    }
3097
-
3098
-
3099
-    /**
3100
-     * redirect_to_txn
3101
-     *
3102
-     * @return void
3103
-     * @throws EE_Error
3104
-     * @throws InvalidArgumentException
3105
-     * @throws InvalidDataTypeException
3106
-     * @throws InvalidInterfaceException
3107
-     * @throws ReflectionException
3108
-     */
3109
-    public function redirect_to_txn()
3110
-    {
3111
-        EE_System::do_not_cache();
3112
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3113
-        $query_args = [
3114
-            'action' => 'view_transaction',
3115
-            'TXN_ID' => $this->request->getRequestParam('TXN_ID', 0, 'int'),
3116
-            'page'   => 'espresso_transactions',
3117
-        ];
3118
-        if ($this->request->requestParamIsSet('EVT_ID') && $this->request->requestParamIsSet('redirect_from')) {
3119
-            $query_args['EVT_ID']        = $this->request->getRequestParam('EVT_ID', 0, 'int');
3120
-            $query_args['event_name']    = urlencode($this->request->getRequestParam('event_name'));
3121
-            $query_args['redirect_from'] = $this->request->getRequestParam('redirect_from');
3122
-        }
3123
-        EE_Error::add_success(
3124
-            esc_html__(
3125
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3126
-                'event_espresso'
3127
-            )
3128
-        );
3129
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3130
-    }
3131
-
3132
-
3133
-    /**
3134
-     * generates HTML for the Attendee Contact List
3135
-     *
3136
-     * @return void
3137
-     * @throws DomainException
3138
-     * @throws EE_Error
3139
-     */
3140
-    protected function _attendee_contact_list_table()
3141
-    {
3142
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3143
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3144
-        $this->display_admin_list_table_page_with_no_sidebar();
3145
-    }
3146
-
3147
-
3148
-    /**
3149
-     * get_attendees
3150
-     *
3151
-     * @param      $per_page
3152
-     * @param bool $count whether to return count or data.
3153
-     * @param bool $trash
3154
-     * @return array|int
3155
-     * @throws EE_Error
3156
-     * @throws InvalidArgumentException
3157
-     * @throws InvalidDataTypeException
3158
-     * @throws InvalidInterfaceException
3159
-     */
3160
-    public function get_attendees($per_page, $count = false, $trash = false)
3161
-    {
3162
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3163
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3164
-        $orderby = $this->request->getRequestParam('orderby');
3165
-        switch ($orderby) {
3166
-            case 'ATT_ID':
3167
-            case 'ATT_fname':
3168
-            case 'ATT_email':
3169
-            case 'ATT_city':
3170
-            case 'STA_ID':
3171
-            case 'CNT_ID':
3172
-                break;
3173
-            case 'Registration_Count':
3174
-                $orderby = 'Registration_Count';
3175
-                break;
3176
-            default:
3177
-                $orderby = 'ATT_lname';
3178
-        }
3179
-        $sort         = $this->request->getRequestParam('order', 'ASC');
3180
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
3181
-        $per_page     = absint($per_page) ? $per_page : 10;
3182
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
3183
-        $_where       = [];
3184
-        $search_term  = $this->request->getRequestParam('s');
3185
-        if ($search_term) {
3186
-            $search_term  = '%' . $search_term . '%';
3187
-            $_where['OR'] = [
3188
-                'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3189
-                'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
3190
-                'Registration.Event.EVT_short_desc' => ['LIKE', $search_term],
3191
-                'ATT_fname'                         => ['LIKE', $search_term],
3192
-                'ATT_lname'                         => ['LIKE', $search_term],
3193
-                'ATT_short_bio'                     => ['LIKE', $search_term],
3194
-                'ATT_email'                         => ['LIKE', $search_term],
3195
-                'ATT_address'                       => ['LIKE', $search_term],
3196
-                'ATT_address2'                      => ['LIKE', $search_term],
3197
-                'ATT_city'                          => ['LIKE', $search_term],
3198
-                'Country.CNT_name'                  => ['LIKE', $search_term],
3199
-                'State.STA_name'                    => ['LIKE', $search_term],
3200
-                'ATT_phone'                         => ['LIKE', $search_term],
3201
-                'Registration.REG_final_price'      => ['LIKE', $search_term],
3202
-                'Registration.REG_code'             => ['LIKE', $search_term],
3203
-                'Registration.REG_group_size'       => ['LIKE', $search_term],
3204
-            ];
3205
-        }
3206
-        $offset     = ($current_page - 1) * $per_page;
3207
-        $limit      = $count ? null : [$offset, $per_page];
3208
-        $query_args = [
3209
-            $_where,
3210
-            'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3211
-            'limit'         => $limit,
3212
-        ];
3213
-        if (! $count) {
3214
-            $query_args['order_by'] = [$orderby => $sort];
3215
-        }
3216
-        $query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
3217
-        return $count
3218
-            ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3219
-            : $this->getAttendeeModel()->get_all($query_args);
3220
-    }
3221
-
3222
-
3223
-    /**
3224
-     * This is just taking care of resending the registration confirmation
3225
-     *
3226
-     * @return void
3227
-     * @throws EE_Error
3228
-     * @throws InvalidArgumentException
3229
-     * @throws InvalidDataTypeException
3230
-     * @throws InvalidInterfaceException
3231
-     * @throws ReflectionException
3232
-     */
3233
-    protected function _resend_registration()
3234
-    {
3235
-        $this->_process_resend_registration();
3236
-        $REG_ID      = $this->request->getRequestParam('_REG_ID', 0, 'int');
3237
-        $redirect_to = $this->request->getRequestParam('redirect_to');
3238
-        $query_args  = $redirect_to
3239
-            ? ['action' => $redirect_to, '_REG_ID' => $REG_ID]
3240
-            : ['action' => 'default'];
3241
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3242
-    }
3243
-
3244
-
3245
-    /**
3246
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3247
-     * to use when selecting registrations
3248
-     *
3249
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3250
-     *                                                     the query parameters from the request
3251
-     * @return void ends the request with a redirect or download
3252
-     */
3253
-    public function _registrations_report_base($method_name_for_getting_query_params)
3254
-    {
3255
-        $EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3256
-            ? $this->request->getRequestParam('EVT_ID', 0, 'int')
3257
-            : null;
3258
-
3259
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3260
-            $request_params = $this->request->requestParams();
3261
-            wp_redirect(
3262
-                EE_Admin_Page::add_query_args_and_nonce(
3263
-                    [
3264
-                        'page'        => 'espresso_batch',
3265
-                        'batch'       => 'file',
3266
-                        'EVT_ID'      => $EVT_ID,
3267
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3268
-                        'return_url'  => urlencode($this->request->getRequestParam('return_url', '', DataType::URL)),
3269
-                        'filters'     => urlencode(
3270
-                            serialize(
3271
-                                $this->$method_name_for_getting_query_params(
3272
-                                    (isset($request_params['filters']) ? $request_params['filters'] : [])
3273
-                                )
3274
-                            )
3275
-                        ),
3276
-                        'use_filters' => $this->request->getRequestParam('use_filters', false, DataType::BOOL)
3277
-                    ]
3278
-                )
3279
-            );
3280
-        } else {
3281
-            // Pull the current request params
3282
-            $request_args = $this->request->requestParams();
3283
-            // Set the required request_args to be passed to the export
3284
-            $required_request_args = [
3285
-                'export' => 'report',
3286
-                'action' => 'registrations_report_for_event',
3287
-                'EVT_ID' => $EVT_ID,
3288
-            ];
3289
-            // Merge required request args, overriding any currently set
3290
-            $request_args = array_merge($request_args, $required_request_args);
3291
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3292
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3293
-                $EE_Export = EE_Export::instance($request_args);
3294
-                $EE_Export->export();
3295
-            }
3296
-        }
3297
-    }
3298
-
3299
-
3300
-    /**
3301
-     * Creates a registration report using only query parameters in the request
3302
-     *
3303
-     * @return void
3304
-     */
3305
-    public function _registrations_report()
3306
-    {
3307
-        $this->_registrations_report_base('_get_registration_query_parameters');
3308
-    }
3309
-
3310
-
3311
-    public function _contact_list_export()
3312
-    {
3313
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3314
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3315
-            $EE_Export = EE_Export::instance($this->request->requestParams());
3316
-            $EE_Export->export_attendees();
3317
-        }
3318
-    }
3319
-
3320
-
3321
-    public function _contact_list_report()
3322
-    {
3323
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3324
-            wp_redirect(
3325
-                EE_Admin_Page::add_query_args_and_nonce(
3326
-                    [
3327
-                        'page'        => 'espresso_batch',
3328
-                        'batch'       => 'file',
3329
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3330
-                        'return_url'  => urlencode($this->request->getRequestParam('return_url', '', 'url')),
3331
-                    ]
3332
-                )
3333
-            );
3334
-        } else {
3335
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3336
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3337
-                $EE_Export = EE_Export::instance($this->request->requestParams());
3338
-                $EE_Export->report_attendees();
3339
-            }
3340
-        }
3341
-    }
3342
-
3343
-
3344
-
3345
-
3346
-
3347
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3348
-    /**
3349
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3350
-     *
3351
-     * @return void
3352
-     * @throws EE_Error
3353
-     * @throws InvalidArgumentException
3354
-     * @throws InvalidDataTypeException
3355
-     * @throws InvalidInterfaceException
3356
-     * @throws ReflectionException
3357
-     */
3358
-    protected function _duplicate_attendee()
3359
-    {
3360
-        $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3361
-        $action = $this->request->getRequestParam('return', 'default');
3362
-        // verify we have necessary info
3363
-        if (! $REG_ID) {
3364
-            EE_Error::add_error(
3365
-                esc_html__(
3366
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3367
-                    'event_espresso'
3368
-                ),
3369
-                __FILE__,
3370
-                __LINE__,
3371
-                __FUNCTION__
3372
-            );
3373
-            $query_args = ['action' => $action];
3374
-            $this->_redirect_after_action('', '', '', $query_args, true);
3375
-        }
3376
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3377
-        $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3378
-        if (! $registration instanceof EE_Registration) {
3379
-            throw new RuntimeException(
3380
-                sprintf(
3381
-                    esc_html__(
3382
-                        'Unable to create the contact because a valid registration could not be retrieved for REG ID: %1$d',
3383
-                        'event_espresso'
3384
-                    ),
3385
-                    $REG_ID
3386
-                )
3387
-            );
3388
-        }
3389
-        $attendee = $registration->attendee();
3390
-        // remove relation of existing attendee on registration
3391
-        $registration->_remove_relation_to($attendee, 'Attendee');
3392
-        // new attendee
3393
-        $new_attendee = clone $attendee;
3394
-        $new_attendee->set('ATT_ID', 0);
3395
-        $new_attendee->save();
3396
-        // add new attendee to reg
3397
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3398
-        EE_Error::add_success(
3399
-            esc_html__(
3400
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3401
-                'event_espresso'
3402
-            )
3403
-        );
3404
-        // redirect to edit page for attendee
3405
-        $query_args = ['post' => $new_attendee->ID(), 'action' => 'edit_attendee'];
3406
-        $this->_redirect_after_action('', '', '', $query_args, true);
3407
-    }
3408
-
3409
-
3410
-    /**
3411
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3412
-     *
3413
-     * @param int     $post_id
3414
-     * @param WP_Post $post
3415
-     * @throws DomainException
3416
-     * @throws EE_Error
3417
-     * @throws InvalidArgumentException
3418
-     * @throws InvalidDataTypeException
3419
-     * @throws InvalidInterfaceException
3420
-     * @throws LogicException
3421
-     * @throws InvalidFormSubmissionException
3422
-     * @throws ReflectionException
3423
-     */
3424
-    protected function _insert_update_cpt_item($post_id, $post)
3425
-    {
3426
-        $success  = true;
3427
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3428
-            ? $this->getAttendeeModel()->get_one_by_ID($post_id)
3429
-            : null;
3430
-        // for attendee updates
3431
-        if ($attendee instanceof EE_Attendee) {
3432
-            // note we should only be UPDATING attendees at this point.
3433
-            $fname          = $this->request->getRequestParam('ATT_fname', '');
3434
-            $lname          = $this->request->getRequestParam('ATT_lname', '');
3435
-            $updated_fields = [
3436
-                'ATT_fname'     => $fname,
3437
-                'ATT_lname'     => $lname,
3438
-                'ATT_full_name' => "{$fname} {$lname}",
3439
-                'ATT_address'   => $this->request->getRequestParam('ATT_address', ''),
3440
-                'ATT_address2'  => $this->request->getRequestParam('ATT_address2', ''),
3441
-                'ATT_city'      => $this->request->getRequestParam('ATT_city', ''),
3442
-                'STA_ID'        => $this->request->getRequestParam('STA_ID', ''),
3443
-                'CNT_ISO'       => $this->request->getRequestParam('CNT_ISO', ''),
3444
-                'ATT_zip'       => $this->request->getRequestParam('ATT_zip', ''),
3445
-            ];
3446
-            foreach ($updated_fields as $field => $value) {
3447
-                $attendee->set($field, $value);
3448
-            }
3449
-
3450
-            // process contact details metabox form handler (which will also save the attendee)
3451
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3452
-            $success              = $contact_details_form->process($this->request->requestParams());
3453
-
3454
-            $attendee_update_callbacks = apply_filters(
3455
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3456
-                []
3457
-            );
3458
-            foreach ($attendee_update_callbacks as $a_callback) {
3459
-                if (false === call_user_func_array($a_callback, [$attendee, $this->request->requestParams()])) {
3460
-                    throw new EE_Error(
3461
-                        sprintf(
3462
-                            esc_html__(
3463
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3464
-                                'event_espresso'
3465
-                            ),
3466
-                            $a_callback
3467
-                        )
3468
-                    );
3469
-                }
3470
-            }
3471
-        }
3472
-
3473
-        if ($success === false) {
3474
-            EE_Error::add_error(
3475
-                esc_html__(
3476
-                    'Something went wrong with updating the meta table data for the registration.',
3477
-                    'event_espresso'
3478
-                ),
3479
-                __FILE__,
3480
-                __FUNCTION__,
3481
-                __LINE__
3482
-            );
3483
-        }
3484
-    }
3485
-
3486
-
3487
-    public function trash_cpt_item($post_id)
3488
-    {
3489
-    }
3490
-
3491
-
3492
-    public function delete_cpt_item($post_id)
3493
-    {
3494
-    }
3495
-
3496
-
3497
-    public function restore_cpt_item($post_id)
3498
-    {
3499
-    }
3500
-
3501
-
3502
-    protected function _restore_cpt_item($post_id, $revision_id)
3503
-    {
3504
-    }
3505
-
3506
-
3507
-    /**
3508
-     * @throws EE_Error
3509
-     * @throws ReflectionException
3510
-     * @since 4.10.2.p
3511
-     */
3512
-    public function attendee_editor_metaboxes()
3513
-    {
3514
-        $this->verify_cpt_object();
3515
-        remove_meta_box(
3516
-            'postexcerpt',
3517
-            $this->_cpt_routes[ $this->_req_action ],
3518
-            'normal'
3519
-        );
3520
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3521
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3522
-            add_meta_box(
3523
-                'postexcerpt',
3524
-                esc_html__('Short Biography', 'event_espresso'),
3525
-                'post_excerpt_meta_box',
3526
-                $this->_cpt_routes[ $this->_req_action ],
3527
-                'normal'
3528
-            );
3529
-        }
3530
-        if (post_type_supports('espresso_attendees', 'comments')) {
3531
-            add_meta_box(
3532
-                'commentsdiv',
3533
-                esc_html__('Notes on the Contact', 'event_espresso'),
3534
-                'post_comment_meta_box',
3535
-                $this->_cpt_routes[ $this->_req_action ],
3536
-                'normal',
3537
-                'core'
3538
-            );
3539
-        }
3540
-        add_meta_box(
3541
-            'attendee_contact_info',
3542
-            esc_html__('Contact Info', 'event_espresso'),
3543
-            [$this, 'attendee_contact_info'],
3544
-            $this->_cpt_routes[ $this->_req_action ],
3545
-            'side',
3546
-            'core'
3547
-        );
3548
-        add_meta_box(
3549
-            'attendee_details_address',
3550
-            esc_html__('Address Details', 'event_espresso'),
3551
-            [$this, 'attendee_address_details'],
3552
-            $this->_cpt_routes[ $this->_req_action ],
3553
-            'normal',
3554
-            'core'
3555
-        );
3556
-        add_meta_box(
3557
-            'attendee_registrations',
3558
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3559
-            [$this, 'attendee_registrations_meta_box'],
3560
-            $this->_cpt_routes[ $this->_req_action ],
3561
-            'normal',
3562
-            'high'
3563
-        );
3564
-    }
3565
-
3566
-
3567
-    /**
3568
-     * Metabox for attendee contact info
3569
-     *
3570
-     * @param WP_Post $post wp post object
3571
-     * @return void attendee contact info ( and form )
3572
-     * @throws EE_Error
3573
-     * @throws InvalidArgumentException
3574
-     * @throws InvalidDataTypeException
3575
-     * @throws InvalidInterfaceException
3576
-     * @throws LogicException
3577
-     * @throws DomainException
3578
-     */
3579
-    public function attendee_contact_info($post)
3580
-    {
3581
-        // get attendee object ( should already have it )
3582
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3583
-        $form->enqueueStylesAndScripts();
3584
-        echo wp_kses($form->display(), AllowedTags::getWithFormTags());
3585
-    }
3586
-
3587
-
3588
-    /**
3589
-     * Return form handler for the contact details metabox
3590
-     *
3591
-     * @param EE_Attendee $attendee
3592
-     * @return AttendeeContactDetailsMetaboxFormHandler
3593
-     * @throws DomainException
3594
-     * @throws InvalidArgumentException
3595
-     * @throws InvalidDataTypeException
3596
-     * @throws InvalidInterfaceException
3597
-     */
3598
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3599
-    {
3600
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3601
-    }
3602
-
3603
-
3604
-    /**
3605
-     * Metabox for attendee details
3606
-     *
3607
-     * @param WP_Post $post wp post object
3608
-     * @throws EE_Error
3609
-     * @throws ReflectionException
3610
-     */
3611
-    public function attendee_address_details($post)
3612
-    {
3613
-        // get attendee object (should already have it)
3614
-        $this->_template_args['attendee']     = $this->_cpt_model_obj;
3615
-        $this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3616
-            new EE_Question_Form_Input(
3617
-                EE_Question::new_instance(
3618
-                    [
3619
-                        'QST_ID'           => 0,
3620
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3621
-                        'QST_system'       => 'admin-state',
3622
-                    ]
3623
-                ),
3624
-                EE_Answer::new_instance(
3625
-                    [
3626
-                        'ANS_ID'    => 0,
3627
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3628
-                    ]
3629
-                ),
3630
-                [
3631
-                    'input_id'       => 'STA_ID',
3632
-                    'input_name'     => 'STA_ID',
3633
-                    'input_prefix'   => '',
3634
-                    'append_qstn_id' => false,
3635
-                ]
3636
-            )
3637
-        );
3638
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3639
-            new EE_Question_Form_Input(
3640
-                EE_Question::new_instance(
3641
-                    [
3642
-                        'QST_ID'           => 0,
3643
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3644
-                        'QST_system'       => 'admin-country',
3645
-                    ]
3646
-                ),
3647
-                EE_Answer::new_instance(
3648
-                    [
3649
-                        'ANS_ID'    => 0,
3650
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3651
-                    ]
3652
-                ),
3653
-                [
3654
-                    'input_id'       => 'CNT_ISO',
3655
-                    'input_name'     => 'CNT_ISO',
3656
-                    'input_prefix'   => '',
3657
-                    'append_qstn_id' => false,
3658
-                ]
3659
-            )
3660
-        );
3661
-        $template                             =
3662
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3663
-        EEH_Template::display_template($template, $this->_template_args);
3664
-    }
3665
-
3666
-
3667
-    /**
3668
-     * _attendee_details
3669
-     *
3670
-     * @param $post
3671
-     * @return void
3672
-     * @throws DomainException
3673
-     * @throws EE_Error
3674
-     * @throws InvalidArgumentException
3675
-     * @throws InvalidDataTypeException
3676
-     * @throws InvalidInterfaceException
3677
-     * @throws ReflectionException
3678
-     */
3679
-    public function attendee_registrations_meta_box($post)
3680
-    {
3681
-        $this->_template_args['attendee']      = $this->_cpt_model_obj;
3682
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3683
-        $template                              =
3684
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3685
-        EEH_Template::display_template($template, $this->_template_args);
3686
-    }
3687
-
3688
-
3689
-    /**
3690
-     * add in the form fields for the attendee edit
3691
-     *
3692
-     * @param WP_Post $post wp post object
3693
-     * @return void echos html for new form.
3694
-     * @throws DomainException
3695
-     */
3696
-    public function after_title_form_fields($post)
3697
-    {
3698
-        if ($post->post_type === 'espresso_attendees') {
3699
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3700
-            $template_args['attendee'] = $this->_cpt_model_obj;
3701
-            EEH_Template::display_template($template, $template_args);
3702
-        }
3703
-    }
3704
-
3705
-
3706
-    /**
3707
-     * _trash_or_restore_attendee
3708
-     *
3709
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3710
-     * @return void
3711
-     * @throws EE_Error
3712
-     * @throws InvalidArgumentException
3713
-     * @throws InvalidDataTypeException
3714
-     * @throws InvalidInterfaceException
3715
-     */
3716
-    protected function _trash_or_restore_attendees($trash = true)
3717
-    {
3718
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3719
-        $status = $trash ? 'trash' : 'publish';
3720
-        // Checkboxes
3721
-        if ($this->request->requestParamIsSet('checkbox')) {
3722
-            $ATT_IDs = $this->request->getRequestParam('checkbox', [], 'int', true);
3723
-            // if array has more than one element than success message should be plural
3724
-            $success = count($ATT_IDs) > 1 ? 2 : 1;
3725
-            // cycle thru checkboxes
3726
-            foreach ($ATT_IDs as $ATT_ID) {
3727
-                $updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3728
-                if (! $updated) {
3729
-                    $success = 0;
3730
-                }
3731
-            }
3732
-        } else {
3733
-            // grab single id and delete
3734
-            $ATT_ID = $this->request->getRequestParam('ATT_ID', 0, 'int');
3735
-            // update attendee
3736
-            $success = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID) ? 1 : 0;
3737
-        }
3738
-        $what        = $success > 1
3739
-            ? esc_html__('Contacts', 'event_espresso')
3740
-            : esc_html__('Contact', 'event_espresso');
3741
-        $action_desc = $trash
3742
-            ? esc_html__('moved to the trash', 'event_espresso')
3743
-            : esc_html__('restored', 'event_espresso');
3744
-        $this->_redirect_after_action($success, $what, $action_desc, ['action' => 'contact_list']);
3745
-    }
2898
+		}
2899
+		$template_args = [
2900
+			'title'                    => '',
2901
+			'content'                  => '',
2902
+			'step_button_text'         => '',
2903
+			'show_notification_toggle' => false,
2904
+		];
2905
+		// to indicate we're processing a new registration
2906
+		$hidden_fields = [
2907
+			'processing_registration' => [
2908
+				'type'  => 'hidden',
2909
+				'value' => 0,
2910
+			],
2911
+			'event_id'                => [
2912
+				'type'  => 'hidden',
2913
+				'value' => $this->_reg_event->ID(),
2914
+			],
2915
+		];
2916
+		// if the cart is empty then we know we're at step one, so we'll display the ticket selector
2917
+		$cart = EE_Registry::instance()->SSN->cart();
2918
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2919
+		switch ($step) {
2920
+			case 'ticket':
2921
+				$hidden_fields['processing_registration']['value'] = 1;
2922
+				$template_args['title']                            = esc_html__(
2923
+					'Step One: Select the Ticket for this registration',
2924
+					'event_espresso'
2925
+				);
2926
+				$template_args['content']                          =
2927
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2928
+				$template_args['content']                          .= '</div>';
2929
+				$template_args['step_button_text']                 = esc_html__(
2930
+					'Add Tickets and Continue to Registrant Details',
2931
+					'event_espresso'
2932
+				);
2933
+				$template_args['show_notification_toggle']         = false;
2934
+				break;
2935
+			case 'questions':
2936
+				$hidden_fields['processing_registration']['value'] = 2;
2937
+				$template_args['title']                            = esc_html__(
2938
+					'Step Two: Add Registrant Details for this Registration',
2939
+					'event_espresso'
2940
+				);
2941
+				// in theory, we should be able to run EED_SPCO at this point
2942
+				// because the cart should have been set up properly by the first process_reg_step run.
2943
+				$template_args['content']                  =
2944
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
2945
+				$template_args['step_button_text']         = esc_html__(
2946
+					'Save Registration and Continue to Details',
2947
+					'event_espresso'
2948
+				);
2949
+				$template_args['show_notification_toggle'] = true;
2950
+				break;
2951
+		}
2952
+		// we come back to the process_registration_step route.
2953
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2954
+		return EEH_Template::display_template(
2955
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2956
+			$template_args,
2957
+			true
2958
+		);
2959
+	}
2960
+
2961
+
2962
+	/**
2963
+	 * set_reg_event
2964
+	 *
2965
+	 * @return bool
2966
+	 * @throws EE_Error
2967
+	 * @throws InvalidArgumentException
2968
+	 * @throws InvalidDataTypeException
2969
+	 * @throws InvalidInterfaceException
2970
+	 */
2971
+	private function _set_reg_event()
2972
+	{
2973
+		if (is_object($this->_reg_event)) {
2974
+			return true;
2975
+		}
2976
+
2977
+		$EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2978
+		if (! $EVT_ID) {
2979
+			return false;
2980
+		}
2981
+		$this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2982
+		return true;
2983
+	}
2984
+
2985
+
2986
+	/**
2987
+	 * process_reg_step
2988
+	 *
2989
+	 * @return void
2990
+	 * @throws DomainException
2991
+	 * @throws EE_Error
2992
+	 * @throws InvalidArgumentException
2993
+	 * @throws InvalidDataTypeException
2994
+	 * @throws InvalidInterfaceException
2995
+	 * @throws ReflectionException
2996
+	 * @throws RuntimeException
2997
+	 */
2998
+	public function process_reg_step()
2999
+	{
3000
+		EE_System::do_not_cache();
3001
+		$this->_set_reg_event();
3002
+		/** @var CurrentPage $current_page */
3003
+		$current_page = $this->loader->getShared(CurrentPage::class);
3004
+		$current_page->setEspressoPage(true);
3005
+		$this->request->setRequestParam('uts', time());
3006
+		// what step are we on?
3007
+		$cart = EE_Registry::instance()->SSN->cart();
3008
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3009
+		// if doing ajax then we need to verify the nonce
3010
+		if ($this->request->isAjax()) {
3011
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
3012
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3013
+		}
3014
+		switch ($step) {
3015
+			case 'ticket':
3016
+				// process ticket selection
3017
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3018
+				if ($success) {
3019
+					EE_Error::add_success(
3020
+						esc_html__(
3021
+							'Tickets Selected. Now complete the registration.',
3022
+							'event_espresso'
3023
+						)
3024
+					);
3025
+				} else {
3026
+					$this->request->setRequestParam('step_error', true);
3027
+					$query_args['step_error'] = $this->request->getRequestParam('step_error', true, 'bool');
3028
+				}
3029
+				if ($this->request->isAjax()) {
3030
+					$this->new_registration(); // display next step
3031
+				} else {
3032
+					$query_args = [
3033
+						'action'                  => 'new_registration',
3034
+						'processing_registration' => 1,
3035
+						'event_id'                => $this->_reg_event->ID(),
3036
+						'uts'                     => time(),
3037
+					];
3038
+					$this->_redirect_after_action(
3039
+						false,
3040
+						'',
3041
+						'',
3042
+						$query_args,
3043
+						true
3044
+					);
3045
+				}
3046
+				break;
3047
+			case 'questions':
3048
+				if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3049
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3050
+				}
3051
+				// process registration
3052
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3053
+				if ($cart instanceof EE_Cart) {
3054
+					$grand_total = $cart->get_grand_total();
3055
+					if ($grand_total instanceof EE_Line_Item) {
3056
+						$grand_total->save_this_and_descendants_to_txn();
3057
+					}
3058
+				}
3059
+				if (! $transaction instanceof EE_Transaction) {
3060
+					$query_args = [
3061
+						'action'                  => 'new_registration',
3062
+						'processing_registration' => 2,
3063
+						'event_id'                => $this->_reg_event->ID(),
3064
+						'uts'                     => time(),
3065
+					];
3066
+					if ($this->request->isAjax()) {
3067
+						// display registration form again because there are errors (maybe validation?)
3068
+						$this->new_registration();
3069
+						return;
3070
+					}
3071
+					$this->_redirect_after_action(
3072
+						false,
3073
+						'',
3074
+						'',
3075
+						$query_args,
3076
+						true
3077
+					);
3078
+					return;
3079
+				}
3080
+				// maybe update status, and make sure to save transaction if not done already
3081
+				if (! $transaction->update_status_based_on_total_paid()) {
3082
+					$transaction->save();
3083
+				}
3084
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3085
+				$query_args = [
3086
+					'action'        => 'redirect_to_txn',
3087
+					'TXN_ID'        => $transaction->ID(),
3088
+					'EVT_ID'        => $this->_reg_event->ID(),
3089
+					'event_name'    => urlencode($this->_reg_event->name()),
3090
+					'redirect_from' => 'new_registration',
3091
+				];
3092
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3093
+				break;
3094
+		}
3095
+		// what are you looking here for?  Should be nothing to do at this point.
3096
+	}
3097
+
3098
+
3099
+	/**
3100
+	 * redirect_to_txn
3101
+	 *
3102
+	 * @return void
3103
+	 * @throws EE_Error
3104
+	 * @throws InvalidArgumentException
3105
+	 * @throws InvalidDataTypeException
3106
+	 * @throws InvalidInterfaceException
3107
+	 * @throws ReflectionException
3108
+	 */
3109
+	public function redirect_to_txn()
3110
+	{
3111
+		EE_System::do_not_cache();
3112
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3113
+		$query_args = [
3114
+			'action' => 'view_transaction',
3115
+			'TXN_ID' => $this->request->getRequestParam('TXN_ID', 0, 'int'),
3116
+			'page'   => 'espresso_transactions',
3117
+		];
3118
+		if ($this->request->requestParamIsSet('EVT_ID') && $this->request->requestParamIsSet('redirect_from')) {
3119
+			$query_args['EVT_ID']        = $this->request->getRequestParam('EVT_ID', 0, 'int');
3120
+			$query_args['event_name']    = urlencode($this->request->getRequestParam('event_name'));
3121
+			$query_args['redirect_from'] = $this->request->getRequestParam('redirect_from');
3122
+		}
3123
+		EE_Error::add_success(
3124
+			esc_html__(
3125
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3126
+				'event_espresso'
3127
+			)
3128
+		);
3129
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3130
+	}
3131
+
3132
+
3133
+	/**
3134
+	 * generates HTML for the Attendee Contact List
3135
+	 *
3136
+	 * @return void
3137
+	 * @throws DomainException
3138
+	 * @throws EE_Error
3139
+	 */
3140
+	protected function _attendee_contact_list_table()
3141
+	{
3142
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3143
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3144
+		$this->display_admin_list_table_page_with_no_sidebar();
3145
+	}
3146
+
3147
+
3148
+	/**
3149
+	 * get_attendees
3150
+	 *
3151
+	 * @param      $per_page
3152
+	 * @param bool $count whether to return count or data.
3153
+	 * @param bool $trash
3154
+	 * @return array|int
3155
+	 * @throws EE_Error
3156
+	 * @throws InvalidArgumentException
3157
+	 * @throws InvalidDataTypeException
3158
+	 * @throws InvalidInterfaceException
3159
+	 */
3160
+	public function get_attendees($per_page, $count = false, $trash = false)
3161
+	{
3162
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3163
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3164
+		$orderby = $this->request->getRequestParam('orderby');
3165
+		switch ($orderby) {
3166
+			case 'ATT_ID':
3167
+			case 'ATT_fname':
3168
+			case 'ATT_email':
3169
+			case 'ATT_city':
3170
+			case 'STA_ID':
3171
+			case 'CNT_ID':
3172
+				break;
3173
+			case 'Registration_Count':
3174
+				$orderby = 'Registration_Count';
3175
+				break;
3176
+			default:
3177
+				$orderby = 'ATT_lname';
3178
+		}
3179
+		$sort         = $this->request->getRequestParam('order', 'ASC');
3180
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
3181
+		$per_page     = absint($per_page) ? $per_page : 10;
3182
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
3183
+		$_where       = [];
3184
+		$search_term  = $this->request->getRequestParam('s');
3185
+		if ($search_term) {
3186
+			$search_term  = '%' . $search_term . '%';
3187
+			$_where['OR'] = [
3188
+				'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3189
+				'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
3190
+				'Registration.Event.EVT_short_desc' => ['LIKE', $search_term],
3191
+				'ATT_fname'                         => ['LIKE', $search_term],
3192
+				'ATT_lname'                         => ['LIKE', $search_term],
3193
+				'ATT_short_bio'                     => ['LIKE', $search_term],
3194
+				'ATT_email'                         => ['LIKE', $search_term],
3195
+				'ATT_address'                       => ['LIKE', $search_term],
3196
+				'ATT_address2'                      => ['LIKE', $search_term],
3197
+				'ATT_city'                          => ['LIKE', $search_term],
3198
+				'Country.CNT_name'                  => ['LIKE', $search_term],
3199
+				'State.STA_name'                    => ['LIKE', $search_term],
3200
+				'ATT_phone'                         => ['LIKE', $search_term],
3201
+				'Registration.REG_final_price'      => ['LIKE', $search_term],
3202
+				'Registration.REG_code'             => ['LIKE', $search_term],
3203
+				'Registration.REG_group_size'       => ['LIKE', $search_term],
3204
+			];
3205
+		}
3206
+		$offset     = ($current_page - 1) * $per_page;
3207
+		$limit      = $count ? null : [$offset, $per_page];
3208
+		$query_args = [
3209
+			$_where,
3210
+			'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3211
+			'limit'         => $limit,
3212
+		];
3213
+		if (! $count) {
3214
+			$query_args['order_by'] = [$orderby => $sort];
3215
+		}
3216
+		$query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
3217
+		return $count
3218
+			? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3219
+			: $this->getAttendeeModel()->get_all($query_args);
3220
+	}
3221
+
3222
+
3223
+	/**
3224
+	 * This is just taking care of resending the registration confirmation
3225
+	 *
3226
+	 * @return void
3227
+	 * @throws EE_Error
3228
+	 * @throws InvalidArgumentException
3229
+	 * @throws InvalidDataTypeException
3230
+	 * @throws InvalidInterfaceException
3231
+	 * @throws ReflectionException
3232
+	 */
3233
+	protected function _resend_registration()
3234
+	{
3235
+		$this->_process_resend_registration();
3236
+		$REG_ID      = $this->request->getRequestParam('_REG_ID', 0, 'int');
3237
+		$redirect_to = $this->request->getRequestParam('redirect_to');
3238
+		$query_args  = $redirect_to
3239
+			? ['action' => $redirect_to, '_REG_ID' => $REG_ID]
3240
+			: ['action' => 'default'];
3241
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3242
+	}
3243
+
3244
+
3245
+	/**
3246
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3247
+	 * to use when selecting registrations
3248
+	 *
3249
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3250
+	 *                                                     the query parameters from the request
3251
+	 * @return void ends the request with a redirect or download
3252
+	 */
3253
+	public function _registrations_report_base($method_name_for_getting_query_params)
3254
+	{
3255
+		$EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3256
+			? $this->request->getRequestParam('EVT_ID', 0, 'int')
3257
+			: null;
3258
+
3259
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3260
+			$request_params = $this->request->requestParams();
3261
+			wp_redirect(
3262
+				EE_Admin_Page::add_query_args_and_nonce(
3263
+					[
3264
+						'page'        => 'espresso_batch',
3265
+						'batch'       => 'file',
3266
+						'EVT_ID'      => $EVT_ID,
3267
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3268
+						'return_url'  => urlencode($this->request->getRequestParam('return_url', '', DataType::URL)),
3269
+						'filters'     => urlencode(
3270
+							serialize(
3271
+								$this->$method_name_for_getting_query_params(
3272
+									(isset($request_params['filters']) ? $request_params['filters'] : [])
3273
+								)
3274
+							)
3275
+						),
3276
+						'use_filters' => $this->request->getRequestParam('use_filters', false, DataType::BOOL)
3277
+					]
3278
+				)
3279
+			);
3280
+		} else {
3281
+			// Pull the current request params
3282
+			$request_args = $this->request->requestParams();
3283
+			// Set the required request_args to be passed to the export
3284
+			$required_request_args = [
3285
+				'export' => 'report',
3286
+				'action' => 'registrations_report_for_event',
3287
+				'EVT_ID' => $EVT_ID,
3288
+			];
3289
+			// Merge required request args, overriding any currently set
3290
+			$request_args = array_merge($request_args, $required_request_args);
3291
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3292
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3293
+				$EE_Export = EE_Export::instance($request_args);
3294
+				$EE_Export->export();
3295
+			}
3296
+		}
3297
+	}
3298
+
3299
+
3300
+	/**
3301
+	 * Creates a registration report using only query parameters in the request
3302
+	 *
3303
+	 * @return void
3304
+	 */
3305
+	public function _registrations_report()
3306
+	{
3307
+		$this->_registrations_report_base('_get_registration_query_parameters');
3308
+	}
3309
+
3310
+
3311
+	public function _contact_list_export()
3312
+	{
3313
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3314
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3315
+			$EE_Export = EE_Export::instance($this->request->requestParams());
3316
+			$EE_Export->export_attendees();
3317
+		}
3318
+	}
3319
+
3320
+
3321
+	public function _contact_list_report()
3322
+	{
3323
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3324
+			wp_redirect(
3325
+				EE_Admin_Page::add_query_args_and_nonce(
3326
+					[
3327
+						'page'        => 'espresso_batch',
3328
+						'batch'       => 'file',
3329
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3330
+						'return_url'  => urlencode($this->request->getRequestParam('return_url', '', 'url')),
3331
+					]
3332
+				)
3333
+			);
3334
+		} else {
3335
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3336
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3337
+				$EE_Export = EE_Export::instance($this->request->requestParams());
3338
+				$EE_Export->report_attendees();
3339
+			}
3340
+		}
3341
+	}
3342
+
3343
+
3344
+
3345
+
3346
+
3347
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3348
+	/**
3349
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3350
+	 *
3351
+	 * @return void
3352
+	 * @throws EE_Error
3353
+	 * @throws InvalidArgumentException
3354
+	 * @throws InvalidDataTypeException
3355
+	 * @throws InvalidInterfaceException
3356
+	 * @throws ReflectionException
3357
+	 */
3358
+	protected function _duplicate_attendee()
3359
+	{
3360
+		$REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3361
+		$action = $this->request->getRequestParam('return', 'default');
3362
+		// verify we have necessary info
3363
+		if (! $REG_ID) {
3364
+			EE_Error::add_error(
3365
+				esc_html__(
3366
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3367
+					'event_espresso'
3368
+				),
3369
+				__FILE__,
3370
+				__LINE__,
3371
+				__FUNCTION__
3372
+			);
3373
+			$query_args = ['action' => $action];
3374
+			$this->_redirect_after_action('', '', '', $query_args, true);
3375
+		}
3376
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3377
+		$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3378
+		if (! $registration instanceof EE_Registration) {
3379
+			throw new RuntimeException(
3380
+				sprintf(
3381
+					esc_html__(
3382
+						'Unable to create the contact because a valid registration could not be retrieved for REG ID: %1$d',
3383
+						'event_espresso'
3384
+					),
3385
+					$REG_ID
3386
+				)
3387
+			);
3388
+		}
3389
+		$attendee = $registration->attendee();
3390
+		// remove relation of existing attendee on registration
3391
+		$registration->_remove_relation_to($attendee, 'Attendee');
3392
+		// new attendee
3393
+		$new_attendee = clone $attendee;
3394
+		$new_attendee->set('ATT_ID', 0);
3395
+		$new_attendee->save();
3396
+		// add new attendee to reg
3397
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3398
+		EE_Error::add_success(
3399
+			esc_html__(
3400
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3401
+				'event_espresso'
3402
+			)
3403
+		);
3404
+		// redirect to edit page for attendee
3405
+		$query_args = ['post' => $new_attendee->ID(), 'action' => 'edit_attendee'];
3406
+		$this->_redirect_after_action('', '', '', $query_args, true);
3407
+	}
3408
+
3409
+
3410
+	/**
3411
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3412
+	 *
3413
+	 * @param int     $post_id
3414
+	 * @param WP_Post $post
3415
+	 * @throws DomainException
3416
+	 * @throws EE_Error
3417
+	 * @throws InvalidArgumentException
3418
+	 * @throws InvalidDataTypeException
3419
+	 * @throws InvalidInterfaceException
3420
+	 * @throws LogicException
3421
+	 * @throws InvalidFormSubmissionException
3422
+	 * @throws ReflectionException
3423
+	 */
3424
+	protected function _insert_update_cpt_item($post_id, $post)
3425
+	{
3426
+		$success  = true;
3427
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3428
+			? $this->getAttendeeModel()->get_one_by_ID($post_id)
3429
+			: null;
3430
+		// for attendee updates
3431
+		if ($attendee instanceof EE_Attendee) {
3432
+			// note we should only be UPDATING attendees at this point.
3433
+			$fname          = $this->request->getRequestParam('ATT_fname', '');
3434
+			$lname          = $this->request->getRequestParam('ATT_lname', '');
3435
+			$updated_fields = [
3436
+				'ATT_fname'     => $fname,
3437
+				'ATT_lname'     => $lname,
3438
+				'ATT_full_name' => "{$fname} {$lname}",
3439
+				'ATT_address'   => $this->request->getRequestParam('ATT_address', ''),
3440
+				'ATT_address2'  => $this->request->getRequestParam('ATT_address2', ''),
3441
+				'ATT_city'      => $this->request->getRequestParam('ATT_city', ''),
3442
+				'STA_ID'        => $this->request->getRequestParam('STA_ID', ''),
3443
+				'CNT_ISO'       => $this->request->getRequestParam('CNT_ISO', ''),
3444
+				'ATT_zip'       => $this->request->getRequestParam('ATT_zip', ''),
3445
+			];
3446
+			foreach ($updated_fields as $field => $value) {
3447
+				$attendee->set($field, $value);
3448
+			}
3449
+
3450
+			// process contact details metabox form handler (which will also save the attendee)
3451
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3452
+			$success              = $contact_details_form->process($this->request->requestParams());
3453
+
3454
+			$attendee_update_callbacks = apply_filters(
3455
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3456
+				[]
3457
+			);
3458
+			foreach ($attendee_update_callbacks as $a_callback) {
3459
+				if (false === call_user_func_array($a_callback, [$attendee, $this->request->requestParams()])) {
3460
+					throw new EE_Error(
3461
+						sprintf(
3462
+							esc_html__(
3463
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3464
+								'event_espresso'
3465
+							),
3466
+							$a_callback
3467
+						)
3468
+					);
3469
+				}
3470
+			}
3471
+		}
3472
+
3473
+		if ($success === false) {
3474
+			EE_Error::add_error(
3475
+				esc_html__(
3476
+					'Something went wrong with updating the meta table data for the registration.',
3477
+					'event_espresso'
3478
+				),
3479
+				__FILE__,
3480
+				__FUNCTION__,
3481
+				__LINE__
3482
+			);
3483
+		}
3484
+	}
3485
+
3486
+
3487
+	public function trash_cpt_item($post_id)
3488
+	{
3489
+	}
3490
+
3491
+
3492
+	public function delete_cpt_item($post_id)
3493
+	{
3494
+	}
3495
+
3496
+
3497
+	public function restore_cpt_item($post_id)
3498
+	{
3499
+	}
3500
+
3501
+
3502
+	protected function _restore_cpt_item($post_id, $revision_id)
3503
+	{
3504
+	}
3505
+
3506
+
3507
+	/**
3508
+	 * @throws EE_Error
3509
+	 * @throws ReflectionException
3510
+	 * @since 4.10.2.p
3511
+	 */
3512
+	public function attendee_editor_metaboxes()
3513
+	{
3514
+		$this->verify_cpt_object();
3515
+		remove_meta_box(
3516
+			'postexcerpt',
3517
+			$this->_cpt_routes[ $this->_req_action ],
3518
+			'normal'
3519
+		);
3520
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3521
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3522
+			add_meta_box(
3523
+				'postexcerpt',
3524
+				esc_html__('Short Biography', 'event_espresso'),
3525
+				'post_excerpt_meta_box',
3526
+				$this->_cpt_routes[ $this->_req_action ],
3527
+				'normal'
3528
+			);
3529
+		}
3530
+		if (post_type_supports('espresso_attendees', 'comments')) {
3531
+			add_meta_box(
3532
+				'commentsdiv',
3533
+				esc_html__('Notes on the Contact', 'event_espresso'),
3534
+				'post_comment_meta_box',
3535
+				$this->_cpt_routes[ $this->_req_action ],
3536
+				'normal',
3537
+				'core'
3538
+			);
3539
+		}
3540
+		add_meta_box(
3541
+			'attendee_contact_info',
3542
+			esc_html__('Contact Info', 'event_espresso'),
3543
+			[$this, 'attendee_contact_info'],
3544
+			$this->_cpt_routes[ $this->_req_action ],
3545
+			'side',
3546
+			'core'
3547
+		);
3548
+		add_meta_box(
3549
+			'attendee_details_address',
3550
+			esc_html__('Address Details', 'event_espresso'),
3551
+			[$this, 'attendee_address_details'],
3552
+			$this->_cpt_routes[ $this->_req_action ],
3553
+			'normal',
3554
+			'core'
3555
+		);
3556
+		add_meta_box(
3557
+			'attendee_registrations',
3558
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3559
+			[$this, 'attendee_registrations_meta_box'],
3560
+			$this->_cpt_routes[ $this->_req_action ],
3561
+			'normal',
3562
+			'high'
3563
+		);
3564
+	}
3565
+
3566
+
3567
+	/**
3568
+	 * Metabox for attendee contact info
3569
+	 *
3570
+	 * @param WP_Post $post wp post object
3571
+	 * @return void attendee contact info ( and form )
3572
+	 * @throws EE_Error
3573
+	 * @throws InvalidArgumentException
3574
+	 * @throws InvalidDataTypeException
3575
+	 * @throws InvalidInterfaceException
3576
+	 * @throws LogicException
3577
+	 * @throws DomainException
3578
+	 */
3579
+	public function attendee_contact_info($post)
3580
+	{
3581
+		// get attendee object ( should already have it )
3582
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3583
+		$form->enqueueStylesAndScripts();
3584
+		echo wp_kses($form->display(), AllowedTags::getWithFormTags());
3585
+	}
3586
+
3587
+
3588
+	/**
3589
+	 * Return form handler for the contact details metabox
3590
+	 *
3591
+	 * @param EE_Attendee $attendee
3592
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3593
+	 * @throws DomainException
3594
+	 * @throws InvalidArgumentException
3595
+	 * @throws InvalidDataTypeException
3596
+	 * @throws InvalidInterfaceException
3597
+	 */
3598
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3599
+	{
3600
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3601
+	}
3602
+
3603
+
3604
+	/**
3605
+	 * Metabox for attendee details
3606
+	 *
3607
+	 * @param WP_Post $post wp post object
3608
+	 * @throws EE_Error
3609
+	 * @throws ReflectionException
3610
+	 */
3611
+	public function attendee_address_details($post)
3612
+	{
3613
+		// get attendee object (should already have it)
3614
+		$this->_template_args['attendee']     = $this->_cpt_model_obj;
3615
+		$this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3616
+			new EE_Question_Form_Input(
3617
+				EE_Question::new_instance(
3618
+					[
3619
+						'QST_ID'           => 0,
3620
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3621
+						'QST_system'       => 'admin-state',
3622
+					]
3623
+				),
3624
+				EE_Answer::new_instance(
3625
+					[
3626
+						'ANS_ID'    => 0,
3627
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3628
+					]
3629
+				),
3630
+				[
3631
+					'input_id'       => 'STA_ID',
3632
+					'input_name'     => 'STA_ID',
3633
+					'input_prefix'   => '',
3634
+					'append_qstn_id' => false,
3635
+				]
3636
+			)
3637
+		);
3638
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3639
+			new EE_Question_Form_Input(
3640
+				EE_Question::new_instance(
3641
+					[
3642
+						'QST_ID'           => 0,
3643
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3644
+						'QST_system'       => 'admin-country',
3645
+					]
3646
+				),
3647
+				EE_Answer::new_instance(
3648
+					[
3649
+						'ANS_ID'    => 0,
3650
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3651
+					]
3652
+				),
3653
+				[
3654
+					'input_id'       => 'CNT_ISO',
3655
+					'input_name'     => 'CNT_ISO',
3656
+					'input_prefix'   => '',
3657
+					'append_qstn_id' => false,
3658
+				]
3659
+			)
3660
+		);
3661
+		$template                             =
3662
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3663
+		EEH_Template::display_template($template, $this->_template_args);
3664
+	}
3665
+
3666
+
3667
+	/**
3668
+	 * _attendee_details
3669
+	 *
3670
+	 * @param $post
3671
+	 * @return void
3672
+	 * @throws DomainException
3673
+	 * @throws EE_Error
3674
+	 * @throws InvalidArgumentException
3675
+	 * @throws InvalidDataTypeException
3676
+	 * @throws InvalidInterfaceException
3677
+	 * @throws ReflectionException
3678
+	 */
3679
+	public function attendee_registrations_meta_box($post)
3680
+	{
3681
+		$this->_template_args['attendee']      = $this->_cpt_model_obj;
3682
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3683
+		$template                              =
3684
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3685
+		EEH_Template::display_template($template, $this->_template_args);
3686
+	}
3687
+
3688
+
3689
+	/**
3690
+	 * add in the form fields for the attendee edit
3691
+	 *
3692
+	 * @param WP_Post $post wp post object
3693
+	 * @return void echos html for new form.
3694
+	 * @throws DomainException
3695
+	 */
3696
+	public function after_title_form_fields($post)
3697
+	{
3698
+		if ($post->post_type === 'espresso_attendees') {
3699
+			$template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3700
+			$template_args['attendee'] = $this->_cpt_model_obj;
3701
+			EEH_Template::display_template($template, $template_args);
3702
+		}
3703
+	}
3704
+
3705
+
3706
+	/**
3707
+	 * _trash_or_restore_attendee
3708
+	 *
3709
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3710
+	 * @return void
3711
+	 * @throws EE_Error
3712
+	 * @throws InvalidArgumentException
3713
+	 * @throws InvalidDataTypeException
3714
+	 * @throws InvalidInterfaceException
3715
+	 */
3716
+	protected function _trash_or_restore_attendees($trash = true)
3717
+	{
3718
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3719
+		$status = $trash ? 'trash' : 'publish';
3720
+		// Checkboxes
3721
+		if ($this->request->requestParamIsSet('checkbox')) {
3722
+			$ATT_IDs = $this->request->getRequestParam('checkbox', [], 'int', true);
3723
+			// if array has more than one element than success message should be plural
3724
+			$success = count($ATT_IDs) > 1 ? 2 : 1;
3725
+			// cycle thru checkboxes
3726
+			foreach ($ATT_IDs as $ATT_ID) {
3727
+				$updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3728
+				if (! $updated) {
3729
+					$success = 0;
3730
+				}
3731
+			}
3732
+		} else {
3733
+			// grab single id and delete
3734
+			$ATT_ID = $this->request->getRequestParam('ATT_ID', 0, 'int');
3735
+			// update attendee
3736
+			$success = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID) ? 1 : 0;
3737
+		}
3738
+		$what        = $success > 1
3739
+			? esc_html__('Contacts', 'event_espresso')
3740
+			: esc_html__('Contact', 'event_espresso');
3741
+		$action_desc = $trash
3742
+			? esc_html__('moved to the trash', 'event_espresso')
3743
+			: esc_html__('restored', 'event_espresso');
3744
+		$this->_redirect_after_action($success, $what, $action_desc, ['action' => 'contact_list']);
3745
+	}
3746 3746
 }
Please login to merge, or discard this patch.
public/template_tags.php 1 patch
Indentation   +1057 added lines, -1057 removed lines patch added patch discarded remove patch
@@ -19,13 +19,13 @@  discard block
 block discarded – undo
19 19
  */
20 20
 function is_espresso_event($event = null)
21 21
 {
22
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
23
-        // extract EE_Event object from passed param regardless of what it is (within reason of course)
24
-        $event = EEH_Event_View::get_event($event);
25
-        // do we have a valid event ?
26
-        return $event instanceof EE_Event;
27
-    }
28
-    return false;
22
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
23
+		// extract EE_Event object from passed param regardless of what it is (within reason of course)
24
+		$event = EEH_Event_View::get_event($event);
25
+		// do we have a valid event ?
26
+		return $event instanceof EE_Event;
27
+	}
28
+	return false;
29 29
 }
30 30
 
31 31
 /**
@@ -36,12 +36,12 @@  discard block
 block discarded – undo
36 36
  */
37 37
 function is_espresso_event_single()
38 38
 {
39
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
40
-        global $wp_query;
41
-        // return conditionals set by CPTs
42
-        return $wp_query instanceof WP_Query ? $wp_query->is_espresso_event_single : false;
43
-    }
44
-    return false;
39
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
40
+		global $wp_query;
41
+		// return conditionals set by CPTs
42
+		return $wp_query instanceof WP_Query ? $wp_query->is_espresso_event_single : false;
43
+	}
44
+	return false;
45 45
 }
46 46
 
47 47
 /**
@@ -52,11 +52,11 @@  discard block
 block discarded – undo
52 52
  */
53 53
 function is_espresso_event_archive()
54 54
 {
55
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
56
-        global $wp_query;
57
-        return $wp_query instanceof WP_Query ? $wp_query->is_espresso_event_archive : false;
58
-    }
59
-    return false;
55
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
56
+		global $wp_query;
57
+		return $wp_query instanceof WP_Query ? $wp_query->is_espresso_event_archive : false;
58
+	}
59
+	return false;
60 60
 }
61 61
 
62 62
 /**
@@ -67,11 +67,11 @@  discard block
 block discarded – undo
67 67
  */
68 68
 function is_espresso_event_taxonomy()
69 69
 {
70
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
71
-        global $wp_query;
72
-        return $wp_query instanceof WP_Query ? $wp_query->is_espresso_event_taxonomy : false;
73
-    }
74
-    return false;
70
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
71
+		global $wp_query;
72
+		return $wp_query instanceof WP_Query ? $wp_query->is_espresso_event_taxonomy : false;
73
+	}
74
+	return false;
75 75
 }
76 76
 
77 77
 /**
@@ -85,13 +85,13 @@  discard block
 block discarded – undo
85 85
  */
86 86
 function is_espresso_venue($venue = null)
87 87
 {
88
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
89
-        // extract EE_Venue object from passed param regardless of what it is (within reason of course)
90
-        $venue = EEH_Venue_View::get_venue($venue, false);
91
-        // do we have a valid event ?
92
-        return $venue instanceof EE_Venue;
93
-    }
94
-    return false;
88
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
89
+		// extract EE_Venue object from passed param regardless of what it is (within reason of course)
90
+		$venue = EEH_Venue_View::get_venue($venue, false);
91
+		// do we have a valid event ?
92
+		return $venue instanceof EE_Venue;
93
+	}
94
+	return false;
95 95
 }
96 96
 
97 97
 /**
@@ -102,11 +102,11 @@  discard block
 block discarded – undo
102 102
  */
103 103
 function is_espresso_venue_single()
104 104
 {
105
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
106
-        global $wp_query;
107
-        return $wp_query instanceof WP_Query ? $wp_query->is_espresso_venue_single : false;
108
-    }
109
-    return false;
105
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
106
+		global $wp_query;
107
+		return $wp_query instanceof WP_Query ? $wp_query->is_espresso_venue_single : false;
108
+	}
109
+	return false;
110 110
 }
111 111
 
112 112
 /**
@@ -117,11 +117,11 @@  discard block
 block discarded – undo
117 117
  */
118 118
 function is_espresso_venue_archive()
119 119
 {
120
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
121
-        global $wp_query;
122
-        return $wp_query instanceof WP_Query ? $wp_query->is_espresso_venue_archive : false;
123
-    }
124
-    return false;
120
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
121
+		global $wp_query;
122
+		return $wp_query instanceof WP_Query ? $wp_query->is_espresso_venue_archive : false;
123
+	}
124
+	return false;
125 125
 }
126 126
 
127 127
 /**
@@ -132,11 +132,11 @@  discard block
 block discarded – undo
132 132
  */
133 133
 function is_espresso_venue_taxonomy()
134 134
 {
135
-    if (can_use_espresso_conditionals(__FUNCTION__)) {
136
-        global $wp_query;
137
-        return $wp_query instanceof WP_Query ? $wp_query->is_espresso_venue_taxonomy : false;
138
-    }
139
-    return false;
135
+	if (can_use_espresso_conditionals(__FUNCTION__)) {
136
+		global $wp_query;
137
+		return $wp_query instanceof WP_Query ? $wp_query->is_espresso_venue_taxonomy : false;
138
+	}
139
+	return false;
140 140
 }
141 141
 
142 142
 /**
@@ -148,62 +148,62 @@  discard block
 block discarded – undo
148 148
  */
149 149
 function can_use_espresso_conditionals($conditional_tag)
150 150
 {
151
-    if (! did_action('AHEE__EE_System__initialize')) {
152
-        EE_Error::doing_it_wrong(
153
-            __FUNCTION__,
154
-            sprintf(
155
-                esc_html__(
156
-                    'The "%s" conditional tag can not be used until after the "init" hook has run, but works best when used within a theme\'s template files.',
157
-                    'event_espresso'
158
-                ),
159
-                $conditional_tag
160
-            ),
161
-            '4.4.0'
162
-        );
163
-        return false;
164
-    }
165
-    return true;
151
+	if (! did_action('AHEE__EE_System__initialize')) {
152
+		EE_Error::doing_it_wrong(
153
+			__FUNCTION__,
154
+			sprintf(
155
+				esc_html__(
156
+					'The "%s" conditional tag can not be used until after the "init" hook has run, but works best when used within a theme\'s template files.',
157
+					'event_espresso'
158
+				),
159
+				$conditional_tag
160
+			),
161
+			'4.4.0'
162
+		);
163
+		return false;
164
+	}
165
+	return true;
166 166
 }
167 167
 
168 168
 
169 169
 /*************************** Event Queries ***************************/
170 170
 
171 171
 if (! function_exists('espresso_get_events')) {
172
-    /**
173
-     *    espresso_get_events
174
-     *
175
-     * @param array $params
176
-     * @return array
177
-     */
178
-    function espresso_get_events($params = [])
179
-    {
180
-        //set default params
181
-        $default_espresso_events_params = [
182
-            'limit'         => 10,
183
-            'show_expired'  => false,
184
-            'month'         => null,
185
-            'category_slug' => null,
186
-            'order_by'      => 'start_date',
187
-            'sort'          => 'ASC',
188
-        ];
189
-        // allow the defaults to be filtered
190
-        $default_espresso_events_params = apply_filters(
191
-            'espresso_get_events__default_espresso_events_params',
192
-            $default_espresso_events_params
193
-        );
194
-        // grab params and merge with defaults, then extract
195
-        $params = array_merge($default_espresso_events_params, $params);
196
-        // run the query
197
-        $events_query = new EventEspresso\core\domain\services\wp_queries\EventListQuery($params);
198
-        // assign results to a variable so we can return it
199
-        $events = $events_query->have_posts() ? $events_query->posts : [];
200
-        // but first reset the query and postdata
201
-        wp_reset_query();
202
-        wp_reset_postdata();
203
-        EED_Events_Archive::remove_all_events_archive_filters();
204
-        unset($events_query);
205
-        return $events;
206
-    }
172
+	/**
173
+	 *    espresso_get_events
174
+	 *
175
+	 * @param array $params
176
+	 * @return array
177
+	 */
178
+	function espresso_get_events($params = [])
179
+	{
180
+		//set default params
181
+		$default_espresso_events_params = [
182
+			'limit'         => 10,
183
+			'show_expired'  => false,
184
+			'month'         => null,
185
+			'category_slug' => null,
186
+			'order_by'      => 'start_date',
187
+			'sort'          => 'ASC',
188
+		];
189
+		// allow the defaults to be filtered
190
+		$default_espresso_events_params = apply_filters(
191
+			'espresso_get_events__default_espresso_events_params',
192
+			$default_espresso_events_params
193
+		);
194
+		// grab params and merge with defaults, then extract
195
+		$params = array_merge($default_espresso_events_params, $params);
196
+		// run the query
197
+		$events_query = new EventEspresso\core\domain\services\wp_queries\EventListQuery($params);
198
+		// assign results to a variable so we can return it
199
+		$events = $events_query->have_posts() ? $events_query->posts : [];
200
+		// but first reset the query and postdata
201
+		wp_reset_query();
202
+		wp_reset_postdata();
203
+		EED_Events_Archive::remove_all_events_archive_filters();
204
+		unset($events_query);
205
+		return $events;
206
+	}
207 207
 }
208 208
 
209 209
 
@@ -218,357 +218,357 @@  discard block
 block discarded – undo
218 218
  */
219 219
 function espresso_load_ticket_selector()
220 220
 {
221
-    EE_Registry::instance()->load_file(EE_MODULES . 'ticket_selector', 'EED_Ticket_Selector', 'module');
221
+	EE_Registry::instance()->load_file(EE_MODULES . 'ticket_selector', 'EED_Ticket_Selector', 'module');
222 222
 }
223 223
 
224 224
 if (! function_exists('espresso_ticket_selector')) {
225
-    /**
226
-     * espresso_ticket_selector
227
-     *
228
-     * @param null $event
229
-     * @throws EE_Error
230
-     * @throws ReflectionException
231
-     */
232
-    function espresso_ticket_selector($event = null)
233
-    {
234
-        if (! apply_filters('FHEE_disable_espresso_ticket_selector', false)) {
235
-            espresso_load_ticket_selector();
236
-            EED_Ticket_Selector::set_definitions();
237
-            echo EED_Ticket_Selector::display_ticket_selector($event); // already escaped
238
-        }
239
-    }
225
+	/**
226
+	 * espresso_ticket_selector
227
+	 *
228
+	 * @param null $event
229
+	 * @throws EE_Error
230
+	 * @throws ReflectionException
231
+	 */
232
+	function espresso_ticket_selector($event = null)
233
+	{
234
+		if (! apply_filters('FHEE_disable_espresso_ticket_selector', false)) {
235
+			espresso_load_ticket_selector();
236
+			EED_Ticket_Selector::set_definitions();
237
+			echo EED_Ticket_Selector::display_ticket_selector($event); // already escaped
238
+		}
239
+	}
240 240
 }
241 241
 
242 242
 
243 243
 if (! function_exists('espresso_view_details_btn')) {
244
-    /**
245
-     * espresso_view_details_btn
246
-     *
247
-     * @param null $event
248
-     * @throws EE_Error
249
-     * @throws ReflectionException
250
-     */
251
-    function espresso_view_details_btn($event = null)
252
-    {
253
-        if (! apply_filters('FHEE_disable_espresso_view_details_btn', false)) {
254
-            espresso_load_ticket_selector();
255
-            echo EED_Ticket_Selector::display_ticket_selector($event, true); // already escaped
256
-        }
257
-    }
244
+	/**
245
+	 * espresso_view_details_btn
246
+	 *
247
+	 * @param null $event
248
+	 * @throws EE_Error
249
+	 * @throws ReflectionException
250
+	 */
251
+	function espresso_view_details_btn($event = null)
252
+	{
253
+		if (! apply_filters('FHEE_disable_espresso_view_details_btn', false)) {
254
+			espresso_load_ticket_selector();
255
+			echo EED_Ticket_Selector::display_ticket_selector($event, true); // already escaped
256
+		}
257
+	}
258 258
 }
259 259
 
260 260
 
261 261
 /*************************** EEH_Event_View ***************************/
262 262
 
263 263
 if (! function_exists('espresso_load_event_list_assets')) {
264
-    /**
265
-     * espresso_load_event_list_assets
266
-     * ensures that event list styles and scripts are loaded
267
-     *
268
-     * @return void
269
-     */
270
-    function espresso_load_event_list_assets()
271
-    {
272
-        $event_list = EED_Events_Archive::instance();
273
-        add_action('AHEE__EE_System__initialize_last', [$event_list, 'load_event_list_assets'], 10);
274
-        add_filter('FHEE_enable_default_espresso_css', '__return_true');
275
-    }
264
+	/**
265
+	 * espresso_load_event_list_assets
266
+	 * ensures that event list styles and scripts are loaded
267
+	 *
268
+	 * @return void
269
+	 */
270
+	function espresso_load_event_list_assets()
271
+	{
272
+		$event_list = EED_Events_Archive::instance();
273
+		add_action('AHEE__EE_System__initialize_last', [$event_list, 'load_event_list_assets'], 10);
274
+		add_filter('FHEE_enable_default_espresso_css', '__return_true');
275
+	}
276 276
 }
277 277
 
278 278
 
279 279
 if (! function_exists('espresso_event_reg_button')) {
280
-    /**
281
-     * espresso_event_reg_button
282
-     * returns the "Register Now" button if event is active,
283
-     * an inactive button like status banner if the event is not active
284
-     * or a "Read More" button if so desired
285
-     *
286
-     * @param null $btn_text_if_active
287
-     * @param bool $btn_text_if_inactive
288
-     * @param bool $EVT_ID
289
-     * @return void
290
-     * @throws EE_Error
291
-     * @throws ReflectionException
292
-     */
293
-    function espresso_event_reg_button($btn_text_if_active = null, $btn_text_if_inactive = false, $EVT_ID = false)
294
-    {
295
-        $event = EEH_Event_View::get_event($EVT_ID);
296
-        if (! $event instanceof EE_Event) {
297
-            return;
298
-        }
299
-        $event_status = $event->get_active_status();
300
-        switch ($event_status) {
301
-            case EE_Datetime::sold_out :
302
-                $btn_text = __('Sold Out', 'event_espresso');
303
-                $class    = 'ee-pink';
304
-                break;
305
-            case EE_Datetime::expired :
306
-                $btn_text = __('Event is Over', 'event_espresso');
307
-                $class    = 'ee-grey';
308
-                break;
309
-            case EE_Datetime::inactive :
310
-                $btn_text = __('Event Not Active', 'event_espresso');
311
-                $class    = 'ee-grey';
312
-                break;
313
-            case EE_Datetime::cancelled :
314
-                $btn_text = __('Event was Cancelled', 'event_espresso');
315
-                $class    = 'ee-red';
316
-                break;
317
-            case EE_Datetime::upcoming :
318
-            case EE_Datetime::active :
319
-            default :
320
-                $btn_text = ! empty($btn_text_if_active)
321
-                    ? $btn_text_if_active
322
-                    : __('Register Now', 'event_espresso');
323
-                $class    = 'ee-green';
324
-        }
325
-        if ($event_status < 1 && ! empty($btn_text_if_inactive)) {
326
-            $btn_text = $btn_text_if_inactive;
327
-            $class    = 'ee-grey';
328
-        }
329
-        ?>
280
+	/**
281
+	 * espresso_event_reg_button
282
+	 * returns the "Register Now" button if event is active,
283
+	 * an inactive button like status banner if the event is not active
284
+	 * or a "Read More" button if so desired
285
+	 *
286
+	 * @param null $btn_text_if_active
287
+	 * @param bool $btn_text_if_inactive
288
+	 * @param bool $EVT_ID
289
+	 * @return void
290
+	 * @throws EE_Error
291
+	 * @throws ReflectionException
292
+	 */
293
+	function espresso_event_reg_button($btn_text_if_active = null, $btn_text_if_inactive = false, $EVT_ID = false)
294
+	{
295
+		$event = EEH_Event_View::get_event($EVT_ID);
296
+		if (! $event instanceof EE_Event) {
297
+			return;
298
+		}
299
+		$event_status = $event->get_active_status();
300
+		switch ($event_status) {
301
+			case EE_Datetime::sold_out :
302
+				$btn_text = __('Sold Out', 'event_espresso');
303
+				$class    = 'ee-pink';
304
+				break;
305
+			case EE_Datetime::expired :
306
+				$btn_text = __('Event is Over', 'event_espresso');
307
+				$class    = 'ee-grey';
308
+				break;
309
+			case EE_Datetime::inactive :
310
+				$btn_text = __('Event Not Active', 'event_espresso');
311
+				$class    = 'ee-grey';
312
+				break;
313
+			case EE_Datetime::cancelled :
314
+				$btn_text = __('Event was Cancelled', 'event_espresso');
315
+				$class    = 'ee-red';
316
+				break;
317
+			case EE_Datetime::upcoming :
318
+			case EE_Datetime::active :
319
+			default :
320
+				$btn_text = ! empty($btn_text_if_active)
321
+					? $btn_text_if_active
322
+					: __('Register Now', 'event_espresso');
323
+				$class    = 'ee-green';
324
+		}
325
+		if ($event_status < 1 && ! empty($btn_text_if_inactive)) {
326
+			$btn_text = $btn_text_if_inactive;
327
+			$class    = 'ee-grey';
328
+		}
329
+		?>
330 330
         <a class="ee-button ee-register-button <?php echo esc_attr($class); ?>"
331 331
            href="<?php espresso_event_link_url($EVT_ID); ?>"
332 332
             <?php echo EED_Events_Archive::link_target(); // already escaped
333
-            ?>
333
+			?>
334 334
         >
335 335
             <?php echo esc_html($btn_text); ?>
336 336
         </a>
337 337
         <?php
338
-    }
338
+	}
339 339
 }
340 340
 
341 341
 
342 342
 if (! function_exists('espresso_display_ticket_selector')) {
343
-    /**
344
-     * espresso_display_ticket_selector
345
-     * whether or not to display the Ticket Selector for an event
346
-     *
347
-     * @param bool $EVT_ID
348
-     * @return boolean
349
-     * @throws EE_Error
350
-     * @throws ReflectionException
351
-     */
352
-    function espresso_display_ticket_selector($EVT_ID = false)
353
-    {
354
-        return EEH_Event_View::display_ticket_selector($EVT_ID);
355
-    }
343
+	/**
344
+	 * espresso_display_ticket_selector
345
+	 * whether or not to display the Ticket Selector for an event
346
+	 *
347
+	 * @param bool $EVT_ID
348
+	 * @return boolean
349
+	 * @throws EE_Error
350
+	 * @throws ReflectionException
351
+	 */
352
+	function espresso_display_ticket_selector($EVT_ID = false)
353
+	{
354
+		return EEH_Event_View::display_ticket_selector($EVT_ID);
355
+	}
356 356
 }
357 357
 
358 358
 
359 359
 if (! function_exists('espresso_event_status_banner')) {
360
-    /**
361
-     * espresso_event_status
362
-     * returns a banner showing the event status if it is sold out, expired, or inactive
363
-     *
364
-     * @param bool $EVT_ID
365
-     * @return string
366
-     * @throws EE_Error
367
-     * @throws ReflectionException
368
-     */
369
-    function espresso_event_status_banner($EVT_ID = false)
370
-    {
371
-        return EEH_Event_View::event_status($EVT_ID);
372
-    }
360
+	/**
361
+	 * espresso_event_status
362
+	 * returns a banner showing the event status if it is sold out, expired, or inactive
363
+	 *
364
+	 * @param bool $EVT_ID
365
+	 * @return string
366
+	 * @throws EE_Error
367
+	 * @throws ReflectionException
368
+	 */
369
+	function espresso_event_status_banner($EVT_ID = false)
370
+	{
371
+		return EEH_Event_View::event_status($EVT_ID);
372
+	}
373 373
 }
374 374
 
375 375
 
376 376
 if (! function_exists('espresso_event_status')) {
377
-    /**
378
-     * espresso_event_status
379
-     * returns the event status if it is sold out, expired, or inactive
380
-     *
381
-     * @param int  $EVT_ID
382
-     * @param bool $echo
383
-     * @return string
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    function espresso_event_status($EVT_ID = 0, $echo = true)
388
-    {
389
-        return EEH_Event_View::event_active_status($EVT_ID, $echo);
390
-    }
377
+	/**
378
+	 * espresso_event_status
379
+	 * returns the event status if it is sold out, expired, or inactive
380
+	 *
381
+	 * @param int  $EVT_ID
382
+	 * @param bool $echo
383
+	 * @return string
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	function espresso_event_status($EVT_ID = 0, $echo = true)
388
+	{
389
+		return EEH_Event_View::event_active_status($EVT_ID, $echo);
390
+	}
391 391
 }
392 392
 
393 393
 
394 394
 if (! function_exists('espresso_event_categories')) {
395
-    /**
396
-     * espresso_event_categories
397
-     * returns the terms associated with an event
398
-     *
399
-     * @param int  $EVT_ID
400
-     * @param bool $hide_uncategorized
401
-     * @param bool $echo
402
-     * @return string
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    function espresso_event_categories($EVT_ID = 0, $hide_uncategorized = true, $echo = true)
407
-    {
408
-        if ($echo) {
409
-            echo EEH_Event_View::event_categories($EVT_ID, $hide_uncategorized); // already escaped
410
-            return '';
411
-        }
412
-        return EEH_Event_View::event_categories($EVT_ID, $hide_uncategorized);
413
-    }
395
+	/**
396
+	 * espresso_event_categories
397
+	 * returns the terms associated with an event
398
+	 *
399
+	 * @param int  $EVT_ID
400
+	 * @param bool $hide_uncategorized
401
+	 * @param bool $echo
402
+	 * @return string
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	function espresso_event_categories($EVT_ID = 0, $hide_uncategorized = true, $echo = true)
407
+	{
408
+		if ($echo) {
409
+			echo EEH_Event_View::event_categories($EVT_ID, $hide_uncategorized); // already escaped
410
+			return '';
411
+		}
412
+		return EEH_Event_View::event_categories($EVT_ID, $hide_uncategorized);
413
+	}
414 414
 }
415 415
 
416 416
 
417 417
 if (! function_exists('espresso_event_tickets_available')) {
418
-    /**
419
-     * espresso_event_tickets_available
420
-     * returns the ticket types available for purchase for an event
421
-     *
422
-     * @param int  $EVT_ID
423
-     * @param bool $echo
424
-     * @param bool $format
425
-     * @return string
426
-     * @throws EE_Error
427
-     * @throws ReflectionException
428
-     */
429
-    function espresso_event_tickets_available($EVT_ID = 0, $echo = true, $format = true)
430
-    {
431
-        $tickets = EEH_Event_View::event_tickets_available($EVT_ID);
432
-        if (is_array($tickets) && ! empty($tickets)) {
433
-            // if formatting then $html will be a string, else it will be an array of ticket objects
434
-            $html =
435
-                $format ? '<ul id="ee-event-tickets-ul-' . esc_attr($EVT_ID) . '" class="ee-event-tickets-ul">' : [];
436
-            foreach ($tickets as $ticket) {
437
-                if ($ticket instanceof EE_Ticket) {
438
-                    if ($format) {
439
-                        $html .= '<li id="ee-event-tickets-li-'
440
-                                 . esc_attr($ticket->ID())
441
-                                 . '" class="ee-event-tickets-li">';
442
-                        $html .= esc_html($ticket->name()) . ' ';
443
-                        $html .= EEH_Template::format_currency(
444
-                            $ticket->get_ticket_total_with_taxes()
445
-                        ); // already escaped
446
-                        $html .= '</li>';
447
-                    } else {
448
-                        $html[] = $ticket;
449
-                    }
450
-                }
451
-            }
452
-            if ($format) {
453
-                $html .= '</ul>';
454
-            }
455
-            if ($echo && $format) {
456
-                echo wp_kses($html, AllowedTags::getAllowedTags());
457
-                return '';
458
-            }
459
-            return $html;
460
-        }
461
-        return '';
462
-    }
418
+	/**
419
+	 * espresso_event_tickets_available
420
+	 * returns the ticket types available for purchase for an event
421
+	 *
422
+	 * @param int  $EVT_ID
423
+	 * @param bool $echo
424
+	 * @param bool $format
425
+	 * @return string
426
+	 * @throws EE_Error
427
+	 * @throws ReflectionException
428
+	 */
429
+	function espresso_event_tickets_available($EVT_ID = 0, $echo = true, $format = true)
430
+	{
431
+		$tickets = EEH_Event_View::event_tickets_available($EVT_ID);
432
+		if (is_array($tickets) && ! empty($tickets)) {
433
+			// if formatting then $html will be a string, else it will be an array of ticket objects
434
+			$html =
435
+				$format ? '<ul id="ee-event-tickets-ul-' . esc_attr($EVT_ID) . '" class="ee-event-tickets-ul">' : [];
436
+			foreach ($tickets as $ticket) {
437
+				if ($ticket instanceof EE_Ticket) {
438
+					if ($format) {
439
+						$html .= '<li id="ee-event-tickets-li-'
440
+								 . esc_attr($ticket->ID())
441
+								 . '" class="ee-event-tickets-li">';
442
+						$html .= esc_html($ticket->name()) . ' ';
443
+						$html .= EEH_Template::format_currency(
444
+							$ticket->get_ticket_total_with_taxes()
445
+						); // already escaped
446
+						$html .= '</li>';
447
+					} else {
448
+						$html[] = $ticket;
449
+					}
450
+				}
451
+			}
452
+			if ($format) {
453
+				$html .= '</ul>';
454
+			}
455
+			if ($echo && $format) {
456
+				echo wp_kses($html, AllowedTags::getAllowedTags());
457
+				return '';
458
+			}
459
+			return $html;
460
+		}
461
+		return '';
462
+	}
463 463
 }
464 464
 
465 465
 if (! function_exists('espresso_event_date_obj')) {
466
-    /**
467
-     * espresso_event_date_obj
468
-     * returns the primary date object for an event
469
-     *
470
-     * @param bool $EVT_ID
471
-     * @return EE_Datetime|null
472
-     * @throws EE_Error
473
-     * @throws ReflectionException
474
-     */
475
-    function espresso_event_date_obj($EVT_ID = false)
476
-    {
477
-        return EEH_Event_View::get_primary_date_obj($EVT_ID);
478
-    }
466
+	/**
467
+	 * espresso_event_date_obj
468
+	 * returns the primary date object for an event
469
+	 *
470
+	 * @param bool $EVT_ID
471
+	 * @return EE_Datetime|null
472
+	 * @throws EE_Error
473
+	 * @throws ReflectionException
474
+	 */
475
+	function espresso_event_date_obj($EVT_ID = false)
476
+	{
477
+		return EEH_Event_View::get_primary_date_obj($EVT_ID);
478
+	}
479 479
 }
480 480
 
481 481
 
482 482
 if (! function_exists('espresso_event_date')) {
483
-    /**
484
-     * espresso_event_date
485
-     * returns the primary date for an event
486
-     *
487
-     * @param string $date_format
488
-     * @param string $time_format
489
-     * @param bool   $EVT_ID
490
-     * @param bool   $echo
491
-     * @return string
492
-     * @throws EE_Error
493
-     * @throws ReflectionException
494
-     */
495
-    function espresso_event_date($date_format = '', $time_format = '', $EVT_ID = false, $echo = true)
496
-    {
497
-        $date_format = ! empty($date_format) ? $date_format : get_option('date_format');
498
-        $time_format = ! empty($time_format) ? $time_format : get_option('time_format');
499
-        $date_format = apply_filters('FHEE__espresso_event_date__date_format', $date_format);
500
-        $time_format = apply_filters('FHEE__espresso_event_date__time_format', $time_format);
501
-        if ($echo) {
502
-            echo EEH_Event_View::the_event_date($date_format, $time_format, $EVT_ID); // already escaped
503
-            return '';
504
-        }
505
-        return EEH_Event_View::the_event_date($date_format, $time_format, $EVT_ID);
506
-
507
-    }
483
+	/**
484
+	 * espresso_event_date
485
+	 * returns the primary date for an event
486
+	 *
487
+	 * @param string $date_format
488
+	 * @param string $time_format
489
+	 * @param bool   $EVT_ID
490
+	 * @param bool   $echo
491
+	 * @return string
492
+	 * @throws EE_Error
493
+	 * @throws ReflectionException
494
+	 */
495
+	function espresso_event_date($date_format = '', $time_format = '', $EVT_ID = false, $echo = true)
496
+	{
497
+		$date_format = ! empty($date_format) ? $date_format : get_option('date_format');
498
+		$time_format = ! empty($time_format) ? $time_format : get_option('time_format');
499
+		$date_format = apply_filters('FHEE__espresso_event_date__date_format', $date_format);
500
+		$time_format = apply_filters('FHEE__espresso_event_date__time_format', $time_format);
501
+		if ($echo) {
502
+			echo EEH_Event_View::the_event_date($date_format, $time_format, $EVT_ID); // already escaped
503
+			return '';
504
+		}
505
+		return EEH_Event_View::the_event_date($date_format, $time_format, $EVT_ID);
506
+
507
+	}
508 508
 }
509 509
 
510 510
 
511 511
 if (! function_exists('espresso_list_of_event_dates')) {
512
-    /**
513
-     * espresso_list_of_event_dates
514
-     * returns a unordered list of dates for an event
515
-     *
516
-     * @param int    $EVT_ID
517
-     * @param string $date_format
518
-     * @param string $time_format
519
-     * @param bool   $echo
520
-     * @param null   $show_expired
521
-     * @param bool   $format
522
-     * @param bool   $add_breaks
523
-     * @param null   $limit
524
-     * @return string
525
-     * @throws EE_Error
526
-     * @throws ReflectionException
527
-     */
528
-    function espresso_list_of_event_dates(
529
-        $EVT_ID = 0,
530
-        $date_format = '',
531
-        $time_format = '',
532
-        $echo = true,
533
-        $show_expired = null,
534
-        $format = true,
535
-        $add_breaks = true,
536
-        $limit = null
537
-    ) {
538
-        $allowedtags = AllowedTags::getAllowedTags();
539
-        $date_format = ! empty($date_format) ? $date_format : get_option('date_format');
540
-        $time_format = ! empty($time_format) ? $time_format : get_option('time_format');
541
-        $date_format = apply_filters('FHEE__espresso_list_of_event_dates__date_format', $date_format);
542
-        $time_format = apply_filters('FHEE__espresso_list_of_event_dates__time_format', $time_format);
543
-        $datetimes   = EEH_Event_View::get_all_date_obj($EVT_ID, $show_expired, false, $limit);
544
-        if (! $format) {
545
-            return apply_filters('FHEE__espresso_list_of_event_dates__datetimes', $datetimes);
546
-        }
547
-        $newline = $add_breaks ? '<br />' : '';
548
-        if (is_array($datetimes) && ! empty($datetimes)) {
549
-            global $post;
550
-            $html =
551
-                '<ul id="ee-event-datetimes-ul-' . esc_attr($post->ID) . '" class="ee-event-datetimes-ul ee-clearfix">';
552
-            foreach ($datetimes as $datetime) {
553
-                if ($datetime instanceof EE_Datetime) {
554
-
555
-                    $datetime_name        = $datetime->name();
556
-                    $datetime_html        = ! empty($datetime_name)
557
-                        ? '
512
+	/**
513
+	 * espresso_list_of_event_dates
514
+	 * returns a unordered list of dates for an event
515
+	 *
516
+	 * @param int    $EVT_ID
517
+	 * @param string $date_format
518
+	 * @param string $time_format
519
+	 * @param bool   $echo
520
+	 * @param null   $show_expired
521
+	 * @param bool   $format
522
+	 * @param bool   $add_breaks
523
+	 * @param null   $limit
524
+	 * @return string
525
+	 * @throws EE_Error
526
+	 * @throws ReflectionException
527
+	 */
528
+	function espresso_list_of_event_dates(
529
+		$EVT_ID = 0,
530
+		$date_format = '',
531
+		$time_format = '',
532
+		$echo = true,
533
+		$show_expired = null,
534
+		$format = true,
535
+		$add_breaks = true,
536
+		$limit = null
537
+	) {
538
+		$allowedtags = AllowedTags::getAllowedTags();
539
+		$date_format = ! empty($date_format) ? $date_format : get_option('date_format');
540
+		$time_format = ! empty($time_format) ? $time_format : get_option('time_format');
541
+		$date_format = apply_filters('FHEE__espresso_list_of_event_dates__date_format', $date_format);
542
+		$time_format = apply_filters('FHEE__espresso_list_of_event_dates__time_format', $time_format);
543
+		$datetimes   = EEH_Event_View::get_all_date_obj($EVT_ID, $show_expired, false, $limit);
544
+		if (! $format) {
545
+			return apply_filters('FHEE__espresso_list_of_event_dates__datetimes', $datetimes);
546
+		}
547
+		$newline = $add_breaks ? '<br />' : '';
548
+		if (is_array($datetimes) && ! empty($datetimes)) {
549
+			global $post;
550
+			$html =
551
+				'<ul id="ee-event-datetimes-ul-' . esc_attr($post->ID) . '" class="ee-event-datetimes-ul ee-clearfix">';
552
+			foreach ($datetimes as $datetime) {
553
+				if ($datetime instanceof EE_Datetime) {
554
+
555
+					$datetime_name        = $datetime->name();
556
+					$datetime_html        = ! empty($datetime_name)
557
+						? '
558 558
                         <strong class="ee-event-datetimes-li-date-name">
559 559
                           ' . esc_html($datetime_name) . '
560 560
                        </strong>' . $newline
561
-                        : '';
561
+						: '';
562 562
 
563
-                    $datetime_description = $datetime->description();
564
-                    $datetime_html .= ! empty($datetime_description)
565
-                        ? '
563
+					$datetime_description = $datetime->description();
564
+					$datetime_html .= ! empty($datetime_description)
565
+						? '
566 566
                         <span class="ee-event-datetimes-li-date-desc">
567 567
                             ' . wp_kses($datetime_description, $allowedtags) . '
568 568
                         </span>' . $newline
569
-                        : '';
569
+						: '';
570 570
 
571
-                    $datetime_html .= '
571
+					$datetime_html .= '
572 572
                         <span class="dashicons dashicons-calendar"></span>
573 573
                         <span class="ee-event-datetimes-li-daterange">' . $datetime->date_range($date_format) . '</span>
574 574
                         <br/>
@@ -576,482 +576,482 @@  discard block
 block discarded – undo
576 576
                         <span class="ee-event-datetimes-li-timerange">' . $datetime->time_range($time_format) . '</span>
577 577
                         ';
578 578
 
579
-                    $datetime_html = apply_filters(
580
-                        'FHEE__espresso_list_of_event_dates__datetime_html',
581
-                        $datetime_html,
582
-                        $datetime
583
-                    );
579
+					$datetime_html = apply_filters(
580
+						'FHEE__espresso_list_of_event_dates__datetime_html',
581
+						$datetime_html,
582
+						$datetime
583
+					);
584 584
 
585
-                    $DTD_ID        = esc_attr($datetime->ID());
586
-                    $active_status = esc_attr(' ee-event-datetimes-li-' . $datetime->get_active_status());
585
+					$DTD_ID        = esc_attr($datetime->ID());
586
+					$active_status = esc_attr(' ee-event-datetimes-li-' . $datetime->get_active_status());
587 587
 
588
-                    $html .= '
588
+					$html .= '
589 589
                     <li id="ee-event-datetimes-li-' . $DTD_ID . '" class="ee-event-datetimes-li' . $active_status . '">
590 590
                         ' . $datetime_html . '
591 591
                     </li>';
592
-                }
593
-            }
594
-            $html .= '</ul>';
595
-        } else {
596
-            $html =
597
-                '
592
+				}
593
+			}
594
+			$html .= '</ul>';
595
+		} else {
596
+			$html =
597
+				'
598 598
             <p>
599 599
                 <span class="dashicons dashicons-marker pink-text"></span>
600 600
                 ' . esc_html__(
601
-                    'There are no upcoming dates for this event.',
602
-                    'event_espresso'
603
-                ) . '
601
+					'There are no upcoming dates for this event.',
602
+					'event_espresso'
603
+				) . '
604 604
             </p>
605 605
             <br/>';
606
-        }
607
-        if ($echo) {
608
-            echo wp_kses($html, AllowedTags::getWithFormTags());
609
-            return '';
610
-        }
611
-        return $html;
612
-    }
606
+		}
607
+		if ($echo) {
608
+			echo wp_kses($html, AllowedTags::getWithFormTags());
609
+			return '';
610
+		}
611
+		return $html;
612
+	}
613 613
 }
614 614
 
615 615
 
616 616
 if (! function_exists('espresso_event_end_date')) {
617
-    /**
618
-     * espresso_event_end_date
619
-     * returns the last date for an event
620
-     *
621
-     * @param string $date_format
622
-     * @param string $time_format
623
-     * @param bool   $EVT_ID
624
-     * @param bool   $echo
625
-     * @return string
626
-     * @throws EE_Error
627
-     * @throws ReflectionException
628
-     */
629
-    function espresso_event_end_date($date_format = '', $time_format = '', $EVT_ID = false, $echo = true)
630
-    {
631
-        $date_format = ! empty($date_format) ? $date_format : get_option('date_format');
632
-        $time_format = ! empty($time_format) ? $time_format : get_option('time_format');
633
-        $date_format = apply_filters('FHEE__espresso_event_end_date__date_format', $date_format);
634
-        $time_format = apply_filters('FHEE__espresso_event_end_date__time_format', $time_format);
635
-        if ($echo) {
636
-            echo EEH_Event_View::the_event_end_date($date_format, $time_format, $EVT_ID); // already escaped
637
-            return '';
638
-        }
639
-        return EEH_Event_View::the_event_end_date($date_format, $time_format, $EVT_ID);
640
-    }
617
+	/**
618
+	 * espresso_event_end_date
619
+	 * returns the last date for an event
620
+	 *
621
+	 * @param string $date_format
622
+	 * @param string $time_format
623
+	 * @param bool   $EVT_ID
624
+	 * @param bool   $echo
625
+	 * @return string
626
+	 * @throws EE_Error
627
+	 * @throws ReflectionException
628
+	 */
629
+	function espresso_event_end_date($date_format = '', $time_format = '', $EVT_ID = false, $echo = true)
630
+	{
631
+		$date_format = ! empty($date_format) ? $date_format : get_option('date_format');
632
+		$time_format = ! empty($time_format) ? $time_format : get_option('time_format');
633
+		$date_format = apply_filters('FHEE__espresso_event_end_date__date_format', $date_format);
634
+		$time_format = apply_filters('FHEE__espresso_event_end_date__time_format', $time_format);
635
+		if ($echo) {
636
+			echo EEH_Event_View::the_event_end_date($date_format, $time_format, $EVT_ID); // already escaped
637
+			return '';
638
+		}
639
+		return EEH_Event_View::the_event_end_date($date_format, $time_format, $EVT_ID);
640
+	}
641 641
 }
642 642
 
643 643
 if (! function_exists('espresso_event_date_range')) {
644
-    /**
645
-     * espresso_event_date_range
646
-     * returns the first and last chronologically ordered dates for an event (if different)
647
-     *
648
-     * @param string $date_format
649
-     * @param string $time_format
650
-     * @param string $single_date_format
651
-     * @param string $single_time_format
652
-     * @param bool   $EVT_ID
653
-     * @param bool   $echo
654
-     * @return string
655
-     * @throws EE_Error
656
-     * @throws ReflectionException
657
-     */
658
-    function espresso_event_date_range(
659
-        $date_format = '',
660
-        $time_format = '',
661
-        $single_date_format = '',
662
-        $single_time_format = '',
663
-        $EVT_ID = false,
664
-        $echo = true
665
-    ) {
666
-        // set and filter date and time formats when a range is returned
667
-        $date_format = ! empty($date_format) ? $date_format : get_option('date_format');
668
-        $date_format = apply_filters('FHEE__espresso_event_date_range__date_format', $date_format);
669
-        // get the start and end date with NO time portion
670
-        $the_event_date     = EEH_Event_View::the_earliest_event_date($date_format, '', $EVT_ID);
671
-        $the_event_end_date = EEH_Event_View::the_latest_event_date($date_format, '', $EVT_ID);
672
-        // now we can determine if date range spans more than one day
673
-        if ($the_event_date != $the_event_end_date) {
674
-            $time_format = ! empty($time_format) ? $time_format : get_option('time_format');
675
-            $time_format = apply_filters('FHEE__espresso_event_date_range__time_format', $time_format);
676
-            $html        = sprintf(
677
-            /* translators: 1: first event date, 2: last event date */
678
-                esc_html__('%1$s - %2$s', 'event_espresso'),
679
-                EEH_Event_View::the_earliest_event_date($date_format, $time_format, $EVT_ID),
680
-                EEH_Event_View::the_latest_event_date($date_format, $time_format, $EVT_ID)
681
-            );
682
-        } else {
683
-            // set and filter date and time formats when only a single datetime is returned
684
-            $single_date_format = ! empty($single_date_format) ? $single_date_format : get_option('date_format');
685
-            $single_time_format = ! empty($single_time_format) ? $single_time_format : get_option('time_format');
686
-            $single_date_format =
687
-                apply_filters('FHEE__espresso_event_date_range__single_date_format', $single_date_format);
688
-            $single_time_format =
689
-                apply_filters('FHEE__espresso_event_date_range__single_time_format', $single_time_format);
690
-            $html               =
691
-                EEH_Event_View::the_earliest_event_date($single_date_format, $single_time_format, $EVT_ID);
692
-        }
693
-        if ($echo) {
694
-            echo wp_kses($html, AllowedTags::getAllowedTags());
695
-            return '';
696
-        }
697
-        return $html;
698
-    }
644
+	/**
645
+	 * espresso_event_date_range
646
+	 * returns the first and last chronologically ordered dates for an event (if different)
647
+	 *
648
+	 * @param string $date_format
649
+	 * @param string $time_format
650
+	 * @param string $single_date_format
651
+	 * @param string $single_time_format
652
+	 * @param bool   $EVT_ID
653
+	 * @param bool   $echo
654
+	 * @return string
655
+	 * @throws EE_Error
656
+	 * @throws ReflectionException
657
+	 */
658
+	function espresso_event_date_range(
659
+		$date_format = '',
660
+		$time_format = '',
661
+		$single_date_format = '',
662
+		$single_time_format = '',
663
+		$EVT_ID = false,
664
+		$echo = true
665
+	) {
666
+		// set and filter date and time formats when a range is returned
667
+		$date_format = ! empty($date_format) ? $date_format : get_option('date_format');
668
+		$date_format = apply_filters('FHEE__espresso_event_date_range__date_format', $date_format);
669
+		// get the start and end date with NO time portion
670
+		$the_event_date     = EEH_Event_View::the_earliest_event_date($date_format, '', $EVT_ID);
671
+		$the_event_end_date = EEH_Event_View::the_latest_event_date($date_format, '', $EVT_ID);
672
+		// now we can determine if date range spans more than one day
673
+		if ($the_event_date != $the_event_end_date) {
674
+			$time_format = ! empty($time_format) ? $time_format : get_option('time_format');
675
+			$time_format = apply_filters('FHEE__espresso_event_date_range__time_format', $time_format);
676
+			$html        = sprintf(
677
+			/* translators: 1: first event date, 2: last event date */
678
+				esc_html__('%1$s - %2$s', 'event_espresso'),
679
+				EEH_Event_View::the_earliest_event_date($date_format, $time_format, $EVT_ID),
680
+				EEH_Event_View::the_latest_event_date($date_format, $time_format, $EVT_ID)
681
+			);
682
+		} else {
683
+			// set and filter date and time formats when only a single datetime is returned
684
+			$single_date_format = ! empty($single_date_format) ? $single_date_format : get_option('date_format');
685
+			$single_time_format = ! empty($single_time_format) ? $single_time_format : get_option('time_format');
686
+			$single_date_format =
687
+				apply_filters('FHEE__espresso_event_date_range__single_date_format', $single_date_format);
688
+			$single_time_format =
689
+				apply_filters('FHEE__espresso_event_date_range__single_time_format', $single_time_format);
690
+			$html               =
691
+				EEH_Event_View::the_earliest_event_date($single_date_format, $single_time_format, $EVT_ID);
692
+		}
693
+		if ($echo) {
694
+			echo wp_kses($html, AllowedTags::getAllowedTags());
695
+			return '';
696
+		}
697
+		return $html;
698
+	}
699 699
 }
700 700
 
701 701
 if (! function_exists('espresso_next_upcoming_datetime_obj')) {
702
-    /**
703
-     * espresso_next_upcoming_datetime_obj
704
-     * returns the next upcoming datetime object for an event
705
-     *
706
-     * @param int $EVT_ID
707
-     * @return EE_Datetime|null
708
-     * @throws EE_Error
709
-     */
710
-    function espresso_next_upcoming_datetime_obj($EVT_ID = 0)
711
-    {
712
-        return EEH_Event_View::get_next_upcoming_date_obj($EVT_ID);
713
-    }
702
+	/**
703
+	 * espresso_next_upcoming_datetime_obj
704
+	 * returns the next upcoming datetime object for an event
705
+	 *
706
+	 * @param int $EVT_ID
707
+	 * @return EE_Datetime|null
708
+	 * @throws EE_Error
709
+	 */
710
+	function espresso_next_upcoming_datetime_obj($EVT_ID = 0)
711
+	{
712
+		return EEH_Event_View::get_next_upcoming_date_obj($EVT_ID);
713
+	}
714 714
 }
715 715
 
716 716
 if (! function_exists('espresso_next_upcoming_datetime')) {
717
-    /**
718
-     * espresso_next_upcoming_datetime
719
-     * returns the start date and time for the next upcoming event.
720
-     *
721
-     * @param string $date_format
722
-     * @param string $time_format
723
-     * @param int    $EVT_ID
724
-     * @param bool   $echo
725
-     * @return string
726
-     * @throws EE_Error
727
-     * @throws ReflectionException
728
-     */
729
-    function espresso_next_upcoming_datetime($date_format = '', $time_format = '', $EVT_ID = 0, $echo = true)
730
-    {
731
-
732
-        $date_format = ! empty($date_format) ? $date_format : get_option('date_format');
733
-        $date_format = apply_filters('FHEE__espresso_next_upcoming_datetime__date_format', $date_format);
734
-
735
-        $time_format = ! empty($time_format) ? $time_format : get_option('time_format');
736
-        $time_format = apply_filters('FHEE__espresso_next_upcoming_datetime__time_format', $time_format);
737
-
738
-        $datetime_format = trim($date_format . ' ' . $time_format);
739
-
740
-        $datetime = espresso_next_upcoming_datetime_obj($EVT_ID);
741
-
742
-        if (! $datetime instanceof EE_Datetime) {
743
-            return '';
744
-        }
745
-        if ($echo) {
746
-            echo esc_html($datetime->get_i18n_datetime('DTT_EVT_start', $datetime_format));
747
-            return '';
748
-        }
749
-        return $datetime->get_i18n_datetime('DTT_EVT_start', $datetime_format);
750
-    }
717
+	/**
718
+	 * espresso_next_upcoming_datetime
719
+	 * returns the start date and time for the next upcoming event.
720
+	 *
721
+	 * @param string $date_format
722
+	 * @param string $time_format
723
+	 * @param int    $EVT_ID
724
+	 * @param bool   $echo
725
+	 * @return string
726
+	 * @throws EE_Error
727
+	 * @throws ReflectionException
728
+	 */
729
+	function espresso_next_upcoming_datetime($date_format = '', $time_format = '', $EVT_ID = 0, $echo = true)
730
+	{
731
+
732
+		$date_format = ! empty($date_format) ? $date_format : get_option('date_format');
733
+		$date_format = apply_filters('FHEE__espresso_next_upcoming_datetime__date_format', $date_format);
734
+
735
+		$time_format = ! empty($time_format) ? $time_format : get_option('time_format');
736
+		$time_format = apply_filters('FHEE__espresso_next_upcoming_datetime__time_format', $time_format);
737
+
738
+		$datetime_format = trim($date_format . ' ' . $time_format);
739
+
740
+		$datetime = espresso_next_upcoming_datetime_obj($EVT_ID);
741
+
742
+		if (! $datetime instanceof EE_Datetime) {
743
+			return '';
744
+		}
745
+		if ($echo) {
746
+			echo esc_html($datetime->get_i18n_datetime('DTT_EVT_start', $datetime_format));
747
+			return '';
748
+		}
749
+		return $datetime->get_i18n_datetime('DTT_EVT_start', $datetime_format);
750
+	}
751 751
 }
752 752
 
753 753
 if (! function_exists('espresso_event_date_as_calendar_page')) {
754
-    /**
755
-     * espresso_event_date_as_calendar_page
756
-     * returns the primary date for an event, stylized to appear as the page of a calendar
757
-     *
758
-     * @param bool $EVT_ID
759
-     * @return void
760
-     * @throws EE_Error
761
-     * @throws ReflectionException
762
-     */
763
-    function espresso_event_date_as_calendar_page($EVT_ID = false)
764
-    {
765
-        EEH_Event_View::event_date_as_calendar_page($EVT_ID);
766
-    }
754
+	/**
755
+	 * espresso_event_date_as_calendar_page
756
+	 * returns the primary date for an event, stylized to appear as the page of a calendar
757
+	 *
758
+	 * @param bool $EVT_ID
759
+	 * @return void
760
+	 * @throws EE_Error
761
+	 * @throws ReflectionException
762
+	 */
763
+	function espresso_event_date_as_calendar_page($EVT_ID = false)
764
+	{
765
+		EEH_Event_View::event_date_as_calendar_page($EVT_ID);
766
+	}
767 767
 }
768 768
 
769 769
 
770 770
 if (! function_exists('espresso_event_link_url')) {
771
-    /**
772
-     * espresso_event_link_url
773
-     *
774
-     * @param int  $EVT_ID
775
-     * @param bool $echo
776
-     * @return string
777
-     * @throws EE_Error
778
-     * @throws ReflectionException
779
-     */
780
-    function espresso_event_link_url($EVT_ID = 0, $echo = true)
781
-    {
782
-        if ($echo) {
783
-            echo EEH_Event_View::event_link_url($EVT_ID); // already escaped
784
-            return '';
785
-        }
786
-        return EEH_Event_View::event_link_url($EVT_ID);
787
-    }
771
+	/**
772
+	 * espresso_event_link_url
773
+	 *
774
+	 * @param int  $EVT_ID
775
+	 * @param bool $echo
776
+	 * @return string
777
+	 * @throws EE_Error
778
+	 * @throws ReflectionException
779
+	 */
780
+	function espresso_event_link_url($EVT_ID = 0, $echo = true)
781
+	{
782
+		if ($echo) {
783
+			echo EEH_Event_View::event_link_url($EVT_ID); // already escaped
784
+			return '';
785
+		}
786
+		return EEH_Event_View::event_link_url($EVT_ID);
787
+	}
788 788
 }
789 789
 
790 790
 
791 791
 if (! function_exists('espresso_event_has_content_or_excerpt')) {
792
-    /**
793
-     *    espresso_event_has_content_or_excerpt
794
-     *
795
-     * @access    public
796
-     * @param bool $EVT_ID
797
-     * @return    boolean
798
-     * @throws EE_Error
799
-     * @throws ReflectionException
800
-     */
801
-    function espresso_event_has_content_or_excerpt($EVT_ID = false)
802
-    {
803
-        return EEH_Event_View::event_has_content_or_excerpt($EVT_ID);
804
-    }
792
+	/**
793
+	 *    espresso_event_has_content_or_excerpt
794
+	 *
795
+	 * @access    public
796
+	 * @param bool $EVT_ID
797
+	 * @return    boolean
798
+	 * @throws EE_Error
799
+	 * @throws ReflectionException
800
+	 */
801
+	function espresso_event_has_content_or_excerpt($EVT_ID = false)
802
+	{
803
+		return EEH_Event_View::event_has_content_or_excerpt($EVT_ID);
804
+	}
805 805
 }
806 806
 
807 807
 
808 808
 if (! function_exists('espresso_event_content_or_excerpt')) {
809
-    /**
810
-     * espresso_event_content_or_excerpt
811
-     *
812
-     * @param int  $num_words
813
-     * @param null $more
814
-     * @param bool $echo
815
-     * @return string
816
-     */
817
-    function espresso_event_content_or_excerpt($num_words = 55, $more = null, $echo = true)
818
-    {
819
-        if ($echo) {
820
-            echo EEH_Event_View::event_content_or_excerpt($num_words, $more); // already escaped
821
-            return '';
822
-        }
823
-        return EEH_Event_View::event_content_or_excerpt($num_words, $more);
824
-    }
809
+	/**
810
+	 * espresso_event_content_or_excerpt
811
+	 *
812
+	 * @param int  $num_words
813
+	 * @param null $more
814
+	 * @param bool $echo
815
+	 * @return string
816
+	 */
817
+	function espresso_event_content_or_excerpt($num_words = 55, $more = null, $echo = true)
818
+	{
819
+		if ($echo) {
820
+			echo EEH_Event_View::event_content_or_excerpt($num_words, $more); // already escaped
821
+			return '';
822
+		}
823
+		return EEH_Event_View::event_content_or_excerpt($num_words, $more);
824
+	}
825 825
 }
826 826
 
827 827
 
828 828
 if (! function_exists('espresso_event_phone')) {
829
-    /**
830
-     * espresso_event_phone
831
-     *
832
-     * @param int  $EVT_ID
833
-     * @param bool $echo
834
-     * @return string
835
-     * @throws EE_Error
836
-     * @throws ReflectionException
837
-     */
838
-    function espresso_event_phone($EVT_ID = 0, $echo = true)
839
-    {
840
-        if ($echo) {
841
-            echo EEH_Event_View::event_phone($EVT_ID); // already escaped
842
-            return '';
843
-        }
844
-        return EEH_Event_View::event_phone($EVT_ID);
845
-    }
829
+	/**
830
+	 * espresso_event_phone
831
+	 *
832
+	 * @param int  $EVT_ID
833
+	 * @param bool $echo
834
+	 * @return string
835
+	 * @throws EE_Error
836
+	 * @throws ReflectionException
837
+	 */
838
+	function espresso_event_phone($EVT_ID = 0, $echo = true)
839
+	{
840
+		if ($echo) {
841
+			echo EEH_Event_View::event_phone($EVT_ID); // already escaped
842
+			return '';
843
+		}
844
+		return EEH_Event_View::event_phone($EVT_ID);
845
+	}
846 846
 }
847 847
 
848 848
 
849 849
 if (! function_exists('espresso_edit_event_link')) {
850
-    /**
851
-     * espresso_edit_event_link
852
-     * returns a link to edit an event
853
-     *
854
-     * @param int  $EVT_ID
855
-     * @param bool $echo
856
-     * @return string
857
-     * @throws EE_Error
858
-     * @throws ReflectionException
859
-     */
860
-    function espresso_edit_event_link($EVT_ID = 0, $echo = true)
861
-    {
862
-        if ($echo) {
863
-            echo EEH_Event_View::edit_event_link($EVT_ID); // already escaped
864
-            return '';
865
-        }
866
-        return EEH_Event_View::edit_event_link($EVT_ID);
867
-    }
850
+	/**
851
+	 * espresso_edit_event_link
852
+	 * returns a link to edit an event
853
+	 *
854
+	 * @param int  $EVT_ID
855
+	 * @param bool $echo
856
+	 * @return string
857
+	 * @throws EE_Error
858
+	 * @throws ReflectionException
859
+	 */
860
+	function espresso_edit_event_link($EVT_ID = 0, $echo = true)
861
+	{
862
+		if ($echo) {
863
+			echo EEH_Event_View::edit_event_link($EVT_ID); // already escaped
864
+			return '';
865
+		}
866
+		return EEH_Event_View::edit_event_link($EVT_ID);
867
+	}
868 868
 }
869 869
 
870 870
 
871 871
 if (! function_exists('espresso_organization_name')) {
872
-    /**
873
-     * espresso_organization_name
874
-     *
875
-     * @param bool $echo
876
-     * @return string
877
-     * @throws EE_Error
878
-     */
879
-    function espresso_organization_name($echo = true)
880
-    {
881
-        if ($echo) {
882
-            echo EE_Registry::instance()->CFG->organization->get_pretty('name'); // already escaped
883
-            return '';
884
-        }
885
-        return EE_Registry::instance()->CFG->organization->get_pretty('name');
886
-    }
872
+	/**
873
+	 * espresso_organization_name
874
+	 *
875
+	 * @param bool $echo
876
+	 * @return string
877
+	 * @throws EE_Error
878
+	 */
879
+	function espresso_organization_name($echo = true)
880
+	{
881
+		if ($echo) {
882
+			echo EE_Registry::instance()->CFG->organization->get_pretty('name'); // already escaped
883
+			return '';
884
+		}
885
+		return EE_Registry::instance()->CFG->organization->get_pretty('name');
886
+	}
887 887
 }
888 888
 
889 889
 if (! function_exists('espresso_organization_address')) {
890
-    /**
891
-     * espresso_organization_address
892
-     *
893
-     * @param string $type
894
-     * @return string
895
-     */
896
-    function espresso_organization_address($type = 'inline')
897
-    {
898
-        if (EE_Registry::instance()->CFG->organization instanceof EE_Organization_Config) {
899
-            $address = new EventEspresso\core\domain\entities\GenericAddress(
900
-                EE_Registry::instance()->CFG->organization->address_1,
901
-                EE_Registry::instance()->CFG->organization->address_2,
902
-                EE_Registry::instance()->CFG->organization->city,
903
-                EE_Registry::instance()->CFG->organization->STA_ID,
904
-                EE_Registry::instance()->CFG->organization->zip,
905
-                EE_Registry::instance()->CFG->organization->CNT_ISO
906
-            );
907
-            return EEH_Address::format($address, $type);
908
-        }
909
-        return '';
910
-    }
890
+	/**
891
+	 * espresso_organization_address
892
+	 *
893
+	 * @param string $type
894
+	 * @return string
895
+	 */
896
+	function espresso_organization_address($type = 'inline')
897
+	{
898
+		if (EE_Registry::instance()->CFG->organization instanceof EE_Organization_Config) {
899
+			$address = new EventEspresso\core\domain\entities\GenericAddress(
900
+				EE_Registry::instance()->CFG->organization->address_1,
901
+				EE_Registry::instance()->CFG->organization->address_2,
902
+				EE_Registry::instance()->CFG->organization->city,
903
+				EE_Registry::instance()->CFG->organization->STA_ID,
904
+				EE_Registry::instance()->CFG->organization->zip,
905
+				EE_Registry::instance()->CFG->organization->CNT_ISO
906
+			);
907
+			return EEH_Address::format($address, $type);
908
+		}
909
+		return '';
910
+	}
911 911
 }
912 912
 
913 913
 if (! function_exists('espresso_organization_email')) {
914
-    /**
915
-     * espresso_organization_email
916
-     *
917
-     * @param bool $echo
918
-     * @return string
919
-     * @throws EE_Error
920
-     */
921
-    function espresso_organization_email($echo = true)
922
-    {
923
-        if ($echo) {
924
-            echo EE_Registry::instance()->CFG->organization->get_pretty('email'); // already escaped
925
-            return '';
926
-        }
927
-        return EE_Registry::instance()->CFG->organization->get_pretty('email');
928
-    }
914
+	/**
915
+	 * espresso_organization_email
916
+	 *
917
+	 * @param bool $echo
918
+	 * @return string
919
+	 * @throws EE_Error
920
+	 */
921
+	function espresso_organization_email($echo = true)
922
+	{
923
+		if ($echo) {
924
+			echo EE_Registry::instance()->CFG->organization->get_pretty('email'); // already escaped
925
+			return '';
926
+		}
927
+		return EE_Registry::instance()->CFG->organization->get_pretty('email');
928
+	}
929 929
 }
930 930
 
931 931
 if (! function_exists('espresso_organization_logo_url')) {
932
-    /**
933
-     * espresso_organization_logo_url
934
-     *
935
-     * @param bool $echo
936
-     * @return string
937
-     * @throws EE_Error
938
-     */
939
-    function espresso_organization_logo_url($echo = true)
940
-    {
941
-        if ($echo) {
942
-            echo EE_Registry::instance()->CFG->organization->get_pretty('logo_url'); // already escaped
943
-            return '';
944
-        }
945
-        return EE_Registry::instance()->CFG->organization->get_pretty('logo_url');
946
-    }
932
+	/**
933
+	 * espresso_organization_logo_url
934
+	 *
935
+	 * @param bool $echo
936
+	 * @return string
937
+	 * @throws EE_Error
938
+	 */
939
+	function espresso_organization_logo_url($echo = true)
940
+	{
941
+		if ($echo) {
942
+			echo EE_Registry::instance()->CFG->organization->get_pretty('logo_url'); // already escaped
943
+			return '';
944
+		}
945
+		return EE_Registry::instance()->CFG->organization->get_pretty('logo_url');
946
+	}
947 947
 }
948 948
 
949 949
 if (! function_exists('espresso_organization_facebook')) {
950
-    /**
951
-     * espresso_organization_facebook
952
-     *
953
-     * @param bool $echo
954
-     * @return string
955
-     * @throws EE_Error
956
-     */
957
-    function espresso_organization_facebook($echo = true)
958
-    {
959
-        if ($echo) {
960
-            echo EE_Registry::instance()->CFG->organization->get_pretty('facebook'); // already escaped
961
-            return '';
962
-        }
963
-        return EE_Registry::instance()->CFG->organization->get_pretty('facebook');
964
-    }
950
+	/**
951
+	 * espresso_organization_facebook
952
+	 *
953
+	 * @param bool $echo
954
+	 * @return string
955
+	 * @throws EE_Error
956
+	 */
957
+	function espresso_organization_facebook($echo = true)
958
+	{
959
+		if ($echo) {
960
+			echo EE_Registry::instance()->CFG->organization->get_pretty('facebook'); // already escaped
961
+			return '';
962
+		}
963
+		return EE_Registry::instance()->CFG->organization->get_pretty('facebook');
964
+	}
965 965
 }
966 966
 
967 967
 if (! function_exists('espresso_organization_twitter')) {
968
-    /**
969
-     * espresso_organization_twitter
970
-     *
971
-     * @param bool $echo
972
-     * @return string
973
-     * @throws EE_Error
974
-     */
975
-    function espresso_organization_twitter($echo = true)
976
-    {
977
-        if ($echo) {
978
-            echo EE_Registry::instance()->CFG->organization->get_pretty('twitter'); // already escaped
979
-            return '';
980
-        }
981
-        return EE_Registry::instance()->CFG->organization->get_pretty('twitter');
982
-    }
968
+	/**
969
+	 * espresso_organization_twitter
970
+	 *
971
+	 * @param bool $echo
972
+	 * @return string
973
+	 * @throws EE_Error
974
+	 */
975
+	function espresso_organization_twitter($echo = true)
976
+	{
977
+		if ($echo) {
978
+			echo EE_Registry::instance()->CFG->organization->get_pretty('twitter'); // already escaped
979
+			return '';
980
+		}
981
+		return EE_Registry::instance()->CFG->organization->get_pretty('twitter');
982
+	}
983 983
 }
984 984
 
985 985
 if (! function_exists('espresso_organization_linkedin')) {
986
-    /**
987
-     * espresso_organization_linkedin
988
-     *
989
-     * @param bool $echo
990
-     * @return string
991
-     * @throws EE_Error
992
-     */
993
-    function espresso_organization_linkedin($echo = true)
994
-    {
995
-        if ($echo) {
996
-            echo EE_Registry::instance()->CFG->organization->get_pretty('linkedin'); // already escaped
997
-            return '';
998
-        }
999
-        return EE_Registry::instance()->CFG->organization->get_pretty('linkedin');
1000
-    }
986
+	/**
987
+	 * espresso_organization_linkedin
988
+	 *
989
+	 * @param bool $echo
990
+	 * @return string
991
+	 * @throws EE_Error
992
+	 */
993
+	function espresso_organization_linkedin($echo = true)
994
+	{
995
+		if ($echo) {
996
+			echo EE_Registry::instance()->CFG->organization->get_pretty('linkedin'); // already escaped
997
+			return '';
998
+		}
999
+		return EE_Registry::instance()->CFG->organization->get_pretty('linkedin');
1000
+	}
1001 1001
 }
1002 1002
 
1003 1003
 if (! function_exists('espresso_organization_pinterest')) {
1004
-    /**
1005
-     * espresso_organization_pinterest
1006
-     *
1007
-     * @param bool $echo
1008
-     * @return string
1009
-     * @throws EE_Error
1010
-     */
1011
-    function espresso_organization_pinterest($echo = true)
1012
-    {
1013
-        if ($echo) {
1014
-            echo EE_Registry::instance()->CFG->organization->get_pretty('pinterest'); // already escaped
1015
-            return '';
1016
-        }
1017
-        return EE_Registry::instance()->CFG->organization->get_pretty('pinterest');
1018
-    }
1004
+	/**
1005
+	 * espresso_organization_pinterest
1006
+	 *
1007
+	 * @param bool $echo
1008
+	 * @return string
1009
+	 * @throws EE_Error
1010
+	 */
1011
+	function espresso_organization_pinterest($echo = true)
1012
+	{
1013
+		if ($echo) {
1014
+			echo EE_Registry::instance()->CFG->organization->get_pretty('pinterest'); // already escaped
1015
+			return '';
1016
+		}
1017
+		return EE_Registry::instance()->CFG->organization->get_pretty('pinterest');
1018
+	}
1019 1019
 }
1020 1020
 
1021 1021
 if (! function_exists('espresso_organization_google')) {
1022
-    /**
1023
-     * espresso_organization_google
1024
-     *
1025
-     * @param bool $echo
1026
-     * @return string
1027
-     * @throws EE_Error
1028
-     */
1029
-    function espresso_organization_google($echo = true)
1030
-    {
1031
-        if ($echo) {
1032
-            echo EE_Registry::instance()->CFG->organization->get_pretty('google'); // already escaped
1033
-            return '';
1034
-        }
1035
-        return EE_Registry::instance()->CFG->organization->get_pretty('google');
1036
-    }
1022
+	/**
1023
+	 * espresso_organization_google
1024
+	 *
1025
+	 * @param bool $echo
1026
+	 * @return string
1027
+	 * @throws EE_Error
1028
+	 */
1029
+	function espresso_organization_google($echo = true)
1030
+	{
1031
+		if ($echo) {
1032
+			echo EE_Registry::instance()->CFG->organization->get_pretty('google'); // already escaped
1033
+			return '';
1034
+		}
1035
+		return EE_Registry::instance()->CFG->organization->get_pretty('google');
1036
+	}
1037 1037
 }
1038 1038
 
1039 1039
 if (! function_exists('espresso_organization_instagram')) {
1040
-    /**
1041
-     * espresso_organization_instagram
1042
-     *
1043
-     * @param bool $echo
1044
-     * @return string
1045
-     * @throws EE_Error
1046
-     */
1047
-    function espresso_organization_instagram($echo = true)
1048
-    {
1049
-        if ($echo) {
1050
-            echo EE_Registry::instance()->CFG->organization->get_pretty('instagram'); // already escaped
1051
-            return '';
1052
-        }
1053
-        return EE_Registry::instance()->CFG->organization->get_pretty('instagram');
1054
-    }
1040
+	/**
1041
+	 * espresso_organization_instagram
1042
+	 *
1043
+	 * @param bool $echo
1044
+	 * @return string
1045
+	 * @throws EE_Error
1046
+	 */
1047
+	function espresso_organization_instagram($echo = true)
1048
+	{
1049
+		if ($echo) {
1050
+			echo EE_Registry::instance()->CFG->organization->get_pretty('instagram'); // already escaped
1051
+			return '';
1052
+		}
1053
+		return EE_Registry::instance()->CFG->organization->get_pretty('instagram');
1054
+	}
1055 1055
 }
1056 1056
 
1057 1057
 
@@ -1059,345 +1059,345 @@  discard block
 block discarded – undo
1059 1059
 
1060 1060
 
1061 1061
 if (! function_exists('espresso_event_venues')) {
1062
-    /**
1063
-     * espresso_event_venues
1064
-     *
1065
-     * @return array  all venues related to an event
1066
-     * @throws EE_Error
1067
-     * @throws ReflectionException
1068
-     */
1069
-    function espresso_event_venues()
1070
-    {
1071
-        return EEH_Venue_View::get_event_venues();
1072
-    }
1062
+	/**
1063
+	 * espresso_event_venues
1064
+	 *
1065
+	 * @return array  all venues related to an event
1066
+	 * @throws EE_Error
1067
+	 * @throws ReflectionException
1068
+	 */
1069
+	function espresso_event_venues()
1070
+	{
1071
+		return EEH_Venue_View::get_event_venues();
1072
+	}
1073 1073
 }
1074 1074
 
1075 1075
 
1076 1076
 if (! function_exists('espresso_venue_id')) {
1077
-    /**
1078
-     *    espresso_venue_name
1079
-     *
1080
-     * @access    public
1081
-     * @param int $EVT_ID
1082
-     * @return    string
1083
-     * @throws EE_Error
1084
-     * @throws ReflectionException
1085
-     */
1086
-    function espresso_venue_id($EVT_ID = 0)
1087
-    {
1088
-        $venue = EEH_Venue_View::get_venue($EVT_ID);
1089
-        return $venue instanceof EE_Venue ? $venue->ID() : 0;
1090
-    }
1077
+	/**
1078
+	 *    espresso_venue_name
1079
+	 *
1080
+	 * @access    public
1081
+	 * @param int $EVT_ID
1082
+	 * @return    string
1083
+	 * @throws EE_Error
1084
+	 * @throws ReflectionException
1085
+	 */
1086
+	function espresso_venue_id($EVT_ID = 0)
1087
+	{
1088
+		$venue = EEH_Venue_View::get_venue($EVT_ID);
1089
+		return $venue instanceof EE_Venue ? $venue->ID() : 0;
1090
+	}
1091 1091
 }
1092 1092
 
1093 1093
 
1094 1094
 if (! function_exists('espresso_is_venue_private')) {
1095
-    /**
1096
-     * Return whether a venue is private or not.
1097
-     *
1098
-     * @param int $VNU_ID optional, the venue id to check.
1099
-     *
1100
-     * @return bool | null
1101
-     * @throws EE_Error
1102
-     * @throws ReflectionException
1103
-     * @see EEH_Venue_View::get_venue() for more info on expected return results.
1104
-     */
1105
-    function espresso_is_venue_private($VNU_ID = 0)
1106
-    {
1107
-        return EEH_Venue_View::is_venue_private($VNU_ID);
1108
-    }
1095
+	/**
1096
+	 * Return whether a venue is private or not.
1097
+	 *
1098
+	 * @param int $VNU_ID optional, the venue id to check.
1099
+	 *
1100
+	 * @return bool | null
1101
+	 * @throws EE_Error
1102
+	 * @throws ReflectionException
1103
+	 * @see EEH_Venue_View::get_venue() for more info on expected return results.
1104
+	 */
1105
+	function espresso_is_venue_private($VNU_ID = 0)
1106
+	{
1107
+		return EEH_Venue_View::is_venue_private($VNU_ID);
1108
+	}
1109 1109
 }
1110 1110
 
1111 1111
 
1112 1112
 if (! function_exists('espresso_venue_is_password_protected')) {
1113
-    /**
1114
-     * returns true or false if a venue is password protected or not
1115
-     *
1116
-     * @param int $VNU_ID optional, the venue id to check.
1117
-     * @return bool
1118
-     * @throws EE_Error
1119
-     * @throws ReflectionException
1120
-     */
1121
-    function espresso_venue_is_password_protected($VNU_ID = 0)
1122
-    {
1123
-        EE_Registry::instance()->load_helper('Venue_View');
1124
-        return EEH_Venue_View::is_venue_password_protected($VNU_ID);
1125
-    }
1113
+	/**
1114
+	 * returns true or false if a venue is password protected or not
1115
+	 *
1116
+	 * @param int $VNU_ID optional, the venue id to check.
1117
+	 * @return bool
1118
+	 * @throws EE_Error
1119
+	 * @throws ReflectionException
1120
+	 */
1121
+	function espresso_venue_is_password_protected($VNU_ID = 0)
1122
+	{
1123
+		EE_Registry::instance()->load_helper('Venue_View');
1124
+		return EEH_Venue_View::is_venue_password_protected($VNU_ID);
1125
+	}
1126 1126
 }
1127 1127
 
1128 1128
 
1129 1129
 if (! function_exists('espresso_password_protected_venue_form')) {
1130
-    /**
1131
-     * Returns a password form if venue is password protected.
1132
-     *
1133
-     * @param int $VNU_ID optional, the venue id to check.
1134
-     * @return string
1135
-     * @throws EE_Error
1136
-     * @throws ReflectionException
1137
-     */
1138
-    function espresso_password_protected_venue_form($VNU_ID = 0)
1139
-    {
1140
-        EE_Registry::instance()->load_helper('Venue_View');
1141
-        return EEH_Venue_View::password_protected_venue_form($VNU_ID);
1142
-    }
1130
+	/**
1131
+	 * Returns a password form if venue is password protected.
1132
+	 *
1133
+	 * @param int $VNU_ID optional, the venue id to check.
1134
+	 * @return string
1135
+	 * @throws EE_Error
1136
+	 * @throws ReflectionException
1137
+	 */
1138
+	function espresso_password_protected_venue_form($VNU_ID = 0)
1139
+	{
1140
+		EE_Registry::instance()->load_helper('Venue_View');
1141
+		return EEH_Venue_View::password_protected_venue_form($VNU_ID);
1142
+	}
1143 1143
 }
1144 1144
 
1145 1145
 
1146 1146
 if (! function_exists('espresso_venue_name')) {
1147
-    /**
1148
-     *    espresso_venue_name
1149
-     *
1150
-     * @access    public
1151
-     * @param int    $VNU_ID
1152
-     * @param string $link_to - options( details, website, none ) whether to turn Venue name into a clickable link to the Venue's details page or website
1153
-     * @param bool   $echo
1154
-     * @return    string
1155
-     * @throws EE_Error
1156
-     * @throws ReflectionException
1157
-     */
1158
-    function espresso_venue_name($VNU_ID = 0, $link_to = 'details', $echo = true)
1159
-    {
1160
-        if ($echo) {
1161
-            echo EEH_Venue_View::venue_name($link_to, $VNU_ID); // already escaped
1162
-            return '';
1163
-        }
1164
-        return EEH_Venue_View::venue_name($link_to, $VNU_ID);
1165
-    }
1147
+	/**
1148
+	 *    espresso_venue_name
1149
+	 *
1150
+	 * @access    public
1151
+	 * @param int    $VNU_ID
1152
+	 * @param string $link_to - options( details, website, none ) whether to turn Venue name into a clickable link to the Venue's details page or website
1153
+	 * @param bool   $echo
1154
+	 * @return    string
1155
+	 * @throws EE_Error
1156
+	 * @throws ReflectionException
1157
+	 */
1158
+	function espresso_venue_name($VNU_ID = 0, $link_to = 'details', $echo = true)
1159
+	{
1160
+		if ($echo) {
1161
+			echo EEH_Venue_View::venue_name($link_to, $VNU_ID); // already escaped
1162
+			return '';
1163
+		}
1164
+		return EEH_Venue_View::venue_name($link_to, $VNU_ID);
1165
+	}
1166 1166
 }
1167 1167
 
1168 1168
 
1169 1169
 if (! function_exists('espresso_venue_link')) {
1170
-    /**
1171
-     *    espresso_venue_link
1172
-     *
1173
-     * @access    public
1174
-     * @param int    $VNU_ID
1175
-     * @param string $text
1176
-     * @return    string
1177
-     * @throws EE_Error
1178
-     * @throws ReflectionException
1179
-     */
1180
-    function espresso_venue_link($VNU_ID = 0, $text = '')
1181
-    {
1182
-        return EEH_Venue_View::venue_details_link($VNU_ID, $text);
1183
-    }
1170
+	/**
1171
+	 *    espresso_venue_link
1172
+	 *
1173
+	 * @access    public
1174
+	 * @param int    $VNU_ID
1175
+	 * @param string $text
1176
+	 * @return    string
1177
+	 * @throws EE_Error
1178
+	 * @throws ReflectionException
1179
+	 */
1180
+	function espresso_venue_link($VNU_ID = 0, $text = '')
1181
+	{
1182
+		return EEH_Venue_View::venue_details_link($VNU_ID, $text);
1183
+	}
1184 1184
 }
1185 1185
 
1186 1186
 
1187 1187
 if (! function_exists('espresso_venue_description')) {
1188
-    /**
1189
-     *    espresso_venue_description
1190
-     *
1191
-     * @access    public
1192
-     * @param bool $VNU_ID
1193
-     * @param bool $echo
1194
-     * @return    string
1195
-     * @throws EE_Error
1196
-     * @throws ReflectionException
1197
-     */
1198
-    function espresso_venue_description($VNU_ID = false, $echo = true)
1199
-    {
1200
-        if ($echo) {
1201
-            echo EEH_Venue_View::venue_description($VNU_ID); // already escaped
1202
-            return '';
1203
-        }
1204
-        return EEH_Venue_View::venue_description($VNU_ID);
1205
-    }
1188
+	/**
1189
+	 *    espresso_venue_description
1190
+	 *
1191
+	 * @access    public
1192
+	 * @param bool $VNU_ID
1193
+	 * @param bool $echo
1194
+	 * @return    string
1195
+	 * @throws EE_Error
1196
+	 * @throws ReflectionException
1197
+	 */
1198
+	function espresso_venue_description($VNU_ID = false, $echo = true)
1199
+	{
1200
+		if ($echo) {
1201
+			echo EEH_Venue_View::venue_description($VNU_ID); // already escaped
1202
+			return '';
1203
+		}
1204
+		return EEH_Venue_View::venue_description($VNU_ID);
1205
+	}
1206 1206
 }
1207 1207
 
1208 1208
 
1209 1209
 if (! function_exists('espresso_venue_excerpt')) {
1210
-    /**
1211
-     *    espresso_venue_excerpt
1212
-     *
1213
-     * @access    public
1214
-     * @param int  $VNU_ID
1215
-     * @param bool $echo
1216
-     * @return    string
1217
-     * @throws EE_Error
1218
-     * @throws ReflectionException
1219
-     */
1220
-    function espresso_venue_excerpt($VNU_ID = 0, $echo = true)
1221
-    {
1222
-        if ($echo) {
1223
-            echo EEH_Venue_View::venue_excerpt($VNU_ID); // already escaped
1224
-            return '';
1225
-        }
1226
-        return EEH_Venue_View::venue_excerpt($VNU_ID);
1227
-    }
1210
+	/**
1211
+	 *    espresso_venue_excerpt
1212
+	 *
1213
+	 * @access    public
1214
+	 * @param int  $VNU_ID
1215
+	 * @param bool $echo
1216
+	 * @return    string
1217
+	 * @throws EE_Error
1218
+	 * @throws ReflectionException
1219
+	 */
1220
+	function espresso_venue_excerpt($VNU_ID = 0, $echo = true)
1221
+	{
1222
+		if ($echo) {
1223
+			echo EEH_Venue_View::venue_excerpt($VNU_ID); // already escaped
1224
+			return '';
1225
+		}
1226
+		return EEH_Venue_View::venue_excerpt($VNU_ID);
1227
+	}
1228 1228
 }
1229 1229
 
1230 1230
 
1231 1231
 if (! function_exists('espresso_venue_categories')) {
1232
-    /**
1233
-     * espresso_venue_categories
1234
-     * returns the terms associated with a venue
1235
-     *
1236
-     * @param int  $VNU_ID
1237
-     * @param bool $hide_uncategorized
1238
-     * @param bool $echo
1239
-     * @return string
1240
-     * @throws EE_Error
1241
-     * @throws ReflectionException
1242
-     */
1243
-    function espresso_venue_categories($VNU_ID = 0, $hide_uncategorized = true, $echo = true)
1244
-    {
1245
-        if ($echo) {
1246
-            echo EEH_Venue_View::venue_categories($VNU_ID, $hide_uncategorized); // already escaped
1247
-            return '';
1248
-        }
1249
-        return EEH_Venue_View::venue_categories($VNU_ID, $hide_uncategorized);
1250
-    }
1232
+	/**
1233
+	 * espresso_venue_categories
1234
+	 * returns the terms associated with a venue
1235
+	 *
1236
+	 * @param int  $VNU_ID
1237
+	 * @param bool $hide_uncategorized
1238
+	 * @param bool $echo
1239
+	 * @return string
1240
+	 * @throws EE_Error
1241
+	 * @throws ReflectionException
1242
+	 */
1243
+	function espresso_venue_categories($VNU_ID = 0, $hide_uncategorized = true, $echo = true)
1244
+	{
1245
+		if ($echo) {
1246
+			echo EEH_Venue_View::venue_categories($VNU_ID, $hide_uncategorized); // already escaped
1247
+			return '';
1248
+		}
1249
+		return EEH_Venue_View::venue_categories($VNU_ID, $hide_uncategorized);
1250
+	}
1251 1251
 }
1252 1252
 
1253 1253
 
1254 1254
 if (! function_exists('espresso_venue_address')) {
1255
-    /**
1256
-     * espresso_venue_address
1257
-     * returns a formatted block of html  for displaying a venue's address
1258
-     *
1259
-     * @param string $type 'inline' or 'multiline'
1260
-     * @param int    $VNU_ID
1261
-     * @param bool   $echo
1262
-     * @return string
1263
-     * @throws EE_Error
1264
-     * @throws ReflectionException
1265
-     */
1266
-    function espresso_venue_address($type = 'multiline', $VNU_ID = 0, $echo = true)
1267
-    {
1268
-        if ($echo) {
1269
-            echo EEH_Venue_View::venue_address($type, $VNU_ID); // already escaped
1270
-            return '';
1271
-        }
1272
-        return EEH_Venue_View::venue_address($type, $VNU_ID);
1273
-    }
1255
+	/**
1256
+	 * espresso_venue_address
1257
+	 * returns a formatted block of html  for displaying a venue's address
1258
+	 *
1259
+	 * @param string $type 'inline' or 'multiline'
1260
+	 * @param int    $VNU_ID
1261
+	 * @param bool   $echo
1262
+	 * @return string
1263
+	 * @throws EE_Error
1264
+	 * @throws ReflectionException
1265
+	 */
1266
+	function espresso_venue_address($type = 'multiline', $VNU_ID = 0, $echo = true)
1267
+	{
1268
+		if ($echo) {
1269
+			echo EEH_Venue_View::venue_address($type, $VNU_ID); // already escaped
1270
+			return '';
1271
+		}
1272
+		return EEH_Venue_View::venue_address($type, $VNU_ID);
1273
+	}
1274 1274
 }
1275 1275
 
1276 1276
 
1277 1277
 if (! function_exists('espresso_venue_raw_address')) {
1278
-    /**
1279
-     * espresso_venue_address
1280
-     * returns an UN-formatted string containing a venue's address
1281
-     *
1282
-     * @param string $type 'inline' or 'multiline'
1283
-     * @param int    $VNU_ID
1284
-     * @param bool   $echo
1285
-     * @return string
1286
-     * @throws EE_Error
1287
-     * @throws ReflectionException
1288
-     */
1289
-    function espresso_venue_raw_address($type = 'multiline', $VNU_ID = 0, $echo = true)
1290
-    {
1291
-        if ($echo) {
1292
-            echo EEH_Venue_View::venue_address($type, $VNU_ID, false, false); // already escaped
1293
-            return '';
1294
-        }
1295
-        return EEH_Venue_View::venue_address($type, $VNU_ID, false, false);
1296
-    }
1278
+	/**
1279
+	 * espresso_venue_address
1280
+	 * returns an UN-formatted string containing a venue's address
1281
+	 *
1282
+	 * @param string $type 'inline' or 'multiline'
1283
+	 * @param int    $VNU_ID
1284
+	 * @param bool   $echo
1285
+	 * @return string
1286
+	 * @throws EE_Error
1287
+	 * @throws ReflectionException
1288
+	 */
1289
+	function espresso_venue_raw_address($type = 'multiline', $VNU_ID = 0, $echo = true)
1290
+	{
1291
+		if ($echo) {
1292
+			echo EEH_Venue_View::venue_address($type, $VNU_ID, false, false); // already escaped
1293
+			return '';
1294
+		}
1295
+		return EEH_Venue_View::venue_address($type, $VNU_ID, false, false);
1296
+	}
1297 1297
 }
1298 1298
 
1299 1299
 
1300 1300
 if (! function_exists('espresso_venue_has_address')) {
1301
-    /**
1302
-     * espresso_venue_has_address
1303
-     * returns TRUE or FALSE if a Venue has address information
1304
-     *
1305
-     * @param int $VNU_ID
1306
-     * @return bool
1307
-     * @throws EE_Error
1308
-     * @throws ReflectionException
1309
-     */
1310
-    function espresso_venue_has_address($VNU_ID = 0)
1311
-    {
1312
-        return EEH_Venue_View::venue_has_address($VNU_ID);
1313
-    }
1301
+	/**
1302
+	 * espresso_venue_has_address
1303
+	 * returns TRUE or FALSE if a Venue has address information
1304
+	 *
1305
+	 * @param int $VNU_ID
1306
+	 * @return bool
1307
+	 * @throws EE_Error
1308
+	 * @throws ReflectionException
1309
+	 */
1310
+	function espresso_venue_has_address($VNU_ID = 0)
1311
+	{
1312
+		return EEH_Venue_View::venue_has_address($VNU_ID);
1313
+	}
1314 1314
 }
1315 1315
 
1316 1316
 
1317 1317
 if (! function_exists('espresso_venue_gmap')) {
1318
-    /**
1319
-     * espresso_venue_gmap
1320
-     * returns a google map for the venue address
1321
-     *
1322
-     * @param int   $VNU_ID
1323
-     * @param bool  $map_ID
1324
-     * @param array $gmap
1325
-     * @param bool  $echo
1326
-     * @return string
1327
-     * @throws EE_Error
1328
-     * @throws ReflectionException
1329
-     */
1330
-    function espresso_venue_gmap($VNU_ID = 0, $map_ID = false, $gmap = [], $echo = true)
1331
-    {
1332
-        if ($echo) {
1333
-            echo EEH_Venue_View::venue_gmap($VNU_ID, $map_ID, $gmap); // already escaped
1334
-            return '';
1335
-        }
1336
-        return EEH_Venue_View::venue_gmap($VNU_ID, $map_ID, $gmap);
1337
-    }
1318
+	/**
1319
+	 * espresso_venue_gmap
1320
+	 * returns a google map for the venue address
1321
+	 *
1322
+	 * @param int   $VNU_ID
1323
+	 * @param bool  $map_ID
1324
+	 * @param array $gmap
1325
+	 * @param bool  $echo
1326
+	 * @return string
1327
+	 * @throws EE_Error
1328
+	 * @throws ReflectionException
1329
+	 */
1330
+	function espresso_venue_gmap($VNU_ID = 0, $map_ID = false, $gmap = [], $echo = true)
1331
+	{
1332
+		if ($echo) {
1333
+			echo EEH_Venue_View::venue_gmap($VNU_ID, $map_ID, $gmap); // already escaped
1334
+			return '';
1335
+		}
1336
+		return EEH_Venue_View::venue_gmap($VNU_ID, $map_ID, $gmap);
1337
+	}
1338 1338
 }
1339 1339
 
1340 1340
 
1341 1341
 if (! function_exists('espresso_venue_phone')) {
1342
-    /**
1343
-     * espresso_venue_phone
1344
-     *
1345
-     * @param int  $VNU_ID
1346
-     * @param bool $echo
1347
-     * @return string
1348
-     * @throws EE_Error
1349
-     * @throws ReflectionException
1350
-     */
1351
-    function espresso_venue_phone($VNU_ID = 0, $echo = true)
1352
-    {
1353
-        if ($echo) {
1354
-            echo EEH_Venue_View::venue_phone($VNU_ID); // already escaped
1355
-            return '';
1356
-        }
1357
-        return EEH_Venue_View::venue_phone($VNU_ID);
1358
-    }
1342
+	/**
1343
+	 * espresso_venue_phone
1344
+	 *
1345
+	 * @param int  $VNU_ID
1346
+	 * @param bool $echo
1347
+	 * @return string
1348
+	 * @throws EE_Error
1349
+	 * @throws ReflectionException
1350
+	 */
1351
+	function espresso_venue_phone($VNU_ID = 0, $echo = true)
1352
+	{
1353
+		if ($echo) {
1354
+			echo EEH_Venue_View::venue_phone($VNU_ID); // already escaped
1355
+			return '';
1356
+		}
1357
+		return EEH_Venue_View::venue_phone($VNU_ID);
1358
+	}
1359 1359
 }
1360 1360
 
1361 1361
 
1362 1362
 if (! function_exists('espresso_venue_website')) {
1363
-    /**
1364
-     * espresso_venue_website
1365
-     *
1366
-     * @param int  $VNU_ID
1367
-     * @param bool $echo
1368
-     * @return string
1369
-     * @throws EE_Error
1370
-     * @throws ReflectionException
1371
-     */
1372
-    function espresso_venue_website($VNU_ID = 0, $echo = true)
1373
-    {
1374
-        if ($echo) {
1375
-            echo EEH_Venue_View::venue_website_link($VNU_ID); // already escaped
1376
-            return '';
1377
-        }
1378
-        return EEH_Venue_View::venue_website_link($VNU_ID);
1379
-    }
1363
+	/**
1364
+	 * espresso_venue_website
1365
+	 *
1366
+	 * @param int  $VNU_ID
1367
+	 * @param bool $echo
1368
+	 * @return string
1369
+	 * @throws EE_Error
1370
+	 * @throws ReflectionException
1371
+	 */
1372
+	function espresso_venue_website($VNU_ID = 0, $echo = true)
1373
+	{
1374
+		if ($echo) {
1375
+			echo EEH_Venue_View::venue_website_link($VNU_ID); // already escaped
1376
+			return '';
1377
+		}
1378
+		return EEH_Venue_View::venue_website_link($VNU_ID);
1379
+	}
1380 1380
 }
1381 1381
 
1382 1382
 
1383 1383
 if (! function_exists('espresso_edit_venue_link')) {
1384
-    /**
1385
-     * espresso_edit_venue_link
1386
-     *
1387
-     * @param int  $VNU_ID
1388
-     * @param bool $echo
1389
-     * @return string
1390
-     * @throws EE_Error
1391
-     * @throws ReflectionException
1392
-     */
1393
-    function espresso_edit_venue_link($VNU_ID = 0, $echo = true)
1394
-    {
1395
-        if ($echo) {
1396
-            echo EEH_Venue_View::edit_venue_link($VNU_ID); // already escaped
1397
-            return '';
1398
-        }
1399
-        return EEH_Venue_View::edit_venue_link($VNU_ID);
1400
-    }
1384
+	/**
1385
+	 * espresso_edit_venue_link
1386
+	 *
1387
+	 * @param int  $VNU_ID
1388
+	 * @param bool $echo
1389
+	 * @return string
1390
+	 * @throws EE_Error
1391
+	 * @throws ReflectionException
1392
+	 */
1393
+	function espresso_edit_venue_link($VNU_ID = 0, $echo = true)
1394
+	{
1395
+		if ($echo) {
1396
+			echo EEH_Venue_View::edit_venue_link($VNU_ID); // already escaped
1397
+			return '';
1398
+		}
1399
+		return EEH_Venue_View::edit_venue_link($VNU_ID);
1400
+	}
1401 1401
 }
1402 1402
 
1403 1403
 
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since           4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.10.33.rc.015');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.10.33.rc.015');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
141 141
\ No newline at end of file
Please login to merge, or discard this patch.