Completed
Branch FET-Wait-List (8e9360)
by
unknown
103:16 queued 91:24
created
core/domain/Domain.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -15,13 +15,13 @@
 block discarded – undo
15 15
  */
16 16
 class Domain extends DomainBase
17 17
 {
18
-    /**
19
-     * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
20
-     * Page ui.
21
-     */
22
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
23
-        = 'manual_registration_status_change_from_registration_admin';
18
+	/**
19
+	 * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
20
+	 * Page ui.
21
+	 */
22
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
23
+		= 'manual_registration_status_change_from_registration_admin';
24 24
 
25
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
26
-        = 'manual_registration_status_change_from_registration_admin_and_notify';
25
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
26
+		= 'manual_registration_status_change_from_registration_admin_and_notify';
27 27
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 1 patch
Indentation   +1844 added lines, -1844 removed lines patch added patch discarded remove patch
@@ -18,1850 +18,1850 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * Used to reference when a registration has never been checked in.
23
-     *
24
-     * @deprecated use \EE_Checkin::status_checked_never instead
25
-     * @type int
26
-     */
27
-    const checkin_status_never = 2;
28
-
29
-    /**
30
-     * Used to reference when a registration has been checked in.
31
-     *
32
-     * @deprecated use \EE_Checkin::status_checked_in instead
33
-     * @type int
34
-     */
35
-    const checkin_status_in = 1;
36
-
37
-
38
-    /**
39
-     * Used to reference when a registration has been checked out.
40
-     *
41
-     * @deprecated use \EE_Checkin::status_checked_out instead
42
-     * @type int
43
-     */
44
-    const checkin_status_out = 0;
45
-
46
-
47
-    /**
48
-     * extra meta key for tracking reg status os trashed registrations
49
-     *
50
-     * @type string
51
-     */
52
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
-
54
-
55
-    /**
56
-     * extra meta key for tracking if registration has reserved ticket
57
-     *
58
-     * @type string
59
-     */
60
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
-
62
-
63
-    /**
64
-     * @param array  $props_n_values          incoming values
65
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
-     *                                        used.)
67
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
-     *                                        date_format and the second value is the time format
69
-     * @return EE_Registration
70
-     * @throws EE_Error
71
-     */
72
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
-    {
74
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Registration
84
-     */
85
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
-    {
87
-        return new self($props_n_values, true, $timezone);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Event ID
93
-     *
94
-     * @param        int $EVT_ID Event ID
95
-     * @throws EE_Error
96
-     * @throws RuntimeException
97
-     */
98
-    public function set_event($EVT_ID = 0)
99
-    {
100
-        $this->set('EVT_ID', $EVT_ID);
101
-    }
102
-
103
-
104
-    /**
105
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
-     * be routed to internal methods
107
-     *
108
-     * @param string $field_name
109
-     * @param mixed  $field_value
110
-     * @param bool   $use_default
111
-     * @throws \EE_Error
112
-     * @throws \RuntimeException
113
-     */
114
-    public function set($field_name, $field_value, $use_default = false)
115
-    {
116
-        switch ($field_name) {
117
-            case 'REG_code':
118
-                if (! empty($field_value) && $this->reg_code() === null) {
119
-                    $this->set_reg_code($field_value, $use_default);
120
-                }
121
-                break;
122
-            case 'STS_ID':
123
-                $this->set_status($field_value, $use_default);
124
-                break;
125
-            default:
126
-                parent::set($field_name, $field_value, $use_default);
127
-        }
128
-    }
129
-
130
-
131
-    /**
132
-     * Set Status ID
133
-     * updates the registration status and ALSO...
134
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
135
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
136
-     *
137
-     * @param string       $new_STS_ID
138
-     * @param boolean      $use_default
139
-     * @param Context|null $context
140
-     * @return bool
141
-     * @throws EE_Error
142
-     * @throws EntityNotFoundException
143
-     * @throws InvalidArgumentException
144
-     * @throws ReflectionException
145
-     * @throws RuntimeException
146
-     * @throws InvalidDataTypeException
147
-     * @throws InvalidInterfaceException
148
-     */
149
-    public function set_status($new_STS_ID = null, $use_default = false, Context $context = null)
150
-    {
151
-        // get current REG_Status
152
-        $old_STS_ID = $this->status_ID();
153
-        // if status has changed
154
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
155
-            && ! empty($old_STS_ID) // and that old status is actually set
156
-            && ! empty($new_STS_ID) // as well as the new status
157
-            && $this->ID() // ensure registration is in the db
158
-        ) {
159
-            // TO approved
160
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
161
-                // reserve a space by incrementing ticket and datetime sold values
162
-                $this->_reserve_registration_space();
163
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
164
-                // OR FROM  approved
165
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
166
-                // release a space by decrementing ticket and datetime sold values
167
-                $this->_release_registration_space();
168
-                do_action(
169
-                    'AHEE__EE_Registration__set_status__from_approved',
170
-                    $this,
171
-                    $old_STS_ID,
172
-                    $new_STS_ID,
173
-                    $context
174
-                );
175
-            }
176
-            // update status
177
-            parent::set('STS_ID', $new_STS_ID, $use_default);
178
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
179
-            /** @type EE_Transaction_Payments $transaction_payments */
180
-            $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
181
-            $transaction_payments->recalculate_transaction_total($this->transaction(), false);
182
-            $this->transaction()->update_status_based_on_total_paid(true);
183
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
184
-            return true;
185
-        }
186
-        //even though the old value matches the new value, it's still good to
187
-        //allow the parent set method to have a say
188
-        parent::set('STS_ID', $new_STS_ID, $use_default);
189
-        return true;
190
-    }
191
-
192
-
193
-    /**
194
-     * update REGs and TXN when cancelled or declined registrations involved
195
-     *
196
-     * @param string       $new_STS_ID
197
-     * @param string       $old_STS_ID
198
-     * @param Context|null $context
199
-     * @throws EE_Error
200
-     * @throws InvalidArgumentException
201
-     * @throws InvalidDataTypeException
202
-     * @throws InvalidInterfaceException
203
-     * @throws ReflectionException
204
-     */
205
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null)
206
-    {
207
-        // these reg statuses should not be considered in any calculations involving monies owing
208
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
209
-        // true if registration has been cancelled or declined
210
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
211
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
212
-        ) {
213
-            /** @type EE_Registration_Processor $registration_processor */
214
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
215
-            /** @type EE_Transaction_Processor $transaction_processor */
216
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
217
-            // cancelled or declined registration
218
-            $registration_processor->update_registration_after_being_canceled_or_declined(
219
-                $this,
220
-                $closed_reg_statuses
221
-            );
222
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
223
-                $this,
224
-                $closed_reg_statuses,
225
-                false
226
-            );
227
-            do_action(
228
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
229
-                $this,
230
-                $old_STS_ID,
231
-                $new_STS_ID,
232
-                $context
233
-            );
234
-            return;
235
-        }
236
-        // true if reinstating cancelled or declined registration
237
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
238
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
239
-        ) {
240
-            /** @type EE_Registration_Processor $registration_processor */
241
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
242
-            /** @type EE_Transaction_Processor $transaction_processor */
243
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
244
-            // reinstating cancelled or declined registration
245
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
246
-                $this,
247
-                $closed_reg_statuses
248
-            );
249
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
250
-                $this,
251
-                $closed_reg_statuses,
252
-                false
253
-            );
254
-            do_action(
255
-                'AHEE__EE_Registration__set_status__after_reinstated',
256
-                $this,
257
-                $old_STS_ID,
258
-                $new_STS_ID,
259
-                $context
260
-            );
261
-        }
262
-    }
263
-
264
-
265
-    /**
266
-     *        get Status ID
267
-     */
268
-    public function status_ID()
269
-    {
270
-        return $this->get('STS_ID');
271
-    }
272
-
273
-
274
-    /**
275
-     * increments this registration's related ticket sold and corresponding datetime sold values
276
-     *
277
-     * @return void
278
-     * @throws EE_Error
279
-     * @throws EntityNotFoundException
280
-     */
281
-    private function _reserve_registration_space()
282
-    {
283
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
284
-        // so stop tracking that this reg has a ticket reserved
285
-        $this->release_reserved_ticket();
286
-        $ticket = $this->ticket();
287
-        $ticket->increase_sold();
288
-        $ticket->save();
289
-        // possibly set event status to sold out
290
-        $this->event()->perform_sold_out_status_check();
291
-    }
292
-
293
-
294
-    /**
295
-     * Gets the ticket this registration is for
296
-     *
297
-     * @param boolean $include_archived whether to include archived tickets or not.
298
-     * @return EE_Ticket|EE_Base_Class
299
-     * @throws \EE_Error
300
-     */
301
-    public function ticket($include_archived = true)
302
-    {
303
-        $query_params = array();
304
-        if ($include_archived) {
305
-            $query_params['default_where_conditions'] = 'none';
306
-        }
307
-        return $this->get_first_related('Ticket', $query_params);
308
-    }
309
-
310
-
311
-    /**
312
-     * Gets the event this registration is for
313
-     *
314
-     * @return EE_Event
315
-     * @throws EE_Error
316
-     * @throws EntityNotFoundException
317
-     */
318
-    public function event()
319
-    {
320
-        $event = $this->get_first_related('Event');
321
-        if (! $event instanceof \EE_Event) {
322
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
323
-        }
324
-        return $event;
325
-    }
326
-
327
-
328
-    /**
329
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
330
-     * with the author of the event this registration is for.
331
-     *
332
-     * @since 4.5.0
333
-     * @return int
334
-     * @throws EE_Error
335
-     * @throws EntityNotFoundException
336
-     */
337
-    public function wp_user()
338
-    {
339
-        $event = $this->event();
340
-        if ($event instanceof EE_Event) {
341
-            return $event->wp_user();
342
-        }
343
-        return 0;
344
-    }
345
-
346
-
347
-    /**
348
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
349
-     *
350
-     * @return void
351
-     * @throws \EE_Error
352
-     */
353
-    private function _release_registration_space()
354
-    {
355
-        $ticket = $this->ticket();
356
-        $ticket->decrease_sold();
357
-        $ticket->save();
358
-    }
359
-
360
-
361
-    /**
362
-     * tracks this registration's ticket reservation in extra meta
363
-     * and can increment related ticket reserved and corresponding datetime reserved values
364
-     *
365
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
366
-     * @return void
367
-     * @throws \EE_Error
368
-     */
369
-    public function reserve_ticket($update_ticket = false)
370
-    {
371
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
372
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
373
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
374
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
375
-                $ticket = $this->ticket();
376
-                $ticket->increase_reserved();
377
-                $ticket->save();
378
-            }
379
-        }
380
-    }
381
-
382
-
383
-    /**
384
-     * stops tracking this registration's ticket reservation in extra meta
385
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
386
-     *
387
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
388
-     * @return void
389
-     * @throws \EE_Error
390
-     */
391
-    public function release_reserved_ticket($update_ticket = false)
392
-    {
393
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
394
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
395
-            // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
396
-            if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
397
-                $ticket = $this->ticket();
398
-                $ticket->decrease_reserved();
399
-                $ticket->save();
400
-            }
401
-        }
402
-    }
403
-
404
-
405
-    /**
406
-     * Set Attendee ID
407
-     *
408
-     * @param        int $ATT_ID Attendee ID
409
-     * @throws EE_Error
410
-     * @throws RuntimeException
411
-     */
412
-    public function set_attendee_id($ATT_ID = 0)
413
-    {
414
-        $this->set('ATT_ID', $ATT_ID);
415
-    }
416
-
417
-
418
-    /**
419
-     *        Set Transaction ID
420
-     *
421
-     * @param        int $TXN_ID Transaction ID
422
-     * @throws EE_Error
423
-     * @throws RuntimeException
424
-     */
425
-    public function set_transaction_id($TXN_ID = 0)
426
-    {
427
-        $this->set('TXN_ID', $TXN_ID);
428
-    }
429
-
430
-
431
-    /**
432
-     *        Set Session
433
-     *
434
-     * @param    string $REG_session PHP Session ID
435
-     * @throws EE_Error
436
-     * @throws RuntimeException
437
-     */
438
-    public function set_session($REG_session = '')
439
-    {
440
-        $this->set('REG_session', $REG_session);
441
-    }
442
-
443
-
444
-    /**
445
-     *        Set Registration URL Link
446
-     *
447
-     * @param    string $REG_url_link Registration URL Link
448
-     * @throws EE_Error
449
-     * @throws RuntimeException
450
-     */
451
-    public function set_reg_url_link($REG_url_link = '')
452
-    {
453
-        $this->set('REG_url_link', $REG_url_link);
454
-    }
455
-
456
-
457
-    /**
458
-     *        Set Attendee Counter
459
-     *
460
-     * @param        int $REG_count Primary Attendee
461
-     * @throws EE_Error
462
-     * @throws RuntimeException
463
-     */
464
-    public function set_count($REG_count = 1)
465
-    {
466
-        $this->set('REG_count', $REG_count);
467
-    }
468
-
469
-
470
-    /**
471
-     *        Set Group Size
472
-     *
473
-     * @param        boolean $REG_group_size Group Registration
474
-     * @throws EE_Error
475
-     * @throws RuntimeException
476
-     */
477
-    public function set_group_size($REG_group_size = false)
478
-    {
479
-        $this->set('REG_group_size', $REG_group_size);
480
-    }
481
-
482
-
483
-    /**
484
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
485
-     *    EEM_Registration::status_id_not_approved
486
-     *
487
-     * @return        boolean
488
-     */
489
-    public function is_not_approved()
490
-    {
491
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
492
-    }
493
-
494
-
495
-    /**
496
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
497
-     *    EEM_Registration::status_id_pending_payment
498
-     *
499
-     * @return        boolean
500
-     */
501
-    public function is_pending_payment()
502
-    {
503
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
504
-    }
505
-
506
-
507
-    /**
508
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
509
-     *
510
-     * @return        boolean
511
-     */
512
-    public function is_approved()
513
-    {
514
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
515
-    }
516
-
517
-
518
-    /**
519
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
520
-     *
521
-     * @return        boolean
522
-     */
523
-    public function is_cancelled()
524
-    {
525
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
526
-    }
527
-
528
-
529
-    /**
530
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
531
-     *
532
-     * @return        boolean
533
-     */
534
-    public function is_declined()
535
-    {
536
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
537
-    }
538
-
539
-
540
-    /**
541
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
542
-     *    EEM_Registration::status_id_incomplete
543
-     *
544
-     * @return        boolean
545
-     */
546
-    public function is_incomplete()
547
-    {
548
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
549
-    }
550
-
551
-
552
-    /**
553
-     *        Set Registration Date
554
-     *
555
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
556
-     *                                                 Date
557
-     * @throws EE_Error
558
-     * @throws RuntimeException
559
-     */
560
-    public function set_reg_date($REG_date = false)
561
-    {
562
-        $this->set('REG_date', $REG_date);
563
-    }
564
-
565
-
566
-    /**
567
-     *    Set final price owing for this registration after all ticket/price modifications
568
-     *
569
-     * @access    public
570
-     * @param    float $REG_final_price
571
-     * @throws EE_Error
572
-     * @throws RuntimeException
573
-     */
574
-    public function set_final_price($REG_final_price = 0.00)
575
-    {
576
-        $this->set('REG_final_price', $REG_final_price);
577
-    }
578
-
579
-
580
-    /**
581
-     *    Set amount paid towards this registration's final price
582
-     *
583
-     * @access    public
584
-     * @param    float $REG_paid
585
-     * @throws EE_Error
586
-     * @throws RuntimeException
587
-     */
588
-    public function set_paid($REG_paid = 0.00)
589
-    {
590
-        $this->set('REG_paid', $REG_paid);
591
-    }
592
-
593
-
594
-    /**
595
-     *        Attendee Is Going
596
-     *
597
-     * @param        boolean $REG_att_is_going Attendee Is Going
598
-     * @throws EE_Error
599
-     * @throws RuntimeException
600
-     */
601
-    public function set_att_is_going($REG_att_is_going = false)
602
-    {
603
-        $this->set('REG_att_is_going', $REG_att_is_going);
604
-    }
605
-
606
-
607
-    /**
608
-     * Gets the related attendee
609
-     *
610
-     * @return EE_Attendee
611
-     * @throws EE_Error
612
-     */
613
-    public function attendee()
614
-    {
615
-        return $this->get_first_related('Attendee');
616
-    }
617
-
618
-
619
-    /**
620
-     *        get Event ID
621
-     */
622
-    public function event_ID()
623
-    {
624
-        return $this->get('EVT_ID');
625
-    }
626
-
627
-
628
-    /**
629
-     *        get Event ID
630
-     */
631
-    public function event_name()
632
-    {
633
-        $event = $this->event_obj();
634
-        if ($event) {
635
-            return $event->name();
636
-        } else {
637
-            return null;
638
-        }
639
-    }
640
-
641
-
642
-    /**
643
-     * Fetches the event this registration is for
644
-     *
645
-     * @return EE_Event
646
-     * @throws EE_Error
647
-     */
648
-    public function event_obj()
649
-    {
650
-        return $this->get_first_related('Event');
651
-    }
652
-
653
-
654
-    /**
655
-     *        get Attendee ID
656
-     */
657
-    public function attendee_ID()
658
-    {
659
-        return $this->get('ATT_ID');
660
-    }
661
-
662
-
663
-    /**
664
-     *        get PHP Session ID
665
-     */
666
-    public function session_ID()
667
-    {
668
-        return $this->get('REG_session');
669
-    }
670
-
671
-
672
-    /**
673
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
674
-     *
675
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
676
-     * @return string
677
-     */
678
-    public function receipt_url($messenger = 'html')
679
-    {
680
-
681
-        /**
682
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
683
-         * already in use on old system.  If there is then we just return the standard url for it.
684
-         *
685
-         * @since 4.5.0
686
-         */
687
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
688
-        $has_custom             = EEH_Template::locate_template(
689
-            $template_relative_path,
690
-            array(),
691
-            true,
692
-            true,
693
-            true
694
-        );
695
-
696
-        if ($has_custom) {
697
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
698
-        }
699
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
700
-    }
701
-
702
-
703
-    /**
704
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
705
-     *
706
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
707
-     * @return string
708
-     * @throws EE_Error
709
-     */
710
-    public function invoice_url($messenger = 'html')
711
-    {
712
-        /**
713
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
714
-         * already in use on old system.  If there is then we just return the standard url for it.
715
-         *
716
-         * @since 4.5.0
717
-         */
718
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
719
-        $has_custom             = EEH_Template::locate_template(
720
-            $template_relative_path,
721
-            array(),
722
-            true,
723
-            true,
724
-            true
725
-        );
726
-
727
-        if ($has_custom) {
728
-            if ($messenger == 'html') {
729
-                return $this->invoice_url('launch');
730
-            }
731
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
732
-
733
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
734
-            if ($messenger == 'html') {
735
-                $query_args['html'] = true;
736
-            }
737
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
738
-        }
739
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
740
-    }
741
-
742
-
743
-    /**
744
-     * get Registration URL Link
745
-     *
746
-     * @access public
747
-     * @return string
748
-     * @throws \EE_Error
749
-     */
750
-    public function reg_url_link()
751
-    {
752
-        return (string) $this->get('REG_url_link');
753
-    }
754
-
755
-
756
-    /**
757
-     * Echoes out invoice_url()
758
-     *
759
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
760
-     * @return void
761
-     * @throws EE_Error
762
-     */
763
-    public function e_invoice_url($type = 'launch')
764
-    {
765
-        echo $this->invoice_url($type);
766
-    }
767
-
768
-
769
-    /**
770
-     * Echoes out payment_overview_url
771
-     */
772
-    public function e_payment_overview_url()
773
-    {
774
-        echo $this->payment_overview_url();
775
-    }
776
-
777
-
778
-    /**
779
-     * Gets the URL of the thank you page with this registration REG_url_link added as
780
-     * a query parameter
781
-     *
782
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
783
-     *                            payment overview url.
784
-     * @return string
785
-     * @throws EE_Error
786
-     */
787
-    public function payment_overview_url($clear_session = false)
788
-    {
789
-        return add_query_arg(array(
790
-            'e_reg_url_link' => $this->reg_url_link(),
791
-            'step'           => 'payment_options',
792
-            'revisit'        => true,
793
-            'clear_session' => (bool) $clear_session
794
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
795
-    }
796
-
797
-
798
-    /**
799
-     * Gets the URL of the thank you page with this registration REG_url_link added as
800
-     * a query parameter
801
-     *
802
-     * @return string
803
-     * @throws EE_Error
804
-     */
805
-    public function edit_attendee_information_url()
806
-    {
807
-        return add_query_arg(array(
808
-            'e_reg_url_link' => $this->reg_url_link(),
809
-            'step'           => 'attendee_information',
810
-            'revisit'        => true,
811
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
812
-    }
813
-
814
-
815
-    /**
816
-     * Simply generates and returns the appropriate admin_url link to edit this registration
817
-     *
818
-     * @return string
819
-     * @throws EE_Error
820
-     */
821
-    public function get_admin_edit_url()
822
-    {
823
-        return EEH_URL::add_query_args_and_nonce(array(
824
-            'page'    => 'espresso_registrations',
825
-            'action'  => 'view_registration',
826
-            '_REG_ID' => $this->ID(),
827
-        ), admin_url('admin.php'));
828
-    }
829
-
830
-
831
-    /**
832
-     *    is_primary_registrant?
833
-     */
834
-    public function is_primary_registrant()
835
-    {
836
-        return $this->get('REG_count') == 1 ? true : false;
837
-    }
838
-
839
-
840
-    /**
841
-     * This returns the primary registration object for this registration group (which may be this object).
842
-     *
843
-     * @return EE_Registration
844
-     * @throws EE_Error
845
-     */
846
-    public function get_primary_registration()
847
-    {
848
-        if ($this->is_primary_registrant()) {
849
-            return $this;
850
-        }
851
-
852
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
853
-        /** @var EE_Registration $primary_registrant */
854
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
855
-            array(
856
-                'TXN_ID'    => $this->transaction_ID(),
857
-                'REG_count' => 1,
858
-            ),
859
-        ));
860
-        return $primary_registrant;
861
-    }
862
-
863
-
864
-    /**
865
-     *        get  Attendee Number
866
-     *
867
-     * @access        public
868
-     */
869
-    public function count()
870
-    {
871
-        return $this->get('REG_count');
872
-    }
873
-
874
-
875
-    /**
876
-     *        get Group Size
877
-     */
878
-    public function group_size()
879
-    {
880
-        return $this->get('REG_group_size');
881
-    }
882
-
883
-
884
-    /**
885
-     *        get Registration Date
886
-     */
887
-    public function date()
888
-    {
889
-        return $this->get('REG_date');
890
-    }
891
-
892
-
893
-    /**
894
-     * gets a pretty date
895
-     *
896
-     * @param string $date_format
897
-     * @param string $time_format
898
-     * @return string
899
-     * @throws EE_Error
900
-     */
901
-    public function pretty_date($date_format = null, $time_format = null)
902
-    {
903
-        return $this->get_datetime('REG_date', $date_format, $time_format);
904
-    }
905
-
906
-
907
-    /**
908
-     * final_price
909
-     * the registration's share of the transaction total, so that the
910
-     * sum of all the transaction's REG_final_prices equal the transaction's total
911
-     *
912
-     * @return float
913
-     * @throws EE_Error
914
-     */
915
-    public function final_price()
916
-    {
917
-        return $this->get('REG_final_price');
918
-    }
919
-
920
-
921
-    /**
922
-     * pretty_final_price
923
-     *  final price as formatted string, with correct decimal places and currency symbol
924
-     *
925
-     * @return string
926
-     * @throws EE_Error
927
-     */
928
-    public function pretty_final_price()
929
-    {
930
-        return $this->get_pretty('REG_final_price');
931
-    }
932
-
933
-
934
-    /**
935
-     * get paid (yeah)
936
-     *
937
-     * @return float
938
-     * @throws EE_Error
939
-     */
940
-    public function paid()
941
-    {
942
-        return $this->get('REG_paid');
943
-    }
944
-
945
-
946
-    /**
947
-     * pretty_paid
948
-     *
949
-     * @return float
950
-     * @throws EE_Error
951
-     */
952
-    public function pretty_paid()
953
-    {
954
-        return $this->get_pretty('REG_paid');
955
-    }
956
-
957
-
958
-    /**
959
-     * owes_monies_and_can_pay
960
-     * whether or not this registration has monies owing and it's' status allows payment
961
-     *
962
-     * @param array $requires_payment
963
-     * @return bool
964
-     * @throws EE_Error
965
-     */
966
-    public function owes_monies_and_can_pay($requires_payment = array())
967
-    {
968
-        // these reg statuses require payment (if event is not free)
969
-        $requires_payment = ! empty($requires_payment)
970
-            ? $requires_payment
971
-            : EEM_Registration::reg_statuses_that_allow_payment();
972
-        if (in_array($this->status_ID(), $requires_payment) &&
973
-            $this->final_price() != 0 &&
974
-            $this->final_price() != $this->paid()
975
-        ) {
976
-            return true;
977
-        } else {
978
-            return false;
979
-        }
980
-    }
981
-
982
-
983
-    /**
984
-     * Prints out the return value of $this->pretty_status()
985
-     *
986
-     * @param bool $show_icons
987
-     * @return void
988
-     * @throws EE_Error
989
-     */
990
-    public function e_pretty_status($show_icons = false)
991
-    {
992
-        echo $this->pretty_status($show_icons);
993
-    }
994
-
995
-
996
-    /**
997
-     * Returns a nice version of the status for displaying to customers
998
-     *
999
-     * @param bool $show_icons
1000
-     * @return string
1001
-     * @throws EE_Error
1002
-     */
1003
-    public function pretty_status($show_icons = false)
1004
-    {
1005
-        $status = EEM_Status::instance()->localized_status(
1006
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1007
-            false,
1008
-            'sentence'
1009
-        );
1010
-        $icon   = '';
1011
-        switch ($this->status_ID()) {
1012
-            case EEM_Registration::status_id_approved:
1013
-                $icon = $show_icons
1014
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1015
-                    : '';
1016
-                break;
1017
-            case EEM_Registration::status_id_pending_payment:
1018
-                $icon = $show_icons
1019
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1020
-                    : '';
1021
-                break;
1022
-            case EEM_Registration::status_id_not_approved:
1023
-                $icon = $show_icons
1024
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1025
-                    : '';
1026
-                break;
1027
-            case EEM_Registration::status_id_cancelled:
1028
-                $icon = $show_icons
1029
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1030
-                    : '';
1031
-                break;
1032
-            case EEM_Registration::status_id_incomplete:
1033
-                $icon = $show_icons
1034
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1035
-                    : '';
1036
-                break;
1037
-            case EEM_Registration::status_id_declined:
1038
-                $icon = $show_icons
1039
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1040
-                    : '';
1041
-                break;
1042
-            case EEM_Registration::status_id_wait_list:
1043
-                $icon = $show_icons
1044
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1045
-                    : '';
1046
-                break;
1047
-        }
1048
-        return $icon . $status[$this->status_ID()];
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     *        get Attendee Is Going
1054
-     */
1055
-    public function att_is_going()
1056
-    {
1057
-        return $this->get('REG_att_is_going');
1058
-    }
1059
-
1060
-
1061
-    /**
1062
-     * Gets related answers
1063
-     *
1064
-     * @param array $query_params like EEM_Base::get_all
1065
-     * @return EE_Answer[]
1066
-     * @throws EE_Error
1067
-     */
1068
-    public function answers($query_params = null)
1069
-    {
1070
-        return $this->get_many_related('Answer', $query_params);
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * Gets the registration's answer value to the specified question
1076
-     * (either the question's ID or a question object)
1077
-     *
1078
-     * @param EE_Question|int $question
1079
-     * @param bool            $pretty_value
1080
-     * @return array|string if pretty_value= true, the result will always be a string
1081
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1082
-     * will convert it into some kind of string)
1083
-     * @throws EE_Error
1084
-     */
1085
-    public function answer_value_to_question($question, $pretty_value = true)
1086
-    {
1087
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1088
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * question_groups
1094
-     * returns an array of EE_Question_Group objects for this registration
1095
-     *
1096
-     * @return EE_Question_Group[]
1097
-     * @throws EE_Error
1098
-     * @throws EntityNotFoundException
1099
-     */
1100
-    public function question_groups()
1101
-    {
1102
-        $question_groups = array();
1103
-        if ($this->event() instanceof EE_Event) {
1104
-            $question_groups = $this->event()->question_groups(
1105
-                array(
1106
-                    array(
1107
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1108
-                    ),
1109
-                    'order_by' => array('QSG_order' => 'ASC'),
1110
-                )
1111
-            );
1112
-        }
1113
-        return $question_groups;
1114
-    }
1115
-
1116
-
1117
-    /**
1118
-     * count_question_groups
1119
-     * returns a count of the number of EE_Question_Group objects for this registration
1120
-     *
1121
-     * @return int
1122
-     * @throws EE_Error
1123
-     * @throws EntityNotFoundException
1124
-     */
1125
-    public function count_question_groups()
1126
-    {
1127
-        $qg_count = 0;
1128
-        if ($this->event() instanceof EE_Event) {
1129
-            $qg_count = $this->event()->count_related(
1130
-                'Question_Group',
1131
-                array(
1132
-                    array(
1133
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1134
-                    ),
1135
-                )
1136
-            );
1137
-        }
1138
-        return $qg_count;
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     * Returns the registration date in the 'standard' string format
1144
-     * (function may be improved in the future to allow for different formats and timezones)
1145
-     *
1146
-     * @return string
1147
-     * @throws EE_Error
1148
-     */
1149
-    public function reg_date()
1150
-    {
1151
-        return $this->get_datetime('REG_date');
1152
-    }
1153
-
1154
-
1155
-    /**
1156
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1157
-     * the ticket this registration purchased, or the datetime they have registered
1158
-     * to attend)
1159
-     *
1160
-     * @return EE_Datetime_Ticket
1161
-     * @throws EE_Error
1162
-     */
1163
-    public function datetime_ticket()
1164
-    {
1165
-        return $this->get_first_related('Datetime_Ticket');
1166
-    }
1167
-
1168
-
1169
-    /**
1170
-     * Sets the registration's datetime_ticket.
1171
-     *
1172
-     * @param EE_Datetime_Ticket $datetime_ticket
1173
-     * @return EE_Datetime_Ticket
1174
-     * @throws EE_Error
1175
-     */
1176
-    public function set_datetime_ticket($datetime_ticket)
1177
-    {
1178
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1179
-    }
1180
-
1181
-    /**
1182
-     * Gets deleted
1183
-     *
1184
-     * @return bool
1185
-     * @throws EE_Error
1186
-     */
1187
-    public function deleted()
1188
-    {
1189
-        return $this->get('REG_deleted');
1190
-    }
1191
-
1192
-    /**
1193
-     * Sets deleted
1194
-     *
1195
-     * @param boolean $deleted
1196
-     * @return bool
1197
-     * @throws EE_Error
1198
-     * @throws RuntimeException
1199
-     */
1200
-    public function set_deleted($deleted)
1201
-    {
1202
-        if ($deleted) {
1203
-            $this->delete();
1204
-        } else {
1205
-            $this->restore();
1206
-        }
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * Get the status object of this object
1212
-     *
1213
-     * @return EE_Status
1214
-     * @throws EE_Error
1215
-     */
1216
-    public function status_obj()
1217
-    {
1218
-        return $this->get_first_related('Status');
1219
-    }
1220
-
1221
-
1222
-    /**
1223
-     * Returns the number of times this registration has checked into any of the datetimes
1224
-     * its available for
1225
-     *
1226
-     * @return int
1227
-     * @throws EE_Error
1228
-     */
1229
-    public function count_checkins()
1230
-    {
1231
-        return $this->get_model()->count_related($this, 'Checkin');
1232
-    }
1233
-
1234
-
1235
-    /**
1236
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1237
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1238
-     *
1239
-     * @return int
1240
-     * @throws EE_Error
1241
-     */
1242
-    public function count_checkins_not_checkedout()
1243
-    {
1244
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1250
-     *
1251
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1252
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1253
-     *                                          consider registration status as well as datetime access.
1254
-     * @return bool
1255
-     * @throws EE_Error
1256
-     */
1257
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1258
-    {
1259
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1260
-
1261
-        //first check registration status
1262
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1263
-            return false;
1264
-        }
1265
-        //is there a datetime ticket that matches this dtt_ID?
1266
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1267
-            array(
1268
-                'TKT_ID' => $this->get('TKT_ID'),
1269
-                'DTT_ID' => $DTT_ID,
1270
-            ),
1271
-        )))
1272
-        ) {
1273
-            return false;
1274
-        }
1275
-
1276
-        //final check is against TKT_uses
1277
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1283
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1284
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1285
-     * then return false.  Otherwise return true.
1286
-     *
1287
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1288
-     * @return bool true means can checkin.  false means cannot checkin.
1289
-     * @throws EE_Error
1290
-     */
1291
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1292
-    {
1293
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1294
-
1295
-        if (! $DTT_ID) {
1296
-            return false;
1297
-        }
1298
-
1299
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1300
-
1301
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1302
-        // check-in or not.
1303
-        if (! $max_uses || $max_uses === EE_INF) {
1304
-            return true;
1305
-        }
1306
-
1307
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1308
-        //go ahead and toggle.
1309
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1310
-            return true;
1311
-        }
1312
-
1313
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1314
-        //disallows further check-ins.
1315
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1316
-            array(
1317
-                'REG_ID' => $this->ID(),
1318
-                'CHK_in' => true,
1319
-            ),
1320
-        ), 'DTT_ID', true);
1321
-        // checkins have already reached their max number of uses
1322
-        // so registrant can NOT checkin
1323
-        if ($count_unique_dtt_checkins >= $max_uses) {
1324
-            EE_Error::add_error(
1325
-                esc_html__(
1326
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1327
-                    'event_espresso'
1328
-                ),
1329
-                __FILE__,
1330
-                __FUNCTION__,
1331
-                __LINE__
1332
-            );
1333
-            return false;
1334
-        }
1335
-        return true;
1336
-    }
1337
-
1338
-
1339
-    /**
1340
-     * toggle Check-in status for this registration
1341
-     * Check-ins are toggled in the following order:
1342
-     * never checked in -> checked in
1343
-     * checked in -> checked out
1344
-     * checked out -> checked in
1345
-     *
1346
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1347
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1348
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1349
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1350
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1351
-     * @throws EE_Error
1352
-     */
1353
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1354
-    {
1355
-        if (empty($DTT_ID)) {
1356
-            $datetime = $this->get_latest_related_datetime();
1357
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1358
-            // verify the registration can checkin for the given DTT_ID
1359
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1360
-            EE_Error::add_error(
1361
-                sprintf(
1362
-                    esc_html__(
1363
-                        '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',
1364
-                        'event_espresso'
1365
-                    ),
1366
-                    $this->ID(),
1367
-                    $DTT_ID
1368
-                ),
1369
-                __FILE__,
1370
-                __FUNCTION__,
1371
-                __LINE__
1372
-            );
1373
-            return false;
1374
-        }
1375
-        $status_paths = array(
1376
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1377
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1378
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1379
-        );
1380
-        //start by getting the current status so we know what status we'll be changing to.
1381
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1382
-        $status_to  = $status_paths[$cur_status];
1383
-        // database only records true for checked IN or false for checked OUT
1384
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1385
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1386
-        // add relation - note Check-ins are always creating new rows
1387
-        // because we are keeping track of Check-ins over time.
1388
-        // Eventually we'll probably want to show a list table
1389
-        // for the individual Check-ins so that they can be managed.
1390
-        $checkin = EE_Checkin::new_instance(array(
1391
-            'REG_ID' => $this->ID(),
1392
-            'DTT_ID' => $DTT_ID,
1393
-            'CHK_in' => $new_status,
1394
-        ));
1395
-        // if the record could not be saved then return false
1396
-        if ($checkin->save() === 0) {
1397
-            if (WP_DEBUG) {
1398
-                global $wpdb;
1399
-                $error = sprintf(
1400
-                    esc_html__(
1401
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1402
-                        'event_espresso'
1403
-                    ),
1404
-                    '<br />',
1405
-                    $wpdb->last_error
1406
-                );
1407
-            } else {
1408
-                $error = esc_html__(
1409
-                    'Registration check in update failed because of an unknown database error',
1410
-                    'event_espresso'
1411
-                );
1412
-            }
1413
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1414
-            return false;
1415
-        }
1416
-        return $status_to;
1417
-    }
1418
-
1419
-
1420
-    /**
1421
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1422
-     * "Latest" is defined by the `DTT_EVT_start` column.
1423
-     *
1424
-     * @return EE_Datetime|null
1425
-     * @throws \EE_Error
1426
-     */
1427
-    public function get_latest_related_datetime()
1428
-    {
1429
-        return EEM_Datetime::instance()->get_one(
1430
-            array(
1431
-                array(
1432
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1433
-                ),
1434
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1435
-            )
1436
-        );
1437
-    }
1438
-
1439
-
1440
-    /**
1441
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1442
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1443
-     *
1444
-     * @throws \EE_Error
1445
-     */
1446
-    public function get_earliest_related_datetime()
1447
-    {
1448
-        return EEM_Datetime::instance()->get_one(
1449
-            array(
1450
-                array(
1451
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1452
-                ),
1453
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1454
-            )
1455
-        );
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * This method simply returns the check-in status for this registration and the given datetime.
1461
-     * If neither the datetime nor the checkin values are provided as arguments,
1462
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1463
-     *
1464
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1465
-     *                            (if empty we'll get the primary datetime for
1466
-     *                            this registration (via event) and use it's ID);
1467
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1468
-     * @return int                Integer representing Check-in status.
1469
-     * @throws \EE_Error
1470
-     */
1471
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1472
-    {
1473
-        $checkin_query_params = array(
1474
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1475
-        );
1476
-
1477
-        if ($DTT_ID > 0) {
1478
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1479
-        }
1480
-
1481
-        //get checkin object (if exists)
1482
-        $checkin = $checkin instanceof EE_Checkin
1483
-            ? $checkin
1484
-            : $this->get_first_related('Checkin', $checkin_query_params);
1485
-        if ($checkin instanceof EE_Checkin) {
1486
-            if ($checkin->get('CHK_in')) {
1487
-                return EE_Checkin::status_checked_in; //checked in
1488
-            }
1489
-            return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1490
-        }
1491
-        return EE_Checkin::status_checked_never; //never been checked in
1492
-    }
1493
-
1494
-
1495
-    /**
1496
-     * This method returns a localized message for the toggled Check-in message.
1497
-     *
1498
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1499
-     *                     then it is assumed Check-in for primary datetime was toggled.
1500
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1501
-     *                     message can be customized with the attendee name.
1502
-     * @return string internationalized message
1503
-     * @throws EE_Error
1504
-     */
1505
-    public function get_checkin_msg($DTT_ID, $error = false)
1506
-    {
1507
-        //let's get the attendee first so we can include the name of the attendee
1508
-        $attendee = $this->get_first_related('Attendee');
1509
-        if ($attendee instanceof EE_Attendee) {
1510
-            if ($error) {
1511
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1512
-            }
1513
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1514
-            //what is the status message going to be?
1515
-            switch ($cur_status) {
1516
-                case EE_Checkin::status_checked_never:
1517
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1518
-                        $attendee->full_name());
1519
-                    break;
1520
-                case EE_Checkin::status_checked_in:
1521
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1522
-                    break;
1523
-                case EE_Checkin::status_checked_out:
1524
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1525
-                    break;
1526
-            }
1527
-        }
1528
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     * Returns the related EE_Transaction to this registration
1534
-     *
1535
-     * @return EE_Transaction
1536
-     * @throws EE_Error
1537
-     * @throws EntityNotFoundException
1538
-     */
1539
-    public function transaction()
1540
-    {
1541
-        $transaction = $this->get_first_related('Transaction');
1542
-        if (! $transaction instanceof \EE_Transaction) {
1543
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1544
-        }
1545
-        return $transaction;
1546
-    }
1547
-
1548
-
1549
-    /**
1550
-     *        get Registration Code
1551
-     */
1552
-    public function reg_code()
1553
-    {
1554
-        return $this->get('REG_code');
1555
-    }
1556
-
1557
-
1558
-    /**
1559
-     *        get Transaction ID
1560
-     */
1561
-    public function transaction_ID()
1562
-    {
1563
-        return $this->get('TXN_ID');
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * @return int
1569
-     * @throws EE_Error
1570
-     */
1571
-    public function ticket_ID()
1572
-    {
1573
-        return $this->get('TKT_ID');
1574
-    }
1575
-
1576
-
1577
-    /**
1578
-     *        Set Registration Code
1579
-     *
1580
-     * @access    public
1581
-     * @param    string  $REG_code Registration Code
1582
-     * @param    boolean $use_default
1583
-     * @throws EE_Error
1584
-     */
1585
-    public function set_reg_code($REG_code, $use_default = false)
1586
-    {
1587
-        if (empty($REG_code)) {
1588
-            EE_Error::add_error(
1589
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1590
-                __FILE__,
1591
-                __FUNCTION__,
1592
-                __LINE__
1593
-            );
1594
-            return;
1595
-        }
1596
-        if (! $this->reg_code()) {
1597
-            parent::set('REG_code', $REG_code, $use_default);
1598
-        } else {
1599
-            EE_Error::doing_it_wrong(
1600
-                __CLASS__ . '::' . __FUNCTION__,
1601
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1602
-                '4.6.0'
1603
-            );
1604
-        }
1605
-    }
1606
-
1607
-
1608
-    /**
1609
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1610
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1611
-     *    $registration->transaction()->registrations();
1612
-     *
1613
-     * @since 4.5.0
1614
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1615
-     * @throws EE_Error
1616
-     */
1617
-    public function get_all_other_registrations_in_group()
1618
-    {
1619
-        if ($this->group_size() < 2) {
1620
-            return array();
1621
-        }
1622
-
1623
-        $query[0] = array(
1624
-            'TXN_ID' => $this->transaction_ID(),
1625
-            'REG_ID' => array('!=', $this->ID()),
1626
-            'TKT_ID' => $this->ticket_ID(),
1627
-        );
1628
-        /** @var EE_Registration[] $registrations */
1629
-        $registrations = $this->get_model()->get_all($query);
1630
-        return $registrations;
1631
-    }
1632
-
1633
-    /**
1634
-     * Return the link to the admin details for the object.
1635
-     *
1636
-     * @return string
1637
-     * @throws EE_Error
1638
-     */
1639
-    public function get_admin_details_link()
1640
-    {
1641
-        EE_Registry::instance()->load_helper('URL');
1642
-        return EEH_URL::add_query_args_and_nonce(
1643
-            array(
1644
-                'page'    => 'espresso_registrations',
1645
-                'action'  => 'view_registration',
1646
-                '_REG_ID' => $this->ID(),
1647
-            ),
1648
-            admin_url('admin.php')
1649
-        );
1650
-    }
1651
-
1652
-    /**
1653
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1654
-     *
1655
-     * @return string
1656
-     * @throws EE_Error
1657
-     */
1658
-    public function get_admin_edit_link()
1659
-    {
1660
-        return $this->get_admin_details_link();
1661
-    }
1662
-
1663
-    /**
1664
-     * Returns the link to a settings page for the object.
1665
-     *
1666
-     * @return string
1667
-     * @throws EE_Error
1668
-     */
1669
-    public function get_admin_settings_link()
1670
-    {
1671
-        return $this->get_admin_details_link();
1672
-    }
1673
-
1674
-    /**
1675
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1676
-     *
1677
-     * @return string
1678
-     */
1679
-    public function get_admin_overview_link()
1680
-    {
1681
-        EE_Registry::instance()->load_helper('URL');
1682
-        return EEH_URL::add_query_args_and_nonce(
1683
-            array(
1684
-                'page' => 'espresso_registrations',
1685
-            ),
1686
-            admin_url('admin.php')
1687
-        );
1688
-    }
1689
-
1690
-
1691
-    /**
1692
-     * @param array $query_params
1693
-     * @return \EE_Registration[]
1694
-     * @throws \EE_Error
1695
-     */
1696
-    public function payments($query_params = array())
1697
-    {
1698
-        return $this->get_many_related('Payment', $query_params);
1699
-    }
1700
-
1701
-
1702
-    /**
1703
-     * @param array $query_params
1704
-     * @return \EE_Registration_Payment[]
1705
-     * @throws \EE_Error
1706
-     */
1707
-    public function registration_payments($query_params = array())
1708
-    {
1709
-        return $this->get_many_related('Registration_Payment', $query_params);
1710
-    }
1711
-
1712
-
1713
-    /**
1714
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1715
-     * Note: if there are no payments on the registration there will be no payment method returned.
1716
-     *
1717
-     * @return EE_Payment_Method|null
1718
-     */
1719
-    public function payment_method()
1720
-    {
1721
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1722
-    }
1723
-
1724
-
1725
-    /**
1726
-     * @return \EE_Line_Item
1727
-     * @throws EntityNotFoundException
1728
-     * @throws \EE_Error
1729
-     */
1730
-    public function ticket_line_item()
1731
-    {
1732
-        $ticket            = $this->ticket();
1733
-        $transaction       = $this->transaction();
1734
-        $line_item         = null;
1735
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1736
-            $transaction->total_line_item(),
1737
-            'Ticket',
1738
-            array($ticket->ID())
1739
-        );
1740
-        foreach ($ticket_line_items as $ticket_line_item) {
1741
-            if (
1742
-                $ticket_line_item instanceof \EE_Line_Item
1743
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1744
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1745
-            ) {
1746
-                $line_item = $ticket_line_item;
1747
-                break;
1748
-            }
1749
-        }
1750
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1751
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1752
-        }
1753
-        return $line_item;
1754
-    }
1755
-
1756
-
1757
-    /**
1758
-     * Soft Deletes this model object.
1759
-     *
1760
-     * @return boolean | int
1761
-     * @throws \RuntimeException
1762
-     * @throws \EE_Error
1763
-     */
1764
-    public function delete()
1765
-    {
1766
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1767
-            $this->set_status(EEM_Registration::status_id_cancelled);
1768
-        }
1769
-        return parent::delete();
1770
-    }
1771
-
1772
-
1773
-    /**
1774
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1775
-     *
1776
-     * @throws \EE_Error
1777
-     * @throws \RuntimeException
1778
-     */
1779
-    public function restore()
1780
-    {
1781
-        $previous_status = $this->get_extra_meta(
1782
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1783
-            true,
1784
-            EEM_Registration::status_id_cancelled
1785
-        );
1786
-        if ($previous_status) {
1787
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1788
-            $this->set_status($previous_status);
1789
-        }
1790
-        return parent::restore();
1791
-    }
1792
-
1793
-
1794
-
1795
-    /*************************** DEPRECATED ***************************/
1796
-
1797
-
1798
-    /**
1799
-     * @deprecated
1800
-     * @since     4.7.0
1801
-     * @access    public
1802
-     */
1803
-    public function price_paid()
1804
-    {
1805
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1806
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1807
-            '4.7.0');
1808
-        return $this->final_price();
1809
-    }
1810
-
1811
-
1812
-    /**
1813
-     * @deprecated
1814
-     * @since     4.7.0
1815
-     * @access    public
1816
-     * @param    float $REG_final_price
1817
-     * @throws EE_Error
1818
-     * @throws RuntimeException
1819
-     */
1820
-    public function set_price_paid($REG_final_price = 0.00)
1821
-    {
1822
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1823
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1824
-            '4.7.0');
1825
-        $this->set_final_price($REG_final_price);
1826
-    }
1827
-
1828
-
1829
-    /**
1830
-     * @deprecated
1831
-     * @since 4.7.0
1832
-     * @return string
1833
-     * @throws EE_Error
1834
-     */
1835
-    public function pretty_price_paid()
1836
-    {
1837
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1838
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1839
-                'event_espresso'), '4.7.0');
1840
-        return $this->pretty_final_price();
1841
-    }
1842
-
1843
-
1844
-    /**
1845
-     * Gets the primary datetime related to this registration via the related Event to this registration
1846
-     *
1847
-     * @deprecated 4.9.17
1848
-     * @return EE_Datetime
1849
-     * @throws EE_Error
1850
-     * @throws EntityNotFoundException
1851
-     */
1852
-    public function get_related_primary_datetime()
1853
-    {
1854
-        EE_Error::doing_it_wrong(
1855
-            __METHOD__,
1856
-            esc_html__(
1857
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1858
-                'event_espresso'
1859
-            ),
1860
-            '4.9.17',
1861
-            '5.0.0'
1862
-        );
1863
-        return $this->event()->primary_datetime();
1864
-    }
21
+	/**
22
+	 * Used to reference when a registration has never been checked in.
23
+	 *
24
+	 * @deprecated use \EE_Checkin::status_checked_never instead
25
+	 * @type int
26
+	 */
27
+	const checkin_status_never = 2;
28
+
29
+	/**
30
+	 * Used to reference when a registration has been checked in.
31
+	 *
32
+	 * @deprecated use \EE_Checkin::status_checked_in instead
33
+	 * @type int
34
+	 */
35
+	const checkin_status_in = 1;
36
+
37
+
38
+	/**
39
+	 * Used to reference when a registration has been checked out.
40
+	 *
41
+	 * @deprecated use \EE_Checkin::status_checked_out instead
42
+	 * @type int
43
+	 */
44
+	const checkin_status_out = 0;
45
+
46
+
47
+	/**
48
+	 * extra meta key for tracking reg status os trashed registrations
49
+	 *
50
+	 * @type string
51
+	 */
52
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
+
54
+
55
+	/**
56
+	 * extra meta key for tracking if registration has reserved ticket
57
+	 *
58
+	 * @type string
59
+	 */
60
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
+
62
+
63
+	/**
64
+	 * @param array  $props_n_values          incoming values
65
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
+	 *                                        used.)
67
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
+	 *                                        date_format and the second value is the time format
69
+	 * @return EE_Registration
70
+	 * @throws EE_Error
71
+	 */
72
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
+	{
74
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Registration
84
+	 */
85
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
+	{
87
+		return new self($props_n_values, true, $timezone);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Event ID
93
+	 *
94
+	 * @param        int $EVT_ID Event ID
95
+	 * @throws EE_Error
96
+	 * @throws RuntimeException
97
+	 */
98
+	public function set_event($EVT_ID = 0)
99
+	{
100
+		$this->set('EVT_ID', $EVT_ID);
101
+	}
102
+
103
+
104
+	/**
105
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
+	 * be routed to internal methods
107
+	 *
108
+	 * @param string $field_name
109
+	 * @param mixed  $field_value
110
+	 * @param bool   $use_default
111
+	 * @throws \EE_Error
112
+	 * @throws \RuntimeException
113
+	 */
114
+	public function set($field_name, $field_value, $use_default = false)
115
+	{
116
+		switch ($field_name) {
117
+			case 'REG_code':
118
+				if (! empty($field_value) && $this->reg_code() === null) {
119
+					$this->set_reg_code($field_value, $use_default);
120
+				}
121
+				break;
122
+			case 'STS_ID':
123
+				$this->set_status($field_value, $use_default);
124
+				break;
125
+			default:
126
+				parent::set($field_name, $field_value, $use_default);
127
+		}
128
+	}
129
+
130
+
131
+	/**
132
+	 * Set Status ID
133
+	 * updates the registration status and ALSO...
134
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
135
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
136
+	 *
137
+	 * @param string       $new_STS_ID
138
+	 * @param boolean      $use_default
139
+	 * @param Context|null $context
140
+	 * @return bool
141
+	 * @throws EE_Error
142
+	 * @throws EntityNotFoundException
143
+	 * @throws InvalidArgumentException
144
+	 * @throws ReflectionException
145
+	 * @throws RuntimeException
146
+	 * @throws InvalidDataTypeException
147
+	 * @throws InvalidInterfaceException
148
+	 */
149
+	public function set_status($new_STS_ID = null, $use_default = false, Context $context = null)
150
+	{
151
+		// get current REG_Status
152
+		$old_STS_ID = $this->status_ID();
153
+		// if status has changed
154
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
155
+			&& ! empty($old_STS_ID) // and that old status is actually set
156
+			&& ! empty($new_STS_ID) // as well as the new status
157
+			&& $this->ID() // ensure registration is in the db
158
+		) {
159
+			// TO approved
160
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
161
+				// reserve a space by incrementing ticket and datetime sold values
162
+				$this->_reserve_registration_space();
163
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
164
+				// OR FROM  approved
165
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
166
+				// release a space by decrementing ticket and datetime sold values
167
+				$this->_release_registration_space();
168
+				do_action(
169
+					'AHEE__EE_Registration__set_status__from_approved',
170
+					$this,
171
+					$old_STS_ID,
172
+					$new_STS_ID,
173
+					$context
174
+				);
175
+			}
176
+			// update status
177
+			parent::set('STS_ID', $new_STS_ID, $use_default);
178
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
179
+			/** @type EE_Transaction_Payments $transaction_payments */
180
+			$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
181
+			$transaction_payments->recalculate_transaction_total($this->transaction(), false);
182
+			$this->transaction()->update_status_based_on_total_paid(true);
183
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
184
+			return true;
185
+		}
186
+		//even though the old value matches the new value, it's still good to
187
+		//allow the parent set method to have a say
188
+		parent::set('STS_ID', $new_STS_ID, $use_default);
189
+		return true;
190
+	}
191
+
192
+
193
+	/**
194
+	 * update REGs and TXN when cancelled or declined registrations involved
195
+	 *
196
+	 * @param string       $new_STS_ID
197
+	 * @param string       $old_STS_ID
198
+	 * @param Context|null $context
199
+	 * @throws EE_Error
200
+	 * @throws InvalidArgumentException
201
+	 * @throws InvalidDataTypeException
202
+	 * @throws InvalidInterfaceException
203
+	 * @throws ReflectionException
204
+	 */
205
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null)
206
+	{
207
+		// these reg statuses should not be considered in any calculations involving monies owing
208
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
209
+		// true if registration has been cancelled or declined
210
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
211
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
212
+		) {
213
+			/** @type EE_Registration_Processor $registration_processor */
214
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
215
+			/** @type EE_Transaction_Processor $transaction_processor */
216
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
217
+			// cancelled or declined registration
218
+			$registration_processor->update_registration_after_being_canceled_or_declined(
219
+				$this,
220
+				$closed_reg_statuses
221
+			);
222
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
223
+				$this,
224
+				$closed_reg_statuses,
225
+				false
226
+			);
227
+			do_action(
228
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
229
+				$this,
230
+				$old_STS_ID,
231
+				$new_STS_ID,
232
+				$context
233
+			);
234
+			return;
235
+		}
236
+		// true if reinstating cancelled or declined registration
237
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
238
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
239
+		) {
240
+			/** @type EE_Registration_Processor $registration_processor */
241
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
242
+			/** @type EE_Transaction_Processor $transaction_processor */
243
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
244
+			// reinstating cancelled or declined registration
245
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
246
+				$this,
247
+				$closed_reg_statuses
248
+			);
249
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
250
+				$this,
251
+				$closed_reg_statuses,
252
+				false
253
+			);
254
+			do_action(
255
+				'AHEE__EE_Registration__set_status__after_reinstated',
256
+				$this,
257
+				$old_STS_ID,
258
+				$new_STS_ID,
259
+				$context
260
+			);
261
+		}
262
+	}
263
+
264
+
265
+	/**
266
+	 *        get Status ID
267
+	 */
268
+	public function status_ID()
269
+	{
270
+		return $this->get('STS_ID');
271
+	}
272
+
273
+
274
+	/**
275
+	 * increments this registration's related ticket sold and corresponding datetime sold values
276
+	 *
277
+	 * @return void
278
+	 * @throws EE_Error
279
+	 * @throws EntityNotFoundException
280
+	 */
281
+	private function _reserve_registration_space()
282
+	{
283
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
284
+		// so stop tracking that this reg has a ticket reserved
285
+		$this->release_reserved_ticket();
286
+		$ticket = $this->ticket();
287
+		$ticket->increase_sold();
288
+		$ticket->save();
289
+		// possibly set event status to sold out
290
+		$this->event()->perform_sold_out_status_check();
291
+	}
292
+
293
+
294
+	/**
295
+	 * Gets the ticket this registration is for
296
+	 *
297
+	 * @param boolean $include_archived whether to include archived tickets or not.
298
+	 * @return EE_Ticket|EE_Base_Class
299
+	 * @throws \EE_Error
300
+	 */
301
+	public function ticket($include_archived = true)
302
+	{
303
+		$query_params = array();
304
+		if ($include_archived) {
305
+			$query_params['default_where_conditions'] = 'none';
306
+		}
307
+		return $this->get_first_related('Ticket', $query_params);
308
+	}
309
+
310
+
311
+	/**
312
+	 * Gets the event this registration is for
313
+	 *
314
+	 * @return EE_Event
315
+	 * @throws EE_Error
316
+	 * @throws EntityNotFoundException
317
+	 */
318
+	public function event()
319
+	{
320
+		$event = $this->get_first_related('Event');
321
+		if (! $event instanceof \EE_Event) {
322
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
323
+		}
324
+		return $event;
325
+	}
326
+
327
+
328
+	/**
329
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
330
+	 * with the author of the event this registration is for.
331
+	 *
332
+	 * @since 4.5.0
333
+	 * @return int
334
+	 * @throws EE_Error
335
+	 * @throws EntityNotFoundException
336
+	 */
337
+	public function wp_user()
338
+	{
339
+		$event = $this->event();
340
+		if ($event instanceof EE_Event) {
341
+			return $event->wp_user();
342
+		}
343
+		return 0;
344
+	}
345
+
346
+
347
+	/**
348
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
349
+	 *
350
+	 * @return void
351
+	 * @throws \EE_Error
352
+	 */
353
+	private function _release_registration_space()
354
+	{
355
+		$ticket = $this->ticket();
356
+		$ticket->decrease_sold();
357
+		$ticket->save();
358
+	}
359
+
360
+
361
+	/**
362
+	 * tracks this registration's ticket reservation in extra meta
363
+	 * and can increment related ticket reserved and corresponding datetime reserved values
364
+	 *
365
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
366
+	 * @return void
367
+	 * @throws \EE_Error
368
+	 */
369
+	public function reserve_ticket($update_ticket = false)
370
+	{
371
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
372
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
373
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
374
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
375
+				$ticket = $this->ticket();
376
+				$ticket->increase_reserved();
377
+				$ticket->save();
378
+			}
379
+		}
380
+	}
381
+
382
+
383
+	/**
384
+	 * stops tracking this registration's ticket reservation in extra meta
385
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
386
+	 *
387
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
388
+	 * @return void
389
+	 * @throws \EE_Error
390
+	 */
391
+	public function release_reserved_ticket($update_ticket = false)
392
+	{
393
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
394
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
395
+			// we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
396
+			if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
397
+				$ticket = $this->ticket();
398
+				$ticket->decrease_reserved();
399
+				$ticket->save();
400
+			}
401
+		}
402
+	}
403
+
404
+
405
+	/**
406
+	 * Set Attendee ID
407
+	 *
408
+	 * @param        int $ATT_ID Attendee ID
409
+	 * @throws EE_Error
410
+	 * @throws RuntimeException
411
+	 */
412
+	public function set_attendee_id($ATT_ID = 0)
413
+	{
414
+		$this->set('ATT_ID', $ATT_ID);
415
+	}
416
+
417
+
418
+	/**
419
+	 *        Set Transaction ID
420
+	 *
421
+	 * @param        int $TXN_ID Transaction ID
422
+	 * @throws EE_Error
423
+	 * @throws RuntimeException
424
+	 */
425
+	public function set_transaction_id($TXN_ID = 0)
426
+	{
427
+		$this->set('TXN_ID', $TXN_ID);
428
+	}
429
+
430
+
431
+	/**
432
+	 *        Set Session
433
+	 *
434
+	 * @param    string $REG_session PHP Session ID
435
+	 * @throws EE_Error
436
+	 * @throws RuntimeException
437
+	 */
438
+	public function set_session($REG_session = '')
439
+	{
440
+		$this->set('REG_session', $REG_session);
441
+	}
442
+
443
+
444
+	/**
445
+	 *        Set Registration URL Link
446
+	 *
447
+	 * @param    string $REG_url_link Registration URL Link
448
+	 * @throws EE_Error
449
+	 * @throws RuntimeException
450
+	 */
451
+	public function set_reg_url_link($REG_url_link = '')
452
+	{
453
+		$this->set('REG_url_link', $REG_url_link);
454
+	}
455
+
456
+
457
+	/**
458
+	 *        Set Attendee Counter
459
+	 *
460
+	 * @param        int $REG_count Primary Attendee
461
+	 * @throws EE_Error
462
+	 * @throws RuntimeException
463
+	 */
464
+	public function set_count($REG_count = 1)
465
+	{
466
+		$this->set('REG_count', $REG_count);
467
+	}
468
+
469
+
470
+	/**
471
+	 *        Set Group Size
472
+	 *
473
+	 * @param        boolean $REG_group_size Group Registration
474
+	 * @throws EE_Error
475
+	 * @throws RuntimeException
476
+	 */
477
+	public function set_group_size($REG_group_size = false)
478
+	{
479
+		$this->set('REG_group_size', $REG_group_size);
480
+	}
481
+
482
+
483
+	/**
484
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
485
+	 *    EEM_Registration::status_id_not_approved
486
+	 *
487
+	 * @return        boolean
488
+	 */
489
+	public function is_not_approved()
490
+	{
491
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
492
+	}
493
+
494
+
495
+	/**
496
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
497
+	 *    EEM_Registration::status_id_pending_payment
498
+	 *
499
+	 * @return        boolean
500
+	 */
501
+	public function is_pending_payment()
502
+	{
503
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
504
+	}
505
+
506
+
507
+	/**
508
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
509
+	 *
510
+	 * @return        boolean
511
+	 */
512
+	public function is_approved()
513
+	{
514
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
515
+	}
516
+
517
+
518
+	/**
519
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
520
+	 *
521
+	 * @return        boolean
522
+	 */
523
+	public function is_cancelled()
524
+	{
525
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
526
+	}
527
+
528
+
529
+	/**
530
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
531
+	 *
532
+	 * @return        boolean
533
+	 */
534
+	public function is_declined()
535
+	{
536
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
537
+	}
538
+
539
+
540
+	/**
541
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
542
+	 *    EEM_Registration::status_id_incomplete
543
+	 *
544
+	 * @return        boolean
545
+	 */
546
+	public function is_incomplete()
547
+	{
548
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
549
+	}
550
+
551
+
552
+	/**
553
+	 *        Set Registration Date
554
+	 *
555
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
556
+	 *                                                 Date
557
+	 * @throws EE_Error
558
+	 * @throws RuntimeException
559
+	 */
560
+	public function set_reg_date($REG_date = false)
561
+	{
562
+		$this->set('REG_date', $REG_date);
563
+	}
564
+
565
+
566
+	/**
567
+	 *    Set final price owing for this registration after all ticket/price modifications
568
+	 *
569
+	 * @access    public
570
+	 * @param    float $REG_final_price
571
+	 * @throws EE_Error
572
+	 * @throws RuntimeException
573
+	 */
574
+	public function set_final_price($REG_final_price = 0.00)
575
+	{
576
+		$this->set('REG_final_price', $REG_final_price);
577
+	}
578
+
579
+
580
+	/**
581
+	 *    Set amount paid towards this registration's final price
582
+	 *
583
+	 * @access    public
584
+	 * @param    float $REG_paid
585
+	 * @throws EE_Error
586
+	 * @throws RuntimeException
587
+	 */
588
+	public function set_paid($REG_paid = 0.00)
589
+	{
590
+		$this->set('REG_paid', $REG_paid);
591
+	}
592
+
593
+
594
+	/**
595
+	 *        Attendee Is Going
596
+	 *
597
+	 * @param        boolean $REG_att_is_going Attendee Is Going
598
+	 * @throws EE_Error
599
+	 * @throws RuntimeException
600
+	 */
601
+	public function set_att_is_going($REG_att_is_going = false)
602
+	{
603
+		$this->set('REG_att_is_going', $REG_att_is_going);
604
+	}
605
+
606
+
607
+	/**
608
+	 * Gets the related attendee
609
+	 *
610
+	 * @return EE_Attendee
611
+	 * @throws EE_Error
612
+	 */
613
+	public function attendee()
614
+	{
615
+		return $this->get_first_related('Attendee');
616
+	}
617
+
618
+
619
+	/**
620
+	 *        get Event ID
621
+	 */
622
+	public function event_ID()
623
+	{
624
+		return $this->get('EVT_ID');
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get Event ID
630
+	 */
631
+	public function event_name()
632
+	{
633
+		$event = $this->event_obj();
634
+		if ($event) {
635
+			return $event->name();
636
+		} else {
637
+			return null;
638
+		}
639
+	}
640
+
641
+
642
+	/**
643
+	 * Fetches the event this registration is for
644
+	 *
645
+	 * @return EE_Event
646
+	 * @throws EE_Error
647
+	 */
648
+	public function event_obj()
649
+	{
650
+		return $this->get_first_related('Event');
651
+	}
652
+
653
+
654
+	/**
655
+	 *        get Attendee ID
656
+	 */
657
+	public function attendee_ID()
658
+	{
659
+		return $this->get('ATT_ID');
660
+	}
661
+
662
+
663
+	/**
664
+	 *        get PHP Session ID
665
+	 */
666
+	public function session_ID()
667
+	{
668
+		return $this->get('REG_session');
669
+	}
670
+
671
+
672
+	/**
673
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
674
+	 *
675
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
676
+	 * @return string
677
+	 */
678
+	public function receipt_url($messenger = 'html')
679
+	{
680
+
681
+		/**
682
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
683
+		 * already in use on old system.  If there is then we just return the standard url for it.
684
+		 *
685
+		 * @since 4.5.0
686
+		 */
687
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
688
+		$has_custom             = EEH_Template::locate_template(
689
+			$template_relative_path,
690
+			array(),
691
+			true,
692
+			true,
693
+			true
694
+		);
695
+
696
+		if ($has_custom) {
697
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
698
+		}
699
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
700
+	}
701
+
702
+
703
+	/**
704
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
705
+	 *
706
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
707
+	 * @return string
708
+	 * @throws EE_Error
709
+	 */
710
+	public function invoice_url($messenger = 'html')
711
+	{
712
+		/**
713
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
714
+		 * already in use on old system.  If there is then we just return the standard url for it.
715
+		 *
716
+		 * @since 4.5.0
717
+		 */
718
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
719
+		$has_custom             = EEH_Template::locate_template(
720
+			$template_relative_path,
721
+			array(),
722
+			true,
723
+			true,
724
+			true
725
+		);
726
+
727
+		if ($has_custom) {
728
+			if ($messenger == 'html') {
729
+				return $this->invoice_url('launch');
730
+			}
731
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
732
+
733
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
734
+			if ($messenger == 'html') {
735
+				$query_args['html'] = true;
736
+			}
737
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
738
+		}
739
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
740
+	}
741
+
742
+
743
+	/**
744
+	 * get Registration URL Link
745
+	 *
746
+	 * @access public
747
+	 * @return string
748
+	 * @throws \EE_Error
749
+	 */
750
+	public function reg_url_link()
751
+	{
752
+		return (string) $this->get('REG_url_link');
753
+	}
754
+
755
+
756
+	/**
757
+	 * Echoes out invoice_url()
758
+	 *
759
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
760
+	 * @return void
761
+	 * @throws EE_Error
762
+	 */
763
+	public function e_invoice_url($type = 'launch')
764
+	{
765
+		echo $this->invoice_url($type);
766
+	}
767
+
768
+
769
+	/**
770
+	 * Echoes out payment_overview_url
771
+	 */
772
+	public function e_payment_overview_url()
773
+	{
774
+		echo $this->payment_overview_url();
775
+	}
776
+
777
+
778
+	/**
779
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
780
+	 * a query parameter
781
+	 *
782
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
783
+	 *                            payment overview url.
784
+	 * @return string
785
+	 * @throws EE_Error
786
+	 */
787
+	public function payment_overview_url($clear_session = false)
788
+	{
789
+		return add_query_arg(array(
790
+			'e_reg_url_link' => $this->reg_url_link(),
791
+			'step'           => 'payment_options',
792
+			'revisit'        => true,
793
+			'clear_session' => (bool) $clear_session
794
+		), EE_Registry::instance()->CFG->core->reg_page_url());
795
+	}
796
+
797
+
798
+	/**
799
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
800
+	 * a query parameter
801
+	 *
802
+	 * @return string
803
+	 * @throws EE_Error
804
+	 */
805
+	public function edit_attendee_information_url()
806
+	{
807
+		return add_query_arg(array(
808
+			'e_reg_url_link' => $this->reg_url_link(),
809
+			'step'           => 'attendee_information',
810
+			'revisit'        => true,
811
+		), EE_Registry::instance()->CFG->core->reg_page_url());
812
+	}
813
+
814
+
815
+	/**
816
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
817
+	 *
818
+	 * @return string
819
+	 * @throws EE_Error
820
+	 */
821
+	public function get_admin_edit_url()
822
+	{
823
+		return EEH_URL::add_query_args_and_nonce(array(
824
+			'page'    => 'espresso_registrations',
825
+			'action'  => 'view_registration',
826
+			'_REG_ID' => $this->ID(),
827
+		), admin_url('admin.php'));
828
+	}
829
+
830
+
831
+	/**
832
+	 *    is_primary_registrant?
833
+	 */
834
+	public function is_primary_registrant()
835
+	{
836
+		return $this->get('REG_count') == 1 ? true : false;
837
+	}
838
+
839
+
840
+	/**
841
+	 * This returns the primary registration object for this registration group (which may be this object).
842
+	 *
843
+	 * @return EE_Registration
844
+	 * @throws EE_Error
845
+	 */
846
+	public function get_primary_registration()
847
+	{
848
+		if ($this->is_primary_registrant()) {
849
+			return $this;
850
+		}
851
+
852
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
853
+		/** @var EE_Registration $primary_registrant */
854
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
855
+			array(
856
+				'TXN_ID'    => $this->transaction_ID(),
857
+				'REG_count' => 1,
858
+			),
859
+		));
860
+		return $primary_registrant;
861
+	}
862
+
863
+
864
+	/**
865
+	 *        get  Attendee Number
866
+	 *
867
+	 * @access        public
868
+	 */
869
+	public function count()
870
+	{
871
+		return $this->get('REG_count');
872
+	}
873
+
874
+
875
+	/**
876
+	 *        get Group Size
877
+	 */
878
+	public function group_size()
879
+	{
880
+		return $this->get('REG_group_size');
881
+	}
882
+
883
+
884
+	/**
885
+	 *        get Registration Date
886
+	 */
887
+	public function date()
888
+	{
889
+		return $this->get('REG_date');
890
+	}
891
+
892
+
893
+	/**
894
+	 * gets a pretty date
895
+	 *
896
+	 * @param string $date_format
897
+	 * @param string $time_format
898
+	 * @return string
899
+	 * @throws EE_Error
900
+	 */
901
+	public function pretty_date($date_format = null, $time_format = null)
902
+	{
903
+		return $this->get_datetime('REG_date', $date_format, $time_format);
904
+	}
905
+
906
+
907
+	/**
908
+	 * final_price
909
+	 * the registration's share of the transaction total, so that the
910
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
911
+	 *
912
+	 * @return float
913
+	 * @throws EE_Error
914
+	 */
915
+	public function final_price()
916
+	{
917
+		return $this->get('REG_final_price');
918
+	}
919
+
920
+
921
+	/**
922
+	 * pretty_final_price
923
+	 *  final price as formatted string, with correct decimal places and currency symbol
924
+	 *
925
+	 * @return string
926
+	 * @throws EE_Error
927
+	 */
928
+	public function pretty_final_price()
929
+	{
930
+		return $this->get_pretty('REG_final_price');
931
+	}
932
+
933
+
934
+	/**
935
+	 * get paid (yeah)
936
+	 *
937
+	 * @return float
938
+	 * @throws EE_Error
939
+	 */
940
+	public function paid()
941
+	{
942
+		return $this->get('REG_paid');
943
+	}
944
+
945
+
946
+	/**
947
+	 * pretty_paid
948
+	 *
949
+	 * @return float
950
+	 * @throws EE_Error
951
+	 */
952
+	public function pretty_paid()
953
+	{
954
+		return $this->get_pretty('REG_paid');
955
+	}
956
+
957
+
958
+	/**
959
+	 * owes_monies_and_can_pay
960
+	 * whether or not this registration has monies owing and it's' status allows payment
961
+	 *
962
+	 * @param array $requires_payment
963
+	 * @return bool
964
+	 * @throws EE_Error
965
+	 */
966
+	public function owes_monies_and_can_pay($requires_payment = array())
967
+	{
968
+		// these reg statuses require payment (if event is not free)
969
+		$requires_payment = ! empty($requires_payment)
970
+			? $requires_payment
971
+			: EEM_Registration::reg_statuses_that_allow_payment();
972
+		if (in_array($this->status_ID(), $requires_payment) &&
973
+			$this->final_price() != 0 &&
974
+			$this->final_price() != $this->paid()
975
+		) {
976
+			return true;
977
+		} else {
978
+			return false;
979
+		}
980
+	}
981
+
982
+
983
+	/**
984
+	 * Prints out the return value of $this->pretty_status()
985
+	 *
986
+	 * @param bool $show_icons
987
+	 * @return void
988
+	 * @throws EE_Error
989
+	 */
990
+	public function e_pretty_status($show_icons = false)
991
+	{
992
+		echo $this->pretty_status($show_icons);
993
+	}
994
+
995
+
996
+	/**
997
+	 * Returns a nice version of the status for displaying to customers
998
+	 *
999
+	 * @param bool $show_icons
1000
+	 * @return string
1001
+	 * @throws EE_Error
1002
+	 */
1003
+	public function pretty_status($show_icons = false)
1004
+	{
1005
+		$status = EEM_Status::instance()->localized_status(
1006
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1007
+			false,
1008
+			'sentence'
1009
+		);
1010
+		$icon   = '';
1011
+		switch ($this->status_ID()) {
1012
+			case EEM_Registration::status_id_approved:
1013
+				$icon = $show_icons
1014
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1015
+					: '';
1016
+				break;
1017
+			case EEM_Registration::status_id_pending_payment:
1018
+				$icon = $show_icons
1019
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1020
+					: '';
1021
+				break;
1022
+			case EEM_Registration::status_id_not_approved:
1023
+				$icon = $show_icons
1024
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1025
+					: '';
1026
+				break;
1027
+			case EEM_Registration::status_id_cancelled:
1028
+				$icon = $show_icons
1029
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1030
+					: '';
1031
+				break;
1032
+			case EEM_Registration::status_id_incomplete:
1033
+				$icon = $show_icons
1034
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1035
+					: '';
1036
+				break;
1037
+			case EEM_Registration::status_id_declined:
1038
+				$icon = $show_icons
1039
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1040
+					: '';
1041
+				break;
1042
+			case EEM_Registration::status_id_wait_list:
1043
+				$icon = $show_icons
1044
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1045
+					: '';
1046
+				break;
1047
+		}
1048
+		return $icon . $status[$this->status_ID()];
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 *        get Attendee Is Going
1054
+	 */
1055
+	public function att_is_going()
1056
+	{
1057
+		return $this->get('REG_att_is_going');
1058
+	}
1059
+
1060
+
1061
+	/**
1062
+	 * Gets related answers
1063
+	 *
1064
+	 * @param array $query_params like EEM_Base::get_all
1065
+	 * @return EE_Answer[]
1066
+	 * @throws EE_Error
1067
+	 */
1068
+	public function answers($query_params = null)
1069
+	{
1070
+		return $this->get_many_related('Answer', $query_params);
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * Gets the registration's answer value to the specified question
1076
+	 * (either the question's ID or a question object)
1077
+	 *
1078
+	 * @param EE_Question|int $question
1079
+	 * @param bool            $pretty_value
1080
+	 * @return array|string if pretty_value= true, the result will always be a string
1081
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1082
+	 * will convert it into some kind of string)
1083
+	 * @throws EE_Error
1084
+	 */
1085
+	public function answer_value_to_question($question, $pretty_value = true)
1086
+	{
1087
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1088
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * question_groups
1094
+	 * returns an array of EE_Question_Group objects for this registration
1095
+	 *
1096
+	 * @return EE_Question_Group[]
1097
+	 * @throws EE_Error
1098
+	 * @throws EntityNotFoundException
1099
+	 */
1100
+	public function question_groups()
1101
+	{
1102
+		$question_groups = array();
1103
+		if ($this->event() instanceof EE_Event) {
1104
+			$question_groups = $this->event()->question_groups(
1105
+				array(
1106
+					array(
1107
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1108
+					),
1109
+					'order_by' => array('QSG_order' => 'ASC'),
1110
+				)
1111
+			);
1112
+		}
1113
+		return $question_groups;
1114
+	}
1115
+
1116
+
1117
+	/**
1118
+	 * count_question_groups
1119
+	 * returns a count of the number of EE_Question_Group objects for this registration
1120
+	 *
1121
+	 * @return int
1122
+	 * @throws EE_Error
1123
+	 * @throws EntityNotFoundException
1124
+	 */
1125
+	public function count_question_groups()
1126
+	{
1127
+		$qg_count = 0;
1128
+		if ($this->event() instanceof EE_Event) {
1129
+			$qg_count = $this->event()->count_related(
1130
+				'Question_Group',
1131
+				array(
1132
+					array(
1133
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1134
+					),
1135
+				)
1136
+			);
1137
+		}
1138
+		return $qg_count;
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 * Returns the registration date in the 'standard' string format
1144
+	 * (function may be improved in the future to allow for different formats and timezones)
1145
+	 *
1146
+	 * @return string
1147
+	 * @throws EE_Error
1148
+	 */
1149
+	public function reg_date()
1150
+	{
1151
+		return $this->get_datetime('REG_date');
1152
+	}
1153
+
1154
+
1155
+	/**
1156
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1157
+	 * the ticket this registration purchased, or the datetime they have registered
1158
+	 * to attend)
1159
+	 *
1160
+	 * @return EE_Datetime_Ticket
1161
+	 * @throws EE_Error
1162
+	 */
1163
+	public function datetime_ticket()
1164
+	{
1165
+		return $this->get_first_related('Datetime_Ticket');
1166
+	}
1167
+
1168
+
1169
+	/**
1170
+	 * Sets the registration's datetime_ticket.
1171
+	 *
1172
+	 * @param EE_Datetime_Ticket $datetime_ticket
1173
+	 * @return EE_Datetime_Ticket
1174
+	 * @throws EE_Error
1175
+	 */
1176
+	public function set_datetime_ticket($datetime_ticket)
1177
+	{
1178
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1179
+	}
1180
+
1181
+	/**
1182
+	 * Gets deleted
1183
+	 *
1184
+	 * @return bool
1185
+	 * @throws EE_Error
1186
+	 */
1187
+	public function deleted()
1188
+	{
1189
+		return $this->get('REG_deleted');
1190
+	}
1191
+
1192
+	/**
1193
+	 * Sets deleted
1194
+	 *
1195
+	 * @param boolean $deleted
1196
+	 * @return bool
1197
+	 * @throws EE_Error
1198
+	 * @throws RuntimeException
1199
+	 */
1200
+	public function set_deleted($deleted)
1201
+	{
1202
+		if ($deleted) {
1203
+			$this->delete();
1204
+		} else {
1205
+			$this->restore();
1206
+		}
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * Get the status object of this object
1212
+	 *
1213
+	 * @return EE_Status
1214
+	 * @throws EE_Error
1215
+	 */
1216
+	public function status_obj()
1217
+	{
1218
+		return $this->get_first_related('Status');
1219
+	}
1220
+
1221
+
1222
+	/**
1223
+	 * Returns the number of times this registration has checked into any of the datetimes
1224
+	 * its available for
1225
+	 *
1226
+	 * @return int
1227
+	 * @throws EE_Error
1228
+	 */
1229
+	public function count_checkins()
1230
+	{
1231
+		return $this->get_model()->count_related($this, 'Checkin');
1232
+	}
1233
+
1234
+
1235
+	/**
1236
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1237
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1238
+	 *
1239
+	 * @return int
1240
+	 * @throws EE_Error
1241
+	 */
1242
+	public function count_checkins_not_checkedout()
1243
+	{
1244
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1250
+	 *
1251
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1252
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1253
+	 *                                          consider registration status as well as datetime access.
1254
+	 * @return bool
1255
+	 * @throws EE_Error
1256
+	 */
1257
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1258
+	{
1259
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1260
+
1261
+		//first check registration status
1262
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1263
+			return false;
1264
+		}
1265
+		//is there a datetime ticket that matches this dtt_ID?
1266
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1267
+			array(
1268
+				'TKT_ID' => $this->get('TKT_ID'),
1269
+				'DTT_ID' => $DTT_ID,
1270
+			),
1271
+		)))
1272
+		) {
1273
+			return false;
1274
+		}
1275
+
1276
+		//final check is against TKT_uses
1277
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1283
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1284
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1285
+	 * then return false.  Otherwise return true.
1286
+	 *
1287
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1288
+	 * @return bool true means can checkin.  false means cannot checkin.
1289
+	 * @throws EE_Error
1290
+	 */
1291
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1292
+	{
1293
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1294
+
1295
+		if (! $DTT_ID) {
1296
+			return false;
1297
+		}
1298
+
1299
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1300
+
1301
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1302
+		// check-in or not.
1303
+		if (! $max_uses || $max_uses === EE_INF) {
1304
+			return true;
1305
+		}
1306
+
1307
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1308
+		//go ahead and toggle.
1309
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1310
+			return true;
1311
+		}
1312
+
1313
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1314
+		//disallows further check-ins.
1315
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1316
+			array(
1317
+				'REG_ID' => $this->ID(),
1318
+				'CHK_in' => true,
1319
+			),
1320
+		), 'DTT_ID', true);
1321
+		// checkins have already reached their max number of uses
1322
+		// so registrant can NOT checkin
1323
+		if ($count_unique_dtt_checkins >= $max_uses) {
1324
+			EE_Error::add_error(
1325
+				esc_html__(
1326
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1327
+					'event_espresso'
1328
+				),
1329
+				__FILE__,
1330
+				__FUNCTION__,
1331
+				__LINE__
1332
+			);
1333
+			return false;
1334
+		}
1335
+		return true;
1336
+	}
1337
+
1338
+
1339
+	/**
1340
+	 * toggle Check-in status for this registration
1341
+	 * Check-ins are toggled in the following order:
1342
+	 * never checked in -> checked in
1343
+	 * checked in -> checked out
1344
+	 * checked out -> checked in
1345
+	 *
1346
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1347
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1348
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1349
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1350
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1351
+	 * @throws EE_Error
1352
+	 */
1353
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1354
+	{
1355
+		if (empty($DTT_ID)) {
1356
+			$datetime = $this->get_latest_related_datetime();
1357
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1358
+			// verify the registration can checkin for the given DTT_ID
1359
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1360
+			EE_Error::add_error(
1361
+				sprintf(
1362
+					esc_html__(
1363
+						'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',
1364
+						'event_espresso'
1365
+					),
1366
+					$this->ID(),
1367
+					$DTT_ID
1368
+				),
1369
+				__FILE__,
1370
+				__FUNCTION__,
1371
+				__LINE__
1372
+			);
1373
+			return false;
1374
+		}
1375
+		$status_paths = array(
1376
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1377
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1378
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1379
+		);
1380
+		//start by getting the current status so we know what status we'll be changing to.
1381
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1382
+		$status_to  = $status_paths[$cur_status];
1383
+		// database only records true for checked IN or false for checked OUT
1384
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1385
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1386
+		// add relation - note Check-ins are always creating new rows
1387
+		// because we are keeping track of Check-ins over time.
1388
+		// Eventually we'll probably want to show a list table
1389
+		// for the individual Check-ins so that they can be managed.
1390
+		$checkin = EE_Checkin::new_instance(array(
1391
+			'REG_ID' => $this->ID(),
1392
+			'DTT_ID' => $DTT_ID,
1393
+			'CHK_in' => $new_status,
1394
+		));
1395
+		// if the record could not be saved then return false
1396
+		if ($checkin->save() === 0) {
1397
+			if (WP_DEBUG) {
1398
+				global $wpdb;
1399
+				$error = sprintf(
1400
+					esc_html__(
1401
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1402
+						'event_espresso'
1403
+					),
1404
+					'<br />',
1405
+					$wpdb->last_error
1406
+				);
1407
+			} else {
1408
+				$error = esc_html__(
1409
+					'Registration check in update failed because of an unknown database error',
1410
+					'event_espresso'
1411
+				);
1412
+			}
1413
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1414
+			return false;
1415
+		}
1416
+		return $status_to;
1417
+	}
1418
+
1419
+
1420
+	/**
1421
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1422
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1423
+	 *
1424
+	 * @return EE_Datetime|null
1425
+	 * @throws \EE_Error
1426
+	 */
1427
+	public function get_latest_related_datetime()
1428
+	{
1429
+		return EEM_Datetime::instance()->get_one(
1430
+			array(
1431
+				array(
1432
+					'Ticket.Registration.REG_ID' => $this->ID(),
1433
+				),
1434
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1435
+			)
1436
+		);
1437
+	}
1438
+
1439
+
1440
+	/**
1441
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1442
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1443
+	 *
1444
+	 * @throws \EE_Error
1445
+	 */
1446
+	public function get_earliest_related_datetime()
1447
+	{
1448
+		return EEM_Datetime::instance()->get_one(
1449
+			array(
1450
+				array(
1451
+					'Ticket.Registration.REG_ID' => $this->ID(),
1452
+				),
1453
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1454
+			)
1455
+		);
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * This method simply returns the check-in status for this registration and the given datetime.
1461
+	 * If neither the datetime nor the checkin values are provided as arguments,
1462
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1463
+	 *
1464
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1465
+	 *                            (if empty we'll get the primary datetime for
1466
+	 *                            this registration (via event) and use it's ID);
1467
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1468
+	 * @return int                Integer representing Check-in status.
1469
+	 * @throws \EE_Error
1470
+	 */
1471
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1472
+	{
1473
+		$checkin_query_params = array(
1474
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1475
+		);
1476
+
1477
+		if ($DTT_ID > 0) {
1478
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1479
+		}
1480
+
1481
+		//get checkin object (if exists)
1482
+		$checkin = $checkin instanceof EE_Checkin
1483
+			? $checkin
1484
+			: $this->get_first_related('Checkin', $checkin_query_params);
1485
+		if ($checkin instanceof EE_Checkin) {
1486
+			if ($checkin->get('CHK_in')) {
1487
+				return EE_Checkin::status_checked_in; //checked in
1488
+			}
1489
+			return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1490
+		}
1491
+		return EE_Checkin::status_checked_never; //never been checked in
1492
+	}
1493
+
1494
+
1495
+	/**
1496
+	 * This method returns a localized message for the toggled Check-in message.
1497
+	 *
1498
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1499
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1500
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1501
+	 *                     message can be customized with the attendee name.
1502
+	 * @return string internationalized message
1503
+	 * @throws EE_Error
1504
+	 */
1505
+	public function get_checkin_msg($DTT_ID, $error = false)
1506
+	{
1507
+		//let's get the attendee first so we can include the name of the attendee
1508
+		$attendee = $this->get_first_related('Attendee');
1509
+		if ($attendee instanceof EE_Attendee) {
1510
+			if ($error) {
1511
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1512
+			}
1513
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1514
+			//what is the status message going to be?
1515
+			switch ($cur_status) {
1516
+				case EE_Checkin::status_checked_never:
1517
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1518
+						$attendee->full_name());
1519
+					break;
1520
+				case EE_Checkin::status_checked_in:
1521
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1522
+					break;
1523
+				case EE_Checkin::status_checked_out:
1524
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1525
+					break;
1526
+			}
1527
+		}
1528
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 * Returns the related EE_Transaction to this registration
1534
+	 *
1535
+	 * @return EE_Transaction
1536
+	 * @throws EE_Error
1537
+	 * @throws EntityNotFoundException
1538
+	 */
1539
+	public function transaction()
1540
+	{
1541
+		$transaction = $this->get_first_related('Transaction');
1542
+		if (! $transaction instanceof \EE_Transaction) {
1543
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1544
+		}
1545
+		return $transaction;
1546
+	}
1547
+
1548
+
1549
+	/**
1550
+	 *        get Registration Code
1551
+	 */
1552
+	public function reg_code()
1553
+	{
1554
+		return $this->get('REG_code');
1555
+	}
1556
+
1557
+
1558
+	/**
1559
+	 *        get Transaction ID
1560
+	 */
1561
+	public function transaction_ID()
1562
+	{
1563
+		return $this->get('TXN_ID');
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * @return int
1569
+	 * @throws EE_Error
1570
+	 */
1571
+	public function ticket_ID()
1572
+	{
1573
+		return $this->get('TKT_ID');
1574
+	}
1575
+
1576
+
1577
+	/**
1578
+	 *        Set Registration Code
1579
+	 *
1580
+	 * @access    public
1581
+	 * @param    string  $REG_code Registration Code
1582
+	 * @param    boolean $use_default
1583
+	 * @throws EE_Error
1584
+	 */
1585
+	public function set_reg_code($REG_code, $use_default = false)
1586
+	{
1587
+		if (empty($REG_code)) {
1588
+			EE_Error::add_error(
1589
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1590
+				__FILE__,
1591
+				__FUNCTION__,
1592
+				__LINE__
1593
+			);
1594
+			return;
1595
+		}
1596
+		if (! $this->reg_code()) {
1597
+			parent::set('REG_code', $REG_code, $use_default);
1598
+		} else {
1599
+			EE_Error::doing_it_wrong(
1600
+				__CLASS__ . '::' . __FUNCTION__,
1601
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1602
+				'4.6.0'
1603
+			);
1604
+		}
1605
+	}
1606
+
1607
+
1608
+	/**
1609
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1610
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1611
+	 *    $registration->transaction()->registrations();
1612
+	 *
1613
+	 * @since 4.5.0
1614
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1615
+	 * @throws EE_Error
1616
+	 */
1617
+	public function get_all_other_registrations_in_group()
1618
+	{
1619
+		if ($this->group_size() < 2) {
1620
+			return array();
1621
+		}
1622
+
1623
+		$query[0] = array(
1624
+			'TXN_ID' => $this->transaction_ID(),
1625
+			'REG_ID' => array('!=', $this->ID()),
1626
+			'TKT_ID' => $this->ticket_ID(),
1627
+		);
1628
+		/** @var EE_Registration[] $registrations */
1629
+		$registrations = $this->get_model()->get_all($query);
1630
+		return $registrations;
1631
+	}
1632
+
1633
+	/**
1634
+	 * Return the link to the admin details for the object.
1635
+	 *
1636
+	 * @return string
1637
+	 * @throws EE_Error
1638
+	 */
1639
+	public function get_admin_details_link()
1640
+	{
1641
+		EE_Registry::instance()->load_helper('URL');
1642
+		return EEH_URL::add_query_args_and_nonce(
1643
+			array(
1644
+				'page'    => 'espresso_registrations',
1645
+				'action'  => 'view_registration',
1646
+				'_REG_ID' => $this->ID(),
1647
+			),
1648
+			admin_url('admin.php')
1649
+		);
1650
+	}
1651
+
1652
+	/**
1653
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1654
+	 *
1655
+	 * @return string
1656
+	 * @throws EE_Error
1657
+	 */
1658
+	public function get_admin_edit_link()
1659
+	{
1660
+		return $this->get_admin_details_link();
1661
+	}
1662
+
1663
+	/**
1664
+	 * Returns the link to a settings page for the object.
1665
+	 *
1666
+	 * @return string
1667
+	 * @throws EE_Error
1668
+	 */
1669
+	public function get_admin_settings_link()
1670
+	{
1671
+		return $this->get_admin_details_link();
1672
+	}
1673
+
1674
+	/**
1675
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1676
+	 *
1677
+	 * @return string
1678
+	 */
1679
+	public function get_admin_overview_link()
1680
+	{
1681
+		EE_Registry::instance()->load_helper('URL');
1682
+		return EEH_URL::add_query_args_and_nonce(
1683
+			array(
1684
+				'page' => 'espresso_registrations',
1685
+			),
1686
+			admin_url('admin.php')
1687
+		);
1688
+	}
1689
+
1690
+
1691
+	/**
1692
+	 * @param array $query_params
1693
+	 * @return \EE_Registration[]
1694
+	 * @throws \EE_Error
1695
+	 */
1696
+	public function payments($query_params = array())
1697
+	{
1698
+		return $this->get_many_related('Payment', $query_params);
1699
+	}
1700
+
1701
+
1702
+	/**
1703
+	 * @param array $query_params
1704
+	 * @return \EE_Registration_Payment[]
1705
+	 * @throws \EE_Error
1706
+	 */
1707
+	public function registration_payments($query_params = array())
1708
+	{
1709
+		return $this->get_many_related('Registration_Payment', $query_params);
1710
+	}
1711
+
1712
+
1713
+	/**
1714
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1715
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1716
+	 *
1717
+	 * @return EE_Payment_Method|null
1718
+	 */
1719
+	public function payment_method()
1720
+	{
1721
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1722
+	}
1723
+
1724
+
1725
+	/**
1726
+	 * @return \EE_Line_Item
1727
+	 * @throws EntityNotFoundException
1728
+	 * @throws \EE_Error
1729
+	 */
1730
+	public function ticket_line_item()
1731
+	{
1732
+		$ticket            = $this->ticket();
1733
+		$transaction       = $this->transaction();
1734
+		$line_item         = null;
1735
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1736
+			$transaction->total_line_item(),
1737
+			'Ticket',
1738
+			array($ticket->ID())
1739
+		);
1740
+		foreach ($ticket_line_items as $ticket_line_item) {
1741
+			if (
1742
+				$ticket_line_item instanceof \EE_Line_Item
1743
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1744
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1745
+			) {
1746
+				$line_item = $ticket_line_item;
1747
+				break;
1748
+			}
1749
+		}
1750
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1751
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1752
+		}
1753
+		return $line_item;
1754
+	}
1755
+
1756
+
1757
+	/**
1758
+	 * Soft Deletes this model object.
1759
+	 *
1760
+	 * @return boolean | int
1761
+	 * @throws \RuntimeException
1762
+	 * @throws \EE_Error
1763
+	 */
1764
+	public function delete()
1765
+	{
1766
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1767
+			$this->set_status(EEM_Registration::status_id_cancelled);
1768
+		}
1769
+		return parent::delete();
1770
+	}
1771
+
1772
+
1773
+	/**
1774
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1775
+	 *
1776
+	 * @throws \EE_Error
1777
+	 * @throws \RuntimeException
1778
+	 */
1779
+	public function restore()
1780
+	{
1781
+		$previous_status = $this->get_extra_meta(
1782
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1783
+			true,
1784
+			EEM_Registration::status_id_cancelled
1785
+		);
1786
+		if ($previous_status) {
1787
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1788
+			$this->set_status($previous_status);
1789
+		}
1790
+		return parent::restore();
1791
+	}
1792
+
1793
+
1794
+
1795
+	/*************************** DEPRECATED ***************************/
1796
+
1797
+
1798
+	/**
1799
+	 * @deprecated
1800
+	 * @since     4.7.0
1801
+	 * @access    public
1802
+	 */
1803
+	public function price_paid()
1804
+	{
1805
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1806
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1807
+			'4.7.0');
1808
+		return $this->final_price();
1809
+	}
1810
+
1811
+
1812
+	/**
1813
+	 * @deprecated
1814
+	 * @since     4.7.0
1815
+	 * @access    public
1816
+	 * @param    float $REG_final_price
1817
+	 * @throws EE_Error
1818
+	 * @throws RuntimeException
1819
+	 */
1820
+	public function set_price_paid($REG_final_price = 0.00)
1821
+	{
1822
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1823
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1824
+			'4.7.0');
1825
+		$this->set_final_price($REG_final_price);
1826
+	}
1827
+
1828
+
1829
+	/**
1830
+	 * @deprecated
1831
+	 * @since 4.7.0
1832
+	 * @return string
1833
+	 * @throws EE_Error
1834
+	 */
1835
+	public function pretty_price_paid()
1836
+	{
1837
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1838
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1839
+				'event_espresso'), '4.7.0');
1840
+		return $this->pretty_final_price();
1841
+	}
1842
+
1843
+
1844
+	/**
1845
+	 * Gets the primary datetime related to this registration via the related Event to this registration
1846
+	 *
1847
+	 * @deprecated 4.9.17
1848
+	 * @return EE_Datetime
1849
+	 * @throws EE_Error
1850
+	 * @throws EntityNotFoundException
1851
+	 */
1852
+	public function get_related_primary_datetime()
1853
+	{
1854
+		EE_Error::doing_it_wrong(
1855
+			__METHOD__,
1856
+			esc_html__(
1857
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1858
+				'event_espresso'
1859
+			),
1860
+			'4.9.17',
1861
+			'5.0.0'
1862
+		);
1863
+		return $this->event()->primary_datetime();
1864
+	}
1865 1865
 
1866 1866
 
1867 1867
 }
Please login to merge, or discard this patch.