Completed
Branch dev (22bd0c)
by
unknown
24:44 queued 18:15
created
core/db_classes/EE_Registration.class.php 1 patch
Indentation   +2112 added lines, -2112 removed lines patch added patch discarded remove patch
@@ -16,2116 +16,2116 @@
 block discarded – undo
16 16
  */
17 17
 class EE_Registration extends EE_Soft_Delete_Base_Class implements EEI_Registration, EEI_Admin_Links
18 18
 {
19
-    /**
20
-     * Used to reference when a registration has never been checked in.
21
-     *
22
-     * @deprecated use \EE_Checkin::status_checked_never instead
23
-     * @type int
24
-     */
25
-    const checkin_status_never = 2;
26
-
27
-    /**
28
-     * Used to reference when a registration has been checked in.
29
-     *
30
-     * @deprecated use \EE_Checkin::status_checked_in instead
31
-     * @type int
32
-     */
33
-    const checkin_status_in = 1;
34
-
35
-
36
-    /**
37
-     * Used to reference when a registration has been checked out.
38
-     *
39
-     * @deprecated use \EE_Checkin::status_checked_out instead
40
-     * @type int
41
-     */
42
-    const checkin_status_out = 0;
43
-
44
-
45
-    /**
46
-     * extra meta key for tracking reg status os trashed registrations
47
-     *
48
-     * @type string
49
-     */
50
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
51
-
52
-
53
-    /**
54
-     * extra meta key for tracking if registration has reserved ticket
55
-     *
56
-     * @type string
57
-     */
58
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
59
-
60
-
61
-    /**
62
-     * @param array  $props_n_values          incoming values
63
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
64
-     *                                        used.)
65
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
66
-     *                                        date_format and the second value is the time format
67
-     * @return EE_Registration
68
-     * @throws EE_Error
69
-     */
70
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
71
-    {
72
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
73
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
74
-    }
75
-
76
-
77
-    /**
78
-     * @param array  $props_n_values  incoming values from the database
79
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
80
-     *                                the website will be used.
81
-     * @return EE_Registration
82
-     */
83
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
84
-    {
85
-        return new self($props_n_values, true, $timezone);
86
-    }
87
-
88
-
89
-    /**
90
-     *        Set Event ID
91
-     *
92
-     * @param        int $EVT_ID Event ID
93
-     * @throws EE_Error
94
-     * @throws RuntimeException
95
-     */
96
-    public function set_event($EVT_ID = 0)
97
-    {
98
-        $this->set('EVT_ID', $EVT_ID);
99
-    }
100
-
101
-
102
-    /**
103
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
104
-     * be routed to internal methods
105
-     *
106
-     * @param string $field_name
107
-     * @param mixed  $field_value
108
-     * @param bool   $use_default
109
-     * @throws EE_Error
110
-     * @throws EntityNotFoundException
111
-     * @throws InvalidArgumentException
112
-     * @throws InvalidDataTypeException
113
-     * @throws InvalidInterfaceException
114
-     * @throws ReflectionException
115
-     * @throws RuntimeException
116
-     */
117
-    public function set($field_name, $field_value, $use_default = false)
118
-    {
119
-        switch ($field_name) {
120
-            case 'REG_code':
121
-                if (! empty($field_value) && $this->reg_code() === null) {
122
-                    $this->set_reg_code($field_value, $use_default);
123
-                }
124
-                break;
125
-            case 'STS_ID':
126
-                $this->set_status($field_value, $use_default);
127
-                break;
128
-            default:
129
-                parent::set($field_name, $field_value, $use_default);
130
-        }
131
-    }
132
-
133
-
134
-    /**
135
-     * Set Status ID
136
-     * updates the registration status and ALSO...
137
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
138
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
139
-     *
140
-     * @param string                $new_STS_ID
141
-     * @param boolean               $use_default
142
-     * @param ContextInterface|null $context
143
-     * @return bool
144
-     * @throws DomainException
145
-     * @throws EE_Error
146
-     * @throws EntityNotFoundException
147
-     * @throws InvalidArgumentException
148
-     * @throws InvalidDataTypeException
149
-     * @throws InvalidInterfaceException
150
-     * @throws ReflectionException
151
-     * @throws RuntimeException
152
-     * @throws UnexpectedEntityException
153
-     */
154
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
155
-    {
156
-        // get current REG_Status
157
-        $old_STS_ID = $this->status_ID();
158
-        // if status has changed
159
-        if (
160
-            $old_STS_ID !== $new_STS_ID // and that status has actually changed
161
-            && ! empty($old_STS_ID) // and that old status is actually set
162
-            && ! empty($new_STS_ID) // as well as the new status
163
-            && $this->ID() // ensure registration is in the db
164
-        ) {
165
-            // update internal status first
166
-            parent::set('STS_ID', $new_STS_ID, $use_default);
167
-            // THEN handle other changes that occur when reg status changes
168
-            // TO approved
169
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
-                // reserve a space by incrementing ticket and datetime sold values
171
-                $this->reserveRegistrationSpace();
172
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
-                // OR FROM  approved
174
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
-                // release a space by decrementing ticket and datetime sold values
176
-                $this->releaseRegistrationSpace();
177
-                do_action(
178
-                    'AHEE__EE_Registration__set_status__from_approved',
179
-                    $this,
180
-                    $old_STS_ID,
181
-                    $new_STS_ID,
182
-                    $context
183
-                );
184
-            }
185
-            // update status
186
-            parent::set('STS_ID', $new_STS_ID, $use_default);
187
-            $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
-            if ($this->statusChangeUpdatesTransaction($context)) {
189
-                $this->updateTransactionAfterStatusChange();
190
-            }
191
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
-            return true;
193
-        }
194
-        // even though the old value matches the new value, it's still good to
195
-        // allow the parent set method to have a say
196
-        parent::set('STS_ID', $new_STS_ID, $use_default);
197
-        return true;
198
-    }
199
-
200
-
201
-    /**
202
-     * update REGs and TXN when cancelled or declined registrations involved
203
-     *
204
-     * @param string                $new_STS_ID
205
-     * @param string                $old_STS_ID
206
-     * @param ContextInterface|null $context
207
-     * @throws EE_Error
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     * @throws ReflectionException
212
-     * @throws RuntimeException
213
-     */
214
-    private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
-    {
216
-        // these reg statuses should not be considered in any calculations involving monies owing
217
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
-        // true if registration has been cancelled or declined
219
-        $this->updateIfCanceled(
220
-            $closed_reg_statuses,
221
-            $new_STS_ID,
222
-            $old_STS_ID,
223
-            $context
224
-        );
225
-        $this->updateIfReinstated(
226
-            $closed_reg_statuses,
227
-            $new_STS_ID,
228
-            $old_STS_ID,
229
-            $context
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     * update REGs and TXN when cancelled or declined registrations involved
236
-     *
237
-     * @param array                 $closed_reg_statuses
238
-     * @param string                $new_STS_ID
239
-     * @param string                $old_STS_ID
240
-     * @param ContextInterface|null $context
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws InvalidDataTypeException
244
-     * @throws InvalidInterfaceException
245
-     * @throws ReflectionException
246
-     * @throws RuntimeException
247
-     */
248
-    private function updateIfCanceled(
249
-        array $closed_reg_statuses,
250
-        $new_STS_ID,
251
-        $old_STS_ID,
252
-        ContextInterface $context = null
253
-    ) {
254
-        // true if registration has been cancelled or declined
255
-        if (
256
-            in_array($new_STS_ID, $closed_reg_statuses, true)
257
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
258
-        ) {
259
-            /** @type EE_Registration_Processor $registration_processor */
260
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
261
-            /** @type EE_Transaction_Processor $transaction_processor */
262
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
263
-            // cancelled or declined registration
264
-            $registration_processor->update_registration_after_being_canceled_or_declined(
265
-                $this,
266
-                $closed_reg_statuses
267
-            );
268
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
269
-                $this,
270
-                $closed_reg_statuses,
271
-                false
272
-            );
273
-            do_action(
274
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
275
-                $this,
276
-                $old_STS_ID,
277
-                $new_STS_ID,
278
-                $context
279
-            );
280
-            return;
281
-        }
282
-    }
283
-
284
-
285
-    /**
286
-     * update REGs and TXN when cancelled or declined registrations involved
287
-     *
288
-     * @param array                 $closed_reg_statuses
289
-     * @param string                $new_STS_ID
290
-     * @param string                $old_STS_ID
291
-     * @param ContextInterface|null $context
292
-     * @throws EE_Error
293
-     * @throws InvalidArgumentException
294
-     * @throws InvalidDataTypeException
295
-     * @throws InvalidInterfaceException
296
-     * @throws ReflectionException
297
-     */
298
-    private function updateIfReinstated(
299
-        array $closed_reg_statuses,
300
-        $new_STS_ID,
301
-        $old_STS_ID,
302
-        ContextInterface $context = null
303
-    ) {
304
-        // true if reinstating cancelled or declined registration
305
-        if (
306
-            in_array($old_STS_ID, $closed_reg_statuses, true)
307
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
308
-        ) {
309
-            /** @type EE_Registration_Processor $registration_processor */
310
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
311
-            /** @type EE_Transaction_Processor $transaction_processor */
312
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
313
-            // reinstating cancelled or declined registration
314
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
315
-                $this,
316
-                $closed_reg_statuses
317
-            );
318
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
319
-                $this,
320
-                $closed_reg_statuses,
321
-                false
322
-            );
323
-            do_action(
324
-                'AHEE__EE_Registration__set_status__after_reinstated',
325
-                $this,
326
-                $old_STS_ID,
327
-                $new_STS_ID,
328
-                $context
329
-            );
330
-        }
331
-    }
332
-
333
-
334
-    /**
335
-     * @param ContextInterface|null $context
336
-     * @return bool
337
-     */
338
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
339
-    {
340
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
341
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
342
-            array('spco_reg_step_attendee_information_process_registrations'),
343
-            $context,
344
-            $this
345
-        );
346
-        return ! (
347
-            $context instanceof ContextInterface
348
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
349
-        );
350
-    }
351
-
352
-
353
-    /**
354
-     * @throws EE_Error
355
-     * @throws EntityNotFoundException
356
-     * @throws InvalidArgumentException
357
-     * @throws InvalidDataTypeException
358
-     * @throws InvalidInterfaceException
359
-     * @throws ReflectionException
360
-     * @throws RuntimeException
361
-     */
362
-    private function updateTransactionAfterStatusChange()
363
-    {
364
-        /** @type EE_Transaction_Payments $transaction_payments */
365
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
366
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
367
-        $this->transaction()->update_status_based_on_total_paid(true);
368
-    }
369
-
370
-
371
-    /**
372
-     *        get Status ID
373
-     */
374
-    public function status_ID()
375
-    {
376
-        return $this->get('STS_ID');
377
-    }
378
-
379
-
380
-    /**
381
-     * Gets the ticket this registration is for
382
-     *
383
-     * @param boolean $include_archived whether to include archived tickets or not.
384
-     *
385
-     * @return EE_Ticket|EE_Base_Class
386
-     * @throws EE_Error
387
-     */
388
-    public function ticket($include_archived = true)
389
-    {
390
-        $query_params = array();
391
-        if ($include_archived) {
392
-            $query_params['default_where_conditions'] = 'none';
393
-        }
394
-        return $this->get_first_related('Ticket', $query_params);
395
-    }
396
-
397
-
398
-    /**
399
-     * Gets the event this registration is for
400
-     *
401
-     * @return EE_Event
402
-     * @throws EE_Error
403
-     * @throws EntityNotFoundException
404
-     */
405
-    public function event()
406
-    {
407
-        $event = $this->get_first_related('Event');
408
-        if (! $event instanceof \EE_Event) {
409
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
410
-        }
411
-        return $event;
412
-    }
413
-
414
-
415
-    /**
416
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
417
-     * with the author of the event this registration is for.
418
-     *
419
-     * @since 4.5.0
420
-     * @return int
421
-     * @throws EE_Error
422
-     * @throws EntityNotFoundException
423
-     */
424
-    public function wp_user()
425
-    {
426
-        $event = $this->event();
427
-        if ($event instanceof EE_Event) {
428
-            return $event->wp_user();
429
-        }
430
-        return 0;
431
-    }
432
-
433
-
434
-    /**
435
-     * increments this registration's related ticket sold and corresponding datetime sold values
436
-     *
437
-     * @return void
438
-     * @throws DomainException
439
-     * @throws EE_Error
440
-     * @throws EntityNotFoundException
441
-     * @throws InvalidArgumentException
442
-     * @throws InvalidDataTypeException
443
-     * @throws InvalidInterfaceException
444
-     * @throws ReflectionException
445
-     * @throws UnexpectedEntityException
446
-     */
447
-    private function reserveRegistrationSpace()
448
-    {
449
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
450
-        // so stop tracking that this reg has a ticket reserved
451
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
452
-        $ticket = $this->ticket();
453
-        $ticket->increaseSold();
454
-        // possibly set event status to sold out
455
-        $this->event()->perform_sold_out_status_check();
456
-    }
457
-
458
-
459
-    /**
460
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
461
-     *
462
-     * @return void
463
-     * @throws DomainException
464
-     * @throws EE_Error
465
-     * @throws EntityNotFoundException
466
-     * @throws InvalidArgumentException
467
-     * @throws InvalidDataTypeException
468
-     * @throws InvalidInterfaceException
469
-     * @throws ReflectionException
470
-     * @throws UnexpectedEntityException
471
-     */
472
-    private function releaseRegistrationSpace()
473
-    {
474
-        $ticket = $this->ticket();
475
-        $ticket->decreaseSold();
476
-        // possibly change event status from sold out back to previous status
477
-        $this->event()->perform_sold_out_status_check();
478
-    }
479
-
480
-
481
-    /**
482
-     * tracks this registration's ticket reservation in extra meta
483
-     * and can increment related ticket reserved and corresponding datetime reserved values
484
-     *
485
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
486
-     * @return void
487
-     * @throws EE_Error
488
-     * @throws InvalidArgumentException
489
-     * @throws InvalidDataTypeException
490
-     * @throws InvalidInterfaceException
491
-     * @throws ReflectionException
492
-     */
493
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
494
-    {
495
-        // only reserve ticket if space is not currently reserved
496
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
497
-            $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
498
-            // IMPORTANT !!!
499
-            // although checking $update_ticket first would be more efficient,
500
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
501
-            if (
502
-                $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
503
-                && $update_ticket
504
-            ) {
505
-                $ticket = $this->ticket();
506
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
507
-                $ticket->save();
508
-            }
509
-        }
510
-    }
511
-
512
-
513
-    /**
514
-     * stops tracking this registration's ticket reservation in extra meta
515
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
516
-     *
517
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
518
-     * @return void
519
-     * @throws EE_Error
520
-     * @throws InvalidArgumentException
521
-     * @throws InvalidDataTypeException
522
-     * @throws InvalidInterfaceException
523
-     * @throws ReflectionException
524
-     */
525
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
526
-    {
527
-        // only release ticket if space is currently reserved
528
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
529
-            $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
530
-            // IMPORTANT !!!
531
-            // although checking $update_ticket first would be more efficient,
532
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
533
-            if (
534
-                $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
535
-                && $update_ticket
536
-            ) {
537
-                $ticket = $this->ticket();
538
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
539
-            }
540
-        }
541
-    }
542
-
543
-
544
-    /**
545
-     * Set Attendee ID
546
-     *
547
-     * @param        int $ATT_ID Attendee ID
548
-     * @throws EE_Error
549
-     * @throws RuntimeException
550
-     */
551
-    public function set_attendee_id($ATT_ID = 0)
552
-    {
553
-        $this->set('ATT_ID', $ATT_ID);
554
-    }
555
-
556
-
557
-    /**
558
-     *        Set Transaction ID
559
-     *
560
-     * @param        int $TXN_ID Transaction ID
561
-     * @throws EE_Error
562
-     * @throws RuntimeException
563
-     */
564
-    public function set_transaction_id($TXN_ID = 0)
565
-    {
566
-        $this->set('TXN_ID', $TXN_ID);
567
-    }
568
-
569
-
570
-    /**
571
-     *        Set Session
572
-     *
573
-     * @param    string $REG_session PHP Session ID
574
-     * @throws EE_Error
575
-     * @throws RuntimeException
576
-     */
577
-    public function set_session($REG_session = '')
578
-    {
579
-        $this->set('REG_session', $REG_session);
580
-    }
581
-
582
-
583
-    /**
584
-     *        Set Registration URL Link
585
-     *
586
-     * @param    string $REG_url_link Registration URL Link
587
-     * @throws EE_Error
588
-     * @throws RuntimeException
589
-     */
590
-    public function set_reg_url_link($REG_url_link = '')
591
-    {
592
-        $this->set('REG_url_link', $REG_url_link);
593
-    }
594
-
595
-
596
-    /**
597
-     *        Set Attendee Counter
598
-     *
599
-     * @param        int $REG_count Primary Attendee
600
-     * @throws EE_Error
601
-     * @throws RuntimeException
602
-     */
603
-    public function set_count($REG_count = 1)
604
-    {
605
-        $this->set('REG_count', $REG_count);
606
-    }
607
-
608
-
609
-    /**
610
-     *        Set Group Size
611
-     *
612
-     * @param        boolean $REG_group_size Group Registration
613
-     * @throws EE_Error
614
-     * @throws RuntimeException
615
-     */
616
-    public function set_group_size($REG_group_size = false)
617
-    {
618
-        $this->set('REG_group_size', $REG_group_size);
619
-    }
620
-
621
-
622
-    /**
623
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
624
-     *    EEM_Registration::status_id_not_approved
625
-     *
626
-     * @return        boolean
627
-     */
628
-    public function is_not_approved()
629
-    {
630
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
631
-    }
632
-
633
-
634
-    /**
635
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
636
-     *    EEM_Registration::status_id_pending_payment
637
-     *
638
-     * @return        boolean
639
-     */
640
-    public function is_pending_payment()
641
-    {
642
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
643
-    }
644
-
645
-
646
-    /**
647
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
648
-     *
649
-     * @return        boolean
650
-     */
651
-    public function is_approved()
652
-    {
653
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
654
-    }
655
-
656
-
657
-    /**
658
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
659
-     *
660
-     * @return        boolean
661
-     */
662
-    public function is_cancelled()
663
-    {
664
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
665
-    }
666
-
667
-
668
-    /**
669
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
670
-     *
671
-     * @return        boolean
672
-     */
673
-    public function is_declined()
674
-    {
675
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
676
-    }
677
-
678
-
679
-    /**
680
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
681
-     *    EEM_Registration::status_id_incomplete
682
-     *
683
-     * @return        boolean
684
-     */
685
-    public function is_incomplete()
686
-    {
687
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
688
-    }
689
-
690
-
691
-    /**
692
-     *        Set Registration Date
693
-     *
694
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
695
-     *                                                 Date
696
-     * @throws EE_Error
697
-     * @throws RuntimeException
698
-     */
699
-    public function set_reg_date($REG_date = false)
700
-    {
701
-        $this->set('REG_date', $REG_date);
702
-    }
703
-
704
-
705
-    /**
706
-     *    Set final price owing for this registration after all ticket/price modifications
707
-     *
708
-     * @access    public
709
-     * @param    float $REG_final_price
710
-     * @throws EE_Error
711
-     * @throws RuntimeException
712
-     */
713
-    public function set_final_price($REG_final_price = 0.00)
714
-    {
715
-        $this->set('REG_final_price', $REG_final_price);
716
-    }
717
-
718
-
719
-    /**
720
-     *    Set amount paid towards this registration's final price
721
-     *
722
-     * @access    public
723
-     * @param    float $REG_paid
724
-     * @throws EE_Error
725
-     * @throws RuntimeException
726
-     */
727
-    public function set_paid($REG_paid = 0.00)
728
-    {
729
-        $this->set('REG_paid', $REG_paid);
730
-    }
731
-
732
-
733
-    /**
734
-     *        Attendee Is Going
735
-     *
736
-     * @param        boolean $REG_att_is_going Attendee Is Going
737
-     * @throws EE_Error
738
-     * @throws RuntimeException
739
-     */
740
-    public function set_att_is_going($REG_att_is_going = false)
741
-    {
742
-        $this->set('REG_att_is_going', $REG_att_is_going);
743
-    }
744
-
745
-
746
-    /**
747
-     * Gets the related attendee
748
-     *
749
-     * @return EE_Attendee
750
-     * @throws EE_Error
751
-     */
752
-    public function attendee()
753
-    {
754
-        return $this->get_first_related('Attendee');
755
-    }
756
-
757
-    /**
758
-     * Gets the name of the attendee.
759
-     * @since 4.10.12.p
760
-     * @param bool $apply_html_entities set to true if you want to use HTML entities.
761
-     * @return string
762
-     * @throws EE_Error
763
-     * @throws InvalidArgumentException
764
-     * @throws InvalidDataTypeException
765
-     * @throws InvalidInterfaceException
766
-     * @throws ReflectionException
767
-     */
768
-    public function attendeeName($apply_html_entities = false)
769
-    {
770
-        $attendee = $this->get_first_related('Attendee');
771
-        if ($attendee instanceof EE_Attendee) {
772
-            $attendee_name = $attendee->full_name($apply_html_entities);
773
-        } else {
774
-            $attendee_name = esc_html__('Unknown', 'event_espresso');
775
-        }
776
-        return $attendee_name;
777
-    }
778
-
779
-
780
-    /**
781
-     *        get Event ID
782
-     */
783
-    public function event_ID()
784
-    {
785
-        return $this->get('EVT_ID');
786
-    }
787
-
788
-
789
-    /**
790
-     *        get Event ID
791
-     */
792
-    public function event_name()
793
-    {
794
-        $event = $this->event_obj();
795
-        if ($event) {
796
-            return $event->name();
797
-        } else {
798
-            return null;
799
-        }
800
-    }
801
-
802
-
803
-    /**
804
-     * Fetches the event this registration is for
805
-     *
806
-     * @return EE_Event
807
-     * @throws EE_Error
808
-     */
809
-    public function event_obj()
810
-    {
811
-        return $this->get_first_related('Event');
812
-    }
813
-
814
-
815
-    /**
816
-     *        get Attendee ID
817
-     */
818
-    public function attendee_ID()
819
-    {
820
-        return $this->get('ATT_ID');
821
-    }
822
-
823
-
824
-    /**
825
-     *        get PHP Session ID
826
-     */
827
-    public function session_ID()
828
-    {
829
-        return $this->get('REG_session');
830
-    }
831
-
832
-
833
-    /**
834
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
835
-     *
836
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
837
-     * @return string
838
-     */
839
-    public function receipt_url($messenger = 'html')
840
-    {
841
-
842
-        /**
843
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
844
-         * already in use on old system.  If there is then we just return the standard url for it.
845
-         *
846
-         * @since 4.5.0
847
-         */
848
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
849
-        $has_custom = EEH_Template::locate_template(
850
-            $template_relative_path,
851
-            array(),
852
-            true,
853
-            true,
854
-            true
855
-        );
856
-
857
-        if ($has_custom) {
858
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
859
-        }
860
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
861
-    }
862
-
863
-
864
-    /**
865
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
866
-     *
867
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
868
-     * @return string
869
-     * @throws EE_Error
870
-     */
871
-    public function invoice_url($messenger = 'html')
872
-    {
873
-        /**
874
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
875
-         * already in use on old system.  If there is then we just return the standard url for it.
876
-         *
877
-         * @since 4.5.0
878
-         */
879
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
880
-        $has_custom = EEH_Template::locate_template(
881
-            $template_relative_path,
882
-            array(),
883
-            true,
884
-            true,
885
-            true
886
-        );
887
-
888
-        if ($has_custom) {
889
-            if ($messenger == 'html') {
890
-                return $this->invoice_url('launch');
891
-            }
892
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
893
-
894
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
895
-            if ($messenger == 'html') {
896
-                $query_args['html'] = true;
897
-            }
898
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
899
-        }
900
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
901
-    }
902
-
903
-
904
-    /**
905
-     * get Registration URL Link
906
-     *
907
-     * @access public
908
-     * @return string
909
-     * @throws EE_Error
910
-     */
911
-    public function reg_url_link()
912
-    {
913
-        return (string) $this->get('REG_url_link');
914
-    }
915
-
916
-
917
-    /**
918
-     * Echoes out invoice_url()
919
-     *
920
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
921
-     * @return void
922
-     * @throws EE_Error
923
-     */
924
-    public function e_invoice_url($type = 'launch')
925
-    {
926
-        echo esc_url_raw($this->invoice_url($type));
927
-    }
928
-
929
-
930
-    /**
931
-     * Echoes out payment_overview_url
932
-     */
933
-    public function e_payment_overview_url()
934
-    {
935
-        echo esc_url_raw($this->payment_overview_url());
936
-    }
937
-
938
-
939
-    /**
940
-     * Gets the URL for the checkout payment options reg step
941
-     * with this registration's REG_url_link added as a query parameter
942
-     *
943
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
944
-     *                            payment overview url.
945
-     * @return string
946
-     * @throws InvalidInterfaceException
947
-     * @throws InvalidDataTypeException
948
-     * @throws EE_Error
949
-     * @throws InvalidArgumentException
950
-     */
951
-    public function payment_overview_url($clear_session = false)
952
-    {
953
-        return add_query_arg(
954
-            (array) apply_filters(
955
-                'FHEE__EE_Registration__payment_overview_url__query_args',
956
-                array(
957
-                    'e_reg_url_link' => $this->reg_url_link(),
958
-                    'step'           => 'payment_options',
959
-                    'revisit'        => true,
960
-                    'clear_session'  => (bool) $clear_session,
961
-                ),
962
-                $this
963
-            ),
964
-            EE_Registry::instance()->CFG->core->reg_page_url()
965
-        );
966
-    }
967
-
968
-
969
-    /**
970
-     * Gets the URL for the checkout attendee information reg step
971
-     * with this registration's REG_url_link added as a query parameter
972
-     *
973
-     * @return string
974
-     * @throws InvalidInterfaceException
975
-     * @throws InvalidDataTypeException
976
-     * @throws EE_Error
977
-     * @throws InvalidArgumentException
978
-     */
979
-    public function edit_attendee_information_url()
980
-    {
981
-        return add_query_arg(
982
-            (array) apply_filters(
983
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
984
-                array(
985
-                    'e_reg_url_link' => $this->reg_url_link(),
986
-                    'step'           => 'attendee_information',
987
-                    'revisit'        => true,
988
-                ),
989
-                $this
990
-            ),
991
-            EE_Registry::instance()->CFG->core->reg_page_url()
992
-        );
993
-    }
994
-
995
-
996
-    /**
997
-     * Simply generates and returns the appropriate admin_url link to edit this registration
998
-     *
999
-     * @return string
1000
-     * @throws EE_Error
1001
-     */
1002
-    public function get_admin_edit_url()
1003
-    {
1004
-        return EEH_URL::add_query_args_and_nonce(
1005
-            array(
1006
-                'page'    => 'espresso_registrations',
1007
-                'action'  => 'view_registration',
1008
-                '_REG_ID' => $this->ID(),
1009
-            ),
1010
-            admin_url('admin.php')
1011
-        );
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     *    is_primary_registrant?
1017
-     */
1018
-    public function is_primary_registrant()
1019
-    {
1020
-        return $this->get('REG_count') === 1 ? true : false;
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     * This returns the primary registration object for this registration group (which may be this object).
1026
-     *
1027
-     * @return EE_Registration
1028
-     * @throws EE_Error
1029
-     */
1030
-    public function get_primary_registration()
1031
-    {
1032
-        if ($this->is_primary_registrant()) {
1033
-            return $this;
1034
-        }
1035
-
1036
-        // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1037
-        /** @var EE_Registration $primary_registrant */
1038
-        $primary_registrant = EEM_Registration::instance()->get_one(
1039
-            array(
1040
-                array(
1041
-                    'TXN_ID'    => $this->transaction_ID(),
1042
-                    'REG_count' => 1,
1043
-                ),
1044
-            )
1045
-        );
1046
-        return $primary_registrant;
1047
-    }
1048
-
1049
-
1050
-    /**
1051
-     *        get  Attendee Number
1052
-     *
1053
-     * @access        public
1054
-     */
1055
-    public function count()
1056
-    {
1057
-        return $this->get('REG_count');
1058
-    }
1059
-
1060
-
1061
-    /**
1062
-     *        get Group Size
1063
-     */
1064
-    public function group_size()
1065
-    {
1066
-        return $this->get('REG_group_size');
1067
-    }
1068
-
1069
-
1070
-    /**
1071
-     *        get Registration Date
1072
-     */
1073
-    public function date()
1074
-    {
1075
-        return $this->get('REG_date');
1076
-    }
1077
-
1078
-
1079
-    /**
1080
-     * gets a pretty date
1081
-     *
1082
-     * @param string $date_format
1083
-     * @param string $time_format
1084
-     * @return string
1085
-     * @throws EE_Error
1086
-     */
1087
-    public function pretty_date($date_format = null, $time_format = null)
1088
-    {
1089
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     * final_price
1095
-     * the registration's share of the transaction total, so that the
1096
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1097
-     *
1098
-     * @return float
1099
-     * @throws EE_Error
1100
-     */
1101
-    public function final_price()
1102
-    {
1103
-        return $this->get('REG_final_price');
1104
-    }
1105
-
1106
-
1107
-    /**
1108
-     * pretty_final_price
1109
-     *  final price as formatted string, with correct decimal places and currency symbol
1110
-     *
1111
-     * @return string
1112
-     * @throws EE_Error
1113
-     */
1114
-    public function pretty_final_price()
1115
-    {
1116
-        return $this->get_pretty('REG_final_price');
1117
-    }
1118
-
1119
-
1120
-    /**
1121
-     * get paid (yeah)
1122
-     *
1123
-     * @return float
1124
-     * @throws EE_Error
1125
-     */
1126
-    public function paid()
1127
-    {
1128
-        return $this->get('REG_paid');
1129
-    }
1130
-
1131
-
1132
-    /**
1133
-     * pretty_paid
1134
-     *
1135
-     * @return float
1136
-     * @throws EE_Error
1137
-     */
1138
-    public function pretty_paid()
1139
-    {
1140
-        return $this->get_pretty('REG_paid');
1141
-    }
1142
-
1143
-
1144
-    /**
1145
-     * owes_monies_and_can_pay
1146
-     * whether or not this registration has monies owing and it's' status allows payment
1147
-     *
1148
-     * @param array $requires_payment
1149
-     * @return bool
1150
-     * @throws EE_Error
1151
-     */
1152
-    public function owes_monies_and_can_pay($requires_payment = array())
1153
-    {
1154
-        // these reg statuses require payment (if event is not free)
1155
-        $requires_payment = ! empty($requires_payment)
1156
-            ? $requires_payment
1157
-            : EEM_Registration::reg_statuses_that_allow_payment();
1158
-        if (
1159
-            in_array($this->status_ID(), $requires_payment) &&
1160
-            $this->final_price() != 0 &&
1161
-            $this->final_price() != $this->paid()
1162
-        ) {
1163
-            return true;
1164
-        } else {
1165
-            return false;
1166
-        }
1167
-    }
1168
-
1169
-
1170
-    /**
1171
-     * Prints out the return value of $this->pretty_status()
1172
-     *
1173
-     * @param bool $show_icons
1174
-     * @return void
1175
-     * @throws EE_Error
1176
-     */
1177
-    public function e_pretty_status($show_icons = false)
1178
-    {
1179
-        echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
1180
-    }
1181
-
1182
-
1183
-    /**
1184
-     * Returns a nice version of the status for displaying to customers
1185
-     *
1186
-     * @param bool $show_icons
1187
-     * @return string
1188
-     * @throws EE_Error
1189
-     */
1190
-    public function pretty_status($show_icons = false)
1191
-    {
1192
-        $status = EEM_Status::instance()->localized_status(
1193
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1194
-            false,
1195
-            'sentence'
1196
-        );
1197
-        $icon = '';
1198
-        switch ($this->status_ID()) {
1199
-            case EEM_Registration::status_id_approved:
1200
-                $icon = $show_icons
1201
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1202
-                    : '';
1203
-                break;
1204
-            case EEM_Registration::status_id_pending_payment:
1205
-                $icon = $show_icons
1206
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1207
-                    : '';
1208
-                break;
1209
-            case EEM_Registration::status_id_not_approved:
1210
-                $icon = $show_icons
1211
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1212
-                    : '';
1213
-                break;
1214
-            case EEM_Registration::status_id_cancelled:
1215
-                $icon = $show_icons
1216
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1217
-                    : '';
1218
-                break;
1219
-            case EEM_Registration::status_id_incomplete:
1220
-                $icon = $show_icons
1221
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1222
-                    : '';
1223
-                break;
1224
-            case EEM_Registration::status_id_declined:
1225
-                $icon = $show_icons
1226
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1227
-                    : '';
1228
-                break;
1229
-            case EEM_Registration::status_id_wait_list:
1230
-                $icon = $show_icons
1231
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1232
-                    : '';
1233
-                break;
1234
-        }
1235
-        return $icon . $status[ $this->status_ID() ];
1236
-    }
1237
-
1238
-
1239
-    /**
1240
-     *        get Attendee Is Going
1241
-     */
1242
-    public function att_is_going()
1243
-    {
1244
-        return $this->get('REG_att_is_going');
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * Gets related answers
1250
-     *
1251
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1252
-     * @return EE_Answer[]
1253
-     * @throws EE_Error
1254
-     */
1255
-    public function answers($query_params = null)
1256
-    {
1257
-        return $this->get_many_related('Answer', $query_params);
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * Gets the registration's answer value to the specified question
1263
-     * (either the question's ID or a question object)
1264
-     *
1265
-     * @param EE_Question|int $question
1266
-     * @param bool            $pretty_value
1267
-     * @return array|string if pretty_value= true, the result will always be a string
1268
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1269
-     * will convert it into some kind of string)
1270
-     * @throws EE_Error
1271
-     */
1272
-    public function answer_value_to_question($question, $pretty_value = true)
1273
-    {
1274
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1275
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * question_groups
1281
-     * returns an array of EE_Question_Group objects for this registration
1282
-     *
1283
-     * @return EE_Question_Group[]
1284
-     * @throws EE_Error
1285
-     * @throws InvalidArgumentException
1286
-     * @throws InvalidDataTypeException
1287
-     * @throws InvalidInterfaceException
1288
-     * @throws ReflectionException
1289
-     */
1290
-    public function question_groups()
1291
-    {
1292
-        return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * count_question_groups
1298
-     * returns a count of the number of EE_Question_Group objects for this registration
1299
-     *
1300
-     * @return int
1301
-     * @throws EE_Error
1302
-     * @throws EntityNotFoundException
1303
-     * @throws InvalidArgumentException
1304
-     * @throws InvalidDataTypeException
1305
-     * @throws InvalidInterfaceException
1306
-     * @throws ReflectionException
1307
-     */
1308
-    public function count_question_groups()
1309
-    {
1310
-        return EEM_Event::instance()->count_related(
1311
-            $this->event_ID(),
1312
-            'Question_Group',
1313
-            [
1314
-                [
1315
-                    'Event_Question_Group.'
1316
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1317
-                ]
1318
-            ]
1319
-        );
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * Returns the registration date in the 'standard' string format
1325
-     * (function may be improved in the future to allow for different formats and timezones)
1326
-     *
1327
-     * @return string
1328
-     * @throws EE_Error
1329
-     */
1330
-    public function reg_date()
1331
-    {
1332
-        return $this->get_datetime('REG_date');
1333
-    }
1334
-
1335
-
1336
-    /**
1337
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1338
-     * the ticket this registration purchased, or the datetime they have registered
1339
-     * to attend)
1340
-     *
1341
-     * @return EE_Datetime_Ticket
1342
-     * @throws EE_Error
1343
-     */
1344
-    public function datetime_ticket()
1345
-    {
1346
-        return $this->get_first_related('Datetime_Ticket');
1347
-    }
1348
-
1349
-
1350
-    /**
1351
-     * Sets the registration's datetime_ticket.
1352
-     *
1353
-     * @param EE_Datetime_Ticket $datetime_ticket
1354
-     * @return EE_Datetime_Ticket
1355
-     * @throws EE_Error
1356
-     */
1357
-    public function set_datetime_ticket($datetime_ticket)
1358
-    {
1359
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1360
-    }
1361
-
1362
-    /**
1363
-     * Gets deleted
1364
-     *
1365
-     * @return bool
1366
-     * @throws EE_Error
1367
-     */
1368
-    public function deleted()
1369
-    {
1370
-        return $this->get('REG_deleted');
1371
-    }
1372
-
1373
-    /**
1374
-     * Sets deleted
1375
-     *
1376
-     * @param boolean $deleted
1377
-     * @return bool
1378
-     * @throws EE_Error
1379
-     * @throws RuntimeException
1380
-     */
1381
-    public function set_deleted($deleted)
1382
-    {
1383
-        if ($deleted) {
1384
-            $this->delete();
1385
-        } else {
1386
-            $this->restore();
1387
-        }
1388
-    }
1389
-
1390
-
1391
-    /**
1392
-     * Get the status object of this object
1393
-     *
1394
-     * @return EE_Status
1395
-     * @throws EE_Error
1396
-     */
1397
-    public function status_obj()
1398
-    {
1399
-        return $this->get_first_related('Status');
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * Returns the number of times this registration has checked into any of the datetimes
1405
-     * its available for
1406
-     *
1407
-     * @return int
1408
-     * @throws EE_Error
1409
-     */
1410
-    public function count_checkins()
1411
-    {
1412
-        return $this->get_model()->count_related($this, 'Checkin');
1413
-    }
1414
-
1415
-
1416
-    /**
1417
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1418
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1419
-     *
1420
-     * @return int
1421
-     * @throws EE_Error
1422
-     */
1423
-    public function count_checkins_not_checkedout()
1424
-    {
1425
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1426
-    }
1427
-
1428
-
1429
-    /**
1430
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1431
-     *
1432
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1433
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1434
-     *                                          consider registration status as well as datetime access.
1435
-     * @return bool
1436
-     * @throws EE_Error
1437
-     */
1438
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1439
-    {
1440
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1441
-
1442
-        // first check registration status
1443
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1444
-            return false;
1445
-        }
1446
-        // is there a datetime ticket that matches this dtt_ID?
1447
-        if (
1448
-            ! (EEM_Datetime_Ticket::instance()->exists(
1449
-                array(
1450
-                array(
1451
-                    'TKT_ID' => $this->get('TKT_ID'),
1452
-                    'DTT_ID' => $DTT_ID,
1453
-                ),
1454
-                )
1455
-            ))
1456
-        ) {
1457
-            return false;
1458
-        }
1459
-
1460
-        // final check is against TKT_uses
1461
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1467
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1468
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1469
-     * then return false.  Otherwise return true.
1470
-     *
1471
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1472
-     * @return bool true means can checkin.  false means cannot checkin.
1473
-     * @throws EE_Error
1474
-     */
1475
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1476
-    {
1477
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1478
-
1479
-        if (! $DTT_ID) {
1480
-            return false;
1481
-        }
1482
-
1483
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1484
-
1485
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1486
-        // check-in or not.
1487
-        if (! $max_uses || $max_uses === EE_INF) {
1488
-            return true;
1489
-        }
1490
-
1491
-        // does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1492
-        // go ahead and toggle.
1493
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1494
-            return true;
1495
-        }
1496
-
1497
-        // made it here so the last check is whether the number of checkins per unique datetime on this registration
1498
-        // disallows further check-ins.
1499
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1500
-            array(
1501
-                array(
1502
-                    'REG_ID' => $this->ID(),
1503
-                    'CHK_in' => true,
1504
-                ),
1505
-            ),
1506
-            'DTT_ID',
1507
-            true
1508
-        );
1509
-        // checkins have already reached their max number of uses
1510
-        // so registrant can NOT checkin
1511
-        if ($count_unique_dtt_checkins >= $max_uses) {
1512
-            EE_Error::add_error(
1513
-                esc_html__(
1514
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1515
-                    'event_espresso'
1516
-                ),
1517
-                __FILE__,
1518
-                __FUNCTION__,
1519
-                __LINE__
1520
-            );
1521
-            return false;
1522
-        }
1523
-        return true;
1524
-    }
1525
-
1526
-
1527
-    /**
1528
-     * toggle Check-in status for this registration
1529
-     * Check-ins are toggled in the following order:
1530
-     * never checked in -> checked in
1531
-     * checked in -> checked out
1532
-     * checked out -> checked in
1533
-     *
1534
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1535
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1536
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1537
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1538
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1539
-     * @throws EE_Error
1540
-     */
1541
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1542
-    {
1543
-        if (empty($DTT_ID)) {
1544
-            $datetime = $this->get_latest_related_datetime();
1545
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1546
-            // verify the registration can checkin for the given DTT_ID
1547
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1548
-            EE_Error::add_error(
1549
-                sprintf(
1550
-                    esc_html__(
1551
-                        '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',
1552
-                        'event_espresso'
1553
-                    ),
1554
-                    $this->ID(),
1555
-                    $DTT_ID
1556
-                ),
1557
-                __FILE__,
1558
-                __FUNCTION__,
1559
-                __LINE__
1560
-            );
1561
-            return false;
1562
-        }
1563
-        $status_paths = array(
1564
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1565
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1566
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1567
-        );
1568
-        // start by getting the current status so we know what status we'll be changing to.
1569
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1570
-        $status_to = $status_paths[ $cur_status ];
1571
-        // database only records true for checked IN or false for checked OUT
1572
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1573
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1574
-        // add relation - note Check-ins are always creating new rows
1575
-        // because we are keeping track of Check-ins over time.
1576
-        // Eventually we'll probably want to show a list table
1577
-        // for the individual Check-ins so that they can be managed.
1578
-        $checkin = EE_Checkin::new_instance(
1579
-            array(
1580
-                'REG_ID' => $this->ID(),
1581
-                'DTT_ID' => $DTT_ID,
1582
-                'CHK_in' => $new_status,
1583
-            )
1584
-        );
1585
-        // if the record could not be saved then return false
1586
-        if ($checkin->save() === 0) {
1587
-            if (WP_DEBUG) {
1588
-                global $wpdb;
1589
-                $error = sprintf(
1590
-                    esc_html__(
1591
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1592
-                        'event_espresso'
1593
-                    ),
1594
-                    '<br />',
1595
-                    $wpdb->last_error
1596
-                );
1597
-            } else {
1598
-                $error = esc_html__(
1599
-                    'Registration check in update failed because of an unknown database error',
1600
-                    'event_espresso'
1601
-                );
1602
-            }
1603
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1604
-            return false;
1605
-        }
1606
-        // Fire a checked_in and checkout_out action.
1607
-        $checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1608
-        do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1609
-        return $status_to;
1610
-    }
1611
-
1612
-
1613
-    /**
1614
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1615
-     * "Latest" is defined by the `DTT_EVT_start` column.
1616
-     *
1617
-     * @return EE_Datetime|null
1618
-     * @throws EE_Error
1619
-     */
1620
-    public function get_latest_related_datetime()
1621
-    {
1622
-        return EEM_Datetime::instance()->get_one(
1623
-            array(
1624
-                array(
1625
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1626
-                ),
1627
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1628
-            )
1629
-        );
1630
-    }
1631
-
1632
-
1633
-    /**
1634
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1635
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1636
-     *
1637
-     * @throws EE_Error
1638
-     */
1639
-    public function get_earliest_related_datetime()
1640
-    {
1641
-        return EEM_Datetime::instance()->get_one(
1642
-            array(
1643
-                array(
1644
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1645
-                ),
1646
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1647
-            )
1648
-        );
1649
-    }
1650
-
1651
-
1652
-    /**
1653
-     * This method simply returns the check-in status for this registration and the given datetime.
1654
-     * If neither the datetime nor the checkin values are provided as arguments,
1655
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1656
-     *
1657
-     * @param int|null        $DTT_ID  The ID of the datetime we're checking against
1658
-     *                                 (if empty we'll get the primary datetime for
1659
-     *                                 this registration (via event) and use it's ID);
1660
-     * @param EE_Checkin|null $checkin If present, we use the given checkin object rather than the dtt_id.
1661
-     * @return int                     Integer representing Check-in status.
1662
-     * @throws EE_Error
1663
-     * @throws ReflectionException
1664
-     */
1665
-    public function check_in_status_for_datetime(?int $DTT_ID = 0, ?EE_Checkin $checkin = null): int
1666
-    {
1667
-        if ($checkin instanceof EE_Checkin) {
1668
-            return $checkin->status();
1669
-        }
1670
-        // can't query checkin for a specific date if no ID was supplied
1671
-        if (empty($DTT_ID)) {
1672
-            return EE_Checkin::status_invalid;
1673
-        }
1674
-
1675
-        $checkin = $this->get_first_related(
1676
-            'Checkin',
1677
-            [
1678
-                ['DTT_ID' => $DTT_ID],
1679
-                'order_by' => ['CHK_timestamp' => 'DESC'],
1680
-            ]
1681
-        );
1682
-        return $checkin instanceof EE_Checkin ? $checkin->status() :  EE_Checkin::status_checked_never;
1683
-    }
1684
-
1685
-
1686
-    /**
1687
-     * This method returns a localized message for the toggled Check-in message.
1688
-     *
1689
-     * @param int|null $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1690
-     *                         then it is assumed Check-in for primary datetime was toggled.
1691
-     * @param bool     $error  This just flags that you want an error message returned. This is put in so that the error
1692
-     *                         message can be customized with the attendee name.
1693
-     * @return string internationalized message
1694
-     * @throws EE_Error
1695
-     * @throws ReflectionException
1696
-     */
1697
-    public function get_checkin_msg(?int $DTT_ID, bool $error = false): string
1698
-    {
1699
-        // let's get the attendee first so we can include the name of the attendee
1700
-        $attendee = $this->get_first_related('Attendee');
1701
-        if ($attendee instanceof EE_Attendee) {
1702
-            if ($error) {
1703
-                return sprintf(
1704
-                    esc_html__("%s's check-in status was not changed.", "event_espresso"),
1705
-                    $attendee->full_name()
1706
-                );
1707
-            }
1708
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1709
-            // what is the status message going to be?
1710
-            switch ($cur_status) {
1711
-                case EE_Checkin::status_checked_never:
1712
-                    return sprintf(
1713
-                        esc_html__("%s has been removed from Check-in records", "event_espresso"),
1714
-                        $attendee->full_name()
1715
-                    );
1716
-                case EE_Checkin::status_checked_in:
1717
-                    return sprintf(esc_html__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1718
-                case EE_Checkin::status_checked_out:
1719
-                    return sprintf(esc_html__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1720
-            }
1721
-        }
1722
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1723
-    }
1724
-
1725
-
1726
-    /**
1727
-     * Returns the related EE_Transaction to this registration
1728
-     *
1729
-     * @return EE_Transaction
1730
-     * @throws EE_Error
1731
-     * @throws EntityNotFoundException
1732
-     * @throws ReflectionException
1733
-     */
1734
-    public function transaction(): EE_Transaction
1735
-    {
1736
-        $transaction = $this->get_first_related('Transaction');
1737
-        if (! $transaction instanceof \EE_Transaction) {
1738
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1739
-        }
1740
-        return $transaction;
1741
-    }
1742
-
1743
-
1744
-    /**
1745
-     *        get Registration Code
1746
-     */
1747
-    public function reg_code()
1748
-    {
1749
-        return $this->get('REG_code');
1750
-    }
1751
-
1752
-
1753
-    /**
1754
-     *        get Transaction ID
1755
-     */
1756
-    public function transaction_ID()
1757
-    {
1758
-        return $this->get('TXN_ID');
1759
-    }
1760
-
1761
-
1762
-    /**
1763
-     * @return int
1764
-     * @throws EE_Error
1765
-     */
1766
-    public function ticket_ID()
1767
-    {
1768
-        return $this->get('TKT_ID');
1769
-    }
1770
-
1771
-
1772
-    /**
1773
-     *        Set Registration Code
1774
-     *
1775
-     * @access    public
1776
-     * @param    string  $REG_code Registration Code
1777
-     * @param    boolean $use_default
1778
-     * @throws EE_Error
1779
-     */
1780
-    public function set_reg_code($REG_code, $use_default = false)
1781
-    {
1782
-        if (empty($REG_code)) {
1783
-            EE_Error::add_error(
1784
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1785
-                __FILE__,
1786
-                __FUNCTION__,
1787
-                __LINE__
1788
-            );
1789
-            return;
1790
-        }
1791
-        if (! $this->reg_code()) {
1792
-            parent::set('REG_code', $REG_code, $use_default);
1793
-        } else {
1794
-            EE_Error::doing_it_wrong(
1795
-                __CLASS__ . '::' . __FUNCTION__,
1796
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1797
-                '4.6.0'
1798
-            );
1799
-        }
1800
-    }
1801
-
1802
-
1803
-    /**
1804
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1805
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1806
-     *    $registration->transaction()->registrations();
1807
-     *
1808
-     * @since 4.5.0
1809
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1810
-     * @throws EE_Error
1811
-     */
1812
-    public function get_all_other_registrations_in_group()
1813
-    {
1814
-        if ($this->group_size() < 2) {
1815
-            return array();
1816
-        }
1817
-
1818
-        $query[0] = array(
1819
-            'TXN_ID' => $this->transaction_ID(),
1820
-            'REG_ID' => array('!=', $this->ID()),
1821
-            'TKT_ID' => $this->ticket_ID(),
1822
-        );
1823
-        /** @var EE_Registration[] $registrations */
1824
-        $registrations = $this->get_model()->get_all($query);
1825
-        return $registrations;
1826
-    }
1827
-
1828
-    /**
1829
-     * Return the link to the admin details for the object.
1830
-     *
1831
-     * @return string
1832
-     * @throws EE_Error
1833
-     */
1834
-    public function get_admin_details_link()
1835
-    {
1836
-        EE_Registry::instance()->load_helper('URL');
1837
-        return EEH_URL::add_query_args_and_nonce(
1838
-            array(
1839
-                'page'    => 'espresso_registrations',
1840
-                'action'  => 'view_registration',
1841
-                '_REG_ID' => $this->ID(),
1842
-            ),
1843
-            admin_url('admin.php')
1844
-        );
1845
-    }
1846
-
1847
-    /**
1848
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1849
-     *
1850
-     * @return string
1851
-     * @throws EE_Error
1852
-     */
1853
-    public function get_admin_edit_link()
1854
-    {
1855
-        return $this->get_admin_details_link();
1856
-    }
1857
-
1858
-    /**
1859
-     * Returns the link to a settings page for the object.
1860
-     *
1861
-     * @return string
1862
-     * @throws EE_Error
1863
-     */
1864
-    public function get_admin_settings_link()
1865
-    {
1866
-        return $this->get_admin_details_link();
1867
-    }
1868
-
1869
-    /**
1870
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1871
-     *
1872
-     * @return string
1873
-     */
1874
-    public function get_admin_overview_link()
1875
-    {
1876
-        EE_Registry::instance()->load_helper('URL');
1877
-        return EEH_URL::add_query_args_and_nonce(
1878
-            array(
1879
-                'page' => 'espresso_registrations',
1880
-            ),
1881
-            admin_url('admin.php')
1882
-        );
1883
-    }
1884
-
1885
-
1886
-    /**
1887
-     * @param array $query_params
1888
-     *
1889
-     * @return \EE_Registration[]
1890
-     * @throws EE_Error
1891
-     */
1892
-    public function payments($query_params = array())
1893
-    {
1894
-        return $this->get_many_related('Payment', $query_params);
1895
-    }
1896
-
1897
-
1898
-    /**
1899
-     * @param array $query_params
1900
-     *
1901
-     * @return \EE_Registration_Payment[]
1902
-     * @throws EE_Error
1903
-     */
1904
-    public function registration_payments($query_params = array())
1905
-    {
1906
-        return $this->get_many_related('Registration_Payment', $query_params);
1907
-    }
1908
-
1909
-
1910
-    /**
1911
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1912
-     * Note: if there are no payments on the registration there will be no payment method returned.
1913
-     *
1914
-     * @return EE_Payment_Method|null
1915
-     */
1916
-    public function payment_method()
1917
-    {
1918
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1919
-    }
1920
-
1921
-
1922
-    /**
1923
-     * @return \EE_Line_Item
1924
-     * @throws EntityNotFoundException
1925
-     * @throws EE_Error
1926
-     */
1927
-    public function ticket_line_item()
1928
-    {
1929
-        $ticket = $this->ticket();
1930
-        $transaction = $this->transaction();
1931
-        $line_item = null;
1932
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1933
-            $transaction->total_line_item(),
1934
-            'Ticket',
1935
-            array($ticket->ID())
1936
-        );
1937
-        foreach ($ticket_line_items as $ticket_line_item) {
1938
-            if (
1939
-                $ticket_line_item instanceof \EE_Line_Item
1940
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1941
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1942
-            ) {
1943
-                $line_item = $ticket_line_item;
1944
-                break;
1945
-            }
1946
-        }
1947
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1948
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1949
-        }
1950
-        return $line_item;
1951
-    }
1952
-
1953
-
1954
-    /**
1955
-     * Soft Deletes this model object.
1956
-     *
1957
-     * @return boolean | int
1958
-     * @throws RuntimeException
1959
-     * @throws EE_Error
1960
-     */
1961
-    public function delete()
1962
-    {
1963
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1964
-            $this->set_status(EEM_Registration::status_id_cancelled);
1965
-        }
1966
-        return parent::delete();
1967
-    }
1968
-
1969
-
1970
-    /**
1971
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1972
-     *
1973
-     * @throws EE_Error
1974
-     * @throws RuntimeException
1975
-     */
1976
-    public function restore()
1977
-    {
1978
-        $previous_status = $this->get_extra_meta(
1979
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1980
-            true,
1981
-            EEM_Registration::status_id_cancelled
1982
-        );
1983
-        if ($previous_status) {
1984
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1985
-            $this->set_status($previous_status);
1986
-        }
1987
-        return parent::restore();
1988
-    }
1989
-
1990
-
1991
-    /**
1992
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1993
-     *
1994
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1995
-     *                                           depending on whether the reg status changes to or from "Approved"
1996
-     * @return boolean whether the Registration status was updated
1997
-     * @throws EE_Error
1998
-     * @throws RuntimeException
1999
-     */
2000
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
2001
-    {
2002
-        $paid = $this->paid();
2003
-        $price = $this->final_price();
2004
-        switch (true) {
2005
-            // overpaid or paid
2006
-            case EEH_Money::compare_floats($paid, $price, '>'):
2007
-            case EEH_Money::compare_floats($paid, $price):
2008
-                $new_status = EEM_Registration::status_id_approved;
2009
-                break;
2010
-            //  underpaid
2011
-            case EEH_Money::compare_floats($paid, $price, '<'):
2012
-                $new_status = EEM_Registration::status_id_pending_payment;
2013
-                break;
2014
-            // uhhh Houston...
2015
-            default:
2016
-                throw new RuntimeException(
2017
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2018
-                );
2019
-        }
2020
-        if ($new_status !== $this->status_ID()) {
2021
-            if ($trigger_set_status_logic) {
2022
-                return $this->set_status($new_status);
2023
-            }
2024
-            parent::set('STS_ID', $new_status);
2025
-            return true;
2026
-        }
2027
-        return false;
2028
-    }
2029
-
2030
-
2031
-    /*************************** DEPRECATED ***************************/
2032
-
2033
-
2034
-    /**
2035
-     * @deprecated
2036
-     * @since     4.7.0
2037
-     * @access    public
2038
-     */
2039
-    public function price_paid()
2040
-    {
2041
-        EE_Error::doing_it_wrong(
2042
-            'EE_Registration::price_paid()',
2043
-            esc_html__(
2044
-                'This method is deprecated, please use EE_Registration::final_price() instead.',
2045
-                'event_espresso'
2046
-            ),
2047
-            '4.7.0'
2048
-        );
2049
-        return $this->final_price();
2050
-    }
2051
-
2052
-
2053
-    /**
2054
-     * @deprecated
2055
-     * @since     4.7.0
2056
-     * @access    public
2057
-     * @param    float $REG_final_price
2058
-     * @throws EE_Error
2059
-     * @throws RuntimeException
2060
-     */
2061
-    public function set_price_paid($REG_final_price = 0.00)
2062
-    {
2063
-        EE_Error::doing_it_wrong(
2064
-            'EE_Registration::set_price_paid()',
2065
-            esc_html__(
2066
-                'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2067
-                'event_espresso'
2068
-            ),
2069
-            '4.7.0'
2070
-        );
2071
-        $this->set_final_price($REG_final_price);
2072
-    }
2073
-
2074
-
2075
-    /**
2076
-     * @deprecated
2077
-     * @since 4.7.0
2078
-     * @return string
2079
-     * @throws EE_Error
2080
-     */
2081
-    public function pretty_price_paid()
2082
-    {
2083
-        EE_Error::doing_it_wrong(
2084
-            'EE_Registration::pretty_price_paid()',
2085
-            esc_html__(
2086
-                'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2087
-                'event_espresso'
2088
-            ),
2089
-            '4.7.0'
2090
-        );
2091
-        return $this->pretty_final_price();
2092
-    }
2093
-
2094
-
2095
-    /**
2096
-     * Gets the primary datetime related to this registration via the related Event to this registration
2097
-     *
2098
-     * @deprecated 4.9.17
2099
-     * @return EE_Datetime
2100
-     * @throws EE_Error
2101
-     * @throws EntityNotFoundException
2102
-     */
2103
-    public function get_related_primary_datetime()
2104
-    {
2105
-        EE_Error::doing_it_wrong(
2106
-            __METHOD__,
2107
-            esc_html__(
2108
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2109
-                'event_espresso'
2110
-            ),
2111
-            '4.9.17',
2112
-            '5.0.0'
2113
-        );
2114
-        return $this->event()->primary_datetime();
2115
-    }
2116
-
2117
-    /**
2118
-     * Returns the contact's name (or "Unknown" if there is no contact.)
2119
-     * @since 4.10.12.p
2120
-     * @return string
2121
-     * @throws EE_Error
2122
-     * @throws InvalidArgumentException
2123
-     * @throws InvalidDataTypeException
2124
-     * @throws InvalidInterfaceException
2125
-     * @throws ReflectionException
2126
-     */
2127
-    public function name()
2128
-    {
2129
-        return $this->attendeeName();
2130
-    }
19
+	/**
20
+	 * Used to reference when a registration has never been checked in.
21
+	 *
22
+	 * @deprecated use \EE_Checkin::status_checked_never instead
23
+	 * @type int
24
+	 */
25
+	const checkin_status_never = 2;
26
+
27
+	/**
28
+	 * Used to reference when a registration has been checked in.
29
+	 *
30
+	 * @deprecated use \EE_Checkin::status_checked_in instead
31
+	 * @type int
32
+	 */
33
+	const checkin_status_in = 1;
34
+
35
+
36
+	/**
37
+	 * Used to reference when a registration has been checked out.
38
+	 *
39
+	 * @deprecated use \EE_Checkin::status_checked_out instead
40
+	 * @type int
41
+	 */
42
+	const checkin_status_out = 0;
43
+
44
+
45
+	/**
46
+	 * extra meta key for tracking reg status os trashed registrations
47
+	 *
48
+	 * @type string
49
+	 */
50
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
51
+
52
+
53
+	/**
54
+	 * extra meta key for tracking if registration has reserved ticket
55
+	 *
56
+	 * @type string
57
+	 */
58
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
59
+
60
+
61
+	/**
62
+	 * @param array  $props_n_values          incoming values
63
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
64
+	 *                                        used.)
65
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
66
+	 *                                        date_format and the second value is the time format
67
+	 * @return EE_Registration
68
+	 * @throws EE_Error
69
+	 */
70
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
71
+	{
72
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
73
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
74
+	}
75
+
76
+
77
+	/**
78
+	 * @param array  $props_n_values  incoming values from the database
79
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
80
+	 *                                the website will be used.
81
+	 * @return EE_Registration
82
+	 */
83
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
84
+	{
85
+		return new self($props_n_values, true, $timezone);
86
+	}
87
+
88
+
89
+	/**
90
+	 *        Set Event ID
91
+	 *
92
+	 * @param        int $EVT_ID Event ID
93
+	 * @throws EE_Error
94
+	 * @throws RuntimeException
95
+	 */
96
+	public function set_event($EVT_ID = 0)
97
+	{
98
+		$this->set('EVT_ID', $EVT_ID);
99
+	}
100
+
101
+
102
+	/**
103
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
104
+	 * be routed to internal methods
105
+	 *
106
+	 * @param string $field_name
107
+	 * @param mixed  $field_value
108
+	 * @param bool   $use_default
109
+	 * @throws EE_Error
110
+	 * @throws EntityNotFoundException
111
+	 * @throws InvalidArgumentException
112
+	 * @throws InvalidDataTypeException
113
+	 * @throws InvalidInterfaceException
114
+	 * @throws ReflectionException
115
+	 * @throws RuntimeException
116
+	 */
117
+	public function set($field_name, $field_value, $use_default = false)
118
+	{
119
+		switch ($field_name) {
120
+			case 'REG_code':
121
+				if (! empty($field_value) && $this->reg_code() === null) {
122
+					$this->set_reg_code($field_value, $use_default);
123
+				}
124
+				break;
125
+			case 'STS_ID':
126
+				$this->set_status($field_value, $use_default);
127
+				break;
128
+			default:
129
+				parent::set($field_name, $field_value, $use_default);
130
+		}
131
+	}
132
+
133
+
134
+	/**
135
+	 * Set Status ID
136
+	 * updates the registration status and ALSO...
137
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
138
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
139
+	 *
140
+	 * @param string                $new_STS_ID
141
+	 * @param boolean               $use_default
142
+	 * @param ContextInterface|null $context
143
+	 * @return bool
144
+	 * @throws DomainException
145
+	 * @throws EE_Error
146
+	 * @throws EntityNotFoundException
147
+	 * @throws InvalidArgumentException
148
+	 * @throws InvalidDataTypeException
149
+	 * @throws InvalidInterfaceException
150
+	 * @throws ReflectionException
151
+	 * @throws RuntimeException
152
+	 * @throws UnexpectedEntityException
153
+	 */
154
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
155
+	{
156
+		// get current REG_Status
157
+		$old_STS_ID = $this->status_ID();
158
+		// if status has changed
159
+		if (
160
+			$old_STS_ID !== $new_STS_ID // and that status has actually changed
161
+			&& ! empty($old_STS_ID) // and that old status is actually set
162
+			&& ! empty($new_STS_ID) // as well as the new status
163
+			&& $this->ID() // ensure registration is in the db
164
+		) {
165
+			// update internal status first
166
+			parent::set('STS_ID', $new_STS_ID, $use_default);
167
+			// THEN handle other changes that occur when reg status changes
168
+			// TO approved
169
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
+				// reserve a space by incrementing ticket and datetime sold values
171
+				$this->reserveRegistrationSpace();
172
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
+				// OR FROM  approved
174
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
+				// release a space by decrementing ticket and datetime sold values
176
+				$this->releaseRegistrationSpace();
177
+				do_action(
178
+					'AHEE__EE_Registration__set_status__from_approved',
179
+					$this,
180
+					$old_STS_ID,
181
+					$new_STS_ID,
182
+					$context
183
+				);
184
+			}
185
+			// update status
186
+			parent::set('STS_ID', $new_STS_ID, $use_default);
187
+			$this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
+			if ($this->statusChangeUpdatesTransaction($context)) {
189
+				$this->updateTransactionAfterStatusChange();
190
+			}
191
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
+			return true;
193
+		}
194
+		// even though the old value matches the new value, it's still good to
195
+		// allow the parent set method to have a say
196
+		parent::set('STS_ID', $new_STS_ID, $use_default);
197
+		return true;
198
+	}
199
+
200
+
201
+	/**
202
+	 * update REGs and TXN when cancelled or declined registrations involved
203
+	 *
204
+	 * @param string                $new_STS_ID
205
+	 * @param string                $old_STS_ID
206
+	 * @param ContextInterface|null $context
207
+	 * @throws EE_Error
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 * @throws ReflectionException
212
+	 * @throws RuntimeException
213
+	 */
214
+	private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
+	{
216
+		// these reg statuses should not be considered in any calculations involving monies owing
217
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
+		// true if registration has been cancelled or declined
219
+		$this->updateIfCanceled(
220
+			$closed_reg_statuses,
221
+			$new_STS_ID,
222
+			$old_STS_ID,
223
+			$context
224
+		);
225
+		$this->updateIfReinstated(
226
+			$closed_reg_statuses,
227
+			$new_STS_ID,
228
+			$old_STS_ID,
229
+			$context
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 * update REGs and TXN when cancelled or declined registrations involved
236
+	 *
237
+	 * @param array                 $closed_reg_statuses
238
+	 * @param string                $new_STS_ID
239
+	 * @param string                $old_STS_ID
240
+	 * @param ContextInterface|null $context
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws InvalidDataTypeException
244
+	 * @throws InvalidInterfaceException
245
+	 * @throws ReflectionException
246
+	 * @throws RuntimeException
247
+	 */
248
+	private function updateIfCanceled(
249
+		array $closed_reg_statuses,
250
+		$new_STS_ID,
251
+		$old_STS_ID,
252
+		ContextInterface $context = null
253
+	) {
254
+		// true if registration has been cancelled or declined
255
+		if (
256
+			in_array($new_STS_ID, $closed_reg_statuses, true)
257
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
258
+		) {
259
+			/** @type EE_Registration_Processor $registration_processor */
260
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
261
+			/** @type EE_Transaction_Processor $transaction_processor */
262
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
263
+			// cancelled or declined registration
264
+			$registration_processor->update_registration_after_being_canceled_or_declined(
265
+				$this,
266
+				$closed_reg_statuses
267
+			);
268
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
269
+				$this,
270
+				$closed_reg_statuses,
271
+				false
272
+			);
273
+			do_action(
274
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
275
+				$this,
276
+				$old_STS_ID,
277
+				$new_STS_ID,
278
+				$context
279
+			);
280
+			return;
281
+		}
282
+	}
283
+
284
+
285
+	/**
286
+	 * update REGs and TXN when cancelled or declined registrations involved
287
+	 *
288
+	 * @param array                 $closed_reg_statuses
289
+	 * @param string                $new_STS_ID
290
+	 * @param string                $old_STS_ID
291
+	 * @param ContextInterface|null $context
292
+	 * @throws EE_Error
293
+	 * @throws InvalidArgumentException
294
+	 * @throws InvalidDataTypeException
295
+	 * @throws InvalidInterfaceException
296
+	 * @throws ReflectionException
297
+	 */
298
+	private function updateIfReinstated(
299
+		array $closed_reg_statuses,
300
+		$new_STS_ID,
301
+		$old_STS_ID,
302
+		ContextInterface $context = null
303
+	) {
304
+		// true if reinstating cancelled or declined registration
305
+		if (
306
+			in_array($old_STS_ID, $closed_reg_statuses, true)
307
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
308
+		) {
309
+			/** @type EE_Registration_Processor $registration_processor */
310
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
311
+			/** @type EE_Transaction_Processor $transaction_processor */
312
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
313
+			// reinstating cancelled or declined registration
314
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
315
+				$this,
316
+				$closed_reg_statuses
317
+			);
318
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
319
+				$this,
320
+				$closed_reg_statuses,
321
+				false
322
+			);
323
+			do_action(
324
+				'AHEE__EE_Registration__set_status__after_reinstated',
325
+				$this,
326
+				$old_STS_ID,
327
+				$new_STS_ID,
328
+				$context
329
+			);
330
+		}
331
+	}
332
+
333
+
334
+	/**
335
+	 * @param ContextInterface|null $context
336
+	 * @return bool
337
+	 */
338
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
339
+	{
340
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
341
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
342
+			array('spco_reg_step_attendee_information_process_registrations'),
343
+			$context,
344
+			$this
345
+		);
346
+		return ! (
347
+			$context instanceof ContextInterface
348
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
349
+		);
350
+	}
351
+
352
+
353
+	/**
354
+	 * @throws EE_Error
355
+	 * @throws EntityNotFoundException
356
+	 * @throws InvalidArgumentException
357
+	 * @throws InvalidDataTypeException
358
+	 * @throws InvalidInterfaceException
359
+	 * @throws ReflectionException
360
+	 * @throws RuntimeException
361
+	 */
362
+	private function updateTransactionAfterStatusChange()
363
+	{
364
+		/** @type EE_Transaction_Payments $transaction_payments */
365
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
366
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
367
+		$this->transaction()->update_status_based_on_total_paid(true);
368
+	}
369
+
370
+
371
+	/**
372
+	 *        get Status ID
373
+	 */
374
+	public function status_ID()
375
+	{
376
+		return $this->get('STS_ID');
377
+	}
378
+
379
+
380
+	/**
381
+	 * Gets the ticket this registration is for
382
+	 *
383
+	 * @param boolean $include_archived whether to include archived tickets or not.
384
+	 *
385
+	 * @return EE_Ticket|EE_Base_Class
386
+	 * @throws EE_Error
387
+	 */
388
+	public function ticket($include_archived = true)
389
+	{
390
+		$query_params = array();
391
+		if ($include_archived) {
392
+			$query_params['default_where_conditions'] = 'none';
393
+		}
394
+		return $this->get_first_related('Ticket', $query_params);
395
+	}
396
+
397
+
398
+	/**
399
+	 * Gets the event this registration is for
400
+	 *
401
+	 * @return EE_Event
402
+	 * @throws EE_Error
403
+	 * @throws EntityNotFoundException
404
+	 */
405
+	public function event()
406
+	{
407
+		$event = $this->get_first_related('Event');
408
+		if (! $event instanceof \EE_Event) {
409
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
410
+		}
411
+		return $event;
412
+	}
413
+
414
+
415
+	/**
416
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
417
+	 * with the author of the event this registration is for.
418
+	 *
419
+	 * @since 4.5.0
420
+	 * @return int
421
+	 * @throws EE_Error
422
+	 * @throws EntityNotFoundException
423
+	 */
424
+	public function wp_user()
425
+	{
426
+		$event = $this->event();
427
+		if ($event instanceof EE_Event) {
428
+			return $event->wp_user();
429
+		}
430
+		return 0;
431
+	}
432
+
433
+
434
+	/**
435
+	 * increments this registration's related ticket sold and corresponding datetime sold values
436
+	 *
437
+	 * @return void
438
+	 * @throws DomainException
439
+	 * @throws EE_Error
440
+	 * @throws EntityNotFoundException
441
+	 * @throws InvalidArgumentException
442
+	 * @throws InvalidDataTypeException
443
+	 * @throws InvalidInterfaceException
444
+	 * @throws ReflectionException
445
+	 * @throws UnexpectedEntityException
446
+	 */
447
+	private function reserveRegistrationSpace()
448
+	{
449
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
450
+		// so stop tracking that this reg has a ticket reserved
451
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
452
+		$ticket = $this->ticket();
453
+		$ticket->increaseSold();
454
+		// possibly set event status to sold out
455
+		$this->event()->perform_sold_out_status_check();
456
+	}
457
+
458
+
459
+	/**
460
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
461
+	 *
462
+	 * @return void
463
+	 * @throws DomainException
464
+	 * @throws EE_Error
465
+	 * @throws EntityNotFoundException
466
+	 * @throws InvalidArgumentException
467
+	 * @throws InvalidDataTypeException
468
+	 * @throws InvalidInterfaceException
469
+	 * @throws ReflectionException
470
+	 * @throws UnexpectedEntityException
471
+	 */
472
+	private function releaseRegistrationSpace()
473
+	{
474
+		$ticket = $this->ticket();
475
+		$ticket->decreaseSold();
476
+		// possibly change event status from sold out back to previous status
477
+		$this->event()->perform_sold_out_status_check();
478
+	}
479
+
480
+
481
+	/**
482
+	 * tracks this registration's ticket reservation in extra meta
483
+	 * and can increment related ticket reserved and corresponding datetime reserved values
484
+	 *
485
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
486
+	 * @return void
487
+	 * @throws EE_Error
488
+	 * @throws InvalidArgumentException
489
+	 * @throws InvalidDataTypeException
490
+	 * @throws InvalidInterfaceException
491
+	 * @throws ReflectionException
492
+	 */
493
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
494
+	{
495
+		// only reserve ticket if space is not currently reserved
496
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
497
+			$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
498
+			// IMPORTANT !!!
499
+			// although checking $update_ticket first would be more efficient,
500
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
501
+			if (
502
+				$this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
503
+				&& $update_ticket
504
+			) {
505
+				$ticket = $this->ticket();
506
+				$ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
507
+				$ticket->save();
508
+			}
509
+		}
510
+	}
511
+
512
+
513
+	/**
514
+	 * stops tracking this registration's ticket reservation in extra meta
515
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
516
+	 *
517
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
518
+	 * @return void
519
+	 * @throws EE_Error
520
+	 * @throws InvalidArgumentException
521
+	 * @throws InvalidDataTypeException
522
+	 * @throws InvalidInterfaceException
523
+	 * @throws ReflectionException
524
+	 */
525
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
526
+	{
527
+		// only release ticket if space is currently reserved
528
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
529
+			$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
530
+			// IMPORTANT !!!
531
+			// although checking $update_ticket first would be more efficient,
532
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
533
+			if (
534
+				$this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
535
+				&& $update_ticket
536
+			) {
537
+				$ticket = $this->ticket();
538
+				$ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
539
+			}
540
+		}
541
+	}
542
+
543
+
544
+	/**
545
+	 * Set Attendee ID
546
+	 *
547
+	 * @param        int $ATT_ID Attendee ID
548
+	 * @throws EE_Error
549
+	 * @throws RuntimeException
550
+	 */
551
+	public function set_attendee_id($ATT_ID = 0)
552
+	{
553
+		$this->set('ATT_ID', $ATT_ID);
554
+	}
555
+
556
+
557
+	/**
558
+	 *        Set Transaction ID
559
+	 *
560
+	 * @param        int $TXN_ID Transaction ID
561
+	 * @throws EE_Error
562
+	 * @throws RuntimeException
563
+	 */
564
+	public function set_transaction_id($TXN_ID = 0)
565
+	{
566
+		$this->set('TXN_ID', $TXN_ID);
567
+	}
568
+
569
+
570
+	/**
571
+	 *        Set Session
572
+	 *
573
+	 * @param    string $REG_session PHP Session ID
574
+	 * @throws EE_Error
575
+	 * @throws RuntimeException
576
+	 */
577
+	public function set_session($REG_session = '')
578
+	{
579
+		$this->set('REG_session', $REG_session);
580
+	}
581
+
582
+
583
+	/**
584
+	 *        Set Registration URL Link
585
+	 *
586
+	 * @param    string $REG_url_link Registration URL Link
587
+	 * @throws EE_Error
588
+	 * @throws RuntimeException
589
+	 */
590
+	public function set_reg_url_link($REG_url_link = '')
591
+	{
592
+		$this->set('REG_url_link', $REG_url_link);
593
+	}
594
+
595
+
596
+	/**
597
+	 *        Set Attendee Counter
598
+	 *
599
+	 * @param        int $REG_count Primary Attendee
600
+	 * @throws EE_Error
601
+	 * @throws RuntimeException
602
+	 */
603
+	public function set_count($REG_count = 1)
604
+	{
605
+		$this->set('REG_count', $REG_count);
606
+	}
607
+
608
+
609
+	/**
610
+	 *        Set Group Size
611
+	 *
612
+	 * @param        boolean $REG_group_size Group Registration
613
+	 * @throws EE_Error
614
+	 * @throws RuntimeException
615
+	 */
616
+	public function set_group_size($REG_group_size = false)
617
+	{
618
+		$this->set('REG_group_size', $REG_group_size);
619
+	}
620
+
621
+
622
+	/**
623
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
624
+	 *    EEM_Registration::status_id_not_approved
625
+	 *
626
+	 * @return        boolean
627
+	 */
628
+	public function is_not_approved()
629
+	{
630
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
631
+	}
632
+
633
+
634
+	/**
635
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
636
+	 *    EEM_Registration::status_id_pending_payment
637
+	 *
638
+	 * @return        boolean
639
+	 */
640
+	public function is_pending_payment()
641
+	{
642
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
643
+	}
644
+
645
+
646
+	/**
647
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
648
+	 *
649
+	 * @return        boolean
650
+	 */
651
+	public function is_approved()
652
+	{
653
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
654
+	}
655
+
656
+
657
+	/**
658
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
659
+	 *
660
+	 * @return        boolean
661
+	 */
662
+	public function is_cancelled()
663
+	{
664
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
665
+	}
666
+
667
+
668
+	/**
669
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
670
+	 *
671
+	 * @return        boolean
672
+	 */
673
+	public function is_declined()
674
+	{
675
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
676
+	}
677
+
678
+
679
+	/**
680
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
681
+	 *    EEM_Registration::status_id_incomplete
682
+	 *
683
+	 * @return        boolean
684
+	 */
685
+	public function is_incomplete()
686
+	{
687
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
688
+	}
689
+
690
+
691
+	/**
692
+	 *        Set Registration Date
693
+	 *
694
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
695
+	 *                                                 Date
696
+	 * @throws EE_Error
697
+	 * @throws RuntimeException
698
+	 */
699
+	public function set_reg_date($REG_date = false)
700
+	{
701
+		$this->set('REG_date', $REG_date);
702
+	}
703
+
704
+
705
+	/**
706
+	 *    Set final price owing for this registration after all ticket/price modifications
707
+	 *
708
+	 * @access    public
709
+	 * @param    float $REG_final_price
710
+	 * @throws EE_Error
711
+	 * @throws RuntimeException
712
+	 */
713
+	public function set_final_price($REG_final_price = 0.00)
714
+	{
715
+		$this->set('REG_final_price', $REG_final_price);
716
+	}
717
+
718
+
719
+	/**
720
+	 *    Set amount paid towards this registration's final price
721
+	 *
722
+	 * @access    public
723
+	 * @param    float $REG_paid
724
+	 * @throws EE_Error
725
+	 * @throws RuntimeException
726
+	 */
727
+	public function set_paid($REG_paid = 0.00)
728
+	{
729
+		$this->set('REG_paid', $REG_paid);
730
+	}
731
+
732
+
733
+	/**
734
+	 *        Attendee Is Going
735
+	 *
736
+	 * @param        boolean $REG_att_is_going Attendee Is Going
737
+	 * @throws EE_Error
738
+	 * @throws RuntimeException
739
+	 */
740
+	public function set_att_is_going($REG_att_is_going = false)
741
+	{
742
+		$this->set('REG_att_is_going', $REG_att_is_going);
743
+	}
744
+
745
+
746
+	/**
747
+	 * Gets the related attendee
748
+	 *
749
+	 * @return EE_Attendee
750
+	 * @throws EE_Error
751
+	 */
752
+	public function attendee()
753
+	{
754
+		return $this->get_first_related('Attendee');
755
+	}
756
+
757
+	/**
758
+	 * Gets the name of the attendee.
759
+	 * @since 4.10.12.p
760
+	 * @param bool $apply_html_entities set to true if you want to use HTML entities.
761
+	 * @return string
762
+	 * @throws EE_Error
763
+	 * @throws InvalidArgumentException
764
+	 * @throws InvalidDataTypeException
765
+	 * @throws InvalidInterfaceException
766
+	 * @throws ReflectionException
767
+	 */
768
+	public function attendeeName($apply_html_entities = false)
769
+	{
770
+		$attendee = $this->get_first_related('Attendee');
771
+		if ($attendee instanceof EE_Attendee) {
772
+			$attendee_name = $attendee->full_name($apply_html_entities);
773
+		} else {
774
+			$attendee_name = esc_html__('Unknown', 'event_espresso');
775
+		}
776
+		return $attendee_name;
777
+	}
778
+
779
+
780
+	/**
781
+	 *        get Event ID
782
+	 */
783
+	public function event_ID()
784
+	{
785
+		return $this->get('EVT_ID');
786
+	}
787
+
788
+
789
+	/**
790
+	 *        get Event ID
791
+	 */
792
+	public function event_name()
793
+	{
794
+		$event = $this->event_obj();
795
+		if ($event) {
796
+			return $event->name();
797
+		} else {
798
+			return null;
799
+		}
800
+	}
801
+
802
+
803
+	/**
804
+	 * Fetches the event this registration is for
805
+	 *
806
+	 * @return EE_Event
807
+	 * @throws EE_Error
808
+	 */
809
+	public function event_obj()
810
+	{
811
+		return $this->get_first_related('Event');
812
+	}
813
+
814
+
815
+	/**
816
+	 *        get Attendee ID
817
+	 */
818
+	public function attendee_ID()
819
+	{
820
+		return $this->get('ATT_ID');
821
+	}
822
+
823
+
824
+	/**
825
+	 *        get PHP Session ID
826
+	 */
827
+	public function session_ID()
828
+	{
829
+		return $this->get('REG_session');
830
+	}
831
+
832
+
833
+	/**
834
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
835
+	 *
836
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
837
+	 * @return string
838
+	 */
839
+	public function receipt_url($messenger = 'html')
840
+	{
841
+
842
+		/**
843
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
844
+		 * already in use on old system.  If there is then we just return the standard url for it.
845
+		 *
846
+		 * @since 4.5.0
847
+		 */
848
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
849
+		$has_custom = EEH_Template::locate_template(
850
+			$template_relative_path,
851
+			array(),
852
+			true,
853
+			true,
854
+			true
855
+		);
856
+
857
+		if ($has_custom) {
858
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
859
+		}
860
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
861
+	}
862
+
863
+
864
+	/**
865
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
866
+	 *
867
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
868
+	 * @return string
869
+	 * @throws EE_Error
870
+	 */
871
+	public function invoice_url($messenger = 'html')
872
+	{
873
+		/**
874
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
875
+		 * already in use on old system.  If there is then we just return the standard url for it.
876
+		 *
877
+		 * @since 4.5.0
878
+		 */
879
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
880
+		$has_custom = EEH_Template::locate_template(
881
+			$template_relative_path,
882
+			array(),
883
+			true,
884
+			true,
885
+			true
886
+		);
887
+
888
+		if ($has_custom) {
889
+			if ($messenger == 'html') {
890
+				return $this->invoice_url('launch');
891
+			}
892
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
893
+
894
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
895
+			if ($messenger == 'html') {
896
+				$query_args['html'] = true;
897
+			}
898
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
899
+		}
900
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
901
+	}
902
+
903
+
904
+	/**
905
+	 * get Registration URL Link
906
+	 *
907
+	 * @access public
908
+	 * @return string
909
+	 * @throws EE_Error
910
+	 */
911
+	public function reg_url_link()
912
+	{
913
+		return (string) $this->get('REG_url_link');
914
+	}
915
+
916
+
917
+	/**
918
+	 * Echoes out invoice_url()
919
+	 *
920
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
921
+	 * @return void
922
+	 * @throws EE_Error
923
+	 */
924
+	public function e_invoice_url($type = 'launch')
925
+	{
926
+		echo esc_url_raw($this->invoice_url($type));
927
+	}
928
+
929
+
930
+	/**
931
+	 * Echoes out payment_overview_url
932
+	 */
933
+	public function e_payment_overview_url()
934
+	{
935
+		echo esc_url_raw($this->payment_overview_url());
936
+	}
937
+
938
+
939
+	/**
940
+	 * Gets the URL for the checkout payment options reg step
941
+	 * with this registration's REG_url_link added as a query parameter
942
+	 *
943
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
944
+	 *                            payment overview url.
945
+	 * @return string
946
+	 * @throws InvalidInterfaceException
947
+	 * @throws InvalidDataTypeException
948
+	 * @throws EE_Error
949
+	 * @throws InvalidArgumentException
950
+	 */
951
+	public function payment_overview_url($clear_session = false)
952
+	{
953
+		return add_query_arg(
954
+			(array) apply_filters(
955
+				'FHEE__EE_Registration__payment_overview_url__query_args',
956
+				array(
957
+					'e_reg_url_link' => $this->reg_url_link(),
958
+					'step'           => 'payment_options',
959
+					'revisit'        => true,
960
+					'clear_session'  => (bool) $clear_session,
961
+				),
962
+				$this
963
+			),
964
+			EE_Registry::instance()->CFG->core->reg_page_url()
965
+		);
966
+	}
967
+
968
+
969
+	/**
970
+	 * Gets the URL for the checkout attendee information reg step
971
+	 * with this registration's REG_url_link added as a query parameter
972
+	 *
973
+	 * @return string
974
+	 * @throws InvalidInterfaceException
975
+	 * @throws InvalidDataTypeException
976
+	 * @throws EE_Error
977
+	 * @throws InvalidArgumentException
978
+	 */
979
+	public function edit_attendee_information_url()
980
+	{
981
+		return add_query_arg(
982
+			(array) apply_filters(
983
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
984
+				array(
985
+					'e_reg_url_link' => $this->reg_url_link(),
986
+					'step'           => 'attendee_information',
987
+					'revisit'        => true,
988
+				),
989
+				$this
990
+			),
991
+			EE_Registry::instance()->CFG->core->reg_page_url()
992
+		);
993
+	}
994
+
995
+
996
+	/**
997
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
998
+	 *
999
+	 * @return string
1000
+	 * @throws EE_Error
1001
+	 */
1002
+	public function get_admin_edit_url()
1003
+	{
1004
+		return EEH_URL::add_query_args_and_nonce(
1005
+			array(
1006
+				'page'    => 'espresso_registrations',
1007
+				'action'  => 'view_registration',
1008
+				'_REG_ID' => $this->ID(),
1009
+			),
1010
+			admin_url('admin.php')
1011
+		);
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 *    is_primary_registrant?
1017
+	 */
1018
+	public function is_primary_registrant()
1019
+	{
1020
+		return $this->get('REG_count') === 1 ? true : false;
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 * This returns the primary registration object for this registration group (which may be this object).
1026
+	 *
1027
+	 * @return EE_Registration
1028
+	 * @throws EE_Error
1029
+	 */
1030
+	public function get_primary_registration()
1031
+	{
1032
+		if ($this->is_primary_registrant()) {
1033
+			return $this;
1034
+		}
1035
+
1036
+		// k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1037
+		/** @var EE_Registration $primary_registrant */
1038
+		$primary_registrant = EEM_Registration::instance()->get_one(
1039
+			array(
1040
+				array(
1041
+					'TXN_ID'    => $this->transaction_ID(),
1042
+					'REG_count' => 1,
1043
+				),
1044
+			)
1045
+		);
1046
+		return $primary_registrant;
1047
+	}
1048
+
1049
+
1050
+	/**
1051
+	 *        get  Attendee Number
1052
+	 *
1053
+	 * @access        public
1054
+	 */
1055
+	public function count()
1056
+	{
1057
+		return $this->get('REG_count');
1058
+	}
1059
+
1060
+
1061
+	/**
1062
+	 *        get Group Size
1063
+	 */
1064
+	public function group_size()
1065
+	{
1066
+		return $this->get('REG_group_size');
1067
+	}
1068
+
1069
+
1070
+	/**
1071
+	 *        get Registration Date
1072
+	 */
1073
+	public function date()
1074
+	{
1075
+		return $this->get('REG_date');
1076
+	}
1077
+
1078
+
1079
+	/**
1080
+	 * gets a pretty date
1081
+	 *
1082
+	 * @param string $date_format
1083
+	 * @param string $time_format
1084
+	 * @return string
1085
+	 * @throws EE_Error
1086
+	 */
1087
+	public function pretty_date($date_format = null, $time_format = null)
1088
+	{
1089
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 * final_price
1095
+	 * the registration's share of the transaction total, so that the
1096
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1097
+	 *
1098
+	 * @return float
1099
+	 * @throws EE_Error
1100
+	 */
1101
+	public function final_price()
1102
+	{
1103
+		return $this->get('REG_final_price');
1104
+	}
1105
+
1106
+
1107
+	/**
1108
+	 * pretty_final_price
1109
+	 *  final price as formatted string, with correct decimal places and currency symbol
1110
+	 *
1111
+	 * @return string
1112
+	 * @throws EE_Error
1113
+	 */
1114
+	public function pretty_final_price()
1115
+	{
1116
+		return $this->get_pretty('REG_final_price');
1117
+	}
1118
+
1119
+
1120
+	/**
1121
+	 * get paid (yeah)
1122
+	 *
1123
+	 * @return float
1124
+	 * @throws EE_Error
1125
+	 */
1126
+	public function paid()
1127
+	{
1128
+		return $this->get('REG_paid');
1129
+	}
1130
+
1131
+
1132
+	/**
1133
+	 * pretty_paid
1134
+	 *
1135
+	 * @return float
1136
+	 * @throws EE_Error
1137
+	 */
1138
+	public function pretty_paid()
1139
+	{
1140
+		return $this->get_pretty('REG_paid');
1141
+	}
1142
+
1143
+
1144
+	/**
1145
+	 * owes_monies_and_can_pay
1146
+	 * whether or not this registration has monies owing and it's' status allows payment
1147
+	 *
1148
+	 * @param array $requires_payment
1149
+	 * @return bool
1150
+	 * @throws EE_Error
1151
+	 */
1152
+	public function owes_monies_and_can_pay($requires_payment = array())
1153
+	{
1154
+		// these reg statuses require payment (if event is not free)
1155
+		$requires_payment = ! empty($requires_payment)
1156
+			? $requires_payment
1157
+			: EEM_Registration::reg_statuses_that_allow_payment();
1158
+		if (
1159
+			in_array($this->status_ID(), $requires_payment) &&
1160
+			$this->final_price() != 0 &&
1161
+			$this->final_price() != $this->paid()
1162
+		) {
1163
+			return true;
1164
+		} else {
1165
+			return false;
1166
+		}
1167
+	}
1168
+
1169
+
1170
+	/**
1171
+	 * Prints out the return value of $this->pretty_status()
1172
+	 *
1173
+	 * @param bool $show_icons
1174
+	 * @return void
1175
+	 * @throws EE_Error
1176
+	 */
1177
+	public function e_pretty_status($show_icons = false)
1178
+	{
1179
+		echo wp_kses($this->pretty_status($show_icons), AllowedTags::getAllowedTags());
1180
+	}
1181
+
1182
+
1183
+	/**
1184
+	 * Returns a nice version of the status for displaying to customers
1185
+	 *
1186
+	 * @param bool $show_icons
1187
+	 * @return string
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	public function pretty_status($show_icons = false)
1191
+	{
1192
+		$status = EEM_Status::instance()->localized_status(
1193
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1194
+			false,
1195
+			'sentence'
1196
+		);
1197
+		$icon = '';
1198
+		switch ($this->status_ID()) {
1199
+			case EEM_Registration::status_id_approved:
1200
+				$icon = $show_icons
1201
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1202
+					: '';
1203
+				break;
1204
+			case EEM_Registration::status_id_pending_payment:
1205
+				$icon = $show_icons
1206
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1207
+					: '';
1208
+				break;
1209
+			case EEM_Registration::status_id_not_approved:
1210
+				$icon = $show_icons
1211
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1212
+					: '';
1213
+				break;
1214
+			case EEM_Registration::status_id_cancelled:
1215
+				$icon = $show_icons
1216
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1217
+					: '';
1218
+				break;
1219
+			case EEM_Registration::status_id_incomplete:
1220
+				$icon = $show_icons
1221
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1222
+					: '';
1223
+				break;
1224
+			case EEM_Registration::status_id_declined:
1225
+				$icon = $show_icons
1226
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1227
+					: '';
1228
+				break;
1229
+			case EEM_Registration::status_id_wait_list:
1230
+				$icon = $show_icons
1231
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1232
+					: '';
1233
+				break;
1234
+		}
1235
+		return $icon . $status[ $this->status_ID() ];
1236
+	}
1237
+
1238
+
1239
+	/**
1240
+	 *        get Attendee Is Going
1241
+	 */
1242
+	public function att_is_going()
1243
+	{
1244
+		return $this->get('REG_att_is_going');
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * Gets related answers
1250
+	 *
1251
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1252
+	 * @return EE_Answer[]
1253
+	 * @throws EE_Error
1254
+	 */
1255
+	public function answers($query_params = null)
1256
+	{
1257
+		return $this->get_many_related('Answer', $query_params);
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * Gets the registration's answer value to the specified question
1263
+	 * (either the question's ID or a question object)
1264
+	 *
1265
+	 * @param EE_Question|int $question
1266
+	 * @param bool            $pretty_value
1267
+	 * @return array|string if pretty_value= true, the result will always be a string
1268
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1269
+	 * will convert it into some kind of string)
1270
+	 * @throws EE_Error
1271
+	 */
1272
+	public function answer_value_to_question($question, $pretty_value = true)
1273
+	{
1274
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1275
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * question_groups
1281
+	 * returns an array of EE_Question_Group objects for this registration
1282
+	 *
1283
+	 * @return EE_Question_Group[]
1284
+	 * @throws EE_Error
1285
+	 * @throws InvalidArgumentException
1286
+	 * @throws InvalidDataTypeException
1287
+	 * @throws InvalidInterfaceException
1288
+	 * @throws ReflectionException
1289
+	 */
1290
+	public function question_groups()
1291
+	{
1292
+		return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * count_question_groups
1298
+	 * returns a count of the number of EE_Question_Group objects for this registration
1299
+	 *
1300
+	 * @return int
1301
+	 * @throws EE_Error
1302
+	 * @throws EntityNotFoundException
1303
+	 * @throws InvalidArgumentException
1304
+	 * @throws InvalidDataTypeException
1305
+	 * @throws InvalidInterfaceException
1306
+	 * @throws ReflectionException
1307
+	 */
1308
+	public function count_question_groups()
1309
+	{
1310
+		return EEM_Event::instance()->count_related(
1311
+			$this->event_ID(),
1312
+			'Question_Group',
1313
+			[
1314
+				[
1315
+					'Event_Question_Group.'
1316
+					. EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1317
+				]
1318
+			]
1319
+		);
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * Returns the registration date in the 'standard' string format
1325
+	 * (function may be improved in the future to allow for different formats and timezones)
1326
+	 *
1327
+	 * @return string
1328
+	 * @throws EE_Error
1329
+	 */
1330
+	public function reg_date()
1331
+	{
1332
+		return $this->get_datetime('REG_date');
1333
+	}
1334
+
1335
+
1336
+	/**
1337
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1338
+	 * the ticket this registration purchased, or the datetime they have registered
1339
+	 * to attend)
1340
+	 *
1341
+	 * @return EE_Datetime_Ticket
1342
+	 * @throws EE_Error
1343
+	 */
1344
+	public function datetime_ticket()
1345
+	{
1346
+		return $this->get_first_related('Datetime_Ticket');
1347
+	}
1348
+
1349
+
1350
+	/**
1351
+	 * Sets the registration's datetime_ticket.
1352
+	 *
1353
+	 * @param EE_Datetime_Ticket $datetime_ticket
1354
+	 * @return EE_Datetime_Ticket
1355
+	 * @throws EE_Error
1356
+	 */
1357
+	public function set_datetime_ticket($datetime_ticket)
1358
+	{
1359
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1360
+	}
1361
+
1362
+	/**
1363
+	 * Gets deleted
1364
+	 *
1365
+	 * @return bool
1366
+	 * @throws EE_Error
1367
+	 */
1368
+	public function deleted()
1369
+	{
1370
+		return $this->get('REG_deleted');
1371
+	}
1372
+
1373
+	/**
1374
+	 * Sets deleted
1375
+	 *
1376
+	 * @param boolean $deleted
1377
+	 * @return bool
1378
+	 * @throws EE_Error
1379
+	 * @throws RuntimeException
1380
+	 */
1381
+	public function set_deleted($deleted)
1382
+	{
1383
+		if ($deleted) {
1384
+			$this->delete();
1385
+		} else {
1386
+			$this->restore();
1387
+		}
1388
+	}
1389
+
1390
+
1391
+	/**
1392
+	 * Get the status object of this object
1393
+	 *
1394
+	 * @return EE_Status
1395
+	 * @throws EE_Error
1396
+	 */
1397
+	public function status_obj()
1398
+	{
1399
+		return $this->get_first_related('Status');
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * Returns the number of times this registration has checked into any of the datetimes
1405
+	 * its available for
1406
+	 *
1407
+	 * @return int
1408
+	 * @throws EE_Error
1409
+	 */
1410
+	public function count_checkins()
1411
+	{
1412
+		return $this->get_model()->count_related($this, 'Checkin');
1413
+	}
1414
+
1415
+
1416
+	/**
1417
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1418
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1419
+	 *
1420
+	 * @return int
1421
+	 * @throws EE_Error
1422
+	 */
1423
+	public function count_checkins_not_checkedout()
1424
+	{
1425
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1426
+	}
1427
+
1428
+
1429
+	/**
1430
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1431
+	 *
1432
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1433
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1434
+	 *                                          consider registration status as well as datetime access.
1435
+	 * @return bool
1436
+	 * @throws EE_Error
1437
+	 */
1438
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1439
+	{
1440
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1441
+
1442
+		// first check registration status
1443
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1444
+			return false;
1445
+		}
1446
+		// is there a datetime ticket that matches this dtt_ID?
1447
+		if (
1448
+			! (EEM_Datetime_Ticket::instance()->exists(
1449
+				array(
1450
+				array(
1451
+					'TKT_ID' => $this->get('TKT_ID'),
1452
+					'DTT_ID' => $DTT_ID,
1453
+				),
1454
+				)
1455
+			))
1456
+		) {
1457
+			return false;
1458
+		}
1459
+
1460
+		// final check is against TKT_uses
1461
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1467
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1468
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1469
+	 * then return false.  Otherwise return true.
1470
+	 *
1471
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1472
+	 * @return bool true means can checkin.  false means cannot checkin.
1473
+	 * @throws EE_Error
1474
+	 */
1475
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1476
+	{
1477
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1478
+
1479
+		if (! $DTT_ID) {
1480
+			return false;
1481
+		}
1482
+
1483
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1484
+
1485
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1486
+		// check-in or not.
1487
+		if (! $max_uses || $max_uses === EE_INF) {
1488
+			return true;
1489
+		}
1490
+
1491
+		// does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1492
+		// go ahead and toggle.
1493
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1494
+			return true;
1495
+		}
1496
+
1497
+		// made it here so the last check is whether the number of checkins per unique datetime on this registration
1498
+		// disallows further check-ins.
1499
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1500
+			array(
1501
+				array(
1502
+					'REG_ID' => $this->ID(),
1503
+					'CHK_in' => true,
1504
+				),
1505
+			),
1506
+			'DTT_ID',
1507
+			true
1508
+		);
1509
+		// checkins have already reached their max number of uses
1510
+		// so registrant can NOT checkin
1511
+		if ($count_unique_dtt_checkins >= $max_uses) {
1512
+			EE_Error::add_error(
1513
+				esc_html__(
1514
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1515
+					'event_espresso'
1516
+				),
1517
+				__FILE__,
1518
+				__FUNCTION__,
1519
+				__LINE__
1520
+			);
1521
+			return false;
1522
+		}
1523
+		return true;
1524
+	}
1525
+
1526
+
1527
+	/**
1528
+	 * toggle Check-in status for this registration
1529
+	 * Check-ins are toggled in the following order:
1530
+	 * never checked in -> checked in
1531
+	 * checked in -> checked out
1532
+	 * checked out -> checked in
1533
+	 *
1534
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1535
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1536
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1537
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1538
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1539
+	 * @throws EE_Error
1540
+	 */
1541
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1542
+	{
1543
+		if (empty($DTT_ID)) {
1544
+			$datetime = $this->get_latest_related_datetime();
1545
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1546
+			// verify the registration can checkin for the given DTT_ID
1547
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1548
+			EE_Error::add_error(
1549
+				sprintf(
1550
+					esc_html__(
1551
+						'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',
1552
+						'event_espresso'
1553
+					),
1554
+					$this->ID(),
1555
+					$DTT_ID
1556
+				),
1557
+				__FILE__,
1558
+				__FUNCTION__,
1559
+				__LINE__
1560
+			);
1561
+			return false;
1562
+		}
1563
+		$status_paths = array(
1564
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1565
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1566
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1567
+		);
1568
+		// start by getting the current status so we know what status we'll be changing to.
1569
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1570
+		$status_to = $status_paths[ $cur_status ];
1571
+		// database only records true for checked IN or false for checked OUT
1572
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1573
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1574
+		// add relation - note Check-ins are always creating new rows
1575
+		// because we are keeping track of Check-ins over time.
1576
+		// Eventually we'll probably want to show a list table
1577
+		// for the individual Check-ins so that they can be managed.
1578
+		$checkin = EE_Checkin::new_instance(
1579
+			array(
1580
+				'REG_ID' => $this->ID(),
1581
+				'DTT_ID' => $DTT_ID,
1582
+				'CHK_in' => $new_status,
1583
+			)
1584
+		);
1585
+		// if the record could not be saved then return false
1586
+		if ($checkin->save() === 0) {
1587
+			if (WP_DEBUG) {
1588
+				global $wpdb;
1589
+				$error = sprintf(
1590
+					esc_html__(
1591
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1592
+						'event_espresso'
1593
+					),
1594
+					'<br />',
1595
+					$wpdb->last_error
1596
+				);
1597
+			} else {
1598
+				$error = esc_html__(
1599
+					'Registration check in update failed because of an unknown database error',
1600
+					'event_espresso'
1601
+				);
1602
+			}
1603
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1604
+			return false;
1605
+		}
1606
+		// Fire a checked_in and checkout_out action.
1607
+		$checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1608
+		do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1609
+		return $status_to;
1610
+	}
1611
+
1612
+
1613
+	/**
1614
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1615
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1616
+	 *
1617
+	 * @return EE_Datetime|null
1618
+	 * @throws EE_Error
1619
+	 */
1620
+	public function get_latest_related_datetime()
1621
+	{
1622
+		return EEM_Datetime::instance()->get_one(
1623
+			array(
1624
+				array(
1625
+					'Ticket.Registration.REG_ID' => $this->ID(),
1626
+				),
1627
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1628
+			)
1629
+		);
1630
+	}
1631
+
1632
+
1633
+	/**
1634
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1635
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1636
+	 *
1637
+	 * @throws EE_Error
1638
+	 */
1639
+	public function get_earliest_related_datetime()
1640
+	{
1641
+		return EEM_Datetime::instance()->get_one(
1642
+			array(
1643
+				array(
1644
+					'Ticket.Registration.REG_ID' => $this->ID(),
1645
+				),
1646
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1647
+			)
1648
+		);
1649
+	}
1650
+
1651
+
1652
+	/**
1653
+	 * This method simply returns the check-in status for this registration and the given datetime.
1654
+	 * If neither the datetime nor the checkin values are provided as arguments,
1655
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1656
+	 *
1657
+	 * @param int|null        $DTT_ID  The ID of the datetime we're checking against
1658
+	 *                                 (if empty we'll get the primary datetime for
1659
+	 *                                 this registration (via event) and use it's ID);
1660
+	 * @param EE_Checkin|null $checkin If present, we use the given checkin object rather than the dtt_id.
1661
+	 * @return int                     Integer representing Check-in status.
1662
+	 * @throws EE_Error
1663
+	 * @throws ReflectionException
1664
+	 */
1665
+	public function check_in_status_for_datetime(?int $DTT_ID = 0, ?EE_Checkin $checkin = null): int
1666
+	{
1667
+		if ($checkin instanceof EE_Checkin) {
1668
+			return $checkin->status();
1669
+		}
1670
+		// can't query checkin for a specific date if no ID was supplied
1671
+		if (empty($DTT_ID)) {
1672
+			return EE_Checkin::status_invalid;
1673
+		}
1674
+
1675
+		$checkin = $this->get_first_related(
1676
+			'Checkin',
1677
+			[
1678
+				['DTT_ID' => $DTT_ID],
1679
+				'order_by' => ['CHK_timestamp' => 'DESC'],
1680
+			]
1681
+		);
1682
+		return $checkin instanceof EE_Checkin ? $checkin->status() :  EE_Checkin::status_checked_never;
1683
+	}
1684
+
1685
+
1686
+	/**
1687
+	 * This method returns a localized message for the toggled Check-in message.
1688
+	 *
1689
+	 * @param int|null $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1690
+	 *                         then it is assumed Check-in for primary datetime was toggled.
1691
+	 * @param bool     $error  This just flags that you want an error message returned. This is put in so that the error
1692
+	 *                         message can be customized with the attendee name.
1693
+	 * @return string internationalized message
1694
+	 * @throws EE_Error
1695
+	 * @throws ReflectionException
1696
+	 */
1697
+	public function get_checkin_msg(?int $DTT_ID, bool $error = false): string
1698
+	{
1699
+		// let's get the attendee first so we can include the name of the attendee
1700
+		$attendee = $this->get_first_related('Attendee');
1701
+		if ($attendee instanceof EE_Attendee) {
1702
+			if ($error) {
1703
+				return sprintf(
1704
+					esc_html__("%s's check-in status was not changed.", "event_espresso"),
1705
+					$attendee->full_name()
1706
+				);
1707
+			}
1708
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1709
+			// what is the status message going to be?
1710
+			switch ($cur_status) {
1711
+				case EE_Checkin::status_checked_never:
1712
+					return sprintf(
1713
+						esc_html__("%s has been removed from Check-in records", "event_espresso"),
1714
+						$attendee->full_name()
1715
+					);
1716
+				case EE_Checkin::status_checked_in:
1717
+					return sprintf(esc_html__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1718
+				case EE_Checkin::status_checked_out:
1719
+					return sprintf(esc_html__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1720
+			}
1721
+		}
1722
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1723
+	}
1724
+
1725
+
1726
+	/**
1727
+	 * Returns the related EE_Transaction to this registration
1728
+	 *
1729
+	 * @return EE_Transaction
1730
+	 * @throws EE_Error
1731
+	 * @throws EntityNotFoundException
1732
+	 * @throws ReflectionException
1733
+	 */
1734
+	public function transaction(): EE_Transaction
1735
+	{
1736
+		$transaction = $this->get_first_related('Transaction');
1737
+		if (! $transaction instanceof \EE_Transaction) {
1738
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1739
+		}
1740
+		return $transaction;
1741
+	}
1742
+
1743
+
1744
+	/**
1745
+	 *        get Registration Code
1746
+	 */
1747
+	public function reg_code()
1748
+	{
1749
+		return $this->get('REG_code');
1750
+	}
1751
+
1752
+
1753
+	/**
1754
+	 *        get Transaction ID
1755
+	 */
1756
+	public function transaction_ID()
1757
+	{
1758
+		return $this->get('TXN_ID');
1759
+	}
1760
+
1761
+
1762
+	/**
1763
+	 * @return int
1764
+	 * @throws EE_Error
1765
+	 */
1766
+	public function ticket_ID()
1767
+	{
1768
+		return $this->get('TKT_ID');
1769
+	}
1770
+
1771
+
1772
+	/**
1773
+	 *        Set Registration Code
1774
+	 *
1775
+	 * @access    public
1776
+	 * @param    string  $REG_code Registration Code
1777
+	 * @param    boolean $use_default
1778
+	 * @throws EE_Error
1779
+	 */
1780
+	public function set_reg_code($REG_code, $use_default = false)
1781
+	{
1782
+		if (empty($REG_code)) {
1783
+			EE_Error::add_error(
1784
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1785
+				__FILE__,
1786
+				__FUNCTION__,
1787
+				__LINE__
1788
+			);
1789
+			return;
1790
+		}
1791
+		if (! $this->reg_code()) {
1792
+			parent::set('REG_code', $REG_code, $use_default);
1793
+		} else {
1794
+			EE_Error::doing_it_wrong(
1795
+				__CLASS__ . '::' . __FUNCTION__,
1796
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1797
+				'4.6.0'
1798
+			);
1799
+		}
1800
+	}
1801
+
1802
+
1803
+	/**
1804
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1805
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1806
+	 *    $registration->transaction()->registrations();
1807
+	 *
1808
+	 * @since 4.5.0
1809
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1810
+	 * @throws EE_Error
1811
+	 */
1812
+	public function get_all_other_registrations_in_group()
1813
+	{
1814
+		if ($this->group_size() < 2) {
1815
+			return array();
1816
+		}
1817
+
1818
+		$query[0] = array(
1819
+			'TXN_ID' => $this->transaction_ID(),
1820
+			'REG_ID' => array('!=', $this->ID()),
1821
+			'TKT_ID' => $this->ticket_ID(),
1822
+		);
1823
+		/** @var EE_Registration[] $registrations */
1824
+		$registrations = $this->get_model()->get_all($query);
1825
+		return $registrations;
1826
+	}
1827
+
1828
+	/**
1829
+	 * Return the link to the admin details for the object.
1830
+	 *
1831
+	 * @return string
1832
+	 * @throws EE_Error
1833
+	 */
1834
+	public function get_admin_details_link()
1835
+	{
1836
+		EE_Registry::instance()->load_helper('URL');
1837
+		return EEH_URL::add_query_args_and_nonce(
1838
+			array(
1839
+				'page'    => 'espresso_registrations',
1840
+				'action'  => 'view_registration',
1841
+				'_REG_ID' => $this->ID(),
1842
+			),
1843
+			admin_url('admin.php')
1844
+		);
1845
+	}
1846
+
1847
+	/**
1848
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1849
+	 *
1850
+	 * @return string
1851
+	 * @throws EE_Error
1852
+	 */
1853
+	public function get_admin_edit_link()
1854
+	{
1855
+		return $this->get_admin_details_link();
1856
+	}
1857
+
1858
+	/**
1859
+	 * Returns the link to a settings page for the object.
1860
+	 *
1861
+	 * @return string
1862
+	 * @throws EE_Error
1863
+	 */
1864
+	public function get_admin_settings_link()
1865
+	{
1866
+		return $this->get_admin_details_link();
1867
+	}
1868
+
1869
+	/**
1870
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1871
+	 *
1872
+	 * @return string
1873
+	 */
1874
+	public function get_admin_overview_link()
1875
+	{
1876
+		EE_Registry::instance()->load_helper('URL');
1877
+		return EEH_URL::add_query_args_and_nonce(
1878
+			array(
1879
+				'page' => 'espresso_registrations',
1880
+			),
1881
+			admin_url('admin.php')
1882
+		);
1883
+	}
1884
+
1885
+
1886
+	/**
1887
+	 * @param array $query_params
1888
+	 *
1889
+	 * @return \EE_Registration[]
1890
+	 * @throws EE_Error
1891
+	 */
1892
+	public function payments($query_params = array())
1893
+	{
1894
+		return $this->get_many_related('Payment', $query_params);
1895
+	}
1896
+
1897
+
1898
+	/**
1899
+	 * @param array $query_params
1900
+	 *
1901
+	 * @return \EE_Registration_Payment[]
1902
+	 * @throws EE_Error
1903
+	 */
1904
+	public function registration_payments($query_params = array())
1905
+	{
1906
+		return $this->get_many_related('Registration_Payment', $query_params);
1907
+	}
1908
+
1909
+
1910
+	/**
1911
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1912
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1913
+	 *
1914
+	 * @return EE_Payment_Method|null
1915
+	 */
1916
+	public function payment_method()
1917
+	{
1918
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1919
+	}
1920
+
1921
+
1922
+	/**
1923
+	 * @return \EE_Line_Item
1924
+	 * @throws EntityNotFoundException
1925
+	 * @throws EE_Error
1926
+	 */
1927
+	public function ticket_line_item()
1928
+	{
1929
+		$ticket = $this->ticket();
1930
+		$transaction = $this->transaction();
1931
+		$line_item = null;
1932
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1933
+			$transaction->total_line_item(),
1934
+			'Ticket',
1935
+			array($ticket->ID())
1936
+		);
1937
+		foreach ($ticket_line_items as $ticket_line_item) {
1938
+			if (
1939
+				$ticket_line_item instanceof \EE_Line_Item
1940
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1941
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1942
+			) {
1943
+				$line_item = $ticket_line_item;
1944
+				break;
1945
+			}
1946
+		}
1947
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1948
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1949
+		}
1950
+		return $line_item;
1951
+	}
1952
+
1953
+
1954
+	/**
1955
+	 * Soft Deletes this model object.
1956
+	 *
1957
+	 * @return boolean | int
1958
+	 * @throws RuntimeException
1959
+	 * @throws EE_Error
1960
+	 */
1961
+	public function delete()
1962
+	{
1963
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1964
+			$this->set_status(EEM_Registration::status_id_cancelled);
1965
+		}
1966
+		return parent::delete();
1967
+	}
1968
+
1969
+
1970
+	/**
1971
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1972
+	 *
1973
+	 * @throws EE_Error
1974
+	 * @throws RuntimeException
1975
+	 */
1976
+	public function restore()
1977
+	{
1978
+		$previous_status = $this->get_extra_meta(
1979
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1980
+			true,
1981
+			EEM_Registration::status_id_cancelled
1982
+		);
1983
+		if ($previous_status) {
1984
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1985
+			$this->set_status($previous_status);
1986
+		}
1987
+		return parent::restore();
1988
+	}
1989
+
1990
+
1991
+	/**
1992
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1993
+	 *
1994
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1995
+	 *                                           depending on whether the reg status changes to or from "Approved"
1996
+	 * @return boolean whether the Registration status was updated
1997
+	 * @throws EE_Error
1998
+	 * @throws RuntimeException
1999
+	 */
2000
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
2001
+	{
2002
+		$paid = $this->paid();
2003
+		$price = $this->final_price();
2004
+		switch (true) {
2005
+			// overpaid or paid
2006
+			case EEH_Money::compare_floats($paid, $price, '>'):
2007
+			case EEH_Money::compare_floats($paid, $price):
2008
+				$new_status = EEM_Registration::status_id_approved;
2009
+				break;
2010
+			//  underpaid
2011
+			case EEH_Money::compare_floats($paid, $price, '<'):
2012
+				$new_status = EEM_Registration::status_id_pending_payment;
2013
+				break;
2014
+			// uhhh Houston...
2015
+			default:
2016
+				throw new RuntimeException(
2017
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
2018
+				);
2019
+		}
2020
+		if ($new_status !== $this->status_ID()) {
2021
+			if ($trigger_set_status_logic) {
2022
+				return $this->set_status($new_status);
2023
+			}
2024
+			parent::set('STS_ID', $new_status);
2025
+			return true;
2026
+		}
2027
+		return false;
2028
+	}
2029
+
2030
+
2031
+	/*************************** DEPRECATED ***************************/
2032
+
2033
+
2034
+	/**
2035
+	 * @deprecated
2036
+	 * @since     4.7.0
2037
+	 * @access    public
2038
+	 */
2039
+	public function price_paid()
2040
+	{
2041
+		EE_Error::doing_it_wrong(
2042
+			'EE_Registration::price_paid()',
2043
+			esc_html__(
2044
+				'This method is deprecated, please use EE_Registration::final_price() instead.',
2045
+				'event_espresso'
2046
+			),
2047
+			'4.7.0'
2048
+		);
2049
+		return $this->final_price();
2050
+	}
2051
+
2052
+
2053
+	/**
2054
+	 * @deprecated
2055
+	 * @since     4.7.0
2056
+	 * @access    public
2057
+	 * @param    float $REG_final_price
2058
+	 * @throws EE_Error
2059
+	 * @throws RuntimeException
2060
+	 */
2061
+	public function set_price_paid($REG_final_price = 0.00)
2062
+	{
2063
+		EE_Error::doing_it_wrong(
2064
+			'EE_Registration::set_price_paid()',
2065
+			esc_html__(
2066
+				'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2067
+				'event_espresso'
2068
+			),
2069
+			'4.7.0'
2070
+		);
2071
+		$this->set_final_price($REG_final_price);
2072
+	}
2073
+
2074
+
2075
+	/**
2076
+	 * @deprecated
2077
+	 * @since 4.7.0
2078
+	 * @return string
2079
+	 * @throws EE_Error
2080
+	 */
2081
+	public function pretty_price_paid()
2082
+	{
2083
+		EE_Error::doing_it_wrong(
2084
+			'EE_Registration::pretty_price_paid()',
2085
+			esc_html__(
2086
+				'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2087
+				'event_espresso'
2088
+			),
2089
+			'4.7.0'
2090
+		);
2091
+		return $this->pretty_final_price();
2092
+	}
2093
+
2094
+
2095
+	/**
2096
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2097
+	 *
2098
+	 * @deprecated 4.9.17
2099
+	 * @return EE_Datetime
2100
+	 * @throws EE_Error
2101
+	 * @throws EntityNotFoundException
2102
+	 */
2103
+	public function get_related_primary_datetime()
2104
+	{
2105
+		EE_Error::doing_it_wrong(
2106
+			__METHOD__,
2107
+			esc_html__(
2108
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2109
+				'event_espresso'
2110
+			),
2111
+			'4.9.17',
2112
+			'5.0.0'
2113
+		);
2114
+		return $this->event()->primary_datetime();
2115
+	}
2116
+
2117
+	/**
2118
+	 * Returns the contact's name (or "Unknown" if there is no contact.)
2119
+	 * @since 4.10.12.p
2120
+	 * @return string
2121
+	 * @throws EE_Error
2122
+	 * @throws InvalidArgumentException
2123
+	 * @throws InvalidDataTypeException
2124
+	 * @throws InvalidInterfaceException
2125
+	 * @throws ReflectionException
2126
+	 */
2127
+	public function name()
2128
+	{
2129
+		return $this->attendeeName();
2130
+	}
2131 2131
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Datetime.class.php 1 patch
Indentation   +1552 added lines, -1552 removed lines patch added patch discarded remove patch
@@ -12,1560 +12,1560 @@
 block discarded – undo
12 12
  */
13 13
 class EE_Datetime extends EE_Soft_Delete_Base_Class
14 14
 {
15
-    /**
16
-     * constant used by get_active_status, indicates datetime has no more available spaces
17
-     */
18
-    const sold_out = 'DTS';
19
-
20
-    /**
21
-     * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
22
-     */
23
-    const active = 'DTA';
24
-
25
-    /**
26
-     * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
27
-     * expired
28
-     */
29
-    const upcoming = 'DTU';
30
-
31
-    /**
32
-     * Datetime is postponed
33
-     */
34
-    const postponed = 'DTP';
35
-
36
-    /**
37
-     * Datetime is cancelled
38
-     */
39
-    const cancelled = 'DTC';
40
-
41
-    /**
42
-     * constant used by get_active_status, indicates datetime has expired (event is over)
43
-     */
44
-    const expired = 'DTE';
45
-
46
-    /**
47
-     * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
48
-     */
49
-    const inactive = 'DTI';
50
-
51
-
52
-    /**
53
-     * @param array  $props_n_values    incoming values
54
-     * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
55
-     * @param array  $date_formats      incoming date_formats in an array where the first value is the date_format
56
-     *                                  and the second value is the time format
57
-     * @return EE_Datetime
58
-     * @throws ReflectionException
59
-     * @throws InvalidArgumentException
60
-     * @throws InvalidInterfaceException
61
-     * @throws InvalidDataTypeException
62
-     * @throws EE_Error
63
-     */
64
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
65
-    {
66
-        $has_object = parent::_check_for_object(
67
-            $props_n_values,
68
-            __CLASS__,
69
-            $timezone,
70
-            $date_formats
71
-        );
72
-        return $has_object
73
-            ? $has_object
74
-            : new self($props_n_values, false, $timezone, $date_formats);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param array  $props_n_values  incoming values from the database
80
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
-     *                                the website will be used.
82
-     * @return EE_Datetime
83
-     * @throws ReflectionException
84
-     * @throws InvalidArgumentException
85
-     * @throws InvalidInterfaceException
86
-     * @throws InvalidDataTypeException
87
-     * @throws EE_Error
88
-     */
89
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
90
-    {
91
-        return new self($props_n_values, true, $timezone);
92
-    }
93
-
94
-
95
-    /**
96
-     * @param $name
97
-     * @throws ReflectionException
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidInterfaceException
100
-     * @throws InvalidDataTypeException
101
-     * @throws EE_Error
102
-     */
103
-    public function set_name($name)
104
-    {
105
-        $this->set('DTT_name', $name);
106
-    }
107
-
108
-
109
-    /**
110
-     * @param $description
111
-     * @throws ReflectionException
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidInterfaceException
114
-     * @throws InvalidDataTypeException
115
-     * @throws EE_Error
116
-     */
117
-    public function set_description($description)
118
-    {
119
-        $this->set('DTT_description', $description);
120
-    }
121
-
122
-
123
-    /**
124
-     * Set event start date
125
-     * set the start date for an event
126
-     *
127
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
128
-     * @throws ReflectionException
129
-     * @throws InvalidArgumentException
130
-     * @throws InvalidInterfaceException
131
-     * @throws InvalidDataTypeException
132
-     * @throws EE_Error
133
-     */
134
-    public function set_start_date($date)
135
-    {
136
-        $this->_set_date_for($date, 'DTT_EVT_start');
137
-    }
138
-
139
-
140
-    /**
141
-     * Set event start time
142
-     * set the start time for an event
143
-     *
144
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
145
-     * @throws ReflectionException
146
-     * @throws InvalidArgumentException
147
-     * @throws InvalidInterfaceException
148
-     * @throws InvalidDataTypeException
149
-     * @throws EE_Error
150
-     */
151
-    public function set_start_time($time)
152
-    {
153
-        $this->_set_time_for($time, 'DTT_EVT_start');
154
-    }
155
-
156
-
157
-    /**
158
-     * Set event end date
159
-     * set the end date for an event
160
-     *
161
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
162
-     * @throws ReflectionException
163
-     * @throws InvalidArgumentException
164
-     * @throws InvalidInterfaceException
165
-     * @throws InvalidDataTypeException
166
-     * @throws EE_Error
167
-     */
168
-    public function set_end_date($date)
169
-    {
170
-        $this->_set_date_for($date, 'DTT_EVT_end');
171
-    }
172
-
173
-
174
-    /**
175
-     * Set event end time
176
-     * set the end time for an event
177
-     *
178
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
179
-     * @throws ReflectionException
180
-     * @throws InvalidArgumentException
181
-     * @throws InvalidInterfaceException
182
-     * @throws InvalidDataTypeException
183
-     * @throws EE_Error
184
-     */
185
-    public function set_end_time($time)
186
-    {
187
-        $this->_set_time_for($time, 'DTT_EVT_end');
188
-    }
189
-
190
-
191
-    /**
192
-     * Set registration limit
193
-     * set the maximum number of attendees that can be registered for this datetime slot
194
-     *
195
-     * @param int $reg_limit
196
-     * @throws ReflectionException
197
-     * @throws InvalidArgumentException
198
-     * @throws InvalidInterfaceException
199
-     * @throws InvalidDataTypeException
200
-     * @throws EE_Error
201
-     */
202
-    public function set_reg_limit($reg_limit)
203
-    {
204
-        $this->set('DTT_reg_limit', $reg_limit);
205
-    }
206
-
207
-
208
-    /**
209
-     * get the number of tickets sold for this datetime slot
210
-     *
211
-     * @return mixed int on success, FALSE on fail
212
-     * @throws ReflectionException
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidInterfaceException
215
-     * @throws InvalidDataTypeException
216
-     * @throws EE_Error
217
-     */
218
-    public function sold()
219
-    {
220
-        return $this->get_raw('DTT_sold');
221
-    }
222
-
223
-
224
-    /**
225
-     * @param int $sold
226
-     * @throws ReflectionException
227
-     * @throws InvalidArgumentException
228
-     * @throws InvalidInterfaceException
229
-     * @throws InvalidDataTypeException
230
-     * @throws EE_Error
231
-     */
232
-    public function set_sold($sold)
233
-    {
234
-        // sold can not go below zero
235
-        $sold = max(0, $sold);
236
-        $this->set('DTT_sold', $sold);
237
-    }
238
-
239
-
240
-    /**
241
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
242
-     * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
243
-     *
244
-     * @param int $qty
245
-     * @param boolean $also_decrease_reserved
246
-     * @return boolean indicating success
247
-     * @throws ReflectionException
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidInterfaceException
250
-     * @throws InvalidDataTypeException
251
-     * @throws EE_Error
252
-     */
253
-    public function increaseSold($qty = 1, $also_decrease_reserved = true)
254
-    {
255
-        $qty = absint($qty);
256
-        if ($also_decrease_reserved) {
257
-            $success = $this->adjustNumericFieldsInDb(
258
-                [
259
-                    'DTT_reserved' => $qty * -1,
260
-                    'DTT_sold' => $qty
261
-                ]
262
-            );
263
-        } else {
264
-            $success = $this->adjustNumericFieldsInDb(
265
-                [
266
-                    'DTT_sold' => $qty
267
-                ]
268
-            );
269
-        }
270
-
271
-        do_action(
272
-            'AHEE__EE_Datetime__increase_sold',
273
-            $this,
274
-            $qty,
275
-            $this->sold(),
276
-            $success
277
-        );
278
-        return $success;
279
-    }
280
-
281
-
282
-    /**
283
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
284
-     * to save afterwards.)
285
-     *
286
-     * @param int $qty
287
-     * @return boolean indicating success
288
-     * @throws ReflectionException
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidInterfaceException
291
-     * @throws InvalidDataTypeException
292
-     * @throws EE_Error
293
-     */
294
-    public function decreaseSold($qty = 1)
295
-    {
296
-        $qty = absint($qty);
297
-        $success = $this->adjustNumericFieldsInDb(
298
-            [
299
-                'DTT_sold' => $qty * -1
300
-            ]
301
-        );
302
-        do_action(
303
-            'AHEE__EE_Datetime__decrease_sold',
304
-            $this,
305
-            $qty,
306
-            $this->sold(),
307
-            $success
308
-        );
309
-        return $success;
310
-    }
311
-
312
-
313
-    /**
314
-     * Gets qty of reserved tickets for this datetime
315
-     *
316
-     * @return int
317
-     * @throws ReflectionException
318
-     * @throws InvalidArgumentException
319
-     * @throws InvalidInterfaceException
320
-     * @throws InvalidDataTypeException
321
-     * @throws EE_Error
322
-     */
323
-    public function reserved()
324
-    {
325
-        return $this->get_raw('DTT_reserved');
326
-    }
327
-
328
-
329
-    /**
330
-     * Sets qty of reserved tickets for this datetime
331
-     *
332
-     * @param int $reserved
333
-     * @throws ReflectionException
334
-     * @throws InvalidArgumentException
335
-     * @throws InvalidInterfaceException
336
-     * @throws InvalidDataTypeException
337
-     * @throws EE_Error
338
-     */
339
-    public function set_reserved($reserved)
340
-    {
341
-        // reserved can not go below zero
342
-        $reserved = max(0, (int) $reserved);
343
-        $this->set('DTT_reserved', $reserved);
344
-    }
345
-
346
-
347
-    /**
348
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
349
-     *
350
-     * @param int $qty
351
-     * @return boolean indicating success
352
-     * @throws ReflectionException
353
-     * @throws InvalidArgumentException
354
-     * @throws InvalidInterfaceException
355
-     * @throws InvalidDataTypeException
356
-     * @throws EE_Error
357
-     */
358
-    public function increaseReserved($qty = 1)
359
-    {
360
-        $qty = absint($qty);
361
-        $success = $this->incrementFieldConditionallyInDb(
362
-            'DTT_reserved',
363
-            'DTT_sold',
364
-            'DTT_reg_limit',
365
-            $qty
366
-        );
367
-        do_action(
368
-            'AHEE__EE_Datetime__increase_reserved',
369
-            $this,
370
-            $qty,
371
-            $this->reserved(),
372
-            $success
373
-        );
374
-        return $success;
375
-    }
376
-
377
-
378
-    /**
379
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
380
-     *
381
-     * @param int $qty
382
-     * @return boolean indicating success
383
-     * @throws ReflectionException
384
-     * @throws InvalidArgumentException
385
-     * @throws InvalidInterfaceException
386
-     * @throws InvalidDataTypeException
387
-     * @throws EE_Error
388
-     */
389
-    public function decreaseReserved($qty = 1)
390
-    {
391
-        $qty = absint($qty);
392
-        $success = $this->adjustNumericFieldsInDb(
393
-            [
394
-                'DTT_reserved' => $qty * -1
395
-            ]
396
-        );
397
-        do_action(
398
-            'AHEE__EE_Datetime__decrease_reserved',
399
-            $this,
400
-            $qty,
401
-            $this->reserved(),
402
-            $success
403
-        );
404
-        return $success;
405
-    }
406
-
407
-
408
-    /**
409
-     * total sold and reserved tickets
410
-     *
411
-     * @return int
412
-     * @throws ReflectionException
413
-     * @throws InvalidArgumentException
414
-     * @throws InvalidInterfaceException
415
-     * @throws InvalidDataTypeException
416
-     * @throws EE_Error
417
-     */
418
-    public function sold_and_reserved()
419
-    {
420
-        return $this->sold() + $this->reserved();
421
-    }
422
-
423
-
424
-    /**
425
-     * returns the datetime name
426
-     *
427
-     * @return string
428
-     * @throws ReflectionException
429
-     * @throws InvalidArgumentException
430
-     * @throws InvalidInterfaceException
431
-     * @throws InvalidDataTypeException
432
-     * @throws EE_Error
433
-     */
434
-    public function name()
435
-    {
436
-        return $this->get('DTT_name');
437
-    }
438
-
439
-
440
-    /**
441
-     * returns the datetime description
442
-     *
443
-     * @return string
444
-     * @throws ReflectionException
445
-     * @throws InvalidArgumentException
446
-     * @throws InvalidInterfaceException
447
-     * @throws InvalidDataTypeException
448
-     * @throws EE_Error
449
-     */
450
-    public function description()
451
-    {
452
-        return $this->get('DTT_description');
453
-    }
454
-
455
-
456
-    /**
457
-     * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
458
-     *
459
-     * @return boolean  TRUE if is primary, FALSE if not.
460
-     * @throws ReflectionException
461
-     * @throws InvalidArgumentException
462
-     * @throws InvalidInterfaceException
463
-     * @throws InvalidDataTypeException
464
-     * @throws EE_Error
465
-     */
466
-    public function is_primary()
467
-    {
468
-        return $this->get('DTT_is_primary');
469
-    }
470
-
471
-
472
-    /**
473
-     * This helper simply returns the order for the datetime
474
-     *
475
-     * @return int  The order of the datetime for this event.
476
-     * @throws ReflectionException
477
-     * @throws InvalidArgumentException
478
-     * @throws InvalidInterfaceException
479
-     * @throws InvalidDataTypeException
480
-     * @throws EE_Error
481
-     */
482
-    public function order()
483
-    {
484
-        return $this->get('DTT_order');
485
-    }
486
-
487
-
488
-    /**
489
-     * This helper simply returns the parent id for the datetime
490
-     *
491
-     * @return int
492
-     * @throws ReflectionException
493
-     * @throws InvalidArgumentException
494
-     * @throws InvalidInterfaceException
495
-     * @throws InvalidDataTypeException
496
-     * @throws EE_Error
497
-     */
498
-    public function parent()
499
-    {
500
-        return $this->get('DTT_parent');
501
-    }
502
-
503
-
504
-    /**
505
-     * show date and/or time
506
-     *
507
-     * @param string $date_or_time    whether to display a date or time or both
508
-     * @param string $start_or_end    whether to display start or end datetimes
509
-     * @param string $dt_frmt
510
-     * @param string $tm_frmt
511
-     * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
512
-     *                                otherwise we use the standard formats)
513
-     * @return string|bool  string on success, FALSE on fail
514
-     * @throws ReflectionException
515
-     * @throws InvalidArgumentException
516
-     * @throws InvalidInterfaceException
517
-     * @throws InvalidDataTypeException
518
-     * @throws EE_Error
519
-     */
520
-    private function _show_datetime(
521
-        $date_or_time = null,
522
-        $start_or_end = 'start',
523
-        $dt_frmt = '',
524
-        $tm_frmt = '',
525
-        $echo = false
526
-    ) {
527
-        $field_name = "DTT_EVT_{$start_or_end}";
528
-        $dtt = $this->_get_datetime(
529
-            $field_name,
530
-            $dt_frmt,
531
-            $tm_frmt,
532
-            $date_or_time,
533
-            $echo
534
-        );
535
-        if (! $echo) {
536
-            return $dtt;
537
-        }
538
-        return '';
539
-    }
540
-
541
-
542
-    /**
543
-     * get event start date.  Provide either the date format, or NULL to re-use the
544
-     * last-used format, or '' to use the default date format
545
-     *
546
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
547
-     * @return mixed            string on success, FALSE on fail
548
-     * @throws ReflectionException
549
-     * @throws InvalidArgumentException
550
-     * @throws InvalidInterfaceException
551
-     * @throws InvalidDataTypeException
552
-     * @throws EE_Error
553
-     */
554
-    public function start_date($dt_frmt = '')
555
-    {
556
-        return $this->_show_datetime('D', 'start', $dt_frmt);
557
-    }
558
-
559
-
560
-    /**
561
-     * Echoes start_date()
562
-     *
563
-     * @param string $dt_frmt
564
-     * @throws ReflectionException
565
-     * @throws InvalidArgumentException
566
-     * @throws InvalidInterfaceException
567
-     * @throws InvalidDataTypeException
568
-     * @throws EE_Error
569
-     */
570
-    public function e_start_date($dt_frmt = '')
571
-    {
572
-        $this->_show_datetime('D', 'start', $dt_frmt, null, true);
573
-    }
574
-
575
-
576
-    /**
577
-     * get end date. Provide either the date format, or NULL to re-use the
578
-     * last-used format, or '' to use the default date format
579
-     *
580
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
581
-     * @return mixed            string on success, FALSE on fail
582
-     * @throws ReflectionException
583
-     * @throws InvalidArgumentException
584
-     * @throws InvalidInterfaceException
585
-     * @throws InvalidDataTypeException
586
-     * @throws EE_Error
587
-     */
588
-    public function end_date($dt_frmt = '')
589
-    {
590
-        return $this->_show_datetime('D', 'end', $dt_frmt);
591
-    }
592
-
593
-
594
-    /**
595
-     * Echoes the end date. See end_date()
596
-     *
597
-     * @param string $dt_frmt
598
-     * @throws ReflectionException
599
-     * @throws InvalidArgumentException
600
-     * @throws InvalidInterfaceException
601
-     * @throws InvalidDataTypeException
602
-     * @throws EE_Error
603
-     */
604
-    public function e_end_date($dt_frmt = '')
605
-    {
606
-        $this->_show_datetime('D', 'end', $dt_frmt, null, true);
607
-    }
608
-
609
-
610
-    /**
611
-     * get date_range - meaning the start AND end date
612
-     *
613
-     * @access public
614
-     * @param string $dt_frmt     string representation of date format defaults to WP settings
615
-     * @param string $conjunction conjunction junction what's your function ?
616
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
617
-     * @return mixed              string on success, FALSE on fail
618
-     * @throws ReflectionException
619
-     * @throws InvalidArgumentException
620
-     * @throws InvalidInterfaceException
621
-     * @throws InvalidDataTypeException
622
-     * @throws EE_Error
623
-     */
624
-    public function date_range($dt_frmt = '', $conjunction = ' - ')
625
-    {
626
-        $dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
627
-        $start = str_replace(
628
-            ' ',
629
-            '&nbsp;',
630
-            $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
631
-        );
632
-        $end = str_replace(
633
-            ' ',
634
-            '&nbsp;',
635
-            $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
636
-        );
637
-        return $start !== $end ? $start . $conjunction . $end : $start;
638
-    }
639
-
640
-
641
-    /**
642
-     * @param string $dt_frmt
643
-     * @param string $conjunction
644
-     * @throws ReflectionException
645
-     * @throws InvalidArgumentException
646
-     * @throws InvalidInterfaceException
647
-     * @throws InvalidDataTypeException
648
-     * @throws EE_Error
649
-     */
650
-    public function e_date_range($dt_frmt = '', $conjunction = ' - ')
651
-    {
652
-        echo esc_html($this->date_range($dt_frmt, $conjunction));
653
-    }
654
-
655
-
656
-    /**
657
-     * get start time
658
-     *
659
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
660
-     * @return mixed        string on success, FALSE on fail
661
-     * @throws ReflectionException
662
-     * @throws InvalidArgumentException
663
-     * @throws InvalidInterfaceException
664
-     * @throws InvalidDataTypeException
665
-     * @throws EE_Error
666
-     */
667
-    public function start_time($tm_format = '')
668
-    {
669
-        return $this->_show_datetime('T', 'start', null, $tm_format);
670
-    }
671
-
672
-
673
-    /**
674
-     * @param string $tm_format
675
-     * @throws ReflectionException
676
-     * @throws InvalidArgumentException
677
-     * @throws InvalidInterfaceException
678
-     * @throws InvalidDataTypeException
679
-     * @throws EE_Error
680
-     */
681
-    public function e_start_time($tm_format = '')
682
-    {
683
-        $this->_show_datetime('T', 'start', null, $tm_format, true);
684
-    }
685
-
686
-
687
-    /**
688
-     * get end time
689
-     *
690
-     * @param string $tm_format string representation of time format defaults to 'g:i a'
691
-     * @return mixed                string on success, FALSE on fail
692
-     * @throws ReflectionException
693
-     * @throws InvalidArgumentException
694
-     * @throws InvalidInterfaceException
695
-     * @throws InvalidDataTypeException
696
-     * @throws EE_Error
697
-     */
698
-    public function end_time($tm_format = '')
699
-    {
700
-        return $this->_show_datetime('T', 'end', null, $tm_format);
701
-    }
702
-
703
-
704
-    /**
705
-     * @param string $tm_format
706
-     * @throws ReflectionException
707
-     * @throws InvalidArgumentException
708
-     * @throws InvalidInterfaceException
709
-     * @throws InvalidDataTypeException
710
-     * @throws EE_Error
711
-     */
712
-    public function e_end_time($tm_format = '')
713
-    {
714
-        $this->_show_datetime('T', 'end', null, $tm_format, true);
715
-    }
716
-
717
-
718
-    /**
719
-     * get time_range
720
-     *
721
-     * @access public
722
-     * @param string $tm_format   string representation of time format defaults to 'g:i a'
723
-     * @param string $conjunction conjunction junction what's your function ?
724
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
725
-     * @return mixed              string on success, FALSE on fail
726
-     * @throws ReflectionException
727
-     * @throws InvalidArgumentException
728
-     * @throws InvalidInterfaceException
729
-     * @throws InvalidDataTypeException
730
-     * @throws EE_Error
731
-     */
732
-    public function time_range($tm_format = '', $conjunction = ' - ')
733
-    {
734
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
735
-        $start = str_replace(
736
-            ' ',
737
-            '&nbsp;',
738
-            $this->get_i18n_datetime('DTT_EVT_start', $tm_format)
739
-        );
740
-        $end = str_replace(
741
-            ' ',
742
-            '&nbsp;',
743
-            $this->get_i18n_datetime('DTT_EVT_end', $tm_format)
744
-        );
745
-        return $start !== $end ? $start . $conjunction . $end : $start;
746
-    }
747
-
748
-
749
-    /**
750
-     * @param string $tm_format
751
-     * @param string $conjunction
752
-     * @throws ReflectionException
753
-     * @throws InvalidArgumentException
754
-     * @throws InvalidInterfaceException
755
-     * @throws InvalidDataTypeException
756
-     * @throws EE_Error
757
-     */
758
-    public function e_time_range($tm_format = '', $conjunction = ' - ')
759
-    {
760
-        echo esc_html($this->time_range($tm_format, $conjunction));
761
-    }
762
-
763
-
764
-    /**
765
-     * This returns a range representation of the date and times.
766
-     * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
767
-     * Also, the return value is localized.
768
-     *
769
-     * @param string $dt_format
770
-     * @param string $tm_format
771
-     * @param string $conjunction used between two different dates or times.
772
-     *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
773
-     * @param string $separator   used between the date and time formats.
774
-     *                            ex: Dec 1, 2016{$separator}2pm
775
-     * @return string
776
-     * @throws ReflectionException
777
-     * @throws InvalidArgumentException
778
-     * @throws InvalidInterfaceException
779
-     * @throws InvalidDataTypeException
780
-     * @throws EE_Error
781
-     */
782
-    public function date_and_time_range(
783
-        $dt_format = '',
784
-        $tm_format = '',
785
-        $conjunction = ' - ',
786
-        $separator = ' '
787
-    ) {
788
-        $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
789
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
790
-        $full_format = $dt_format . $separator . $tm_format;
791
-        // the range output depends on various conditions
792
-        switch (true) {
793
-            // start date timestamp and end date timestamp are the same.
794
-            case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
795
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
796
-                break;
797
-            // start and end date are the same but times are different
798
-            case ($this->start_date() === $this->end_date()):
799
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
800
-                          . $conjunction
801
-                          . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
802
-                break;
803
-            // all other conditions
804
-            default:
805
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
806
-                          . $conjunction
807
-                          . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
808
-                break;
809
-        }
810
-        return $output;
811
-    }
812
-
813
-
814
-    /**
815
-     * This echos the results of date and time range.
816
-     *
817
-     * @see date_and_time_range() for more details on purpose.
818
-     * @param string $dt_format
819
-     * @param string $tm_format
820
-     * @param string $conjunction
821
-     * @return void
822
-     * @throws ReflectionException
823
-     * @throws InvalidArgumentException
824
-     * @throws InvalidInterfaceException
825
-     * @throws InvalidDataTypeException
826
-     * @throws EE_Error
827
-     */
828
-    public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
829
-    {
830
-        echo esc_html($this->date_and_time_range($dt_format, $tm_format, $conjunction));
831
-    }
832
-
833
-
834
-    /**
835
-     * get start date and start time
836
-     *
837
-     * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
838
-     * @param    string $tm_format - string representation of time format defaults to 'g:i a'
839
-     * @return    mixed    string on success, FALSE on fail
840
-     * @throws ReflectionException
841
-     * @throws InvalidArgumentException
842
-     * @throws InvalidInterfaceException
843
-     * @throws InvalidDataTypeException
844
-     * @throws EE_Error
845
-     */
846
-    public function start_date_and_time($dt_format = '', $tm_format = '')
847
-    {
848
-        return $this->_show_datetime('', 'start', $dt_format, $tm_format);
849
-    }
850
-
851
-
852
-    /**
853
-     * @param string $dt_frmt
854
-     * @param string $tm_format
855
-     * @throws ReflectionException
856
-     * @throws InvalidArgumentException
857
-     * @throws InvalidInterfaceException
858
-     * @throws InvalidDataTypeException
859
-     * @throws EE_Error
860
-     */
861
-    public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
862
-    {
863
-        $this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
864
-    }
865
-
866
-
867
-    /**
868
-     * Shows the length of the event (start to end time).
869
-     * Can be shown in 'seconds','minutes','hours', or 'days'.
870
-     * By default, rounds up. (So if you use 'days', and then event
871
-     * only occurs for 1 hour, it will return 1 day).
872
-     *
873
-     * @param string $units 'seconds','minutes','hours','days'
874
-     * @param bool   $round_up
875
-     * @return float|int|mixed
876
-     * @throws ReflectionException
877
-     * @throws InvalidArgumentException
878
-     * @throws InvalidInterfaceException
879
-     * @throws InvalidDataTypeException
880
-     * @throws EE_Error
881
-     */
882
-    public function length($units = 'seconds', $round_up = false)
883
-    {
884
-        $start = $this->get_raw('DTT_EVT_start');
885
-        $end = $this->get_raw('DTT_EVT_end');
886
-        $length_in_units = $end - $start;
887
-        switch ($units) {
888
-            // NOTE: We purposefully don't use "break;" in order to chain the divisions
889
-            /** @noinspection PhpMissingBreakStatementInspection */
890
-            // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
891
-            case 'days':
892
-                $length_in_units /= 24;
893
-            /** @noinspection PhpMissingBreakStatementInspection */
894
-            case 'hours':
895
-                // fall through is intentional
896
-                $length_in_units /= 60;
897
-            /** @noinspection PhpMissingBreakStatementInspection */
898
-            case 'minutes':
899
-                // fall through is intentional
900
-                $length_in_units /= 60;
901
-            case 'seconds':
902
-            default:
903
-                $length_in_units = ceil($length_in_units);
904
-        }
905
-        // phpcs:enable
906
-        if ($round_up) {
907
-            $length_in_units = max($length_in_units, 1);
908
-        }
909
-        return $length_in_units;
910
-    }
911
-
912
-
913
-    /**
914
-     *        get end date and time
915
-     *
916
-     * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
917
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
918
-     * @return    mixed                string on success, FALSE on fail
919
-     * @throws ReflectionException
920
-     * @throws InvalidArgumentException
921
-     * @throws InvalidInterfaceException
922
-     * @throws InvalidDataTypeException
923
-     * @throws EE_Error
924
-     */
925
-    public function end_date_and_time($dt_frmt = '', $tm_format = '')
926
-    {
927
-        return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
928
-    }
929
-
930
-
931
-    /**
932
-     * @param string $dt_frmt
933
-     * @param string $tm_format
934
-     * @throws ReflectionException
935
-     * @throws InvalidArgumentException
936
-     * @throws InvalidInterfaceException
937
-     * @throws InvalidDataTypeException
938
-     * @throws EE_Error
939
-     */
940
-    public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
941
-    {
942
-        $this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
943
-    }
944
-
945
-
946
-    /**
947
-     *        get start timestamp
948
-     *
949
-     * @return        int
950
-     * @throws ReflectionException
951
-     * @throws InvalidArgumentException
952
-     * @throws InvalidInterfaceException
953
-     * @throws InvalidDataTypeException
954
-     * @throws EE_Error
955
-     */
956
-    public function start()
957
-    {
958
-        return $this->get_raw('DTT_EVT_start');
959
-    }
960
-
961
-
962
-    /**
963
-     *        get end timestamp
964
-     *
965
-     * @return        int
966
-     * @throws ReflectionException
967
-     * @throws InvalidArgumentException
968
-     * @throws InvalidInterfaceException
969
-     * @throws InvalidDataTypeException
970
-     * @throws EE_Error
971
-     */
972
-    public function end()
973
-    {
974
-        return $this->get_raw('DTT_EVT_end');
975
-    }
976
-
977
-
978
-    /**
979
-     *    get the registration limit for this datetime slot
980
-     *
981
-     * @return        mixed        int on success, FALSE on fail
982
-     * @throws ReflectionException
983
-     * @throws InvalidArgumentException
984
-     * @throws InvalidInterfaceException
985
-     * @throws InvalidDataTypeException
986
-     * @throws EE_Error
987
-     */
988
-    public function reg_limit()
989
-    {
990
-        return $this->get_raw('DTT_reg_limit');
991
-    }
992
-
993
-
994
-    /**
995
-     *    have the tickets sold for this datetime, met or exceed the registration limit ?
996
-     *
997
-     * @return        boolean
998
-     * @throws ReflectionException
999
-     * @throws InvalidArgumentException
1000
-     * @throws InvalidInterfaceException
1001
-     * @throws InvalidDataTypeException
1002
-     * @throws EE_Error
1003
-     */
1004
-    public function sold_out()
1005
-    {
1006
-        return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * return the total number of spaces remaining at this venue.
1012
-     * This only takes the venue's capacity into account, NOT the tickets available for sale
1013
-     *
1014
-     * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1015
-     *                               Because if all tickets attached to this datetime have no spaces left,
1016
-     *                               then this datetime IS effectively sold out.
1017
-     *                               However, there are cases where we just want to know the spaces
1018
-     *                               remaining for this particular datetime, hence the flag.
1019
-     * @return int
1020
-     * @throws ReflectionException
1021
-     * @throws InvalidArgumentException
1022
-     * @throws InvalidInterfaceException
1023
-     * @throws InvalidDataTypeException
1024
-     * @throws EE_Error
1025
-     */
1026
-    public function spaces_remaining($consider_tickets = false)
1027
-    {
1028
-        // tickets remaining available for purchase
1029
-        // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1030
-        $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1031
-        if (! $consider_tickets) {
1032
-            return $dtt_remaining;
1033
-        }
1034
-        $tickets_remaining = $this->tickets_remaining();
1035
-        return min($dtt_remaining, $tickets_remaining);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * Counts the total tickets available
1041
-     * (from all the different types of tickets which are available for this datetime).
1042
-     *
1043
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1044
-     * @return int
1045
-     * @throws ReflectionException
1046
-     * @throws InvalidArgumentException
1047
-     * @throws InvalidInterfaceException
1048
-     * @throws InvalidDataTypeException
1049
-     * @throws EE_Error
1050
-     */
1051
-    public function tickets_remaining($query_params = array())
1052
-    {
1053
-        $sum = 0;
1054
-        $tickets = $this->tickets($query_params);
1055
-        if (! empty($tickets)) {
1056
-            foreach ($tickets as $ticket) {
1057
-                if ($ticket instanceof EE_Ticket) {
1058
-                    // get the actual amount of tickets that can be sold
1059
-                    $qty = $ticket->qty('saleable');
1060
-                    if ($qty === EE_INF) {
1061
-                        return EE_INF;
1062
-                    }
1063
-                    // no negative ticket quantities plz
1064
-                    if ($qty > 0) {
1065
-                        $sum += $qty;
1066
-                    }
1067
-                }
1068
-            }
1069
-        }
1070
-        return $sum;
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * Gets the count of all the tickets available at this datetime (not ticket types)
1076
-     * before any were sold
1077
-     *
1078
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1079
-     * @return int
1080
-     * @throws ReflectionException
1081
-     * @throws InvalidArgumentException
1082
-     * @throws InvalidInterfaceException
1083
-     * @throws InvalidDataTypeException
1084
-     * @throws EE_Error
1085
-     */
1086
-    public function sum_tickets_initially_available($query_params = array())
1087
-    {
1088
-        return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * Returns the lesser-of-the two: spaces remaining at this datetime, or
1094
-     * the total tickets remaining (a sum of the tickets remaining for each ticket type
1095
-     * that is available for this datetime).
1096
-     *
1097
-     * @return int
1098
-     * @throws ReflectionException
1099
-     * @throws InvalidArgumentException
1100
-     * @throws InvalidInterfaceException
1101
-     * @throws InvalidDataTypeException
1102
-     * @throws EE_Error
1103
-     */
1104
-    public function total_tickets_available_at_this_datetime()
1105
-    {
1106
-        return $this->spaces_remaining(true);
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * This simply compares the internal dtt for the given string with NOW
1112
-     * and determines if the date is upcoming or not.
1113
-     *
1114
-     * @access public
1115
-     * @return boolean
1116
-     * @throws ReflectionException
1117
-     * @throws InvalidArgumentException
1118
-     * @throws InvalidInterfaceException
1119
-     * @throws InvalidDataTypeException
1120
-     * @throws EE_Error
1121
-     */
1122
-    public function is_upcoming()
1123
-    {
1124
-        return ($this->get_raw('DTT_EVT_start') > time());
1125
-    }
1126
-
1127
-
1128
-    /**
1129
-     * This simply compares the internal datetime for the given string with NOW
1130
-     * and returns if the date is active (i.e. start and end time)
1131
-     *
1132
-     * @return boolean
1133
-     * @throws ReflectionException
1134
-     * @throws InvalidArgumentException
1135
-     * @throws InvalidInterfaceException
1136
-     * @throws InvalidDataTypeException
1137
-     * @throws EE_Error
1138
-     */
1139
-    public function is_active()
1140
-    {
1141
-        return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     * This simply compares the internal dtt for the given string with NOW
1147
-     * and determines if the date is expired or not.
1148
-     *
1149
-     * @return boolean
1150
-     * @throws ReflectionException
1151
-     * @throws InvalidArgumentException
1152
-     * @throws InvalidInterfaceException
1153
-     * @throws InvalidDataTypeException
1154
-     * @throws EE_Error
1155
-     */
1156
-    public function is_expired()
1157
-    {
1158
-        return ($this->get_raw('DTT_EVT_end') < time());
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * This returns the active status for whether an event is active, upcoming, or expired
1164
-     *
1165
-     * @return int return value will be one of the EE_Datetime status constants.
1166
-     * @throws ReflectionException
1167
-     * @throws InvalidArgumentException
1168
-     * @throws InvalidInterfaceException
1169
-     * @throws InvalidDataTypeException
1170
-     * @throws EE_Error
1171
-     */
1172
-    public function get_active_status()
1173
-    {
1174
-        $total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1175
-        if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1176
-            return EE_Datetime::sold_out;
1177
-        }
1178
-        if ($this->is_expired()) {
1179
-            return EE_Datetime::expired;
1180
-        }
1181
-        if ($this->is_upcoming()) {
1182
-            return EE_Datetime::upcoming;
1183
-        }
1184
-        if ($this->is_active()) {
1185
-            return EE_Datetime::active;
1186
-        }
1187
-        return null;
1188
-    }
1189
-
1190
-
1191
-    /**
1192
-     * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1193
-     *
1194
-     * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1195
-     * @return string
1196
-     * @throws ReflectionException
1197
-     * @throws InvalidArgumentException
1198
-     * @throws InvalidInterfaceException
1199
-     * @throws InvalidDataTypeException
1200
-     * @throws EE_Error
1201
-     */
1202
-    public function get_dtt_display_name($use_dtt_name = false)
1203
-    {
1204
-        if ($use_dtt_name) {
1205
-            $dtt_name = $this->name();
1206
-            if (! empty($dtt_name)) {
1207
-                return $dtt_name;
1208
-            }
1209
-        }
1210
-        // first condition is to see if the months are different
1211
-        if (
1212
-            date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1213
-        ) {
1214
-            $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
-            // next condition is if its the same month but different day
1216
-        } else {
1217
-            if (
1218
-                date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1219
-                && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1220
-            ) {
1221
-                $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1222
-            } else {
1223
-                $display_date = $this->start_date('F j\, Y')
1224
-                                . ' @ '
1225
-                                . $this->start_date('g:i a')
1226
-                                . ' - '
1227
-                                . $this->end_date('g:i a');
1228
-            }
1229
-        }
1230
-        return $display_date;
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     * Gets all the tickets for this datetime
1236
-     *
1237
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1238
-     * @return EE_Base_Class[]|EE_Ticket[]
1239
-     * @throws ReflectionException
1240
-     * @throws InvalidArgumentException
1241
-     * @throws InvalidInterfaceException
1242
-     * @throws InvalidDataTypeException
1243
-     * @throws EE_Error
1244
-     */
1245
-    public function tickets($query_params = array())
1246
-    {
1247
-        return $this->get_many_related('Ticket', $query_params);
1248
-    }
1249
-
1250
-
1251
-    /**
1252
-     * Gets all the ticket types currently available for purchase
1253
-     *
1254
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1255
-     * @return EE_Ticket[]
1256
-     * @throws ReflectionException
1257
-     * @throws InvalidArgumentException
1258
-     * @throws InvalidInterfaceException
1259
-     * @throws InvalidDataTypeException
1260
-     * @throws EE_Error
1261
-     */
1262
-    public function ticket_types_available_for_purchase($query_params = array())
1263
-    {
1264
-        // first check if datetime is valid
1265
-        if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1266
-            return array();
1267
-        }
1268
-        if (empty($query_params)) {
1269
-            $query_params = array(
1270
-                array(
1271
-                    'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1272
-                    'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1273
-                    'TKT_deleted'    => false,
1274
-                ),
1275
-            );
1276
-        }
1277
-        return $this->tickets($query_params);
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * @return EE_Base_Class|EE_Event
1283
-     * @throws ReflectionException
1284
-     * @throws InvalidArgumentException
1285
-     * @throws InvalidInterfaceException
1286
-     * @throws InvalidDataTypeException
1287
-     * @throws EE_Error
1288
-     */
1289
-    public function event()
1290
-    {
1291
-        return $this->get_first_related('Event');
1292
-    }
1293
-
1294
-
1295
-    /**
1296
-     * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1297
-     * (via the tickets).
1298
-     *
1299
-     * @return int
1300
-     * @throws ReflectionException
1301
-     * @throws InvalidArgumentException
1302
-     * @throws InvalidInterfaceException
1303
-     * @throws InvalidDataTypeException
1304
-     * @throws EE_Error
1305
-     */
1306
-    public function update_sold()
1307
-    {
1308
-        $count_regs_for_this_datetime = EEM_Registration::instance()->count(
1309
-            array(
1310
-                array(
1311
-                    'STS_ID'                 => EEM_Registration::status_id_approved,
1312
-                    'REG_deleted'            => 0,
1313
-                    'Ticket.Datetime.DTT_ID' => $this->ID(),
1314
-                ),
1315
-            )
1316
-        );
1317
-        $this->set_sold($count_regs_for_this_datetime);
1318
-        $this->save();
1319
-        return $count_regs_for_this_datetime;
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * Adds a venue to this event
1325
-     *
1326
-     * @param int|EE_Venue /int $venue_id_or_obj
1327
-     * @return EE_Base_Class|EE_Venue
1328
-     * @throws EE_Error
1329
-     * @throws ReflectionException
1330
-     */
1331
-    public function add_venue($venue_id_or_obj): EE_Venue
1332
-    {
1333
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
1334
-    }
1335
-
1336
-
1337
-    /**
1338
-     * Removes a venue from the event
1339
-     *
1340
-     * @param EE_Venue /int $venue_id_or_obj
1341
-     * @return EE_Base_Class|EE_Venue
1342
-     * @throws EE_Error
1343
-     * @throws ReflectionException
1344
-     */
1345
-    public function remove_venue($venue_id_or_obj): EE_Venue
1346
-    {
1347
-        $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
1348
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
1349
-    }
1350
-
1351
-
1352
-    /**
1353
-     * Gets the venue related to the event. May provide additional $query_params if desired
1354
-     *
1355
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1356
-     * @return int
1357
-     * @throws EE_Error
1358
-     * @throws ReflectionException
1359
-     */
1360
-    public function venue_ID(array $query_params = []): int
1361
-    {
1362
-        $venue = $this->get_first_related('Venue', $query_params);
1363
-        return $venue instanceof EE_Venue
1364
-            ? $venue->ID()
1365
-            : 0;
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     * Gets the venue related to the event. May provide additional $query_params if desired
1371
-     *
1372
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1373
-     * @return EE_Base_Class|EE_Venue
1374
-     * @throws EE_Error
1375
-     * @throws ReflectionException
1376
-     */
1377
-    public function venue(array $query_params = [])
1378
-    {
1379
-        return $this->get_first_related('Venue', $query_params);
1380
-    }
1381
-
1382
-
1383
-    /**
1384
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1385
-     * @param string                   $relationName
1386
-     * @param array                    $extra_join_model_fields_n_values
1387
-     * @param string|null              $cache_id
1388
-     * @return EE_Base_Class
1389
-     * @throws EE_Error
1390
-     * @throws ReflectionException
1391
-     * @since   $VID:$
1392
-     */
1393
-    public function _add_relation_to(
1394
-        $otherObjectModelObjectOrID,
1395
-        $relationName,
1396
-        $extra_join_model_fields_n_values = [],
1397
-        $cache_id = null
1398
-    ) {
1399
-        // if we're adding a new relation to a ticket
1400
-        if ($relationName === 'Ticket' && ! $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1401
-            /** @var EE_Ticket $ticket */
1402
-            $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1403
-            $this->increaseSold($ticket->sold(), false);
1404
-            $this->increaseReserved($ticket->reserved());
1405
-            $this->save();
1406
-            $otherObjectModelObjectOrID = $ticket;
1407
-        }
1408
-        return parent::_add_relation_to(
1409
-            $otherObjectModelObjectOrID,
1410
-            $relationName,
1411
-            $extra_join_model_fields_n_values,
1412
-            $cache_id
1413
-        );
1414
-    }
1415
-
1416
-
1417
-    /**
1418
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1419
-     * @param string                   $relationName
1420
-     * @param array                    $where_query
1421
-     * @return bool|EE_Base_Class|null
1422
-     * @throws EE_Error
1423
-     * @throws ReflectionException
1424
-     * @since   $VID:$
1425
-     */
1426
-    public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = [])
1427
-    {
1428
-        if ($relationName === 'Ticket' && $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1429
-            /** @var EE_Ticket $ticket */
1430
-            $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1431
-            $this->decreaseSold($ticket->sold());
1432
-            $this->decreaseReserved($ticket->reserved());
1433
-            $this->save();
1434
-            $otherObjectModelObjectOrID = $ticket;
1435
-        }
1436
-        return parent::_remove_relation_to(
1437
-            $otherObjectModelObjectOrID,
1438
-            $relationName,
1439
-            $where_query
1440
-        );
1441
-    }
1442
-
1443
-
1444
-    /**
1445
-     * Removes ALL the related things for the $relationName.
1446
-     *
1447
-     * @param string $relationName
1448
-     * @param array  $where_query_params
1449
-     * @return EE_Base_Class
1450
-     * @throws ReflectionException
1451
-     * @throws InvalidArgumentException
1452
-     * @throws InvalidInterfaceException
1453
-     * @throws InvalidDataTypeException
1454
-     * @throws EE_Error
1455
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
1456
-     */
1457
-    public function _remove_relations($relationName, $where_query_params = [])
1458
-    {
1459
-        if ($relationName === 'Ticket') {
1460
-            $tickets = $this->tickets();
1461
-            foreach ($tickets as $ticket) {
1462
-                $this->decreaseSold($ticket->sold());
1463
-                $this->decreaseReserved($ticket->reserved());
1464
-                $this->save();
1465
-            }
1466
-        }
1467
-        return parent::_remove_relations($relationName, $where_query_params);
1468
-    }
1469
-
1470
-
1471
-    /*******************************************************************
15
+	/**
16
+	 * constant used by get_active_status, indicates datetime has no more available spaces
17
+	 */
18
+	const sold_out = 'DTS';
19
+
20
+	/**
21
+	 * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
22
+	 */
23
+	const active = 'DTA';
24
+
25
+	/**
26
+	 * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
27
+	 * expired
28
+	 */
29
+	const upcoming = 'DTU';
30
+
31
+	/**
32
+	 * Datetime is postponed
33
+	 */
34
+	const postponed = 'DTP';
35
+
36
+	/**
37
+	 * Datetime is cancelled
38
+	 */
39
+	const cancelled = 'DTC';
40
+
41
+	/**
42
+	 * constant used by get_active_status, indicates datetime has expired (event is over)
43
+	 */
44
+	const expired = 'DTE';
45
+
46
+	/**
47
+	 * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
48
+	 */
49
+	const inactive = 'DTI';
50
+
51
+
52
+	/**
53
+	 * @param array  $props_n_values    incoming values
54
+	 * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
55
+	 * @param array  $date_formats      incoming date_formats in an array where the first value is the date_format
56
+	 *                                  and the second value is the time format
57
+	 * @return EE_Datetime
58
+	 * @throws ReflectionException
59
+	 * @throws InvalidArgumentException
60
+	 * @throws InvalidInterfaceException
61
+	 * @throws InvalidDataTypeException
62
+	 * @throws EE_Error
63
+	 */
64
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
65
+	{
66
+		$has_object = parent::_check_for_object(
67
+			$props_n_values,
68
+			__CLASS__,
69
+			$timezone,
70
+			$date_formats
71
+		);
72
+		return $has_object
73
+			? $has_object
74
+			: new self($props_n_values, false, $timezone, $date_formats);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param array  $props_n_values  incoming values from the database
80
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
+	 *                                the website will be used.
82
+	 * @return EE_Datetime
83
+	 * @throws ReflectionException
84
+	 * @throws InvalidArgumentException
85
+	 * @throws InvalidInterfaceException
86
+	 * @throws InvalidDataTypeException
87
+	 * @throws EE_Error
88
+	 */
89
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
90
+	{
91
+		return new self($props_n_values, true, $timezone);
92
+	}
93
+
94
+
95
+	/**
96
+	 * @param $name
97
+	 * @throws ReflectionException
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidInterfaceException
100
+	 * @throws InvalidDataTypeException
101
+	 * @throws EE_Error
102
+	 */
103
+	public function set_name($name)
104
+	{
105
+		$this->set('DTT_name', $name);
106
+	}
107
+
108
+
109
+	/**
110
+	 * @param $description
111
+	 * @throws ReflectionException
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidInterfaceException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws EE_Error
116
+	 */
117
+	public function set_description($description)
118
+	{
119
+		$this->set('DTT_description', $description);
120
+	}
121
+
122
+
123
+	/**
124
+	 * Set event start date
125
+	 * set the start date for an event
126
+	 *
127
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
128
+	 * @throws ReflectionException
129
+	 * @throws InvalidArgumentException
130
+	 * @throws InvalidInterfaceException
131
+	 * @throws InvalidDataTypeException
132
+	 * @throws EE_Error
133
+	 */
134
+	public function set_start_date($date)
135
+	{
136
+		$this->_set_date_for($date, 'DTT_EVT_start');
137
+	}
138
+
139
+
140
+	/**
141
+	 * Set event start time
142
+	 * set the start time for an event
143
+	 *
144
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
145
+	 * @throws ReflectionException
146
+	 * @throws InvalidArgumentException
147
+	 * @throws InvalidInterfaceException
148
+	 * @throws InvalidDataTypeException
149
+	 * @throws EE_Error
150
+	 */
151
+	public function set_start_time($time)
152
+	{
153
+		$this->_set_time_for($time, 'DTT_EVT_start');
154
+	}
155
+
156
+
157
+	/**
158
+	 * Set event end date
159
+	 * set the end date for an event
160
+	 *
161
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
162
+	 * @throws ReflectionException
163
+	 * @throws InvalidArgumentException
164
+	 * @throws InvalidInterfaceException
165
+	 * @throws InvalidDataTypeException
166
+	 * @throws EE_Error
167
+	 */
168
+	public function set_end_date($date)
169
+	{
170
+		$this->_set_date_for($date, 'DTT_EVT_end');
171
+	}
172
+
173
+
174
+	/**
175
+	 * Set event end time
176
+	 * set the end time for an event
177
+	 *
178
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
179
+	 * @throws ReflectionException
180
+	 * @throws InvalidArgumentException
181
+	 * @throws InvalidInterfaceException
182
+	 * @throws InvalidDataTypeException
183
+	 * @throws EE_Error
184
+	 */
185
+	public function set_end_time($time)
186
+	{
187
+		$this->_set_time_for($time, 'DTT_EVT_end');
188
+	}
189
+
190
+
191
+	/**
192
+	 * Set registration limit
193
+	 * set the maximum number of attendees that can be registered for this datetime slot
194
+	 *
195
+	 * @param int $reg_limit
196
+	 * @throws ReflectionException
197
+	 * @throws InvalidArgumentException
198
+	 * @throws InvalidInterfaceException
199
+	 * @throws InvalidDataTypeException
200
+	 * @throws EE_Error
201
+	 */
202
+	public function set_reg_limit($reg_limit)
203
+	{
204
+		$this->set('DTT_reg_limit', $reg_limit);
205
+	}
206
+
207
+
208
+	/**
209
+	 * get the number of tickets sold for this datetime slot
210
+	 *
211
+	 * @return mixed int on success, FALSE on fail
212
+	 * @throws ReflectionException
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidInterfaceException
215
+	 * @throws InvalidDataTypeException
216
+	 * @throws EE_Error
217
+	 */
218
+	public function sold()
219
+	{
220
+		return $this->get_raw('DTT_sold');
221
+	}
222
+
223
+
224
+	/**
225
+	 * @param int $sold
226
+	 * @throws ReflectionException
227
+	 * @throws InvalidArgumentException
228
+	 * @throws InvalidInterfaceException
229
+	 * @throws InvalidDataTypeException
230
+	 * @throws EE_Error
231
+	 */
232
+	public function set_sold($sold)
233
+	{
234
+		// sold can not go below zero
235
+		$sold = max(0, $sold);
236
+		$this->set('DTT_sold', $sold);
237
+	}
238
+
239
+
240
+	/**
241
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
242
+	 * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
243
+	 *
244
+	 * @param int $qty
245
+	 * @param boolean $also_decrease_reserved
246
+	 * @return boolean indicating success
247
+	 * @throws ReflectionException
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidInterfaceException
250
+	 * @throws InvalidDataTypeException
251
+	 * @throws EE_Error
252
+	 */
253
+	public function increaseSold($qty = 1, $also_decrease_reserved = true)
254
+	{
255
+		$qty = absint($qty);
256
+		if ($also_decrease_reserved) {
257
+			$success = $this->adjustNumericFieldsInDb(
258
+				[
259
+					'DTT_reserved' => $qty * -1,
260
+					'DTT_sold' => $qty
261
+				]
262
+			);
263
+		} else {
264
+			$success = $this->adjustNumericFieldsInDb(
265
+				[
266
+					'DTT_sold' => $qty
267
+				]
268
+			);
269
+		}
270
+
271
+		do_action(
272
+			'AHEE__EE_Datetime__increase_sold',
273
+			$this,
274
+			$qty,
275
+			$this->sold(),
276
+			$success
277
+		);
278
+		return $success;
279
+	}
280
+
281
+
282
+	/**
283
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
284
+	 * to save afterwards.)
285
+	 *
286
+	 * @param int $qty
287
+	 * @return boolean indicating success
288
+	 * @throws ReflectionException
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidInterfaceException
291
+	 * @throws InvalidDataTypeException
292
+	 * @throws EE_Error
293
+	 */
294
+	public function decreaseSold($qty = 1)
295
+	{
296
+		$qty = absint($qty);
297
+		$success = $this->adjustNumericFieldsInDb(
298
+			[
299
+				'DTT_sold' => $qty * -1
300
+			]
301
+		);
302
+		do_action(
303
+			'AHEE__EE_Datetime__decrease_sold',
304
+			$this,
305
+			$qty,
306
+			$this->sold(),
307
+			$success
308
+		);
309
+		return $success;
310
+	}
311
+
312
+
313
+	/**
314
+	 * Gets qty of reserved tickets for this datetime
315
+	 *
316
+	 * @return int
317
+	 * @throws ReflectionException
318
+	 * @throws InvalidArgumentException
319
+	 * @throws InvalidInterfaceException
320
+	 * @throws InvalidDataTypeException
321
+	 * @throws EE_Error
322
+	 */
323
+	public function reserved()
324
+	{
325
+		return $this->get_raw('DTT_reserved');
326
+	}
327
+
328
+
329
+	/**
330
+	 * Sets qty of reserved tickets for this datetime
331
+	 *
332
+	 * @param int $reserved
333
+	 * @throws ReflectionException
334
+	 * @throws InvalidArgumentException
335
+	 * @throws InvalidInterfaceException
336
+	 * @throws InvalidDataTypeException
337
+	 * @throws EE_Error
338
+	 */
339
+	public function set_reserved($reserved)
340
+	{
341
+		// reserved can not go below zero
342
+		$reserved = max(0, (int) $reserved);
343
+		$this->set('DTT_reserved', $reserved);
344
+	}
345
+
346
+
347
+	/**
348
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
349
+	 *
350
+	 * @param int $qty
351
+	 * @return boolean indicating success
352
+	 * @throws ReflectionException
353
+	 * @throws InvalidArgumentException
354
+	 * @throws InvalidInterfaceException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws EE_Error
357
+	 */
358
+	public function increaseReserved($qty = 1)
359
+	{
360
+		$qty = absint($qty);
361
+		$success = $this->incrementFieldConditionallyInDb(
362
+			'DTT_reserved',
363
+			'DTT_sold',
364
+			'DTT_reg_limit',
365
+			$qty
366
+		);
367
+		do_action(
368
+			'AHEE__EE_Datetime__increase_reserved',
369
+			$this,
370
+			$qty,
371
+			$this->reserved(),
372
+			$success
373
+		);
374
+		return $success;
375
+	}
376
+
377
+
378
+	/**
379
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
380
+	 *
381
+	 * @param int $qty
382
+	 * @return boolean indicating success
383
+	 * @throws ReflectionException
384
+	 * @throws InvalidArgumentException
385
+	 * @throws InvalidInterfaceException
386
+	 * @throws InvalidDataTypeException
387
+	 * @throws EE_Error
388
+	 */
389
+	public function decreaseReserved($qty = 1)
390
+	{
391
+		$qty = absint($qty);
392
+		$success = $this->adjustNumericFieldsInDb(
393
+			[
394
+				'DTT_reserved' => $qty * -1
395
+			]
396
+		);
397
+		do_action(
398
+			'AHEE__EE_Datetime__decrease_reserved',
399
+			$this,
400
+			$qty,
401
+			$this->reserved(),
402
+			$success
403
+		);
404
+		return $success;
405
+	}
406
+
407
+
408
+	/**
409
+	 * total sold and reserved tickets
410
+	 *
411
+	 * @return int
412
+	 * @throws ReflectionException
413
+	 * @throws InvalidArgumentException
414
+	 * @throws InvalidInterfaceException
415
+	 * @throws InvalidDataTypeException
416
+	 * @throws EE_Error
417
+	 */
418
+	public function sold_and_reserved()
419
+	{
420
+		return $this->sold() + $this->reserved();
421
+	}
422
+
423
+
424
+	/**
425
+	 * returns the datetime name
426
+	 *
427
+	 * @return string
428
+	 * @throws ReflectionException
429
+	 * @throws InvalidArgumentException
430
+	 * @throws InvalidInterfaceException
431
+	 * @throws InvalidDataTypeException
432
+	 * @throws EE_Error
433
+	 */
434
+	public function name()
435
+	{
436
+		return $this->get('DTT_name');
437
+	}
438
+
439
+
440
+	/**
441
+	 * returns the datetime description
442
+	 *
443
+	 * @return string
444
+	 * @throws ReflectionException
445
+	 * @throws InvalidArgumentException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws EE_Error
449
+	 */
450
+	public function description()
451
+	{
452
+		return $this->get('DTT_description');
453
+	}
454
+
455
+
456
+	/**
457
+	 * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
458
+	 *
459
+	 * @return boolean  TRUE if is primary, FALSE if not.
460
+	 * @throws ReflectionException
461
+	 * @throws InvalidArgumentException
462
+	 * @throws InvalidInterfaceException
463
+	 * @throws InvalidDataTypeException
464
+	 * @throws EE_Error
465
+	 */
466
+	public function is_primary()
467
+	{
468
+		return $this->get('DTT_is_primary');
469
+	}
470
+
471
+
472
+	/**
473
+	 * This helper simply returns the order for the datetime
474
+	 *
475
+	 * @return int  The order of the datetime for this event.
476
+	 * @throws ReflectionException
477
+	 * @throws InvalidArgumentException
478
+	 * @throws InvalidInterfaceException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws EE_Error
481
+	 */
482
+	public function order()
483
+	{
484
+		return $this->get('DTT_order');
485
+	}
486
+
487
+
488
+	/**
489
+	 * This helper simply returns the parent id for the datetime
490
+	 *
491
+	 * @return int
492
+	 * @throws ReflectionException
493
+	 * @throws InvalidArgumentException
494
+	 * @throws InvalidInterfaceException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws EE_Error
497
+	 */
498
+	public function parent()
499
+	{
500
+		return $this->get('DTT_parent');
501
+	}
502
+
503
+
504
+	/**
505
+	 * show date and/or time
506
+	 *
507
+	 * @param string $date_or_time    whether to display a date or time or both
508
+	 * @param string $start_or_end    whether to display start or end datetimes
509
+	 * @param string $dt_frmt
510
+	 * @param string $tm_frmt
511
+	 * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
512
+	 *                                otherwise we use the standard formats)
513
+	 * @return string|bool  string on success, FALSE on fail
514
+	 * @throws ReflectionException
515
+	 * @throws InvalidArgumentException
516
+	 * @throws InvalidInterfaceException
517
+	 * @throws InvalidDataTypeException
518
+	 * @throws EE_Error
519
+	 */
520
+	private function _show_datetime(
521
+		$date_or_time = null,
522
+		$start_or_end = 'start',
523
+		$dt_frmt = '',
524
+		$tm_frmt = '',
525
+		$echo = false
526
+	) {
527
+		$field_name = "DTT_EVT_{$start_or_end}";
528
+		$dtt = $this->_get_datetime(
529
+			$field_name,
530
+			$dt_frmt,
531
+			$tm_frmt,
532
+			$date_or_time,
533
+			$echo
534
+		);
535
+		if (! $echo) {
536
+			return $dtt;
537
+		}
538
+		return '';
539
+	}
540
+
541
+
542
+	/**
543
+	 * get event start date.  Provide either the date format, or NULL to re-use the
544
+	 * last-used format, or '' to use the default date format
545
+	 *
546
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
547
+	 * @return mixed            string on success, FALSE on fail
548
+	 * @throws ReflectionException
549
+	 * @throws InvalidArgumentException
550
+	 * @throws InvalidInterfaceException
551
+	 * @throws InvalidDataTypeException
552
+	 * @throws EE_Error
553
+	 */
554
+	public function start_date($dt_frmt = '')
555
+	{
556
+		return $this->_show_datetime('D', 'start', $dt_frmt);
557
+	}
558
+
559
+
560
+	/**
561
+	 * Echoes start_date()
562
+	 *
563
+	 * @param string $dt_frmt
564
+	 * @throws ReflectionException
565
+	 * @throws InvalidArgumentException
566
+	 * @throws InvalidInterfaceException
567
+	 * @throws InvalidDataTypeException
568
+	 * @throws EE_Error
569
+	 */
570
+	public function e_start_date($dt_frmt = '')
571
+	{
572
+		$this->_show_datetime('D', 'start', $dt_frmt, null, true);
573
+	}
574
+
575
+
576
+	/**
577
+	 * get end date. Provide either the date format, or NULL to re-use the
578
+	 * last-used format, or '' to use the default date format
579
+	 *
580
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
581
+	 * @return mixed            string on success, FALSE on fail
582
+	 * @throws ReflectionException
583
+	 * @throws InvalidArgumentException
584
+	 * @throws InvalidInterfaceException
585
+	 * @throws InvalidDataTypeException
586
+	 * @throws EE_Error
587
+	 */
588
+	public function end_date($dt_frmt = '')
589
+	{
590
+		return $this->_show_datetime('D', 'end', $dt_frmt);
591
+	}
592
+
593
+
594
+	/**
595
+	 * Echoes the end date. See end_date()
596
+	 *
597
+	 * @param string $dt_frmt
598
+	 * @throws ReflectionException
599
+	 * @throws InvalidArgumentException
600
+	 * @throws InvalidInterfaceException
601
+	 * @throws InvalidDataTypeException
602
+	 * @throws EE_Error
603
+	 */
604
+	public function e_end_date($dt_frmt = '')
605
+	{
606
+		$this->_show_datetime('D', 'end', $dt_frmt, null, true);
607
+	}
608
+
609
+
610
+	/**
611
+	 * get date_range - meaning the start AND end date
612
+	 *
613
+	 * @access public
614
+	 * @param string $dt_frmt     string representation of date format defaults to WP settings
615
+	 * @param string $conjunction conjunction junction what's your function ?
616
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
617
+	 * @return mixed              string on success, FALSE on fail
618
+	 * @throws ReflectionException
619
+	 * @throws InvalidArgumentException
620
+	 * @throws InvalidInterfaceException
621
+	 * @throws InvalidDataTypeException
622
+	 * @throws EE_Error
623
+	 */
624
+	public function date_range($dt_frmt = '', $conjunction = ' - ')
625
+	{
626
+		$dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
627
+		$start = str_replace(
628
+			' ',
629
+			'&nbsp;',
630
+			$this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
631
+		);
632
+		$end = str_replace(
633
+			' ',
634
+			'&nbsp;',
635
+			$this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
636
+		);
637
+		return $start !== $end ? $start . $conjunction . $end : $start;
638
+	}
639
+
640
+
641
+	/**
642
+	 * @param string $dt_frmt
643
+	 * @param string $conjunction
644
+	 * @throws ReflectionException
645
+	 * @throws InvalidArgumentException
646
+	 * @throws InvalidInterfaceException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws EE_Error
649
+	 */
650
+	public function e_date_range($dt_frmt = '', $conjunction = ' - ')
651
+	{
652
+		echo esc_html($this->date_range($dt_frmt, $conjunction));
653
+	}
654
+
655
+
656
+	/**
657
+	 * get start time
658
+	 *
659
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
660
+	 * @return mixed        string on success, FALSE on fail
661
+	 * @throws ReflectionException
662
+	 * @throws InvalidArgumentException
663
+	 * @throws InvalidInterfaceException
664
+	 * @throws InvalidDataTypeException
665
+	 * @throws EE_Error
666
+	 */
667
+	public function start_time($tm_format = '')
668
+	{
669
+		return $this->_show_datetime('T', 'start', null, $tm_format);
670
+	}
671
+
672
+
673
+	/**
674
+	 * @param string $tm_format
675
+	 * @throws ReflectionException
676
+	 * @throws InvalidArgumentException
677
+	 * @throws InvalidInterfaceException
678
+	 * @throws InvalidDataTypeException
679
+	 * @throws EE_Error
680
+	 */
681
+	public function e_start_time($tm_format = '')
682
+	{
683
+		$this->_show_datetime('T', 'start', null, $tm_format, true);
684
+	}
685
+
686
+
687
+	/**
688
+	 * get end time
689
+	 *
690
+	 * @param string $tm_format string representation of time format defaults to 'g:i a'
691
+	 * @return mixed                string on success, FALSE on fail
692
+	 * @throws ReflectionException
693
+	 * @throws InvalidArgumentException
694
+	 * @throws InvalidInterfaceException
695
+	 * @throws InvalidDataTypeException
696
+	 * @throws EE_Error
697
+	 */
698
+	public function end_time($tm_format = '')
699
+	{
700
+		return $this->_show_datetime('T', 'end', null, $tm_format);
701
+	}
702
+
703
+
704
+	/**
705
+	 * @param string $tm_format
706
+	 * @throws ReflectionException
707
+	 * @throws InvalidArgumentException
708
+	 * @throws InvalidInterfaceException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws EE_Error
711
+	 */
712
+	public function e_end_time($tm_format = '')
713
+	{
714
+		$this->_show_datetime('T', 'end', null, $tm_format, true);
715
+	}
716
+
717
+
718
+	/**
719
+	 * get time_range
720
+	 *
721
+	 * @access public
722
+	 * @param string $tm_format   string representation of time format defaults to 'g:i a'
723
+	 * @param string $conjunction conjunction junction what's your function ?
724
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
725
+	 * @return mixed              string on success, FALSE on fail
726
+	 * @throws ReflectionException
727
+	 * @throws InvalidArgumentException
728
+	 * @throws InvalidInterfaceException
729
+	 * @throws InvalidDataTypeException
730
+	 * @throws EE_Error
731
+	 */
732
+	public function time_range($tm_format = '', $conjunction = ' - ')
733
+	{
734
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
735
+		$start = str_replace(
736
+			' ',
737
+			'&nbsp;',
738
+			$this->get_i18n_datetime('DTT_EVT_start', $tm_format)
739
+		);
740
+		$end = str_replace(
741
+			' ',
742
+			'&nbsp;',
743
+			$this->get_i18n_datetime('DTT_EVT_end', $tm_format)
744
+		);
745
+		return $start !== $end ? $start . $conjunction . $end : $start;
746
+	}
747
+
748
+
749
+	/**
750
+	 * @param string $tm_format
751
+	 * @param string $conjunction
752
+	 * @throws ReflectionException
753
+	 * @throws InvalidArgumentException
754
+	 * @throws InvalidInterfaceException
755
+	 * @throws InvalidDataTypeException
756
+	 * @throws EE_Error
757
+	 */
758
+	public function e_time_range($tm_format = '', $conjunction = ' - ')
759
+	{
760
+		echo esc_html($this->time_range($tm_format, $conjunction));
761
+	}
762
+
763
+
764
+	/**
765
+	 * This returns a range representation of the date and times.
766
+	 * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
767
+	 * Also, the return value is localized.
768
+	 *
769
+	 * @param string $dt_format
770
+	 * @param string $tm_format
771
+	 * @param string $conjunction used between two different dates or times.
772
+	 *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
773
+	 * @param string $separator   used between the date and time formats.
774
+	 *                            ex: Dec 1, 2016{$separator}2pm
775
+	 * @return string
776
+	 * @throws ReflectionException
777
+	 * @throws InvalidArgumentException
778
+	 * @throws InvalidInterfaceException
779
+	 * @throws InvalidDataTypeException
780
+	 * @throws EE_Error
781
+	 */
782
+	public function date_and_time_range(
783
+		$dt_format = '',
784
+		$tm_format = '',
785
+		$conjunction = ' - ',
786
+		$separator = ' '
787
+	) {
788
+		$dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
789
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
790
+		$full_format = $dt_format . $separator . $tm_format;
791
+		// the range output depends on various conditions
792
+		switch (true) {
793
+			// start date timestamp and end date timestamp are the same.
794
+			case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
795
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
796
+				break;
797
+			// start and end date are the same but times are different
798
+			case ($this->start_date() === $this->end_date()):
799
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
800
+						  . $conjunction
801
+						  . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
802
+				break;
803
+			// all other conditions
804
+			default:
805
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
806
+						  . $conjunction
807
+						  . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
808
+				break;
809
+		}
810
+		return $output;
811
+	}
812
+
813
+
814
+	/**
815
+	 * This echos the results of date and time range.
816
+	 *
817
+	 * @see date_and_time_range() for more details on purpose.
818
+	 * @param string $dt_format
819
+	 * @param string $tm_format
820
+	 * @param string $conjunction
821
+	 * @return void
822
+	 * @throws ReflectionException
823
+	 * @throws InvalidArgumentException
824
+	 * @throws InvalidInterfaceException
825
+	 * @throws InvalidDataTypeException
826
+	 * @throws EE_Error
827
+	 */
828
+	public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
829
+	{
830
+		echo esc_html($this->date_and_time_range($dt_format, $tm_format, $conjunction));
831
+	}
832
+
833
+
834
+	/**
835
+	 * get start date and start time
836
+	 *
837
+	 * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
838
+	 * @param    string $tm_format - string representation of time format defaults to 'g:i a'
839
+	 * @return    mixed    string on success, FALSE on fail
840
+	 * @throws ReflectionException
841
+	 * @throws InvalidArgumentException
842
+	 * @throws InvalidInterfaceException
843
+	 * @throws InvalidDataTypeException
844
+	 * @throws EE_Error
845
+	 */
846
+	public function start_date_and_time($dt_format = '', $tm_format = '')
847
+	{
848
+		return $this->_show_datetime('', 'start', $dt_format, $tm_format);
849
+	}
850
+
851
+
852
+	/**
853
+	 * @param string $dt_frmt
854
+	 * @param string $tm_format
855
+	 * @throws ReflectionException
856
+	 * @throws InvalidArgumentException
857
+	 * @throws InvalidInterfaceException
858
+	 * @throws InvalidDataTypeException
859
+	 * @throws EE_Error
860
+	 */
861
+	public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
862
+	{
863
+		$this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
864
+	}
865
+
866
+
867
+	/**
868
+	 * Shows the length of the event (start to end time).
869
+	 * Can be shown in 'seconds','minutes','hours', or 'days'.
870
+	 * By default, rounds up. (So if you use 'days', and then event
871
+	 * only occurs for 1 hour, it will return 1 day).
872
+	 *
873
+	 * @param string $units 'seconds','minutes','hours','days'
874
+	 * @param bool   $round_up
875
+	 * @return float|int|mixed
876
+	 * @throws ReflectionException
877
+	 * @throws InvalidArgumentException
878
+	 * @throws InvalidInterfaceException
879
+	 * @throws InvalidDataTypeException
880
+	 * @throws EE_Error
881
+	 */
882
+	public function length($units = 'seconds', $round_up = false)
883
+	{
884
+		$start = $this->get_raw('DTT_EVT_start');
885
+		$end = $this->get_raw('DTT_EVT_end');
886
+		$length_in_units = $end - $start;
887
+		switch ($units) {
888
+			// NOTE: We purposefully don't use "break;" in order to chain the divisions
889
+			/** @noinspection PhpMissingBreakStatementInspection */
890
+			// phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
891
+			case 'days':
892
+				$length_in_units /= 24;
893
+			/** @noinspection PhpMissingBreakStatementInspection */
894
+			case 'hours':
895
+				// fall through is intentional
896
+				$length_in_units /= 60;
897
+			/** @noinspection PhpMissingBreakStatementInspection */
898
+			case 'minutes':
899
+				// fall through is intentional
900
+				$length_in_units /= 60;
901
+			case 'seconds':
902
+			default:
903
+				$length_in_units = ceil($length_in_units);
904
+		}
905
+		// phpcs:enable
906
+		if ($round_up) {
907
+			$length_in_units = max($length_in_units, 1);
908
+		}
909
+		return $length_in_units;
910
+	}
911
+
912
+
913
+	/**
914
+	 *        get end date and time
915
+	 *
916
+	 * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
917
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
918
+	 * @return    mixed                string on success, FALSE on fail
919
+	 * @throws ReflectionException
920
+	 * @throws InvalidArgumentException
921
+	 * @throws InvalidInterfaceException
922
+	 * @throws InvalidDataTypeException
923
+	 * @throws EE_Error
924
+	 */
925
+	public function end_date_and_time($dt_frmt = '', $tm_format = '')
926
+	{
927
+		return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
928
+	}
929
+
930
+
931
+	/**
932
+	 * @param string $dt_frmt
933
+	 * @param string $tm_format
934
+	 * @throws ReflectionException
935
+	 * @throws InvalidArgumentException
936
+	 * @throws InvalidInterfaceException
937
+	 * @throws InvalidDataTypeException
938
+	 * @throws EE_Error
939
+	 */
940
+	public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
941
+	{
942
+		$this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
943
+	}
944
+
945
+
946
+	/**
947
+	 *        get start timestamp
948
+	 *
949
+	 * @return        int
950
+	 * @throws ReflectionException
951
+	 * @throws InvalidArgumentException
952
+	 * @throws InvalidInterfaceException
953
+	 * @throws InvalidDataTypeException
954
+	 * @throws EE_Error
955
+	 */
956
+	public function start()
957
+	{
958
+		return $this->get_raw('DTT_EVT_start');
959
+	}
960
+
961
+
962
+	/**
963
+	 *        get end timestamp
964
+	 *
965
+	 * @return        int
966
+	 * @throws ReflectionException
967
+	 * @throws InvalidArgumentException
968
+	 * @throws InvalidInterfaceException
969
+	 * @throws InvalidDataTypeException
970
+	 * @throws EE_Error
971
+	 */
972
+	public function end()
973
+	{
974
+		return $this->get_raw('DTT_EVT_end');
975
+	}
976
+
977
+
978
+	/**
979
+	 *    get the registration limit for this datetime slot
980
+	 *
981
+	 * @return        mixed        int on success, FALSE on fail
982
+	 * @throws ReflectionException
983
+	 * @throws InvalidArgumentException
984
+	 * @throws InvalidInterfaceException
985
+	 * @throws InvalidDataTypeException
986
+	 * @throws EE_Error
987
+	 */
988
+	public function reg_limit()
989
+	{
990
+		return $this->get_raw('DTT_reg_limit');
991
+	}
992
+
993
+
994
+	/**
995
+	 *    have the tickets sold for this datetime, met or exceed the registration limit ?
996
+	 *
997
+	 * @return        boolean
998
+	 * @throws ReflectionException
999
+	 * @throws InvalidArgumentException
1000
+	 * @throws InvalidInterfaceException
1001
+	 * @throws InvalidDataTypeException
1002
+	 * @throws EE_Error
1003
+	 */
1004
+	public function sold_out()
1005
+	{
1006
+		return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * return the total number of spaces remaining at this venue.
1012
+	 * This only takes the venue's capacity into account, NOT the tickets available for sale
1013
+	 *
1014
+	 * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1015
+	 *                               Because if all tickets attached to this datetime have no spaces left,
1016
+	 *                               then this datetime IS effectively sold out.
1017
+	 *                               However, there are cases where we just want to know the spaces
1018
+	 *                               remaining for this particular datetime, hence the flag.
1019
+	 * @return int
1020
+	 * @throws ReflectionException
1021
+	 * @throws InvalidArgumentException
1022
+	 * @throws InvalidInterfaceException
1023
+	 * @throws InvalidDataTypeException
1024
+	 * @throws EE_Error
1025
+	 */
1026
+	public function spaces_remaining($consider_tickets = false)
1027
+	{
1028
+		// tickets remaining available for purchase
1029
+		// no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1030
+		$dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1031
+		if (! $consider_tickets) {
1032
+			return $dtt_remaining;
1033
+		}
1034
+		$tickets_remaining = $this->tickets_remaining();
1035
+		return min($dtt_remaining, $tickets_remaining);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * Counts the total tickets available
1041
+	 * (from all the different types of tickets which are available for this datetime).
1042
+	 *
1043
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1044
+	 * @return int
1045
+	 * @throws ReflectionException
1046
+	 * @throws InvalidArgumentException
1047
+	 * @throws InvalidInterfaceException
1048
+	 * @throws InvalidDataTypeException
1049
+	 * @throws EE_Error
1050
+	 */
1051
+	public function tickets_remaining($query_params = array())
1052
+	{
1053
+		$sum = 0;
1054
+		$tickets = $this->tickets($query_params);
1055
+		if (! empty($tickets)) {
1056
+			foreach ($tickets as $ticket) {
1057
+				if ($ticket instanceof EE_Ticket) {
1058
+					// get the actual amount of tickets that can be sold
1059
+					$qty = $ticket->qty('saleable');
1060
+					if ($qty === EE_INF) {
1061
+						return EE_INF;
1062
+					}
1063
+					// no negative ticket quantities plz
1064
+					if ($qty > 0) {
1065
+						$sum += $qty;
1066
+					}
1067
+				}
1068
+			}
1069
+		}
1070
+		return $sum;
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * Gets the count of all the tickets available at this datetime (not ticket types)
1076
+	 * before any were sold
1077
+	 *
1078
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1079
+	 * @return int
1080
+	 * @throws ReflectionException
1081
+	 * @throws InvalidArgumentException
1082
+	 * @throws InvalidInterfaceException
1083
+	 * @throws InvalidDataTypeException
1084
+	 * @throws EE_Error
1085
+	 */
1086
+	public function sum_tickets_initially_available($query_params = array())
1087
+	{
1088
+		return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * Returns the lesser-of-the two: spaces remaining at this datetime, or
1094
+	 * the total tickets remaining (a sum of the tickets remaining for each ticket type
1095
+	 * that is available for this datetime).
1096
+	 *
1097
+	 * @return int
1098
+	 * @throws ReflectionException
1099
+	 * @throws InvalidArgumentException
1100
+	 * @throws InvalidInterfaceException
1101
+	 * @throws InvalidDataTypeException
1102
+	 * @throws EE_Error
1103
+	 */
1104
+	public function total_tickets_available_at_this_datetime()
1105
+	{
1106
+		return $this->spaces_remaining(true);
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * This simply compares the internal dtt for the given string with NOW
1112
+	 * and determines if the date is upcoming or not.
1113
+	 *
1114
+	 * @access public
1115
+	 * @return boolean
1116
+	 * @throws ReflectionException
1117
+	 * @throws InvalidArgumentException
1118
+	 * @throws InvalidInterfaceException
1119
+	 * @throws InvalidDataTypeException
1120
+	 * @throws EE_Error
1121
+	 */
1122
+	public function is_upcoming()
1123
+	{
1124
+		return ($this->get_raw('DTT_EVT_start') > time());
1125
+	}
1126
+
1127
+
1128
+	/**
1129
+	 * This simply compares the internal datetime for the given string with NOW
1130
+	 * and returns if the date is active (i.e. start and end time)
1131
+	 *
1132
+	 * @return boolean
1133
+	 * @throws ReflectionException
1134
+	 * @throws InvalidArgumentException
1135
+	 * @throws InvalidInterfaceException
1136
+	 * @throws InvalidDataTypeException
1137
+	 * @throws EE_Error
1138
+	 */
1139
+	public function is_active()
1140
+	{
1141
+		return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 * This simply compares the internal dtt for the given string with NOW
1147
+	 * and determines if the date is expired or not.
1148
+	 *
1149
+	 * @return boolean
1150
+	 * @throws ReflectionException
1151
+	 * @throws InvalidArgumentException
1152
+	 * @throws InvalidInterfaceException
1153
+	 * @throws InvalidDataTypeException
1154
+	 * @throws EE_Error
1155
+	 */
1156
+	public function is_expired()
1157
+	{
1158
+		return ($this->get_raw('DTT_EVT_end') < time());
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * This returns the active status for whether an event is active, upcoming, or expired
1164
+	 *
1165
+	 * @return int return value will be one of the EE_Datetime status constants.
1166
+	 * @throws ReflectionException
1167
+	 * @throws InvalidArgumentException
1168
+	 * @throws InvalidInterfaceException
1169
+	 * @throws InvalidDataTypeException
1170
+	 * @throws EE_Error
1171
+	 */
1172
+	public function get_active_status()
1173
+	{
1174
+		$total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1175
+		if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1176
+			return EE_Datetime::sold_out;
1177
+		}
1178
+		if ($this->is_expired()) {
1179
+			return EE_Datetime::expired;
1180
+		}
1181
+		if ($this->is_upcoming()) {
1182
+			return EE_Datetime::upcoming;
1183
+		}
1184
+		if ($this->is_active()) {
1185
+			return EE_Datetime::active;
1186
+		}
1187
+		return null;
1188
+	}
1189
+
1190
+
1191
+	/**
1192
+	 * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1193
+	 *
1194
+	 * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1195
+	 * @return string
1196
+	 * @throws ReflectionException
1197
+	 * @throws InvalidArgumentException
1198
+	 * @throws InvalidInterfaceException
1199
+	 * @throws InvalidDataTypeException
1200
+	 * @throws EE_Error
1201
+	 */
1202
+	public function get_dtt_display_name($use_dtt_name = false)
1203
+	{
1204
+		if ($use_dtt_name) {
1205
+			$dtt_name = $this->name();
1206
+			if (! empty($dtt_name)) {
1207
+				return $dtt_name;
1208
+			}
1209
+		}
1210
+		// first condition is to see if the months are different
1211
+		if (
1212
+			date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1213
+		) {
1214
+			$display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
+			// next condition is if its the same month but different day
1216
+		} else {
1217
+			if (
1218
+				date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1219
+				&& date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1220
+			) {
1221
+				$display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1222
+			} else {
1223
+				$display_date = $this->start_date('F j\, Y')
1224
+								. ' @ '
1225
+								. $this->start_date('g:i a')
1226
+								. ' - '
1227
+								. $this->end_date('g:i a');
1228
+			}
1229
+		}
1230
+		return $display_date;
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 * Gets all the tickets for this datetime
1236
+	 *
1237
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1238
+	 * @return EE_Base_Class[]|EE_Ticket[]
1239
+	 * @throws ReflectionException
1240
+	 * @throws InvalidArgumentException
1241
+	 * @throws InvalidInterfaceException
1242
+	 * @throws InvalidDataTypeException
1243
+	 * @throws EE_Error
1244
+	 */
1245
+	public function tickets($query_params = array())
1246
+	{
1247
+		return $this->get_many_related('Ticket', $query_params);
1248
+	}
1249
+
1250
+
1251
+	/**
1252
+	 * Gets all the ticket types currently available for purchase
1253
+	 *
1254
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1255
+	 * @return EE_Ticket[]
1256
+	 * @throws ReflectionException
1257
+	 * @throws InvalidArgumentException
1258
+	 * @throws InvalidInterfaceException
1259
+	 * @throws InvalidDataTypeException
1260
+	 * @throws EE_Error
1261
+	 */
1262
+	public function ticket_types_available_for_purchase($query_params = array())
1263
+	{
1264
+		// first check if datetime is valid
1265
+		if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1266
+			return array();
1267
+		}
1268
+		if (empty($query_params)) {
1269
+			$query_params = array(
1270
+				array(
1271
+					'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1272
+					'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1273
+					'TKT_deleted'    => false,
1274
+				),
1275
+			);
1276
+		}
1277
+		return $this->tickets($query_params);
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * @return EE_Base_Class|EE_Event
1283
+	 * @throws ReflectionException
1284
+	 * @throws InvalidArgumentException
1285
+	 * @throws InvalidInterfaceException
1286
+	 * @throws InvalidDataTypeException
1287
+	 * @throws EE_Error
1288
+	 */
1289
+	public function event()
1290
+	{
1291
+		return $this->get_first_related('Event');
1292
+	}
1293
+
1294
+
1295
+	/**
1296
+	 * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1297
+	 * (via the tickets).
1298
+	 *
1299
+	 * @return int
1300
+	 * @throws ReflectionException
1301
+	 * @throws InvalidArgumentException
1302
+	 * @throws InvalidInterfaceException
1303
+	 * @throws InvalidDataTypeException
1304
+	 * @throws EE_Error
1305
+	 */
1306
+	public function update_sold()
1307
+	{
1308
+		$count_regs_for_this_datetime = EEM_Registration::instance()->count(
1309
+			array(
1310
+				array(
1311
+					'STS_ID'                 => EEM_Registration::status_id_approved,
1312
+					'REG_deleted'            => 0,
1313
+					'Ticket.Datetime.DTT_ID' => $this->ID(),
1314
+				),
1315
+			)
1316
+		);
1317
+		$this->set_sold($count_regs_for_this_datetime);
1318
+		$this->save();
1319
+		return $count_regs_for_this_datetime;
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * Adds a venue to this event
1325
+	 *
1326
+	 * @param int|EE_Venue /int $venue_id_or_obj
1327
+	 * @return EE_Base_Class|EE_Venue
1328
+	 * @throws EE_Error
1329
+	 * @throws ReflectionException
1330
+	 */
1331
+	public function add_venue($venue_id_or_obj): EE_Venue
1332
+	{
1333
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
1334
+	}
1335
+
1336
+
1337
+	/**
1338
+	 * Removes a venue from the event
1339
+	 *
1340
+	 * @param EE_Venue /int $venue_id_or_obj
1341
+	 * @return EE_Base_Class|EE_Venue
1342
+	 * @throws EE_Error
1343
+	 * @throws ReflectionException
1344
+	 */
1345
+	public function remove_venue($venue_id_or_obj): EE_Venue
1346
+	{
1347
+		$venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
1348
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
1349
+	}
1350
+
1351
+
1352
+	/**
1353
+	 * Gets the venue related to the event. May provide additional $query_params if desired
1354
+	 *
1355
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1356
+	 * @return int
1357
+	 * @throws EE_Error
1358
+	 * @throws ReflectionException
1359
+	 */
1360
+	public function venue_ID(array $query_params = []): int
1361
+	{
1362
+		$venue = $this->get_first_related('Venue', $query_params);
1363
+		return $venue instanceof EE_Venue
1364
+			? $venue->ID()
1365
+			: 0;
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 * Gets the venue related to the event. May provide additional $query_params if desired
1371
+	 *
1372
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1373
+	 * @return EE_Base_Class|EE_Venue
1374
+	 * @throws EE_Error
1375
+	 * @throws ReflectionException
1376
+	 */
1377
+	public function venue(array $query_params = [])
1378
+	{
1379
+		return $this->get_first_related('Venue', $query_params);
1380
+	}
1381
+
1382
+
1383
+	/**
1384
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1385
+	 * @param string                   $relationName
1386
+	 * @param array                    $extra_join_model_fields_n_values
1387
+	 * @param string|null              $cache_id
1388
+	 * @return EE_Base_Class
1389
+	 * @throws EE_Error
1390
+	 * @throws ReflectionException
1391
+	 * @since   $VID:$
1392
+	 */
1393
+	public function _add_relation_to(
1394
+		$otherObjectModelObjectOrID,
1395
+		$relationName,
1396
+		$extra_join_model_fields_n_values = [],
1397
+		$cache_id = null
1398
+	) {
1399
+		// if we're adding a new relation to a ticket
1400
+		if ($relationName === 'Ticket' && ! $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1401
+			/** @var EE_Ticket $ticket */
1402
+			$ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1403
+			$this->increaseSold($ticket->sold(), false);
1404
+			$this->increaseReserved($ticket->reserved());
1405
+			$this->save();
1406
+			$otherObjectModelObjectOrID = $ticket;
1407
+		}
1408
+		return parent::_add_relation_to(
1409
+			$otherObjectModelObjectOrID,
1410
+			$relationName,
1411
+			$extra_join_model_fields_n_values,
1412
+			$cache_id
1413
+		);
1414
+	}
1415
+
1416
+
1417
+	/**
1418
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1419
+	 * @param string                   $relationName
1420
+	 * @param array                    $where_query
1421
+	 * @return bool|EE_Base_Class|null
1422
+	 * @throws EE_Error
1423
+	 * @throws ReflectionException
1424
+	 * @since   $VID:$
1425
+	 */
1426
+	public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = [])
1427
+	{
1428
+		if ($relationName === 'Ticket' && $this->hasRelation($otherObjectModelObjectOrID, $relationName)) {
1429
+			/** @var EE_Ticket $ticket */
1430
+			$ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1431
+			$this->decreaseSold($ticket->sold());
1432
+			$this->decreaseReserved($ticket->reserved());
1433
+			$this->save();
1434
+			$otherObjectModelObjectOrID = $ticket;
1435
+		}
1436
+		return parent::_remove_relation_to(
1437
+			$otherObjectModelObjectOrID,
1438
+			$relationName,
1439
+			$where_query
1440
+		);
1441
+	}
1442
+
1443
+
1444
+	/**
1445
+	 * Removes ALL the related things for the $relationName.
1446
+	 *
1447
+	 * @param string $relationName
1448
+	 * @param array  $where_query_params
1449
+	 * @return EE_Base_Class
1450
+	 * @throws ReflectionException
1451
+	 * @throws InvalidArgumentException
1452
+	 * @throws InvalidInterfaceException
1453
+	 * @throws InvalidDataTypeException
1454
+	 * @throws EE_Error
1455
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
1456
+	 */
1457
+	public function _remove_relations($relationName, $where_query_params = [])
1458
+	{
1459
+		if ($relationName === 'Ticket') {
1460
+			$tickets = $this->tickets();
1461
+			foreach ($tickets as $ticket) {
1462
+				$this->decreaseSold($ticket->sold());
1463
+				$this->decreaseReserved($ticket->reserved());
1464
+				$this->save();
1465
+			}
1466
+		}
1467
+		return parent::_remove_relations($relationName, $where_query_params);
1468
+	}
1469
+
1470
+
1471
+	/*******************************************************************
1472 1472
      ***********************  DEPRECATED METHODS  **********************
1473 1473
      *******************************************************************/
1474 1474
 
1475 1475
 
1476
-    /**
1477
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
1478
-     *
1479
-     * @deprecated 4.9.80.p
1480
-     * @param int $qty
1481
-     * @return boolean
1482
-     * @throws ReflectionException
1483
-     * @throws InvalidArgumentException
1484
-     * @throws InvalidInterfaceException
1485
-     * @throws InvalidDataTypeException
1486
-     * @throws EE_Error
1487
-     */
1488
-    public function increase_sold($qty = 1)
1489
-    {
1490
-        EE_Error::doing_it_wrong(
1491
-            __FUNCTION__,
1492
-            esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1493
-            '4.9.80.p',
1494
-            '5.0.0.p'
1495
-        );
1496
-        return $this->increaseSold($qty);
1497
-    }
1498
-
1499
-
1500
-    /**
1501
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1502
-     * to save afterwards.)
1503
-     *
1504
-     * @deprecated 4.9.80.p
1505
-     * @param int $qty
1506
-     * @return boolean
1507
-     * @throws ReflectionException
1508
-     * @throws InvalidArgumentException
1509
-     * @throws InvalidInterfaceException
1510
-     * @throws InvalidDataTypeException
1511
-     * @throws EE_Error
1512
-     */
1513
-    public function decrease_sold($qty = 1)
1514
-    {
1515
-        EE_Error::doing_it_wrong(
1516
-            __FUNCTION__,
1517
-            esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1518
-            '4.9.80.p',
1519
-            '5.0.0.p'
1520
-        );
1521
-        return $this->decreaseSold($qty);
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1527
-     *
1528
-     * @deprecated 4.9.80.p
1529
-     * @param int $qty
1530
-     * @return boolean indicating success
1531
-     * @throws ReflectionException
1532
-     * @throws InvalidArgumentException
1533
-     * @throws InvalidInterfaceException
1534
-     * @throws InvalidDataTypeException
1535
-     * @throws EE_Error
1536
-     */
1537
-    public function increase_reserved($qty = 1)
1538
-    {
1539
-        EE_Error::doing_it_wrong(
1540
-            __FUNCTION__,
1541
-            esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1542
-            '4.9.80.p',
1543
-            '5.0.0.p'
1544
-        );
1545
-        return $this->increaseReserved($qty);
1546
-    }
1547
-
1548
-
1549
-    /**
1550
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1551
-     *
1552
-     * @deprecated 4.9.80.p
1553
-     * @param int $qty
1554
-     * @return boolean
1555
-     * @throws ReflectionException
1556
-     * @throws InvalidArgumentException
1557
-     * @throws InvalidInterfaceException
1558
-     * @throws InvalidDataTypeException
1559
-     * @throws EE_Error
1560
-     */
1561
-    public function decrease_reserved($qty = 1)
1562
-    {
1563
-        EE_Error::doing_it_wrong(
1564
-            __FUNCTION__,
1565
-            esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1566
-            '4.9.80.p',
1567
-            '5.0.0.p'
1568
-        );
1569
-        return $this->decreaseReserved($qty);
1570
-    }
1476
+	/**
1477
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
1478
+	 *
1479
+	 * @deprecated 4.9.80.p
1480
+	 * @param int $qty
1481
+	 * @return boolean
1482
+	 * @throws ReflectionException
1483
+	 * @throws InvalidArgumentException
1484
+	 * @throws InvalidInterfaceException
1485
+	 * @throws InvalidDataTypeException
1486
+	 * @throws EE_Error
1487
+	 */
1488
+	public function increase_sold($qty = 1)
1489
+	{
1490
+		EE_Error::doing_it_wrong(
1491
+			__FUNCTION__,
1492
+			esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1493
+			'4.9.80.p',
1494
+			'5.0.0.p'
1495
+		);
1496
+		return $this->increaseSold($qty);
1497
+	}
1498
+
1499
+
1500
+	/**
1501
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1502
+	 * to save afterwards.)
1503
+	 *
1504
+	 * @deprecated 4.9.80.p
1505
+	 * @param int $qty
1506
+	 * @return boolean
1507
+	 * @throws ReflectionException
1508
+	 * @throws InvalidArgumentException
1509
+	 * @throws InvalidInterfaceException
1510
+	 * @throws InvalidDataTypeException
1511
+	 * @throws EE_Error
1512
+	 */
1513
+	public function decrease_sold($qty = 1)
1514
+	{
1515
+		EE_Error::doing_it_wrong(
1516
+			__FUNCTION__,
1517
+			esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1518
+			'4.9.80.p',
1519
+			'5.0.0.p'
1520
+		);
1521
+		return $this->decreaseSold($qty);
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1527
+	 *
1528
+	 * @deprecated 4.9.80.p
1529
+	 * @param int $qty
1530
+	 * @return boolean indicating success
1531
+	 * @throws ReflectionException
1532
+	 * @throws InvalidArgumentException
1533
+	 * @throws InvalidInterfaceException
1534
+	 * @throws InvalidDataTypeException
1535
+	 * @throws EE_Error
1536
+	 */
1537
+	public function increase_reserved($qty = 1)
1538
+	{
1539
+		EE_Error::doing_it_wrong(
1540
+			__FUNCTION__,
1541
+			esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1542
+			'4.9.80.p',
1543
+			'5.0.0.p'
1544
+		);
1545
+		return $this->increaseReserved($qty);
1546
+	}
1547
+
1548
+
1549
+	/**
1550
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1551
+	 *
1552
+	 * @deprecated 4.9.80.p
1553
+	 * @param int $qty
1554
+	 * @return boolean
1555
+	 * @throws ReflectionException
1556
+	 * @throws InvalidArgumentException
1557
+	 * @throws InvalidInterfaceException
1558
+	 * @throws InvalidDataTypeException
1559
+	 * @throws EE_Error
1560
+	 */
1561
+	public function decrease_reserved($qty = 1)
1562
+	{
1563
+		EE_Error::doing_it_wrong(
1564
+			__FUNCTION__,
1565
+			esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1566
+			'4.9.80.p',
1567
+			'5.0.0.p'
1568
+		);
1569
+		return $this->decreaseReserved($qty);
1570
+	}
1571 1571
 }
Please login to merge, or discard this patch.
admin/new/pricing/templates/event_tickets_metabox_main.template.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -141,10 +141,10 @@
 block discarded – undo
141 141
     <div style="clear:both"></div>
142 142
 
143 143
     <?php
144
-    if (isset($status_change_notice)) {
145
-        echo $status_change_notice;
146
-    }
147
-    ?>
144
+	if (isset($status_change_notice)) {
145
+		echo $status_change_notice;
146
+	}
147
+	?>
148 148
 
149 149
     <div class="available-tickets-container">
150 150
         <h3 class="event-tickets-datetimes-title">
Please login to merge, or discard this patch.
pricing/templates/event_tickets_datetime_attached_tickets_row.template.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -25,10 +25,10 @@  discard block
 block discarded – undo
25 25
                           placeholder="Datetime Description (optional)"><?php echo esc_textarea($DTT_description); ?></textarea>
26 26
             </div>
27 27
             <?php do_action(
28
-                'AHEE__event_tickets_datetime_attached_tickets_row_template__advanced_details_after_dtt_description',
29
-                $dtt_row,
30
-                $DTT_ID
31
-            ); ?>
28
+				'AHEE__event_tickets_datetime_attached_tickets_row_template__advanced_details_after_dtt_description',
29
+				$dtt_row,
30
+				$DTT_ID
31
+			); ?>
32 32
             <h4 class="datetime-tickets-heading"><?php esc_html_e('Assigned Tickets', 'event_espresso'); ?></h4>
33 33
 
34 34
             <ul class="datetime-tickets-list">
@@ -38,28 +38,28 @@  discard block
 block discarded – undo
38 38
 
39 39
             <div class="add-datetime-ticket-container">
40 40
                 <h4 class="datetime-tickets-heading"><?php
41
-                    esc_html_e(
42
-                        'Add New Ticket',
43
-                        'event_espresso'
44
-                    ); ?></h4><?php echo wp_kses($add_new_datetime_ticket_help_link, AllowedTags::getAllowedTags()); ?><br>
41
+					esc_html_e(
42
+						'Add New Ticket',
43
+						'event_espresso'
44
+					); ?></h4><?php echo wp_kses($add_new_datetime_ticket_help_link, AllowedTags::getAllowedTags()); ?><br>
45 45
                 <table class="add-new-ticket-table">
46 46
                     <thead>
47 47
                     <tr valign="top">
48 48
                         <td><span class="ANT_TKT_name_label"><?php
49
-                                esc_html_e(
50
-                                    'Ticket Name',
51
-                                    'event_espresso'
52
-                                ); ?></span></td>
49
+								esc_html_e(
50
+									'Ticket Name',
51
+									'event_espresso'
52
+								); ?></span></td>
53 53
                         <td><span class="ANT_TKT_goes_on_sale_label"><?php
54
-                                esc_html_e(
55
-                                    'Sale Starts',
56
-                                    'event_espresso'
57
-                                ); ?></span></td>
54
+								esc_html_e(
55
+									'Sale Starts',
56
+									'event_espresso'
57
+								); ?></span></td>
58 58
                         <td><span class="ANT_TKT_sell_until_label"><?php
59
-                                esc_html_e(
60
-                                    'Sell Until',
61
-                                    'event_espresso'
62
-                                ); ?></span></td>
59
+								esc_html_e(
60
+									'Sell Until',
61
+									'event_espresso'
62
+								); ?></span></td>
63 63
                         <td><span class="ANT_TKT_price_label"><?php esc_html_e('Price', 'event_espresso'); ?></span>
64 64
                         </td>
65 65
                         <td><span class="ANT_TKT_qty_label"><?php esc_html_e('Qty', 'event_espresso'); ?></span></td>
@@ -115,12 +115,12 @@  discard block
 block discarded – undo
115 115
                 <div class="ee-editor-footer-container">
116 116
                     <div class="ee-editor-id-container">
117 117
                         <span class="ee-item-id"><?php
118
-                            echo ($DTT_ID
119
-                                ? sprintf(
120
-                                    esc_html__('Datetime ID: %d', 'event_espresso'),
121
-                                    $DTT_ID
122
-                                )
123
-                                : ''); ?></span>
118
+							echo ($DTT_ID
119
+								? sprintf(
120
+									esc_html__('Datetime ID: %d', 'event_espresso'),
121
+									$DTT_ID
122
+								)
123
+								: ''); ?></span>
124 124
                     </div>
125 125
                     <div class="save-cancel-button-container">
126 126
                         <button class="button button--primary ee-create-button"
Please login to merge, or discard this patch.
admin/new/pricing/templates/pricing_type_details_main_meta_box.template.php 1 patch
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -21,12 +21,12 @@  discard block
 block discarded – undo
21 21
                     <?php echo wp_kses($base_type_select, AllowedTags::getWithFormTags()); ?>
22 22
                     <p class="description">
23 23
                         <?php printf(
24
-                            esc_html__(
25
-                                'Choosing a basic type allows us to quickly configure a bunch of other options for you.%1$sAll events need to have at least one Base Price type option.%1$sDiscounts reduce the price of an event, Surcharges increase the price.%1$sTaxes are applied to the final total.',
26
-                                'event_espresso'
27
-                            ),
28
-                            '<br/>'
29
-                        ); ?>
24
+							esc_html__(
25
+								'Choosing a basic type allows us to quickly configure a bunch of other options for you.%1$sAll events need to have at least one Base Price type option.%1$sDiscounts reduce the price of an event, Surcharges increase the price.%1$sTaxes are applied to the final total.',
26
+								'event_espresso'
27
+							),
28
+							'<br/>'
29
+						); ?>
30 30
                     </p>
31 31
                 </td>
32 32
             </tr>
@@ -73,21 +73,21 @@  discard block
 block discarded – undo
73 73
                         <?php esc_html_e('Fixed', 'event_espresso'); ?>
74 74
                     </label>
75 75
                     <p class="description"><?php
76
-                        esc_html_e(
77
-                            'Whether this Price Type will be applied as a percentage or applied as a set fixed amount.',
78
-                            'event_espresso'
79
-                        ); ?>
76
+						esc_html_e(
77
+							'Whether this Price Type will be applied as a percentage or applied as a set fixed amount.',
78
+							'event_espresso'
79
+						); ?>
80 80
                     </p>
81 81
                     <?php if ($price_type->base_type() == EEM_Price_Type::base_type_tax) :
82
-                        // base type is tax so let's just let the user know that taxes are always percentage.
83
-                        ?>
82
+						// base type is tax so let's just let the user know that taxes are always percentage.
83
+						?>
84 84
                         <p class="description" style="color:#E44064">
85 85
                             <?php
86
-                            esc_html_e(
87
-                                'The selected base type for this price type is "Tax".  Taxes are always assumed to be a percentage.  If you want to use a fixed value for a tax then please change the base type to a surcharge.',
88
-                                'event_espresso'
89
-                            );
90
-                            ?>
86
+							esc_html_e(
87
+								'The selected base type for this price type is "Tax".  Taxes are always assumed to be a percentage.  If you want to use a fixed value for a tax then please change the base type to a surcharge.',
88
+								'event_espresso'
89
+							);
90
+							?>
91 91
                         </p>
92 92
                     <?php endif; ?>
93 93
                 </td>
@@ -110,13 +110,13 @@  discard block
 block discarded – undo
110 110
                     </p>
111 111
                     <p class="description">
112 112
                         <?php
113
-                        printf(
114
-                            esc_html__(
115
-                                'Price types are applied sequentially according to their Order, where higher ordered Price Types will affect lower ordered Price Types.%1$sPrice types with equal Orders will be applied in parallel to whatever total precedes them and will not affect each other. Actual Prices will be set to "0" so that they are processed first. Taxes will be always be applied last but their order will still determine if they are applied in parallel or as compound taxes (one tax on top of the other).',
116
-                                'event_espresso'
117
-                            ),
118
-                            '<br/>'
119
-                        ); ?>
113
+						printf(
114
+							esc_html__(
115
+								'Price types are applied sequentially according to their Order, where higher ordered Price Types will affect lower ordered Price Types.%1$sPrice types with equal Orders will be applied in parallel to whatever total precedes them and will not affect each other. Actual Prices will be set to "0" so that they are processed first. Taxes will be always be applied last but their order will still determine if they are applied in parallel or as compound taxes (one tax on top of the other).',
116
+								'event_espresso'
117
+							),
118
+							'<br/>'
119
+						); ?>
120 120
                     </p>
121 121
                 </td>
122 122
             </tr>
Please login to merge, or discard this patch.
new/pricing/templates/event_tickets_datetime_ticket_price_row.template.php 1 patch
Braces   +10 added lines, -4 removed lines patch added patch discarded remove patch
@@ -64,9 +64,12 @@  discard block
 block discarded – undo
64 64
             <input type="text" size="1" class="edit-price-PRC_amount ee-numeric"
65 65
                    name="prices_archive[<?php echo esc_attr($tkt_row); ?>][<?php echo esc_attr($PRC_order); ?>][PRC_amount]"
66 66
                    value="<?php echo esc_attr($PRC_amount); ?>" disabled>
67
-        <?php else : ?>
67
+        <?php else {
68
+	: ?>
68 69
             <input type="text" size="1" class="edit-price-PRC_amount ee-numeric"
69
-                   name="<?php echo esc_attr($edit_prices_name); ?>[<?php echo esc_attr($tkt_row); ?>][<?php echo esc_attr($PRC_order); ?>][PRC_amount]"
70
+                   name="<?php echo esc_attr($edit_prices_name);
71
+}
72
+?>[<?php echo esc_attr($tkt_row); ?>][<?php echo esc_attr($PRC_order); ?>][PRC_amount]"
70 73
                    value="<?php echo esc_attr($PRC_amount); ?>">
71 74
         <?php endif; ?>
72 75
     </td>
@@ -77,8 +80,11 @@  discard block
 block discarded – undo
77 80
     <td>
78 81
         <?php if ($disabled) : ?>
79 82
             <span class="dashicons dashicons-lock"></span>
80
-        <?php else : ?>
81
-            <span class="trash-icon dashicons dashicons-post-trash clickable" data-ticket-row="<?php echo esc_attr($tkt_row); ?>"
83
+        <?php else {
84
+	: ?>
85
+            <span class="trash-icon dashicons dashicons-post-trash clickable" data-ticket-row="<?php echo esc_attr($tkt_row);
86
+}
87
+?>"
82 88
                   data-context="price" data-price-row="<?php echo esc_attr($PRC_order); ?>"<?php echo wp_kses($show_trash_icon, AllowedTags::getWithFormTags()); ?>></span>
83 89
             <button data-ticket-row="<?php echo esc_attr($tkt_row); ?>" data-price-row="<?php echo esc_attr($PRC_order); ?>"
84 90
                     data-context="price" class="ee-create-button"<?php echo wp_kses($show_create_button, AllowedTags::getWithFormTags()); ?>><strong>+</strong>
Please login to merge, or discard this patch.
caffeinated/admin/new/pricing/espresso_events_Pricing_Hooks.class.php 1 patch
Indentation   +2140 added lines, -2140 removed lines patch added patch discarded remove patch
@@ -14,2202 +14,2202 @@
 block discarded – undo
14 14
  */
15 15
 class espresso_events_Pricing_Hooks extends EE_Admin_Hooks
16 16
 {
17
-    /**
18
-     * This property is just used to hold the status of whether an event is currently being
19
-     * created (true) or edited (false)
20
-     *
21
-     * @access protected
22
-     * @var bool
23
-     */
24
-    protected $_is_creating_event;
17
+	/**
18
+	 * This property is just used to hold the status of whether an event is currently being
19
+	 * created (true) or edited (false)
20
+	 *
21
+	 * @access protected
22
+	 * @var bool
23
+	 */
24
+	protected $_is_creating_event;
25 25
 
26
-    /**
27
-     * Used to contain the format strings for date and time that will be used for php date and
28
-     * time.
29
-     * Is set in the _set_hooks_properties() method.
30
-     *
31
-     * @var array
32
-     */
33
-    protected $_date_format_strings;
26
+	/**
27
+	 * Used to contain the format strings for date and time that will be used for php date and
28
+	 * time.
29
+	 * Is set in the _set_hooks_properties() method.
30
+	 *
31
+	 * @var array
32
+	 */
33
+	protected $_date_format_strings;
34 34
 
35
-    /**
36
-     * @var string $_date_time_format
37
-     */
38
-    protected $_date_time_format;
35
+	/**
36
+	 * @var string $_date_time_format
37
+	 */
38
+	protected $_date_time_format;
39 39
 
40 40
 
41
-    /**
42
-     * @throws InvalidArgumentException
43
-     * @throws InvalidInterfaceException
44
-     * @throws InvalidDataTypeException
45
-     */
46
-    protected function _set_hooks_properties()
47
-    {
48
-        $this->_name = 'pricing';
49
-        // capability check
50
-        if (
51
-            $this->_adminpage_obj->adminConfig()->useAdvancedEditor()
52
-            || ! EE_Registry::instance()->CAP->current_user_can(
53
-                'ee_read_default_prices',
54
-                'advanced_ticket_datetime_metabox'
55
-            )
56
-        ) {
57
-            $this->_metaboxes      = [];
58
-            $this->_scripts_styles = [];
59
-            return;
60
-        }
61
-        $this->_setup_metaboxes();
62
-        $this->_set_date_time_formats();
63
-        $this->_validate_format_strings();
64
-        $this->_set_scripts_styles();
65
-        // commented out temporarily until logic is implemented in callback
66
-        // add_action(
67
-        //     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
68
-        //     array($this, 'autosave_handling')
69
-        // );
70
-        add_filter(
71
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
72
-            array($this, 'caf_updates')
73
-        );
74
-    }
41
+	/**
42
+	 * @throws InvalidArgumentException
43
+	 * @throws InvalidInterfaceException
44
+	 * @throws InvalidDataTypeException
45
+	 */
46
+	protected function _set_hooks_properties()
47
+	{
48
+		$this->_name = 'pricing';
49
+		// capability check
50
+		if (
51
+			$this->_adminpage_obj->adminConfig()->useAdvancedEditor()
52
+			|| ! EE_Registry::instance()->CAP->current_user_can(
53
+				'ee_read_default_prices',
54
+				'advanced_ticket_datetime_metabox'
55
+			)
56
+		) {
57
+			$this->_metaboxes      = [];
58
+			$this->_scripts_styles = [];
59
+			return;
60
+		}
61
+		$this->_setup_metaboxes();
62
+		$this->_set_date_time_formats();
63
+		$this->_validate_format_strings();
64
+		$this->_set_scripts_styles();
65
+		// commented out temporarily until logic is implemented in callback
66
+		// add_action(
67
+		//     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
68
+		//     array($this, 'autosave_handling')
69
+		// );
70
+		add_filter(
71
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
72
+			array($this, 'caf_updates')
73
+		);
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * @return void
79
-     */
80
-    protected function _setup_metaboxes()
81
-    {
82
-        // if we were going to add our own metaboxes we'd use the below.
83
-        $this->_metaboxes = array(
84
-            0 => array(
85
-                'page_route' => array('edit', 'create_new'),
86
-                'func'       => 'pricing_metabox',
87
-                'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
88
-                'priority'   => 'high',
89
-                'context'    => 'normal',
90
-            ),
91
-        );
92
-        $this->_remove_metaboxes = array(
93
-            0 => array(
94
-                'page_route' => array('edit', 'create_new'),
95
-                'id'         => 'espresso_event_editor_tickets',
96
-                'context'    => 'normal',
97
-            ),
98
-        );
99
-    }
77
+	/**
78
+	 * @return void
79
+	 */
80
+	protected function _setup_metaboxes()
81
+	{
82
+		// if we were going to add our own metaboxes we'd use the below.
83
+		$this->_metaboxes = array(
84
+			0 => array(
85
+				'page_route' => array('edit', 'create_new'),
86
+				'func'       => 'pricing_metabox',
87
+				'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
88
+				'priority'   => 'high',
89
+				'context'    => 'normal',
90
+			),
91
+		);
92
+		$this->_remove_metaboxes = array(
93
+			0 => array(
94
+				'page_route' => array('edit', 'create_new'),
95
+				'id'         => 'espresso_event_editor_tickets',
96
+				'context'    => 'normal',
97
+			),
98
+		);
99
+	}
100 100
 
101 101
 
102
-    /**
103
-     * @return void
104
-     */
105
-    protected function _set_date_time_formats()
106
-    {
107
-        /**
108
-         * Format strings for date and time.  Defaults are existing behaviour from 4.1.
109
-         * Note, that if you return null as the value for 'date', and 'time' in the array, then
110
-         * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
111
-         *
112
-         * @since 4.6.7
113
-         * @var array  Expected an array returned with 'date' and 'time' keys.
114
-         */
115
-        $this->_date_format_strings = apply_filters(
116
-            'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
117
-            array(
118
-                'date' => 'Y-m-d',
119
-                'time' => 'h:i a',
120
-            )
121
-        );
122
-        // validate
123
-        $this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
124
-            ? $this->_date_format_strings['date']
125
-            : null;
126
-        $this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
127
-            ? $this->_date_format_strings['time']
128
-            : null;
129
-        $this->_date_time_format = $this->_date_format_strings['date']
130
-                                   . ' '
131
-                                   . $this->_date_format_strings['time'];
132
-    }
102
+	/**
103
+	 * @return void
104
+	 */
105
+	protected function _set_date_time_formats()
106
+	{
107
+		/**
108
+		 * Format strings for date and time.  Defaults are existing behaviour from 4.1.
109
+		 * Note, that if you return null as the value for 'date', and 'time' in the array, then
110
+		 * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
111
+		 *
112
+		 * @since 4.6.7
113
+		 * @var array  Expected an array returned with 'date' and 'time' keys.
114
+		 */
115
+		$this->_date_format_strings = apply_filters(
116
+			'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
117
+			array(
118
+				'date' => 'Y-m-d',
119
+				'time' => 'h:i a',
120
+			)
121
+		);
122
+		// validate
123
+		$this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
124
+			? $this->_date_format_strings['date']
125
+			: null;
126
+		$this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
127
+			? $this->_date_format_strings['time']
128
+			: null;
129
+		$this->_date_time_format = $this->_date_format_strings['date']
130
+								   . ' '
131
+								   . $this->_date_format_strings['time'];
132
+	}
133 133
 
134 134
 
135
-    /**
136
-     * @return void
137
-     */
138
-    protected function _validate_format_strings()
139
-    {
140
-        // validate format strings
141
-        $format_validation = EEH_DTT_Helper::validate_format_string(
142
-            $this->_date_time_format
143
-        );
144
-        if (is_array($format_validation)) {
145
-            $msg = '<p>';
146
-            $msg .= sprintf(
147
-                esc_html__(
148
-                    'The format "%s" was likely added via a filter and is invalid for the following reasons:',
149
-                    'event_espresso'
150
-                ),
151
-                $this->_date_time_format
152
-            );
153
-            $msg .= '</p><ul>';
154
-            foreach ($format_validation as $error) {
155
-                $msg .= '<li>' . $error . '</li>';
156
-            }
157
-            $msg .= '</ul><p>';
158
-            $msg .= sprintf(
159
-                esc_html__(
160
-                    '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
161
-                    'event_espresso'
162
-                ),
163
-                '<span style="color:#D54E21;">',
164
-                '</span>'
165
-            );
166
-            $msg .= '</p>';
167
-            EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
168
-            $this->_date_format_strings = array(
169
-                'date' => 'Y-m-d',
170
-                'time' => 'h:i a',
171
-            );
172
-        }
173
-    }
135
+	/**
136
+	 * @return void
137
+	 */
138
+	protected function _validate_format_strings()
139
+	{
140
+		// validate format strings
141
+		$format_validation = EEH_DTT_Helper::validate_format_string(
142
+			$this->_date_time_format
143
+		);
144
+		if (is_array($format_validation)) {
145
+			$msg = '<p>';
146
+			$msg .= sprintf(
147
+				esc_html__(
148
+					'The format "%s" was likely added via a filter and is invalid for the following reasons:',
149
+					'event_espresso'
150
+				),
151
+				$this->_date_time_format
152
+			);
153
+			$msg .= '</p><ul>';
154
+			foreach ($format_validation as $error) {
155
+				$msg .= '<li>' . $error . '</li>';
156
+			}
157
+			$msg .= '</ul><p>';
158
+			$msg .= sprintf(
159
+				esc_html__(
160
+					'%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
161
+					'event_espresso'
162
+				),
163
+				'<span style="color:#D54E21;">',
164
+				'</span>'
165
+			);
166
+			$msg .= '</p>';
167
+			EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
168
+			$this->_date_format_strings = array(
169
+				'date' => 'Y-m-d',
170
+				'time' => 'h:i a',
171
+			);
172
+		}
173
+	}
174 174
 
175 175
 
176
-    /**
177
-     * @return void
178
-     */
179
-    protected function _set_scripts_styles()
180
-    {
181
-        $this->_scripts_styles = array(
182
-            'registers'   => array(
183
-                'ee-tickets-datetimes-css' => array(
184
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
185
-                    'type' => 'css',
186
-                ),
187
-                'ee-dtt-ticket-metabox'    => array(
188
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
189
-                    'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
190
-                ),
191
-            ),
192
-            'deregisters' => array(
193
-                'event-editor-css'       => array('type' => 'css'),
194
-                'event-datetime-metabox' => array('type' => 'js'),
195
-            ),
196
-            'enqueues'    => array(
197
-                'ee-tickets-datetimes-css' => array('edit', 'create_new'),
198
-                'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
199
-            ),
200
-            'localize'    => array(
201
-                'ee-dtt-ticket-metabox' => array(
202
-                    'DTT_TRASH_BLOCK'       => array(
203
-                        'main_warning'            => esc_html__(
204
-                            'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
205
-                            'event_espresso'
206
-                        ),
207
-                        'after_warning'           => esc_html__(
208
-                            'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
209
-                            'event_espresso'
210
-                        ),
211
-                        'cancel_button'           => '<button class="button--secondary ee-modal-cancel">'
212
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
213
-                        'close_button'            => '<button class="button--secondary ee-modal-cancel">'
214
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
215
-                        'single_warning_from_tkt' => esc_html__(
216
-                            'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.',
217
-                            'event_espresso'
218
-                        ),
219
-                        'single_warning_from_dtt' => esc_html__(
220
-                            'The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket.  Tickets must always have at least one datetime assigned to them.',
221
-                            'event_espresso'
222
-                        ),
223
-                        'dismiss_button'          => '<button class="button--secondary ee-modal-cancel">'
224
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
225
-                    ),
226
-                    'DTT_ERROR_MSG'         => array(
227
-                        'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
228
-                        'dismiss_button' => '<div class="save-cancel-button-container">'
229
-                                            . '<button class="button--secondary ee-modal-cancel">'
230
-                                            . esc_html__('Dismiss', 'event_espresso')
231
-                                            . '</button></div>',
232
-                    ),
233
-                    'DTT_OVERSELL_WARNING'  => array(
234
-                        'datetime_ticket' => esc_html__(
235
-                            'You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.',
236
-                            'event_espresso'
237
-                        ),
238
-                        'ticket_datetime' => esc_html__(
239
-                            'You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.',
240
-                            'event_espresso'
241
-                        ),
242
-                    ),
243
-                    'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
244
-                        $this->_date_format_strings['date'],
245
-                        $this->_date_format_strings['time']
246
-                    ),
247
-                    'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
248
-                ),
249
-            ),
250
-        );
251
-    }
176
+	/**
177
+	 * @return void
178
+	 */
179
+	protected function _set_scripts_styles()
180
+	{
181
+		$this->_scripts_styles = array(
182
+			'registers'   => array(
183
+				'ee-tickets-datetimes-css' => array(
184
+					'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
185
+					'type' => 'css',
186
+				),
187
+				'ee-dtt-ticket-metabox'    => array(
188
+					'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
189
+					'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
190
+				),
191
+			),
192
+			'deregisters' => array(
193
+				'event-editor-css'       => array('type' => 'css'),
194
+				'event-datetime-metabox' => array('type' => 'js'),
195
+			),
196
+			'enqueues'    => array(
197
+				'ee-tickets-datetimes-css' => array('edit', 'create_new'),
198
+				'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
199
+			),
200
+			'localize'    => array(
201
+				'ee-dtt-ticket-metabox' => array(
202
+					'DTT_TRASH_BLOCK'       => array(
203
+						'main_warning'            => esc_html__(
204
+							'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
205
+							'event_espresso'
206
+						),
207
+						'after_warning'           => esc_html__(
208
+							'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
209
+							'event_espresso'
210
+						),
211
+						'cancel_button'           => '<button class="button--secondary ee-modal-cancel">'
212
+													 . esc_html__('Cancel', 'event_espresso') . '</button>',
213
+						'close_button'            => '<button class="button--secondary ee-modal-cancel">'
214
+													 . esc_html__('Close', 'event_espresso') . '</button>',
215
+						'single_warning_from_tkt' => esc_html__(
216
+							'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.',
217
+							'event_espresso'
218
+						),
219
+						'single_warning_from_dtt' => esc_html__(
220
+							'The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket.  Tickets must always have at least one datetime assigned to them.',
221
+							'event_espresso'
222
+						),
223
+						'dismiss_button'          => '<button class="button--secondary ee-modal-cancel">'
224
+													 . esc_html__('Dismiss', 'event_espresso') . '</button>',
225
+					),
226
+					'DTT_ERROR_MSG'         => array(
227
+						'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
228
+						'dismiss_button' => '<div class="save-cancel-button-container">'
229
+											. '<button class="button--secondary ee-modal-cancel">'
230
+											. esc_html__('Dismiss', 'event_espresso')
231
+											. '</button></div>',
232
+					),
233
+					'DTT_OVERSELL_WARNING'  => array(
234
+						'datetime_ticket' => esc_html__(
235
+							'You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.',
236
+							'event_espresso'
237
+						),
238
+						'ticket_datetime' => esc_html__(
239
+							'You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.',
240
+							'event_espresso'
241
+						),
242
+					),
243
+					'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
244
+						$this->_date_format_strings['date'],
245
+						$this->_date_format_strings['time']
246
+					),
247
+					'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
248
+				),
249
+			),
250
+		);
251
+	}
252 252
 
253 253
 
254
-    /**
255
-     * @param array $update_callbacks
256
-     * @return array
257
-     */
258
-    public function caf_updates(array $update_callbacks)
259
-    {
260
-        unset($update_callbacks['_default_tickets_update']);
261
-        $update_callbacks['datetime_and_tickets_caf_update'] = array($this, 'datetime_and_tickets_caf_update');
262
-        return $update_callbacks;
263
-    }
254
+	/**
255
+	 * @param array $update_callbacks
256
+	 * @return array
257
+	 */
258
+	public function caf_updates(array $update_callbacks)
259
+	{
260
+		unset($update_callbacks['_default_tickets_update']);
261
+		$update_callbacks['datetime_and_tickets_caf_update'] = array($this, 'datetime_and_tickets_caf_update');
262
+		return $update_callbacks;
263
+	}
264 264
 
265 265
 
266
-    /**
267
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
268
-     *
269
-     * @param  EE_Event $event The Event object we're attaching data to
270
-     * @param  array    $data  The request data from the form
271
-     * @throws ReflectionException
272
-     * @throws Exception
273
-     * @throws InvalidInterfaceException
274
-     * @throws InvalidDataTypeException
275
-     * @throws EE_Error
276
-     * @throws InvalidArgumentException
277
-     */
278
-    public function datetime_and_tickets_caf_update($event, $data)
279
-    {
280
-        // first we need to start with datetimes cause they are the "root" items attached to events.
281
-        $saved_datetimes = $this->_update_datetimes($event, $data);
282
-        // next tackle the tickets (and prices?)
283
-        $this->_update_tickets($event, $saved_datetimes, $data);
284
-    }
266
+	/**
267
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
268
+	 *
269
+	 * @param  EE_Event $event The Event object we're attaching data to
270
+	 * @param  array    $data  The request data from the form
271
+	 * @throws ReflectionException
272
+	 * @throws Exception
273
+	 * @throws InvalidInterfaceException
274
+	 * @throws InvalidDataTypeException
275
+	 * @throws EE_Error
276
+	 * @throws InvalidArgumentException
277
+	 */
278
+	public function datetime_and_tickets_caf_update($event, $data)
279
+	{
280
+		// first we need to start with datetimes cause they are the "root" items attached to events.
281
+		$saved_datetimes = $this->_update_datetimes($event, $data);
282
+		// next tackle the tickets (and prices?)
283
+		$this->_update_tickets($event, $saved_datetimes, $data);
284
+	}
285 285
 
286 286
 
287
-    /**
288
-     * update event_datetimes
289
-     *
290
-     * @param  EE_Event $event Event being updated
291
-     * @param  array    $data  the request data from the form
292
-     * @return EE_Datetime[]
293
-     * @throws Exception
294
-     * @throws ReflectionException
295
-     * @throws InvalidInterfaceException
296
-     * @throws InvalidDataTypeException
297
-     * @throws InvalidArgumentException
298
-     * @throws EE_Error
299
-     */
300
-    protected function _update_datetimes($event, $data)
301
-    {
302
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
303
-        $saved_dtt_ids = array();
304
-        $saved_dtt_objs = array();
305
-        if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
306
-            throw new InvalidArgumentException(
307
-                esc_html__(
308
-                    'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
309
-                    'event_espresso'
310
-                )
311
-            );
312
-        }
313
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
314
-            // trim all values to ensure any excess whitespace is removed.
315
-            $datetime_data = array_map(
316
-                function ($datetime_data) {
317
-                    return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
318
-                },
319
-                $datetime_data
320
-            );
321
-            $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
322
-                                            && ! empty($datetime_data['DTT_EVT_end'])
323
-                ? $datetime_data['DTT_EVT_end']
324
-                : $datetime_data['DTT_EVT_start'];
325
-            $datetime_values = array(
326
-                'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
327
-                    ? $datetime_data['DTT_ID']
328
-                    : null,
329
-                'DTT_name'        => ! empty($datetime_data['DTT_name'])
330
-                    ? $datetime_data['DTT_name']
331
-                    : '',
332
-                'DTT_description' => ! empty($datetime_data['DTT_description'])
333
-                    ? $datetime_data['DTT_description']
334
-                    : '',
335
-                'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
336
-                'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
337
-                'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
338
-                    ? EE_INF
339
-                    : $datetime_data['DTT_reg_limit'],
340
-                'DTT_order'       => ! isset($datetime_data['DTT_order'])
341
-                    ? $row
342
-                    : $datetime_data['DTT_order'],
343
-            );
344
-            // if we have an id then let's get existing object first and then set the new values.
345
-            // Otherwise we instantiate a new object for save.
346
-            if (! empty($datetime_data['DTT_ID'])) {
347
-                $datetime = EE_Registry::instance()
348
-                                       ->load_model('Datetime', array($timezone))
349
-                                       ->get_one_by_ID($datetime_data['DTT_ID']);
350
-                // set date and time format according to what is set in this class.
351
-                $datetime->set_date_format($this->_date_format_strings['date']);
352
-                $datetime->set_time_format($this->_date_format_strings['time']);
353
-                foreach ($datetime_values as $field => $value) {
354
-                    $datetime->set($field, $value);
355
-                }
356
-                // make sure the $dtt_id here is saved just in case
357
-                // after the add_relation_to() the autosave replaces it.
358
-                // We need to do this so we dont' TRASH the parent DTT.
359
-                // (save the ID for both key and value to avoid duplications)
360
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
361
-            } else {
362
-                $datetime = EE_Registry::instance()->load_class(
363
-                    'Datetime',
364
-                    array(
365
-                        $datetime_values,
366
-                        $timezone,
367
-                        array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
368
-                    ),
369
-                    false,
370
-                    false
371
-                );
372
-                foreach ($datetime_values as $field => $value) {
373
-                    $datetime->set($field, $value);
374
-                }
375
-            }
376
-            $datetime->save();
377
-            do_action(
378
-                'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
379
-                $datetime,
380
-                $row,
381
-                $datetime_data,
382
-                $data
383
-            );
384
-            $datetime = $event->_add_relation_to($datetime, 'Datetime');
385
-            // before going any further make sure our dates are setup correctly
386
-            // so that the end date is always equal or greater than the start date.
387
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
388
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
389
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
390
-                $datetime->save();
391
-            }
392
-            // now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
393
-            // because it is possible there was a new one created for the autosave.
394
-            // (save the ID for both key and value to avoid duplications)
395
-            $DTT_ID = $datetime->ID();
396
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
397
-            $saved_dtt_objs[ $row ] = $datetime;
398
-            // @todo if ANY of these updates fail then we want the appropriate global error message.
399
-        }
400
-        $event->save();
401
-        // now we need to REMOVE any datetimes that got deleted.
402
-        // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
403
-        // So its safe to permanently delete at this point.
404
-        $old_datetimes = explode(',', $data['datetime_IDs']);
405
-        $old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
406
-        if (is_array($old_datetimes)) {
407
-            $datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
408
-            foreach ($datetimes_to_delete as $id) {
409
-                $id = absint($id);
410
-                if (empty($id)) {
411
-                    continue;
412
-                }
413
-                $dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
414
-                // remove tkt relationships.
415
-                $related_tickets = $dtt_to_remove->get_many_related('Ticket');
416
-                foreach ($related_tickets as $tkt) {
417
-                    $dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
418
-                }
419
-                $event->_remove_relation_to($id, 'Datetime');
420
-                $dtt_to_remove->refresh_cache_of_related_objects();
421
-            }
422
-        }
423
-        return $saved_dtt_objs;
424
-    }
287
+	/**
288
+	 * update event_datetimes
289
+	 *
290
+	 * @param  EE_Event $event Event being updated
291
+	 * @param  array    $data  the request data from the form
292
+	 * @return EE_Datetime[]
293
+	 * @throws Exception
294
+	 * @throws ReflectionException
295
+	 * @throws InvalidInterfaceException
296
+	 * @throws InvalidDataTypeException
297
+	 * @throws InvalidArgumentException
298
+	 * @throws EE_Error
299
+	 */
300
+	protected function _update_datetimes($event, $data)
301
+	{
302
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
303
+		$saved_dtt_ids = array();
304
+		$saved_dtt_objs = array();
305
+		if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
306
+			throw new InvalidArgumentException(
307
+				esc_html__(
308
+					'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
309
+					'event_espresso'
310
+				)
311
+			);
312
+		}
313
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
314
+			// trim all values to ensure any excess whitespace is removed.
315
+			$datetime_data = array_map(
316
+				function ($datetime_data) {
317
+					return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
318
+				},
319
+				$datetime_data
320
+			);
321
+			$datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
322
+											&& ! empty($datetime_data['DTT_EVT_end'])
323
+				? $datetime_data['DTT_EVT_end']
324
+				: $datetime_data['DTT_EVT_start'];
325
+			$datetime_values = array(
326
+				'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
327
+					? $datetime_data['DTT_ID']
328
+					: null,
329
+				'DTT_name'        => ! empty($datetime_data['DTT_name'])
330
+					? $datetime_data['DTT_name']
331
+					: '',
332
+				'DTT_description' => ! empty($datetime_data['DTT_description'])
333
+					? $datetime_data['DTT_description']
334
+					: '',
335
+				'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
336
+				'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
337
+				'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
338
+					? EE_INF
339
+					: $datetime_data['DTT_reg_limit'],
340
+				'DTT_order'       => ! isset($datetime_data['DTT_order'])
341
+					? $row
342
+					: $datetime_data['DTT_order'],
343
+			);
344
+			// if we have an id then let's get existing object first and then set the new values.
345
+			// Otherwise we instantiate a new object for save.
346
+			if (! empty($datetime_data['DTT_ID'])) {
347
+				$datetime = EE_Registry::instance()
348
+									   ->load_model('Datetime', array($timezone))
349
+									   ->get_one_by_ID($datetime_data['DTT_ID']);
350
+				// set date and time format according to what is set in this class.
351
+				$datetime->set_date_format($this->_date_format_strings['date']);
352
+				$datetime->set_time_format($this->_date_format_strings['time']);
353
+				foreach ($datetime_values as $field => $value) {
354
+					$datetime->set($field, $value);
355
+				}
356
+				// make sure the $dtt_id here is saved just in case
357
+				// after the add_relation_to() the autosave replaces it.
358
+				// We need to do this so we dont' TRASH the parent DTT.
359
+				// (save the ID for both key and value to avoid duplications)
360
+				$saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
361
+			} else {
362
+				$datetime = EE_Registry::instance()->load_class(
363
+					'Datetime',
364
+					array(
365
+						$datetime_values,
366
+						$timezone,
367
+						array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
368
+					),
369
+					false,
370
+					false
371
+				);
372
+				foreach ($datetime_values as $field => $value) {
373
+					$datetime->set($field, $value);
374
+				}
375
+			}
376
+			$datetime->save();
377
+			do_action(
378
+				'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
379
+				$datetime,
380
+				$row,
381
+				$datetime_data,
382
+				$data
383
+			);
384
+			$datetime = $event->_add_relation_to($datetime, 'Datetime');
385
+			// before going any further make sure our dates are setup correctly
386
+			// so that the end date is always equal or greater than the start date.
387
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
388
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
389
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
390
+				$datetime->save();
391
+			}
392
+			// now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
393
+			// because it is possible there was a new one created for the autosave.
394
+			// (save the ID for both key and value to avoid duplications)
395
+			$DTT_ID = $datetime->ID();
396
+			$saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
397
+			$saved_dtt_objs[ $row ] = $datetime;
398
+			// @todo if ANY of these updates fail then we want the appropriate global error message.
399
+		}
400
+		$event->save();
401
+		// now we need to REMOVE any datetimes that got deleted.
402
+		// Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
403
+		// So its safe to permanently delete at this point.
404
+		$old_datetimes = explode(',', $data['datetime_IDs']);
405
+		$old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
406
+		if (is_array($old_datetimes)) {
407
+			$datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
408
+			foreach ($datetimes_to_delete as $id) {
409
+				$id = absint($id);
410
+				if (empty($id)) {
411
+					continue;
412
+				}
413
+				$dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
414
+				// remove tkt relationships.
415
+				$related_tickets = $dtt_to_remove->get_many_related('Ticket');
416
+				foreach ($related_tickets as $tkt) {
417
+					$dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
418
+				}
419
+				$event->_remove_relation_to($id, 'Datetime');
420
+				$dtt_to_remove->refresh_cache_of_related_objects();
421
+			}
422
+		}
423
+		return $saved_dtt_objs;
424
+	}
425 425
 
426 426
 
427
-    /**
428
-     * update tickets
429
-     *
430
-     * @param  EE_Event      $event           Event object being updated
431
-     * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
432
-     * @param  array         $data            incoming request data
433
-     * @return EE_Ticket[]
434
-     * @throws Exception
435
-     * @throws ReflectionException
436
-     * @throws InvalidInterfaceException
437
-     * @throws InvalidDataTypeException
438
-     * @throws InvalidArgumentException
439
-     * @throws EE_Error
440
-     */
441
-    protected function _update_tickets($event, $saved_datetimes, $data)
442
-    {
443
-        $new_tkt = null;
444
-        // stripslashes because WP filtered the $_POST ($data) array to add slashes
445
-        $data = stripslashes_deep($data);
446
-        $timezone = $data['timezone_string'] ?? null;
447
-        $saved_tickets = array();
448
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
449
-        if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
450
-            throw new InvalidArgumentException(
451
-                esc_html__(
452
-                    'The "edit_tickets" array is invalid therefore the event can not be updated.',
453
-                    'event_espresso'
454
-                )
455
-            );
456
-        }
457
-        foreach ($data['edit_tickets'] as $row => $tkt) {
458
-            $update_prices = $create_new_TKT = false;
459
-            // figure out what datetimes were added to the ticket
460
-            // and what datetimes were removed from the ticket in the session.
461
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
462
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
463
-            $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
464
-            $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
465
-            // trim inputs to ensure any excess whitespace is removed.
466
-            $tkt = array_map(
467
-                function ($ticket_data) {
468
-                    return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
469
-                },
470
-                $tkt
471
-            );
472
-            // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
473
-            // because we're doing calculations prior to using the models.
474
-            // note incoming ['TKT_price'] value is already in standard notation (via js).
475
-            $ticket_price = isset($tkt['TKT_price'])
476
-                ? round((float) $tkt['TKT_price'], 3)
477
-                : 0;
478
-            // note incoming base price needs converted from localized value.
479
-            $base_price = isset($tkt['TKT_base_price'])
480
-                ? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
481
-                : 0;
482
-            // if ticket price == 0 and $base_price != 0 then ticket price == base_price
483
-            $ticket_price = $ticket_price === 0 && $base_price !== 0
484
-                ? $base_price
485
-                : $ticket_price;
486
-            $base_price_id = $tkt['TKT_base_price_ID'] ?? 0;
487
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
488
-                ? $data['edit_prices'][ $row ]
489
-                : array();
490
-            $now = null;
491
-            if (empty($tkt['TKT_start_date'])) {
492
-                // lets' use now in the set timezone.
493
-                $now = new DateTime('now', new DateTimeZone($event->get_timezone()));
494
-                $tkt['TKT_start_date'] = $now->format($this->_date_time_format);
495
-            }
496
-            if (empty($tkt['TKT_end_date'])) {
497
-                /**
498
-                 * set the TKT_end_date to the first datetime attached to the ticket.
499
-                 */
500
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
501
-                $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
502
-            }
503
-            $TKT_values = array(
504
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
505
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
506
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
507
-                'TKT_description' => ! empty($tkt['TKT_description'])
508
-                                     && $tkt['TKT_description'] !== esc_html__(
509
-                                         'You can modify this description',
510
-                                         'event_espresso'
511
-                                     )
512
-                    ? $tkt['TKT_description']
513
-                    : '',
514
-                'TKT_start_date'  => $tkt['TKT_start_date'],
515
-                'TKT_end_date'    => $tkt['TKT_end_date'],
516
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
517
-                    ? EE_INF
518
-                    : $tkt['TKT_qty'],
519
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
520
-                    ? EE_INF
521
-                    : $tkt['TKT_uses'],
522
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
523
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
524
-                'TKT_row'         => $row,
525
-                'TKT_order'       => $tkt['TKT_order'] ?? 0,
526
-                'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
527
-                'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
528
-                'TKT_price'       => $ticket_price,
529
-            );
530
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
531
-            // which means in turn that the prices will become new prices as well.
532
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
533
-                $TKT_values['TKT_ID'] = 0;
534
-                $TKT_values['TKT_is_default'] = 0;
535
-                $update_prices = true;
536
-            }
537
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
538
-            // we actually do our saves ahead of doing any add_relations to
539
-            // because its entirely possible that this ticket wasn't removed or added to any datetime in the session
540
-            // but DID have it's items modified.
541
-            // keep in mind that if the TKT has been sold (and we have changed pricing information),
542
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
543
-            if (absint($TKT_values['TKT_ID'])) {
544
-                $ticket = EE_Registry::instance()
545
-                                     ->load_model('Ticket', array($timezone))
546
-                                     ->get_one_by_ID($tkt['TKT_ID']);
547
-                if ($ticket instanceof EE_Ticket) {
548
-                    $ticket = $this->_update_ticket_datetimes(
549
-                        $ticket,
550
-                        $saved_datetimes,
551
-                        $datetimes_added,
552
-                        $datetimes_removed
553
-                    );
554
-                    // are there any registrations using this ticket ?
555
-                    $tickets_sold = $ticket->count_related(
556
-                        'Registration',
557
-                        array(
558
-                            array(
559
-                                'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
560
-                            ),
561
-                        )
562
-                    );
563
-                    // set ticket formats
564
-                    $ticket->set_date_format($this->_date_format_strings['date']);
565
-                    $ticket->set_time_format($this->_date_format_strings['time']);
566
-                    // let's just check the total price for the existing ticket
567
-                    // and determine if it matches the new total price.
568
-                    // if they are different then we create a new ticket (if tickets sold)
569
-                    // if they aren't different then we go ahead and modify existing ticket.
570
-                    $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
571
-                    // set new values
572
-                    foreach ($TKT_values as $field => $value) {
573
-                        if ($field === 'TKT_qty') {
574
-                            $ticket->set_qty($value);
575
-                        } else {
576
-                            $ticket->set($field, $value);
577
-                        }
578
-                    }
579
-                    // if $create_new_TKT is false then we can safely update the existing ticket.
580
-                    // Otherwise we have to create a new ticket.
581
-                    if ($create_new_TKT) {
582
-                        $new_tkt = $this->_duplicate_ticket(
583
-                            $ticket,
584
-                            $price_rows,
585
-                            $ticket_price,
586
-                            $base_price,
587
-                            $base_price_id
588
-                        );
589
-                    }
590
-                }
591
-            } else {
592
-                // no TKT_id so a new TKT
593
-                $ticket = EE_Ticket::new_instance(
594
-                    $TKT_values,
595
-                    $timezone,
596
-                    array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
597
-                );
598
-                if ($ticket instanceof EE_Ticket) {
599
-                    // make sure ticket has an ID of setting relations won't work
600
-                    $ticket->save();
601
-                    $ticket = $this->_update_ticket_datetimes(
602
-                        $ticket,
603
-                        $saved_datetimes,
604
-                        $datetimes_added,
605
-                        $datetimes_removed
606
-                    );
607
-                    $update_prices = true;
608
-                }
609
-            }
610
-            // make sure any current values have been saved.
611
-            // $ticket->save();
612
-            // before going any further make sure our dates are setup correctly
613
-            // so that the end date is always equal or greater than the start date.
614
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
615
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
616
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
617
-            }
618
-            // let's make sure the base price is handled
619
-            $ticket = ! $create_new_TKT
620
-                ? $this->_add_prices_to_ticket(
621
-                    array(),
622
-                    $ticket,
623
-                    $update_prices,
624
-                    $base_price,
625
-                    $base_price_id
626
-                )
627
-                : $ticket;
628
-            // add/update price_modifiers
629
-            $ticket = ! $create_new_TKT
630
-                ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
631
-                : $ticket;
632
-            // need to make sue that the TKT_price is accurate after saving the prices.
633
-            $ticket->ensure_TKT_Price_correct();
634
-            // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
635
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
636
-                $update_prices = true;
637
-                $new_default = clone $ticket;
638
-                $new_default->set('TKT_ID', 0);
639
-                $new_default->set('TKT_is_default', 1);
640
-                $new_default->set('TKT_row', 1);
641
-                $new_default->set('TKT_price', $ticket_price);
642
-                // remove any dtt relations cause we DON'T want dtt relations attached
643
-                // (note this is just removing the cached relations in the object)
644
-                $new_default->_remove_relations('Datetime');
645
-                // @todo we need to add the current attached prices as new prices to the new default ticket.
646
-                $new_default = $this->_add_prices_to_ticket(
647
-                    $price_rows,
648
-                    $new_default,
649
-                    $update_prices
650
-                );
651
-                // don't forget the base price!
652
-                $new_default = $this->_add_prices_to_ticket(
653
-                    array(),
654
-                    $new_default,
655
-                    $update_prices,
656
-                    $base_price,
657
-                    $base_price_id
658
-                );
659
-                $new_default->save();
660
-                do_action(
661
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
662
-                    $new_default,
663
-                    $row,
664
-                    $ticket,
665
-                    $data
666
-                );
667
-            }
668
-            // DO ALL dtt relationships for both current tickets and any archived tickets
669
-            // for the given dtt that are related to the current ticket.
670
-            // TODO... not sure exactly how we're going to do this considering we don't know
671
-            // what current ticket the archived tickets are related to
672
-            // (and TKT_parent is used for autosaves so that's not a field we can reliably use).
673
-            // let's assign any tickets that have been setup to the saved_tickets tracker
674
-            // save existing TKT
675
-            $ticket->save();
676
-            if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
677
-                // save new TKT
678
-                $new_tkt->save();
679
-                // add new ticket to array
680
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
681
-                do_action(
682
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
683
-                    $new_tkt,
684
-                    $row,
685
-                    $tkt,
686
-                    $data
687
-                );
688
-            } else {
689
-                // add tkt to saved tkts
690
-                $saved_tickets[ $ticket->ID() ] = $ticket;
691
-                do_action(
692
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
693
-                    $ticket,
694
-                    $row,
695
-                    $tkt,
696
-                    $data
697
-                );
698
-            }
699
-        }
700
-        // now we need to handle tickets actually "deleted permanently".
701
-        // There are cases where we'd want this to happen
702
-        // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
703
-        // Or a draft event was saved and in the process of editing a ticket is trashed.
704
-        // No sense in keeping all the related data in the db!
705
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
706
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
707
-        foreach ($tickets_removed as $id) {
708
-            $id = absint($id);
709
-            // get the ticket for this id
710
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
711
-            // if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
712
-            if ($tkt_to_remove->get('TKT_is_default')) {
713
-                continue;
714
-            }
715
-            // if this tkt has any registrations attached so then we just ARCHIVE
716
-            // because we don't actually permanently delete these tickets.
717
-            if ($tkt_to_remove->count_related('Registration') > 0) {
718
-                $tkt_to_remove->delete();
719
-                continue;
720
-            }
721
-            // need to get all the related datetimes on this ticket and remove from every single one of them
722
-            // (remember this process can ONLY kick off if there are NO tkts_sold)
723
-            $datetimes = $tkt_to_remove->get_many_related('Datetime');
724
-            foreach ($datetimes as $datetime) {
725
-                $tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
726
-            }
727
-            // need to do the same for prices (except these prices can also be deleted because again,
728
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
729
-            $tkt_to_remove->delete_related_permanently('Price');
730
-            do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
731
-            // finally let's delete this ticket
732
-            // (which should not be blocked at this point b/c we've removed all our relationships)
733
-            $tkt_to_remove->delete_permanently();
734
-        }
735
-        return $saved_tickets;
736
-    }
427
+	/**
428
+	 * update tickets
429
+	 *
430
+	 * @param  EE_Event      $event           Event object being updated
431
+	 * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
432
+	 * @param  array         $data            incoming request data
433
+	 * @return EE_Ticket[]
434
+	 * @throws Exception
435
+	 * @throws ReflectionException
436
+	 * @throws InvalidInterfaceException
437
+	 * @throws InvalidDataTypeException
438
+	 * @throws InvalidArgumentException
439
+	 * @throws EE_Error
440
+	 */
441
+	protected function _update_tickets($event, $saved_datetimes, $data)
442
+	{
443
+		$new_tkt = null;
444
+		// stripslashes because WP filtered the $_POST ($data) array to add slashes
445
+		$data = stripslashes_deep($data);
446
+		$timezone = $data['timezone_string'] ?? null;
447
+		$saved_tickets = array();
448
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
449
+		if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
450
+			throw new InvalidArgumentException(
451
+				esc_html__(
452
+					'The "edit_tickets" array is invalid therefore the event can not be updated.',
453
+					'event_espresso'
454
+				)
455
+			);
456
+		}
457
+		foreach ($data['edit_tickets'] as $row => $tkt) {
458
+			$update_prices = $create_new_TKT = false;
459
+			// figure out what datetimes were added to the ticket
460
+			// and what datetimes were removed from the ticket in the session.
461
+			$starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
462
+			$tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
463
+			$datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
464
+			$datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
465
+			// trim inputs to ensure any excess whitespace is removed.
466
+			$tkt = array_map(
467
+				function ($ticket_data) {
468
+					return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
469
+				},
470
+				$tkt
471
+			);
472
+			// note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
473
+			// because we're doing calculations prior to using the models.
474
+			// note incoming ['TKT_price'] value is already in standard notation (via js).
475
+			$ticket_price = isset($tkt['TKT_price'])
476
+				? round((float) $tkt['TKT_price'], 3)
477
+				: 0;
478
+			// note incoming base price needs converted from localized value.
479
+			$base_price = isset($tkt['TKT_base_price'])
480
+				? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
481
+				: 0;
482
+			// if ticket price == 0 and $base_price != 0 then ticket price == base_price
483
+			$ticket_price = $ticket_price === 0 && $base_price !== 0
484
+				? $base_price
485
+				: $ticket_price;
486
+			$base_price_id = $tkt['TKT_base_price_ID'] ?? 0;
487
+			$price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
488
+				? $data['edit_prices'][ $row ]
489
+				: array();
490
+			$now = null;
491
+			if (empty($tkt['TKT_start_date'])) {
492
+				// lets' use now in the set timezone.
493
+				$now = new DateTime('now', new DateTimeZone($event->get_timezone()));
494
+				$tkt['TKT_start_date'] = $now->format($this->_date_time_format);
495
+			}
496
+			if (empty($tkt['TKT_end_date'])) {
497
+				/**
498
+				 * set the TKT_end_date to the first datetime attached to the ticket.
499
+				 */
500
+				$first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
501
+				$tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
502
+			}
503
+			$TKT_values = array(
504
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
505
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
506
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
507
+				'TKT_description' => ! empty($tkt['TKT_description'])
508
+									 && $tkt['TKT_description'] !== esc_html__(
509
+										 'You can modify this description',
510
+										 'event_espresso'
511
+									 )
512
+					? $tkt['TKT_description']
513
+					: '',
514
+				'TKT_start_date'  => $tkt['TKT_start_date'],
515
+				'TKT_end_date'    => $tkt['TKT_end_date'],
516
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
517
+					? EE_INF
518
+					: $tkt['TKT_qty'],
519
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
520
+					? EE_INF
521
+					: $tkt['TKT_uses'],
522
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
523
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
524
+				'TKT_row'         => $row,
525
+				'TKT_order'       => $tkt['TKT_order'] ?? 0,
526
+				'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
527
+				'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
528
+				'TKT_price'       => $ticket_price,
529
+			);
530
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
531
+			// which means in turn that the prices will become new prices as well.
532
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
533
+				$TKT_values['TKT_ID'] = 0;
534
+				$TKT_values['TKT_is_default'] = 0;
535
+				$update_prices = true;
536
+			}
537
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
538
+			// we actually do our saves ahead of doing any add_relations to
539
+			// because its entirely possible that this ticket wasn't removed or added to any datetime in the session
540
+			// but DID have it's items modified.
541
+			// keep in mind that if the TKT has been sold (and we have changed pricing information),
542
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
543
+			if (absint($TKT_values['TKT_ID'])) {
544
+				$ticket = EE_Registry::instance()
545
+									 ->load_model('Ticket', array($timezone))
546
+									 ->get_one_by_ID($tkt['TKT_ID']);
547
+				if ($ticket instanceof EE_Ticket) {
548
+					$ticket = $this->_update_ticket_datetimes(
549
+						$ticket,
550
+						$saved_datetimes,
551
+						$datetimes_added,
552
+						$datetimes_removed
553
+					);
554
+					// are there any registrations using this ticket ?
555
+					$tickets_sold = $ticket->count_related(
556
+						'Registration',
557
+						array(
558
+							array(
559
+								'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
560
+							),
561
+						)
562
+					);
563
+					// set ticket formats
564
+					$ticket->set_date_format($this->_date_format_strings['date']);
565
+					$ticket->set_time_format($this->_date_format_strings['time']);
566
+					// let's just check the total price for the existing ticket
567
+					// and determine if it matches the new total price.
568
+					// if they are different then we create a new ticket (if tickets sold)
569
+					// if they aren't different then we go ahead and modify existing ticket.
570
+					$create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
571
+					// set new values
572
+					foreach ($TKT_values as $field => $value) {
573
+						if ($field === 'TKT_qty') {
574
+							$ticket->set_qty($value);
575
+						} else {
576
+							$ticket->set($field, $value);
577
+						}
578
+					}
579
+					// if $create_new_TKT is false then we can safely update the existing ticket.
580
+					// Otherwise we have to create a new ticket.
581
+					if ($create_new_TKT) {
582
+						$new_tkt = $this->_duplicate_ticket(
583
+							$ticket,
584
+							$price_rows,
585
+							$ticket_price,
586
+							$base_price,
587
+							$base_price_id
588
+						);
589
+					}
590
+				}
591
+			} else {
592
+				// no TKT_id so a new TKT
593
+				$ticket = EE_Ticket::new_instance(
594
+					$TKT_values,
595
+					$timezone,
596
+					array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
597
+				);
598
+				if ($ticket instanceof EE_Ticket) {
599
+					// make sure ticket has an ID of setting relations won't work
600
+					$ticket->save();
601
+					$ticket = $this->_update_ticket_datetimes(
602
+						$ticket,
603
+						$saved_datetimes,
604
+						$datetimes_added,
605
+						$datetimes_removed
606
+					);
607
+					$update_prices = true;
608
+				}
609
+			}
610
+			// make sure any current values have been saved.
611
+			// $ticket->save();
612
+			// before going any further make sure our dates are setup correctly
613
+			// so that the end date is always equal or greater than the start date.
614
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
615
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
616
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
617
+			}
618
+			// let's make sure the base price is handled
619
+			$ticket = ! $create_new_TKT
620
+				? $this->_add_prices_to_ticket(
621
+					array(),
622
+					$ticket,
623
+					$update_prices,
624
+					$base_price,
625
+					$base_price_id
626
+				)
627
+				: $ticket;
628
+			// add/update price_modifiers
629
+			$ticket = ! $create_new_TKT
630
+				? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
631
+				: $ticket;
632
+			// need to make sue that the TKT_price is accurate after saving the prices.
633
+			$ticket->ensure_TKT_Price_correct();
634
+			// handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
635
+			if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
636
+				$update_prices = true;
637
+				$new_default = clone $ticket;
638
+				$new_default->set('TKT_ID', 0);
639
+				$new_default->set('TKT_is_default', 1);
640
+				$new_default->set('TKT_row', 1);
641
+				$new_default->set('TKT_price', $ticket_price);
642
+				// remove any dtt relations cause we DON'T want dtt relations attached
643
+				// (note this is just removing the cached relations in the object)
644
+				$new_default->_remove_relations('Datetime');
645
+				// @todo we need to add the current attached prices as new prices to the new default ticket.
646
+				$new_default = $this->_add_prices_to_ticket(
647
+					$price_rows,
648
+					$new_default,
649
+					$update_prices
650
+				);
651
+				// don't forget the base price!
652
+				$new_default = $this->_add_prices_to_ticket(
653
+					array(),
654
+					$new_default,
655
+					$update_prices,
656
+					$base_price,
657
+					$base_price_id
658
+				);
659
+				$new_default->save();
660
+				do_action(
661
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
662
+					$new_default,
663
+					$row,
664
+					$ticket,
665
+					$data
666
+				);
667
+			}
668
+			// DO ALL dtt relationships for both current tickets and any archived tickets
669
+			// for the given dtt that are related to the current ticket.
670
+			// TODO... not sure exactly how we're going to do this considering we don't know
671
+			// what current ticket the archived tickets are related to
672
+			// (and TKT_parent is used for autosaves so that's not a field we can reliably use).
673
+			// let's assign any tickets that have been setup to the saved_tickets tracker
674
+			// save existing TKT
675
+			$ticket->save();
676
+			if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
677
+				// save new TKT
678
+				$new_tkt->save();
679
+				// add new ticket to array
680
+				$saved_tickets[ $new_tkt->ID() ] = $new_tkt;
681
+				do_action(
682
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
683
+					$new_tkt,
684
+					$row,
685
+					$tkt,
686
+					$data
687
+				);
688
+			} else {
689
+				// add tkt to saved tkts
690
+				$saved_tickets[ $ticket->ID() ] = $ticket;
691
+				do_action(
692
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
693
+					$ticket,
694
+					$row,
695
+					$tkt,
696
+					$data
697
+				);
698
+			}
699
+		}
700
+		// now we need to handle tickets actually "deleted permanently".
701
+		// There are cases where we'd want this to happen
702
+		// (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
703
+		// Or a draft event was saved and in the process of editing a ticket is trashed.
704
+		// No sense in keeping all the related data in the db!
705
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
706
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
707
+		foreach ($tickets_removed as $id) {
708
+			$id = absint($id);
709
+			// get the ticket for this id
710
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
711
+			// if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
712
+			if ($tkt_to_remove->get('TKT_is_default')) {
713
+				continue;
714
+			}
715
+			// if this tkt has any registrations attached so then we just ARCHIVE
716
+			// because we don't actually permanently delete these tickets.
717
+			if ($tkt_to_remove->count_related('Registration') > 0) {
718
+				$tkt_to_remove->delete();
719
+				continue;
720
+			}
721
+			// need to get all the related datetimes on this ticket and remove from every single one of them
722
+			// (remember this process can ONLY kick off if there are NO tkts_sold)
723
+			$datetimes = $tkt_to_remove->get_many_related('Datetime');
724
+			foreach ($datetimes as $datetime) {
725
+				$tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
726
+			}
727
+			// need to do the same for prices (except these prices can also be deleted because again,
728
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
729
+			$tkt_to_remove->delete_related_permanently('Price');
730
+			do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
731
+			// finally let's delete this ticket
732
+			// (which should not be blocked at this point b/c we've removed all our relationships)
733
+			$tkt_to_remove->delete_permanently();
734
+		}
735
+		return $saved_tickets;
736
+	}
737 737
 
738 738
 
739
-    /**
740
-     * @access  protected
741
-     * @param EE_Ticket      $ticket
742
-     * @param \EE_Datetime[] $saved_datetimes
743
-     * @param \EE_Datetime[] $added_datetimes
744
-     * @param \EE_Datetime[] $removed_datetimes
745
-     * @return EE_Ticket
746
-     * @throws EE_Error
747
-     */
748
-    protected function _update_ticket_datetimes(
749
-        EE_Ticket $ticket,
750
-        $saved_datetimes = array(),
751
-        $added_datetimes = array(),
752
-        $removed_datetimes = array()
753
-    ) {
754
-        // to start we have to add the ticket to all the datetimes its supposed to be with,
755
-        // and removing the ticket from datetimes it got removed from.
756
-        // first let's add datetimes
757
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
758
-            foreach ($added_datetimes as $row_id) {
759
-                $row_id = (int) $row_id;
760
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
761
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
762
-                }
763
-            }
764
-        }
765
-        // then remove datetimes
766
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
767
-            foreach ($removed_datetimes as $row_id) {
768
-                $row_id = (int) $row_id;
769
-                // its entirely possible that a datetime got deleted (instead of just removed from relationship.
770
-                // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
771
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
772
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
773
-                }
774
-            }
775
-        }
776
-        // cap ticket qty by datetime reg limits
777
-        $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
778
-        return $ticket;
779
-    }
739
+	/**
740
+	 * @access  protected
741
+	 * @param EE_Ticket      $ticket
742
+	 * @param \EE_Datetime[] $saved_datetimes
743
+	 * @param \EE_Datetime[] $added_datetimes
744
+	 * @param \EE_Datetime[] $removed_datetimes
745
+	 * @return EE_Ticket
746
+	 * @throws EE_Error
747
+	 */
748
+	protected function _update_ticket_datetimes(
749
+		EE_Ticket $ticket,
750
+		$saved_datetimes = array(),
751
+		$added_datetimes = array(),
752
+		$removed_datetimes = array()
753
+	) {
754
+		// to start we have to add the ticket to all the datetimes its supposed to be with,
755
+		// and removing the ticket from datetimes it got removed from.
756
+		// first let's add datetimes
757
+		if (! empty($added_datetimes) && is_array($added_datetimes)) {
758
+			foreach ($added_datetimes as $row_id) {
759
+				$row_id = (int) $row_id;
760
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
761
+					$ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
762
+				}
763
+			}
764
+		}
765
+		// then remove datetimes
766
+		if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
767
+			foreach ($removed_datetimes as $row_id) {
768
+				$row_id = (int) $row_id;
769
+				// its entirely possible that a datetime got deleted (instead of just removed from relationship.
770
+				// So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
771
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
772
+					$ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
773
+				}
774
+			}
775
+		}
776
+		// cap ticket qty by datetime reg limits
777
+		$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
778
+		return $ticket;
779
+	}
780 780
 
781 781
 
782
-    /**
783
-     * @access  protected
784
-     * @param EE_Ticket $ticket
785
-     * @param array     $price_rows
786
-     * @param int       $ticket_price
787
-     * @param int       $base_price
788
-     * @param int       $base_price_id
789
-     * @return EE_Ticket
790
-     * @throws ReflectionException
791
-     * @throws InvalidArgumentException
792
-     * @throws InvalidInterfaceException
793
-     * @throws InvalidDataTypeException
794
-     * @throws EE_Error
795
-     */
796
-    protected function _duplicate_ticket(
797
-        EE_Ticket $ticket,
798
-        $price_rows = array(),
799
-        $ticket_price = 0,
800
-        $base_price = 0,
801
-        $base_price_id = 0
802
-    ) {
803
-        // create new ticket that's a copy of the existing
804
-        // except a new id of course (and not archived)
805
-        // AND has the new TKT_price associated with it.
806
-        $new_ticket = clone $ticket;
807
-        $new_ticket->set('TKT_ID', 0);
808
-        $new_ticket->set_deleted(0);
809
-        $new_ticket->set_price($ticket_price);
810
-        $new_ticket->set_sold(0);
811
-        // let's get a new ID for this ticket
812
-        $new_ticket->save();
813
-        // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
814
-        $datetimes_on_existing = $ticket->datetimes();
815
-        $new_ticket = $this->_update_ticket_datetimes(
816
-            $new_ticket,
817
-            $datetimes_on_existing,
818
-            array_keys($datetimes_on_existing)
819
-        );
820
-        // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
821
-        // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
822
-        // available.
823
-        if ($ticket->sold() > 0) {
824
-            $new_qty = $ticket->qty() - $ticket->sold();
825
-            $new_ticket->set_qty($new_qty);
826
-        }
827
-        // now we update the prices just for this ticket
828
-        $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
829
-        // and we update the base price
830
-        $new_ticket = $this->_add_prices_to_ticket(
831
-            array(),
832
-            $new_ticket,
833
-            true,
834
-            $base_price,
835
-            $base_price_id
836
-        );
837
-        return $new_ticket;
838
-    }
782
+	/**
783
+	 * @access  protected
784
+	 * @param EE_Ticket $ticket
785
+	 * @param array     $price_rows
786
+	 * @param int       $ticket_price
787
+	 * @param int       $base_price
788
+	 * @param int       $base_price_id
789
+	 * @return EE_Ticket
790
+	 * @throws ReflectionException
791
+	 * @throws InvalidArgumentException
792
+	 * @throws InvalidInterfaceException
793
+	 * @throws InvalidDataTypeException
794
+	 * @throws EE_Error
795
+	 */
796
+	protected function _duplicate_ticket(
797
+		EE_Ticket $ticket,
798
+		$price_rows = array(),
799
+		$ticket_price = 0,
800
+		$base_price = 0,
801
+		$base_price_id = 0
802
+	) {
803
+		// create new ticket that's a copy of the existing
804
+		// except a new id of course (and not archived)
805
+		// AND has the new TKT_price associated with it.
806
+		$new_ticket = clone $ticket;
807
+		$new_ticket->set('TKT_ID', 0);
808
+		$new_ticket->set_deleted(0);
809
+		$new_ticket->set_price($ticket_price);
810
+		$new_ticket->set_sold(0);
811
+		// let's get a new ID for this ticket
812
+		$new_ticket->save();
813
+		// we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
814
+		$datetimes_on_existing = $ticket->datetimes();
815
+		$new_ticket = $this->_update_ticket_datetimes(
816
+			$new_ticket,
817
+			$datetimes_on_existing,
818
+			array_keys($datetimes_on_existing)
819
+		);
820
+		// $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
821
+		// if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
822
+		// available.
823
+		if ($ticket->sold() > 0) {
824
+			$new_qty = $ticket->qty() - $ticket->sold();
825
+			$new_ticket->set_qty($new_qty);
826
+		}
827
+		// now we update the prices just for this ticket
828
+		$new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
829
+		// and we update the base price
830
+		$new_ticket = $this->_add_prices_to_ticket(
831
+			array(),
832
+			$new_ticket,
833
+			true,
834
+			$base_price,
835
+			$base_price_id
836
+		);
837
+		return $new_ticket;
838
+	}
839 839
 
840 840
 
841
-    /**
842
-     * This attaches a list of given prices to a ticket.
843
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
844
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
845
-     * price info and prices are automatically "archived" via the ticket.
846
-     *
847
-     * @access  private
848
-     * @param array     $prices        Array of prices from the form.
849
-     * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
850
-     * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
851
-     * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
852
-     * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
853
-     * @return EE_Ticket
854
-     * @throws ReflectionException
855
-     * @throws InvalidArgumentException
856
-     * @throws InvalidInterfaceException
857
-     * @throws InvalidDataTypeException
858
-     * @throws EE_Error
859
-     */
860
-    protected function _add_prices_to_ticket(
861
-        $prices = array(),
862
-        EE_Ticket $ticket,
863
-        $new_prices = false,
864
-        $base_price = false,
865
-        $base_price_id = false
866
-    ) {
867
-        // let's just get any current prices that may exist on the given ticket
868
-        // so we can remove any prices that got trashed in this session.
869
-        $current_prices_on_ticket = $base_price !== false
870
-            ? $ticket->base_price(true)
871
-            : $ticket->price_modifiers();
872
-        $updated_prices = array();
873
-        // if $base_price ! FALSE then updating a base price.
874
-        if ($base_price !== false) {
875
-            $prices[1] = array(
876
-                'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
877
-                'PRT_ID'     => 1,
878
-                'PRC_amount' => $base_price,
879
-                'PRC_name'   => $ticket->get('TKT_name'),
880
-                'PRC_desc'   => $ticket->get('TKT_description'),
881
-            );
882
-        }
883
-        // possibly need to save tkt
884
-        if (! $ticket->ID()) {
885
-            $ticket->save();
886
-        }
887
-        foreach ($prices as $row => $prc) {
888
-            $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
889
-            if (empty($prt_id)) {
890
-                continue;
891
-            } //prices MUST have a price type id.
892
-            $PRC_values = array(
893
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
894
-                'PRT_ID'         => $prt_id,
895
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
896
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
897
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
898
-                'PRC_is_default' => false,
899
-                // make sure we set PRC_is_default to false for all ticket saves from event_editor
900
-                'PRC_order'      => $row,
901
-            );
902
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
903
-                $PRC_values['PRC_ID'] = 0;
904
-                $price = EE_Registry::instance()->load_class(
905
-                    'Price',
906
-                    array($PRC_values),
907
-                    false,
908
-                    false
909
-                );
910
-            } else {
911
-                $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
912
-                // update this price with new values
913
-                foreach ($PRC_values as $field => $value) {
914
-                    $price->set($field, $value);
915
-                }
916
-            }
917
-            $price->save();
918
-            $updated_prices[ $price->ID() ] = $price;
919
-            $ticket->_add_relation_to($price, 'Price');
920
-        }
921
-        // now let's remove any prices that got removed from the ticket
922
-        if (! empty($current_prices_on_ticket)) {
923
-            $current = array_keys($current_prices_on_ticket);
924
-            $updated = array_keys($updated_prices);
925
-            $prices_to_remove = array_diff($current, $updated);
926
-            if (! empty($prices_to_remove)) {
927
-                foreach ($prices_to_remove as $prc_id) {
928
-                    $p = $current_prices_on_ticket[ $prc_id ];
929
-                    $ticket->_remove_relation_to($p, 'Price');
930
-                    // delete permanently the price
931
-                    $p->delete_permanently();
932
-                }
933
-            }
934
-        }
935
-        return $ticket;
936
-    }
841
+	/**
842
+	 * This attaches a list of given prices to a ticket.
843
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
844
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
845
+	 * price info and prices are automatically "archived" via the ticket.
846
+	 *
847
+	 * @access  private
848
+	 * @param array     $prices        Array of prices from the form.
849
+	 * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
850
+	 * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
851
+	 * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
852
+	 * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
853
+	 * @return EE_Ticket
854
+	 * @throws ReflectionException
855
+	 * @throws InvalidArgumentException
856
+	 * @throws InvalidInterfaceException
857
+	 * @throws InvalidDataTypeException
858
+	 * @throws EE_Error
859
+	 */
860
+	protected function _add_prices_to_ticket(
861
+		$prices = array(),
862
+		EE_Ticket $ticket,
863
+		$new_prices = false,
864
+		$base_price = false,
865
+		$base_price_id = false
866
+	) {
867
+		// let's just get any current prices that may exist on the given ticket
868
+		// so we can remove any prices that got trashed in this session.
869
+		$current_prices_on_ticket = $base_price !== false
870
+			? $ticket->base_price(true)
871
+			: $ticket->price_modifiers();
872
+		$updated_prices = array();
873
+		// if $base_price ! FALSE then updating a base price.
874
+		if ($base_price !== false) {
875
+			$prices[1] = array(
876
+				'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
877
+				'PRT_ID'     => 1,
878
+				'PRC_amount' => $base_price,
879
+				'PRC_name'   => $ticket->get('TKT_name'),
880
+				'PRC_desc'   => $ticket->get('TKT_description'),
881
+			);
882
+		}
883
+		// possibly need to save tkt
884
+		if (! $ticket->ID()) {
885
+			$ticket->save();
886
+		}
887
+		foreach ($prices as $row => $prc) {
888
+			$prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
889
+			if (empty($prt_id)) {
890
+				continue;
891
+			} //prices MUST have a price type id.
892
+			$PRC_values = array(
893
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
894
+				'PRT_ID'         => $prt_id,
895
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
896
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
897
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
898
+				'PRC_is_default' => false,
899
+				// make sure we set PRC_is_default to false for all ticket saves from event_editor
900
+				'PRC_order'      => $row,
901
+			);
902
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
903
+				$PRC_values['PRC_ID'] = 0;
904
+				$price = EE_Registry::instance()->load_class(
905
+					'Price',
906
+					array($PRC_values),
907
+					false,
908
+					false
909
+				);
910
+			} else {
911
+				$price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
912
+				// update this price with new values
913
+				foreach ($PRC_values as $field => $value) {
914
+					$price->set($field, $value);
915
+				}
916
+			}
917
+			$price->save();
918
+			$updated_prices[ $price->ID() ] = $price;
919
+			$ticket->_add_relation_to($price, 'Price');
920
+		}
921
+		// now let's remove any prices that got removed from the ticket
922
+		if (! empty($current_prices_on_ticket)) {
923
+			$current = array_keys($current_prices_on_ticket);
924
+			$updated = array_keys($updated_prices);
925
+			$prices_to_remove = array_diff($current, $updated);
926
+			if (! empty($prices_to_remove)) {
927
+				foreach ($prices_to_remove as $prc_id) {
928
+					$p = $current_prices_on_ticket[ $prc_id ];
929
+					$ticket->_remove_relation_to($p, 'Price');
930
+					// delete permanently the price
931
+					$p->delete_permanently();
932
+				}
933
+			}
934
+		}
935
+		return $ticket;
936
+	}
937 937
 
938 938
 
939
-    /**
940
-     * @param Events_Admin_Page $event_admin_obj
941
-     * @return Events_Admin_Page
942
-     */
943
-    public function autosave_handling(Events_Admin_Page $event_admin_obj)
944
-    {
945
-        return $event_admin_obj;
946
-        // doing nothing for the moment.
947
-        // todo when I get to this remember that I need to set the template args on the $event_admin_obj
948
-        // (use the set_template_args() method)
949
-        /**
950
-         * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
951
-         * 1. TKT_is_default_selector (visible)
952
-         * 2. TKT_is_default (hidden)
953
-         * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
954
-         * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
955
-         * this ticket to be saved as a default.
956
-         * The tricky part is, on an initial display on create or edit (or after manually updating),
957
-         * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
958
-         * if this is a create.  However, after an autosave, users will want some sort of indicator that
959
-         * the TKT HAS been saved as a default..
960
-         * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
961
-         * On Autosave:
962
-         * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
963
-         * then set the TKT_is_default to false.
964
-         * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
965
-         *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
966
-         * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
967
-         */
968
-    }
939
+	/**
940
+	 * @param Events_Admin_Page $event_admin_obj
941
+	 * @return Events_Admin_Page
942
+	 */
943
+	public function autosave_handling(Events_Admin_Page $event_admin_obj)
944
+	{
945
+		return $event_admin_obj;
946
+		// doing nothing for the moment.
947
+		// todo when I get to this remember that I need to set the template args on the $event_admin_obj
948
+		// (use the set_template_args() method)
949
+		/**
950
+		 * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
951
+		 * 1. TKT_is_default_selector (visible)
952
+		 * 2. TKT_is_default (hidden)
953
+		 * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
954
+		 * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
955
+		 * this ticket to be saved as a default.
956
+		 * The tricky part is, on an initial display on create or edit (or after manually updating),
957
+		 * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
958
+		 * if this is a create.  However, after an autosave, users will want some sort of indicator that
959
+		 * the TKT HAS been saved as a default..
960
+		 * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
961
+		 * On Autosave:
962
+		 * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
963
+		 * then set the TKT_is_default to false.
964
+		 * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
965
+		 *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
966
+		 * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
967
+		 */
968
+	}
969 969
 
970 970
 
971
-    /**
972
-     * @throws ReflectionException
973
-     * @throws InvalidArgumentException
974
-     * @throws InvalidInterfaceException
975
-     * @throws InvalidDataTypeException
976
-     * @throws DomainException
977
-     * @throws EE_Error
978
-     */
979
-    public function pricing_metabox()
980
-    {
981
-        $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
982
-        $event = $this->_adminpage_obj->get_cpt_model_obj();
983
-        // set is_creating_event property.
984
-        $EVT_ID = $event->ID();
985
-        $this->_is_creating_event = empty($this->_req_data['post']);
986
-        // default main template args
987
-        $main_template_args = array(
988
-            'event_datetime_help_link' => EEH_Template::get_help_tab_link(
989
-                'event_editor_event_datetimes_help_tab',
990
-                $this->_adminpage_obj->page_slug,
991
-                $this->_adminpage_obj->get_req_action(),
992
-                false,
993
-                false
994
-            ),
995
-            // todo need to add a filter to the template for the help text
996
-            // in the Events_Admin_Page core file so we can add further help
997
-            'existing_datetime_ids'    => '',
998
-            'total_dtt_rows'           => 1,
999
-            'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1000
-                'add_new_dtt_info',
1001
-                $this->_adminpage_obj->page_slug,
1002
-                $this->_adminpage_obj->get_req_action(),
1003
-                false,
1004
-                false
1005
-            ),
1006
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1007
-            'datetime_rows'            => '',
1008
-            'show_tickets_container'   => '',
1009
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1010
-            'ticket_rows'              => '',
1011
-            'existing_ticket_ids'      => '',
1012
-            'total_ticket_rows'        => 1,
1013
-            'ticket_js_structure'      => '',
1014
-            'ee_collapsible_status'    => ' ee-collapsible-open'
1015
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1016
-        );
1017
-        $timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1018
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1019
-        /**
1020
-         * 1. Start with retrieving Datetimes
1021
-         * 2. For each datetime get related tickets
1022
-         * 3. For each ticket get related prices
1023
-         */
1024
-        /** @var EEM_Datetime $datetime_model */
1025
-        $datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1026
-        $datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1027
-        $main_template_args['total_dtt_rows'] = count($datetimes);
1028
-        /**
1029
-         * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1030
-         * for why we are counting $datetime_row and then setting that on the Datetime object
1031
-         */
1032
-        $datetime_row = 1;
1033
-        foreach ($datetimes as $datetime) {
1034
-            $DTT_ID = $datetime->get('DTT_ID');
1035
-            $datetime->set('DTT_order', $datetime_row);
1036
-            $existing_datetime_ids[] = $DTT_ID;
1037
-            // tickets attached
1038
-            $related_tickets = $datetime->ID() > 0
1039
-                ? $datetime->get_many_related(
1040
-                    'Ticket',
1041
-                    array(
1042
-                        array(
1043
-                            'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1044
-                        ),
1045
-                        'default_where_conditions' => 'none',
1046
-                        'order_by'                 => array('TKT_order' => 'ASC'),
1047
-                    )
1048
-                )
1049
-                : array();
1050
-            // if there are no related tickets this is likely a new event OR autodraft
1051
-            // event so we need to generate the default tickets because datetimes
1052
-            // ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1053
-            // datetime on the event.
1054
-            if (empty($related_tickets) && count($datetimes) < 2) {
1055
-                /** @var EEM_Ticket $ticket_model */
1056
-                $ticket_model = EE_Registry::instance()->load_model('Ticket');
1057
-                $related_tickets = $ticket_model->get_all_default_tickets();
1058
-                // this should be ordered by TKT_ID, so let's grab the first default ticket
1059
-                // (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1060
-                $default_prices = EEM_Price::instance()->get_all_default_prices();
1061
-                $main_default_ticket = reset($related_tickets);
1062
-                if ($main_default_ticket instanceof EE_Ticket) {
1063
-                    foreach ($default_prices as $default_price) {
1064
-                        if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1065
-                            continue;
1066
-                        }
1067
-                        $main_default_ticket->cache('Price', $default_price);
1068
-                    }
1069
-                }
1070
-            }
1071
-            // we can't actually setup rows in this loop yet cause we don't know all
1072
-            // the unique tickets for this event yet (tickets are linked through all datetimes).
1073
-            // So we're going to temporarily cache some of that information.
1074
-            // loop through and setup the ticket rows and make sure the order is set.
1075
-            foreach ($related_tickets as $ticket) {
1076
-                $TKT_ID = $ticket->get('TKT_ID');
1077
-                $ticket_row = $ticket->get('TKT_row');
1078
-                // we only want unique tickets in our final display!!
1079
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1080
-                    $existing_ticket_ids[] = $TKT_ID;
1081
-                    $all_tickets[] = $ticket;
1082
-                }
1083
-                // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1084
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1085
-                // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1086
-                if (
1087
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1088
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1089
-                ) {
1090
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1091
-                }
1092
-            }
1093
-            $datetime_row++;
1094
-        }
1095
-        $main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1096
-        $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1097
-        $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1098
-        // sort $all_tickets by order
1099
-        usort(
1100
-            $all_tickets,
1101
-            function (EE_Ticket $a, EE_Ticket $b) {
1102
-                $a_order = (int) $a->get('TKT_order');
1103
-                $b_order = (int) $b->get('TKT_order');
1104
-                if ($a_order === $b_order) {
1105
-                    return 0;
1106
-                }
1107
-                return ($a_order < $b_order) ? -1 : 1;
1108
-            }
1109
-        );
1110
-        // k NOW we have all the data we need for setting up the dtt rows
1111
-        // and ticket rows so we start our dtt loop again.
1112
-        $datetime_row = 1;
1113
-        foreach ($datetimes as $datetime) {
1114
-            $main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1115
-                $datetime_row,
1116
-                $datetime,
1117
-                $datetime_tickets,
1118
-                $all_tickets,
1119
-                false,
1120
-                $datetimes
1121
-            );
1122
-            $datetime_row++;
1123
-        }
1124
-        // then loop through all tickets for the ticket rows.
1125
-        $ticket_row = 1;
1126
-        foreach ($all_tickets as $ticket) {
1127
-            $main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1128
-                $ticket_row,
1129
-                $ticket,
1130
-                $ticket_datetimes,
1131
-                $datetimes,
1132
-                false,
1133
-                $all_tickets
1134
-            );
1135
-            $ticket_row++;
1136
-        }
1137
-        $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
971
+	/**
972
+	 * @throws ReflectionException
973
+	 * @throws InvalidArgumentException
974
+	 * @throws InvalidInterfaceException
975
+	 * @throws InvalidDataTypeException
976
+	 * @throws DomainException
977
+	 * @throws EE_Error
978
+	 */
979
+	public function pricing_metabox()
980
+	{
981
+		$existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
982
+		$event = $this->_adminpage_obj->get_cpt_model_obj();
983
+		// set is_creating_event property.
984
+		$EVT_ID = $event->ID();
985
+		$this->_is_creating_event = empty($this->_req_data['post']);
986
+		// default main template args
987
+		$main_template_args = array(
988
+			'event_datetime_help_link' => EEH_Template::get_help_tab_link(
989
+				'event_editor_event_datetimes_help_tab',
990
+				$this->_adminpage_obj->page_slug,
991
+				$this->_adminpage_obj->get_req_action(),
992
+				false,
993
+				false
994
+			),
995
+			// todo need to add a filter to the template for the help text
996
+			// in the Events_Admin_Page core file so we can add further help
997
+			'existing_datetime_ids'    => '',
998
+			'total_dtt_rows'           => 1,
999
+			'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1000
+				'add_new_dtt_info',
1001
+				$this->_adminpage_obj->page_slug,
1002
+				$this->_adminpage_obj->get_req_action(),
1003
+				false,
1004
+				false
1005
+			),
1006
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1007
+			'datetime_rows'            => '',
1008
+			'show_tickets_container'   => '',
1009
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1010
+			'ticket_rows'              => '',
1011
+			'existing_ticket_ids'      => '',
1012
+			'total_ticket_rows'        => 1,
1013
+			'ticket_js_structure'      => '',
1014
+			'ee_collapsible_status'    => ' ee-collapsible-open'
1015
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1016
+		);
1017
+		$timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1018
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1019
+		/**
1020
+		 * 1. Start with retrieving Datetimes
1021
+		 * 2. For each datetime get related tickets
1022
+		 * 3. For each ticket get related prices
1023
+		 */
1024
+		/** @var EEM_Datetime $datetime_model */
1025
+		$datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1026
+		$datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1027
+		$main_template_args['total_dtt_rows'] = count($datetimes);
1028
+		/**
1029
+		 * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1030
+		 * for why we are counting $datetime_row and then setting that on the Datetime object
1031
+		 */
1032
+		$datetime_row = 1;
1033
+		foreach ($datetimes as $datetime) {
1034
+			$DTT_ID = $datetime->get('DTT_ID');
1035
+			$datetime->set('DTT_order', $datetime_row);
1036
+			$existing_datetime_ids[] = $DTT_ID;
1037
+			// tickets attached
1038
+			$related_tickets = $datetime->ID() > 0
1039
+				? $datetime->get_many_related(
1040
+					'Ticket',
1041
+					array(
1042
+						array(
1043
+							'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1044
+						),
1045
+						'default_where_conditions' => 'none',
1046
+						'order_by'                 => array('TKT_order' => 'ASC'),
1047
+					)
1048
+				)
1049
+				: array();
1050
+			// if there are no related tickets this is likely a new event OR autodraft
1051
+			// event so we need to generate the default tickets because datetimes
1052
+			// ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1053
+			// datetime on the event.
1054
+			if (empty($related_tickets) && count($datetimes) < 2) {
1055
+				/** @var EEM_Ticket $ticket_model */
1056
+				$ticket_model = EE_Registry::instance()->load_model('Ticket');
1057
+				$related_tickets = $ticket_model->get_all_default_tickets();
1058
+				// this should be ordered by TKT_ID, so let's grab the first default ticket
1059
+				// (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1060
+				$default_prices = EEM_Price::instance()->get_all_default_prices();
1061
+				$main_default_ticket = reset($related_tickets);
1062
+				if ($main_default_ticket instanceof EE_Ticket) {
1063
+					foreach ($default_prices as $default_price) {
1064
+						if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1065
+							continue;
1066
+						}
1067
+						$main_default_ticket->cache('Price', $default_price);
1068
+					}
1069
+				}
1070
+			}
1071
+			// we can't actually setup rows in this loop yet cause we don't know all
1072
+			// the unique tickets for this event yet (tickets are linked through all datetimes).
1073
+			// So we're going to temporarily cache some of that information.
1074
+			// loop through and setup the ticket rows and make sure the order is set.
1075
+			foreach ($related_tickets as $ticket) {
1076
+				$TKT_ID = $ticket->get('TKT_ID');
1077
+				$ticket_row = $ticket->get('TKT_row');
1078
+				// we only want unique tickets in our final display!!
1079
+				if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1080
+					$existing_ticket_ids[] = $TKT_ID;
1081
+					$all_tickets[] = $ticket;
1082
+				}
1083
+				// temporary cache of this ticket info for this datetime for later processing of datetime rows.
1084
+				$datetime_tickets[ $DTT_ID ][] = $ticket_row;
1085
+				// temporary cache of this datetime info for this ticket for later processing of ticket rows.
1086
+				if (
1087
+					! isset($ticket_datetimes[ $TKT_ID ])
1088
+					|| ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1089
+				) {
1090
+					$ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1091
+				}
1092
+			}
1093
+			$datetime_row++;
1094
+		}
1095
+		$main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1096
+		$main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1097
+		$main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1098
+		// sort $all_tickets by order
1099
+		usort(
1100
+			$all_tickets,
1101
+			function (EE_Ticket $a, EE_Ticket $b) {
1102
+				$a_order = (int) $a->get('TKT_order');
1103
+				$b_order = (int) $b->get('TKT_order');
1104
+				if ($a_order === $b_order) {
1105
+					return 0;
1106
+				}
1107
+				return ($a_order < $b_order) ? -1 : 1;
1108
+			}
1109
+		);
1110
+		// k NOW we have all the data we need for setting up the dtt rows
1111
+		// and ticket rows so we start our dtt loop again.
1112
+		$datetime_row = 1;
1113
+		foreach ($datetimes as $datetime) {
1114
+			$main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1115
+				$datetime_row,
1116
+				$datetime,
1117
+				$datetime_tickets,
1118
+				$all_tickets,
1119
+				false,
1120
+				$datetimes
1121
+			);
1122
+			$datetime_row++;
1123
+		}
1124
+		// then loop through all tickets for the ticket rows.
1125
+		$ticket_row = 1;
1126
+		foreach ($all_tickets as $ticket) {
1127
+			$main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1128
+				$ticket_row,
1129
+				$ticket,
1130
+				$ticket_datetimes,
1131
+				$datetimes,
1132
+				false,
1133
+				$all_tickets
1134
+			);
1135
+			$ticket_row++;
1136
+		}
1137
+		$main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1138 1138
 
1139
-        $status_change_notice = EventEspresso\core\services\loaders\LoaderFactory::getLoader()->getShared(
1140
-            'EventEspresso\core\admin\StatusChangeNotice'
1141
-        );
1142
-        if (! $status_change_notice->isDismissed()) {
1143
-            $main_template_args['status_change_notice'] = EEH_Template::display_template(
1144
-                EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
1145
-                ['context' => '__event-editor', 'page_slug' => 'espresso-events'],
1146
-                true
1147
-            );
1148
-        }
1139
+		$status_change_notice = EventEspresso\core\services\loaders\LoaderFactory::getLoader()->getShared(
1140
+			'EventEspresso\core\admin\StatusChangeNotice'
1141
+		);
1142
+		if (! $status_change_notice->isDismissed()) {
1143
+			$main_template_args['status_change_notice'] = EEH_Template::display_template(
1144
+				EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
1145
+				['context' => '__event-editor', 'page_slug' => 'espresso-events'],
1146
+				true
1147
+			);
1148
+		}
1149 1149
 
1150
-        EEH_Template::display_template(
1151
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1152
-            $main_template_args
1153
-        );
1154
-    }
1150
+		EEH_Template::display_template(
1151
+			PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1152
+			$main_template_args
1153
+		);
1154
+	}
1155 1155
 
1156 1156
 
1157
-    /**
1158
-     * @param int         $datetime_row
1159
-     * @param EE_Datetime $datetime
1160
-     * @param array       $datetime_tickets
1161
-     * @param array       $all_tickets
1162
-     * @param bool        $default
1163
-     * @param array       $all_datetimes
1164
-     * @return mixed
1165
-     * @throws DomainException
1166
-     * @throws EE_Error
1167
-     */
1168
-    protected function _get_datetime_row(
1169
-        $datetime_row,
1170
-        EE_Datetime $datetime,
1171
-        $datetime_tickets = array(),
1172
-        $all_tickets = array(),
1173
-        $default = false,
1174
-        $all_datetimes = array()
1175
-    ) {
1176
-        $dtt_display_template_args = array(
1177
-            'dtt_edit_row'             => $this->_get_dtt_edit_row(
1178
-                $datetime_row,
1179
-                $datetime,
1180
-                $default,
1181
-                $all_datetimes
1182
-            ),
1183
-            'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1184
-                $datetime_row,
1185
-                $datetime,
1186
-                $datetime_tickets,
1187
-                $all_tickets,
1188
-                $default
1189
-            ),
1190
-            'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1191
-        );
1192
-        return EEH_Template::display_template(
1193
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1194
-            $dtt_display_template_args,
1195
-            true
1196
-        );
1197
-    }
1157
+	/**
1158
+	 * @param int         $datetime_row
1159
+	 * @param EE_Datetime $datetime
1160
+	 * @param array       $datetime_tickets
1161
+	 * @param array       $all_tickets
1162
+	 * @param bool        $default
1163
+	 * @param array       $all_datetimes
1164
+	 * @return mixed
1165
+	 * @throws DomainException
1166
+	 * @throws EE_Error
1167
+	 */
1168
+	protected function _get_datetime_row(
1169
+		$datetime_row,
1170
+		EE_Datetime $datetime,
1171
+		$datetime_tickets = array(),
1172
+		$all_tickets = array(),
1173
+		$default = false,
1174
+		$all_datetimes = array()
1175
+	) {
1176
+		$dtt_display_template_args = array(
1177
+			'dtt_edit_row'             => $this->_get_dtt_edit_row(
1178
+				$datetime_row,
1179
+				$datetime,
1180
+				$default,
1181
+				$all_datetimes
1182
+			),
1183
+			'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1184
+				$datetime_row,
1185
+				$datetime,
1186
+				$datetime_tickets,
1187
+				$all_tickets,
1188
+				$default
1189
+			),
1190
+			'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1191
+		);
1192
+		return EEH_Template::display_template(
1193
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1194
+			$dtt_display_template_args,
1195
+			true
1196
+		);
1197
+	}
1198 1198
 
1199 1199
 
1200
-    /**
1201
-     * This method is used to generate a dtt fields  edit row.
1202
-     * The same row is used to generate a row with valid DTT objects
1203
-     * and the default row that is used as the skeleton by the js.
1204
-     *
1205
-     * @param int           $datetime_row  The row number for the row being generated.
1206
-     * @param EE_Datetime   $datetime
1207
-     * @param bool          $default       Whether a default row is being generated or not.
1208
-     * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1209
-     * @return string
1210
-     * @throws DomainException
1211
-     * @throws EE_Error
1212
-     */
1213
-    protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1214
-    {
1215
-        // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1216
-        $default = ! $datetime instanceof EE_Datetime ? true : $default;
1217
-        $template_args = array(
1218
-            'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1219
-            'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1220
-            'edit_dtt_expanded'    => '',
1221
-            'DTT_ID'               => $default ? '' : $datetime->ID(),
1222
-            'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1223
-            'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1224
-            'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1225
-            'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1226
-            'DTT_reg_limit'        => $default
1227
-                ? ''
1228
-                : $datetime->get_pretty(
1229
-                    'DTT_reg_limit',
1230
-                    'input'
1231
-                ),
1232
-            'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1233
-            'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1234
-            'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1235
-            'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1236
-                ? ''
1237
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1238
-            'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1239
-                ? 'dashicons dashicons-lock'
1240
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1241
-            'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1242
-                ? ''
1243
-                : EE_Admin_Page::add_query_args_and_nonce(
1244
-                    array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1245
-                    REG_ADMIN_URL
1246
-                ),
1247
-        );
1248
-        $template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'dashicons dashicons-lock'
1249
-            ? ' style="display:none"'
1250
-            : '';
1251
-        // allow filtering of template args at this point.
1252
-        $template_args = apply_filters(
1253
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1254
-            $template_args,
1255
-            $datetime_row,
1256
-            $datetime,
1257
-            $default,
1258
-            $all_datetimes,
1259
-            $this->_is_creating_event
1260
-        );
1261
-        return EEH_Template::display_template(
1262
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1263
-            $template_args,
1264
-            true
1265
-        );
1266
-    }
1200
+	/**
1201
+	 * This method is used to generate a dtt fields  edit row.
1202
+	 * The same row is used to generate a row with valid DTT objects
1203
+	 * and the default row that is used as the skeleton by the js.
1204
+	 *
1205
+	 * @param int           $datetime_row  The row number for the row being generated.
1206
+	 * @param EE_Datetime   $datetime
1207
+	 * @param bool          $default       Whether a default row is being generated or not.
1208
+	 * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1209
+	 * @return string
1210
+	 * @throws DomainException
1211
+	 * @throws EE_Error
1212
+	 */
1213
+	protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1214
+	{
1215
+		// if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1216
+		$default = ! $datetime instanceof EE_Datetime ? true : $default;
1217
+		$template_args = array(
1218
+			'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1219
+			'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1220
+			'edit_dtt_expanded'    => '',
1221
+			'DTT_ID'               => $default ? '' : $datetime->ID(),
1222
+			'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1223
+			'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1224
+			'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1225
+			'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1226
+			'DTT_reg_limit'        => $default
1227
+				? ''
1228
+				: $datetime->get_pretty(
1229
+					'DTT_reg_limit',
1230
+					'input'
1231
+				),
1232
+			'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1233
+			'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1234
+			'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1235
+			'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1236
+				? ''
1237
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1238
+			'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1239
+				? 'dashicons dashicons-lock'
1240
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1241
+			'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1242
+				? ''
1243
+				: EE_Admin_Page::add_query_args_and_nonce(
1244
+					array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1245
+					REG_ADMIN_URL
1246
+				),
1247
+		);
1248
+		$template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'dashicons dashicons-lock'
1249
+			? ' style="display:none"'
1250
+			: '';
1251
+		// allow filtering of template args at this point.
1252
+		$template_args = apply_filters(
1253
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1254
+			$template_args,
1255
+			$datetime_row,
1256
+			$datetime,
1257
+			$default,
1258
+			$all_datetimes,
1259
+			$this->_is_creating_event
1260
+		);
1261
+		return EEH_Template::display_template(
1262
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1263
+			$template_args,
1264
+			true
1265
+		);
1266
+	}
1267 1267
 
1268 1268
 
1269
-    /**
1270
-     * @param int         $datetime_row
1271
-     * @param EE_Datetime $datetime
1272
-     * @param array       $datetime_tickets
1273
-     * @param array       $all_tickets
1274
-     * @param bool        $default
1275
-     * @return mixed
1276
-     * @throws DomainException
1277
-     * @throws EE_Error
1278
-     */
1279
-    protected function _get_dtt_attached_tickets_row(
1280
-        $datetime_row,
1281
-        $datetime,
1282
-        $datetime_tickets = array(),
1283
-        $all_tickets = array(),
1284
-        $default
1285
-    ) {
1286
-        $template_args = array(
1287
-            'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1288
-            'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1289
-            'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1290
-            'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1291
-            'show_tickets_row'                  => ' style="display:none;"',
1292
-            'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1293
-                'add_new_ticket_via_datetime',
1294
-                $this->_adminpage_obj->page_slug,
1295
-                $this->_adminpage_obj->get_req_action(),
1296
-                false,
1297
-                false
1298
-            ),
1299
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1300
-            'DTT_ID'                            => $default ? '' : $datetime->ID(),
1301
-        );
1302
-        // need to setup the list items (but only if this isn't a default skeleton setup)
1303
-        if (! $default) {
1304
-            $ticket_row = 1;
1305
-            foreach ($all_tickets as $ticket) {
1306
-                $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1307
-                    $datetime_row,
1308
-                    $ticket_row,
1309
-                    $datetime,
1310
-                    $ticket,
1311
-                    $datetime_tickets,
1312
-                    $default
1313
-                );
1314
-                $ticket_row++;
1315
-            }
1316
-        }
1317
-        // filter template args at this point
1318
-        $template_args = apply_filters(
1319
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1320
-            $template_args,
1321
-            $datetime_row,
1322
-            $datetime,
1323
-            $datetime_tickets,
1324
-            $all_tickets,
1325
-            $default,
1326
-            $this->_is_creating_event
1327
-        );
1328
-        return EEH_Template::display_template(
1329
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1330
-            $template_args,
1331
-            true
1332
-        );
1333
-    }
1269
+	/**
1270
+	 * @param int         $datetime_row
1271
+	 * @param EE_Datetime $datetime
1272
+	 * @param array       $datetime_tickets
1273
+	 * @param array       $all_tickets
1274
+	 * @param bool        $default
1275
+	 * @return mixed
1276
+	 * @throws DomainException
1277
+	 * @throws EE_Error
1278
+	 */
1279
+	protected function _get_dtt_attached_tickets_row(
1280
+		$datetime_row,
1281
+		$datetime,
1282
+		$datetime_tickets = array(),
1283
+		$all_tickets = array(),
1284
+		$default
1285
+	) {
1286
+		$template_args = array(
1287
+			'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1288
+			'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1289
+			'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1290
+			'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1291
+			'show_tickets_row'                  => ' style="display:none;"',
1292
+			'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1293
+				'add_new_ticket_via_datetime',
1294
+				$this->_adminpage_obj->page_slug,
1295
+				$this->_adminpage_obj->get_req_action(),
1296
+				false,
1297
+				false
1298
+			),
1299
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1300
+			'DTT_ID'                            => $default ? '' : $datetime->ID(),
1301
+		);
1302
+		// need to setup the list items (but only if this isn't a default skeleton setup)
1303
+		if (! $default) {
1304
+			$ticket_row = 1;
1305
+			foreach ($all_tickets as $ticket) {
1306
+				$template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1307
+					$datetime_row,
1308
+					$ticket_row,
1309
+					$datetime,
1310
+					$ticket,
1311
+					$datetime_tickets,
1312
+					$default
1313
+				);
1314
+				$ticket_row++;
1315
+			}
1316
+		}
1317
+		// filter template args at this point
1318
+		$template_args = apply_filters(
1319
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1320
+			$template_args,
1321
+			$datetime_row,
1322
+			$datetime,
1323
+			$datetime_tickets,
1324
+			$all_tickets,
1325
+			$default,
1326
+			$this->_is_creating_event
1327
+		);
1328
+		return EEH_Template::display_template(
1329
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1330
+			$template_args,
1331
+			true
1332
+		);
1333
+	}
1334 1334
 
1335 1335
 
1336
-    /**
1337
-     * @param int         $datetime_row
1338
-     * @param int         $ticket_row
1339
-     * @param EE_Datetime $datetime
1340
-     * @param EE_Ticket   $ticket
1341
-     * @param array       $datetime_tickets
1342
-     * @param bool        $default
1343
-     * @return mixed
1344
-     * @throws DomainException
1345
-     * @throws EE_Error
1346
-     */
1347
-    protected function _get_datetime_tickets_list_item(
1348
-        $datetime_row,
1349
-        $ticket_row,
1350
-        $datetime,
1351
-        $ticket,
1352
-        $datetime_tickets = array(),
1353
-        $default
1354
-    ) {
1355
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1356
-            ? $datetime_tickets[ $datetime->ID() ]
1357
-            : array();
1358
-        $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1359
-        $no_ticket = $default && empty($ticket);
1360
-        $template_args = array(
1361
-            'dtt_row'                 => $default
1362
-                ? 'DTTNUM'
1363
-                : $datetime_row,
1364
-            'tkt_row'                 => $no_ticket
1365
-                ? 'TICKETNUM'
1366
-                : $ticket_row,
1367
-            'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1368
-                ? ' checked'
1369
-                : '',
1370
-            'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1371
-                ? ' ticket-selected'
1372
-                : '',
1373
-            'TKT_name'                => $no_ticket
1374
-                ? 'TKTNAME'
1375
-                : $ticket->get('TKT_name'),
1376
-            'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1377
-                ? ' tkt-status-' . EE_Ticket::onsale
1378
-                : ' tkt-status-' . $ticket->ticket_status(),
1379
-        );
1380
-        // filter template args
1381
-        $template_args = apply_filters(
1382
-            'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1383
-            $template_args,
1384
-            $datetime_row,
1385
-            $ticket_row,
1386
-            $datetime,
1387
-            $ticket,
1388
-            $datetime_tickets,
1389
-            $default,
1390
-            $this->_is_creating_event
1391
-        );
1392
-        return EEH_Template::display_template(
1393
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1394
-            $template_args,
1395
-            true
1396
-        );
1397
-    }
1336
+	/**
1337
+	 * @param int         $datetime_row
1338
+	 * @param int         $ticket_row
1339
+	 * @param EE_Datetime $datetime
1340
+	 * @param EE_Ticket   $ticket
1341
+	 * @param array       $datetime_tickets
1342
+	 * @param bool        $default
1343
+	 * @return mixed
1344
+	 * @throws DomainException
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	protected function _get_datetime_tickets_list_item(
1348
+		$datetime_row,
1349
+		$ticket_row,
1350
+		$datetime,
1351
+		$ticket,
1352
+		$datetime_tickets = array(),
1353
+		$default
1354
+	) {
1355
+		$dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1356
+			? $datetime_tickets[ $datetime->ID() ]
1357
+			: array();
1358
+		$display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1359
+		$no_ticket = $default && empty($ticket);
1360
+		$template_args = array(
1361
+			'dtt_row'                 => $default
1362
+				? 'DTTNUM'
1363
+				: $datetime_row,
1364
+			'tkt_row'                 => $no_ticket
1365
+				? 'TICKETNUM'
1366
+				: $ticket_row,
1367
+			'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1368
+				? ' checked'
1369
+				: '',
1370
+			'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1371
+				? ' ticket-selected'
1372
+				: '',
1373
+			'TKT_name'                => $no_ticket
1374
+				? 'TKTNAME'
1375
+				: $ticket->get('TKT_name'),
1376
+			'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1377
+				? ' tkt-status-' . EE_Ticket::onsale
1378
+				: ' tkt-status-' . $ticket->ticket_status(),
1379
+		);
1380
+		// filter template args
1381
+		$template_args = apply_filters(
1382
+			'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1383
+			$template_args,
1384
+			$datetime_row,
1385
+			$ticket_row,
1386
+			$datetime,
1387
+			$ticket,
1388
+			$datetime_tickets,
1389
+			$default,
1390
+			$this->_is_creating_event
1391
+		);
1392
+		return EEH_Template::display_template(
1393
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1394
+			$template_args,
1395
+			true
1396
+		);
1397
+	}
1398 1398
 
1399 1399
 
1400
-    /**
1401
-     * This generates the ticket row for tickets.
1402
-     * This same method is used to generate both the actual rows and the js skeleton row
1403
-     * (when default === true)
1404
-     *
1405
-     * @param int           $ticket_row       Represents the row number being generated.
1406
-     * @param               $ticket
1407
-     * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1408
-     *                                        or empty for default
1409
-     * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1410
-     * @param bool          $default          Whether default row being generated or not.
1411
-     * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1412
-     *                                        (or empty in the case of defaults)
1413
-     * @return mixed
1414
-     * @throws InvalidArgumentException
1415
-     * @throws InvalidInterfaceException
1416
-     * @throws InvalidDataTypeException
1417
-     * @throws DomainException
1418
-     * @throws EE_Error
1419
-     * @throws ReflectionException
1420
-     */
1421
-    protected function _get_ticket_row(
1422
-        $ticket_row,
1423
-        $ticket,
1424
-        $ticket_datetimes,
1425
-        $all_datetimes,
1426
-        $default = false,
1427
-        $all_tickets = array()
1428
-    ) {
1429
-        // if $ticket is not an instance of EE_Ticket then force default to true.
1430
-        $default = ! $ticket instanceof EE_Ticket ? true : $default;
1431
-        $prices = ! empty($ticket) && ! $default
1432
-            ? $ticket->get_many_related(
1433
-                'Price',
1434
-                array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1435
-            )
1436
-            : array();
1437
-        // if there is only one price (which would be the base price)
1438
-        // or NO prices and this ticket is a default ticket,
1439
-        // let's just make sure there are no cached default prices on the object.
1440
-        // This is done by not including any query_params.
1441
-        if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1442
-            $prices = $ticket->prices();
1443
-        }
1444
-        // check if we're dealing with a default ticket in which case
1445
-        // we don't want any starting_ticket_datetime_row values set
1446
-        // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1447
-        // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1448
-        $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1449
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1450
-            ? $ticket_datetimes[ $ticket->ID() ]
1451
-            : array();
1452
-        $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1453
-        $base_price = $default ? null : $ticket->base_price();
1454
-        $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1455
-        // breaking out complicated condition for ticket_status
1456
-        if ($default) {
1457
-            $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1458
-        } else {
1459
-            $ticket_status_class = $ticket->is_default()
1460
-                ? ' tkt-status-' . EE_Ticket::onsale
1461
-                : ' tkt-status-' . $ticket->ticket_status();
1462
-        }
1463
-        // breaking out complicated condition for TKT_taxable
1464
-        if ($default) {
1465
-            $TKT_taxable = '';
1466
-        } else {
1467
-            $TKT_taxable = $ticket->taxable()
1468
-                ? ' checked'
1469
-                : '';
1470
-        }
1471
-        if ($default) {
1472
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1473
-        } elseif ($ticket->is_default()) {
1474
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1475
-        } else {
1476
-            $TKT_status = $ticket->ticket_status(true);
1477
-        }
1478
-        if ($default) {
1479
-            $TKT_min = '';
1480
-        } else {
1481
-            $TKT_min = $ticket->min();
1482
-            if ($TKT_min === -1 || $TKT_min === 0) {
1483
-                $TKT_min = '';
1484
-            }
1485
-        }
1486
-        $template_args = array(
1487
-            'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1488
-            'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1489
-            // on initial page load this will always be the correct order.
1490
-            'tkt_status_class'              => $ticket_status_class,
1491
-            'display_edit_tkt_row'          => ' style="display:none;"',
1492
-            'edit_tkt_expanded'             => '',
1493
-            'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1494
-            'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1495
-            'TKT_start_date'                => $default
1496
-                ? ''
1497
-                : $ticket->get_date('TKT_start_date', $this->_date_time_format),
1498
-            'TKT_end_date'                  => $default
1499
-                ? ''
1500
-                : $ticket->get_date('TKT_end_date', $this->_date_time_format),
1501
-            'TKT_status'                    => $TKT_status,
1502
-            'TKT_price'                     => $default
1503
-                ? ''
1504
-                : EEH_Template::format_currency(
1505
-                    $ticket->get_ticket_total_with_taxes(),
1506
-                    false,
1507
-                    false
1508
-                ),
1509
-            'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1510
-            'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1511
-            'TKT_qty'                       => $default
1512
-                ? ''
1513
-                : $ticket->get_pretty('TKT_qty', 'symbol'),
1514
-            'TKT_qty_for_input'             => $default
1515
-                ? ''
1516
-                : $ticket->get_pretty('TKT_qty', 'input'),
1517
-            'TKT_uses'                      => $default
1518
-                ? ''
1519
-                : $ticket->get_pretty('TKT_uses', 'input'),
1520
-            'TKT_min'                       => $TKT_min,
1521
-            'TKT_max'                       => $default
1522
-                ? ''
1523
-                : $ticket->get_pretty('TKT_max', 'input'),
1524
-            'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1525
-            'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1526
-            'TKT_registrations'             => $default
1527
-                ? 0
1528
-                : $ticket->count_registrations(
1529
-                    array(
1530
-                        array(
1531
-                            'STS_ID' => array(
1532
-                                '!=',
1533
-                                EEM_Registration::status_id_incomplete,
1534
-                            ),
1535
-                        ),
1536
-                    )
1537
-                ),
1538
-            'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1539
-            'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1540
-            'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1541
-            'TKT_required'                  => $default ? 0 : $ticket->required(),
1542
-            'TKT_is_default_selector'       => '',
1543
-            'ticket_price_rows'             => '',
1544
-            'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1545
-                ? ''
1546
-                : $base_price->get_pretty('PRC_amount', 'localized_float'),
1547
-            'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1548
-            'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1549
-                ? ''
1550
-                : ' style="display:none;"',
1551
-            'show_price_mod_button'         => count($prices) > 1
1552
-                                               || ($default && $count_price_mods > 0)
1553
-                                               || (! $default && $ticket->deleted())
1554
-                ? ' style="display:none;"'
1555
-                : '',
1556
-            'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1557
-            'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1558
-            'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1559
-            'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1560
-            'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1561
-            'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1562
-            'TKT_taxable'                   => $TKT_taxable,
1563
-            'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1564
-                ? ''
1565
-                : ' style="display:none"',
1566
-            'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1567
-            'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1568
-                $ticket_subtotal,
1569
-                false,
1570
-                false
1571
-            ),
1572
-            'TKT_subtotal_amount'           => $ticket_subtotal,
1573
-            'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1574
-            'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1575
-            'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1576
-                ? ' ticket-archived'
1577
-                : '',
1578
-            'trash_icon'                    => $ticket instanceof EE_Ticket
1579
-                                               && $ticket->deleted()
1580
-                                               && ! $ticket->is_permanently_deleteable()
1581
-                ? 'dashicons dashicons-lock '
1582
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1583
-            'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1584
-                ? ''
1585
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1586
-        );
1587
-        $template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'dashicons dashicons-lock'
1588
-            ? ' style="display:none"'
1589
-            : '';
1590
-        // handle rows that should NOT be empty
1591
-        if (empty($template_args['TKT_start_date'])) {
1592
-            // if empty then the start date will be now.
1593
-            $template_args['TKT_start_date'] = date(
1594
-                $this->_date_time_format,
1595
-                current_time('timestamp')
1596
-            );
1597
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1598
-        }
1599
-        if (empty($template_args['TKT_end_date'])) {
1600
-            // get the earliest datetime (if present);
1601
-            $earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1602
-                ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1603
-                    'Datetime',
1604
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1605
-                )
1606
-                : null;
1607
-            if (! empty($earliest_dtt)) {
1608
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1609
-                    'DTT_EVT_start',
1610
-                    $this->_date_time_format
1611
-                );
1612
-            } else {
1613
-                // default so let's just use what's been set for the default date-time which is 30 days from now.
1614
-                $template_args['TKT_end_date'] = date(
1615
-                    $this->_date_time_format,
1616
-                    mktime(
1617
-                        24,
1618
-                        0,
1619
-                        0,
1620
-                        date('m'),
1621
-                        date('d') + 29,
1622
-                        date('Y')
1623
-                    )
1624
-                );
1625
-            }
1626
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1627
-        }
1628
-        // generate ticket_datetime items
1629
-        if (! $default) {
1630
-            $datetime_row = 1;
1631
-            foreach ($all_datetimes as $datetime) {
1632
-                $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1633
-                    $datetime_row,
1634
-                    $ticket_row,
1635
-                    $datetime,
1636
-                    $ticket,
1637
-                    $ticket_datetimes,
1638
-                    $default
1639
-                );
1640
-                $datetime_row++;
1641
-            }
1642
-        }
1643
-        $price_row = 1;
1644
-        foreach ($prices as $price) {
1645
-            if (! $price instanceof EE_Price) {
1646
-                continue;
1647
-            }
1648
-            if ($price->is_base_price()) {
1649
-                $price_row++;
1650
-                continue;
1651
-            }
1652
-            $show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1653
-            $show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1654
-            $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1655
-                $ticket_row,
1656
-                $price_row,
1657
-                $price,
1658
-                $default,
1659
-                $ticket,
1660
-                $show_trash,
1661
-                $show_create
1662
-            );
1663
-            $price_row++;
1664
-        }
1665
-        // filter $template_args
1666
-        $template_args = apply_filters(
1667
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1668
-            $template_args,
1669
-            $ticket_row,
1670
-            $ticket,
1671
-            $ticket_datetimes,
1672
-            $all_datetimes,
1673
-            $default,
1674
-            $all_tickets,
1675
-            $this->_is_creating_event
1676
-        );
1677
-        return EEH_Template::display_template(
1678
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1679
-            $template_args,
1680
-            true
1681
-        );
1682
-    }
1400
+	/**
1401
+	 * This generates the ticket row for tickets.
1402
+	 * This same method is used to generate both the actual rows and the js skeleton row
1403
+	 * (when default === true)
1404
+	 *
1405
+	 * @param int           $ticket_row       Represents the row number being generated.
1406
+	 * @param               $ticket
1407
+	 * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1408
+	 *                                        or empty for default
1409
+	 * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1410
+	 * @param bool          $default          Whether default row being generated or not.
1411
+	 * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1412
+	 *                                        (or empty in the case of defaults)
1413
+	 * @return mixed
1414
+	 * @throws InvalidArgumentException
1415
+	 * @throws InvalidInterfaceException
1416
+	 * @throws InvalidDataTypeException
1417
+	 * @throws DomainException
1418
+	 * @throws EE_Error
1419
+	 * @throws ReflectionException
1420
+	 */
1421
+	protected function _get_ticket_row(
1422
+		$ticket_row,
1423
+		$ticket,
1424
+		$ticket_datetimes,
1425
+		$all_datetimes,
1426
+		$default = false,
1427
+		$all_tickets = array()
1428
+	) {
1429
+		// if $ticket is not an instance of EE_Ticket then force default to true.
1430
+		$default = ! $ticket instanceof EE_Ticket ? true : $default;
1431
+		$prices = ! empty($ticket) && ! $default
1432
+			? $ticket->get_many_related(
1433
+				'Price',
1434
+				array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1435
+			)
1436
+			: array();
1437
+		// if there is only one price (which would be the base price)
1438
+		// or NO prices and this ticket is a default ticket,
1439
+		// let's just make sure there are no cached default prices on the object.
1440
+		// This is done by not including any query_params.
1441
+		if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1442
+			$prices = $ticket->prices();
1443
+		}
1444
+		// check if we're dealing with a default ticket in which case
1445
+		// we don't want any starting_ticket_datetime_row values set
1446
+		// (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1447
+		// This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1448
+		$default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1449
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1450
+			? $ticket_datetimes[ $ticket->ID() ]
1451
+			: array();
1452
+		$ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1453
+		$base_price = $default ? null : $ticket->base_price();
1454
+		$count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1455
+		// breaking out complicated condition for ticket_status
1456
+		if ($default) {
1457
+			$ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1458
+		} else {
1459
+			$ticket_status_class = $ticket->is_default()
1460
+				? ' tkt-status-' . EE_Ticket::onsale
1461
+				: ' tkt-status-' . $ticket->ticket_status();
1462
+		}
1463
+		// breaking out complicated condition for TKT_taxable
1464
+		if ($default) {
1465
+			$TKT_taxable = '';
1466
+		} else {
1467
+			$TKT_taxable = $ticket->taxable()
1468
+				? ' checked'
1469
+				: '';
1470
+		}
1471
+		if ($default) {
1472
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1473
+		} elseif ($ticket->is_default()) {
1474
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1475
+		} else {
1476
+			$TKT_status = $ticket->ticket_status(true);
1477
+		}
1478
+		if ($default) {
1479
+			$TKT_min = '';
1480
+		} else {
1481
+			$TKT_min = $ticket->min();
1482
+			if ($TKT_min === -1 || $TKT_min === 0) {
1483
+				$TKT_min = '';
1484
+			}
1485
+		}
1486
+		$template_args = array(
1487
+			'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1488
+			'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1489
+			// on initial page load this will always be the correct order.
1490
+			'tkt_status_class'              => $ticket_status_class,
1491
+			'display_edit_tkt_row'          => ' style="display:none;"',
1492
+			'edit_tkt_expanded'             => '',
1493
+			'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1494
+			'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1495
+			'TKT_start_date'                => $default
1496
+				? ''
1497
+				: $ticket->get_date('TKT_start_date', $this->_date_time_format),
1498
+			'TKT_end_date'                  => $default
1499
+				? ''
1500
+				: $ticket->get_date('TKT_end_date', $this->_date_time_format),
1501
+			'TKT_status'                    => $TKT_status,
1502
+			'TKT_price'                     => $default
1503
+				? ''
1504
+				: EEH_Template::format_currency(
1505
+					$ticket->get_ticket_total_with_taxes(),
1506
+					false,
1507
+					false
1508
+				),
1509
+			'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1510
+			'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1511
+			'TKT_qty'                       => $default
1512
+				? ''
1513
+				: $ticket->get_pretty('TKT_qty', 'symbol'),
1514
+			'TKT_qty_for_input'             => $default
1515
+				? ''
1516
+				: $ticket->get_pretty('TKT_qty', 'input'),
1517
+			'TKT_uses'                      => $default
1518
+				? ''
1519
+				: $ticket->get_pretty('TKT_uses', 'input'),
1520
+			'TKT_min'                       => $TKT_min,
1521
+			'TKT_max'                       => $default
1522
+				? ''
1523
+				: $ticket->get_pretty('TKT_max', 'input'),
1524
+			'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1525
+			'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1526
+			'TKT_registrations'             => $default
1527
+				? 0
1528
+				: $ticket->count_registrations(
1529
+					array(
1530
+						array(
1531
+							'STS_ID' => array(
1532
+								'!=',
1533
+								EEM_Registration::status_id_incomplete,
1534
+							),
1535
+						),
1536
+					)
1537
+				),
1538
+			'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1539
+			'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1540
+			'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1541
+			'TKT_required'                  => $default ? 0 : $ticket->required(),
1542
+			'TKT_is_default_selector'       => '',
1543
+			'ticket_price_rows'             => '',
1544
+			'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1545
+				? ''
1546
+				: $base_price->get_pretty('PRC_amount', 'localized_float'),
1547
+			'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1548
+			'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1549
+				? ''
1550
+				: ' style="display:none;"',
1551
+			'show_price_mod_button'         => count($prices) > 1
1552
+											   || ($default && $count_price_mods > 0)
1553
+											   || (! $default && $ticket->deleted())
1554
+				? ' style="display:none;"'
1555
+				: '',
1556
+			'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1557
+			'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1558
+			'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1559
+			'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1560
+			'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1561
+			'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1562
+			'TKT_taxable'                   => $TKT_taxable,
1563
+			'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1564
+				? ''
1565
+				: ' style="display:none"',
1566
+			'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1567
+			'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1568
+				$ticket_subtotal,
1569
+				false,
1570
+				false
1571
+			),
1572
+			'TKT_subtotal_amount'           => $ticket_subtotal,
1573
+			'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1574
+			'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1575
+			'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1576
+				? ' ticket-archived'
1577
+				: '',
1578
+			'trash_icon'                    => $ticket instanceof EE_Ticket
1579
+											   && $ticket->deleted()
1580
+											   && ! $ticket->is_permanently_deleteable()
1581
+				? 'dashicons dashicons-lock '
1582
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1583
+			'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1584
+				? ''
1585
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1586
+		);
1587
+		$template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'dashicons dashicons-lock'
1588
+			? ' style="display:none"'
1589
+			: '';
1590
+		// handle rows that should NOT be empty
1591
+		if (empty($template_args['TKT_start_date'])) {
1592
+			// if empty then the start date will be now.
1593
+			$template_args['TKT_start_date'] = date(
1594
+				$this->_date_time_format,
1595
+				current_time('timestamp')
1596
+			);
1597
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1598
+		}
1599
+		if (empty($template_args['TKT_end_date'])) {
1600
+			// get the earliest datetime (if present);
1601
+			$earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1602
+				? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1603
+					'Datetime',
1604
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1605
+				)
1606
+				: null;
1607
+			if (! empty($earliest_dtt)) {
1608
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1609
+					'DTT_EVT_start',
1610
+					$this->_date_time_format
1611
+				);
1612
+			} else {
1613
+				// default so let's just use what's been set for the default date-time which is 30 days from now.
1614
+				$template_args['TKT_end_date'] = date(
1615
+					$this->_date_time_format,
1616
+					mktime(
1617
+						24,
1618
+						0,
1619
+						0,
1620
+						date('m'),
1621
+						date('d') + 29,
1622
+						date('Y')
1623
+					)
1624
+				);
1625
+			}
1626
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1627
+		}
1628
+		// generate ticket_datetime items
1629
+		if (! $default) {
1630
+			$datetime_row = 1;
1631
+			foreach ($all_datetimes as $datetime) {
1632
+				$template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1633
+					$datetime_row,
1634
+					$ticket_row,
1635
+					$datetime,
1636
+					$ticket,
1637
+					$ticket_datetimes,
1638
+					$default
1639
+				);
1640
+				$datetime_row++;
1641
+			}
1642
+		}
1643
+		$price_row = 1;
1644
+		foreach ($prices as $price) {
1645
+			if (! $price instanceof EE_Price) {
1646
+				continue;
1647
+			}
1648
+			if ($price->is_base_price()) {
1649
+				$price_row++;
1650
+				continue;
1651
+			}
1652
+			$show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1653
+			$show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1654
+			$template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1655
+				$ticket_row,
1656
+				$price_row,
1657
+				$price,
1658
+				$default,
1659
+				$ticket,
1660
+				$show_trash,
1661
+				$show_create
1662
+			);
1663
+			$price_row++;
1664
+		}
1665
+		// filter $template_args
1666
+		$template_args = apply_filters(
1667
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1668
+			$template_args,
1669
+			$ticket_row,
1670
+			$ticket,
1671
+			$ticket_datetimes,
1672
+			$all_datetimes,
1673
+			$default,
1674
+			$all_tickets,
1675
+			$this->_is_creating_event
1676
+		);
1677
+		return EEH_Template::display_template(
1678
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1679
+			$template_args,
1680
+			true
1681
+		);
1682
+	}
1683 1683
 
1684 1684
 
1685
-    /**
1686
-     * @param int            $ticket_row
1687
-     * @param EE_Ticket|null $ticket
1688
-     * @return string
1689
-     * @throws DomainException
1690
-     * @throws EE_Error
1691
-     */
1692
-    protected function _get_tax_rows($ticket_row, $ticket)
1693
-    {
1694
-        $tax_rows = '';
1695
-        /** @var EE_Price[] $taxes */
1696
-        $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1697
-        foreach ($taxes as $tax) {
1698
-            $tax_added = $this->_get_tax_added($tax, $ticket);
1699
-            $template_args = array(
1700
-                'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1701
-                    ? ''
1702
-                    : ' style="display:none;"',
1703
-                'tax_id'            => $tax->ID(),
1704
-                'tkt_row'           => $ticket_row,
1705
-                'tax_label'         => $tax->get('PRC_name'),
1706
-                'tax_added'         => $tax_added,
1707
-                'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1708
-                'tax_amount'        => $tax->get('PRC_amount'),
1709
-            );
1710
-            $template_args = apply_filters(
1711
-                'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1712
-                $template_args,
1713
-                $ticket_row,
1714
-                $ticket,
1715
-                $this->_is_creating_event
1716
-            );
1717
-            $tax_rows .= EEH_Template::display_template(
1718
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1719
-                $template_args,
1720
-                true
1721
-            );
1722
-        }
1723
-        return $tax_rows;
1724
-    }
1685
+	/**
1686
+	 * @param int            $ticket_row
1687
+	 * @param EE_Ticket|null $ticket
1688
+	 * @return string
1689
+	 * @throws DomainException
1690
+	 * @throws EE_Error
1691
+	 */
1692
+	protected function _get_tax_rows($ticket_row, $ticket)
1693
+	{
1694
+		$tax_rows = '';
1695
+		/** @var EE_Price[] $taxes */
1696
+		$taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1697
+		foreach ($taxes as $tax) {
1698
+			$tax_added = $this->_get_tax_added($tax, $ticket);
1699
+			$template_args = array(
1700
+				'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1701
+					? ''
1702
+					: ' style="display:none;"',
1703
+				'tax_id'            => $tax->ID(),
1704
+				'tkt_row'           => $ticket_row,
1705
+				'tax_label'         => $tax->get('PRC_name'),
1706
+				'tax_added'         => $tax_added,
1707
+				'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1708
+				'tax_amount'        => $tax->get('PRC_amount'),
1709
+			);
1710
+			$template_args = apply_filters(
1711
+				'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1712
+				$template_args,
1713
+				$ticket_row,
1714
+				$ticket,
1715
+				$this->_is_creating_event
1716
+			);
1717
+			$tax_rows .= EEH_Template::display_template(
1718
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1719
+				$template_args,
1720
+				true
1721
+			);
1722
+		}
1723
+		return $tax_rows;
1724
+	}
1725 1725
 
1726 1726
 
1727
-    /**
1728
-     * @param EE_Price       $tax
1729
-     * @param EE_Ticket|null $ticket
1730
-     * @return float|int
1731
-     * @throws EE_Error
1732
-     */
1733
-    protected function _get_tax_added(EE_Price $tax, $ticket)
1734
-    {
1735
-        $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1736
-        return $subtotal * $tax->get('PRC_amount') / 100;
1737
-    }
1727
+	/**
1728
+	 * @param EE_Price       $tax
1729
+	 * @param EE_Ticket|null $ticket
1730
+	 * @return float|int
1731
+	 * @throws EE_Error
1732
+	 */
1733
+	protected function _get_tax_added(EE_Price $tax, $ticket)
1734
+	{
1735
+		$subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1736
+		return $subtotal * $tax->get('PRC_amount') / 100;
1737
+	}
1738 1738
 
1739 1739
 
1740
-    /**
1741
-     * @param int            $ticket_row
1742
-     * @param int            $price_row
1743
-     * @param EE_Price|null  $price
1744
-     * @param bool           $default
1745
-     * @param EE_Ticket|null $ticket
1746
-     * @param bool           $show_trash
1747
-     * @param bool           $show_create
1748
-     * @return mixed
1749
-     * @throws InvalidArgumentException
1750
-     * @throws InvalidInterfaceException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws DomainException
1753
-     * @throws EE_Error
1754
-     * @throws ReflectionException
1755
-     */
1756
-    protected function _get_ticket_price_row(
1757
-        $ticket_row,
1758
-        $price_row,
1759
-        $price,
1760
-        $default,
1761
-        $ticket,
1762
-        $show_trash = true,
1763
-        $show_create = true
1764
-    ) {
1765
-        $send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1766
-        $template_args = array(
1767
-            'tkt_row'               => $default && empty($ticket)
1768
-                ? 'TICKETNUM'
1769
-                : $ticket_row,
1770
-            'PRC_order'             => $default && empty($price)
1771
-                ? 'PRICENUM'
1772
-                : $price_row,
1773
-            'edit_prices_name'      => $default && empty($price)
1774
-                ? 'PRICENAMEATTR'
1775
-                : 'edit_prices',
1776
-            'price_type_selector'   => $default && empty($price)
1777
-                ? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1778
-                : $this->_get_price_type_selector(
1779
-                    $ticket_row,
1780
-                    $price_row,
1781
-                    $price,
1782
-                    $default,
1783
-                    $send_disabled
1784
-                ),
1785
-            'PRC_ID'                => $default && empty($price)
1786
-                ? 0
1787
-                : $price->ID(),
1788
-            'PRC_is_default'        => $default && empty($price)
1789
-                ? 0
1790
-                : $price->get('PRC_is_default'),
1791
-            'PRC_name'              => $default && empty($price)
1792
-                ? ''
1793
-                : $price->get('PRC_name'),
1794
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1795
-            'show_plus_or_minus'    => $default && empty($price)
1796
-                ? ''
1797
-                : ' style="display:none;"',
1798
-            'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1799
-                ? ' style="display:none;"'
1800
-                : '',
1801
-            'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1802
-                ? ' style="display:none;"'
1803
-                : '',
1804
-            'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1805
-                ? ' style="display:none"'
1806
-                : '',
1807
-            'PRC_amount'            => $default && empty($price)
1808
-                ? 0
1809
-                : $price->get_pretty('PRC_amount', 'localized_float'),
1810
-            'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1811
-                ? ' style="display:none;"'
1812
-                : '',
1813
-            'show_trash_icon'       => $show_trash
1814
-                ? ''
1815
-                : ' style="display:none;"',
1816
-            'show_create_button'    => $show_create
1817
-                ? ''
1818
-                : ' style="display:none;"',
1819
-            'PRC_desc'              => $default && empty($price)
1820
-                ? ''
1821
-                : $price->get('PRC_desc'),
1822
-            'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1823
-        );
1824
-        $template_args = apply_filters(
1825
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1826
-            $template_args,
1827
-            $ticket_row,
1828
-            $price_row,
1829
-            $price,
1830
-            $default,
1831
-            $ticket,
1832
-            $show_trash,
1833
-            $show_create,
1834
-            $this->_is_creating_event
1835
-        );
1836
-        return EEH_Template::display_template(
1837
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1838
-            $template_args,
1839
-            true
1840
-        );
1841
-    }
1740
+	/**
1741
+	 * @param int            $ticket_row
1742
+	 * @param int            $price_row
1743
+	 * @param EE_Price|null  $price
1744
+	 * @param bool           $default
1745
+	 * @param EE_Ticket|null $ticket
1746
+	 * @param bool           $show_trash
1747
+	 * @param bool           $show_create
1748
+	 * @return mixed
1749
+	 * @throws InvalidArgumentException
1750
+	 * @throws InvalidInterfaceException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws DomainException
1753
+	 * @throws EE_Error
1754
+	 * @throws ReflectionException
1755
+	 */
1756
+	protected function _get_ticket_price_row(
1757
+		$ticket_row,
1758
+		$price_row,
1759
+		$price,
1760
+		$default,
1761
+		$ticket,
1762
+		$show_trash = true,
1763
+		$show_create = true
1764
+	) {
1765
+		$send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1766
+		$template_args = array(
1767
+			'tkt_row'               => $default && empty($ticket)
1768
+				? 'TICKETNUM'
1769
+				: $ticket_row,
1770
+			'PRC_order'             => $default && empty($price)
1771
+				? 'PRICENUM'
1772
+				: $price_row,
1773
+			'edit_prices_name'      => $default && empty($price)
1774
+				? 'PRICENAMEATTR'
1775
+				: 'edit_prices',
1776
+			'price_type_selector'   => $default && empty($price)
1777
+				? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1778
+				: $this->_get_price_type_selector(
1779
+					$ticket_row,
1780
+					$price_row,
1781
+					$price,
1782
+					$default,
1783
+					$send_disabled
1784
+				),
1785
+			'PRC_ID'                => $default && empty($price)
1786
+				? 0
1787
+				: $price->ID(),
1788
+			'PRC_is_default'        => $default && empty($price)
1789
+				? 0
1790
+				: $price->get('PRC_is_default'),
1791
+			'PRC_name'              => $default && empty($price)
1792
+				? ''
1793
+				: $price->get('PRC_name'),
1794
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1795
+			'show_plus_or_minus'    => $default && empty($price)
1796
+				? ''
1797
+				: ' style="display:none;"',
1798
+			'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1799
+				? ' style="display:none;"'
1800
+				: '',
1801
+			'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1802
+				? ' style="display:none;"'
1803
+				: '',
1804
+			'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1805
+				? ' style="display:none"'
1806
+				: '',
1807
+			'PRC_amount'            => $default && empty($price)
1808
+				? 0
1809
+				: $price->get_pretty('PRC_amount', 'localized_float'),
1810
+			'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1811
+				? ' style="display:none;"'
1812
+				: '',
1813
+			'show_trash_icon'       => $show_trash
1814
+				? ''
1815
+				: ' style="display:none;"',
1816
+			'show_create_button'    => $show_create
1817
+				? ''
1818
+				: ' style="display:none;"',
1819
+			'PRC_desc'              => $default && empty($price)
1820
+				? ''
1821
+				: $price->get('PRC_desc'),
1822
+			'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1823
+		);
1824
+		$template_args = apply_filters(
1825
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1826
+			$template_args,
1827
+			$ticket_row,
1828
+			$price_row,
1829
+			$price,
1830
+			$default,
1831
+			$ticket,
1832
+			$show_trash,
1833
+			$show_create,
1834
+			$this->_is_creating_event
1835
+		);
1836
+		return EEH_Template::display_template(
1837
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1838
+			$template_args,
1839
+			true
1840
+		);
1841
+	}
1842 1842
 
1843 1843
 
1844
-    /**
1845
-     * @param int      $ticket_row
1846
-     * @param int      $price_row
1847
-     * @param EE_Price $price
1848
-     * @param bool     $default
1849
-     * @param bool     $disabled
1850
-     * @return mixed
1851
-     * @throws ReflectionException
1852
-     * @throws InvalidArgumentException
1853
-     * @throws InvalidInterfaceException
1854
-     * @throws InvalidDataTypeException
1855
-     * @throws DomainException
1856
-     * @throws EE_Error
1857
-     */
1858
-    protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1859
-    {
1860
-        if ($price->is_base_price()) {
1861
-            return $this->_get_base_price_template(
1862
-                $ticket_row,
1863
-                $price_row,
1864
-                $price,
1865
-                $default
1866
-            );
1867
-        }
1868
-        return $this->_get_price_modifier_template(
1869
-            $ticket_row,
1870
-            $price_row,
1871
-            $price,
1872
-            $default,
1873
-            $disabled
1874
-        );
1875
-    }
1844
+	/**
1845
+	 * @param int      $ticket_row
1846
+	 * @param int      $price_row
1847
+	 * @param EE_Price $price
1848
+	 * @param bool     $default
1849
+	 * @param bool     $disabled
1850
+	 * @return mixed
1851
+	 * @throws ReflectionException
1852
+	 * @throws InvalidArgumentException
1853
+	 * @throws InvalidInterfaceException
1854
+	 * @throws InvalidDataTypeException
1855
+	 * @throws DomainException
1856
+	 * @throws EE_Error
1857
+	 */
1858
+	protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1859
+	{
1860
+		if ($price->is_base_price()) {
1861
+			return $this->_get_base_price_template(
1862
+				$ticket_row,
1863
+				$price_row,
1864
+				$price,
1865
+				$default
1866
+			);
1867
+		}
1868
+		return $this->_get_price_modifier_template(
1869
+			$ticket_row,
1870
+			$price_row,
1871
+			$price,
1872
+			$default,
1873
+			$disabled
1874
+		);
1875
+	}
1876 1876
 
1877 1877
 
1878
-    /**
1879
-     * @param int      $ticket_row
1880
-     * @param int      $price_row
1881
-     * @param EE_Price $price
1882
-     * @param bool     $default
1883
-     * @return mixed
1884
-     * @throws DomainException
1885
-     * @throws EE_Error
1886
-     */
1887
-    protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1888
-    {
1889
-        $template_args = array(
1890
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1891
-            'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1892
-            'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1893
-            'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1894
-            'price_selected_operator'   => '+',
1895
-            'price_selected_is_percent' => 0,
1896
-        );
1897
-        $template_args = apply_filters(
1898
-            'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1899
-            $template_args,
1900
-            $ticket_row,
1901
-            $price_row,
1902
-            $price,
1903
-            $default,
1904
-            $this->_is_creating_event
1905
-        );
1906
-        return EEH_Template::display_template(
1907
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1908
-            $template_args,
1909
-            true
1910
-        );
1911
-    }
1878
+	/**
1879
+	 * @param int      $ticket_row
1880
+	 * @param int      $price_row
1881
+	 * @param EE_Price $price
1882
+	 * @param bool     $default
1883
+	 * @return mixed
1884
+	 * @throws DomainException
1885
+	 * @throws EE_Error
1886
+	 */
1887
+	protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1888
+	{
1889
+		$template_args = array(
1890
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1891
+			'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1892
+			'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1893
+			'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1894
+			'price_selected_operator'   => '+',
1895
+			'price_selected_is_percent' => 0,
1896
+		);
1897
+		$template_args = apply_filters(
1898
+			'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1899
+			$template_args,
1900
+			$ticket_row,
1901
+			$price_row,
1902
+			$price,
1903
+			$default,
1904
+			$this->_is_creating_event
1905
+		);
1906
+		return EEH_Template::display_template(
1907
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1908
+			$template_args,
1909
+			true
1910
+		);
1911
+	}
1912 1912
 
1913 1913
 
1914
-    /**
1915
-     * @param int      $ticket_row
1916
-     * @param int      $price_row
1917
-     * @param EE_Price $price
1918
-     * @param bool     $default
1919
-     * @param bool     $disabled
1920
-     * @return mixed
1921
-     * @throws ReflectionException
1922
-     * @throws InvalidArgumentException
1923
-     * @throws InvalidInterfaceException
1924
-     * @throws InvalidDataTypeException
1925
-     * @throws DomainException
1926
-     * @throws EE_Error
1927
-     */
1928
-    protected function _get_price_modifier_template(
1929
-        $ticket_row,
1930
-        $price_row,
1931
-        $price,
1932
-        $default,
1933
-        $disabled = false
1934
-    ) {
1935
-        $select_name = $default && ! $price instanceof EE_Price
1936
-            ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1937
-            : 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]';
1938
-        /** @var EEM_Price_Type $price_type_model */
1939
-        $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1940
-        $price_types = $price_type_model->get_all(array(
1941
-            array(
1942
-                'OR' => array(
1943
-                    'PBT_ID'  => '2',
1944
-                    'PBT_ID*' => '3',
1945
-                ),
1946
-            ),
1947
-        ));
1948
-        $all_price_types = $default && ! $price instanceof EE_Price
1949
-            ? array(esc_html__('Select Modifier', 'event_espresso'))
1950
-            : array();
1951
-        $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1952
-        $price_option_spans = '';
1953
-        // setup price types for selector
1954
-        foreach ($price_types as $price_type) {
1955
-            if (! $price_type instanceof EE_Price_Type) {
1956
-                continue;
1957
-            }
1958
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1959
-            // while we're in the loop let's setup the option spans used by js
1960
-            $span_args = array(
1961
-                'PRT_ID'         => $price_type->ID(),
1962
-                'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1963
-                'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1964
-            );
1965
-            $price_option_spans .= EEH_Template::display_template(
1966
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1967
-                $span_args,
1968
-                true
1969
-            );
1970
-        }
1971
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1972
-            : $select_name;
1973
-        $select_input = new EE_Select_Input(
1974
-            $all_price_types,
1975
-            array(
1976
-                'default'               => $selected_price_type_id,
1977
-                'html_name'             => $select_name,
1978
-                'html_class'            => 'edit-price-PRT_ID',
1979
-                'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1980
-            )
1981
-        );
1982
-        $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1983
-        $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1984
-        $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1985
-        $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1986
-        $template_args = array(
1987
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1988
-            'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1989
-            'price_modifier_selector'   => $select_input->get_html_for_input(),
1990
-            'main_name'                 => $select_name,
1991
-            'selected_price_type_id'    => $selected_price_type_id,
1992
-            'price_option_spans'        => $price_option_spans,
1993
-            'price_selected_operator'   => $price_selected_operator,
1994
-            'price_selected_is_percent' => $price_selected_is_percent,
1995
-            'disabled'                  => $disabled,
1996
-        );
1997
-        $template_args = apply_filters(
1998
-            'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
1999
-            $template_args,
2000
-            $ticket_row,
2001
-            $price_row,
2002
-            $price,
2003
-            $default,
2004
-            $disabled,
2005
-            $this->_is_creating_event
2006
-        );
2007
-        return EEH_Template::display_template(
2008
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2009
-            $template_args,
2010
-            true
2011
-        );
2012
-    }
1914
+	/**
1915
+	 * @param int      $ticket_row
1916
+	 * @param int      $price_row
1917
+	 * @param EE_Price $price
1918
+	 * @param bool     $default
1919
+	 * @param bool     $disabled
1920
+	 * @return mixed
1921
+	 * @throws ReflectionException
1922
+	 * @throws InvalidArgumentException
1923
+	 * @throws InvalidInterfaceException
1924
+	 * @throws InvalidDataTypeException
1925
+	 * @throws DomainException
1926
+	 * @throws EE_Error
1927
+	 */
1928
+	protected function _get_price_modifier_template(
1929
+		$ticket_row,
1930
+		$price_row,
1931
+		$price,
1932
+		$default,
1933
+		$disabled = false
1934
+	) {
1935
+		$select_name = $default && ! $price instanceof EE_Price
1936
+			? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1937
+			: 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]';
1938
+		/** @var EEM_Price_Type $price_type_model */
1939
+		$price_type_model = EE_Registry::instance()->load_model('Price_Type');
1940
+		$price_types = $price_type_model->get_all(array(
1941
+			array(
1942
+				'OR' => array(
1943
+					'PBT_ID'  => '2',
1944
+					'PBT_ID*' => '3',
1945
+				),
1946
+			),
1947
+		));
1948
+		$all_price_types = $default && ! $price instanceof EE_Price
1949
+			? array(esc_html__('Select Modifier', 'event_espresso'))
1950
+			: array();
1951
+		$selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1952
+		$price_option_spans = '';
1953
+		// setup price types for selector
1954
+		foreach ($price_types as $price_type) {
1955
+			if (! $price_type instanceof EE_Price_Type) {
1956
+				continue;
1957
+			}
1958
+			$all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1959
+			// while we're in the loop let's setup the option spans used by js
1960
+			$span_args = array(
1961
+				'PRT_ID'         => $price_type->ID(),
1962
+				'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1963
+				'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1964
+			);
1965
+			$price_option_spans .= EEH_Template::display_template(
1966
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1967
+				$span_args,
1968
+				true
1969
+			);
1970
+		}
1971
+		$select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1972
+			: $select_name;
1973
+		$select_input = new EE_Select_Input(
1974
+			$all_price_types,
1975
+			array(
1976
+				'default'               => $selected_price_type_id,
1977
+				'html_name'             => $select_name,
1978
+				'html_class'            => 'edit-price-PRT_ID',
1979
+				'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1980
+			)
1981
+		);
1982
+		$price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1983
+		$price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1984
+		$price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1985
+		$price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1986
+		$template_args = array(
1987
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1988
+			'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1989
+			'price_modifier_selector'   => $select_input->get_html_for_input(),
1990
+			'main_name'                 => $select_name,
1991
+			'selected_price_type_id'    => $selected_price_type_id,
1992
+			'price_option_spans'        => $price_option_spans,
1993
+			'price_selected_operator'   => $price_selected_operator,
1994
+			'price_selected_is_percent' => $price_selected_is_percent,
1995
+			'disabled'                  => $disabled,
1996
+		);
1997
+		$template_args = apply_filters(
1998
+			'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
1999
+			$template_args,
2000
+			$ticket_row,
2001
+			$price_row,
2002
+			$price,
2003
+			$default,
2004
+			$disabled,
2005
+			$this->_is_creating_event
2006
+		);
2007
+		return EEH_Template::display_template(
2008
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2009
+			$template_args,
2010
+			true
2011
+		);
2012
+	}
2013 2013
 
2014 2014
 
2015
-    /**
2016
-     * @param int              $datetime_row
2017
-     * @param int              $ticket_row
2018
-     * @param EE_Datetime|null $datetime
2019
-     * @param EE_Ticket|null   $ticket
2020
-     * @param array            $ticket_datetimes
2021
-     * @param bool             $default
2022
-     * @return mixed
2023
-     * @throws DomainException
2024
-     * @throws EE_Error
2025
-     */
2026
-    protected function _get_ticket_datetime_list_item(
2027
-        $datetime_row,
2028
-        $ticket_row,
2029
-        $datetime,
2030
-        $ticket,
2031
-        $ticket_datetimes = array(),
2032
-        $default
2033
-    ) {
2034
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2035
-            ? $ticket_datetimes[ $ticket->ID() ]
2036
-            : array();
2037
-        $template_args = array(
2038
-            'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2039
-                ? 'DTTNUM'
2040
-                : $datetime_row,
2041
-            'tkt_row'                  => $default
2042
-                ? 'TICKETNUM'
2043
-                : $ticket_row,
2044
-            'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2045
-                ? ' ticket-selected'
2046
-                : '',
2047
-            'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2048
-                ? ' checked'
2049
-                : '',
2050
-            'DTT_name'                 => $default && empty($datetime)
2051
-                ? 'DTTNAME'
2052
-                : $datetime->get_dtt_display_name(true),
2053
-            'tkt_status_class'         => '',
2054
-        );
2055
-        $template_args = apply_filters(
2056
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2057
-            $template_args,
2058
-            $datetime_row,
2059
-            $ticket_row,
2060
-            $datetime,
2061
-            $ticket,
2062
-            $ticket_datetimes,
2063
-            $default,
2064
-            $this->_is_creating_event
2065
-        );
2066
-        return EEH_Template::display_template(
2067
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2068
-            $template_args,
2069
-            true
2070
-        );
2071
-    }
2015
+	/**
2016
+	 * @param int              $datetime_row
2017
+	 * @param int              $ticket_row
2018
+	 * @param EE_Datetime|null $datetime
2019
+	 * @param EE_Ticket|null   $ticket
2020
+	 * @param array            $ticket_datetimes
2021
+	 * @param bool             $default
2022
+	 * @return mixed
2023
+	 * @throws DomainException
2024
+	 * @throws EE_Error
2025
+	 */
2026
+	protected function _get_ticket_datetime_list_item(
2027
+		$datetime_row,
2028
+		$ticket_row,
2029
+		$datetime,
2030
+		$ticket,
2031
+		$ticket_datetimes = array(),
2032
+		$default
2033
+	) {
2034
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2035
+			? $ticket_datetimes[ $ticket->ID() ]
2036
+			: array();
2037
+		$template_args = array(
2038
+			'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2039
+				? 'DTTNUM'
2040
+				: $datetime_row,
2041
+			'tkt_row'                  => $default
2042
+				? 'TICKETNUM'
2043
+				: $ticket_row,
2044
+			'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2045
+				? ' ticket-selected'
2046
+				: '',
2047
+			'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2048
+				? ' checked'
2049
+				: '',
2050
+			'DTT_name'                 => $default && empty($datetime)
2051
+				? 'DTTNAME'
2052
+				: $datetime->get_dtt_display_name(true),
2053
+			'tkt_status_class'         => '',
2054
+		);
2055
+		$template_args = apply_filters(
2056
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2057
+			$template_args,
2058
+			$datetime_row,
2059
+			$ticket_row,
2060
+			$datetime,
2061
+			$ticket,
2062
+			$ticket_datetimes,
2063
+			$default,
2064
+			$this->_is_creating_event
2065
+		);
2066
+		return EEH_Template::display_template(
2067
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2068
+			$template_args,
2069
+			true
2070
+		);
2071
+	}
2072 2072
 
2073 2073
 
2074
-    /**
2075
-     * @param array $all_datetimes
2076
-     * @param array $all_tickets
2077
-     * @return mixed
2078
-     * @throws ReflectionException
2079
-     * @throws InvalidArgumentException
2080
-     * @throws InvalidInterfaceException
2081
-     * @throws InvalidDataTypeException
2082
-     * @throws DomainException
2083
-     * @throws EE_Error
2084
-     */
2085
-    protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2086
-    {
2087
-        $template_args = array(
2088
-            'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2089
-                'DTTNUM',
2090
-                null,
2091
-                true,
2092
-                $all_datetimes
2093
-            ),
2094
-            'default_ticket_row'                       => $this->_get_ticket_row(
2095
-                'TICKETNUM',
2096
-                null,
2097
-                array(),
2098
-                array(),
2099
-                true
2100
-            ),
2101
-            'default_price_row'                        => $this->_get_ticket_price_row(
2102
-                'TICKETNUM',
2103
-                'PRICENUM',
2104
-                null,
2105
-                true,
2106
-                null
2107
-            ),
2108
-            'default_price_rows'                       => '',
2109
-            'default_base_price_amount'                => 0,
2110
-            'default_base_price_name'                  => '',
2111
-            'default_base_price_description'           => '',
2112
-            'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2113
-                'TICKETNUM',
2114
-                'PRICENUM',
2115
-                null,
2116
-                true
2117
-            ),
2118
-            'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2119
-                'DTTNUM',
2120
-                null,
2121
-                array(),
2122
-                array(),
2123
-                true
2124
-            ),
2125
-            'existing_available_datetime_tickets_list' => '',
2126
-            'existing_available_ticket_datetimes_list' => '',
2127
-            'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2128
-                'DTTNUM',
2129
-                'TICKETNUM',
2130
-                null,
2131
-                null,
2132
-                array(),
2133
-                true
2134
-            ),
2135
-            'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2136
-                'DTTNUM',
2137
-                'TICKETNUM',
2138
-                null,
2139
-                null,
2140
-                array(),
2141
-                true
2142
-            ),
2143
-        );
2144
-        $ticket_row = 1;
2145
-        foreach ($all_tickets as $ticket) {
2146
-            $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2147
-                'DTTNUM',
2148
-                $ticket_row,
2149
-                null,
2150
-                $ticket,
2151
-                array(),
2152
-                true
2153
-            );
2154
-            $ticket_row++;
2155
-        }
2156
-        $datetime_row = 1;
2157
-        foreach ($all_datetimes as $datetime) {
2158
-            $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2159
-                $datetime_row,
2160
-                'TICKETNUM',
2161
-                $datetime,
2162
-                null,
2163
-                array(),
2164
-                true
2165
-            );
2166
-            $datetime_row++;
2167
-        }
2168
-        /** @var EEM_Price $price_model */
2169
-        $price_model = EE_Registry::instance()->load_model('Price');
2170
-        $default_prices = $price_model->get_all_default_prices();
2171
-        $price_row = 1;
2172
-        foreach ($default_prices as $price) {
2173
-            if (! $price instanceof EE_Price) {
2174
-                continue;
2175
-            }
2176
-            if ($price->is_base_price()) {
2177
-                $template_args['default_base_price_amount'] = $price->get_pretty(
2178
-                    'PRC_amount',
2179
-                    'localized_float'
2180
-                );
2181
-                $template_args['default_base_price_name'] = $price->get('PRC_name');
2182
-                $template_args['default_base_price_description'] = $price->get('PRC_desc');
2183
-                $price_row++;
2184
-                continue;
2185
-            }
2186
-            $show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2187
-                             || count($default_prices) === 1);
2188
-            $show_create = ! (count($default_prices) > 1
2189
-                              && count($default_prices)
2190
-                                 !== $price_row);
2191
-            $template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2192
-                'TICKETNUM',
2193
-                $price_row,
2194
-                $price,
2195
-                true,
2196
-                null,
2197
-                $show_trash,
2198
-                $show_create
2199
-            );
2200
-            $price_row++;
2201
-        }
2202
-        $template_args = apply_filters(
2203
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2204
-            $template_args,
2205
-            $all_datetimes,
2206
-            $all_tickets,
2207
-            $this->_is_creating_event
2208
-        );
2209
-        return EEH_Template::display_template(
2210
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2211
-            $template_args,
2212
-            true
2213
-        );
2214
-    }
2074
+	/**
2075
+	 * @param array $all_datetimes
2076
+	 * @param array $all_tickets
2077
+	 * @return mixed
2078
+	 * @throws ReflectionException
2079
+	 * @throws InvalidArgumentException
2080
+	 * @throws InvalidInterfaceException
2081
+	 * @throws InvalidDataTypeException
2082
+	 * @throws DomainException
2083
+	 * @throws EE_Error
2084
+	 */
2085
+	protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2086
+	{
2087
+		$template_args = array(
2088
+			'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2089
+				'DTTNUM',
2090
+				null,
2091
+				true,
2092
+				$all_datetimes
2093
+			),
2094
+			'default_ticket_row'                       => $this->_get_ticket_row(
2095
+				'TICKETNUM',
2096
+				null,
2097
+				array(),
2098
+				array(),
2099
+				true
2100
+			),
2101
+			'default_price_row'                        => $this->_get_ticket_price_row(
2102
+				'TICKETNUM',
2103
+				'PRICENUM',
2104
+				null,
2105
+				true,
2106
+				null
2107
+			),
2108
+			'default_price_rows'                       => '',
2109
+			'default_base_price_amount'                => 0,
2110
+			'default_base_price_name'                  => '',
2111
+			'default_base_price_description'           => '',
2112
+			'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2113
+				'TICKETNUM',
2114
+				'PRICENUM',
2115
+				null,
2116
+				true
2117
+			),
2118
+			'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2119
+				'DTTNUM',
2120
+				null,
2121
+				array(),
2122
+				array(),
2123
+				true
2124
+			),
2125
+			'existing_available_datetime_tickets_list' => '',
2126
+			'existing_available_ticket_datetimes_list' => '',
2127
+			'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2128
+				'DTTNUM',
2129
+				'TICKETNUM',
2130
+				null,
2131
+				null,
2132
+				array(),
2133
+				true
2134
+			),
2135
+			'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2136
+				'DTTNUM',
2137
+				'TICKETNUM',
2138
+				null,
2139
+				null,
2140
+				array(),
2141
+				true
2142
+			),
2143
+		);
2144
+		$ticket_row = 1;
2145
+		foreach ($all_tickets as $ticket) {
2146
+			$template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2147
+				'DTTNUM',
2148
+				$ticket_row,
2149
+				null,
2150
+				$ticket,
2151
+				array(),
2152
+				true
2153
+			);
2154
+			$ticket_row++;
2155
+		}
2156
+		$datetime_row = 1;
2157
+		foreach ($all_datetimes as $datetime) {
2158
+			$template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2159
+				$datetime_row,
2160
+				'TICKETNUM',
2161
+				$datetime,
2162
+				null,
2163
+				array(),
2164
+				true
2165
+			);
2166
+			$datetime_row++;
2167
+		}
2168
+		/** @var EEM_Price $price_model */
2169
+		$price_model = EE_Registry::instance()->load_model('Price');
2170
+		$default_prices = $price_model->get_all_default_prices();
2171
+		$price_row = 1;
2172
+		foreach ($default_prices as $price) {
2173
+			if (! $price instanceof EE_Price) {
2174
+				continue;
2175
+			}
2176
+			if ($price->is_base_price()) {
2177
+				$template_args['default_base_price_amount'] = $price->get_pretty(
2178
+					'PRC_amount',
2179
+					'localized_float'
2180
+				);
2181
+				$template_args['default_base_price_name'] = $price->get('PRC_name');
2182
+				$template_args['default_base_price_description'] = $price->get('PRC_desc');
2183
+				$price_row++;
2184
+				continue;
2185
+			}
2186
+			$show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2187
+							 || count($default_prices) === 1);
2188
+			$show_create = ! (count($default_prices) > 1
2189
+							  && count($default_prices)
2190
+								 !== $price_row);
2191
+			$template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2192
+				'TICKETNUM',
2193
+				$price_row,
2194
+				$price,
2195
+				true,
2196
+				null,
2197
+				$show_trash,
2198
+				$show_create
2199
+			);
2200
+			$price_row++;
2201
+		}
2202
+		$template_args = apply_filters(
2203
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2204
+			$template_args,
2205
+			$all_datetimes,
2206
+			$all_tickets,
2207
+			$this->_is_creating_event
2208
+		);
2209
+		return EEH_Template::display_template(
2210
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2211
+			$template_args,
2212
+			true
2213
+		);
2214
+	}
2215 2215
 }
Please login to merge, or discard this patch.
admin/extend/events/templates/event_registration_options.template.php 1 patch
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -19,12 +19,12 @@  discard block
 block discarded – undo
19 19
 
20 20
 <?php
21 21
 $settings_array                = [
22
-    'max_registrants'                 => '<p>
22
+	'max_registrants'                 => '<p>
23 23
         <label for="max-registrants">
24 24
         ' . esc_html__(
25
-        'Maximum number of tickets allowed per order for this event: ',
26
-        'event_espresso'
27
-    ) . '
25
+		'Maximum number of tickets allowed per order for this event: ',
26
+		'event_espresso'
27
+	) . '
28 28
         </label>
29 29
         <input class="ee-numeric"
30 30
                 type="text" 
@@ -34,31 +34,31 @@  discard block
 block discarded – undo
34 34
                 size="4" 
35 35
                 />
36 36
         </p>',
37
-    'additional_registration_options' => $additional_registration_options,
38
-    'display_ticket_selector'         => '<p>
37
+	'additional_registration_options' => $additional_registration_options,
38
+	'display_ticket_selector'         => '<p>
39 39
             <label>' . esc_html__('Display Ticket Selector', 'event_espresso') . '</label>'
40
-            . $display_ticket_selector // already escaped
41
-            . '</p>',
42
-    'alternative_registration_page'   => '<p>
40
+			. $display_ticket_selector // already escaped
41
+			. '</p>',
42
+	'alternative_registration_page'   => '<p>
43 43
             <label>' . esc_html__('Alternative Registration Page', 'event_espresso') . '</label>
44 44
             <input name="externalURL" size="20" type="text" value="' . esc_url_raw($_event->external_url()) . '"> 
45 45
             </p>',
46
-    'event_phone_number'              => '<p>
46
+	'event_phone_number'              => '<p>
47 47
             <label>' . esc_html__('Event Phone Number', 'event_espresso') . '</label>
48 48
             <input name="event_phone" size="20" type="text" value="' . esc_attr($_event->phone()) . '">
49 49
             </p>',
50
-    'default_registration_status'     => '<p>
50
+	'default_registration_status'     => '<p>
51 51
             <label>
52 52
             ' . esc_html__('Default Registration Status', 'event_espresso')
53
-             . EEH_Template::get_help_tab_link('event_editor_event_registration_options_help_tab')
54
-            . '</label>'
55
-             . $EVT_default_registration_status // already escaped
56
-             . '</p>',
53
+			 . EEH_Template::get_help_tab_link('event_editor_event_registration_options_help_tab')
54
+			. '</label>'
55
+			 . $EVT_default_registration_status // already escaped
56
+			 . '</p>',
57 57
 ];
58 58
 // filter
59 59
 $settings_array = apply_filters('FHEE__caffeinated_event_registration_options__template__settings', $settings_array);
60 60
 
61 61
 // echo
62 62
 foreach ($settings_array as $item) {
63
-    echo wp_kses($item, AllowedTags::getWithFormTags());
63
+	echo wp_kses($item, AllowedTags::getWithFormTags());
64 64
 }
Please login to merge, or discard this patch.
admin/extend/registrations/EE_Event_Registrations_List_Table.class.php 2 patches
Indentation   +663 added lines, -663 removed lines patch added patch discarded remove patch
@@ -15,711 +15,711 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Event_Registrations_List_Table extends EE_Admin_List_Table
17 17
 {
18
-    /**
19
-     * @var RequestInterface
20
-     */
21
-    protected $request;
22
-
23
-    /**
24
-     * @var Extend_Registrations_Admin_Page
25
-     */
26
-    protected $_admin_page;
27
-
28
-    /**
29
-     * The event ID if one is specified in the request
30
-     *
31
-     * @var int
32
-     */
33
-    protected $event_id = 0;
34
-
35
-    /**
36
-     * This property will hold the related Datetimes on an event IF the event id is included in the request.
37
-     *
38
-     * @var DatetimesForEventCheckIn
39
-     */
40
-    protected $datetimes_for_event = [];
41
-
42
-    /**
43
-     * The DTT_ID if the current view has a specified datetime.
44
-     *
45
-     * @var int
46
-     */
47
-    protected $datetime_id = 0;
48
-
49
-    /**
50
-     * @var EE_Datetime
51
-     */
52
-    protected $datetime;
53
-
54
-    /**
55
-     * @var EE_Event
56
-     */
57
-    protected $event;
58
-
59
-    /**
60
-     * @var DatetimesForEventCheckIn
61
-     */
62
-    protected $datetimes_for_current_row;
63
-
64
-    /**
65
-     * @var bool
66
-     */
67
-    protected $hide_expired;
68
-
69
-    /**
70
-     * @var bool
71
-     */
72
-    protected $hide_upcoming;
73
-
74
-
75
-    /**
76
-     * EE_Event_Registrations_List_Table constructor.
77
-     *
78
-     * @param Registrations_Admin_Page $admin_page
79
-     * @throws EE_Error
80
-     * @throws ReflectionException
81
-     */
82
-    public function __construct($admin_page)
83
-    {
84
-        $this->request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
85
-        $this->resolveRequestVars();
86
-        parent::__construct($admin_page);
87
-    }
88
-
89
-
90
-    /**
91
-     * @throws EE_Error
92
-     * @throws ReflectionException
93
-     * @since $VID:$
94
-     */
95
-    private function resolveRequestVars()
96
-    {
97
-        $this->event_id = $this->request->getRequestParam('event_id', 0, 'int');
98
-        $this->datetimes_for_event = DatetimesForEventCheckIn::fromEventID($this->event_id);
99
-        // if we're filtering for a specific event and it only has one datetime, then grab its ID
100
-        $datetime          = $this->datetimes_for_event->getOneActiveDatetimeForEvent();
101
-        $this->datetime_id = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
102
-        // else check the request, but use the above as the default (and hope they match if BOTH exist, LOLZ)
103
-        $this->datetime_id = $this->request->getRequestParam(
104
-            'DTT_ID',
105
-            $this->datetime_id,
106
-            'int'
107
-        );
108
-    }
109
-
110
-
111
-    /**
112
-     * @throws EE_Error
113
-     */
114
-    protected function _setup_data()
115
-    {
116
-        $this->_data = $this->_view !== 'trash'
117
-            ? $this->_admin_page->get_event_attendees($this->_per_page)
118
-            : $this->_admin_page->get_event_attendees($this->_per_page, false, true);
119
-
120
-        $this->_all_data_count = $this->_view !== 'trash'
121
-            ? $this->_admin_page->get_event_attendees($this->_per_page, true)
122
-            : $this->_admin_page->get_event_attendees($this->_per_page, true, true);
123
-    }
124
-
125
-
126
-    protected function _set_properties()
127
-    {
128
-        $this->_wp_list_args = [
129
-            'singular' => esc_html__('registrant', 'event_espresso'),
130
-            'plural'   => esc_html__('registrants', 'event_espresso'),
131
-            'ajax'     => true,
132
-            'screen'   => $this->_admin_page->get_current_screen()->id,
133
-        ];
134
-
135
-        $this->_columns      = [
136
-            'cb' => '<input type="checkbox" />', // Render a checkbox instead of text
137
-            '_REG_att_checked_in' => esc_html__('Check In', 'event_espresso'),
138
-            'ATT_name'            => esc_html__('Registrant', 'event_espresso'),
139
-            'ATT_email'           => esc_html__('Email Address', 'event_espresso'),
140
-            'Event'               => esc_html__('Event', 'event_espresso'),
141
-            'PRC_name'            => esc_html__('TKT Option', 'event_espresso'),
142
-            '_REG_final_price'    => esc_html__('Price', 'event_espresso'),
143
-            'TXN_paid'            => esc_html__('Paid', 'event_espresso'),
144
-            'TXN_total'           => esc_html__('Total', 'event_espresso'),
145
-        ];
146
-        $this->_primary_column = '_REG_att_checked_in';
147
-
148
-        // Add/remove columns when an event has been selected
149
-        if ($this->event_id) {
150
-            // Render a checkbox column
151
-            $this->_columns['cb'] = '<input type="checkbox" />';
152
-            $this->_has_checkbox_column = true;
153
-            // Remove the 'Event' column
154
-            unset($this->_columns['Event']);
155
-            $this->setBottomButtons();
156
-        }
157
-
158
-        $this->_sortable_columns = [
159
-            /**
160
-             * Allows users to change the default sort if they wish.
161
-             * Returning a falsey on this filter will result in the default sort to be by firstname rather than last name.
162
-             *
163
-             * Note: usual naming conventions for filters aren't followed here so that just one filter can be used to
164
-             * change the sorts on any list table involving registration contacts.  If you want to only change the filter
165
-             * for a specific list table you can use the provided reference to this object instance.
166
-             */
167
-            'ATT_name' => [
168
-                'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
169
-                true,
170
-                $this,
171
-            ]
172
-                ? ['ATT_lname' => true]
173
-                : ['ATT_fname' => true],
174
-            'Event'    => ['Event.EVT_name' => false],
175
-        ];
176
-
177
-        $this->_hidden_columns = [];
178
-    }
179
-
180
-
181
-    private function setBottomButtons()
182
-    {
183
-        if (
184
-            ! EE_Registry::instance()->CAP->current_user_can(
185
-                'ee_read_registrations',
186
-                'espresso_registrations_registrations_reports',
187
-                $this->event_id
188
-            )
189
-        ) {
190
-            return;
191
-        }
192
-
193
-        $return_url = $this->getReturnUrl();
194
-        $this->_bottom_buttons = [
195
-            'report' => [
196
-                'route'         => 'registrations_report',
197
-                'extra_request' =>
198
-                    [
199
-                        'EVT_ID'     => $this->event_id,
200
-                        'return_url' => $return_url,
201
-                    ],
202
-            ],
203
-        ];
204
-
205
-        $request_params = $this->request->requestParams();
206
-
207
-        $this->_bottom_buttons['report_filtered'] = [
208
-            'route'         => 'registrations_checkin_report',
209
-            'extra_request' => [
210
-                'use_filters' => true,
211
-                'filters'     => array_merge(
212
-                    [
213
-                        'EVT_ID' => $this->event_id,
214
-                    ],
215
-                    array_diff_key(
216
-                        $request_params,
217
-                        array_flip(
218
-                            [
219
-                                'page',
220
-                                'action',
221
-                                'default_nonce',
222
-                            ]
223
-                        )
224
-                    )
225
-                ),
226
-                'return_url'  => $return_url,
227
-            ],
228
-        ];
229
-    }
230
-
231
-
232
-    /**
233
-     * @param EE_Registration $item
234
-     * @return string
235
-     */
236
-    protected function _get_row_class($item): string
237
-    {
238
-        $class = parent::_get_row_class($item);
239
-        if ($this->_has_checkbox_column) {
240
-            $class .= ' has-checkbox-column';
241
-        }
242
-        return $class;
243
-    }
244
-
245
-
246
-    /**
247
-     * @return array
248
-     * @throws EE_Error
249
-     * @throws ReflectionException
250
-     */
251
-    protected function _get_table_filters(): array
252
-    {
253
-        $filters = [];
254
-        $this->hide_expired = $this->request->getRequestParam('hide_expired', false, 'bool');
255
-        $this->hide_upcoming = $this->request->getRequestParam('hide_upcoming', false, 'bool');
256
-        $hide_expired_checked = $this->hide_expired ? 'checked' : '';
257
-        $hide_upcoming_checked = $this->hide_upcoming ? 'checked' : '';
258
-        // get datetimes for ALL active events (note possible capability restrictions)
259
-        $events   = $this->datetimes_for_event->getAllActiveDatetimesForAllEvents();
260
-        $event_options[] = [
261
-            'id'   => 0,
262
-            'text' => esc_html__(' - select an event - ', 'event_espresso'),
263
-        ];
264
-        /** @var EE_Event $event */
265
-        foreach ($events as $event) {
266
-            // any registrations for this event?
267
-            if (! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
268
-                continue;
269
-            }
270
-            $expired_class = $event->is_expired() ? 'ee-expired-event' : '';
271
-            $upcoming_class  = $event->is_upcoming() ? ' ee-upcoming-event' : '';
272
-            $event_options[] = [
273
-                'id'    => $event->ID(),
274
-                'text'  => apply_filters(
275
-                    'FHEE__EE_Event_Registrations___get_table_filters__event_name',
276
-                    $event->name(),
277
-                    $event
278
-                ),
279
-                'class' => $expired_class . $upcoming_class,
280
-            ];
281
-            if ($event->ID() === $this->event_id) {
282
-                $this->hide_expired = $expired_class === '';
283
-                $hide_expired_checked  = $expired_class === '' ? $hide_expired_checked : '';
284
-                $this->hide_upcoming = $upcoming_class === '';
285
-                $hide_upcoming_checked = $upcoming_class === '' ? $hide_upcoming_checked : '';
286
-            }
287
-        }
288
-
289
-        $select_class = $this->hide_expired ? 'ee-hide-expired-events' : '';
290
-        $select_class .= $this->hide_upcoming ? ' ee-hide-upcoming-events' : '';
291
-
292
-        $filters[] = '
18
+	/**
19
+	 * @var RequestInterface
20
+	 */
21
+	protected $request;
22
+
23
+	/**
24
+	 * @var Extend_Registrations_Admin_Page
25
+	 */
26
+	protected $_admin_page;
27
+
28
+	/**
29
+	 * The event ID if one is specified in the request
30
+	 *
31
+	 * @var int
32
+	 */
33
+	protected $event_id = 0;
34
+
35
+	/**
36
+	 * This property will hold the related Datetimes on an event IF the event id is included in the request.
37
+	 *
38
+	 * @var DatetimesForEventCheckIn
39
+	 */
40
+	protected $datetimes_for_event = [];
41
+
42
+	/**
43
+	 * The DTT_ID if the current view has a specified datetime.
44
+	 *
45
+	 * @var int
46
+	 */
47
+	protected $datetime_id = 0;
48
+
49
+	/**
50
+	 * @var EE_Datetime
51
+	 */
52
+	protected $datetime;
53
+
54
+	/**
55
+	 * @var EE_Event
56
+	 */
57
+	protected $event;
58
+
59
+	/**
60
+	 * @var DatetimesForEventCheckIn
61
+	 */
62
+	protected $datetimes_for_current_row;
63
+
64
+	/**
65
+	 * @var bool
66
+	 */
67
+	protected $hide_expired;
68
+
69
+	/**
70
+	 * @var bool
71
+	 */
72
+	protected $hide_upcoming;
73
+
74
+
75
+	/**
76
+	 * EE_Event_Registrations_List_Table constructor.
77
+	 *
78
+	 * @param Registrations_Admin_Page $admin_page
79
+	 * @throws EE_Error
80
+	 * @throws ReflectionException
81
+	 */
82
+	public function __construct($admin_page)
83
+	{
84
+		$this->request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
85
+		$this->resolveRequestVars();
86
+		parent::__construct($admin_page);
87
+	}
88
+
89
+
90
+	/**
91
+	 * @throws EE_Error
92
+	 * @throws ReflectionException
93
+	 * @since $VID:$
94
+	 */
95
+	private function resolveRequestVars()
96
+	{
97
+		$this->event_id = $this->request->getRequestParam('event_id', 0, 'int');
98
+		$this->datetimes_for_event = DatetimesForEventCheckIn::fromEventID($this->event_id);
99
+		// if we're filtering for a specific event and it only has one datetime, then grab its ID
100
+		$datetime          = $this->datetimes_for_event->getOneActiveDatetimeForEvent();
101
+		$this->datetime_id = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
102
+		// else check the request, but use the above as the default (and hope they match if BOTH exist, LOLZ)
103
+		$this->datetime_id = $this->request->getRequestParam(
104
+			'DTT_ID',
105
+			$this->datetime_id,
106
+			'int'
107
+		);
108
+	}
109
+
110
+
111
+	/**
112
+	 * @throws EE_Error
113
+	 */
114
+	protected function _setup_data()
115
+	{
116
+		$this->_data = $this->_view !== 'trash'
117
+			? $this->_admin_page->get_event_attendees($this->_per_page)
118
+			: $this->_admin_page->get_event_attendees($this->_per_page, false, true);
119
+
120
+		$this->_all_data_count = $this->_view !== 'trash'
121
+			? $this->_admin_page->get_event_attendees($this->_per_page, true)
122
+			: $this->_admin_page->get_event_attendees($this->_per_page, true, true);
123
+	}
124
+
125
+
126
+	protected function _set_properties()
127
+	{
128
+		$this->_wp_list_args = [
129
+			'singular' => esc_html__('registrant', 'event_espresso'),
130
+			'plural'   => esc_html__('registrants', 'event_espresso'),
131
+			'ajax'     => true,
132
+			'screen'   => $this->_admin_page->get_current_screen()->id,
133
+		];
134
+
135
+		$this->_columns      = [
136
+			'cb' => '<input type="checkbox" />', // Render a checkbox instead of text
137
+			'_REG_att_checked_in' => esc_html__('Check In', 'event_espresso'),
138
+			'ATT_name'            => esc_html__('Registrant', 'event_espresso'),
139
+			'ATT_email'           => esc_html__('Email Address', 'event_espresso'),
140
+			'Event'               => esc_html__('Event', 'event_espresso'),
141
+			'PRC_name'            => esc_html__('TKT Option', 'event_espresso'),
142
+			'_REG_final_price'    => esc_html__('Price', 'event_espresso'),
143
+			'TXN_paid'            => esc_html__('Paid', 'event_espresso'),
144
+			'TXN_total'           => esc_html__('Total', 'event_espresso'),
145
+		];
146
+		$this->_primary_column = '_REG_att_checked_in';
147
+
148
+		// Add/remove columns when an event has been selected
149
+		if ($this->event_id) {
150
+			// Render a checkbox column
151
+			$this->_columns['cb'] = '<input type="checkbox" />';
152
+			$this->_has_checkbox_column = true;
153
+			// Remove the 'Event' column
154
+			unset($this->_columns['Event']);
155
+			$this->setBottomButtons();
156
+		}
157
+
158
+		$this->_sortable_columns = [
159
+			/**
160
+			 * Allows users to change the default sort if they wish.
161
+			 * Returning a falsey on this filter will result in the default sort to be by firstname rather than last name.
162
+			 *
163
+			 * Note: usual naming conventions for filters aren't followed here so that just one filter can be used to
164
+			 * change the sorts on any list table involving registration contacts.  If you want to only change the filter
165
+			 * for a specific list table you can use the provided reference to this object instance.
166
+			 */
167
+			'ATT_name' => [
168
+				'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
169
+				true,
170
+				$this,
171
+			]
172
+				? ['ATT_lname' => true]
173
+				: ['ATT_fname' => true],
174
+			'Event'    => ['Event.EVT_name' => false],
175
+		];
176
+
177
+		$this->_hidden_columns = [];
178
+	}
179
+
180
+
181
+	private function setBottomButtons()
182
+	{
183
+		if (
184
+			! EE_Registry::instance()->CAP->current_user_can(
185
+				'ee_read_registrations',
186
+				'espresso_registrations_registrations_reports',
187
+				$this->event_id
188
+			)
189
+		) {
190
+			return;
191
+		}
192
+
193
+		$return_url = $this->getReturnUrl();
194
+		$this->_bottom_buttons = [
195
+			'report' => [
196
+				'route'         => 'registrations_report',
197
+				'extra_request' =>
198
+					[
199
+						'EVT_ID'     => $this->event_id,
200
+						'return_url' => $return_url,
201
+					],
202
+			],
203
+		];
204
+
205
+		$request_params = $this->request->requestParams();
206
+
207
+		$this->_bottom_buttons['report_filtered'] = [
208
+			'route'         => 'registrations_checkin_report',
209
+			'extra_request' => [
210
+				'use_filters' => true,
211
+				'filters'     => array_merge(
212
+					[
213
+						'EVT_ID' => $this->event_id,
214
+					],
215
+					array_diff_key(
216
+						$request_params,
217
+						array_flip(
218
+							[
219
+								'page',
220
+								'action',
221
+								'default_nonce',
222
+							]
223
+						)
224
+					)
225
+				),
226
+				'return_url'  => $return_url,
227
+			],
228
+		];
229
+	}
230
+
231
+
232
+	/**
233
+	 * @param EE_Registration $item
234
+	 * @return string
235
+	 */
236
+	protected function _get_row_class($item): string
237
+	{
238
+		$class = parent::_get_row_class($item);
239
+		if ($this->_has_checkbox_column) {
240
+			$class .= ' has-checkbox-column';
241
+		}
242
+		return $class;
243
+	}
244
+
245
+
246
+	/**
247
+	 * @return array
248
+	 * @throws EE_Error
249
+	 * @throws ReflectionException
250
+	 */
251
+	protected function _get_table_filters(): array
252
+	{
253
+		$filters = [];
254
+		$this->hide_expired = $this->request->getRequestParam('hide_expired', false, 'bool');
255
+		$this->hide_upcoming = $this->request->getRequestParam('hide_upcoming', false, 'bool');
256
+		$hide_expired_checked = $this->hide_expired ? 'checked' : '';
257
+		$hide_upcoming_checked = $this->hide_upcoming ? 'checked' : '';
258
+		// get datetimes for ALL active events (note possible capability restrictions)
259
+		$events   = $this->datetimes_for_event->getAllActiveDatetimesForAllEvents();
260
+		$event_options[] = [
261
+			'id'   => 0,
262
+			'text' => esc_html__(' - select an event - ', 'event_espresso'),
263
+		];
264
+		/** @var EE_Event $event */
265
+		foreach ($events as $event) {
266
+			// any registrations for this event?
267
+			if (! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
268
+				continue;
269
+			}
270
+			$expired_class = $event->is_expired() ? 'ee-expired-event' : '';
271
+			$upcoming_class  = $event->is_upcoming() ? ' ee-upcoming-event' : '';
272
+			$event_options[] = [
273
+				'id'    => $event->ID(),
274
+				'text'  => apply_filters(
275
+					'FHEE__EE_Event_Registrations___get_table_filters__event_name',
276
+					$event->name(),
277
+					$event
278
+				),
279
+				'class' => $expired_class . $upcoming_class,
280
+			];
281
+			if ($event->ID() === $this->event_id) {
282
+				$this->hide_expired = $expired_class === '';
283
+				$hide_expired_checked  = $expired_class === '' ? $hide_expired_checked : '';
284
+				$this->hide_upcoming = $upcoming_class === '';
285
+				$hide_upcoming_checked = $upcoming_class === '' ? $hide_upcoming_checked : '';
286
+			}
287
+		}
288
+
289
+		$select_class = $this->hide_expired ? 'ee-hide-expired-events' : '';
290
+		$select_class .= $this->hide_upcoming ? ' ee-hide-upcoming-events' : '';
291
+
292
+		$filters[] = '
293 293
         <div class="ee-event-filter__wrapper">
294 294
             <label class="ee-event-filter-main-label">' . esc_html__('Check-in Status for', 'event_espresso') . '</label>
295 295
             <div class="ee-event-filter">
296 296
                 <span class="ee-event-selector">
297 297
                     <label for="event_id">' . esc_html__('Event', 'event_espresso') . '</label>
298 298
                     ' . EEH_Form_Fields::select_input(
299
-                            'event_id',
300
-                            $event_options,
301
-                            $this->event_id,
302
-                            '',
303
-                            $select_class
304
-                        ) . '
299
+							'event_id',
300
+							$event_options,
301
+							$this->event_id,
302
+							'',
303
+							$select_class
304
+						) . '
305 305
                 </span>';
306
-        // DTT datetimes filter
307
-        $datetimes_for_event = $this->datetimes_for_event->getAllActiveDatetimesForEvent($hide_upcoming_checked === 'checked');
308
-        if (count($datetimes_for_event) > 1) {
309
-            $datetimes[0] = esc_html__(' - select a datetime - ', 'event_espresso');
310
-            foreach ($datetimes_for_event as $datetime) {
311
-                $datetime_string              = $datetime->name();
312
-                $datetime_string              = ! empty($datetime_string) ? ' (' . $datetime_string . ')' : '';
313
-                $datetime_string              =
314
-                    $datetime->start_date_and_time() . ' - ' . $datetime->end_date_and_time() . $datetime_string;
315
-                $datetimes[ $datetime->ID() ] = $datetime_string;
316
-            }
317
-            $filters[] = '
306
+		// DTT datetimes filter
307
+		$datetimes_for_event = $this->datetimes_for_event->getAllActiveDatetimesForEvent($hide_upcoming_checked === 'checked');
308
+		if (count($datetimes_for_event) > 1) {
309
+			$datetimes[0] = esc_html__(' - select a datetime - ', 'event_espresso');
310
+			foreach ($datetimes_for_event as $datetime) {
311
+				$datetime_string              = $datetime->name();
312
+				$datetime_string              = ! empty($datetime_string) ? ' (' . $datetime_string . ')' : '';
313
+				$datetime_string              =
314
+					$datetime->start_date_and_time() . ' - ' . $datetime->end_date_and_time() . $datetime_string;
315
+				$datetimes[ $datetime->ID() ] = $datetime_string;
316
+			}
317
+			$filters[] = '
318 318
                 <span class="ee-datetime-selector">
319 319
                     <label for="DTT_ID">' . esc_html__('Datetime', 'event_espresso') . '</label>
320 320
                     ' . EEH_Form_Fields::select_input(
321
-                        'DTT_ID',
322
-                        $datetimes,
323
-                        $this->datetime_id
324
-                    ) . '
321
+						'DTT_ID',
322
+						$datetimes,
323
+						$this->datetime_id
324
+					) . '
325 325
                 </span>';
326
-        }
327
-        $filters[] = '
326
+		}
327
+		$filters[] = '
328 328
                 <span class="ee-hide-upcoming-check">
329 329
                     <label for="js-ee-hide-upcoming-events">
330 330
                         <input type="checkbox" id="js-ee-hide-upcoming-events" name="hide_upcoming" '
331
-                         . $hide_upcoming_checked
332
-                         . '>
331
+						 . $hide_upcoming_checked
332
+						 . '>
333 333
                         '
334
-                         . esc_html__('Hide Upcoming Events', 'event_espresso')
335
-                         . '
334
+						 . esc_html__('Hide Upcoming Events', 'event_espresso')
335
+						 . '
336 336
                     </label>
337 337
                     <span class="ee-help-btn dashicons dashicons-editor-help ee-aria-tooltip" aria-label="'
338
-                         . esc_html__(
339
-                             'Will not display events with start dates in the future (ie: have not yet begun)',
340
-                             'event_espresso'
341
-                         )
342
-                         . '"></span>
338
+						 . esc_html__(
339
+							 'Will not display events with start dates in the future (ie: have not yet begun)',
340
+							 'event_espresso'
341
+						 )
342
+						 . '"></span>
343 343
                 </span>
344 344
                 <span class="ee-hide-expired-check">
345 345
                     <label for="js-ee-hide-expired-events">
346 346
                         <input type="checkbox" id="js-ee-hide-expired-events" name="hide_expired" '
347
-                         . $hide_expired_checked
348
-                         . '>
347
+						 . $hide_expired_checked
348
+						 . '>
349 349
                         '
350
-                         . esc_html__('Hide Expired Events', 'event_espresso')
351
-                         . '
350
+						 . esc_html__('Hide Expired Events', 'event_espresso')
351
+						 . '
352 352
                     </label>
353 353
                     <span class="ee-help-btn dashicons dashicons-editor-help ee-aria-tooltip" aria-label="'
354
-                         . esc_html__(
355
-                             'Will not display events with end dates in the past (ie: have already finished)',
356
-                             'event_espresso'
357
-                         )
358
-                         . '"></span>
354
+						 . esc_html__(
355
+							 'Will not display events with end dates in the past (ie: have already finished)',
356
+							 'event_espresso'
357
+						 )
358
+						 . '"></span>
359 359
                 </span>
360 360
             </div>
361 361
         </div>';
362
-        return $filters;
363
-    }
364
-
365
-
366
-    /**
367
-     * @throws EE_Error
368
-     * @throws ReflectionException
369
-     */
370
-    protected function _add_view_counts()
371
-    {
372
-        $this->_views['all']['count'] = $this->_get_total_event_attendees();
373
-    }
374
-
375
-
376
-    /**
377
-     * @return int
378
-     * @throws EE_Error
379
-     * @throws ReflectionException
380
-     */
381
-    protected function _get_total_event_attendees(): int
382
-    {
383
-        $query_params      = [];
384
-        if ($this->event_id) {
385
-            $query_params[0]['EVT_ID'] = $this->event_id;
386
-        }
387
-        // if DTT is included we only show for that datetime.  Otherwise we're showing for all datetimes (the event).
388
-        if ($this->datetime_id) {
389
-            $query_params[0]['Ticket.Datetime.DTT_ID'] = $this->datetime_id;
390
-        }
391
-        $status_ids_array          = apply_filters(
392
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
393
-            [EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved]
394
-        );
395
-        $query_params[0]['STS_ID'] = ['IN', $status_ids_array];
396
-        return EEM_Registration::instance()->count($query_params);
397
-    }
398
-
399
-
400
-    /**
401
-     * @param EE_Registration $item
402
-     * @return string
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    public function column_cb($item): string
407
-    {
408
-        return sprintf('<input type="checkbox" name="checkbox[%1$s]" value="%1$s" />', $item->ID());
409
-    }
410
-
411
-
412
-    /**
413
-     * column_REG_att_checked_in
414
-     *
415
-     * @param EE_Registration $registration
416
-     * @return string
417
-     * @throws EE_Error
418
-     * @throws InvalidArgumentException
419
-     * @throws InvalidDataTypeException
420
-     * @throws InvalidInterfaceException
421
-     * @throws ReflectionException
422
-     */
423
-    public function column__REG_att_checked_in(EE_Registration $registration): string
424
-    {
425
-        $reg_date_id = 0;
426
-        $reg_datetimes = $registration->ticket()->datetimes();
427
-        if (count($reg_datetimes) === 1) {
428
-            $reg_datetime = reset($reg_datetimes);
429
-            $reg_date_id = $reg_datetime instanceof EE_Datetime ? $reg_datetime->ID() : 0;
430
-        }
431
-        // we need a local variable for the datetime for each row
432
-        // (so that we don't pollute state for the entire table)
433
-        // so let's try to get it from the registration's event
434
-        $this->datetimes_for_current_row = DatetimesForEventCheckIn::fromRegistration($registration);
435
-        $datetime = $this->datetimes_for_current_row->getOneActiveDatetimeForEvent(
436
-            $reg_date_id ?: $this->datetime_id,
437
-            $this->hide_expired
438
-        );
439
-
440
-        $DTD_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
441
-
442
-        $checkin_status_dashicon = CheckinStatusDashicon::fromRegistrationAndDatetimeId(
443
-            $registration,
444
-            $DTD_ID
445
-        );
446
-
447
-        $aria_label = $checkin_status_dashicon->ariaLabel();
448
-        $dashicon_class = $checkin_status_dashicon->cssClasses();
449
-        $attributes = ' onClick="return false"';
450
-        $button_class = 'button button--secondary button--icon-only ee-aria-tooltip ee-aria-tooltip--big-box';
451
-
452
-        if (
453
-            $DTD_ID
454
-            && EE_Registry::instance()->CAP->current_user_can(
455
-                'ee_edit_checkin',
456
-                'espresso_registrations_toggle_checkin_status',
457
-                $registration->ID()
458
-            )
459
-        ) {
460
-            // overwrite the disabled attribute with data attributes for performing checkin
461
-            $attributes = 'data-_regid="' . $registration->ID() . '"';
462
-            $attributes .= ' data-dttid="' . $DTD_ID . '"';
463
-            $attributes .= ' data-nonce="' . wp_create_nonce('checkin_nonce') . '"';
464
-            $button_class .= ' clickable trigger-checkin';
465
-        }
466
-
467
-        $content = '
362
+		return $filters;
363
+	}
364
+
365
+
366
+	/**
367
+	 * @throws EE_Error
368
+	 * @throws ReflectionException
369
+	 */
370
+	protected function _add_view_counts()
371
+	{
372
+		$this->_views['all']['count'] = $this->_get_total_event_attendees();
373
+	}
374
+
375
+
376
+	/**
377
+	 * @return int
378
+	 * @throws EE_Error
379
+	 * @throws ReflectionException
380
+	 */
381
+	protected function _get_total_event_attendees(): int
382
+	{
383
+		$query_params      = [];
384
+		if ($this->event_id) {
385
+			$query_params[0]['EVT_ID'] = $this->event_id;
386
+		}
387
+		// if DTT is included we only show for that datetime.  Otherwise we're showing for all datetimes (the event).
388
+		if ($this->datetime_id) {
389
+			$query_params[0]['Ticket.Datetime.DTT_ID'] = $this->datetime_id;
390
+		}
391
+		$status_ids_array          = apply_filters(
392
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
393
+			[EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved]
394
+		);
395
+		$query_params[0]['STS_ID'] = ['IN', $status_ids_array];
396
+		return EEM_Registration::instance()->count($query_params);
397
+	}
398
+
399
+
400
+	/**
401
+	 * @param EE_Registration $item
402
+	 * @return string
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	public function column_cb($item): string
407
+	{
408
+		return sprintf('<input type="checkbox" name="checkbox[%1$s]" value="%1$s" />', $item->ID());
409
+	}
410
+
411
+
412
+	/**
413
+	 * column_REG_att_checked_in
414
+	 *
415
+	 * @param EE_Registration $registration
416
+	 * @return string
417
+	 * @throws EE_Error
418
+	 * @throws InvalidArgumentException
419
+	 * @throws InvalidDataTypeException
420
+	 * @throws InvalidInterfaceException
421
+	 * @throws ReflectionException
422
+	 */
423
+	public function column__REG_att_checked_in(EE_Registration $registration): string
424
+	{
425
+		$reg_date_id = 0;
426
+		$reg_datetimes = $registration->ticket()->datetimes();
427
+		if (count($reg_datetimes) === 1) {
428
+			$reg_datetime = reset($reg_datetimes);
429
+			$reg_date_id = $reg_datetime instanceof EE_Datetime ? $reg_datetime->ID() : 0;
430
+		}
431
+		// we need a local variable for the datetime for each row
432
+		// (so that we don't pollute state for the entire table)
433
+		// so let's try to get it from the registration's event
434
+		$this->datetimes_for_current_row = DatetimesForEventCheckIn::fromRegistration($registration);
435
+		$datetime = $this->datetimes_for_current_row->getOneActiveDatetimeForEvent(
436
+			$reg_date_id ?: $this->datetime_id,
437
+			$this->hide_expired
438
+		);
439
+
440
+		$DTD_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
441
+
442
+		$checkin_status_dashicon = CheckinStatusDashicon::fromRegistrationAndDatetimeId(
443
+			$registration,
444
+			$DTD_ID
445
+		);
446
+
447
+		$aria_label = $checkin_status_dashicon->ariaLabel();
448
+		$dashicon_class = $checkin_status_dashicon->cssClasses();
449
+		$attributes = ' onClick="return false"';
450
+		$button_class = 'button button--secondary button--icon-only ee-aria-tooltip ee-aria-tooltip--big-box';
451
+
452
+		if (
453
+			$DTD_ID
454
+			&& EE_Registry::instance()->CAP->current_user_can(
455
+				'ee_edit_checkin',
456
+				'espresso_registrations_toggle_checkin_status',
457
+				$registration->ID()
458
+			)
459
+		) {
460
+			// overwrite the disabled attribute with data attributes for performing checkin
461
+			$attributes = 'data-_regid="' . $registration->ID() . '"';
462
+			$attributes .= ' data-dttid="' . $DTD_ID . '"';
463
+			$attributes .= ' data-nonce="' . wp_create_nonce('checkin_nonce') . '"';
464
+			$button_class .= ' clickable trigger-checkin';
465
+		}
466
+
467
+		$content = '
468 468
         <button aria-label="' . $aria_label . '" class="' . $button_class . '" ' . $attributes . '>   
469 469
             <span class="' . $dashicon_class . '" ></span>
470 470
         </button>
471 471
         <span class="show-on-mobile-view-only">' . $this->column_ATT_name($registration) . '</span>';
472
-        return $this->columnContent('_REG_att_checked_in', $content, 'center');
473
-    }
474
-
475
-
476
-    /**
477
-     * @param EE_Registration $registration
478
-     * @return string
479
-     * @throws EE_Error
480
-     * @throws ReflectionException
481
-     */
482
-    public function column_ATT_name(EE_Registration $registration): string
483
-    {
484
-        $attendee = $registration->attendee();
485
-        if (! $attendee instanceof EE_Attendee) {
486
-            return esc_html__('No contact record for this registration.', 'event_espresso');
487
-        }
488
-        // edit attendee link
489
-        $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
490
-            ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
491
-            REG_ADMIN_URL
492
-        );
493
-        $name_link    = '
472
+		return $this->columnContent('_REG_att_checked_in', $content, 'center');
473
+	}
474
+
475
+
476
+	/**
477
+	 * @param EE_Registration $registration
478
+	 * @return string
479
+	 * @throws EE_Error
480
+	 * @throws ReflectionException
481
+	 */
482
+	public function column_ATT_name(EE_Registration $registration): string
483
+	{
484
+		$attendee = $registration->attendee();
485
+		if (! $attendee instanceof EE_Attendee) {
486
+			return esc_html__('No contact record for this registration.', 'event_espresso');
487
+		}
488
+		// edit attendee link
489
+		$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
490
+			['action' => 'view_registration', '_REG_ID' => $registration->ID()],
491
+			REG_ADMIN_URL
492
+		);
493
+		$name_link    = '
494 494
             <span class="ee-status-dot ee-status-bg--' . esc_attr($registration->status_ID()) . ' ee-aria-tooltip"
495 495
             aria-label="' . EEH_Template::pretty_status($registration->status_ID(), false, 'sentence') . '">
496 496
             </span>';
497
-        $name_link    .= EE_Registry::instance()->CAP->current_user_can(
498
-            'ee_edit_contacts',
499
-            'espresso_registrations_edit_attendee'
500
-        )
501
-            ? '<a class="ee-aria-tooltip" href="' . $edit_lnk_url . '" aria-label="' . esc_attr__(
502
-                'View Registration Details',
503
-                'event_espresso'
504
-            ) . '">'
505
-              . $registration->attendee()->full_name()
506
-              . '</a>'
507
-            : $registration->attendee()->full_name();
508
-        $name_link    .= $registration->count() === 1
509
-            ? '&nbsp;<sup><div class="dashicons dashicons-star-filled gold-icon"></div></sup>	'
510
-            : '';
511
-        // add group details
512
-        $name_link .= '&nbsp;' . sprintf(
513
-            esc_html__('(%s of %s)', 'event_espresso'),
514
-            $registration->count(),
515
-            $registration->group_size()
516
-        );
517
-        // add regcode
518
-        $link      = EE_Admin_Page::add_query_args_and_nonce(
519
-            ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
520
-            REG_ADMIN_URL
521
-        );
522
-        $name_link .= '<br>';
523
-        $name_link .= EE_Registry::instance()->instance()->CAP->current_user_can(
524
-            'ee_read_registration',
525
-            'view_registration',
526
-            $registration->ID()
527
-        )
528
-            ? '<a class="ee-aria-tooltip" href="' . $link . '" aria-label="' . esc_attr__(
529
-                'View Registration Details',
530
-                'event_espresso'
531
-            ) . '">'
532
-              . $registration->reg_code()
533
-              . '</a>'
534
-            : $registration->reg_code();
535
-
536
-        $actions                 = [];
537
-        if (
538
-            $this->datetime_id
539
-            && EE_Registry::instance()->CAP->current_user_can(
540
-                'ee_read_checkins',
541
-                'espresso_registrations_registration_checkins'
542
-            )
543
-        ) {
544
-            $checkin_list_url = EE_Admin_Page::add_query_args_and_nonce(
545
-                ['action' => 'registration_checkins', '_REG_ID' => $registration->ID(), 'DTT_ID' => $this->datetime_id],
546
-                REG_ADMIN_URL
547
-            );
548
-            // get the timestamps for this registration's checkins, related to the selected datetime
549
-            /** @var EE_Checkin[] $checkins */
550
-            $checkins = $registration->get_many_related('Checkin', [['DTT_ID' => $this->datetime_id]]);
551
-            if (! empty($checkins)) {
552
-                // get the last timestamp
553
-                $last_checkin = end($checkins);
554
-                // get timestamp string
555
-                $timestamp_string   = $last_checkin->get_datetime('CHK_timestamp');
556
-                $actions['checkin'] = '
497
+		$name_link    .= EE_Registry::instance()->CAP->current_user_can(
498
+			'ee_edit_contacts',
499
+			'espresso_registrations_edit_attendee'
500
+		)
501
+			? '<a class="ee-aria-tooltip" href="' . $edit_lnk_url . '" aria-label="' . esc_attr__(
502
+				'View Registration Details',
503
+				'event_espresso'
504
+			) . '">'
505
+			  . $registration->attendee()->full_name()
506
+			  . '</a>'
507
+			: $registration->attendee()->full_name();
508
+		$name_link    .= $registration->count() === 1
509
+			? '&nbsp;<sup><div class="dashicons dashicons-star-filled gold-icon"></div></sup>	'
510
+			: '';
511
+		// add group details
512
+		$name_link .= '&nbsp;' . sprintf(
513
+			esc_html__('(%s of %s)', 'event_espresso'),
514
+			$registration->count(),
515
+			$registration->group_size()
516
+		);
517
+		// add regcode
518
+		$link      = EE_Admin_Page::add_query_args_and_nonce(
519
+			['action' => 'view_registration', '_REG_ID' => $registration->ID()],
520
+			REG_ADMIN_URL
521
+		);
522
+		$name_link .= '<br>';
523
+		$name_link .= EE_Registry::instance()->instance()->CAP->current_user_can(
524
+			'ee_read_registration',
525
+			'view_registration',
526
+			$registration->ID()
527
+		)
528
+			? '<a class="ee-aria-tooltip" href="' . $link . '" aria-label="' . esc_attr__(
529
+				'View Registration Details',
530
+				'event_espresso'
531
+			) . '">'
532
+			  . $registration->reg_code()
533
+			  . '</a>'
534
+			: $registration->reg_code();
535
+
536
+		$actions                 = [];
537
+		if (
538
+			$this->datetime_id
539
+			&& EE_Registry::instance()->CAP->current_user_can(
540
+				'ee_read_checkins',
541
+				'espresso_registrations_registration_checkins'
542
+			)
543
+		) {
544
+			$checkin_list_url = EE_Admin_Page::add_query_args_and_nonce(
545
+				['action' => 'registration_checkins', '_REG_ID' => $registration->ID(), 'DTT_ID' => $this->datetime_id],
546
+				REG_ADMIN_URL
547
+			);
548
+			// get the timestamps for this registration's checkins, related to the selected datetime
549
+			/** @var EE_Checkin[] $checkins */
550
+			$checkins = $registration->get_many_related('Checkin', [['DTT_ID' => $this->datetime_id]]);
551
+			if (! empty($checkins)) {
552
+				// get the last timestamp
553
+				$last_checkin = end($checkins);
554
+				// get timestamp string
555
+				$timestamp_string   = $last_checkin->get_datetime('CHK_timestamp');
556
+				$actions['checkin'] = '
557 557
                     <a  class="ee-aria-tooltip" 
558 558
                         href="' . $checkin_list_url . '" 
559 559
                         aria-label="' . esc_attr__(
560
-                            'View this registrant\'s check-ins/checkouts for the datetime',
561
-                            'event_espresso'
562
-                        ) . '"
560
+							'View this registrant\'s check-ins/checkouts for the datetime',
561
+							'event_espresso'
562
+						) . '"
563 563
                     >
564 564
                         ' . $last_checkin->getCheckInText() . ': ' . $timestamp_string . '
565 565
                     </a>';
566
-            }
567
-        }
568
-        $content = (! empty($this->datetime_id) && ! empty($checkins))
569
-            ? sprintf('%1$s %2$s', $name_link, $this->row_actions($actions, true))
570
-            : $name_link;
571
-        return $this->columnContent('ATT_name', $content);
572
-    }
573
-
574
-
575
-    /**
576
-     * @param EE_Registration $registration
577
-     * @return string
578
-     * @throws EE_Error
579
-     * @throws EE_Error
580
-     */
581
-    public function column_ATT_email(EE_Registration $registration): string
582
-    {
583
-        $attendee = $registration->attendee();
584
-        $content = $attendee instanceof EE_Attendee ? $attendee->email() : '';
585
-        return $this->columnContent('ATT_email', $content);
586
-    }
587
-
588
-
589
-    /**
590
-     * @param EE_Registration $registration
591
-     * @return string
592
-     * @throws EE_Error
593
-     * @throws ReflectionException
594
-     */
595
-    public function column_Event(EE_Registration $registration): string
596
-    {
597
-        try {
598
-            $event            = $this->event instanceof EE_Event ? $this->event : $registration->event();
599
-            $checkin_link_url = EE_Admin_Page::add_query_args_and_nonce(
600
-                ['action' => 'event_registrations', 'event_id' => $event->ID()],
601
-                REG_ADMIN_URL
602
-            );
603
-            $content      = EE_Registry::instance()->CAP->current_user_can(
604
-                'ee_read_checkins',
605
-                'espresso_registrations_registration_checkins'
606
-            ) ? '<a class="ee-aria-tooltip" href="' . $checkin_link_url . '" aria-label="'
607
-                . esc_attr__(
608
-                    'View Checkins for this Event',
609
-                    'event_espresso'
610
-                ) . '">' . $event->name() . '</a>' : $event->name();
611
-        } catch (EntityNotFoundException $e) {
612
-            $content = esc_html__('Unknown', 'event_espresso');
613
-        }
614
-        return $this->columnContent('Event', $content);
615
-    }
616
-
617
-
618
-    /**
619
-     * @param EE_Registration $registration
620
-     * @return string
621
-     * @throws EE_Error
622
-     * @throws ReflectionException
623
-     */
624
-    public function column_PRC_name(EE_Registration $registration): string
625
-    {
626
-        $content = $registration->ticket() instanceof EE_Ticket
627
-            ? $registration->ticket()->name()
628
-            : esc_html__(
629
-                "Unknown",
630
-                "event_espresso"
631
-            );
632
-        return $this->columnContent('PRC_name', $content);
633
-    }
634
-
635
-
636
-    /**
637
-     * column_REG_final_price
638
-     *
639
-     * @param EE_Registration $registration
640
-     * @return string
641
-     * @throws EE_Error
642
-     */
643
-    public function column__REG_final_price(EE_Registration $registration): string
644
-    {
645
-        return $this->columnContent('_REG_final_price', $registration->pretty_final_price(), 'end');
646
-    }
647
-
648
-
649
-    /**
650
-     * column_TXN_paid
651
-     *
652
-     * @param EE_Registration $registration
653
-     * @return string
654
-     * @throws EE_Error
655
-     * @throws ReflectionException
656
-     */
657
-    public function column_TXN_paid(EE_Registration $registration): string
658
-    {
659
-        $content = '';
660
-        if ($registration->count() === 1) {
661
-            if ($registration->transaction()->paid() >= $registration->transaction()->total()) {
662
-                return '<div class="dashicons dashicons-yes green-icon"></div>';
663
-            } else {
664
-                $view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
665
-                    ['action' => 'view_transaction', 'TXN_ID' => $registration->transaction_ID()],
666
-                    TXN_ADMIN_URL
667
-                );
668
-                $content = EE_Registry::instance()->CAP->current_user_can(
669
-                    'ee_read_transaction',
670
-                    'espresso_transactions_view_transaction'
671
-                ) ? '
566
+			}
567
+		}
568
+		$content = (! empty($this->datetime_id) && ! empty($checkins))
569
+			? sprintf('%1$s %2$s', $name_link, $this->row_actions($actions, true))
570
+			: $name_link;
571
+		return $this->columnContent('ATT_name', $content);
572
+	}
573
+
574
+
575
+	/**
576
+	 * @param EE_Registration $registration
577
+	 * @return string
578
+	 * @throws EE_Error
579
+	 * @throws EE_Error
580
+	 */
581
+	public function column_ATT_email(EE_Registration $registration): string
582
+	{
583
+		$attendee = $registration->attendee();
584
+		$content = $attendee instanceof EE_Attendee ? $attendee->email() : '';
585
+		return $this->columnContent('ATT_email', $content);
586
+	}
587
+
588
+
589
+	/**
590
+	 * @param EE_Registration $registration
591
+	 * @return string
592
+	 * @throws EE_Error
593
+	 * @throws ReflectionException
594
+	 */
595
+	public function column_Event(EE_Registration $registration): string
596
+	{
597
+		try {
598
+			$event            = $this->event instanceof EE_Event ? $this->event : $registration->event();
599
+			$checkin_link_url = EE_Admin_Page::add_query_args_and_nonce(
600
+				['action' => 'event_registrations', 'event_id' => $event->ID()],
601
+				REG_ADMIN_URL
602
+			);
603
+			$content      = EE_Registry::instance()->CAP->current_user_can(
604
+				'ee_read_checkins',
605
+				'espresso_registrations_registration_checkins'
606
+			) ? '<a class="ee-aria-tooltip" href="' . $checkin_link_url . '" aria-label="'
607
+				. esc_attr__(
608
+					'View Checkins for this Event',
609
+					'event_espresso'
610
+				) . '">' . $event->name() . '</a>' : $event->name();
611
+		} catch (EntityNotFoundException $e) {
612
+			$content = esc_html__('Unknown', 'event_espresso');
613
+		}
614
+		return $this->columnContent('Event', $content);
615
+	}
616
+
617
+
618
+	/**
619
+	 * @param EE_Registration $registration
620
+	 * @return string
621
+	 * @throws EE_Error
622
+	 * @throws ReflectionException
623
+	 */
624
+	public function column_PRC_name(EE_Registration $registration): string
625
+	{
626
+		$content = $registration->ticket() instanceof EE_Ticket
627
+			? $registration->ticket()->name()
628
+			: esc_html__(
629
+				"Unknown",
630
+				"event_espresso"
631
+			);
632
+		return $this->columnContent('PRC_name', $content);
633
+	}
634
+
635
+
636
+	/**
637
+	 * column_REG_final_price
638
+	 *
639
+	 * @param EE_Registration $registration
640
+	 * @return string
641
+	 * @throws EE_Error
642
+	 */
643
+	public function column__REG_final_price(EE_Registration $registration): string
644
+	{
645
+		return $this->columnContent('_REG_final_price', $registration->pretty_final_price(), 'end');
646
+	}
647
+
648
+
649
+	/**
650
+	 * column_TXN_paid
651
+	 *
652
+	 * @param EE_Registration $registration
653
+	 * @return string
654
+	 * @throws EE_Error
655
+	 * @throws ReflectionException
656
+	 */
657
+	public function column_TXN_paid(EE_Registration $registration): string
658
+	{
659
+		$content = '';
660
+		if ($registration->count() === 1) {
661
+			if ($registration->transaction()->paid() >= $registration->transaction()->total()) {
662
+				return '<div class="dashicons dashicons-yes green-icon"></div>';
663
+			} else {
664
+				$view_txn_lnk_url = EE_Admin_Page::add_query_args_and_nonce(
665
+					['action' => 'view_transaction', 'TXN_ID' => $registration->transaction_ID()],
666
+					TXN_ADMIN_URL
667
+				);
668
+				$content = EE_Registry::instance()->CAP->current_user_can(
669
+					'ee_read_transaction',
670
+					'espresso_transactions_view_transaction'
671
+				) ? '
672 672
 				<a class="ee-aria-tooltip ee-status-color--'
673
-                    . $registration->transaction()->status_ID()
674
-                    . '" href="'
675
-                    . $view_txn_lnk_url
676
-                    . '"  aria-label="'
677
-                    . esc_attr__('View Transaction', 'event_espresso')
678
-                    . '">
673
+					. $registration->transaction()->status_ID()
674
+					. '" href="'
675
+					. $view_txn_lnk_url
676
+					. '"  aria-label="'
677
+					. esc_attr__('View Transaction', 'event_espresso')
678
+					. '">
679 679
 						'
680
-                    . $registration->transaction()->pretty_paid()
681
-                    . '
680
+					. $registration->transaction()->pretty_paid()
681
+					. '
682 682
 					</a>
683 683
 				' : $registration->transaction()->pretty_paid();
684
-            }
685
-        }
686
-        return $this->columnContent('TXN_paid', $content, 'end');
687
-    }
688
-
689
-
690
-    /**
691
-     *        column_TXN_total
692
-     *
693
-     * @param EE_Registration $registration
694
-     * @return string
695
-     * @throws EE_Error
696
-     * @throws ReflectionException
697
-     */
698
-    public function column_TXN_total(EE_Registration $registration): string
699
-    {
700
-        $content = '';
701
-        $txn = $registration->transaction();
702
-        $view_txn_url = add_query_arg(['action' => 'view_transaction', 'TXN_ID' => $txn->ID()], TXN_ADMIN_URL);
703
-        if ($registration->get('REG_count') === 1) {
704
-            $line_total_obj = $txn->total_line_item();
705
-            $txn_total      = $line_total_obj instanceof EE_Line_Item
706
-                ? $line_total_obj->get_pretty('LIN_total')
707
-                : esc_html__(
708
-                    'View Transaction',
709
-                    'event_espresso'
710
-                );
711
-            $content = EE_Registry::instance()->CAP->current_user_can(
712
-                'ee_read_transaction',
713
-                'espresso_transactions_view_transaction'
714
-            ) ? '<a class="ee-aria-tooltip" href="'
715
-                . $view_txn_url
716
-                . '" aria-label="'
717
-                . esc_attr__('View Transaction', 'event_espresso')
718
-                . '">'
719
-                . $txn_total
720
-                . '</a>'
721
-                : $txn_total;
722
-        }
723
-        return $this->columnContent('TXN_total', $content, 'end');
724
-    }
684
+			}
685
+		}
686
+		return $this->columnContent('TXN_paid', $content, 'end');
687
+	}
688
+
689
+
690
+	/**
691
+	 *        column_TXN_total
692
+	 *
693
+	 * @param EE_Registration $registration
694
+	 * @return string
695
+	 * @throws EE_Error
696
+	 * @throws ReflectionException
697
+	 */
698
+	public function column_TXN_total(EE_Registration $registration): string
699
+	{
700
+		$content = '';
701
+		$txn = $registration->transaction();
702
+		$view_txn_url = add_query_arg(['action' => 'view_transaction', 'TXN_ID' => $txn->ID()], TXN_ADMIN_URL);
703
+		if ($registration->get('REG_count') === 1) {
704
+			$line_total_obj = $txn->total_line_item();
705
+			$txn_total      = $line_total_obj instanceof EE_Line_Item
706
+				? $line_total_obj->get_pretty('LIN_total')
707
+				: esc_html__(
708
+					'View Transaction',
709
+					'event_espresso'
710
+				);
711
+			$content = EE_Registry::instance()->CAP->current_user_can(
712
+				'ee_read_transaction',
713
+				'espresso_transactions_view_transaction'
714
+			) ? '<a class="ee-aria-tooltip" href="'
715
+				. $view_txn_url
716
+				. '" aria-label="'
717
+				. esc_attr__('View Transaction', 'event_espresso')
718
+				. '">'
719
+				. $txn_total
720
+				. '</a>'
721
+				: $txn_total;
722
+		}
723
+		return $this->columnContent('TXN_total', $content, 'end');
724
+	}
725 725
 }
Please login to merge, or discard this patch.
Spacing   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
             'screen'   => $this->_admin_page->get_current_screen()->id,
133 133
         ];
134 134
 
135
-        $this->_columns      = [
135
+        $this->_columns = [
136 136
             'cb' => '<input type="checkbox" />', // Render a checkbox instead of text
137 137
             '_REG_att_checked_in' => esc_html__('Check In', 'event_espresso'),
138 138
             'ATT_name'            => esc_html__('Registrant', 'event_espresso'),
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
         $hide_expired_checked = $this->hide_expired ? 'checked' : '';
257 257
         $hide_upcoming_checked = $this->hide_upcoming ? 'checked' : '';
258 258
         // get datetimes for ALL active events (note possible capability restrictions)
259
-        $events   = $this->datetimes_for_event->getAllActiveDatetimesForAllEvents();
259
+        $events = $this->datetimes_for_event->getAllActiveDatetimesForAllEvents();
260 260
         $event_options[] = [
261 261
             'id'   => 0,
262 262
             'text' => esc_html__(' - select an event - ', 'event_espresso'),
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
         /** @var EE_Event $event */
265 265
         foreach ($events as $event) {
266 266
             // any registrations for this event?
267
-            if (! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
267
+            if ( ! $event instanceof EE_Event/* || ! $event->get_count_of_all_registrations()*/) {
268 268
                 continue;
269 269
             }
270 270
             $expired_class = $event->is_expired() ? 'ee-expired-event' : '';
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
                     $event->name(),
277 277
                     $event
278 278
                 ),
279
-                'class' => $expired_class . $upcoming_class,
279
+                'class' => $expired_class.$upcoming_class,
280 280
             ];
281 281
             if ($event->ID() === $this->event_id) {
282 282
                 $this->hide_expired = $expired_class === '';
@@ -291,17 +291,17 @@  discard block
 block discarded – undo
291 291
 
292 292
         $filters[] = '
293 293
         <div class="ee-event-filter__wrapper">
294
-            <label class="ee-event-filter-main-label">' . esc_html__('Check-in Status for', 'event_espresso') . '</label>
294
+            <label class="ee-event-filter-main-label">' . esc_html__('Check-in Status for', 'event_espresso').'</label>
295 295
             <div class="ee-event-filter">
296 296
                 <span class="ee-event-selector">
297
-                    <label for="event_id">' . esc_html__('Event', 'event_espresso') . '</label>
297
+                    <label for="event_id">' . esc_html__('Event', 'event_espresso').'</label>
298 298
                     ' . EEH_Form_Fields::select_input(
299 299
                             'event_id',
300 300
                             $event_options,
301 301
                             $this->event_id,
302 302
                             '',
303 303
                             $select_class
304
-                        ) . '
304
+                        ).'
305 305
                 </span>';
306 306
         // DTT datetimes filter
307 307
         $datetimes_for_event = $this->datetimes_for_event->getAllActiveDatetimesForEvent($hide_upcoming_checked === 'checked');
@@ -309,19 +309,19 @@  discard block
 block discarded – undo
309 309
             $datetimes[0] = esc_html__(' - select a datetime - ', 'event_espresso');
310 310
             foreach ($datetimes_for_event as $datetime) {
311 311
                 $datetime_string              = $datetime->name();
312
-                $datetime_string              = ! empty($datetime_string) ? ' (' . $datetime_string . ')' : '';
312
+                $datetime_string              = ! empty($datetime_string) ? ' ('.$datetime_string.')' : '';
313 313
                 $datetime_string              =
314
-                    $datetime->start_date_and_time() . ' - ' . $datetime->end_date_and_time() . $datetime_string;
315
-                $datetimes[ $datetime->ID() ] = $datetime_string;
314
+                    $datetime->start_date_and_time().' - '.$datetime->end_date_and_time().$datetime_string;
315
+                $datetimes[$datetime->ID()] = $datetime_string;
316 316
             }
317 317
             $filters[] = '
318 318
                 <span class="ee-datetime-selector">
319
-                    <label for="DTT_ID">' . esc_html__('Datetime', 'event_espresso') . '</label>
319
+                    <label for="DTT_ID">' . esc_html__('Datetime', 'event_espresso').'</label>
320 320
                     ' . EEH_Form_Fields::select_input(
321 321
                         'DTT_ID',
322 322
                         $datetimes,
323 323
                         $this->datetime_id
324
-                    ) . '
324
+                    ).'
325 325
                 </span>';
326 326
         }
327 327
         $filters[] = '
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
      */
381 381
     protected function _get_total_event_attendees(): int
382 382
     {
383
-        $query_params      = [];
383
+        $query_params = [];
384 384
         if ($this->event_id) {
385 385
             $query_params[0]['EVT_ID'] = $this->event_id;
386 386
         }
@@ -388,7 +388,7 @@  discard block
 block discarded – undo
388 388
         if ($this->datetime_id) {
389 389
             $query_params[0]['Ticket.Datetime.DTT_ID'] = $this->datetime_id;
390 390
         }
391
-        $status_ids_array          = apply_filters(
391
+        $status_ids_array = apply_filters(
392 392
             'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
393 393
             [EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved]
394 394
         );
@@ -458,17 +458,17 @@  discard block
 block discarded – undo
458 458
             )
459 459
         ) {
460 460
             // overwrite the disabled attribute with data attributes for performing checkin
461
-            $attributes = 'data-_regid="' . $registration->ID() . '"';
462
-            $attributes .= ' data-dttid="' . $DTD_ID . '"';
463
-            $attributes .= ' data-nonce="' . wp_create_nonce('checkin_nonce') . '"';
461
+            $attributes = 'data-_regid="'.$registration->ID().'"';
462
+            $attributes .= ' data-dttid="'.$DTD_ID.'"';
463
+            $attributes .= ' data-nonce="'.wp_create_nonce('checkin_nonce').'"';
464 464
             $button_class .= ' clickable trigger-checkin';
465 465
         }
466 466
 
467 467
         $content = '
468
-        <button aria-label="' . $aria_label . '" class="' . $button_class . '" ' . $attributes . '>   
469
-            <span class="' . $dashicon_class . '" ></span>
468
+        <button aria-label="' . $aria_label.'" class="'.$button_class.'" '.$attributes.'>   
469
+            <span class="' . $dashicon_class.'" ></span>
470 470
         </button>
471
-        <span class="show-on-mobile-view-only">' . $this->column_ATT_name($registration) . '</span>';
471
+        <span class="show-on-mobile-view-only">' . $this->column_ATT_name($registration).'</span>';
472 472
         return $this->columnContent('_REG_att_checked_in', $content, 'center');
473 473
     }
474 474
 
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
     public function column_ATT_name(EE_Registration $registration): string
483 483
     {
484 484
         $attendee = $registration->attendee();
485
-        if (! $attendee instanceof EE_Attendee) {
485
+        if ( ! $attendee instanceof EE_Attendee) {
486 486
             return esc_html__('No contact record for this registration.', 'event_espresso');
487 487
         }
488 488
         // edit attendee link
@@ -490,32 +490,32 @@  discard block
 block discarded – undo
490 490
             ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
491 491
             REG_ADMIN_URL
492 492
         );
493
-        $name_link    = '
494
-            <span class="ee-status-dot ee-status-bg--' . esc_attr($registration->status_ID()) . ' ee-aria-tooltip"
495
-            aria-label="' . EEH_Template::pretty_status($registration->status_ID(), false, 'sentence') . '">
493
+        $name_link = '
494
+            <span class="ee-status-dot ee-status-bg--' . esc_attr($registration->status_ID()).' ee-aria-tooltip"
495
+            aria-label="' . EEH_Template::pretty_status($registration->status_ID(), false, 'sentence').'">
496 496
             </span>';
497
-        $name_link    .= EE_Registry::instance()->CAP->current_user_can(
497
+        $name_link .= EE_Registry::instance()->CAP->current_user_can(
498 498
             'ee_edit_contacts',
499 499
             'espresso_registrations_edit_attendee'
500 500
         )
501
-            ? '<a class="ee-aria-tooltip" href="' . $edit_lnk_url . '" aria-label="' . esc_attr__(
501
+            ? '<a class="ee-aria-tooltip" href="'.$edit_lnk_url.'" aria-label="'.esc_attr__(
502 502
                 'View Registration Details',
503 503
                 'event_espresso'
504
-            ) . '">'
504
+            ).'">'
505 505
               . $registration->attendee()->full_name()
506 506
               . '</a>'
507 507
             : $registration->attendee()->full_name();
508
-        $name_link    .= $registration->count() === 1
508
+        $name_link .= $registration->count() === 1
509 509
             ? '&nbsp;<sup><div class="dashicons dashicons-star-filled gold-icon"></div></sup>	'
510 510
             : '';
511 511
         // add group details
512
-        $name_link .= '&nbsp;' . sprintf(
512
+        $name_link .= '&nbsp;'.sprintf(
513 513
             esc_html__('(%s of %s)', 'event_espresso'),
514 514
             $registration->count(),
515 515
             $registration->group_size()
516 516
         );
517 517
         // add regcode
518
-        $link      = EE_Admin_Page::add_query_args_and_nonce(
518
+        $link = EE_Admin_Page::add_query_args_and_nonce(
519 519
             ['action' => 'view_registration', '_REG_ID' => $registration->ID()],
520 520
             REG_ADMIN_URL
521 521
         );
@@ -525,15 +525,15 @@  discard block
 block discarded – undo
525 525
             'view_registration',
526 526
             $registration->ID()
527 527
         )
528
-            ? '<a class="ee-aria-tooltip" href="' . $link . '" aria-label="' . esc_attr__(
528
+            ? '<a class="ee-aria-tooltip" href="'.$link.'" aria-label="'.esc_attr__(
529 529
                 'View Registration Details',
530 530
                 'event_espresso'
531
-            ) . '">'
531
+            ).'">'
532 532
               . $registration->reg_code()
533 533
               . '</a>'
534 534
             : $registration->reg_code();
535 535
 
536
-        $actions                 = [];
536
+        $actions = [];
537 537
         if (
538 538
             $this->datetime_id
539 539
             && EE_Registry::instance()->CAP->current_user_can(
@@ -548,24 +548,24 @@  discard block
 block discarded – undo
548 548
             // get the timestamps for this registration's checkins, related to the selected datetime
549 549
             /** @var EE_Checkin[] $checkins */
550 550
             $checkins = $registration->get_many_related('Checkin', [['DTT_ID' => $this->datetime_id]]);
551
-            if (! empty($checkins)) {
551
+            if ( ! empty($checkins)) {
552 552
                 // get the last timestamp
553 553
                 $last_checkin = end($checkins);
554 554
                 // get timestamp string
555 555
                 $timestamp_string   = $last_checkin->get_datetime('CHK_timestamp');
556 556
                 $actions['checkin'] = '
557 557
                     <a  class="ee-aria-tooltip" 
558
-                        href="' . $checkin_list_url . '" 
558
+                        href="' . $checkin_list_url.'" 
559 559
                         aria-label="' . esc_attr__(
560 560
                             'View this registrant\'s check-ins/checkouts for the datetime',
561 561
                             'event_espresso'
562
-                        ) . '"
562
+                        ).'"
563 563
                     >
564
-                        ' . $last_checkin->getCheckInText() . ': ' . $timestamp_string . '
564
+                        ' . $last_checkin->getCheckInText().': '.$timestamp_string.'
565 565
                     </a>';
566 566
             }
567 567
         }
568
-        $content = (! empty($this->datetime_id) && ! empty($checkins))
568
+        $content = ( ! empty($this->datetime_id) && ! empty($checkins))
569 569
             ? sprintf('%1$s %2$s', $name_link, $this->row_actions($actions, true))
570 570
             : $name_link;
571 571
         return $this->columnContent('ATT_name', $content);
@@ -600,14 +600,14 @@  discard block
 block discarded – undo
600 600
                 ['action' => 'event_registrations', 'event_id' => $event->ID()],
601 601
                 REG_ADMIN_URL
602 602
             );
603
-            $content      = EE_Registry::instance()->CAP->current_user_can(
603
+            $content = EE_Registry::instance()->CAP->current_user_can(
604 604
                 'ee_read_checkins',
605 605
                 'espresso_registrations_registration_checkins'
606
-            ) ? '<a class="ee-aria-tooltip" href="' . $checkin_link_url . '" aria-label="'
606
+            ) ? '<a class="ee-aria-tooltip" href="'.$checkin_link_url.'" aria-label="'
607 607
                 . esc_attr__(
608 608
                     'View Checkins for this Event',
609 609
                     'event_espresso'
610
-                ) . '">' . $event->name() . '</a>' : $event->name();
610
+                ).'">'.$event->name().'</a>' : $event->name();
611 611
         } catch (EntityNotFoundException $e) {
612 612
             $content = esc_html__('Unknown', 'event_espresso');
613 613
         }
Please login to merge, or discard this patch.