Completed
Branch BUG/datetime-ticket-sold-count... (5d38da)
by
unknown
03:30 queued 49s
created
core/db_classes/EE_Datetime.class.php 1 patch
Indentation   +1524 added lines, -1524 removed lines patch added patch discarded remove patch
@@ -13,1532 +13,1532 @@
 block discarded – undo
13 13
 class EE_Datetime extends EE_Soft_Delete_Base_Class
14 14
 {
15 15
 
16
-    /**
17
-     * constant used by get_active_status, indicates datetime has no more available spaces
18
-     */
19
-    const sold_out = 'DTS';
20
-
21
-    /**
22
-     * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
23
-     */
24
-    const active = 'DTA';
25
-
26
-    /**
27
-     * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
28
-     * expired
29
-     */
30
-    const upcoming = 'DTU';
31
-
32
-    /**
33
-     * Datetime is postponed
34
-     */
35
-    const postponed = 'DTP';
36
-
37
-    /**
38
-     * Datetime is cancelled
39
-     */
40
-    const cancelled = 'DTC';
41
-
42
-    /**
43
-     * constant used by get_active_status, indicates datetime has expired (event is over)
44
-     */
45
-    const expired = 'DTE';
46
-
47
-    /**
48
-     * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
49
-     */
50
-    const inactive = 'DTI';
51
-
52
-
53
-    /**
54
-     * @param array  $props_n_values    incoming values
55
-     * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
56
-     * @param array  $date_formats      incoming date_formats in an array where the first value is the date_format
57
-     *                                  and the second value is the time format
58
-     * @return EE_Datetime
59
-     * @throws ReflectionException
60
-     * @throws InvalidArgumentException
61
-     * @throws InvalidInterfaceException
62
-     * @throws InvalidDataTypeException
63
-     * @throws EE_Error
64
-     */
65
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
66
-    {
67
-        $has_object = parent::_check_for_object(
68
-            $props_n_values,
69
-            __CLASS__,
70
-            $timezone,
71
-            $date_formats
72
-        );
73
-        return $has_object
74
-            ? $has_object
75
-            : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Datetime
84
-     * @throws ReflectionException
85
-     * @throws InvalidArgumentException
86
-     * @throws InvalidInterfaceException
87
-     * @throws InvalidDataTypeException
88
-     * @throws EE_Error
89
-     */
90
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
91
-    {
92
-        return new self($props_n_values, true, $timezone);
93
-    }
94
-
95
-
96
-    /**
97
-     * @param $name
98
-     * @throws ReflectionException
99
-     * @throws InvalidArgumentException
100
-     * @throws InvalidInterfaceException
101
-     * @throws InvalidDataTypeException
102
-     * @throws EE_Error
103
-     */
104
-    public function set_name($name)
105
-    {
106
-        $this->set('DTT_name', $name);
107
-    }
108
-
109
-
110
-    /**
111
-     * @param $description
112
-     * @throws ReflectionException
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidDataTypeException
116
-     * @throws EE_Error
117
-     */
118
-    public function set_description($description)
119
-    {
120
-        $this->set('DTT_description', $description);
121
-    }
122
-
123
-
124
-    /**
125
-     * Set event start date
126
-     * set the start date for an event
127
-     *
128
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
129
-     * @throws ReflectionException
130
-     * @throws InvalidArgumentException
131
-     * @throws InvalidInterfaceException
132
-     * @throws InvalidDataTypeException
133
-     * @throws EE_Error
134
-     */
135
-    public function set_start_date($date)
136
-    {
137
-        $this->_set_date_for($date, 'DTT_EVT_start');
138
-    }
139
-
140
-
141
-    /**
142
-     * Set event start time
143
-     * set the start time for an event
144
-     *
145
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
146
-     * @throws ReflectionException
147
-     * @throws InvalidArgumentException
148
-     * @throws InvalidInterfaceException
149
-     * @throws InvalidDataTypeException
150
-     * @throws EE_Error
151
-     */
152
-    public function set_start_time($time)
153
-    {
154
-        $this->_set_time_for($time, 'DTT_EVT_start');
155
-    }
156
-
157
-
158
-    /**
159
-     * Set event end date
160
-     * set the end date for an event
161
-     *
162
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
163
-     * @throws ReflectionException
164
-     * @throws InvalidArgumentException
165
-     * @throws InvalidInterfaceException
166
-     * @throws InvalidDataTypeException
167
-     * @throws EE_Error
168
-     */
169
-    public function set_end_date($date)
170
-    {
171
-        $this->_set_date_for($date, 'DTT_EVT_end');
172
-    }
173
-
174
-
175
-    /**
176
-     * Set event end time
177
-     * set the end time for an event
178
-     *
179
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
180
-     * @throws ReflectionException
181
-     * @throws InvalidArgumentException
182
-     * @throws InvalidInterfaceException
183
-     * @throws InvalidDataTypeException
184
-     * @throws EE_Error
185
-     */
186
-    public function set_end_time($time)
187
-    {
188
-        $this->_set_time_for($time, 'DTT_EVT_end');
189
-    }
190
-
191
-
192
-    /**
193
-     * Set registration limit
194
-     * set the maximum number of attendees that can be registered for this datetime slot
195
-     *
196
-     * @param int $reg_limit
197
-     * @throws ReflectionException
198
-     * @throws InvalidArgumentException
199
-     * @throws InvalidInterfaceException
200
-     * @throws InvalidDataTypeException
201
-     * @throws EE_Error
202
-     */
203
-    public function set_reg_limit($reg_limit)
204
-    {
205
-        $this->set('DTT_reg_limit', $reg_limit);
206
-    }
207
-
208
-
209
-    /**
210
-     * get the number of tickets sold for this datetime slot
211
-     *
212
-     * @return mixed int on success, FALSE on fail
213
-     * @throws ReflectionException
214
-     * @throws InvalidArgumentException
215
-     * @throws InvalidInterfaceException
216
-     * @throws InvalidDataTypeException
217
-     * @throws EE_Error
218
-     */
219
-    public function sold()
220
-    {
221
-        return $this->get_raw('DTT_sold');
222
-    }
223
-
224
-
225
-    /**
226
-     * @param int $sold
227
-     * @throws ReflectionException
228
-     * @throws InvalidArgumentException
229
-     * @throws InvalidInterfaceException
230
-     * @throws InvalidDataTypeException
231
-     * @throws EE_Error
232
-     */
233
-    public function set_sold($sold)
234
-    {
235
-        // sold can not go below zero
236
-        $sold = max(0, $sold);
237
-        $this->set('DTT_sold', $sold);
238
-    }
239
-
240
-
241
-    /**
242
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
243
-     * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
244
-     *
245
-     * @param int $qty
246
-     * @param boolean $also_decrease_reserved
247
-     * @return boolean indicating success
248
-     * @throws ReflectionException
249
-     * @throws InvalidArgumentException
250
-     * @throws InvalidInterfaceException
251
-     * @throws InvalidDataTypeException
252
-     * @throws EE_Error
253
-     */
254
-    public function increaseSold($qty = 1, $also_decrease_reserved = true)
255
-    {
256
-        $qty = absint($qty);
257
-        if ($also_decrease_reserved) {
258
-            $success = $this->adjustNumericFieldsInDb(
259
-                [
260
-                    'DTT_reserved' => $qty * -1,
261
-                    'DTT_sold' => $qty
262
-                ]
263
-            );
264
-        } else {
265
-            $success = $this->adjustNumericFieldsInDb(
266
-                [
267
-                    'DTT_sold' => $qty
268
-                ]
269
-            );
270
-        }
271
-
272
-        do_action(
273
-            'AHEE__EE_Datetime__increase_sold',
274
-            $this,
275
-            $qty,
276
-            $this->sold(),
277
-            $success
278
-        );
279
-        return $success;
280
-    }
281
-
282
-
283
-    /**
284
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
285
-     * to save afterwards.)
286
-     *
287
-     * @param int $qty
288
-     * @return boolean indicating success
289
-     * @throws ReflectionException
290
-     * @throws InvalidArgumentException
291
-     * @throws InvalidInterfaceException
292
-     * @throws InvalidDataTypeException
293
-     * @throws EE_Error
294
-     */
295
-    public function decreaseSold($qty = 1)
296
-    {
297
-        $qty = absint($qty);
298
-        $success = $this->adjustNumericFieldsInDb(
299
-            [
300
-                'DTT_sold' => $qty * -1
301
-            ]
302
-        );
303
-        do_action(
304
-            'AHEE__EE_Datetime__decrease_sold',
305
-            $this,
306
-            $qty,
307
-            $this->sold(),
308
-            $success
309
-        );
310
-        return $success;
311
-    }
312
-
313
-
314
-    /**
315
-     * Gets qty of reserved tickets for this datetime
316
-     *
317
-     * @return int
318
-     * @throws ReflectionException
319
-     * @throws InvalidArgumentException
320
-     * @throws InvalidInterfaceException
321
-     * @throws InvalidDataTypeException
322
-     * @throws EE_Error
323
-     */
324
-    public function reserved()
325
-    {
326
-        return $this->get_raw('DTT_reserved');
327
-    }
328
-
329
-
330
-    /**
331
-     * Sets qty of reserved tickets for this datetime
332
-     *
333
-     * @param int $reserved
334
-     * @throws ReflectionException
335
-     * @throws InvalidArgumentException
336
-     * @throws InvalidInterfaceException
337
-     * @throws InvalidDataTypeException
338
-     * @throws EE_Error
339
-     */
340
-    public function set_reserved($reserved)
341
-    {
342
-        // reserved can not go below zero
343
-        $reserved = max(0, (int) $reserved);
344
-        $this->set('DTT_reserved', $reserved);
345
-    }
346
-
347
-
348
-    /**
349
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
350
-     *
351
-     * @param int $qty
352
-     * @return boolean indicating success
353
-     * @throws ReflectionException
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidInterfaceException
356
-     * @throws InvalidDataTypeException
357
-     * @throws EE_Error
358
-     */
359
-    public function increaseReserved($qty = 1)
360
-    {
361
-        $qty = absint($qty);
362
-        $success = $this->incrementFieldConditionallyInDb(
363
-            'DTT_reserved',
364
-            'DTT_sold',
365
-            'DTT_reg_limit',
366
-            $qty
367
-        );
368
-        do_action(
369
-            'AHEE__EE_Datetime__increase_reserved',
370
-            $this,
371
-            $qty,
372
-            $this->reserved(),
373
-            $success
374
-        );
375
-        return $success;
376
-    }
377
-
378
-
379
-    /**
380
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
381
-     *
382
-     * @param int $qty
383
-     * @return boolean indicating success
384
-     * @throws ReflectionException
385
-     * @throws InvalidArgumentException
386
-     * @throws InvalidInterfaceException
387
-     * @throws InvalidDataTypeException
388
-     * @throws EE_Error
389
-     */
390
-    public function decreaseReserved($qty = 1)
391
-    {
392
-        $qty = absint($qty);
393
-        $success = $this->adjustNumericFieldsInDb(
394
-            [
395
-                'DTT_reserved' => $qty * -1
396
-            ]
397
-        );
398
-        do_action(
399
-            'AHEE__EE_Datetime__decrease_reserved',
400
-            $this,
401
-            $qty,
402
-            $this->reserved(),
403
-            $success
404
-        );
405
-        return $success;
406
-    }
407
-
408
-
409
-    /**
410
-     * total sold and reserved tickets
411
-     *
412
-     * @return int
413
-     * @throws ReflectionException
414
-     * @throws InvalidArgumentException
415
-     * @throws InvalidInterfaceException
416
-     * @throws InvalidDataTypeException
417
-     * @throws EE_Error
418
-     */
419
-    public function sold_and_reserved()
420
-    {
421
-        return $this->sold() + $this->reserved();
422
-    }
423
-
424
-
425
-    /**
426
-     * returns the datetime name
427
-     *
428
-     * @return string
429
-     * @throws ReflectionException
430
-     * @throws InvalidArgumentException
431
-     * @throws InvalidInterfaceException
432
-     * @throws InvalidDataTypeException
433
-     * @throws EE_Error
434
-     */
435
-    public function name()
436
-    {
437
-        return $this->get('DTT_name');
438
-    }
439
-
440
-
441
-    /**
442
-     * returns the datetime description
443
-     *
444
-     * @return string
445
-     * @throws ReflectionException
446
-     * @throws InvalidArgumentException
447
-     * @throws InvalidInterfaceException
448
-     * @throws InvalidDataTypeException
449
-     * @throws EE_Error
450
-     */
451
-    public function description()
452
-    {
453
-        return $this->get('DTT_description');
454
-    }
455
-
456
-
457
-    /**
458
-     * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
459
-     *
460
-     * @return boolean  TRUE if is primary, FALSE if not.
461
-     * @throws ReflectionException
462
-     * @throws InvalidArgumentException
463
-     * @throws InvalidInterfaceException
464
-     * @throws InvalidDataTypeException
465
-     * @throws EE_Error
466
-     */
467
-    public function is_primary()
468
-    {
469
-        return $this->get('DTT_is_primary');
470
-    }
471
-
472
-
473
-    /**
474
-     * This helper simply returns the order for the datetime
475
-     *
476
-     * @return int  The order of the datetime for this event.
477
-     * @throws ReflectionException
478
-     * @throws InvalidArgumentException
479
-     * @throws InvalidInterfaceException
480
-     * @throws InvalidDataTypeException
481
-     * @throws EE_Error
482
-     */
483
-    public function order()
484
-    {
485
-        return $this->get('DTT_order');
486
-    }
487
-
488
-
489
-    /**
490
-     * This helper simply returns the parent id for the datetime
491
-     *
492
-     * @return int
493
-     * @throws ReflectionException
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidInterfaceException
496
-     * @throws InvalidDataTypeException
497
-     * @throws EE_Error
498
-     */
499
-    public function parent()
500
-    {
501
-        return $this->get('DTT_parent');
502
-    }
503
-
504
-
505
-    /**
506
-     * show date and/or time
507
-     *
508
-     * @param string $date_or_time    whether to display a date or time or both
509
-     * @param string $start_or_end    whether to display start or end datetimes
510
-     * @param string $dt_frmt
511
-     * @param string $tm_frmt
512
-     * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
513
-     *                                otherwise we use the standard formats)
514
-     * @return string|bool  string on success, FALSE on fail
515
-     * @throws ReflectionException
516
-     * @throws InvalidArgumentException
517
-     * @throws InvalidInterfaceException
518
-     * @throws InvalidDataTypeException
519
-     * @throws EE_Error
520
-     */
521
-    private function _show_datetime(
522
-        $date_or_time = null,
523
-        $start_or_end = 'start',
524
-        $dt_frmt = '',
525
-        $tm_frmt = '',
526
-        $echo = false
527
-    ) {
528
-        $field_name = "DTT_EVT_{$start_or_end}";
529
-        $dtt = $this->_get_datetime(
530
-            $field_name,
531
-            $dt_frmt,
532
-            $tm_frmt,
533
-            $date_or_time,
534
-            $echo
535
-        );
536
-        if (! $echo) {
537
-            return $dtt;
538
-        }
539
-        return '';
540
-    }
541
-
542
-
543
-    /**
544
-     * get event start date.  Provide either the date format, or NULL to re-use the
545
-     * last-used format, or '' to use the default date format
546
-     *
547
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
548
-     * @return mixed            string on success, FALSE on fail
549
-     * @throws ReflectionException
550
-     * @throws InvalidArgumentException
551
-     * @throws InvalidInterfaceException
552
-     * @throws InvalidDataTypeException
553
-     * @throws EE_Error
554
-     */
555
-    public function start_date($dt_frmt = '')
556
-    {
557
-        return $this->_show_datetime('D', 'start', $dt_frmt);
558
-    }
559
-
560
-
561
-    /**
562
-     * Echoes start_date()
563
-     *
564
-     * @param string $dt_frmt
565
-     * @throws ReflectionException
566
-     * @throws InvalidArgumentException
567
-     * @throws InvalidInterfaceException
568
-     * @throws InvalidDataTypeException
569
-     * @throws EE_Error
570
-     */
571
-    public function e_start_date($dt_frmt = '')
572
-    {
573
-        $this->_show_datetime('D', 'start', $dt_frmt, null, true);
574
-    }
575
-
576
-
577
-    /**
578
-     * get end date. Provide either the date format, or NULL to re-use the
579
-     * last-used format, or '' to use the default date format
580
-     *
581
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
582
-     * @return mixed            string on success, FALSE on fail
583
-     * @throws ReflectionException
584
-     * @throws InvalidArgumentException
585
-     * @throws InvalidInterfaceException
586
-     * @throws InvalidDataTypeException
587
-     * @throws EE_Error
588
-     */
589
-    public function end_date($dt_frmt = '')
590
-    {
591
-        return $this->_show_datetime('D', 'end', $dt_frmt);
592
-    }
593
-
594
-
595
-    /**
596
-     * Echoes the end date. See end_date()
597
-     *
598
-     * @param string $dt_frmt
599
-     * @throws ReflectionException
600
-     * @throws InvalidArgumentException
601
-     * @throws InvalidInterfaceException
602
-     * @throws InvalidDataTypeException
603
-     * @throws EE_Error
604
-     */
605
-    public function e_end_date($dt_frmt = '')
606
-    {
607
-        $this->_show_datetime('D', 'end', $dt_frmt, null, true);
608
-    }
609
-
610
-
611
-    /**
612
-     * get date_range - meaning the start AND end date
613
-     *
614
-     * @access public
615
-     * @param string $dt_frmt     string representation of date format defaults to WP settings
616
-     * @param string $conjunction conjunction junction what's your function ?
617
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
618
-     * @return mixed              string on success, FALSE on fail
619
-     * @throws ReflectionException
620
-     * @throws InvalidArgumentException
621
-     * @throws InvalidInterfaceException
622
-     * @throws InvalidDataTypeException
623
-     * @throws EE_Error
624
-     */
625
-    public function date_range($dt_frmt = '', $conjunction = ' - ')
626
-    {
627
-        $dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
628
-        $start = str_replace(
629
-            ' ',
630
-            ' ',
631
-            $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
632
-        );
633
-        $end = str_replace(
634
-            ' ',
635
-            ' ',
636
-            $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
637
-        );
638
-        return $start !== $end ? $start . $conjunction . $end : $start;
639
-    }
640
-
641
-
642
-    /**
643
-     * @param string $dt_frmt
644
-     * @param string $conjunction
645
-     * @throws ReflectionException
646
-     * @throws InvalidArgumentException
647
-     * @throws InvalidInterfaceException
648
-     * @throws InvalidDataTypeException
649
-     * @throws EE_Error
650
-     */
651
-    public function e_date_range($dt_frmt = '', $conjunction = ' - ')
652
-    {
653
-        echo $this->date_range($dt_frmt, $conjunction);
654
-    }
655
-
656
-
657
-    /**
658
-     * get start time
659
-     *
660
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
661
-     * @return mixed        string on success, FALSE on fail
662
-     * @throws ReflectionException
663
-     * @throws InvalidArgumentException
664
-     * @throws InvalidInterfaceException
665
-     * @throws InvalidDataTypeException
666
-     * @throws EE_Error
667
-     */
668
-    public function start_time($tm_format = '')
669
-    {
670
-        return $this->_show_datetime('T', 'start', null, $tm_format);
671
-    }
672
-
673
-
674
-    /**
675
-     * @param string $tm_format
676
-     * @throws ReflectionException
677
-     * @throws InvalidArgumentException
678
-     * @throws InvalidInterfaceException
679
-     * @throws InvalidDataTypeException
680
-     * @throws EE_Error
681
-     */
682
-    public function e_start_time($tm_format = '')
683
-    {
684
-        $this->_show_datetime('T', 'start', null, $tm_format, true);
685
-    }
686
-
687
-
688
-    /**
689
-     * get end time
690
-     *
691
-     * @param string $tm_format string representation of time format defaults to 'g:i a'
692
-     * @return mixed                string on success, FALSE on fail
693
-     * @throws ReflectionException
694
-     * @throws InvalidArgumentException
695
-     * @throws InvalidInterfaceException
696
-     * @throws InvalidDataTypeException
697
-     * @throws EE_Error
698
-     */
699
-    public function end_time($tm_format = '')
700
-    {
701
-        return $this->_show_datetime('T', 'end', null, $tm_format);
702
-    }
703
-
704
-
705
-    /**
706
-     * @param string $tm_format
707
-     * @throws ReflectionException
708
-     * @throws InvalidArgumentException
709
-     * @throws InvalidInterfaceException
710
-     * @throws InvalidDataTypeException
711
-     * @throws EE_Error
712
-     */
713
-    public function e_end_time($tm_format = '')
714
-    {
715
-        $this->_show_datetime('T', 'end', null, $tm_format, true);
716
-    }
717
-
718
-
719
-    /**
720
-     * get time_range
721
-     *
722
-     * @access public
723
-     * @param string $tm_format   string representation of time format defaults to 'g:i a'
724
-     * @param string $conjunction conjunction junction what's your function ?
725
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
726
-     * @return mixed              string on success, FALSE on fail
727
-     * @throws ReflectionException
728
-     * @throws InvalidArgumentException
729
-     * @throws InvalidInterfaceException
730
-     * @throws InvalidDataTypeException
731
-     * @throws EE_Error
732
-     */
733
-    public function time_range($tm_format = '', $conjunction = ' - ')
734
-    {
735
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
736
-        $start = str_replace(
737
-            ' ',
738
-            ' ',
739
-            $this->get_i18n_datetime('DTT_EVT_start', $tm_format)
740
-        );
741
-        $end = str_replace(
742
-            ' ',
743
-            ' ',
744
-            $this->get_i18n_datetime('DTT_EVT_end', $tm_format)
745
-        );
746
-        return $start !== $end ? $start . $conjunction . $end : $start;
747
-    }
748
-
749
-
750
-    /**
751
-     * @param string $tm_format
752
-     * @param string $conjunction
753
-     * @throws ReflectionException
754
-     * @throws InvalidArgumentException
755
-     * @throws InvalidInterfaceException
756
-     * @throws InvalidDataTypeException
757
-     * @throws EE_Error
758
-     */
759
-    public function e_time_range($tm_format = '', $conjunction = ' - ')
760
-    {
761
-        echo $this->time_range($tm_format, $conjunction);
762
-    }
763
-
764
-
765
-    /**
766
-     * This returns a range representation of the date and times.
767
-     * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
768
-     * Also, the return value is localized.
769
-     *
770
-     * @param string $dt_format
771
-     * @param string $tm_format
772
-     * @param string $conjunction used between two different dates or times.
773
-     *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
774
-     * @param string $separator   used between the date and time formats.
775
-     *                            ex: Dec 1, 2016{$separator}2pm
776
-     * @return string
777
-     * @throws ReflectionException
778
-     * @throws InvalidArgumentException
779
-     * @throws InvalidInterfaceException
780
-     * @throws InvalidDataTypeException
781
-     * @throws EE_Error
782
-     */
783
-    public function date_and_time_range(
784
-        $dt_format = '',
785
-        $tm_format = '',
786
-        $conjunction = ' - ',
787
-        $separator = ' '
788
-    ) {
789
-        $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
790
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
791
-        $full_format = $dt_format . $separator . $tm_format;
792
-        // the range output depends on various conditions
793
-        switch (true) {
794
-            // start date timestamp and end date timestamp are the same.
795
-            case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
796
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
797
-                break;
798
-            // start and end date are the same but times are different
799
-            case ($this->start_date() === $this->end_date()):
800
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
801
-                          . $conjunction
802
-                          . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
803
-                break;
804
-            // all other conditions
805
-            default:
806
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
807
-                          . $conjunction
808
-                          . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
809
-                break;
810
-        }
811
-        return $output;
812
-    }
813
-
814
-
815
-    /**
816
-     * This echos the results of date and time range.
817
-     *
818
-     * @see date_and_time_range() for more details on purpose.
819
-     * @param string $dt_format
820
-     * @param string $tm_format
821
-     * @param string $conjunction
822
-     * @return void
823
-     * @throws ReflectionException
824
-     * @throws InvalidArgumentException
825
-     * @throws InvalidInterfaceException
826
-     * @throws InvalidDataTypeException
827
-     * @throws EE_Error
828
-     */
829
-    public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
830
-    {
831
-        echo $this->date_and_time_range($dt_format, $tm_format, $conjunction);
832
-    }
833
-
834
-
835
-    /**
836
-     * get start date and start time
837
-     *
838
-     * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
839
-     * @param    string $tm_format - string representation of time format defaults to 'g:i a'
840
-     * @return    mixed    string on success, FALSE on fail
841
-     * @throws ReflectionException
842
-     * @throws InvalidArgumentException
843
-     * @throws InvalidInterfaceException
844
-     * @throws InvalidDataTypeException
845
-     * @throws EE_Error
846
-     */
847
-    public function start_date_and_time($dt_format = '', $tm_format = '')
848
-    {
849
-        return $this->_show_datetime('', 'start', $dt_format, $tm_format);
850
-    }
851
-
852
-
853
-    /**
854
-     * @param string $dt_frmt
855
-     * @param string $tm_format
856
-     * @throws ReflectionException
857
-     * @throws InvalidArgumentException
858
-     * @throws InvalidInterfaceException
859
-     * @throws InvalidDataTypeException
860
-     * @throws EE_Error
861
-     */
862
-    public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
863
-    {
864
-        $this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
865
-    }
866
-
867
-
868
-    /**
869
-     * Shows the length of the event (start to end time).
870
-     * Can be shown in 'seconds','minutes','hours', or 'days'.
871
-     * By default, rounds up. (So if you use 'days', and then event
872
-     * only occurs for 1 hour, it will return 1 day).
873
-     *
874
-     * @param string $units 'seconds','minutes','hours','days'
875
-     * @param bool   $round_up
876
-     * @return float|int|mixed
877
-     * @throws ReflectionException
878
-     * @throws InvalidArgumentException
879
-     * @throws InvalidInterfaceException
880
-     * @throws InvalidDataTypeException
881
-     * @throws EE_Error
882
-     */
883
-    public function length($units = 'seconds', $round_up = false)
884
-    {
885
-        $start = $this->get_raw('DTT_EVT_start');
886
-        $end = $this->get_raw('DTT_EVT_end');
887
-        $length_in_units = $end - $start;
888
-        switch ($units) {
889
-            // NOTE: We purposefully don't use "break;" in order to chain the divisions
890
-            /** @noinspection PhpMissingBreakStatementInspection */
891
-            // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
892
-            case 'days':
893
-                $length_in_units /= 24;
894
-            /** @noinspection PhpMissingBreakStatementInspection */
895
-            case 'hours':
896
-                // fall through is intentional
897
-                $length_in_units /= 60;
898
-            /** @noinspection PhpMissingBreakStatementInspection */
899
-            case 'minutes':
900
-                // fall through is intentional
901
-                $length_in_units /= 60;
902
-            case 'seconds':
903
-            default:
904
-                $length_in_units = ceil($length_in_units);
905
-        }
906
-        // phpcs:enable
907
-        if ($round_up) {
908
-            $length_in_units = max($length_in_units, 1);
909
-        }
910
-        return $length_in_units;
911
-    }
912
-
913
-
914
-    /**
915
-     *        get end date and time
916
-     *
917
-     * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
918
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
919
-     * @return    mixed                string on success, FALSE on fail
920
-     * @throws ReflectionException
921
-     * @throws InvalidArgumentException
922
-     * @throws InvalidInterfaceException
923
-     * @throws InvalidDataTypeException
924
-     * @throws EE_Error
925
-     */
926
-    public function end_date_and_time($dt_frmt = '', $tm_format = '')
927
-    {
928
-        return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
929
-    }
930
-
931
-
932
-    /**
933
-     * @param string $dt_frmt
934
-     * @param string $tm_format
935
-     * @throws ReflectionException
936
-     * @throws InvalidArgumentException
937
-     * @throws InvalidInterfaceException
938
-     * @throws InvalidDataTypeException
939
-     * @throws EE_Error
940
-     */
941
-    public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
942
-    {
943
-        $this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
944
-    }
945
-
946
-
947
-    /**
948
-     *        get start timestamp
949
-     *
950
-     * @return        int
951
-     * @throws ReflectionException
952
-     * @throws InvalidArgumentException
953
-     * @throws InvalidInterfaceException
954
-     * @throws InvalidDataTypeException
955
-     * @throws EE_Error
956
-     */
957
-    public function start()
958
-    {
959
-        return $this->get_raw('DTT_EVT_start');
960
-    }
961
-
962
-
963
-    /**
964
-     *        get end timestamp
965
-     *
966
-     * @return        int
967
-     * @throws ReflectionException
968
-     * @throws InvalidArgumentException
969
-     * @throws InvalidInterfaceException
970
-     * @throws InvalidDataTypeException
971
-     * @throws EE_Error
972
-     */
973
-    public function end()
974
-    {
975
-        return $this->get_raw('DTT_EVT_end');
976
-    }
977
-
978
-
979
-    /**
980
-     *    get the registration limit for this datetime slot
981
-     *
982
-     * @return        mixed        int on success, FALSE on fail
983
-     * @throws ReflectionException
984
-     * @throws InvalidArgumentException
985
-     * @throws InvalidInterfaceException
986
-     * @throws InvalidDataTypeException
987
-     * @throws EE_Error
988
-     */
989
-    public function reg_limit()
990
-    {
991
-        return $this->get_raw('DTT_reg_limit');
992
-    }
993
-
994
-
995
-    /**
996
-     *    have the tickets sold for this datetime, met or exceed the registration limit ?
997
-     *
998
-     * @return        boolean
999
-     * @throws ReflectionException
1000
-     * @throws InvalidArgumentException
1001
-     * @throws InvalidInterfaceException
1002
-     * @throws InvalidDataTypeException
1003
-     * @throws EE_Error
1004
-     */
1005
-    public function sold_out()
1006
-    {
1007
-        return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * return the total number of spaces remaining at this venue.
1013
-     * This only takes the venue's capacity into account, NOT the tickets available for sale
1014
-     *
1015
-     * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1016
-     *                               Because if all tickets attached to this datetime have no spaces left,
1017
-     *                               then this datetime IS effectively sold out.
1018
-     *                               However, there are cases where we just want to know the spaces
1019
-     *                               remaining for this particular datetime, hence the flag.
1020
-     * @return int
1021
-     * @throws ReflectionException
1022
-     * @throws InvalidArgumentException
1023
-     * @throws InvalidInterfaceException
1024
-     * @throws InvalidDataTypeException
1025
-     * @throws EE_Error
1026
-     */
1027
-    public function spaces_remaining($consider_tickets = false)
1028
-    {
1029
-        // tickets remaining available for purchase
1030
-        // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1031
-        $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1032
-        if (! $consider_tickets) {
1033
-            return $dtt_remaining;
1034
-        }
1035
-        $tickets_remaining = $this->tickets_remaining();
1036
-        return min($dtt_remaining, $tickets_remaining);
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     * Counts the total tickets available
1042
-     * (from all the different types of tickets which are available for this datetime).
1043
-     *
1044
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1045
-     * @return int
1046
-     * @throws ReflectionException
1047
-     * @throws InvalidArgumentException
1048
-     * @throws InvalidInterfaceException
1049
-     * @throws InvalidDataTypeException
1050
-     * @throws EE_Error
1051
-     */
1052
-    public function tickets_remaining($query_params = array())
1053
-    {
1054
-        $sum = 0;
1055
-        $tickets = $this->tickets($query_params);
1056
-        if (! empty($tickets)) {
1057
-            foreach ($tickets as $ticket) {
1058
-                if ($ticket instanceof EE_Ticket) {
1059
-                    // get the actual amount of tickets that can be sold
1060
-                    $qty = $ticket->qty('saleable');
1061
-                    if ($qty === EE_INF) {
1062
-                        return EE_INF;
1063
-                    }
1064
-                    // no negative ticket quantities plz
1065
-                    if ($qty > 0) {
1066
-                        $sum += $qty;
1067
-                    }
1068
-                }
1069
-            }
1070
-        }
1071
-        return $sum;
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * Gets the count of all the tickets available at this datetime (not ticket types)
1077
-     * before any were sold
1078
-     *
1079
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1080
-     * @return int
1081
-     * @throws ReflectionException
1082
-     * @throws InvalidArgumentException
1083
-     * @throws InvalidInterfaceException
1084
-     * @throws InvalidDataTypeException
1085
-     * @throws EE_Error
1086
-     */
1087
-    public function sum_tickets_initially_available($query_params = array())
1088
-    {
1089
-        return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     * Returns the lesser-of-the two: spaces remaining at this datetime, or
1095
-     * the total tickets remaining (a sum of the tickets remaining for each ticket type
1096
-     * that is available for this datetime).
1097
-     *
1098
-     * @return int
1099
-     * @throws ReflectionException
1100
-     * @throws InvalidArgumentException
1101
-     * @throws InvalidInterfaceException
1102
-     * @throws InvalidDataTypeException
1103
-     * @throws EE_Error
1104
-     */
1105
-    public function total_tickets_available_at_this_datetime()
1106
-    {
1107
-        return $this->spaces_remaining(true);
1108
-    }
1109
-
1110
-
1111
-    /**
1112
-     * This simply compares the internal dtt for the given string with NOW
1113
-     * and determines if the date is upcoming or not.
1114
-     *
1115
-     * @access public
1116
-     * @return boolean
1117
-     * @throws ReflectionException
1118
-     * @throws InvalidArgumentException
1119
-     * @throws InvalidInterfaceException
1120
-     * @throws InvalidDataTypeException
1121
-     * @throws EE_Error
1122
-     */
1123
-    public function is_upcoming()
1124
-    {
1125
-        return ($this->get_raw('DTT_EVT_start') > time());
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * This simply compares the internal datetime for the given string with NOW
1131
-     * and returns if the date is active (i.e. start and end time)
1132
-     *
1133
-     * @return boolean
1134
-     * @throws ReflectionException
1135
-     * @throws InvalidArgumentException
1136
-     * @throws InvalidInterfaceException
1137
-     * @throws InvalidDataTypeException
1138
-     * @throws EE_Error
1139
-     */
1140
-    public function is_active()
1141
-    {
1142
-        return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1143
-    }
1144
-
1145
-
1146
-    /**
1147
-     * This simply compares the internal dtt for the given string with NOW
1148
-     * and determines if the date is expired or not.
1149
-     *
1150
-     * @return boolean
1151
-     * @throws ReflectionException
1152
-     * @throws InvalidArgumentException
1153
-     * @throws InvalidInterfaceException
1154
-     * @throws InvalidDataTypeException
1155
-     * @throws EE_Error
1156
-     */
1157
-    public function is_expired()
1158
-    {
1159
-        return ($this->get_raw('DTT_EVT_end') < time());
1160
-    }
1161
-
1162
-
1163
-    /**
1164
-     * This returns the active status for whether an event is active, upcoming, or expired
1165
-     *
1166
-     * @return int return value will be one of the EE_Datetime status constants.
1167
-     * @throws ReflectionException
1168
-     * @throws InvalidArgumentException
1169
-     * @throws InvalidInterfaceException
1170
-     * @throws InvalidDataTypeException
1171
-     * @throws EE_Error
1172
-     */
1173
-    public function get_active_status()
1174
-    {
1175
-        $total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1176
-        if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1177
-            return EE_Datetime::sold_out;
1178
-        }
1179
-        if ($this->is_expired()) {
1180
-            return EE_Datetime::expired;
1181
-        }
1182
-        if ($this->is_upcoming()) {
1183
-            return EE_Datetime::upcoming;
1184
-        }
1185
-        if ($this->is_active()) {
1186
-            return EE_Datetime::active;
1187
-        }
1188
-        return null;
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1194
-     *
1195
-     * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1196
-     * @return string
1197
-     * @throws ReflectionException
1198
-     * @throws InvalidArgumentException
1199
-     * @throws InvalidInterfaceException
1200
-     * @throws InvalidDataTypeException
1201
-     * @throws EE_Error
1202
-     */
1203
-    public function get_dtt_display_name($use_dtt_name = false)
1204
-    {
1205
-        if ($use_dtt_name) {
1206
-            $dtt_name = $this->name();
1207
-            if (! empty($dtt_name)) {
1208
-                return $dtt_name;
1209
-            }
1210
-        }
1211
-        // first condition is to see if the months are different
1212
-        if (
1213
-            date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1214
-        ) {
1215
-            $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1216
-            // next condition is if its the same month but different day
1217
-        } else {
1218
-            if (
1219
-                date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1220
-                && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1221
-            ) {
1222
-                $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1223
-            } else {
1224
-                $display_date = $this->start_date('F j\, Y')
1225
-                                . ' @ '
1226
-                                . $this->start_date('g:i a')
1227
-                                . ' - '
1228
-                                . $this->end_date('g:i a');
1229
-            }
1230
-        }
1231
-        return $display_date;
1232
-    }
1233
-
1234
-
1235
-    /**
1236
-     * Gets all the tickets for this datetime
1237
-     *
1238
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1239
-     * @return EE_Base_Class[]|EE_Ticket[]
1240
-     * @throws ReflectionException
1241
-     * @throws InvalidArgumentException
1242
-     * @throws InvalidInterfaceException
1243
-     * @throws InvalidDataTypeException
1244
-     * @throws EE_Error
1245
-     */
1246
-    public function tickets($query_params = array())
1247
-    {
1248
-        return $this->get_many_related('Ticket', $query_params);
1249
-    }
1250
-
1251
-
1252
-    /**
1253
-     * Gets all the ticket types currently available for purchase
1254
-     *
1255
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1256
-     * @return EE_Ticket[]
1257
-     * @throws ReflectionException
1258
-     * @throws InvalidArgumentException
1259
-     * @throws InvalidInterfaceException
1260
-     * @throws InvalidDataTypeException
1261
-     * @throws EE_Error
1262
-     */
1263
-    public function ticket_types_available_for_purchase($query_params = array())
1264
-    {
1265
-        // first check if datetime is valid
1266
-        if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1267
-            return array();
1268
-        }
1269
-        if (empty($query_params)) {
1270
-            $query_params = array(
1271
-                array(
1272
-                    'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1273
-                    'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1274
-                    'TKT_deleted'    => false,
1275
-                ),
1276
-            );
1277
-        }
1278
-        return $this->tickets($query_params);
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * @return EE_Base_Class|EE_Event
1284
-     * @throws ReflectionException
1285
-     * @throws InvalidArgumentException
1286
-     * @throws InvalidInterfaceException
1287
-     * @throws InvalidDataTypeException
1288
-     * @throws EE_Error
1289
-     */
1290
-    public function event()
1291
-    {
1292
-        return $this->get_first_related('Event');
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1298
-     * (via the tickets).
1299
-     *
1300
-     * @return int
1301
-     * @throws ReflectionException
1302
-     * @throws InvalidArgumentException
1303
-     * @throws InvalidInterfaceException
1304
-     * @throws InvalidDataTypeException
1305
-     * @throws EE_Error
1306
-     */
1307
-    public function update_sold()
1308
-    {
1309
-        $count_regs_for_this_datetime = EEM_Registration::instance()->count(
1310
-            array(
1311
-                array(
1312
-                    'STS_ID'                 => EEM_Registration::status_id_approved,
1313
-                    'REG_deleted'            => 0,
1314
-                    'Ticket.Datetime.DTT_ID' => $this->ID(),
1315
-                ),
1316
-            )
1317
-        );
1318
-        $this->set_sold($count_regs_for_this_datetime);
1319
-        $this->save();
1320
-        return $count_regs_for_this_datetime;
1321
-    }
1322
-
1323
-
1324
-    /**
1325
-     * Adds a venue to this event
1326
-     *
1327
-     * @param int|EE_Venue /int $venue_id_or_obj
1328
-     * @return EE_Base_Class|EE_Venue
1329
-     * @throws EE_Error
1330
-     * @throws ReflectionException
1331
-     */
1332
-    public function add_venue($venue_id_or_obj): EE_Venue
1333
-    {
1334
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     * Removes a venue from the event
1340
-     *
1341
-     * @param EE_Venue /int $venue_id_or_obj
1342
-     * @return EE_Base_Class|EE_Venue
1343
-     * @throws EE_Error
1344
-     * @throws ReflectionException
1345
-     */
1346
-    public function remove_venue($venue_id_or_obj): EE_Venue
1347
-    {
1348
-        $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
1349
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Gets the venue related to the event. May provide additional $query_params if desired
1355
-     *
1356
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1357
-     * @return int
1358
-     * @throws EE_Error
1359
-     * @throws ReflectionException
1360
-     */
1361
-    public function venue_ID(array $query_params = []): int
1362
-    {
1363
-        $venue = $this->get_first_related('Venue', $query_params);
1364
-        return $venue instanceof EE_Venue
1365
-            ? $venue->ID()
1366
-            : 0;
1367
-    }
1368
-
1369
-
1370
-    /**
1371
-     * Gets the venue related to the event. May provide additional $query_params if desired
1372
-     *
1373
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1374
-     * @return EE_Base_Class|EE_Venue
1375
-     * @throws EE_Error
1376
-     * @throws ReflectionException
1377
-     */
1378
-    public function venue(array $query_params = [])
1379
-    {
1380
-        return $this->get_first_related('Venue', $query_params);
1381
-    }
1382
-
1383
-
1384
-    /**
1385
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1386
-     * @param string                   $relationName
1387
-     * @param array                    $extra_join_model_fields_n_values
1388
-     * @param string|null              $cache_id
1389
-     * @return EE_Base_Class
1390
-     * @throws EE_Error
1391
-     * @throws ReflectionException
1392
-     * @since   $VID:$
1393
-     */
1394
-    public function _add_relation_to(
1395
-        $otherObjectModelObjectOrID,
1396
-        $relationName,
1397
-        $extra_join_model_fields_n_values = [],
1398
-        $cache_id = null
1399
-    ) {
1400
-        if ($relationName === 'Ticket') {
1401
-            /** @var EE_Ticket $ticket */
1402
-            $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1403
-            $this->increaseSold($ticket->sold());
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') {
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
-    /*******************************************************************
16
+	/**
17
+	 * constant used by get_active_status, indicates datetime has no more available spaces
18
+	 */
19
+	const sold_out = 'DTS';
20
+
21
+	/**
22
+	 * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
23
+	 */
24
+	const active = 'DTA';
25
+
26
+	/**
27
+	 * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
28
+	 * expired
29
+	 */
30
+	const upcoming = 'DTU';
31
+
32
+	/**
33
+	 * Datetime is postponed
34
+	 */
35
+	const postponed = 'DTP';
36
+
37
+	/**
38
+	 * Datetime is cancelled
39
+	 */
40
+	const cancelled = 'DTC';
41
+
42
+	/**
43
+	 * constant used by get_active_status, indicates datetime has expired (event is over)
44
+	 */
45
+	const expired = 'DTE';
46
+
47
+	/**
48
+	 * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
49
+	 */
50
+	const inactive = 'DTI';
51
+
52
+
53
+	/**
54
+	 * @param array  $props_n_values    incoming values
55
+	 * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
56
+	 * @param array  $date_formats      incoming date_formats in an array where the first value is the date_format
57
+	 *                                  and the second value is the time format
58
+	 * @return EE_Datetime
59
+	 * @throws ReflectionException
60
+	 * @throws InvalidArgumentException
61
+	 * @throws InvalidInterfaceException
62
+	 * @throws InvalidDataTypeException
63
+	 * @throws EE_Error
64
+	 */
65
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
66
+	{
67
+		$has_object = parent::_check_for_object(
68
+			$props_n_values,
69
+			__CLASS__,
70
+			$timezone,
71
+			$date_formats
72
+		);
73
+		return $has_object
74
+			? $has_object
75
+			: new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Datetime
84
+	 * @throws ReflectionException
85
+	 * @throws InvalidArgumentException
86
+	 * @throws InvalidInterfaceException
87
+	 * @throws InvalidDataTypeException
88
+	 * @throws EE_Error
89
+	 */
90
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
91
+	{
92
+		return new self($props_n_values, true, $timezone);
93
+	}
94
+
95
+
96
+	/**
97
+	 * @param $name
98
+	 * @throws ReflectionException
99
+	 * @throws InvalidArgumentException
100
+	 * @throws InvalidInterfaceException
101
+	 * @throws InvalidDataTypeException
102
+	 * @throws EE_Error
103
+	 */
104
+	public function set_name($name)
105
+	{
106
+		$this->set('DTT_name', $name);
107
+	}
108
+
109
+
110
+	/**
111
+	 * @param $description
112
+	 * @throws ReflectionException
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws EE_Error
117
+	 */
118
+	public function set_description($description)
119
+	{
120
+		$this->set('DTT_description', $description);
121
+	}
122
+
123
+
124
+	/**
125
+	 * Set event start date
126
+	 * set the start date for an event
127
+	 *
128
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
129
+	 * @throws ReflectionException
130
+	 * @throws InvalidArgumentException
131
+	 * @throws InvalidInterfaceException
132
+	 * @throws InvalidDataTypeException
133
+	 * @throws EE_Error
134
+	 */
135
+	public function set_start_date($date)
136
+	{
137
+		$this->_set_date_for($date, 'DTT_EVT_start');
138
+	}
139
+
140
+
141
+	/**
142
+	 * Set event start time
143
+	 * set the start time for an event
144
+	 *
145
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
146
+	 * @throws ReflectionException
147
+	 * @throws InvalidArgumentException
148
+	 * @throws InvalidInterfaceException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws EE_Error
151
+	 */
152
+	public function set_start_time($time)
153
+	{
154
+		$this->_set_time_for($time, 'DTT_EVT_start');
155
+	}
156
+
157
+
158
+	/**
159
+	 * Set event end date
160
+	 * set the end date for an event
161
+	 *
162
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
163
+	 * @throws ReflectionException
164
+	 * @throws InvalidArgumentException
165
+	 * @throws InvalidInterfaceException
166
+	 * @throws InvalidDataTypeException
167
+	 * @throws EE_Error
168
+	 */
169
+	public function set_end_date($date)
170
+	{
171
+		$this->_set_date_for($date, 'DTT_EVT_end');
172
+	}
173
+
174
+
175
+	/**
176
+	 * Set event end time
177
+	 * set the end time for an event
178
+	 *
179
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
180
+	 * @throws ReflectionException
181
+	 * @throws InvalidArgumentException
182
+	 * @throws InvalidInterfaceException
183
+	 * @throws InvalidDataTypeException
184
+	 * @throws EE_Error
185
+	 */
186
+	public function set_end_time($time)
187
+	{
188
+		$this->_set_time_for($time, 'DTT_EVT_end');
189
+	}
190
+
191
+
192
+	/**
193
+	 * Set registration limit
194
+	 * set the maximum number of attendees that can be registered for this datetime slot
195
+	 *
196
+	 * @param int $reg_limit
197
+	 * @throws ReflectionException
198
+	 * @throws InvalidArgumentException
199
+	 * @throws InvalidInterfaceException
200
+	 * @throws InvalidDataTypeException
201
+	 * @throws EE_Error
202
+	 */
203
+	public function set_reg_limit($reg_limit)
204
+	{
205
+		$this->set('DTT_reg_limit', $reg_limit);
206
+	}
207
+
208
+
209
+	/**
210
+	 * get the number of tickets sold for this datetime slot
211
+	 *
212
+	 * @return mixed int on success, FALSE on fail
213
+	 * @throws ReflectionException
214
+	 * @throws InvalidArgumentException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws InvalidDataTypeException
217
+	 * @throws EE_Error
218
+	 */
219
+	public function sold()
220
+	{
221
+		return $this->get_raw('DTT_sold');
222
+	}
223
+
224
+
225
+	/**
226
+	 * @param int $sold
227
+	 * @throws ReflectionException
228
+	 * @throws InvalidArgumentException
229
+	 * @throws InvalidInterfaceException
230
+	 * @throws InvalidDataTypeException
231
+	 * @throws EE_Error
232
+	 */
233
+	public function set_sold($sold)
234
+	{
235
+		// sold can not go below zero
236
+		$sold = max(0, $sold);
237
+		$this->set('DTT_sold', $sold);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
243
+	 * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
244
+	 *
245
+	 * @param int $qty
246
+	 * @param boolean $also_decrease_reserved
247
+	 * @return boolean indicating success
248
+	 * @throws ReflectionException
249
+	 * @throws InvalidArgumentException
250
+	 * @throws InvalidInterfaceException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws EE_Error
253
+	 */
254
+	public function increaseSold($qty = 1, $also_decrease_reserved = true)
255
+	{
256
+		$qty = absint($qty);
257
+		if ($also_decrease_reserved) {
258
+			$success = $this->adjustNumericFieldsInDb(
259
+				[
260
+					'DTT_reserved' => $qty * -1,
261
+					'DTT_sold' => $qty
262
+				]
263
+			);
264
+		} else {
265
+			$success = $this->adjustNumericFieldsInDb(
266
+				[
267
+					'DTT_sold' => $qty
268
+				]
269
+			);
270
+		}
271
+
272
+		do_action(
273
+			'AHEE__EE_Datetime__increase_sold',
274
+			$this,
275
+			$qty,
276
+			$this->sold(),
277
+			$success
278
+		);
279
+		return $success;
280
+	}
281
+
282
+
283
+	/**
284
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
285
+	 * to save afterwards.)
286
+	 *
287
+	 * @param int $qty
288
+	 * @return boolean indicating success
289
+	 * @throws ReflectionException
290
+	 * @throws InvalidArgumentException
291
+	 * @throws InvalidInterfaceException
292
+	 * @throws InvalidDataTypeException
293
+	 * @throws EE_Error
294
+	 */
295
+	public function decreaseSold($qty = 1)
296
+	{
297
+		$qty = absint($qty);
298
+		$success = $this->adjustNumericFieldsInDb(
299
+			[
300
+				'DTT_sold' => $qty * -1
301
+			]
302
+		);
303
+		do_action(
304
+			'AHEE__EE_Datetime__decrease_sold',
305
+			$this,
306
+			$qty,
307
+			$this->sold(),
308
+			$success
309
+		);
310
+		return $success;
311
+	}
312
+
313
+
314
+	/**
315
+	 * Gets qty of reserved tickets for this datetime
316
+	 *
317
+	 * @return int
318
+	 * @throws ReflectionException
319
+	 * @throws InvalidArgumentException
320
+	 * @throws InvalidInterfaceException
321
+	 * @throws InvalidDataTypeException
322
+	 * @throws EE_Error
323
+	 */
324
+	public function reserved()
325
+	{
326
+		return $this->get_raw('DTT_reserved');
327
+	}
328
+
329
+
330
+	/**
331
+	 * Sets qty of reserved tickets for this datetime
332
+	 *
333
+	 * @param int $reserved
334
+	 * @throws ReflectionException
335
+	 * @throws InvalidArgumentException
336
+	 * @throws InvalidInterfaceException
337
+	 * @throws InvalidDataTypeException
338
+	 * @throws EE_Error
339
+	 */
340
+	public function set_reserved($reserved)
341
+	{
342
+		// reserved can not go below zero
343
+		$reserved = max(0, (int) $reserved);
344
+		$this->set('DTT_reserved', $reserved);
345
+	}
346
+
347
+
348
+	/**
349
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
350
+	 *
351
+	 * @param int $qty
352
+	 * @return boolean indicating success
353
+	 * @throws ReflectionException
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidInterfaceException
356
+	 * @throws InvalidDataTypeException
357
+	 * @throws EE_Error
358
+	 */
359
+	public function increaseReserved($qty = 1)
360
+	{
361
+		$qty = absint($qty);
362
+		$success = $this->incrementFieldConditionallyInDb(
363
+			'DTT_reserved',
364
+			'DTT_sold',
365
+			'DTT_reg_limit',
366
+			$qty
367
+		);
368
+		do_action(
369
+			'AHEE__EE_Datetime__increase_reserved',
370
+			$this,
371
+			$qty,
372
+			$this->reserved(),
373
+			$success
374
+		);
375
+		return $success;
376
+	}
377
+
378
+
379
+	/**
380
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
381
+	 *
382
+	 * @param int $qty
383
+	 * @return boolean indicating success
384
+	 * @throws ReflectionException
385
+	 * @throws InvalidArgumentException
386
+	 * @throws InvalidInterfaceException
387
+	 * @throws InvalidDataTypeException
388
+	 * @throws EE_Error
389
+	 */
390
+	public function decreaseReserved($qty = 1)
391
+	{
392
+		$qty = absint($qty);
393
+		$success = $this->adjustNumericFieldsInDb(
394
+			[
395
+				'DTT_reserved' => $qty * -1
396
+			]
397
+		);
398
+		do_action(
399
+			'AHEE__EE_Datetime__decrease_reserved',
400
+			$this,
401
+			$qty,
402
+			$this->reserved(),
403
+			$success
404
+		);
405
+		return $success;
406
+	}
407
+
408
+
409
+	/**
410
+	 * total sold and reserved tickets
411
+	 *
412
+	 * @return int
413
+	 * @throws ReflectionException
414
+	 * @throws InvalidArgumentException
415
+	 * @throws InvalidInterfaceException
416
+	 * @throws InvalidDataTypeException
417
+	 * @throws EE_Error
418
+	 */
419
+	public function sold_and_reserved()
420
+	{
421
+		return $this->sold() + $this->reserved();
422
+	}
423
+
424
+
425
+	/**
426
+	 * returns the datetime name
427
+	 *
428
+	 * @return string
429
+	 * @throws ReflectionException
430
+	 * @throws InvalidArgumentException
431
+	 * @throws InvalidInterfaceException
432
+	 * @throws InvalidDataTypeException
433
+	 * @throws EE_Error
434
+	 */
435
+	public function name()
436
+	{
437
+		return $this->get('DTT_name');
438
+	}
439
+
440
+
441
+	/**
442
+	 * returns the datetime description
443
+	 *
444
+	 * @return string
445
+	 * @throws ReflectionException
446
+	 * @throws InvalidArgumentException
447
+	 * @throws InvalidInterfaceException
448
+	 * @throws InvalidDataTypeException
449
+	 * @throws EE_Error
450
+	 */
451
+	public function description()
452
+	{
453
+		return $this->get('DTT_description');
454
+	}
455
+
456
+
457
+	/**
458
+	 * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
459
+	 *
460
+	 * @return boolean  TRUE if is primary, FALSE if not.
461
+	 * @throws ReflectionException
462
+	 * @throws InvalidArgumentException
463
+	 * @throws InvalidInterfaceException
464
+	 * @throws InvalidDataTypeException
465
+	 * @throws EE_Error
466
+	 */
467
+	public function is_primary()
468
+	{
469
+		return $this->get('DTT_is_primary');
470
+	}
471
+
472
+
473
+	/**
474
+	 * This helper simply returns the order for the datetime
475
+	 *
476
+	 * @return int  The order of the datetime for this event.
477
+	 * @throws ReflectionException
478
+	 * @throws InvalidArgumentException
479
+	 * @throws InvalidInterfaceException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws EE_Error
482
+	 */
483
+	public function order()
484
+	{
485
+		return $this->get('DTT_order');
486
+	}
487
+
488
+
489
+	/**
490
+	 * This helper simply returns the parent id for the datetime
491
+	 *
492
+	 * @return int
493
+	 * @throws ReflectionException
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidInterfaceException
496
+	 * @throws InvalidDataTypeException
497
+	 * @throws EE_Error
498
+	 */
499
+	public function parent()
500
+	{
501
+		return $this->get('DTT_parent');
502
+	}
503
+
504
+
505
+	/**
506
+	 * show date and/or time
507
+	 *
508
+	 * @param string $date_or_time    whether to display a date or time or both
509
+	 * @param string $start_or_end    whether to display start or end datetimes
510
+	 * @param string $dt_frmt
511
+	 * @param string $tm_frmt
512
+	 * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
513
+	 *                                otherwise we use the standard formats)
514
+	 * @return string|bool  string on success, FALSE on fail
515
+	 * @throws ReflectionException
516
+	 * @throws InvalidArgumentException
517
+	 * @throws InvalidInterfaceException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws EE_Error
520
+	 */
521
+	private function _show_datetime(
522
+		$date_or_time = null,
523
+		$start_or_end = 'start',
524
+		$dt_frmt = '',
525
+		$tm_frmt = '',
526
+		$echo = false
527
+	) {
528
+		$field_name = "DTT_EVT_{$start_or_end}";
529
+		$dtt = $this->_get_datetime(
530
+			$field_name,
531
+			$dt_frmt,
532
+			$tm_frmt,
533
+			$date_or_time,
534
+			$echo
535
+		);
536
+		if (! $echo) {
537
+			return $dtt;
538
+		}
539
+		return '';
540
+	}
541
+
542
+
543
+	/**
544
+	 * get event start date.  Provide either the date format, or NULL to re-use the
545
+	 * last-used format, or '' to use the default date format
546
+	 *
547
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
548
+	 * @return mixed            string on success, FALSE on fail
549
+	 * @throws ReflectionException
550
+	 * @throws InvalidArgumentException
551
+	 * @throws InvalidInterfaceException
552
+	 * @throws InvalidDataTypeException
553
+	 * @throws EE_Error
554
+	 */
555
+	public function start_date($dt_frmt = '')
556
+	{
557
+		return $this->_show_datetime('D', 'start', $dt_frmt);
558
+	}
559
+
560
+
561
+	/**
562
+	 * Echoes start_date()
563
+	 *
564
+	 * @param string $dt_frmt
565
+	 * @throws ReflectionException
566
+	 * @throws InvalidArgumentException
567
+	 * @throws InvalidInterfaceException
568
+	 * @throws InvalidDataTypeException
569
+	 * @throws EE_Error
570
+	 */
571
+	public function e_start_date($dt_frmt = '')
572
+	{
573
+		$this->_show_datetime('D', 'start', $dt_frmt, null, true);
574
+	}
575
+
576
+
577
+	/**
578
+	 * get end date. Provide either the date format, or NULL to re-use the
579
+	 * last-used format, or '' to use the default date format
580
+	 *
581
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
582
+	 * @return mixed            string on success, FALSE on fail
583
+	 * @throws ReflectionException
584
+	 * @throws InvalidArgumentException
585
+	 * @throws InvalidInterfaceException
586
+	 * @throws InvalidDataTypeException
587
+	 * @throws EE_Error
588
+	 */
589
+	public function end_date($dt_frmt = '')
590
+	{
591
+		return $this->_show_datetime('D', 'end', $dt_frmt);
592
+	}
593
+
594
+
595
+	/**
596
+	 * Echoes the end date. See end_date()
597
+	 *
598
+	 * @param string $dt_frmt
599
+	 * @throws ReflectionException
600
+	 * @throws InvalidArgumentException
601
+	 * @throws InvalidInterfaceException
602
+	 * @throws InvalidDataTypeException
603
+	 * @throws EE_Error
604
+	 */
605
+	public function e_end_date($dt_frmt = '')
606
+	{
607
+		$this->_show_datetime('D', 'end', $dt_frmt, null, true);
608
+	}
609
+
610
+
611
+	/**
612
+	 * get date_range - meaning the start AND end date
613
+	 *
614
+	 * @access public
615
+	 * @param string $dt_frmt     string representation of date format defaults to WP settings
616
+	 * @param string $conjunction conjunction junction what's your function ?
617
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
618
+	 * @return mixed              string on success, FALSE on fail
619
+	 * @throws ReflectionException
620
+	 * @throws InvalidArgumentException
621
+	 * @throws InvalidInterfaceException
622
+	 * @throws InvalidDataTypeException
623
+	 * @throws EE_Error
624
+	 */
625
+	public function date_range($dt_frmt = '', $conjunction = ' - ')
626
+	{
627
+		$dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
628
+		$start = str_replace(
629
+			' ',
630
+			'&nbsp;',
631
+			$this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
632
+		);
633
+		$end = str_replace(
634
+			' ',
635
+			'&nbsp;',
636
+			$this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
637
+		);
638
+		return $start !== $end ? $start . $conjunction . $end : $start;
639
+	}
640
+
641
+
642
+	/**
643
+	 * @param string $dt_frmt
644
+	 * @param string $conjunction
645
+	 * @throws ReflectionException
646
+	 * @throws InvalidArgumentException
647
+	 * @throws InvalidInterfaceException
648
+	 * @throws InvalidDataTypeException
649
+	 * @throws EE_Error
650
+	 */
651
+	public function e_date_range($dt_frmt = '', $conjunction = ' - ')
652
+	{
653
+		echo $this->date_range($dt_frmt, $conjunction);
654
+	}
655
+
656
+
657
+	/**
658
+	 * get start time
659
+	 *
660
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
661
+	 * @return mixed        string on success, FALSE on fail
662
+	 * @throws ReflectionException
663
+	 * @throws InvalidArgumentException
664
+	 * @throws InvalidInterfaceException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws EE_Error
667
+	 */
668
+	public function start_time($tm_format = '')
669
+	{
670
+		return $this->_show_datetime('T', 'start', null, $tm_format);
671
+	}
672
+
673
+
674
+	/**
675
+	 * @param string $tm_format
676
+	 * @throws ReflectionException
677
+	 * @throws InvalidArgumentException
678
+	 * @throws InvalidInterfaceException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws EE_Error
681
+	 */
682
+	public function e_start_time($tm_format = '')
683
+	{
684
+		$this->_show_datetime('T', 'start', null, $tm_format, true);
685
+	}
686
+
687
+
688
+	/**
689
+	 * get end time
690
+	 *
691
+	 * @param string $tm_format string representation of time format defaults to 'g:i a'
692
+	 * @return mixed                string on success, FALSE on fail
693
+	 * @throws ReflectionException
694
+	 * @throws InvalidArgumentException
695
+	 * @throws InvalidInterfaceException
696
+	 * @throws InvalidDataTypeException
697
+	 * @throws EE_Error
698
+	 */
699
+	public function end_time($tm_format = '')
700
+	{
701
+		return $this->_show_datetime('T', 'end', null, $tm_format);
702
+	}
703
+
704
+
705
+	/**
706
+	 * @param string $tm_format
707
+	 * @throws ReflectionException
708
+	 * @throws InvalidArgumentException
709
+	 * @throws InvalidInterfaceException
710
+	 * @throws InvalidDataTypeException
711
+	 * @throws EE_Error
712
+	 */
713
+	public function e_end_time($tm_format = '')
714
+	{
715
+		$this->_show_datetime('T', 'end', null, $tm_format, true);
716
+	}
717
+
718
+
719
+	/**
720
+	 * get time_range
721
+	 *
722
+	 * @access public
723
+	 * @param string $tm_format   string representation of time format defaults to 'g:i a'
724
+	 * @param string $conjunction conjunction junction what's your function ?
725
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
726
+	 * @return mixed              string on success, FALSE on fail
727
+	 * @throws ReflectionException
728
+	 * @throws InvalidArgumentException
729
+	 * @throws InvalidInterfaceException
730
+	 * @throws InvalidDataTypeException
731
+	 * @throws EE_Error
732
+	 */
733
+	public function time_range($tm_format = '', $conjunction = ' - ')
734
+	{
735
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
736
+		$start = str_replace(
737
+			' ',
738
+			'&nbsp;',
739
+			$this->get_i18n_datetime('DTT_EVT_start', $tm_format)
740
+		);
741
+		$end = str_replace(
742
+			' ',
743
+			'&nbsp;',
744
+			$this->get_i18n_datetime('DTT_EVT_end', $tm_format)
745
+		);
746
+		return $start !== $end ? $start . $conjunction . $end : $start;
747
+	}
748
+
749
+
750
+	/**
751
+	 * @param string $tm_format
752
+	 * @param string $conjunction
753
+	 * @throws ReflectionException
754
+	 * @throws InvalidArgumentException
755
+	 * @throws InvalidInterfaceException
756
+	 * @throws InvalidDataTypeException
757
+	 * @throws EE_Error
758
+	 */
759
+	public function e_time_range($tm_format = '', $conjunction = ' - ')
760
+	{
761
+		echo $this->time_range($tm_format, $conjunction);
762
+	}
763
+
764
+
765
+	/**
766
+	 * This returns a range representation of the date and times.
767
+	 * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
768
+	 * Also, the return value is localized.
769
+	 *
770
+	 * @param string $dt_format
771
+	 * @param string $tm_format
772
+	 * @param string $conjunction used between two different dates or times.
773
+	 *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
774
+	 * @param string $separator   used between the date and time formats.
775
+	 *                            ex: Dec 1, 2016{$separator}2pm
776
+	 * @return string
777
+	 * @throws ReflectionException
778
+	 * @throws InvalidArgumentException
779
+	 * @throws InvalidInterfaceException
780
+	 * @throws InvalidDataTypeException
781
+	 * @throws EE_Error
782
+	 */
783
+	public function date_and_time_range(
784
+		$dt_format = '',
785
+		$tm_format = '',
786
+		$conjunction = ' - ',
787
+		$separator = ' '
788
+	) {
789
+		$dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
790
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
791
+		$full_format = $dt_format . $separator . $tm_format;
792
+		// the range output depends on various conditions
793
+		switch (true) {
794
+			// start date timestamp and end date timestamp are the same.
795
+			case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
796
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
797
+				break;
798
+			// start and end date are the same but times are different
799
+			case ($this->start_date() === $this->end_date()):
800
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
801
+						  . $conjunction
802
+						  . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
803
+				break;
804
+			// all other conditions
805
+			default:
806
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
807
+						  . $conjunction
808
+						  . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
809
+				break;
810
+		}
811
+		return $output;
812
+	}
813
+
814
+
815
+	/**
816
+	 * This echos the results of date and time range.
817
+	 *
818
+	 * @see date_and_time_range() for more details on purpose.
819
+	 * @param string $dt_format
820
+	 * @param string $tm_format
821
+	 * @param string $conjunction
822
+	 * @return void
823
+	 * @throws ReflectionException
824
+	 * @throws InvalidArgumentException
825
+	 * @throws InvalidInterfaceException
826
+	 * @throws InvalidDataTypeException
827
+	 * @throws EE_Error
828
+	 */
829
+	public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
830
+	{
831
+		echo $this->date_and_time_range($dt_format, $tm_format, $conjunction);
832
+	}
833
+
834
+
835
+	/**
836
+	 * get start date and start time
837
+	 *
838
+	 * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
839
+	 * @param    string $tm_format - string representation of time format defaults to 'g:i a'
840
+	 * @return    mixed    string on success, FALSE on fail
841
+	 * @throws ReflectionException
842
+	 * @throws InvalidArgumentException
843
+	 * @throws InvalidInterfaceException
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws EE_Error
846
+	 */
847
+	public function start_date_and_time($dt_format = '', $tm_format = '')
848
+	{
849
+		return $this->_show_datetime('', 'start', $dt_format, $tm_format);
850
+	}
851
+
852
+
853
+	/**
854
+	 * @param string $dt_frmt
855
+	 * @param string $tm_format
856
+	 * @throws ReflectionException
857
+	 * @throws InvalidArgumentException
858
+	 * @throws InvalidInterfaceException
859
+	 * @throws InvalidDataTypeException
860
+	 * @throws EE_Error
861
+	 */
862
+	public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
863
+	{
864
+		$this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
865
+	}
866
+
867
+
868
+	/**
869
+	 * Shows the length of the event (start to end time).
870
+	 * Can be shown in 'seconds','minutes','hours', or 'days'.
871
+	 * By default, rounds up. (So if you use 'days', and then event
872
+	 * only occurs for 1 hour, it will return 1 day).
873
+	 *
874
+	 * @param string $units 'seconds','minutes','hours','days'
875
+	 * @param bool   $round_up
876
+	 * @return float|int|mixed
877
+	 * @throws ReflectionException
878
+	 * @throws InvalidArgumentException
879
+	 * @throws InvalidInterfaceException
880
+	 * @throws InvalidDataTypeException
881
+	 * @throws EE_Error
882
+	 */
883
+	public function length($units = 'seconds', $round_up = false)
884
+	{
885
+		$start = $this->get_raw('DTT_EVT_start');
886
+		$end = $this->get_raw('DTT_EVT_end');
887
+		$length_in_units = $end - $start;
888
+		switch ($units) {
889
+			// NOTE: We purposefully don't use "break;" in order to chain the divisions
890
+			/** @noinspection PhpMissingBreakStatementInspection */
891
+			// phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
892
+			case 'days':
893
+				$length_in_units /= 24;
894
+			/** @noinspection PhpMissingBreakStatementInspection */
895
+			case 'hours':
896
+				// fall through is intentional
897
+				$length_in_units /= 60;
898
+			/** @noinspection PhpMissingBreakStatementInspection */
899
+			case 'minutes':
900
+				// fall through is intentional
901
+				$length_in_units /= 60;
902
+			case 'seconds':
903
+			default:
904
+				$length_in_units = ceil($length_in_units);
905
+		}
906
+		// phpcs:enable
907
+		if ($round_up) {
908
+			$length_in_units = max($length_in_units, 1);
909
+		}
910
+		return $length_in_units;
911
+	}
912
+
913
+
914
+	/**
915
+	 *        get end date and time
916
+	 *
917
+	 * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
918
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
919
+	 * @return    mixed                string on success, FALSE on fail
920
+	 * @throws ReflectionException
921
+	 * @throws InvalidArgumentException
922
+	 * @throws InvalidInterfaceException
923
+	 * @throws InvalidDataTypeException
924
+	 * @throws EE_Error
925
+	 */
926
+	public function end_date_and_time($dt_frmt = '', $tm_format = '')
927
+	{
928
+		return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
929
+	}
930
+
931
+
932
+	/**
933
+	 * @param string $dt_frmt
934
+	 * @param string $tm_format
935
+	 * @throws ReflectionException
936
+	 * @throws InvalidArgumentException
937
+	 * @throws InvalidInterfaceException
938
+	 * @throws InvalidDataTypeException
939
+	 * @throws EE_Error
940
+	 */
941
+	public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
942
+	{
943
+		$this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
944
+	}
945
+
946
+
947
+	/**
948
+	 *        get start timestamp
949
+	 *
950
+	 * @return        int
951
+	 * @throws ReflectionException
952
+	 * @throws InvalidArgumentException
953
+	 * @throws InvalidInterfaceException
954
+	 * @throws InvalidDataTypeException
955
+	 * @throws EE_Error
956
+	 */
957
+	public function start()
958
+	{
959
+		return $this->get_raw('DTT_EVT_start');
960
+	}
961
+
962
+
963
+	/**
964
+	 *        get end timestamp
965
+	 *
966
+	 * @return        int
967
+	 * @throws ReflectionException
968
+	 * @throws InvalidArgumentException
969
+	 * @throws InvalidInterfaceException
970
+	 * @throws InvalidDataTypeException
971
+	 * @throws EE_Error
972
+	 */
973
+	public function end()
974
+	{
975
+		return $this->get_raw('DTT_EVT_end');
976
+	}
977
+
978
+
979
+	/**
980
+	 *    get the registration limit for this datetime slot
981
+	 *
982
+	 * @return        mixed        int on success, FALSE on fail
983
+	 * @throws ReflectionException
984
+	 * @throws InvalidArgumentException
985
+	 * @throws InvalidInterfaceException
986
+	 * @throws InvalidDataTypeException
987
+	 * @throws EE_Error
988
+	 */
989
+	public function reg_limit()
990
+	{
991
+		return $this->get_raw('DTT_reg_limit');
992
+	}
993
+
994
+
995
+	/**
996
+	 *    have the tickets sold for this datetime, met or exceed the registration limit ?
997
+	 *
998
+	 * @return        boolean
999
+	 * @throws ReflectionException
1000
+	 * @throws InvalidArgumentException
1001
+	 * @throws InvalidInterfaceException
1002
+	 * @throws InvalidDataTypeException
1003
+	 * @throws EE_Error
1004
+	 */
1005
+	public function sold_out()
1006
+	{
1007
+		return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * return the total number of spaces remaining at this venue.
1013
+	 * This only takes the venue's capacity into account, NOT the tickets available for sale
1014
+	 *
1015
+	 * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1016
+	 *                               Because if all tickets attached to this datetime have no spaces left,
1017
+	 *                               then this datetime IS effectively sold out.
1018
+	 *                               However, there are cases where we just want to know the spaces
1019
+	 *                               remaining for this particular datetime, hence the flag.
1020
+	 * @return int
1021
+	 * @throws ReflectionException
1022
+	 * @throws InvalidArgumentException
1023
+	 * @throws InvalidInterfaceException
1024
+	 * @throws InvalidDataTypeException
1025
+	 * @throws EE_Error
1026
+	 */
1027
+	public function spaces_remaining($consider_tickets = false)
1028
+	{
1029
+		// tickets remaining available for purchase
1030
+		// no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1031
+		$dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1032
+		if (! $consider_tickets) {
1033
+			return $dtt_remaining;
1034
+		}
1035
+		$tickets_remaining = $this->tickets_remaining();
1036
+		return min($dtt_remaining, $tickets_remaining);
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 * Counts the total tickets available
1042
+	 * (from all the different types of tickets which are available for this datetime).
1043
+	 *
1044
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1045
+	 * @return int
1046
+	 * @throws ReflectionException
1047
+	 * @throws InvalidArgumentException
1048
+	 * @throws InvalidInterfaceException
1049
+	 * @throws InvalidDataTypeException
1050
+	 * @throws EE_Error
1051
+	 */
1052
+	public function tickets_remaining($query_params = array())
1053
+	{
1054
+		$sum = 0;
1055
+		$tickets = $this->tickets($query_params);
1056
+		if (! empty($tickets)) {
1057
+			foreach ($tickets as $ticket) {
1058
+				if ($ticket instanceof EE_Ticket) {
1059
+					// get the actual amount of tickets that can be sold
1060
+					$qty = $ticket->qty('saleable');
1061
+					if ($qty === EE_INF) {
1062
+						return EE_INF;
1063
+					}
1064
+					// no negative ticket quantities plz
1065
+					if ($qty > 0) {
1066
+						$sum += $qty;
1067
+					}
1068
+				}
1069
+			}
1070
+		}
1071
+		return $sum;
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * Gets the count of all the tickets available at this datetime (not ticket types)
1077
+	 * before any were sold
1078
+	 *
1079
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1080
+	 * @return int
1081
+	 * @throws ReflectionException
1082
+	 * @throws InvalidArgumentException
1083
+	 * @throws InvalidInterfaceException
1084
+	 * @throws InvalidDataTypeException
1085
+	 * @throws EE_Error
1086
+	 */
1087
+	public function sum_tickets_initially_available($query_params = array())
1088
+	{
1089
+		return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 * Returns the lesser-of-the two: spaces remaining at this datetime, or
1095
+	 * the total tickets remaining (a sum of the tickets remaining for each ticket type
1096
+	 * that is available for this datetime).
1097
+	 *
1098
+	 * @return int
1099
+	 * @throws ReflectionException
1100
+	 * @throws InvalidArgumentException
1101
+	 * @throws InvalidInterfaceException
1102
+	 * @throws InvalidDataTypeException
1103
+	 * @throws EE_Error
1104
+	 */
1105
+	public function total_tickets_available_at_this_datetime()
1106
+	{
1107
+		return $this->spaces_remaining(true);
1108
+	}
1109
+
1110
+
1111
+	/**
1112
+	 * This simply compares the internal dtt for the given string with NOW
1113
+	 * and determines if the date is upcoming or not.
1114
+	 *
1115
+	 * @access public
1116
+	 * @return boolean
1117
+	 * @throws ReflectionException
1118
+	 * @throws InvalidArgumentException
1119
+	 * @throws InvalidInterfaceException
1120
+	 * @throws InvalidDataTypeException
1121
+	 * @throws EE_Error
1122
+	 */
1123
+	public function is_upcoming()
1124
+	{
1125
+		return ($this->get_raw('DTT_EVT_start') > time());
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * This simply compares the internal datetime for the given string with NOW
1131
+	 * and returns if the date is active (i.e. start and end time)
1132
+	 *
1133
+	 * @return boolean
1134
+	 * @throws ReflectionException
1135
+	 * @throws InvalidArgumentException
1136
+	 * @throws InvalidInterfaceException
1137
+	 * @throws InvalidDataTypeException
1138
+	 * @throws EE_Error
1139
+	 */
1140
+	public function is_active()
1141
+	{
1142
+		return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1143
+	}
1144
+
1145
+
1146
+	/**
1147
+	 * This simply compares the internal dtt for the given string with NOW
1148
+	 * and determines if the date is expired or not.
1149
+	 *
1150
+	 * @return boolean
1151
+	 * @throws ReflectionException
1152
+	 * @throws InvalidArgumentException
1153
+	 * @throws InvalidInterfaceException
1154
+	 * @throws InvalidDataTypeException
1155
+	 * @throws EE_Error
1156
+	 */
1157
+	public function is_expired()
1158
+	{
1159
+		return ($this->get_raw('DTT_EVT_end') < time());
1160
+	}
1161
+
1162
+
1163
+	/**
1164
+	 * This returns the active status for whether an event is active, upcoming, or expired
1165
+	 *
1166
+	 * @return int return value will be one of the EE_Datetime status constants.
1167
+	 * @throws ReflectionException
1168
+	 * @throws InvalidArgumentException
1169
+	 * @throws InvalidInterfaceException
1170
+	 * @throws InvalidDataTypeException
1171
+	 * @throws EE_Error
1172
+	 */
1173
+	public function get_active_status()
1174
+	{
1175
+		$total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1176
+		if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1177
+			return EE_Datetime::sold_out;
1178
+		}
1179
+		if ($this->is_expired()) {
1180
+			return EE_Datetime::expired;
1181
+		}
1182
+		if ($this->is_upcoming()) {
1183
+			return EE_Datetime::upcoming;
1184
+		}
1185
+		if ($this->is_active()) {
1186
+			return EE_Datetime::active;
1187
+		}
1188
+		return null;
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1194
+	 *
1195
+	 * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1196
+	 * @return string
1197
+	 * @throws ReflectionException
1198
+	 * @throws InvalidArgumentException
1199
+	 * @throws InvalidInterfaceException
1200
+	 * @throws InvalidDataTypeException
1201
+	 * @throws EE_Error
1202
+	 */
1203
+	public function get_dtt_display_name($use_dtt_name = false)
1204
+	{
1205
+		if ($use_dtt_name) {
1206
+			$dtt_name = $this->name();
1207
+			if (! empty($dtt_name)) {
1208
+				return $dtt_name;
1209
+			}
1210
+		}
1211
+		// first condition is to see if the months are different
1212
+		if (
1213
+			date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1214
+		) {
1215
+			$display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1216
+			// next condition is if its the same month but different day
1217
+		} else {
1218
+			if (
1219
+				date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1220
+				&& date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1221
+			) {
1222
+				$display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1223
+			} else {
1224
+				$display_date = $this->start_date('F j\, Y')
1225
+								. ' @ '
1226
+								. $this->start_date('g:i a')
1227
+								. ' - '
1228
+								. $this->end_date('g:i a');
1229
+			}
1230
+		}
1231
+		return $display_date;
1232
+	}
1233
+
1234
+
1235
+	/**
1236
+	 * Gets all the tickets for this datetime
1237
+	 *
1238
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1239
+	 * @return EE_Base_Class[]|EE_Ticket[]
1240
+	 * @throws ReflectionException
1241
+	 * @throws InvalidArgumentException
1242
+	 * @throws InvalidInterfaceException
1243
+	 * @throws InvalidDataTypeException
1244
+	 * @throws EE_Error
1245
+	 */
1246
+	public function tickets($query_params = array())
1247
+	{
1248
+		return $this->get_many_related('Ticket', $query_params);
1249
+	}
1250
+
1251
+
1252
+	/**
1253
+	 * Gets all the ticket types currently available for purchase
1254
+	 *
1255
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1256
+	 * @return EE_Ticket[]
1257
+	 * @throws ReflectionException
1258
+	 * @throws InvalidArgumentException
1259
+	 * @throws InvalidInterfaceException
1260
+	 * @throws InvalidDataTypeException
1261
+	 * @throws EE_Error
1262
+	 */
1263
+	public function ticket_types_available_for_purchase($query_params = array())
1264
+	{
1265
+		// first check if datetime is valid
1266
+		if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1267
+			return array();
1268
+		}
1269
+		if (empty($query_params)) {
1270
+			$query_params = array(
1271
+				array(
1272
+					'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1273
+					'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1274
+					'TKT_deleted'    => false,
1275
+				),
1276
+			);
1277
+		}
1278
+		return $this->tickets($query_params);
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * @return EE_Base_Class|EE_Event
1284
+	 * @throws ReflectionException
1285
+	 * @throws InvalidArgumentException
1286
+	 * @throws InvalidInterfaceException
1287
+	 * @throws InvalidDataTypeException
1288
+	 * @throws EE_Error
1289
+	 */
1290
+	public function event()
1291
+	{
1292
+		return $this->get_first_related('Event');
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1298
+	 * (via the tickets).
1299
+	 *
1300
+	 * @return int
1301
+	 * @throws ReflectionException
1302
+	 * @throws InvalidArgumentException
1303
+	 * @throws InvalidInterfaceException
1304
+	 * @throws InvalidDataTypeException
1305
+	 * @throws EE_Error
1306
+	 */
1307
+	public function update_sold()
1308
+	{
1309
+		$count_regs_for_this_datetime = EEM_Registration::instance()->count(
1310
+			array(
1311
+				array(
1312
+					'STS_ID'                 => EEM_Registration::status_id_approved,
1313
+					'REG_deleted'            => 0,
1314
+					'Ticket.Datetime.DTT_ID' => $this->ID(),
1315
+				),
1316
+			)
1317
+		);
1318
+		$this->set_sold($count_regs_for_this_datetime);
1319
+		$this->save();
1320
+		return $count_regs_for_this_datetime;
1321
+	}
1322
+
1323
+
1324
+	/**
1325
+	 * Adds a venue to this event
1326
+	 *
1327
+	 * @param int|EE_Venue /int $venue_id_or_obj
1328
+	 * @return EE_Base_Class|EE_Venue
1329
+	 * @throws EE_Error
1330
+	 * @throws ReflectionException
1331
+	 */
1332
+	public function add_venue($venue_id_or_obj): EE_Venue
1333
+	{
1334
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 * Removes a venue from the event
1340
+	 *
1341
+	 * @param EE_Venue /int $venue_id_or_obj
1342
+	 * @return EE_Base_Class|EE_Venue
1343
+	 * @throws EE_Error
1344
+	 * @throws ReflectionException
1345
+	 */
1346
+	public function remove_venue($venue_id_or_obj): EE_Venue
1347
+	{
1348
+		$venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
1349
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Gets the venue related to the event. May provide additional $query_params if desired
1355
+	 *
1356
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1357
+	 * @return int
1358
+	 * @throws EE_Error
1359
+	 * @throws ReflectionException
1360
+	 */
1361
+	public function venue_ID(array $query_params = []): int
1362
+	{
1363
+		$venue = $this->get_first_related('Venue', $query_params);
1364
+		return $venue instanceof EE_Venue
1365
+			? $venue->ID()
1366
+			: 0;
1367
+	}
1368
+
1369
+
1370
+	/**
1371
+	 * Gets the venue related to the event. May provide additional $query_params if desired
1372
+	 *
1373
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1374
+	 * @return EE_Base_Class|EE_Venue
1375
+	 * @throws EE_Error
1376
+	 * @throws ReflectionException
1377
+	 */
1378
+	public function venue(array $query_params = [])
1379
+	{
1380
+		return $this->get_first_related('Venue', $query_params);
1381
+	}
1382
+
1383
+
1384
+	/**
1385
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1386
+	 * @param string                   $relationName
1387
+	 * @param array                    $extra_join_model_fields_n_values
1388
+	 * @param string|null              $cache_id
1389
+	 * @return EE_Base_Class
1390
+	 * @throws EE_Error
1391
+	 * @throws ReflectionException
1392
+	 * @since   $VID:$
1393
+	 */
1394
+	public function _add_relation_to(
1395
+		$otherObjectModelObjectOrID,
1396
+		$relationName,
1397
+		$extra_join_model_fields_n_values = [],
1398
+		$cache_id = null
1399
+	) {
1400
+		if ($relationName === 'Ticket') {
1401
+			/** @var EE_Ticket $ticket */
1402
+			$ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1403
+			$this->increaseSold($ticket->sold());
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') {
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 1445
      ***********************  DEPRECATED METHODS  **********************
1446 1446
      *******************************************************************/
1447 1447
 
1448 1448
 
1449
-    /**
1450
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
1451
-     *
1452
-     * @deprecated 4.9.80.p
1453
-     * @param int $qty
1454
-     * @return boolean
1455
-     * @throws ReflectionException
1456
-     * @throws InvalidArgumentException
1457
-     * @throws InvalidInterfaceException
1458
-     * @throws InvalidDataTypeException
1459
-     * @throws EE_Error
1460
-     */
1461
-    public function increase_sold($qty = 1)
1462
-    {
1463
-        EE_Error::doing_it_wrong(
1464
-            __FUNCTION__,
1465
-            esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1466
-            '4.9.80.p',
1467
-            '5.0.0.p'
1468
-        );
1469
-        return $this->increaseSold($qty);
1470
-    }
1471
-
1472
-
1473
-    /**
1474
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1475
-     * to save afterwards.)
1476
-     *
1477
-     * @deprecated 4.9.80.p
1478
-     * @param int $qty
1479
-     * @return boolean
1480
-     * @throws ReflectionException
1481
-     * @throws InvalidArgumentException
1482
-     * @throws InvalidInterfaceException
1483
-     * @throws InvalidDataTypeException
1484
-     * @throws EE_Error
1485
-     */
1486
-    public function decrease_sold($qty = 1)
1487
-    {
1488
-        EE_Error::doing_it_wrong(
1489
-            __FUNCTION__,
1490
-            esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1491
-            '4.9.80.p',
1492
-            '5.0.0.p'
1493
-        );
1494
-        return $this->decreaseSold($qty);
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1500
-     *
1501
-     * @deprecated 4.9.80.p
1502
-     * @param int $qty
1503
-     * @return boolean indicating success
1504
-     * @throws ReflectionException
1505
-     * @throws InvalidArgumentException
1506
-     * @throws InvalidInterfaceException
1507
-     * @throws InvalidDataTypeException
1508
-     * @throws EE_Error
1509
-     */
1510
-    public function increase_reserved($qty = 1)
1511
-    {
1512
-        EE_Error::doing_it_wrong(
1513
-            __FUNCTION__,
1514
-            esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1515
-            '4.9.80.p',
1516
-            '5.0.0.p'
1517
-        );
1518
-        return $this->increaseReserved($qty);
1519
-    }
1520
-
1521
-
1522
-    /**
1523
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1524
-     *
1525
-     * @deprecated 4.9.80.p
1526
-     * @param int $qty
1527
-     * @return boolean
1528
-     * @throws ReflectionException
1529
-     * @throws InvalidArgumentException
1530
-     * @throws InvalidInterfaceException
1531
-     * @throws InvalidDataTypeException
1532
-     * @throws EE_Error
1533
-     */
1534
-    public function decrease_reserved($qty = 1)
1535
-    {
1536
-        EE_Error::doing_it_wrong(
1537
-            __FUNCTION__,
1538
-            esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1539
-            '4.9.80.p',
1540
-            '5.0.0.p'
1541
-        );
1542
-        return $this->decreaseReserved($qty);
1543
-    }
1449
+	/**
1450
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
1451
+	 *
1452
+	 * @deprecated 4.9.80.p
1453
+	 * @param int $qty
1454
+	 * @return boolean
1455
+	 * @throws ReflectionException
1456
+	 * @throws InvalidArgumentException
1457
+	 * @throws InvalidInterfaceException
1458
+	 * @throws InvalidDataTypeException
1459
+	 * @throws EE_Error
1460
+	 */
1461
+	public function increase_sold($qty = 1)
1462
+	{
1463
+		EE_Error::doing_it_wrong(
1464
+			__FUNCTION__,
1465
+			esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1466
+			'4.9.80.p',
1467
+			'5.0.0.p'
1468
+		);
1469
+		return $this->increaseSold($qty);
1470
+	}
1471
+
1472
+
1473
+	/**
1474
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1475
+	 * to save afterwards.)
1476
+	 *
1477
+	 * @deprecated 4.9.80.p
1478
+	 * @param int $qty
1479
+	 * @return boolean
1480
+	 * @throws ReflectionException
1481
+	 * @throws InvalidArgumentException
1482
+	 * @throws InvalidInterfaceException
1483
+	 * @throws InvalidDataTypeException
1484
+	 * @throws EE_Error
1485
+	 */
1486
+	public function decrease_sold($qty = 1)
1487
+	{
1488
+		EE_Error::doing_it_wrong(
1489
+			__FUNCTION__,
1490
+			esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1491
+			'4.9.80.p',
1492
+			'5.0.0.p'
1493
+		);
1494
+		return $this->decreaseSold($qty);
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1500
+	 *
1501
+	 * @deprecated 4.9.80.p
1502
+	 * @param int $qty
1503
+	 * @return boolean indicating success
1504
+	 * @throws ReflectionException
1505
+	 * @throws InvalidArgumentException
1506
+	 * @throws InvalidInterfaceException
1507
+	 * @throws InvalidDataTypeException
1508
+	 * @throws EE_Error
1509
+	 */
1510
+	public function increase_reserved($qty = 1)
1511
+	{
1512
+		EE_Error::doing_it_wrong(
1513
+			__FUNCTION__,
1514
+			esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1515
+			'4.9.80.p',
1516
+			'5.0.0.p'
1517
+		);
1518
+		return $this->increaseReserved($qty);
1519
+	}
1520
+
1521
+
1522
+	/**
1523
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1524
+	 *
1525
+	 * @deprecated 4.9.80.p
1526
+	 * @param int $qty
1527
+	 * @return boolean
1528
+	 * @throws ReflectionException
1529
+	 * @throws InvalidArgumentException
1530
+	 * @throws InvalidInterfaceException
1531
+	 * @throws InvalidDataTypeException
1532
+	 * @throws EE_Error
1533
+	 */
1534
+	public function decrease_reserved($qty = 1)
1535
+	{
1536
+		EE_Error::doing_it_wrong(
1537
+			__FUNCTION__,
1538
+			esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1539
+			'4.9.80.p',
1540
+			'5.0.0.p'
1541
+		);
1542
+		return $this->decreaseReserved($qty);
1543
+	}
1544 1544
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Ticket.class.php 1 patch
Indentation   +2058 added lines, -2058 removed lines patch added patch discarded remove patch
@@ -14,2066 +14,2066 @@
 block discarded – undo
14 14
 class EE_Ticket extends EE_Soft_Delete_Base_Class implements EEI_Line_Item_Object, EEI_Event_Relation, EEI_Has_Icon
15 15
 {
16 16
 
17
-    /**
18
-     * TicKet Sold out:
19
-     * constant used by ticket_status() to indicate that a ticket is sold out
20
-     * and no longer available for purchases
21
-     */
22
-    const sold_out = 'TKS';
23
-
24
-    /**
25
-     * TicKet Expired:
26
-     * constant used by ticket_status() to indicate that a ticket is expired
27
-     * and no longer available for purchase
28
-     */
29
-    const expired = 'TKE';
30
-
31
-    /**
32
-     * TicKet Archived:
33
-     * constant used by ticket_status() to indicate that a ticket is archived
34
-     * and no longer available for purchase
35
-     */
36
-    const archived = 'TKA';
37
-
38
-    /**
39
-     * TicKet Pending:
40
-     * constant used by ticket_status() to indicate that a ticket is pending
41
-     * and is NOT YET available for purchase
42
-     */
43
-    const pending = 'TKP';
44
-
45
-    /**
46
-     * TicKet On sale:
47
-     * constant used by ticket_status() to indicate that a ticket is On Sale
48
-     * and IS available for purchase
49
-     */
50
-    const onsale = 'TKO';
51
-
52
-    /**
53
-     * extra meta key for tracking ticket reservations
54
-     *
55
-     * @type string
56
-     */
57
-    const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
58
-
59
-    /**
60
-     * override of parent property
61
-     *
62
-     * @var EEM_Ticket
63
-     */
64
-    protected $_model;
65
-
66
-    /**
67
-     * cached result from method of the same name
68
-     *
69
-     * @var float $_ticket_total_with_taxes
70
-     */
71
-    private $_ticket_total_with_taxes;
72
-
73
-
74
-    /**
75
-     * @param array  $props_n_values          incoming values
76
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
77
-     *                                        used.)
78
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
79
-     *                                        date_format and the second value is the time format
80
-     * @return EE_Ticket
81
-     * @throws EE_Error
82
-     * @throws ReflectionException
83
-     */
84
-    public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
85
-    {
86
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
87
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
88
-    }
89
-
90
-
91
-    /**
92
-     * @param array  $props_n_values  incoming values from the database
93
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
94
-     *                                the website will be used.
95
-     * @return EE_Ticket
96
-     * @throws EE_Error
97
-     * @throws ReflectionException
98
-     */
99
-    public static function new_instance_from_db($props_n_values = [], $timezone = null)
100
-    {
101
-        return new self($props_n_values, true, $timezone);
102
-    }
103
-
104
-
105
-    /**
106
-     * @return bool
107
-     * @throws EE_Error
108
-     * @throws ReflectionException
109
-     */
110
-    public function parent()
111
-    {
112
-        return $this->get('TKT_parent');
113
-    }
114
-
115
-
116
-    /**
117
-     * return if a ticket has quantities available for purchase
118
-     *
119
-     * @param int $DTT_ID the primary key for a particular datetime
120
-     * @return boolean
121
-     * @throws EE_Error
122
-     * @throws ReflectionException
123
-     */
124
-    public function available($DTT_ID = 0)
125
-    {
126
-        // are we checking availability for a particular datetime ?
127
-        if ($DTT_ID) {
128
-            // get that datetime object
129
-            $datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
130
-            // if  ticket sales for this datetime have exceeded the reg limit...
131
-            if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
132
-                return false;
133
-            }
134
-        }
135
-        // datetime is still open for registration, but is this ticket sold out ?
136
-        return $this->qty() < 1 || $this->qty() > $this->sold();
137
-    }
138
-
139
-
140
-    /**
141
-     * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
142
-     *
143
-     * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
144
-     *                               relevant status const
145
-     * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
146
-     *                               further processing
147
-     * @return mixed status int if the display string isn't requested
148
-     * @throws EE_Error
149
-     * @throws ReflectionException
150
-     */
151
-    public function ticket_status($display = false, $remaining = null)
152
-    {
153
-        $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
154
-        if (! $remaining) {
155
-            return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
156
-        }
157
-        if ($this->get('TKT_deleted')) {
158
-            return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
159
-        }
160
-        if ($this->is_expired()) {
161
-            return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
162
-        }
163
-        if ($this->is_pending()) {
164
-            return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
165
-        }
166
-        if ($this->is_on_sale()) {
167
-            return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
168
-        }
169
-        return '';
170
-    }
171
-
172
-
173
-    /**
174
-     * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
175
-     * considering ALL the factors used for figuring that out.
176
-     *
177
-     * @access public
178
-     * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
179
-     * @return boolean         true = tickets remaining, false not.
180
-     * @throws EE_Error
181
-     * @throws ReflectionException
182
-     */
183
-    public function is_remaining($DTT_ID = 0)
184
-    {
185
-        $num_remaining = $this->remaining($DTT_ID);
186
-        if ($num_remaining === 0) {
187
-            return false;
188
-        }
189
-        if ($num_remaining > 0 && $num_remaining < $this->min()) {
190
-            return false;
191
-        }
192
-        return true;
193
-    }
194
-
195
-
196
-    /**
197
-     * return the total number of tickets available for purchase
198
-     *
199
-     * @param int $DTT_ID  the primary key for a particular datetime.
200
-     *                     set to 0 for all related datetimes
201
-     * @return int
202
-     * @throws EE_Error
203
-     * @throws ReflectionException
204
-     */
205
-    public function remaining($DTT_ID = 0)
206
-    {
207
-        return $this->real_quantity_on_ticket('saleable', $DTT_ID);
208
-    }
209
-
210
-
211
-    /**
212
-     * Gets min
213
-     *
214
-     * @return int
215
-     * @throws EE_Error
216
-     * @throws ReflectionException
217
-     */
218
-    public function min()
219
-    {
220
-        return $this->get('TKT_min');
221
-    }
222
-
223
-
224
-    /**
225
-     * return if a ticket is no longer available cause its available dates have expired.
226
-     *
227
-     * @return boolean
228
-     * @throws EE_Error
229
-     * @throws ReflectionException
230
-     */
231
-    public function is_expired()
232
-    {
233
-        return ($this->get_raw('TKT_end_date') < time());
234
-    }
235
-
236
-
237
-    /**
238
-     * Return if a ticket is yet to go on sale or not
239
-     *
240
-     * @return boolean
241
-     * @throws EE_Error
242
-     * @throws ReflectionException
243
-     */
244
-    public function is_pending()
245
-    {
246
-        return ($this->get_raw('TKT_start_date') >= time());
247
-    }
248
-
249
-
250
-    /**
251
-     * Return if a ticket is on sale or not
252
-     *
253
-     * @return boolean
254
-     * @throws EE_Error
255
-     * @throws ReflectionException
256
-     */
257
-    public function is_on_sale()
258
-    {
259
-        return ($this->get_raw('TKT_start_date') <= time() && $this->get_raw('TKT_end_date') >= time());
260
-    }
261
-
262
-
263
-    /**
264
-     * This returns the chronologically last datetime that this ticket is associated with
265
-     *
266
-     * @param string $date_format
267
-     * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
268
-     *                            the end date ie: Jan 01 "to" Dec 31
269
-     * @return string
270
-     * @throws EE_Error
271
-     * @throws ReflectionException
272
-     */
273
-    public function date_range($date_format = '', $conjunction = ' - ')
274
-    {
275
-        $date_format = ! empty($date_format) ? $date_format : $this->_dt_frmt;
276
-        $first_date  = $this->first_datetime() instanceof EE_Datetime
277
-            ? $this->first_datetime()->get_i18n_datetime('DTT_EVT_start', $date_format)
278
-            : '';
279
-        $last_date   = $this->last_datetime() instanceof EE_Datetime
280
-            ? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format)
281
-            : '';
282
-
283
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
284
-    }
285
-
286
-
287
-    /**
288
-     * This returns the chronologically first datetime that this ticket is associated with
289
-     *
290
-     * @return EE_Datetime
291
-     * @throws EE_Error
292
-     * @throws ReflectionException
293
-     */
294
-    public function first_datetime()
295
-    {
296
-        $datetimes = $this->datetimes(['limit' => 1]);
297
-        return reset($datetimes);
298
-    }
299
-
300
-
301
-    /**
302
-     * Gets all the datetimes this ticket can be used for attending.
303
-     * Unless otherwise specified, orders datetimes by start date.
304
-     *
305
-     * @param array $query_params @see
306
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
307
-     * @return EE_Datetime[]|EE_Base_Class[]
308
-     * @throws EE_Error
309
-     * @throws ReflectionException
310
-     */
311
-    public function datetimes($query_params = [])
312
-    {
313
-        if (! isset($query_params['order_by'])) {
314
-            $query_params['order_by']['DTT_order'] = 'ASC';
315
-        }
316
-        return $this->get_many_related('Datetime', $query_params);
317
-    }
318
-
319
-
320
-    /**
321
-     * This returns the chronologically last datetime that this ticket is associated with
322
-     *
323
-     * @return EE_Datetime
324
-     * @throws EE_Error
325
-     * @throws ReflectionException
326
-     */
327
-    public function last_datetime()
328
-    {
329
-        $datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
330
-        return end($datetimes);
331
-    }
332
-
333
-
334
-    /**
335
-     * This returns the total tickets sold depending on the given parameters.
336
-     *
337
-     * @param string $what    Can be one of two options: 'ticket', 'datetime'.
338
-     *                        'ticket' = total ticket sales for all datetimes this ticket is related to
339
-     *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
340
-     *                        'datetime' = total ticket sales in the datetime_ticket table.
341
-     *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
342
-     *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
343
-     * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
344
-     * @return mixed (array|int)          how many tickets have sold
345
-     * @throws EE_Error
346
-     * @throws ReflectionException
347
-     */
348
-    public function tickets_sold($what = 'ticket', $dtt_id = null)
349
-    {
350
-        $total        = 0;
351
-        $tickets_sold = $this->_all_tickets_sold();
352
-        switch ($what) {
353
-            case 'ticket':
354
-                return $tickets_sold['ticket'];
355
-                break;
356
-            case 'datetime':
357
-                if (empty($tickets_sold['datetime'])) {
358
-                    return $total;
359
-                }
360
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
361
-                    EE_Error::add_error(
362
-                        __(
363
-                            'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
364
-                            'event_espresso'
365
-                        ),
366
-                        __FILE__,
367
-                        __FUNCTION__,
368
-                        __LINE__
369
-                    );
370
-                    return $total;
371
-                }
372
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
373
-                break;
374
-            default:
375
-                return $total;
376
-        }
377
-    }
378
-
379
-
380
-    /**
381
-     * This returns an array indexed by datetime_id for tickets sold with this ticket.
382
-     *
383
-     * @return EE_Ticket[]
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    protected function _all_tickets_sold()
388
-    {
389
-        $datetimes    = $this->get_many_related('Datetime');
390
-        $tickets_sold = [];
391
-        if (! empty($datetimes)) {
392
-            foreach ($datetimes as $datetime) {
393
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
394
-            }
395
-        }
396
-        // Tickets sold
397
-        $tickets_sold['ticket'] = $this->sold();
398
-        return $tickets_sold;
399
-    }
400
-
401
-
402
-    /**
403
-     * This returns the base price object for the ticket.
404
-     *
405
-     * @param bool $return_array whether to return as an array indexed by price id or just the object.
406
-     * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
407
-     * @throws EE_Error
408
-     * @throws ReflectionException
409
-     */
410
-    public function base_price($return_array = false)
411
-    {
412
-        $_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
413
-        return $return_array
414
-            ? $this->get_many_related('Price', [$_where])
415
-            : $this->get_first_related('Price', [$_where]);
416
-    }
417
-
418
-
419
-    /**
420
-     * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
421
-     *
422
-     * @access public
423
-     * @return EE_Price[]
424
-     * @throws EE_Error
425
-     * @throws ReflectionException
426
-     */
427
-    public function price_modifiers()
428
-    {
429
-        $query_params = [
430
-            0 => [
431
-                'Price_Type.PBT_ID' => [
432
-                    'NOT IN',
433
-                    [EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
434
-                ],
435
-            ],
436
-        ];
437
-        return $this->prices($query_params);
438
-    }
439
-
440
-
441
-    /**
442
-     * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
443
-     *
444
-     * @access public
445
-     * @return EE_Price[]
446
-     * @throws EE_Error
447
-     * @throws ReflectionException
448
-     */
449
-    public function tax_price_modifiers()
450
-    {
451
-        $query_params = [
452
-            0 => [
453
-                'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax,
454
-            ],
455
-        ];
456
-        return $this->prices($query_params);
457
-    }
458
-
459
-
460
-    /**
461
-     * Gets all the prices that combine to form the final price of this ticket
462
-     *
463
-     * @param array $query_params @see
464
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
465
-     * @return EE_Price[]|EE_Base_Class[]
466
-     * @throws EE_Error
467
-     * @throws ReflectionException
468
-     */
469
-    public function prices($query_params = [])
470
-    {
471
-        return $this->get_many_related('Price', $query_params);
472
-    }
473
-
474
-
475
-    /**
476
-     * Gets all the ticket datetimes (ie, relations between datetimes and tickets)
477
-     *
478
-     * @param array $query_params @see
479
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
480
-     * @return EE_Datetime_Ticket|EE_Base_Class[]
481
-     * @throws EE_Error
482
-     * @throws ReflectionException
483
-     */
484
-    public function datetime_tickets($query_params = [])
485
-    {
486
-        return $this->get_many_related('Datetime_Ticket', $query_params);
487
-    }
488
-
489
-
490
-    /**
491
-     * Gets all the datetimes from the db ordered by DTT_order
492
-     *
493
-     * @param boolean $show_expired
494
-     * @param boolean $show_deleted
495
-     * @return EE_Datetime[]
496
-     * @throws EE_Error
497
-     * @throws ReflectionException
498
-     */
499
-    public function datetimes_ordered($show_expired = true, $show_deleted = false)
500
-    {
501
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
502
-            $this->ID(),
503
-            $show_expired,
504
-            $show_deleted
505
-        );
506
-    }
507
-
508
-
509
-    /**
510
-     * Gets ID
511
-     *
512
-     * @return int
513
-     * @throws EE_Error
514
-     * @throws ReflectionException
515
-     */
516
-    public function ID()
517
-    {
518
-        return $this->get('TKT_ID');
519
-    }
520
-
521
-
522
-    /**
523
-     * get the author of the ticket.
524
-     *
525
-     * @return int
526
-     * @throws EE_Error
527
-     * @throws ReflectionException
528
-     * @since 4.5.0
529
-     */
530
-    public function wp_user()
531
-    {
532
-        return $this->get('TKT_wp_user');
533
-    }
534
-
535
-
536
-    /**
537
-     * Gets the template for the ticket
538
-     *
539
-     * @return EE_Ticket_Template|EE_Base_Class
540
-     * @throws EE_Error
541
-     * @throws ReflectionException
542
-     */
543
-    public function template()
544
-    {
545
-        return $this->get_first_related('Ticket_Template');
546
-    }
547
-
548
-
549
-    /**
550
-     * Simply returns an array of EE_Price objects that are taxes.
551
-     *
552
-     * @return EE_Price[]
553
-     * @throws EE_Error
554
-     */
555
-    public function get_ticket_taxes_for_admin()
556
-    {
557
-        return EE_Taxes::get_taxes_for_admin();
558
-    }
559
-
560
-
561
-    /**
562
-     * @return float
563
-     * @throws EE_Error
564
-     * @throws ReflectionException
565
-     */
566
-    public function ticket_price()
567
-    {
568
-        return $this->get('TKT_price');
569
-    }
570
-
571
-
572
-    /**
573
-     * @return mixed
574
-     * @throws EE_Error
575
-     * @throws ReflectionException
576
-     */
577
-    public function pretty_price()
578
-    {
579
-        return $this->get_pretty('TKT_price');
580
-    }
581
-
582
-
583
-    /**
584
-     * @return bool
585
-     * @throws EE_Error
586
-     * @throws ReflectionException
587
-     */
588
-    public function is_free()
589
-    {
590
-        return $this->get_ticket_total_with_taxes() === (float) 0;
591
-    }
592
-
593
-
594
-    /**
595
-     * get_ticket_total_with_taxes
596
-     *
597
-     * @param bool $no_cache
598
-     * @return float
599
-     * @throws EE_Error
600
-     * @throws ReflectionException
601
-     */
602
-    public function get_ticket_total_with_taxes($no_cache = false)
603
-    {
604
-        if ($this->_ticket_total_with_taxes === null || $no_cache) {
605
-            $this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
606
-        }
607
-        return (float) $this->_ticket_total_with_taxes;
608
-    }
609
-
610
-
611
-    /**
612
-     * @throws EE_Error
613
-     * @throws ReflectionException
614
-     */
615
-    public function ensure_TKT_Price_correct()
616
-    {
617
-        $this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
618
-        $this->save();
619
-    }
620
-
621
-
622
-    /**
623
-     * @return float
624
-     * @throws EE_Error
625
-     * @throws ReflectionException
626
-     */
627
-    public function get_ticket_subtotal()
628
-    {
629
-        return EE_Taxes::get_subtotal_for_admin($this);
630
-    }
631
-
632
-
633
-    /**
634
-     * Returns the total taxes applied to this ticket
635
-     *
636
-     * @return float
637
-     * @throws EE_Error
638
-     * @throws ReflectionException
639
-     */
640
-    public function get_ticket_taxes_total_for_admin()
641
-    {
642
-        return EE_Taxes::get_total_taxes_for_admin($this);
643
-    }
644
-
645
-
646
-    /**
647
-     * Sets name
648
-     *
649
-     * @param string $name
650
-     * @throws EE_Error
651
-     * @throws ReflectionException
652
-     */
653
-    public function set_name($name)
654
-    {
655
-        $this->set('TKT_name', $name);
656
-    }
657
-
658
-
659
-    /**
660
-     * Gets description
661
-     *
662
-     * @return string
663
-     * @throws EE_Error
664
-     * @throws ReflectionException
665
-     */
666
-    public function description()
667
-    {
668
-        return $this->get('TKT_description');
669
-    }
670
-
671
-
672
-    /**
673
-     * Sets description
674
-     *
675
-     * @param string $description
676
-     * @throws EE_Error
677
-     * @throws ReflectionException
678
-     */
679
-    public function set_description($description)
680
-    {
681
-        $this->set('TKT_description', $description);
682
-    }
683
-
684
-
685
-    /**
686
-     * Gets start_date
687
-     *
688
-     * @param string $date_format
689
-     * @param string $time_format
690
-     * @return string
691
-     * @throws EE_Error
692
-     * @throws ReflectionException
693
-     */
694
-    public function start_date($date_format = '', $time_format = '')
695
-    {
696
-        return $this->_get_datetime('TKT_start_date', $date_format, $time_format);
697
-    }
698
-
699
-
700
-    /**
701
-     * Sets start_date
702
-     *
703
-     * @param string $start_date
704
-     * @return void
705
-     * @throws EE_Error
706
-     * @throws ReflectionException
707
-     */
708
-    public function set_start_date($start_date)
709
-    {
710
-        $this->_set_date_time('B', $start_date, 'TKT_start_date');
711
-    }
712
-
713
-
714
-    /**
715
-     * Gets end_date
716
-     *
717
-     * @param string $date_format
718
-     * @param string $time_format
719
-     * @return string
720
-     * @throws EE_Error
721
-     * @throws ReflectionException
722
-     */
723
-    public function end_date($date_format = '', $time_format = '')
724
-    {
725
-        return $this->_get_datetime('TKT_end_date', $date_format, $time_format);
726
-    }
727
-
728
-
729
-    /**
730
-     * Sets end_date
731
-     *
732
-     * @param string $end_date
733
-     * @return void
734
-     * @throws EE_Error
735
-     * @throws ReflectionException
736
-     */
737
-    public function set_end_date($end_date)
738
-    {
739
-        $this->_set_date_time('B', $end_date, 'TKT_end_date');
740
-    }
741
-
742
-
743
-    /**
744
-     * Sets sell until time
745
-     *
746
-     * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
747
-     * @throws EE_Error
748
-     * @throws ReflectionException
749
-     * @since 4.5.0
750
-     */
751
-    public function set_end_time($time)
752
-    {
753
-        $this->_set_time_for($time, 'TKT_end_date');
754
-    }
755
-
756
-
757
-    /**
758
-     * Sets min
759
-     *
760
-     * @param int $min
761
-     * @return void
762
-     * @throws EE_Error
763
-     * @throws ReflectionException
764
-     */
765
-    public function set_min($min)
766
-    {
767
-        $this->set('TKT_min', $min);
768
-    }
769
-
770
-
771
-    /**
772
-     * Gets max
773
-     *
774
-     * @return int
775
-     * @throws EE_Error
776
-     * @throws ReflectionException
777
-     */
778
-    public function max()
779
-    {
780
-        return $this->get('TKT_max');
781
-    }
782
-
783
-
784
-    /**
785
-     * Sets max
786
-     *
787
-     * @param int $max
788
-     * @return void
789
-     * @throws EE_Error
790
-     * @throws ReflectionException
791
-     */
792
-    public function set_max($max)
793
-    {
794
-        $this->set('TKT_max', $max);
795
-    }
796
-
797
-
798
-    /**
799
-     * Sets price
800
-     *
801
-     * @param float $price
802
-     * @return void
803
-     * @throws EE_Error
804
-     * @throws ReflectionException
805
-     */
806
-    public function set_price($price)
807
-    {
808
-        $this->set('TKT_price', $price);
809
-    }
810
-
811
-
812
-    /**
813
-     * Gets sold
814
-     *
815
-     * @return int
816
-     * @throws EE_Error
817
-     * @throws ReflectionException
818
-     */
819
-    public function sold()
820
-    {
821
-        return $this->get_raw('TKT_sold');
822
-    }
823
-
824
-
825
-    /**
826
-     * Sets sold
827
-     *
828
-     * @param int $sold
829
-     * @return void
830
-     * @throws EE_Error
831
-     * @throws ReflectionException
832
-     */
833
-    public function set_sold($sold)
834
-    {
835
-        // sold can not go below zero
836
-        $sold = max(0, $sold);
837
-        $this->set('TKT_sold', $sold);
838
-    }
839
-
840
-
841
-    /**
842
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
843
-     * associated datetimes.
844
-     *
845
-     * @param int $qty
846
-     * @return boolean
847
-     * @throws EE_Error
848
-     * @throws InvalidArgumentException
849
-     * @throws InvalidDataTypeException
850
-     * @throws InvalidInterfaceException
851
-     * @throws ReflectionException
852
-     * @since 4.9.80.p
853
-     */
854
-    public function increaseSold($qty = 1)
855
-    {
856
-        $qty = absint($qty);
857
-        // increment sold and decrement reserved datetime quantities simultaneously
858
-        // don't worry about failures, because they must have already had a spot reserved
859
-        $this->increaseSoldForDatetimes($qty);
860
-        // Increment and decrement ticket quantities simultaneously
861
-        $success = $this->adjustNumericFieldsInDb(
862
-            [
863
-                'TKT_reserved' => $qty * -1,
864
-                'TKT_sold'     => $qty,
865
-            ]
866
-        );
867
-        do_action(
868
-            'AHEE__EE_Ticket__increase_sold',
869
-            $this,
870
-            $qty,
871
-            $this->sold(),
872
-            $success
873
-        );
874
-        return $success;
875
-    }
876
-
877
-
878
-    /**
879
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
880
-     *
881
-     * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
882
-     *                           counts), Negative means to decreases old counts (and increase reserved counts).
883
-     * @param EE_Datetime[] $datetimes
884
-     * @throws EE_Error
885
-     * @throws InvalidArgumentException
886
-     * @throws InvalidDataTypeException
887
-     * @throws InvalidInterfaceException
888
-     * @throws ReflectionException
889
-     * @since 4.9.80.p
890
-     */
891
-    protected function increaseSoldForDatetimes($qty, array $datetimes = [])
892
-    {
893
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
894
-        foreach ($datetimes as $datetime) {
895
-            $datetime->increaseSold($qty);
896
-        }
897
-    }
898
-
899
-
900
-    /**
901
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
902
-     * DB and then updates the model objects.
903
-     * Does not affect the reserved counts.
904
-     *
905
-     * @param int $qty
906
-     * @return boolean
907
-     * @throws EE_Error
908
-     * @throws InvalidArgumentException
909
-     * @throws InvalidDataTypeException
910
-     * @throws InvalidInterfaceException
911
-     * @throws ReflectionException
912
-     * @since 4.9.80.p
913
-     */
914
-    public function decreaseSold($qty = 1)
915
-    {
916
-        $qty = absint($qty);
917
-        $this->decreaseSoldForDatetimes($qty);
918
-        $success = $this->adjustNumericFieldsInDb(
919
-            [
920
-                'TKT_sold' => $qty * -1,
921
-            ]
922
-        );
923
-        do_action(
924
-            'AHEE__EE_Ticket__decrease_sold',
925
-            $this,
926
-            $qty,
927
-            $this->sold(),
928
-            $success
929
-        );
930
-        return $success;
931
-    }
932
-
933
-
934
-    /**
935
-     * Decreases sold on related datetimes
936
-     *
937
-     * @param int           $qty
938
-     * @param EE_Datetime[] $datetimes
939
-     * @return void
940
-     * @throws EE_Error
941
-     * @throws InvalidArgumentException
942
-     * @throws InvalidDataTypeException
943
-     * @throws InvalidInterfaceException
944
-     * @throws ReflectionException
945
-     * @since 4.9.80.p
946
-     */
947
-    protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
948
-    {
949
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
950
-        if (is_array($datetimes)) {
951
-            foreach ($datetimes as $datetime) {
952
-                if ($datetime instanceof EE_Datetime) {
953
-                    $datetime->decreaseSold($qty);
954
-                }
955
-            }
956
-        }
957
-    }
958
-
959
-
960
-    /**
961
-     * Gets qty of reserved tickets
962
-     *
963
-     * @return int
964
-     * @throws EE_Error
965
-     * @throws ReflectionException
966
-     */
967
-    public function reserved()
968
-    {
969
-        return $this->get_raw('TKT_reserved');
970
-    }
971
-
972
-
973
-    /**
974
-     * Sets reserved
975
-     *
976
-     * @param int $reserved
977
-     * @return void
978
-     * @throws EE_Error
979
-     * @throws ReflectionException
980
-     */
981
-    public function set_reserved($reserved)
982
-    {
983
-        // reserved can not go below zero
984
-        $reserved = max(0, (int) $reserved);
985
-        $this->set('TKT_reserved', $reserved);
986
-    }
987
-
988
-
989
-    /**
990
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
991
-     *
992
-     * @param int    $qty
993
-     * @param string $source
994
-     * @return bool whether we successfully reserved the ticket or not.
995
-     * @throws EE_Error
996
-     * @throws InvalidArgumentException
997
-     * @throws ReflectionException
998
-     * @throws InvalidDataTypeException
999
-     * @throws InvalidInterfaceException
1000
-     * @since 4.9.80.p
1001
-     */
1002
-    public function increaseReserved($qty = 1, $source = 'unknown')
1003
-    {
1004
-        $qty = absint($qty);
1005
-        do_action(
1006
-            'AHEE__EE_Ticket__increase_reserved__begin',
1007
-            $this,
1008
-            $qty,
1009
-            $source
1010
-        );
1011
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
1012
-        $success                         = false;
1013
-        $datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
1014
-        if ($datetimes_adjusted_successfully) {
1015
-            $success = $this->incrementFieldConditionallyInDb(
1016
-                'TKT_reserved',
1017
-                'TKT_sold',
1018
-                'TKT_qty',
1019
-                $qty
1020
-            );
1021
-            if (! $success) {
1022
-                // The datetimes were successfully bumped, but not the
1023
-                // ticket. So we need to manually rollback the datetimes.
1024
-                $this->decreaseReservedForDatetimes($qty);
1025
-            }
1026
-        }
1027
-        do_action(
1028
-            'AHEE__EE_Ticket__increase_reserved',
1029
-            $this,
1030
-            $qty,
1031
-            $this->reserved(),
1032
-            $success
1033
-        );
1034
-        return $success;
1035
-    }
1036
-
1037
-
1038
-    /**
1039
-     * Increases reserved counts on related datetimes
1040
-     *
1041
-     * @param int           $qty
1042
-     * @param EE_Datetime[] $datetimes
1043
-     * @return boolean indicating success
1044
-     * @throws EE_Error
1045
-     * @throws InvalidArgumentException
1046
-     * @throws InvalidDataTypeException
1047
-     * @throws InvalidInterfaceException
1048
-     * @throws ReflectionException
1049
-     * @since 4.9.80.p
1050
-     */
1051
-    protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1052
-    {
1053
-        $datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1054
-        $datetimes_updated = [];
1055
-        $limit_exceeded    = false;
1056
-        if (is_array($datetimes)) {
1057
-            foreach ($datetimes as $datetime) {
1058
-                if ($datetime instanceof EE_Datetime) {
1059
-                    if ($datetime->increaseReserved($qty)) {
1060
-                        $datetimes_updated[] = $datetime;
1061
-                    } else {
1062
-                        $limit_exceeded = true;
1063
-                        break;
1064
-                    }
1065
-                }
1066
-            }
1067
-            // If somewhere along the way we detected a datetime whose
1068
-            // limit was exceeded, do a manual rollback.
1069
-            if ($limit_exceeded) {
1070
-                $this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1071
-                return false;
1072
-            }
1073
-        }
1074
-        return true;
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1080
-     *
1081
-     * @param int    $qty
1082
-     * @param bool   $adjust_datetimes
1083
-     * @param string $source
1084
-     * @return boolean
1085
-     * @throws EE_Error
1086
-     * @throws InvalidArgumentException
1087
-     * @throws ReflectionException
1088
-     * @throws InvalidDataTypeException
1089
-     * @throws InvalidInterfaceException
1090
-     * @since 4.9.80.p
1091
-     */
1092
-    public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1093
-    {
1094
-        $qty = absint($qty);
1095
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1096
-        if ($adjust_datetimes) {
1097
-            $this->decreaseReservedForDatetimes($qty);
1098
-        }
1099
-        $success = $this->adjustNumericFieldsInDb(
1100
-            [
1101
-                'TKT_reserved' => $qty * -1,
1102
-            ]
1103
-        );
1104
-        do_action(
1105
-            'AHEE__EE_Ticket__decrease_reserved',
1106
-            $this,
1107
-            $qty,
1108
-            $this->reserved(),
1109
-            $success
1110
-        );
1111
-        return $success;
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * Decreases the reserved count on the specified datetimes.
1117
-     *
1118
-     * @param int           $qty
1119
-     * @param EE_Datetime[] $datetimes
1120
-     * @throws EE_Error
1121
-     * @throws InvalidArgumentException
1122
-     * @throws ReflectionException
1123
-     * @throws InvalidDataTypeException
1124
-     * @throws InvalidInterfaceException
1125
-     * @since 4.9.80.p
1126
-     */
1127
-    protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1128
-    {
1129
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1130
-        foreach ($datetimes as $datetime) {
1131
-            if ($datetime instanceof EE_Datetime) {
1132
-                $datetime->decreaseReserved($qty);
1133
-            }
1134
-        }
1135
-    }
1136
-
1137
-
1138
-    /**
1139
-     * Gets ticket quantity
1140
-     *
1141
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1142
-     *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1143
-     *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1144
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1145
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1146
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1147
-     * @return int
1148
-     * @throws EE_Error
1149
-     * @throws ReflectionException
1150
-     */
1151
-    public function qty($context = '')
1152
-    {
1153
-        switch ($context) {
1154
-            case 'reg_limit':
1155
-                return $this->real_quantity_on_ticket();
1156
-            case 'saleable':
1157
-                return $this->real_quantity_on_ticket('saleable');
1158
-            default:
1159
-                return $this->get_raw('TKT_qty');
1160
-        }
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Gets ticket quantity
1166
-     *
1167
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1168
-     *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1169
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1170
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1171
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1172
-     * @param int    $DTT_ID      the primary key for a particular datetime.
1173
-     *                            set to 0 for all related datetimes
1174
-     * @return int
1175
-     * @throws EE_Error
1176
-     * @throws ReflectionException
1177
-     */
1178
-    public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1179
-    {
1180
-        $raw = $this->get_raw('TKT_qty');
1181
-        // return immediately if it's zero
1182
-        if ($raw === 0) {
1183
-            return $raw;
1184
-        }
1185
-        // echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1186
-        // ensure qty doesn't exceed raw value for THIS ticket
1187
-        $qty = min(EE_INF, $raw);
1188
-        // echo "\n . qty: " . $qty . '<br />';
1189
-        // calculate this ticket's total sales and reservations
1190
-        $sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1191
-        // echo "\n . sold: " . $this->sold() . '<br />';
1192
-        // echo "\n . reserved: " . $this->reserved() . '<br />';
1193
-        // echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1194
-        // first we need to calculate the maximum number of tickets available for the datetime
1195
-        // do we want data for one datetime or all of them ?
1196
-        $query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1197
-        $datetimes    = $this->datetimes($query_params);
1198
-        if (is_array($datetimes) && ! empty($datetimes)) {
1199
-            foreach ($datetimes as $datetime) {
1200
-                if ($datetime instanceof EE_Datetime) {
1201
-                    $datetime->refresh_from_db();
1202
-                    // echo "\n . . datetime name: " . $datetime->name() . '<br />';
1203
-                    // echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1204
-                    // initialize with no restrictions for each datetime
1205
-                    // but adjust datetime qty based on datetime reg limit
1206
-                    $datetime_qty = min(EE_INF, $datetime->reg_limit());
1207
-                    // echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1208
-                    // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1209
-                    // if we want the actual saleable amount, then we need to consider OTHER ticket sales
1210
-                    // and reservations for this datetime, that do NOT include sales and reservations
1211
-                    // for this ticket (so we add $this->sold() and $this->reserved() back in)
1212
-                    if ($context === 'saleable') {
1213
-                        $datetime_qty = max(
1214
-                            $datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1215
-                            0
1216
-                        );
1217
-                        // echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1218
-                        // echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1219
-                        // echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1220
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1221
-                        $datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1222
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1223
-                    }
1224
-                    $qty = min($datetime_qty, $qty);
1225
-                    // echo "\n . . qty: " . $qty . '<br />';
1226
-                }
1227
-            }
1228
-        }
1229
-        // NOW that we know the  maximum number of tickets available for the datetime
1230
-        // we can finally factor in the details for this specific ticket
1231
-        if ($qty > 0 && $context === 'saleable') {
1232
-            // and subtract the sales for THIS ticket
1233
-            $qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1234
-            // echo "\n . qty: " . $qty . '<br />';
1235
-        }
1236
-        // echo "\nFINAL QTY: " . $qty . "<br /><br />";
1237
-        return $qty;
1238
-    }
1239
-
1240
-
1241
-    /**
1242
-     * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1243
-     *
1244
-     * @param int $qty
1245
-     * @return void
1246
-     * @throws EE_Error
1247
-     * @throws ReflectionException
1248
-     */
1249
-    public function set_qty($qty)
1250
-    {
1251
-        $datetimes = $this->datetimes();
1252
-        foreach ($datetimes as $datetime) {
1253
-            if ($datetime instanceof EE_Datetime) {
1254
-                $qty = min($qty, $datetime->reg_limit());
1255
-            }
1256
-        }
1257
-        $this->set('TKT_qty', $qty);
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * Gets uses
1263
-     *
1264
-     * @return int
1265
-     * @throws EE_Error
1266
-     * @throws ReflectionException
1267
-     */
1268
-    public function uses()
1269
-    {
1270
-        return $this->get('TKT_uses');
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * Sets uses
1276
-     *
1277
-     * @param int $uses
1278
-     * @return void
1279
-     * @throws EE_Error
1280
-     * @throws ReflectionException
1281
-     */
1282
-    public function set_uses($uses)
1283
-    {
1284
-        $this->set('TKT_uses', $uses);
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     * returns whether ticket is required or not.
1290
-     *
1291
-     * @return boolean
1292
-     * @throws EE_Error
1293
-     * @throws ReflectionException
1294
-     */
1295
-    public function required()
1296
-    {
1297
-        return $this->get('TKT_required');
1298
-    }
1299
-
1300
-
1301
-    /**
1302
-     * sets the TKT_required property
1303
-     *
1304
-     * @param boolean $required
1305
-     * @return void
1306
-     * @throws EE_Error
1307
-     * @throws ReflectionException
1308
-     */
1309
-    public function set_required($required)
1310
-    {
1311
-        $this->set('TKT_required', $required);
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * Gets taxable
1317
-     *
1318
-     * @return boolean
1319
-     * @throws EE_Error
1320
-     * @throws ReflectionException
1321
-     */
1322
-    public function taxable()
1323
-    {
1324
-        return $this->get('TKT_taxable');
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Sets taxable
1330
-     *
1331
-     * @param boolean $taxable
1332
-     * @return void
1333
-     * @throws EE_Error
1334
-     * @throws ReflectionException
1335
-     */
1336
-    public function set_taxable($taxable)
1337
-    {
1338
-        $this->set('TKT_taxable', $taxable);
1339
-    }
1340
-
1341
-
1342
-    /**
1343
-     * Gets is_default
1344
-     *
1345
-     * @return boolean
1346
-     * @throws EE_Error
1347
-     * @throws ReflectionException
1348
-     */
1349
-    public function is_default()
1350
-    {
1351
-        return $this->get('TKT_is_default');
1352
-    }
1353
-
1354
-
1355
-    /**
1356
-     * Sets is_default
1357
-     *
1358
-     * @param boolean $is_default
1359
-     * @return void
1360
-     * @throws EE_Error
1361
-     * @throws ReflectionException
1362
-     */
1363
-    public function set_is_default($is_default)
1364
-    {
1365
-        $this->set('TKT_is_default', $is_default);
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     * Gets order
1371
-     *
1372
-     * @return int
1373
-     * @throws EE_Error
1374
-     * @throws ReflectionException
1375
-     */
1376
-    public function order()
1377
-    {
1378
-        return $this->get('TKT_order');
1379
-    }
1380
-
1381
-
1382
-    /**
1383
-     * Sets order
1384
-     *
1385
-     * @param int $order
1386
-     * @return void
1387
-     * @throws EE_Error
1388
-     * @throws ReflectionException
1389
-     */
1390
-    public function set_order($order)
1391
-    {
1392
-        $this->set('TKT_order', $order);
1393
-    }
1394
-
1395
-
1396
-    /**
1397
-     * Gets row
1398
-     *
1399
-     * @return int
1400
-     * @throws EE_Error
1401
-     * @throws ReflectionException
1402
-     */
1403
-    public function row()
1404
-    {
1405
-        return $this->get('TKT_row');
1406
-    }
1407
-
1408
-
1409
-    /**
1410
-     * Sets row
1411
-     *
1412
-     * @param int $row
1413
-     * @return void
1414
-     * @throws EE_Error
1415
-     * @throws ReflectionException
1416
-     */
1417
-    public function set_row($row)
1418
-    {
1419
-        $this->set('TKT_row', $row);
1420
-    }
1421
-
1422
-
1423
-    /**
1424
-     * Gets deleted
1425
-     *
1426
-     * @return boolean
1427
-     * @throws EE_Error
1428
-     * @throws ReflectionException
1429
-     */
1430
-    public function deleted()
1431
-    {
1432
-        return $this->get('TKT_deleted');
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * Sets deleted
1438
-     *
1439
-     * @param boolean $deleted
1440
-     * @return void
1441
-     * @throws EE_Error
1442
-     * @throws ReflectionException
1443
-     */
1444
-    public function set_deleted($deleted)
1445
-    {
1446
-        $this->set('TKT_deleted', $deleted);
1447
-    }
1448
-
1449
-
1450
-    /**
1451
-     * Gets parent
1452
-     *
1453
-     * @return int
1454
-     * @throws EE_Error
1455
-     * @throws ReflectionException
1456
-     */
1457
-    public function parent_ID()
1458
-    {
1459
-        return $this->get('TKT_parent');
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * Sets parent
1465
-     *
1466
-     * @param int $parent
1467
-     * @return void
1468
-     * @throws EE_Error
1469
-     * @throws ReflectionException
1470
-     */
1471
-    public function set_parent_ID($parent)
1472
-    {
1473
-        $this->set('TKT_parent', $parent);
1474
-    }
1475
-
1476
-
1477
-    /**
1478
-     * @return boolean
1479
-     * @throws EE_Error
1480
-     * @throws InvalidArgumentException
1481
-     * @throws InvalidDataTypeException
1482
-     * @throws InvalidInterfaceException
1483
-     * @throws ReflectionException
1484
-     */
1485
-    public function reverse_calculate()
1486
-    {
1487
-        return $this->get('TKT_reverse_calculate');
1488
-    }
1489
-
1490
-
1491
-    /**
1492
-     * @param boolean $reverse_calculate
1493
-     * @throws EE_Error
1494
-     * @throws InvalidArgumentException
1495
-     * @throws InvalidDataTypeException
1496
-     * @throws InvalidInterfaceException
1497
-     * @throws ReflectionException
1498
-     */
1499
-    public function set_reverse_calculate($reverse_calculate)
1500
-    {
1501
-        $this->set('TKT_reverse_calculate', $reverse_calculate);
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * Gets a string which is handy for showing in gateways etc that describes the ticket.
1507
-     *
1508
-     * @return string
1509
-     * @throws EE_Error
1510
-     * @throws ReflectionException
1511
-     */
1512
-    public function name_and_info()
1513
-    {
1514
-        $times = [];
1515
-        foreach ($this->datetimes() as $datetime) {
1516
-            $times[] = $datetime->start_date_and_time();
1517
-        }
1518
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1519
-    }
1520
-
1521
-
1522
-    /**
1523
-     * Gets name
1524
-     *
1525
-     * @return string
1526
-     * @throws EE_Error
1527
-     * @throws ReflectionException
1528
-     */
1529
-    public function name()
1530
-    {
1531
-        return $this->get('TKT_name');
1532
-    }
1533
-
1534
-
1535
-    /**
1536
-     * Gets price
1537
-     *
1538
-     * @return float
1539
-     * @throws EE_Error
1540
-     * @throws ReflectionException
1541
-     */
1542
-    public function price()
1543
-    {
1544
-        return $this->get('TKT_price');
1545
-    }
1546
-
1547
-
1548
-    /**
1549
-     * Gets all the registrations for this ticket
1550
-     *
1551
-     * @param array $query_params @see
1552
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1553
-     * @return EE_Registration[]|EE_Base_Class[]
1554
-     * @throws EE_Error
1555
-     * @throws ReflectionException
1556
-     */
1557
-    public function registrations($query_params = [])
1558
-    {
1559
-        return $this->get_many_related('Registration', $query_params);
1560
-    }
1561
-
1562
-
1563
-    /**
1564
-     * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1565
-     *
1566
-     * @return int
1567
-     * @throws EE_Error
1568
-     * @throws ReflectionException
1569
-     */
1570
-    public function update_tickets_sold()
1571
-    {
1572
-        $count_regs_for_this_ticket = $this->count_registrations(
1573
-            [
1574
-                [
1575
-                    'STS_ID'      => EEM_Registration::status_id_approved,
1576
-                    'REG_deleted' => 0,
1577
-                ],
1578
-            ]
1579
-        );
1580
-        $this->set_sold($count_regs_for_this_ticket);
1581
-        $this->save();
1582
-        return $count_regs_for_this_ticket;
1583
-    }
1584
-
1585
-
1586
-    /**
1587
-     * Counts the registrations for this ticket
1588
-     *
1589
-     * @param array $query_params @see
1590
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1591
-     * @return int
1592
-     * @throws EE_Error
1593
-     * @throws ReflectionException
1594
-     */
1595
-    public function count_registrations($query_params = [])
1596
-    {
1597
-        return $this->count_related('Registration', $query_params);
1598
-    }
1599
-
1600
-
1601
-    /**
1602
-     * Implementation for EEI_Has_Icon interface method.
1603
-     *
1604
-     * @return string
1605
-     * @see EEI_Visual_Representation for comments
1606
-     */
1607
-    public function get_icon()
1608
-    {
1609
-        return '<span class="dashicons dashicons-tickets-alt"/>';
1610
-    }
1611
-
1612
-
1613
-    /**
1614
-     * Implementation of the EEI_Event_Relation interface method
1615
-     *
1616
-     * @return EE_Event
1617
-     * @throws EE_Error
1618
-     * @throws UnexpectedEntityException
1619
-     * @throws ReflectionException
1620
-     * @see EEI_Event_Relation for comments
1621
-     */
1622
-    public function get_related_event()
1623
-    {
1624
-        // get one datetime to use for getting the event
1625
-        $datetime = $this->first_datetime();
1626
-        if (! $datetime instanceof EE_Datetime) {
1627
-            throw new UnexpectedEntityException(
1628
-                $datetime,
1629
-                'EE_Datetime',
1630
-                sprintf(
1631
-                    __('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1632
-                    $this->name()
1633
-                )
1634
-            );
1635
-        }
1636
-        $event = $datetime->event();
1637
-        if (! $event instanceof EE_Event) {
1638
-            throw new UnexpectedEntityException(
1639
-                $event,
1640
-                'EE_Event',
1641
-                sprintf(
1642
-                    __('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1643
-                    $this->name()
1644
-                )
1645
-            );
1646
-        }
1647
-        return $event;
1648
-    }
1649
-
1650
-
1651
-    /**
1652
-     * Implementation of the EEI_Event_Relation interface method
1653
-     *
1654
-     * @return string
1655
-     * @throws UnexpectedEntityException
1656
-     * @throws EE_Error
1657
-     * @throws ReflectionException
1658
-     * @see EEI_Event_Relation for comments
1659
-     */
1660
-    public function get_event_name()
1661
-    {
1662
-        $event = $this->get_related_event();
1663
-        return $event instanceof EE_Event ? $event->name() : '';
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     * Implementation of the EEI_Event_Relation interface method
1669
-     *
1670
-     * @return int
1671
-     * @throws UnexpectedEntityException
1672
-     * @throws EE_Error
1673
-     * @throws ReflectionException
1674
-     * @see EEI_Event_Relation for comments
1675
-     */
1676
-    public function get_event_ID()
1677
-    {
1678
-        $event = $this->get_related_event();
1679
-        return $event instanceof EE_Event ? $event->ID() : 0;
1680
-    }
1681
-
1682
-
1683
-    /**
1684
-     * This simply returns whether a ticket can be permanently deleted or not.
1685
-     * The criteria for determining this is whether the ticket has any related registrations.
1686
-     * If there are none then it can be permanently deleted.
1687
-     *
1688
-     * @return bool
1689
-     * @throws EE_Error
1690
-     * @throws ReflectionException
1691
-     */
1692
-    public function is_permanently_deleteable()
1693
-    {
1694
-        return $this->count_registrations() === 0;
1695
-    }
1696
-
1697
-
1698
-    /**
1699
-     * @return int
1700
-     * @throws EE_Error
1701
-     * @throws ReflectionException
1702
-     * @since   $VID:$
1703
-     */
1704
-    public function visibility(): int
1705
-    {
1706
-        return $this->get('TKT_visibility');
1707
-    }
1708
-
1709
-
1710
-    /**
1711
-     * @return int
1712
-     * @throws EE_Error
1713
-     * @throws ReflectionException
1714
-     * @since   $VID:$
1715
-     */
1716
-    public function isHidden(): int
1717
-    {
1718
-        return $this->visibility() === EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1719
-    }
1720
-
1721
-
1722
-    /**
1723
-     * @return int
1724
-     * @throws EE_Error
1725
-     * @throws ReflectionException
1726
-     * @since   $VID:$
1727
-     */
1728
-    public function isNotHidden(): int
1729
-    {
1730
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1731
-    }
1732
-
1733
-
1734
-    /**
1735
-     * @return int
1736
-     * @throws EE_Error
1737
-     * @throws ReflectionException
1738
-     * @since   $VID:$
1739
-     */
1740
-    public function isPublicOnly(): int
1741
-    {
1742
-        return $this->isNotHidden() && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE;
1743
-    }
1744
-
1745
-
1746
-    /**
1747
-     * @return int
1748
-     * @throws EE_Error
1749
-     * @throws ReflectionException
1750
-     * @since   $VID:$
1751
-     */
1752
-    public function isMembersOnly(): int
1753
-    {
1754
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE
1755
-               && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE;
1756
-    }
1757
-
1758
-
1759
-    /**
1760
-     * @return int
1761
-     * @throws EE_Error
1762
-     * @throws ReflectionException
1763
-     * @since   $VID:$
1764
-     */
1765
-    public function isAdminsOnly(): int
1766
-    {
1767
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE
1768
-               && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE;
1769
-    }
1770
-
1771
-
1772
-    /**
1773
-     * @return int
1774
-     * @throws EE_Error
1775
-     * @throws ReflectionException
1776
-     * @since   $VID:$
1777
-     */
1778
-    public function isAdminUiOnly(): int
1779
-    {
1780
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE
1781
-               && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMIN_UI_ONLY_VALUE;
1782
-    }
1783
-
1784
-
1785
-    /**
1786
-     * @param int $visibility
1787
-     * @throws EE_Error
1788
-     * @throws ReflectionException
1789
-     * @since   $VID:$
1790
-     */
1791
-    public function set_visibility(int $visibility)
1792
-    {
1793
-
1794
-        $ticket_visibility_options = $this->_model->ticketVisibilityOptions();
1795
-        $ticket_visibility         = -1;
1796
-        foreach ($ticket_visibility_options as $ticket_visibility_option) {
1797
-            if ($visibility === $ticket_visibility_option) {
1798
-                $ticket_visibility = $visibility;
1799
-            }
1800
-        }
1801
-        if ($ticket_visibility === -1) {
1802
-            throw new DomainException(
1803
-                sprintf(
1804
-                    esc_html__(
1805
-                        'The supplied ticket visibility setting of "%1$s" is not valid. It needs to match one of the keys in the following array:%2$s %3$s ',
1806
-                        'event_espresso'
1807
-                    ),
1808
-                    $visibility,
1809
-                    '<br />',
1810
-                    var_export($ticket_visibility_options, true)
1811
-                )
1812
-            );
1813
-        }
1814
-        $this->set('TKT_visibility', $ticket_visibility);
1815
-    }
1816
-
1817
-
1818
-    /**
1819
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1820
-     * @param string                   $relationName
1821
-     * @param array                    $extra_join_model_fields_n_values
1822
-     * @param string|null              $cache_id
1823
-     * @return EE_Base_Class
1824
-     * @throws EE_Error
1825
-     * @throws ReflectionException
1826
-     * @since   $VID:$
1827
-     */
1828
-    public function _add_relation_to(
1829
-        $otherObjectModelObjectOrID,
1830
-        $relationName,
1831
-        $extra_join_model_fields_n_values = [],
1832
-        $cache_id = null
1833
-    ) {
1834
-        if ($relationName === 'Datetime') {
1835
-            /** @var EE_Datetime $datetime */
1836
-            $datetime = EEM_Datetime::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1837
-            $datetime->increaseSold($this->sold());
1838
-            $datetime->increaseReserved($this->reserved());
1839
-            $datetime->save();
1840
-            $otherObjectModelObjectOrID = $datetime;
1841
-        }
1842
-        return parent::_add_relation_to(
1843
-            $otherObjectModelObjectOrID,
1844
-            $relationName,
1845
-            $extra_join_model_fields_n_values,
1846
-            $cache_id
1847
-        );
1848
-    }
1849
-
1850
-
1851
-    /**
1852
-     * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1853
-     * @param string                   $relationName
1854
-     * @param array                    $where_query
1855
-     * @return bool|EE_Base_Class|null
1856
-     * @throws EE_Error
1857
-     * @throws ReflectionException
1858
-     * @since   $VID:$
1859
-     */
1860
-    public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = [])
1861
-    {
1862
-        if ($relationName === 'Datetime') {
1863
-            /** @var EE_Datetime $datetime */
1864
-            $datetime = EEM_Datetime::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1865
-            $datetime->decreaseSold($this->sold());
1866
-            $datetime->decreaseReserved($this->reserved());
1867
-            $datetime->save();
1868
-            $otherObjectModelObjectOrID = $datetime;
1869
-        }
1870
-        return parent::_remove_relation_to(
1871
-            $otherObjectModelObjectOrID,
1872
-            $relationName,
1873
-            $where_query
1874
-        );
1875
-    }
1876
-
1877
-
1878
-    /*******************************************************************
17
+	/**
18
+	 * TicKet Sold out:
19
+	 * constant used by ticket_status() to indicate that a ticket is sold out
20
+	 * and no longer available for purchases
21
+	 */
22
+	const sold_out = 'TKS';
23
+
24
+	/**
25
+	 * TicKet Expired:
26
+	 * constant used by ticket_status() to indicate that a ticket is expired
27
+	 * and no longer available for purchase
28
+	 */
29
+	const expired = 'TKE';
30
+
31
+	/**
32
+	 * TicKet Archived:
33
+	 * constant used by ticket_status() to indicate that a ticket is archived
34
+	 * and no longer available for purchase
35
+	 */
36
+	const archived = 'TKA';
37
+
38
+	/**
39
+	 * TicKet Pending:
40
+	 * constant used by ticket_status() to indicate that a ticket is pending
41
+	 * and is NOT YET available for purchase
42
+	 */
43
+	const pending = 'TKP';
44
+
45
+	/**
46
+	 * TicKet On sale:
47
+	 * constant used by ticket_status() to indicate that a ticket is On Sale
48
+	 * and IS available for purchase
49
+	 */
50
+	const onsale = 'TKO';
51
+
52
+	/**
53
+	 * extra meta key for tracking ticket reservations
54
+	 *
55
+	 * @type string
56
+	 */
57
+	const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
58
+
59
+	/**
60
+	 * override of parent property
61
+	 *
62
+	 * @var EEM_Ticket
63
+	 */
64
+	protected $_model;
65
+
66
+	/**
67
+	 * cached result from method of the same name
68
+	 *
69
+	 * @var float $_ticket_total_with_taxes
70
+	 */
71
+	private $_ticket_total_with_taxes;
72
+
73
+
74
+	/**
75
+	 * @param array  $props_n_values          incoming values
76
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
77
+	 *                                        used.)
78
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
79
+	 *                                        date_format and the second value is the time format
80
+	 * @return EE_Ticket
81
+	 * @throws EE_Error
82
+	 * @throws ReflectionException
83
+	 */
84
+	public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
85
+	{
86
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
87
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
88
+	}
89
+
90
+
91
+	/**
92
+	 * @param array  $props_n_values  incoming values from the database
93
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
94
+	 *                                the website will be used.
95
+	 * @return EE_Ticket
96
+	 * @throws EE_Error
97
+	 * @throws ReflectionException
98
+	 */
99
+	public static function new_instance_from_db($props_n_values = [], $timezone = null)
100
+	{
101
+		return new self($props_n_values, true, $timezone);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return bool
107
+	 * @throws EE_Error
108
+	 * @throws ReflectionException
109
+	 */
110
+	public function parent()
111
+	{
112
+		return $this->get('TKT_parent');
113
+	}
114
+
115
+
116
+	/**
117
+	 * return if a ticket has quantities available for purchase
118
+	 *
119
+	 * @param int $DTT_ID the primary key for a particular datetime
120
+	 * @return boolean
121
+	 * @throws EE_Error
122
+	 * @throws ReflectionException
123
+	 */
124
+	public function available($DTT_ID = 0)
125
+	{
126
+		// are we checking availability for a particular datetime ?
127
+		if ($DTT_ID) {
128
+			// get that datetime object
129
+			$datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
130
+			// if  ticket sales for this datetime have exceeded the reg limit...
131
+			if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
132
+				return false;
133
+			}
134
+		}
135
+		// datetime is still open for registration, but is this ticket sold out ?
136
+		return $this->qty() < 1 || $this->qty() > $this->sold();
137
+	}
138
+
139
+
140
+	/**
141
+	 * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
142
+	 *
143
+	 * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
144
+	 *                               relevant status const
145
+	 * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
146
+	 *                               further processing
147
+	 * @return mixed status int if the display string isn't requested
148
+	 * @throws EE_Error
149
+	 * @throws ReflectionException
150
+	 */
151
+	public function ticket_status($display = false, $remaining = null)
152
+	{
153
+		$remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
154
+		if (! $remaining) {
155
+			return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
156
+		}
157
+		if ($this->get('TKT_deleted')) {
158
+			return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
159
+		}
160
+		if ($this->is_expired()) {
161
+			return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
162
+		}
163
+		if ($this->is_pending()) {
164
+			return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
165
+		}
166
+		if ($this->is_on_sale()) {
167
+			return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
168
+		}
169
+		return '';
170
+	}
171
+
172
+
173
+	/**
174
+	 * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
175
+	 * considering ALL the factors used for figuring that out.
176
+	 *
177
+	 * @access public
178
+	 * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
179
+	 * @return boolean         true = tickets remaining, false not.
180
+	 * @throws EE_Error
181
+	 * @throws ReflectionException
182
+	 */
183
+	public function is_remaining($DTT_ID = 0)
184
+	{
185
+		$num_remaining = $this->remaining($DTT_ID);
186
+		if ($num_remaining === 0) {
187
+			return false;
188
+		}
189
+		if ($num_remaining > 0 && $num_remaining < $this->min()) {
190
+			return false;
191
+		}
192
+		return true;
193
+	}
194
+
195
+
196
+	/**
197
+	 * return the total number of tickets available for purchase
198
+	 *
199
+	 * @param int $DTT_ID  the primary key for a particular datetime.
200
+	 *                     set to 0 for all related datetimes
201
+	 * @return int
202
+	 * @throws EE_Error
203
+	 * @throws ReflectionException
204
+	 */
205
+	public function remaining($DTT_ID = 0)
206
+	{
207
+		return $this->real_quantity_on_ticket('saleable', $DTT_ID);
208
+	}
209
+
210
+
211
+	/**
212
+	 * Gets min
213
+	 *
214
+	 * @return int
215
+	 * @throws EE_Error
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function min()
219
+	{
220
+		return $this->get('TKT_min');
221
+	}
222
+
223
+
224
+	/**
225
+	 * return if a ticket is no longer available cause its available dates have expired.
226
+	 *
227
+	 * @return boolean
228
+	 * @throws EE_Error
229
+	 * @throws ReflectionException
230
+	 */
231
+	public function is_expired()
232
+	{
233
+		return ($this->get_raw('TKT_end_date') < time());
234
+	}
235
+
236
+
237
+	/**
238
+	 * Return if a ticket is yet to go on sale or not
239
+	 *
240
+	 * @return boolean
241
+	 * @throws EE_Error
242
+	 * @throws ReflectionException
243
+	 */
244
+	public function is_pending()
245
+	{
246
+		return ($this->get_raw('TKT_start_date') >= time());
247
+	}
248
+
249
+
250
+	/**
251
+	 * Return if a ticket is on sale or not
252
+	 *
253
+	 * @return boolean
254
+	 * @throws EE_Error
255
+	 * @throws ReflectionException
256
+	 */
257
+	public function is_on_sale()
258
+	{
259
+		return ($this->get_raw('TKT_start_date') <= time() && $this->get_raw('TKT_end_date') >= time());
260
+	}
261
+
262
+
263
+	/**
264
+	 * This returns the chronologically last datetime that this ticket is associated with
265
+	 *
266
+	 * @param string $date_format
267
+	 * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
268
+	 *                            the end date ie: Jan 01 "to" Dec 31
269
+	 * @return string
270
+	 * @throws EE_Error
271
+	 * @throws ReflectionException
272
+	 */
273
+	public function date_range($date_format = '', $conjunction = ' - ')
274
+	{
275
+		$date_format = ! empty($date_format) ? $date_format : $this->_dt_frmt;
276
+		$first_date  = $this->first_datetime() instanceof EE_Datetime
277
+			? $this->first_datetime()->get_i18n_datetime('DTT_EVT_start', $date_format)
278
+			: '';
279
+		$last_date   = $this->last_datetime() instanceof EE_Datetime
280
+			? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format)
281
+			: '';
282
+
283
+		return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
284
+	}
285
+
286
+
287
+	/**
288
+	 * This returns the chronologically first datetime that this ticket is associated with
289
+	 *
290
+	 * @return EE_Datetime
291
+	 * @throws EE_Error
292
+	 * @throws ReflectionException
293
+	 */
294
+	public function first_datetime()
295
+	{
296
+		$datetimes = $this->datetimes(['limit' => 1]);
297
+		return reset($datetimes);
298
+	}
299
+
300
+
301
+	/**
302
+	 * Gets all the datetimes this ticket can be used for attending.
303
+	 * Unless otherwise specified, orders datetimes by start date.
304
+	 *
305
+	 * @param array $query_params @see
306
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
307
+	 * @return EE_Datetime[]|EE_Base_Class[]
308
+	 * @throws EE_Error
309
+	 * @throws ReflectionException
310
+	 */
311
+	public function datetimes($query_params = [])
312
+	{
313
+		if (! isset($query_params['order_by'])) {
314
+			$query_params['order_by']['DTT_order'] = 'ASC';
315
+		}
316
+		return $this->get_many_related('Datetime', $query_params);
317
+	}
318
+
319
+
320
+	/**
321
+	 * This returns the chronologically last datetime that this ticket is associated with
322
+	 *
323
+	 * @return EE_Datetime
324
+	 * @throws EE_Error
325
+	 * @throws ReflectionException
326
+	 */
327
+	public function last_datetime()
328
+	{
329
+		$datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
330
+		return end($datetimes);
331
+	}
332
+
333
+
334
+	/**
335
+	 * This returns the total tickets sold depending on the given parameters.
336
+	 *
337
+	 * @param string $what    Can be one of two options: 'ticket', 'datetime'.
338
+	 *                        'ticket' = total ticket sales for all datetimes this ticket is related to
339
+	 *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
340
+	 *                        'datetime' = total ticket sales in the datetime_ticket table.
341
+	 *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
342
+	 *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
343
+	 * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
344
+	 * @return mixed (array|int)          how many tickets have sold
345
+	 * @throws EE_Error
346
+	 * @throws ReflectionException
347
+	 */
348
+	public function tickets_sold($what = 'ticket', $dtt_id = null)
349
+	{
350
+		$total        = 0;
351
+		$tickets_sold = $this->_all_tickets_sold();
352
+		switch ($what) {
353
+			case 'ticket':
354
+				return $tickets_sold['ticket'];
355
+				break;
356
+			case 'datetime':
357
+				if (empty($tickets_sold['datetime'])) {
358
+					return $total;
359
+				}
360
+				if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
361
+					EE_Error::add_error(
362
+						__(
363
+							'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
364
+							'event_espresso'
365
+						),
366
+						__FILE__,
367
+						__FUNCTION__,
368
+						__LINE__
369
+					);
370
+					return $total;
371
+				}
372
+				return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
373
+				break;
374
+			default:
375
+				return $total;
376
+		}
377
+	}
378
+
379
+
380
+	/**
381
+	 * This returns an array indexed by datetime_id for tickets sold with this ticket.
382
+	 *
383
+	 * @return EE_Ticket[]
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	protected function _all_tickets_sold()
388
+	{
389
+		$datetimes    = $this->get_many_related('Datetime');
390
+		$tickets_sold = [];
391
+		if (! empty($datetimes)) {
392
+			foreach ($datetimes as $datetime) {
393
+				$tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
394
+			}
395
+		}
396
+		// Tickets sold
397
+		$tickets_sold['ticket'] = $this->sold();
398
+		return $tickets_sold;
399
+	}
400
+
401
+
402
+	/**
403
+	 * This returns the base price object for the ticket.
404
+	 *
405
+	 * @param bool $return_array whether to return as an array indexed by price id or just the object.
406
+	 * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
407
+	 * @throws EE_Error
408
+	 * @throws ReflectionException
409
+	 */
410
+	public function base_price($return_array = false)
411
+	{
412
+		$_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
413
+		return $return_array
414
+			? $this->get_many_related('Price', [$_where])
415
+			: $this->get_first_related('Price', [$_where]);
416
+	}
417
+
418
+
419
+	/**
420
+	 * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
421
+	 *
422
+	 * @access public
423
+	 * @return EE_Price[]
424
+	 * @throws EE_Error
425
+	 * @throws ReflectionException
426
+	 */
427
+	public function price_modifiers()
428
+	{
429
+		$query_params = [
430
+			0 => [
431
+				'Price_Type.PBT_ID' => [
432
+					'NOT IN',
433
+					[EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
434
+				],
435
+			],
436
+		];
437
+		return $this->prices($query_params);
438
+	}
439
+
440
+
441
+	/**
442
+	 * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
443
+	 *
444
+	 * @access public
445
+	 * @return EE_Price[]
446
+	 * @throws EE_Error
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function tax_price_modifiers()
450
+	{
451
+		$query_params = [
452
+			0 => [
453
+				'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax,
454
+			],
455
+		];
456
+		return $this->prices($query_params);
457
+	}
458
+
459
+
460
+	/**
461
+	 * Gets all the prices that combine to form the final price of this ticket
462
+	 *
463
+	 * @param array $query_params @see
464
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
465
+	 * @return EE_Price[]|EE_Base_Class[]
466
+	 * @throws EE_Error
467
+	 * @throws ReflectionException
468
+	 */
469
+	public function prices($query_params = [])
470
+	{
471
+		return $this->get_many_related('Price', $query_params);
472
+	}
473
+
474
+
475
+	/**
476
+	 * Gets all the ticket datetimes (ie, relations between datetimes and tickets)
477
+	 *
478
+	 * @param array $query_params @see
479
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
480
+	 * @return EE_Datetime_Ticket|EE_Base_Class[]
481
+	 * @throws EE_Error
482
+	 * @throws ReflectionException
483
+	 */
484
+	public function datetime_tickets($query_params = [])
485
+	{
486
+		return $this->get_many_related('Datetime_Ticket', $query_params);
487
+	}
488
+
489
+
490
+	/**
491
+	 * Gets all the datetimes from the db ordered by DTT_order
492
+	 *
493
+	 * @param boolean $show_expired
494
+	 * @param boolean $show_deleted
495
+	 * @return EE_Datetime[]
496
+	 * @throws EE_Error
497
+	 * @throws ReflectionException
498
+	 */
499
+	public function datetimes_ordered($show_expired = true, $show_deleted = false)
500
+	{
501
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
502
+			$this->ID(),
503
+			$show_expired,
504
+			$show_deleted
505
+		);
506
+	}
507
+
508
+
509
+	/**
510
+	 * Gets ID
511
+	 *
512
+	 * @return int
513
+	 * @throws EE_Error
514
+	 * @throws ReflectionException
515
+	 */
516
+	public function ID()
517
+	{
518
+		return $this->get('TKT_ID');
519
+	}
520
+
521
+
522
+	/**
523
+	 * get the author of the ticket.
524
+	 *
525
+	 * @return int
526
+	 * @throws EE_Error
527
+	 * @throws ReflectionException
528
+	 * @since 4.5.0
529
+	 */
530
+	public function wp_user()
531
+	{
532
+		return $this->get('TKT_wp_user');
533
+	}
534
+
535
+
536
+	/**
537
+	 * Gets the template for the ticket
538
+	 *
539
+	 * @return EE_Ticket_Template|EE_Base_Class
540
+	 * @throws EE_Error
541
+	 * @throws ReflectionException
542
+	 */
543
+	public function template()
544
+	{
545
+		return $this->get_first_related('Ticket_Template');
546
+	}
547
+
548
+
549
+	/**
550
+	 * Simply returns an array of EE_Price objects that are taxes.
551
+	 *
552
+	 * @return EE_Price[]
553
+	 * @throws EE_Error
554
+	 */
555
+	public function get_ticket_taxes_for_admin()
556
+	{
557
+		return EE_Taxes::get_taxes_for_admin();
558
+	}
559
+
560
+
561
+	/**
562
+	 * @return float
563
+	 * @throws EE_Error
564
+	 * @throws ReflectionException
565
+	 */
566
+	public function ticket_price()
567
+	{
568
+		return $this->get('TKT_price');
569
+	}
570
+
571
+
572
+	/**
573
+	 * @return mixed
574
+	 * @throws EE_Error
575
+	 * @throws ReflectionException
576
+	 */
577
+	public function pretty_price()
578
+	{
579
+		return $this->get_pretty('TKT_price');
580
+	}
581
+
582
+
583
+	/**
584
+	 * @return bool
585
+	 * @throws EE_Error
586
+	 * @throws ReflectionException
587
+	 */
588
+	public function is_free()
589
+	{
590
+		return $this->get_ticket_total_with_taxes() === (float) 0;
591
+	}
592
+
593
+
594
+	/**
595
+	 * get_ticket_total_with_taxes
596
+	 *
597
+	 * @param bool $no_cache
598
+	 * @return float
599
+	 * @throws EE_Error
600
+	 * @throws ReflectionException
601
+	 */
602
+	public function get_ticket_total_with_taxes($no_cache = false)
603
+	{
604
+		if ($this->_ticket_total_with_taxes === null || $no_cache) {
605
+			$this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
606
+		}
607
+		return (float) $this->_ticket_total_with_taxes;
608
+	}
609
+
610
+
611
+	/**
612
+	 * @throws EE_Error
613
+	 * @throws ReflectionException
614
+	 */
615
+	public function ensure_TKT_Price_correct()
616
+	{
617
+		$this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
618
+		$this->save();
619
+	}
620
+
621
+
622
+	/**
623
+	 * @return float
624
+	 * @throws EE_Error
625
+	 * @throws ReflectionException
626
+	 */
627
+	public function get_ticket_subtotal()
628
+	{
629
+		return EE_Taxes::get_subtotal_for_admin($this);
630
+	}
631
+
632
+
633
+	/**
634
+	 * Returns the total taxes applied to this ticket
635
+	 *
636
+	 * @return float
637
+	 * @throws EE_Error
638
+	 * @throws ReflectionException
639
+	 */
640
+	public function get_ticket_taxes_total_for_admin()
641
+	{
642
+		return EE_Taxes::get_total_taxes_for_admin($this);
643
+	}
644
+
645
+
646
+	/**
647
+	 * Sets name
648
+	 *
649
+	 * @param string $name
650
+	 * @throws EE_Error
651
+	 * @throws ReflectionException
652
+	 */
653
+	public function set_name($name)
654
+	{
655
+		$this->set('TKT_name', $name);
656
+	}
657
+
658
+
659
+	/**
660
+	 * Gets description
661
+	 *
662
+	 * @return string
663
+	 * @throws EE_Error
664
+	 * @throws ReflectionException
665
+	 */
666
+	public function description()
667
+	{
668
+		return $this->get('TKT_description');
669
+	}
670
+
671
+
672
+	/**
673
+	 * Sets description
674
+	 *
675
+	 * @param string $description
676
+	 * @throws EE_Error
677
+	 * @throws ReflectionException
678
+	 */
679
+	public function set_description($description)
680
+	{
681
+		$this->set('TKT_description', $description);
682
+	}
683
+
684
+
685
+	/**
686
+	 * Gets start_date
687
+	 *
688
+	 * @param string $date_format
689
+	 * @param string $time_format
690
+	 * @return string
691
+	 * @throws EE_Error
692
+	 * @throws ReflectionException
693
+	 */
694
+	public function start_date($date_format = '', $time_format = '')
695
+	{
696
+		return $this->_get_datetime('TKT_start_date', $date_format, $time_format);
697
+	}
698
+
699
+
700
+	/**
701
+	 * Sets start_date
702
+	 *
703
+	 * @param string $start_date
704
+	 * @return void
705
+	 * @throws EE_Error
706
+	 * @throws ReflectionException
707
+	 */
708
+	public function set_start_date($start_date)
709
+	{
710
+		$this->_set_date_time('B', $start_date, 'TKT_start_date');
711
+	}
712
+
713
+
714
+	/**
715
+	 * Gets end_date
716
+	 *
717
+	 * @param string $date_format
718
+	 * @param string $time_format
719
+	 * @return string
720
+	 * @throws EE_Error
721
+	 * @throws ReflectionException
722
+	 */
723
+	public function end_date($date_format = '', $time_format = '')
724
+	{
725
+		return $this->_get_datetime('TKT_end_date', $date_format, $time_format);
726
+	}
727
+
728
+
729
+	/**
730
+	 * Sets end_date
731
+	 *
732
+	 * @param string $end_date
733
+	 * @return void
734
+	 * @throws EE_Error
735
+	 * @throws ReflectionException
736
+	 */
737
+	public function set_end_date($end_date)
738
+	{
739
+		$this->_set_date_time('B', $end_date, 'TKT_end_date');
740
+	}
741
+
742
+
743
+	/**
744
+	 * Sets sell until time
745
+	 *
746
+	 * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
747
+	 * @throws EE_Error
748
+	 * @throws ReflectionException
749
+	 * @since 4.5.0
750
+	 */
751
+	public function set_end_time($time)
752
+	{
753
+		$this->_set_time_for($time, 'TKT_end_date');
754
+	}
755
+
756
+
757
+	/**
758
+	 * Sets min
759
+	 *
760
+	 * @param int $min
761
+	 * @return void
762
+	 * @throws EE_Error
763
+	 * @throws ReflectionException
764
+	 */
765
+	public function set_min($min)
766
+	{
767
+		$this->set('TKT_min', $min);
768
+	}
769
+
770
+
771
+	/**
772
+	 * Gets max
773
+	 *
774
+	 * @return int
775
+	 * @throws EE_Error
776
+	 * @throws ReflectionException
777
+	 */
778
+	public function max()
779
+	{
780
+		return $this->get('TKT_max');
781
+	}
782
+
783
+
784
+	/**
785
+	 * Sets max
786
+	 *
787
+	 * @param int $max
788
+	 * @return void
789
+	 * @throws EE_Error
790
+	 * @throws ReflectionException
791
+	 */
792
+	public function set_max($max)
793
+	{
794
+		$this->set('TKT_max', $max);
795
+	}
796
+
797
+
798
+	/**
799
+	 * Sets price
800
+	 *
801
+	 * @param float $price
802
+	 * @return void
803
+	 * @throws EE_Error
804
+	 * @throws ReflectionException
805
+	 */
806
+	public function set_price($price)
807
+	{
808
+		$this->set('TKT_price', $price);
809
+	}
810
+
811
+
812
+	/**
813
+	 * Gets sold
814
+	 *
815
+	 * @return int
816
+	 * @throws EE_Error
817
+	 * @throws ReflectionException
818
+	 */
819
+	public function sold()
820
+	{
821
+		return $this->get_raw('TKT_sold');
822
+	}
823
+
824
+
825
+	/**
826
+	 * Sets sold
827
+	 *
828
+	 * @param int $sold
829
+	 * @return void
830
+	 * @throws EE_Error
831
+	 * @throws ReflectionException
832
+	 */
833
+	public function set_sold($sold)
834
+	{
835
+		// sold can not go below zero
836
+		$sold = max(0, $sold);
837
+		$this->set('TKT_sold', $sold);
838
+	}
839
+
840
+
841
+	/**
842
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
843
+	 * associated datetimes.
844
+	 *
845
+	 * @param int $qty
846
+	 * @return boolean
847
+	 * @throws EE_Error
848
+	 * @throws InvalidArgumentException
849
+	 * @throws InvalidDataTypeException
850
+	 * @throws InvalidInterfaceException
851
+	 * @throws ReflectionException
852
+	 * @since 4.9.80.p
853
+	 */
854
+	public function increaseSold($qty = 1)
855
+	{
856
+		$qty = absint($qty);
857
+		// increment sold and decrement reserved datetime quantities simultaneously
858
+		// don't worry about failures, because they must have already had a spot reserved
859
+		$this->increaseSoldForDatetimes($qty);
860
+		// Increment and decrement ticket quantities simultaneously
861
+		$success = $this->adjustNumericFieldsInDb(
862
+			[
863
+				'TKT_reserved' => $qty * -1,
864
+				'TKT_sold'     => $qty,
865
+			]
866
+		);
867
+		do_action(
868
+			'AHEE__EE_Ticket__increase_sold',
869
+			$this,
870
+			$qty,
871
+			$this->sold(),
872
+			$success
873
+		);
874
+		return $success;
875
+	}
876
+
877
+
878
+	/**
879
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
880
+	 *
881
+	 * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
882
+	 *                           counts), Negative means to decreases old counts (and increase reserved counts).
883
+	 * @param EE_Datetime[] $datetimes
884
+	 * @throws EE_Error
885
+	 * @throws InvalidArgumentException
886
+	 * @throws InvalidDataTypeException
887
+	 * @throws InvalidInterfaceException
888
+	 * @throws ReflectionException
889
+	 * @since 4.9.80.p
890
+	 */
891
+	protected function increaseSoldForDatetimes($qty, array $datetimes = [])
892
+	{
893
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
894
+		foreach ($datetimes as $datetime) {
895
+			$datetime->increaseSold($qty);
896
+		}
897
+	}
898
+
899
+
900
+	/**
901
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
902
+	 * DB and then updates the model objects.
903
+	 * Does not affect the reserved counts.
904
+	 *
905
+	 * @param int $qty
906
+	 * @return boolean
907
+	 * @throws EE_Error
908
+	 * @throws InvalidArgumentException
909
+	 * @throws InvalidDataTypeException
910
+	 * @throws InvalidInterfaceException
911
+	 * @throws ReflectionException
912
+	 * @since 4.9.80.p
913
+	 */
914
+	public function decreaseSold($qty = 1)
915
+	{
916
+		$qty = absint($qty);
917
+		$this->decreaseSoldForDatetimes($qty);
918
+		$success = $this->adjustNumericFieldsInDb(
919
+			[
920
+				'TKT_sold' => $qty * -1,
921
+			]
922
+		);
923
+		do_action(
924
+			'AHEE__EE_Ticket__decrease_sold',
925
+			$this,
926
+			$qty,
927
+			$this->sold(),
928
+			$success
929
+		);
930
+		return $success;
931
+	}
932
+
933
+
934
+	/**
935
+	 * Decreases sold on related datetimes
936
+	 *
937
+	 * @param int           $qty
938
+	 * @param EE_Datetime[] $datetimes
939
+	 * @return void
940
+	 * @throws EE_Error
941
+	 * @throws InvalidArgumentException
942
+	 * @throws InvalidDataTypeException
943
+	 * @throws InvalidInterfaceException
944
+	 * @throws ReflectionException
945
+	 * @since 4.9.80.p
946
+	 */
947
+	protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
948
+	{
949
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
950
+		if (is_array($datetimes)) {
951
+			foreach ($datetimes as $datetime) {
952
+				if ($datetime instanceof EE_Datetime) {
953
+					$datetime->decreaseSold($qty);
954
+				}
955
+			}
956
+		}
957
+	}
958
+
959
+
960
+	/**
961
+	 * Gets qty of reserved tickets
962
+	 *
963
+	 * @return int
964
+	 * @throws EE_Error
965
+	 * @throws ReflectionException
966
+	 */
967
+	public function reserved()
968
+	{
969
+		return $this->get_raw('TKT_reserved');
970
+	}
971
+
972
+
973
+	/**
974
+	 * Sets reserved
975
+	 *
976
+	 * @param int $reserved
977
+	 * @return void
978
+	 * @throws EE_Error
979
+	 * @throws ReflectionException
980
+	 */
981
+	public function set_reserved($reserved)
982
+	{
983
+		// reserved can not go below zero
984
+		$reserved = max(0, (int) $reserved);
985
+		$this->set('TKT_reserved', $reserved);
986
+	}
987
+
988
+
989
+	/**
990
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
991
+	 *
992
+	 * @param int    $qty
993
+	 * @param string $source
994
+	 * @return bool whether we successfully reserved the ticket or not.
995
+	 * @throws EE_Error
996
+	 * @throws InvalidArgumentException
997
+	 * @throws ReflectionException
998
+	 * @throws InvalidDataTypeException
999
+	 * @throws InvalidInterfaceException
1000
+	 * @since 4.9.80.p
1001
+	 */
1002
+	public function increaseReserved($qty = 1, $source = 'unknown')
1003
+	{
1004
+		$qty = absint($qty);
1005
+		do_action(
1006
+			'AHEE__EE_Ticket__increase_reserved__begin',
1007
+			$this,
1008
+			$qty,
1009
+			$source
1010
+		);
1011
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
1012
+		$success                         = false;
1013
+		$datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
1014
+		if ($datetimes_adjusted_successfully) {
1015
+			$success = $this->incrementFieldConditionallyInDb(
1016
+				'TKT_reserved',
1017
+				'TKT_sold',
1018
+				'TKT_qty',
1019
+				$qty
1020
+			);
1021
+			if (! $success) {
1022
+				// The datetimes were successfully bumped, but not the
1023
+				// ticket. So we need to manually rollback the datetimes.
1024
+				$this->decreaseReservedForDatetimes($qty);
1025
+			}
1026
+		}
1027
+		do_action(
1028
+			'AHEE__EE_Ticket__increase_reserved',
1029
+			$this,
1030
+			$qty,
1031
+			$this->reserved(),
1032
+			$success
1033
+		);
1034
+		return $success;
1035
+	}
1036
+
1037
+
1038
+	/**
1039
+	 * Increases reserved counts on related datetimes
1040
+	 *
1041
+	 * @param int           $qty
1042
+	 * @param EE_Datetime[] $datetimes
1043
+	 * @return boolean indicating success
1044
+	 * @throws EE_Error
1045
+	 * @throws InvalidArgumentException
1046
+	 * @throws InvalidDataTypeException
1047
+	 * @throws InvalidInterfaceException
1048
+	 * @throws ReflectionException
1049
+	 * @since 4.9.80.p
1050
+	 */
1051
+	protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1052
+	{
1053
+		$datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1054
+		$datetimes_updated = [];
1055
+		$limit_exceeded    = false;
1056
+		if (is_array($datetimes)) {
1057
+			foreach ($datetimes as $datetime) {
1058
+				if ($datetime instanceof EE_Datetime) {
1059
+					if ($datetime->increaseReserved($qty)) {
1060
+						$datetimes_updated[] = $datetime;
1061
+					} else {
1062
+						$limit_exceeded = true;
1063
+						break;
1064
+					}
1065
+				}
1066
+			}
1067
+			// If somewhere along the way we detected a datetime whose
1068
+			// limit was exceeded, do a manual rollback.
1069
+			if ($limit_exceeded) {
1070
+				$this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1071
+				return false;
1072
+			}
1073
+		}
1074
+		return true;
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1080
+	 *
1081
+	 * @param int    $qty
1082
+	 * @param bool   $adjust_datetimes
1083
+	 * @param string $source
1084
+	 * @return boolean
1085
+	 * @throws EE_Error
1086
+	 * @throws InvalidArgumentException
1087
+	 * @throws ReflectionException
1088
+	 * @throws InvalidDataTypeException
1089
+	 * @throws InvalidInterfaceException
1090
+	 * @since 4.9.80.p
1091
+	 */
1092
+	public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1093
+	{
1094
+		$qty = absint($qty);
1095
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1096
+		if ($adjust_datetimes) {
1097
+			$this->decreaseReservedForDatetimes($qty);
1098
+		}
1099
+		$success = $this->adjustNumericFieldsInDb(
1100
+			[
1101
+				'TKT_reserved' => $qty * -1,
1102
+			]
1103
+		);
1104
+		do_action(
1105
+			'AHEE__EE_Ticket__decrease_reserved',
1106
+			$this,
1107
+			$qty,
1108
+			$this->reserved(),
1109
+			$success
1110
+		);
1111
+		return $success;
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * Decreases the reserved count on the specified datetimes.
1117
+	 *
1118
+	 * @param int           $qty
1119
+	 * @param EE_Datetime[] $datetimes
1120
+	 * @throws EE_Error
1121
+	 * @throws InvalidArgumentException
1122
+	 * @throws ReflectionException
1123
+	 * @throws InvalidDataTypeException
1124
+	 * @throws InvalidInterfaceException
1125
+	 * @since 4.9.80.p
1126
+	 */
1127
+	protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1128
+	{
1129
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1130
+		foreach ($datetimes as $datetime) {
1131
+			if ($datetime instanceof EE_Datetime) {
1132
+				$datetime->decreaseReserved($qty);
1133
+			}
1134
+		}
1135
+	}
1136
+
1137
+
1138
+	/**
1139
+	 * Gets ticket quantity
1140
+	 *
1141
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1142
+	 *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1143
+	 *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1144
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1145
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1146
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1147
+	 * @return int
1148
+	 * @throws EE_Error
1149
+	 * @throws ReflectionException
1150
+	 */
1151
+	public function qty($context = '')
1152
+	{
1153
+		switch ($context) {
1154
+			case 'reg_limit':
1155
+				return $this->real_quantity_on_ticket();
1156
+			case 'saleable':
1157
+				return $this->real_quantity_on_ticket('saleable');
1158
+			default:
1159
+				return $this->get_raw('TKT_qty');
1160
+		}
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Gets ticket quantity
1166
+	 *
1167
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1168
+	 *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1169
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1170
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1171
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1172
+	 * @param int    $DTT_ID      the primary key for a particular datetime.
1173
+	 *                            set to 0 for all related datetimes
1174
+	 * @return int
1175
+	 * @throws EE_Error
1176
+	 * @throws ReflectionException
1177
+	 */
1178
+	public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1179
+	{
1180
+		$raw = $this->get_raw('TKT_qty');
1181
+		// return immediately if it's zero
1182
+		if ($raw === 0) {
1183
+			return $raw;
1184
+		}
1185
+		// echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1186
+		// ensure qty doesn't exceed raw value for THIS ticket
1187
+		$qty = min(EE_INF, $raw);
1188
+		// echo "\n . qty: " . $qty . '<br />';
1189
+		// calculate this ticket's total sales and reservations
1190
+		$sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1191
+		// echo "\n . sold: " . $this->sold() . '<br />';
1192
+		// echo "\n . reserved: " . $this->reserved() . '<br />';
1193
+		// echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1194
+		// first we need to calculate the maximum number of tickets available for the datetime
1195
+		// do we want data for one datetime or all of them ?
1196
+		$query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1197
+		$datetimes    = $this->datetimes($query_params);
1198
+		if (is_array($datetimes) && ! empty($datetimes)) {
1199
+			foreach ($datetimes as $datetime) {
1200
+				if ($datetime instanceof EE_Datetime) {
1201
+					$datetime->refresh_from_db();
1202
+					// echo "\n . . datetime name: " . $datetime->name() . '<br />';
1203
+					// echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1204
+					// initialize with no restrictions for each datetime
1205
+					// but adjust datetime qty based on datetime reg limit
1206
+					$datetime_qty = min(EE_INF, $datetime->reg_limit());
1207
+					// echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1208
+					// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1209
+					// if we want the actual saleable amount, then we need to consider OTHER ticket sales
1210
+					// and reservations for this datetime, that do NOT include sales and reservations
1211
+					// for this ticket (so we add $this->sold() and $this->reserved() back in)
1212
+					if ($context === 'saleable') {
1213
+						$datetime_qty = max(
1214
+							$datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1215
+							0
1216
+						);
1217
+						// echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1218
+						// echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1219
+						// echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1220
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1221
+						$datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1222
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1223
+					}
1224
+					$qty = min($datetime_qty, $qty);
1225
+					// echo "\n . . qty: " . $qty . '<br />';
1226
+				}
1227
+			}
1228
+		}
1229
+		// NOW that we know the  maximum number of tickets available for the datetime
1230
+		// we can finally factor in the details for this specific ticket
1231
+		if ($qty > 0 && $context === 'saleable') {
1232
+			// and subtract the sales for THIS ticket
1233
+			$qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1234
+			// echo "\n . qty: " . $qty . '<br />';
1235
+		}
1236
+		// echo "\nFINAL QTY: " . $qty . "<br /><br />";
1237
+		return $qty;
1238
+	}
1239
+
1240
+
1241
+	/**
1242
+	 * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1243
+	 *
1244
+	 * @param int $qty
1245
+	 * @return void
1246
+	 * @throws EE_Error
1247
+	 * @throws ReflectionException
1248
+	 */
1249
+	public function set_qty($qty)
1250
+	{
1251
+		$datetimes = $this->datetimes();
1252
+		foreach ($datetimes as $datetime) {
1253
+			if ($datetime instanceof EE_Datetime) {
1254
+				$qty = min($qty, $datetime->reg_limit());
1255
+			}
1256
+		}
1257
+		$this->set('TKT_qty', $qty);
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * Gets uses
1263
+	 *
1264
+	 * @return int
1265
+	 * @throws EE_Error
1266
+	 * @throws ReflectionException
1267
+	 */
1268
+	public function uses()
1269
+	{
1270
+		return $this->get('TKT_uses');
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * Sets uses
1276
+	 *
1277
+	 * @param int $uses
1278
+	 * @return void
1279
+	 * @throws EE_Error
1280
+	 * @throws ReflectionException
1281
+	 */
1282
+	public function set_uses($uses)
1283
+	{
1284
+		$this->set('TKT_uses', $uses);
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 * returns whether ticket is required or not.
1290
+	 *
1291
+	 * @return boolean
1292
+	 * @throws EE_Error
1293
+	 * @throws ReflectionException
1294
+	 */
1295
+	public function required()
1296
+	{
1297
+		return $this->get('TKT_required');
1298
+	}
1299
+
1300
+
1301
+	/**
1302
+	 * sets the TKT_required property
1303
+	 *
1304
+	 * @param boolean $required
1305
+	 * @return void
1306
+	 * @throws EE_Error
1307
+	 * @throws ReflectionException
1308
+	 */
1309
+	public function set_required($required)
1310
+	{
1311
+		$this->set('TKT_required', $required);
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * Gets taxable
1317
+	 *
1318
+	 * @return boolean
1319
+	 * @throws EE_Error
1320
+	 * @throws ReflectionException
1321
+	 */
1322
+	public function taxable()
1323
+	{
1324
+		return $this->get('TKT_taxable');
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Sets taxable
1330
+	 *
1331
+	 * @param boolean $taxable
1332
+	 * @return void
1333
+	 * @throws EE_Error
1334
+	 * @throws ReflectionException
1335
+	 */
1336
+	public function set_taxable($taxable)
1337
+	{
1338
+		$this->set('TKT_taxable', $taxable);
1339
+	}
1340
+
1341
+
1342
+	/**
1343
+	 * Gets is_default
1344
+	 *
1345
+	 * @return boolean
1346
+	 * @throws EE_Error
1347
+	 * @throws ReflectionException
1348
+	 */
1349
+	public function is_default()
1350
+	{
1351
+		return $this->get('TKT_is_default');
1352
+	}
1353
+
1354
+
1355
+	/**
1356
+	 * Sets is_default
1357
+	 *
1358
+	 * @param boolean $is_default
1359
+	 * @return void
1360
+	 * @throws EE_Error
1361
+	 * @throws ReflectionException
1362
+	 */
1363
+	public function set_is_default($is_default)
1364
+	{
1365
+		$this->set('TKT_is_default', $is_default);
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 * Gets order
1371
+	 *
1372
+	 * @return int
1373
+	 * @throws EE_Error
1374
+	 * @throws ReflectionException
1375
+	 */
1376
+	public function order()
1377
+	{
1378
+		return $this->get('TKT_order');
1379
+	}
1380
+
1381
+
1382
+	/**
1383
+	 * Sets order
1384
+	 *
1385
+	 * @param int $order
1386
+	 * @return void
1387
+	 * @throws EE_Error
1388
+	 * @throws ReflectionException
1389
+	 */
1390
+	public function set_order($order)
1391
+	{
1392
+		$this->set('TKT_order', $order);
1393
+	}
1394
+
1395
+
1396
+	/**
1397
+	 * Gets row
1398
+	 *
1399
+	 * @return int
1400
+	 * @throws EE_Error
1401
+	 * @throws ReflectionException
1402
+	 */
1403
+	public function row()
1404
+	{
1405
+		return $this->get('TKT_row');
1406
+	}
1407
+
1408
+
1409
+	/**
1410
+	 * Sets row
1411
+	 *
1412
+	 * @param int $row
1413
+	 * @return void
1414
+	 * @throws EE_Error
1415
+	 * @throws ReflectionException
1416
+	 */
1417
+	public function set_row($row)
1418
+	{
1419
+		$this->set('TKT_row', $row);
1420
+	}
1421
+
1422
+
1423
+	/**
1424
+	 * Gets deleted
1425
+	 *
1426
+	 * @return boolean
1427
+	 * @throws EE_Error
1428
+	 * @throws ReflectionException
1429
+	 */
1430
+	public function deleted()
1431
+	{
1432
+		return $this->get('TKT_deleted');
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * Sets deleted
1438
+	 *
1439
+	 * @param boolean $deleted
1440
+	 * @return void
1441
+	 * @throws EE_Error
1442
+	 * @throws ReflectionException
1443
+	 */
1444
+	public function set_deleted($deleted)
1445
+	{
1446
+		$this->set('TKT_deleted', $deleted);
1447
+	}
1448
+
1449
+
1450
+	/**
1451
+	 * Gets parent
1452
+	 *
1453
+	 * @return int
1454
+	 * @throws EE_Error
1455
+	 * @throws ReflectionException
1456
+	 */
1457
+	public function parent_ID()
1458
+	{
1459
+		return $this->get('TKT_parent');
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * Sets parent
1465
+	 *
1466
+	 * @param int $parent
1467
+	 * @return void
1468
+	 * @throws EE_Error
1469
+	 * @throws ReflectionException
1470
+	 */
1471
+	public function set_parent_ID($parent)
1472
+	{
1473
+		$this->set('TKT_parent', $parent);
1474
+	}
1475
+
1476
+
1477
+	/**
1478
+	 * @return boolean
1479
+	 * @throws EE_Error
1480
+	 * @throws InvalidArgumentException
1481
+	 * @throws InvalidDataTypeException
1482
+	 * @throws InvalidInterfaceException
1483
+	 * @throws ReflectionException
1484
+	 */
1485
+	public function reverse_calculate()
1486
+	{
1487
+		return $this->get('TKT_reverse_calculate');
1488
+	}
1489
+
1490
+
1491
+	/**
1492
+	 * @param boolean $reverse_calculate
1493
+	 * @throws EE_Error
1494
+	 * @throws InvalidArgumentException
1495
+	 * @throws InvalidDataTypeException
1496
+	 * @throws InvalidInterfaceException
1497
+	 * @throws ReflectionException
1498
+	 */
1499
+	public function set_reverse_calculate($reverse_calculate)
1500
+	{
1501
+		$this->set('TKT_reverse_calculate', $reverse_calculate);
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * Gets a string which is handy for showing in gateways etc that describes the ticket.
1507
+	 *
1508
+	 * @return string
1509
+	 * @throws EE_Error
1510
+	 * @throws ReflectionException
1511
+	 */
1512
+	public function name_and_info()
1513
+	{
1514
+		$times = [];
1515
+		foreach ($this->datetimes() as $datetime) {
1516
+			$times[] = $datetime->start_date_and_time();
1517
+		}
1518
+		return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1519
+	}
1520
+
1521
+
1522
+	/**
1523
+	 * Gets name
1524
+	 *
1525
+	 * @return string
1526
+	 * @throws EE_Error
1527
+	 * @throws ReflectionException
1528
+	 */
1529
+	public function name()
1530
+	{
1531
+		return $this->get('TKT_name');
1532
+	}
1533
+
1534
+
1535
+	/**
1536
+	 * Gets price
1537
+	 *
1538
+	 * @return float
1539
+	 * @throws EE_Error
1540
+	 * @throws ReflectionException
1541
+	 */
1542
+	public function price()
1543
+	{
1544
+		return $this->get('TKT_price');
1545
+	}
1546
+
1547
+
1548
+	/**
1549
+	 * Gets all the registrations for this ticket
1550
+	 *
1551
+	 * @param array $query_params @see
1552
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1553
+	 * @return EE_Registration[]|EE_Base_Class[]
1554
+	 * @throws EE_Error
1555
+	 * @throws ReflectionException
1556
+	 */
1557
+	public function registrations($query_params = [])
1558
+	{
1559
+		return $this->get_many_related('Registration', $query_params);
1560
+	}
1561
+
1562
+
1563
+	/**
1564
+	 * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1565
+	 *
1566
+	 * @return int
1567
+	 * @throws EE_Error
1568
+	 * @throws ReflectionException
1569
+	 */
1570
+	public function update_tickets_sold()
1571
+	{
1572
+		$count_regs_for_this_ticket = $this->count_registrations(
1573
+			[
1574
+				[
1575
+					'STS_ID'      => EEM_Registration::status_id_approved,
1576
+					'REG_deleted' => 0,
1577
+				],
1578
+			]
1579
+		);
1580
+		$this->set_sold($count_regs_for_this_ticket);
1581
+		$this->save();
1582
+		return $count_regs_for_this_ticket;
1583
+	}
1584
+
1585
+
1586
+	/**
1587
+	 * Counts the registrations for this ticket
1588
+	 *
1589
+	 * @param array $query_params @see
1590
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1591
+	 * @return int
1592
+	 * @throws EE_Error
1593
+	 * @throws ReflectionException
1594
+	 */
1595
+	public function count_registrations($query_params = [])
1596
+	{
1597
+		return $this->count_related('Registration', $query_params);
1598
+	}
1599
+
1600
+
1601
+	/**
1602
+	 * Implementation for EEI_Has_Icon interface method.
1603
+	 *
1604
+	 * @return string
1605
+	 * @see EEI_Visual_Representation for comments
1606
+	 */
1607
+	public function get_icon()
1608
+	{
1609
+		return '<span class="dashicons dashicons-tickets-alt"/>';
1610
+	}
1611
+
1612
+
1613
+	/**
1614
+	 * Implementation of the EEI_Event_Relation interface method
1615
+	 *
1616
+	 * @return EE_Event
1617
+	 * @throws EE_Error
1618
+	 * @throws UnexpectedEntityException
1619
+	 * @throws ReflectionException
1620
+	 * @see EEI_Event_Relation for comments
1621
+	 */
1622
+	public function get_related_event()
1623
+	{
1624
+		// get one datetime to use for getting the event
1625
+		$datetime = $this->first_datetime();
1626
+		if (! $datetime instanceof EE_Datetime) {
1627
+			throw new UnexpectedEntityException(
1628
+				$datetime,
1629
+				'EE_Datetime',
1630
+				sprintf(
1631
+					__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1632
+					$this->name()
1633
+				)
1634
+			);
1635
+		}
1636
+		$event = $datetime->event();
1637
+		if (! $event instanceof EE_Event) {
1638
+			throw new UnexpectedEntityException(
1639
+				$event,
1640
+				'EE_Event',
1641
+				sprintf(
1642
+					__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1643
+					$this->name()
1644
+				)
1645
+			);
1646
+		}
1647
+		return $event;
1648
+	}
1649
+
1650
+
1651
+	/**
1652
+	 * Implementation of the EEI_Event_Relation interface method
1653
+	 *
1654
+	 * @return string
1655
+	 * @throws UnexpectedEntityException
1656
+	 * @throws EE_Error
1657
+	 * @throws ReflectionException
1658
+	 * @see EEI_Event_Relation for comments
1659
+	 */
1660
+	public function get_event_name()
1661
+	{
1662
+		$event = $this->get_related_event();
1663
+		return $event instanceof EE_Event ? $event->name() : '';
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 * Implementation of the EEI_Event_Relation interface method
1669
+	 *
1670
+	 * @return int
1671
+	 * @throws UnexpectedEntityException
1672
+	 * @throws EE_Error
1673
+	 * @throws ReflectionException
1674
+	 * @see EEI_Event_Relation for comments
1675
+	 */
1676
+	public function get_event_ID()
1677
+	{
1678
+		$event = $this->get_related_event();
1679
+		return $event instanceof EE_Event ? $event->ID() : 0;
1680
+	}
1681
+
1682
+
1683
+	/**
1684
+	 * This simply returns whether a ticket can be permanently deleted or not.
1685
+	 * The criteria for determining this is whether the ticket has any related registrations.
1686
+	 * If there are none then it can be permanently deleted.
1687
+	 *
1688
+	 * @return bool
1689
+	 * @throws EE_Error
1690
+	 * @throws ReflectionException
1691
+	 */
1692
+	public function is_permanently_deleteable()
1693
+	{
1694
+		return $this->count_registrations() === 0;
1695
+	}
1696
+
1697
+
1698
+	/**
1699
+	 * @return int
1700
+	 * @throws EE_Error
1701
+	 * @throws ReflectionException
1702
+	 * @since   $VID:$
1703
+	 */
1704
+	public function visibility(): int
1705
+	{
1706
+		return $this->get('TKT_visibility');
1707
+	}
1708
+
1709
+
1710
+	/**
1711
+	 * @return int
1712
+	 * @throws EE_Error
1713
+	 * @throws ReflectionException
1714
+	 * @since   $VID:$
1715
+	 */
1716
+	public function isHidden(): int
1717
+	{
1718
+		return $this->visibility() === EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1719
+	}
1720
+
1721
+
1722
+	/**
1723
+	 * @return int
1724
+	 * @throws EE_Error
1725
+	 * @throws ReflectionException
1726
+	 * @since   $VID:$
1727
+	 */
1728
+	public function isNotHidden(): int
1729
+	{
1730
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1731
+	}
1732
+
1733
+
1734
+	/**
1735
+	 * @return int
1736
+	 * @throws EE_Error
1737
+	 * @throws ReflectionException
1738
+	 * @since   $VID:$
1739
+	 */
1740
+	public function isPublicOnly(): int
1741
+	{
1742
+		return $this->isNotHidden() && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE;
1743
+	}
1744
+
1745
+
1746
+	/**
1747
+	 * @return int
1748
+	 * @throws EE_Error
1749
+	 * @throws ReflectionException
1750
+	 * @since   $VID:$
1751
+	 */
1752
+	public function isMembersOnly(): int
1753
+	{
1754
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE
1755
+			   && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE;
1756
+	}
1757
+
1758
+
1759
+	/**
1760
+	 * @return int
1761
+	 * @throws EE_Error
1762
+	 * @throws ReflectionException
1763
+	 * @since   $VID:$
1764
+	 */
1765
+	public function isAdminsOnly(): int
1766
+	{
1767
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE
1768
+			   && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE;
1769
+	}
1770
+
1771
+
1772
+	/**
1773
+	 * @return int
1774
+	 * @throws EE_Error
1775
+	 * @throws ReflectionException
1776
+	 * @since   $VID:$
1777
+	 */
1778
+	public function isAdminUiOnly(): int
1779
+	{
1780
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE
1781
+			   && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMIN_UI_ONLY_VALUE;
1782
+	}
1783
+
1784
+
1785
+	/**
1786
+	 * @param int $visibility
1787
+	 * @throws EE_Error
1788
+	 * @throws ReflectionException
1789
+	 * @since   $VID:$
1790
+	 */
1791
+	public function set_visibility(int $visibility)
1792
+	{
1793
+
1794
+		$ticket_visibility_options = $this->_model->ticketVisibilityOptions();
1795
+		$ticket_visibility         = -1;
1796
+		foreach ($ticket_visibility_options as $ticket_visibility_option) {
1797
+			if ($visibility === $ticket_visibility_option) {
1798
+				$ticket_visibility = $visibility;
1799
+			}
1800
+		}
1801
+		if ($ticket_visibility === -1) {
1802
+			throw new DomainException(
1803
+				sprintf(
1804
+					esc_html__(
1805
+						'The supplied ticket visibility setting of "%1$s" is not valid. It needs to match one of the keys in the following array:%2$s %3$s ',
1806
+						'event_espresso'
1807
+					),
1808
+					$visibility,
1809
+					'<br />',
1810
+					var_export($ticket_visibility_options, true)
1811
+				)
1812
+			);
1813
+		}
1814
+		$this->set('TKT_visibility', $ticket_visibility);
1815
+	}
1816
+
1817
+
1818
+	/**
1819
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1820
+	 * @param string                   $relationName
1821
+	 * @param array                    $extra_join_model_fields_n_values
1822
+	 * @param string|null              $cache_id
1823
+	 * @return EE_Base_Class
1824
+	 * @throws EE_Error
1825
+	 * @throws ReflectionException
1826
+	 * @since   $VID:$
1827
+	 */
1828
+	public function _add_relation_to(
1829
+		$otherObjectModelObjectOrID,
1830
+		$relationName,
1831
+		$extra_join_model_fields_n_values = [],
1832
+		$cache_id = null
1833
+	) {
1834
+		if ($relationName === 'Datetime') {
1835
+			/** @var EE_Datetime $datetime */
1836
+			$datetime = EEM_Datetime::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1837
+			$datetime->increaseSold($this->sold());
1838
+			$datetime->increaseReserved($this->reserved());
1839
+			$datetime->save();
1840
+			$otherObjectModelObjectOrID = $datetime;
1841
+		}
1842
+		return parent::_add_relation_to(
1843
+			$otherObjectModelObjectOrID,
1844
+			$relationName,
1845
+			$extra_join_model_fields_n_values,
1846
+			$cache_id
1847
+		);
1848
+	}
1849
+
1850
+
1851
+	/**
1852
+	 * @param EE_Base_Class|int|string $otherObjectModelObjectOrID
1853
+	 * @param string                   $relationName
1854
+	 * @param array                    $where_query
1855
+	 * @return bool|EE_Base_Class|null
1856
+	 * @throws EE_Error
1857
+	 * @throws ReflectionException
1858
+	 * @since   $VID:$
1859
+	 */
1860
+	public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = [])
1861
+	{
1862
+		if ($relationName === 'Datetime') {
1863
+			/** @var EE_Datetime $datetime */
1864
+			$datetime = EEM_Datetime::instance()->ensure_is_obj($otherObjectModelObjectOrID);
1865
+			$datetime->decreaseSold($this->sold());
1866
+			$datetime->decreaseReserved($this->reserved());
1867
+			$datetime->save();
1868
+			$otherObjectModelObjectOrID = $datetime;
1869
+		}
1870
+		return parent::_remove_relation_to(
1871
+			$otherObjectModelObjectOrID,
1872
+			$relationName,
1873
+			$where_query
1874
+		);
1875
+	}
1876
+
1877
+
1878
+	/*******************************************************************
1879 1879
      ***********************  DEPRECATED METHODS  **********************
1880 1880
      *******************************************************************/
1881 1881
 
1882 1882
 
1883
-    /**
1884
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1885
-     * associated datetimes.
1886
-     *
1887
-     * @param int $qty
1888
-     * @return void
1889
-     * @throws EE_Error
1890
-     * @throws InvalidArgumentException
1891
-     * @throws InvalidDataTypeException
1892
-     * @throws InvalidInterfaceException
1893
-     * @throws ReflectionException
1894
-     * @deprecated 4.9.80.p
1895
-     */
1896
-    public function increase_sold($qty = 1)
1897
-    {
1898
-        EE_Error::doing_it_wrong(
1899
-            __FUNCTION__,
1900
-            esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1901
-            '4.9.80.p',
1902
-            '5.0.0.p'
1903
-        );
1904
-        $this->increaseSold($qty);
1905
-    }
1906
-
1907
-
1908
-    /**
1909
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1910
-     *
1911
-     * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1912
-     *                 Negative means to decreases old counts (and increase reserved counts).
1913
-     * @throws EE_Error
1914
-     * @throws InvalidArgumentException
1915
-     * @throws InvalidDataTypeException
1916
-     * @throws InvalidInterfaceException
1917
-     * @throws ReflectionException
1918
-     * @deprecated 4.9.80.p
1919
-     */
1920
-    protected function _increase_sold_for_datetimes($qty)
1921
-    {
1922
-        EE_Error::doing_it_wrong(
1923
-            __FUNCTION__,
1924
-            esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1925
-            '4.9.80.p',
1926
-            '5.0.0.p'
1927
-        );
1928
-        $this->increaseSoldForDatetimes($qty);
1929
-    }
1930
-
1931
-
1932
-    /**
1933
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1934
-     * DB and then updates the model objects.
1935
-     * Does not affect the reserved counts.
1936
-     *
1937
-     * @param int $qty
1938
-     * @return void
1939
-     * @throws EE_Error
1940
-     * @throws InvalidArgumentException
1941
-     * @throws InvalidDataTypeException
1942
-     * @throws InvalidInterfaceException
1943
-     * @throws ReflectionException
1944
-     * @deprecated 4.9.80.p
1945
-     */
1946
-    public function decrease_sold($qty = 1)
1947
-    {
1948
-        EE_Error::doing_it_wrong(
1949
-            __FUNCTION__,
1950
-            esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1951
-            '4.9.80.p',
1952
-            '5.0.0.p'
1953
-        );
1954
-        $this->decreaseSold($qty);
1955
-    }
1956
-
1957
-
1958
-    /**
1959
-     * Decreases sold on related datetimes
1960
-     *
1961
-     * @param int $qty
1962
-     * @return void
1963
-     * @throws EE_Error
1964
-     * @throws InvalidArgumentException
1965
-     * @throws InvalidDataTypeException
1966
-     * @throws InvalidInterfaceException
1967
-     * @throws ReflectionException
1968
-     * @deprecated 4.9.80.p
1969
-     */
1970
-    protected function _decrease_sold_for_datetimes($qty = 1)
1971
-    {
1972
-        EE_Error::doing_it_wrong(
1973
-            __FUNCTION__,
1974
-            esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1975
-            '4.9.80.p',
1976
-            '5.0.0.p'
1977
-        );
1978
-        $this->decreaseSoldForDatetimes($qty);
1979
-    }
1980
-
1981
-
1982
-    /**
1983
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1984
-     *
1985
-     * @param int    $qty
1986
-     * @param string $source
1987
-     * @return bool whether we successfully reserved the ticket or not.
1988
-     * @throws EE_Error
1989
-     * @throws InvalidArgumentException
1990
-     * @throws ReflectionException
1991
-     * @throws InvalidDataTypeException
1992
-     * @throws InvalidInterfaceException
1993
-     * @deprecated 4.9.80.p
1994
-     */
1995
-    public function increase_reserved($qty = 1, $source = 'unknown')
1996
-    {
1997
-        EE_Error::doing_it_wrong(
1998
-            __FUNCTION__,
1999
-            esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
2000
-            '4.9.80.p',
2001
-            '5.0.0.p'
2002
-        );
2003
-        return $this->increaseReserved($qty);
2004
-    }
2005
-
2006
-
2007
-    /**
2008
-     * Increases sold on related datetimes
2009
-     *
2010
-     * @param int $qty
2011
-     * @return boolean indicating success
2012
-     * @throws EE_Error
2013
-     * @throws InvalidArgumentException
2014
-     * @throws InvalidDataTypeException
2015
-     * @throws InvalidInterfaceException
2016
-     * @throws ReflectionException
2017
-     * @deprecated 4.9.80.p
2018
-     */
2019
-    protected function _increase_reserved_for_datetimes($qty = 1)
2020
-    {
2021
-        EE_Error::doing_it_wrong(
2022
-            __FUNCTION__,
2023
-            esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
2024
-            '4.9.80.p',
2025
-            '5.0.0.p'
2026
-        );
2027
-        return $this->increaseReservedForDatetimes($qty);
2028
-    }
2029
-
2030
-
2031
-    /**
2032
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
2033
-     *
2034
-     * @param int    $qty
2035
-     * @param bool   $adjust_datetimes
2036
-     * @param string $source
2037
-     * @return void
2038
-     * @throws EE_Error
2039
-     * @throws InvalidArgumentException
2040
-     * @throws ReflectionException
2041
-     * @throws InvalidDataTypeException
2042
-     * @throws InvalidInterfaceException
2043
-     * @deprecated 4.9.80.p
2044
-     */
2045
-    public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
2046
-    {
2047
-        EE_Error::doing_it_wrong(
2048
-            __FUNCTION__,
2049
-            esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
2050
-            '4.9.80.p',
2051
-            '5.0.0.p'
2052
-        );
2053
-        $this->decreaseReserved($qty);
2054
-    }
2055
-
2056
-
2057
-    /**
2058
-     * Decreases reserved on related datetimes
2059
-     *
2060
-     * @param int $qty
2061
-     * @return void
2062
-     * @throws EE_Error
2063
-     * @throws InvalidArgumentException
2064
-     * @throws ReflectionException
2065
-     * @throws InvalidDataTypeException
2066
-     * @throws InvalidInterfaceException
2067
-     * @deprecated 4.9.80.p
2068
-     */
2069
-    protected function _decrease_reserved_for_datetimes($qty = 1)
2070
-    {
2071
-        EE_Error::doing_it_wrong(
2072
-            __FUNCTION__,
2073
-            esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
2074
-            '4.9.80.p',
2075
-            '5.0.0.p'
2076
-        );
2077
-        $this->decreaseReservedForDatetimes($qty);
2078
-    }
1883
+	/**
1884
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1885
+	 * associated datetimes.
1886
+	 *
1887
+	 * @param int $qty
1888
+	 * @return void
1889
+	 * @throws EE_Error
1890
+	 * @throws InvalidArgumentException
1891
+	 * @throws InvalidDataTypeException
1892
+	 * @throws InvalidInterfaceException
1893
+	 * @throws ReflectionException
1894
+	 * @deprecated 4.9.80.p
1895
+	 */
1896
+	public function increase_sold($qty = 1)
1897
+	{
1898
+		EE_Error::doing_it_wrong(
1899
+			__FUNCTION__,
1900
+			esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1901
+			'4.9.80.p',
1902
+			'5.0.0.p'
1903
+		);
1904
+		$this->increaseSold($qty);
1905
+	}
1906
+
1907
+
1908
+	/**
1909
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1910
+	 *
1911
+	 * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1912
+	 *                 Negative means to decreases old counts (and increase reserved counts).
1913
+	 * @throws EE_Error
1914
+	 * @throws InvalidArgumentException
1915
+	 * @throws InvalidDataTypeException
1916
+	 * @throws InvalidInterfaceException
1917
+	 * @throws ReflectionException
1918
+	 * @deprecated 4.9.80.p
1919
+	 */
1920
+	protected function _increase_sold_for_datetimes($qty)
1921
+	{
1922
+		EE_Error::doing_it_wrong(
1923
+			__FUNCTION__,
1924
+			esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1925
+			'4.9.80.p',
1926
+			'5.0.0.p'
1927
+		);
1928
+		$this->increaseSoldForDatetimes($qty);
1929
+	}
1930
+
1931
+
1932
+	/**
1933
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1934
+	 * DB and then updates the model objects.
1935
+	 * Does not affect the reserved counts.
1936
+	 *
1937
+	 * @param int $qty
1938
+	 * @return void
1939
+	 * @throws EE_Error
1940
+	 * @throws InvalidArgumentException
1941
+	 * @throws InvalidDataTypeException
1942
+	 * @throws InvalidInterfaceException
1943
+	 * @throws ReflectionException
1944
+	 * @deprecated 4.9.80.p
1945
+	 */
1946
+	public function decrease_sold($qty = 1)
1947
+	{
1948
+		EE_Error::doing_it_wrong(
1949
+			__FUNCTION__,
1950
+			esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1951
+			'4.9.80.p',
1952
+			'5.0.0.p'
1953
+		);
1954
+		$this->decreaseSold($qty);
1955
+	}
1956
+
1957
+
1958
+	/**
1959
+	 * Decreases sold on related datetimes
1960
+	 *
1961
+	 * @param int $qty
1962
+	 * @return void
1963
+	 * @throws EE_Error
1964
+	 * @throws InvalidArgumentException
1965
+	 * @throws InvalidDataTypeException
1966
+	 * @throws InvalidInterfaceException
1967
+	 * @throws ReflectionException
1968
+	 * @deprecated 4.9.80.p
1969
+	 */
1970
+	protected function _decrease_sold_for_datetimes($qty = 1)
1971
+	{
1972
+		EE_Error::doing_it_wrong(
1973
+			__FUNCTION__,
1974
+			esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1975
+			'4.9.80.p',
1976
+			'5.0.0.p'
1977
+		);
1978
+		$this->decreaseSoldForDatetimes($qty);
1979
+	}
1980
+
1981
+
1982
+	/**
1983
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1984
+	 *
1985
+	 * @param int    $qty
1986
+	 * @param string $source
1987
+	 * @return bool whether we successfully reserved the ticket or not.
1988
+	 * @throws EE_Error
1989
+	 * @throws InvalidArgumentException
1990
+	 * @throws ReflectionException
1991
+	 * @throws InvalidDataTypeException
1992
+	 * @throws InvalidInterfaceException
1993
+	 * @deprecated 4.9.80.p
1994
+	 */
1995
+	public function increase_reserved($qty = 1, $source = 'unknown')
1996
+	{
1997
+		EE_Error::doing_it_wrong(
1998
+			__FUNCTION__,
1999
+			esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
2000
+			'4.9.80.p',
2001
+			'5.0.0.p'
2002
+		);
2003
+		return $this->increaseReserved($qty);
2004
+	}
2005
+
2006
+
2007
+	/**
2008
+	 * Increases sold on related datetimes
2009
+	 *
2010
+	 * @param int $qty
2011
+	 * @return boolean indicating success
2012
+	 * @throws EE_Error
2013
+	 * @throws InvalidArgumentException
2014
+	 * @throws InvalidDataTypeException
2015
+	 * @throws InvalidInterfaceException
2016
+	 * @throws ReflectionException
2017
+	 * @deprecated 4.9.80.p
2018
+	 */
2019
+	protected function _increase_reserved_for_datetimes($qty = 1)
2020
+	{
2021
+		EE_Error::doing_it_wrong(
2022
+			__FUNCTION__,
2023
+			esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
2024
+			'4.9.80.p',
2025
+			'5.0.0.p'
2026
+		);
2027
+		return $this->increaseReservedForDatetimes($qty);
2028
+	}
2029
+
2030
+
2031
+	/**
2032
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
2033
+	 *
2034
+	 * @param int    $qty
2035
+	 * @param bool   $adjust_datetimes
2036
+	 * @param string $source
2037
+	 * @return void
2038
+	 * @throws EE_Error
2039
+	 * @throws InvalidArgumentException
2040
+	 * @throws ReflectionException
2041
+	 * @throws InvalidDataTypeException
2042
+	 * @throws InvalidInterfaceException
2043
+	 * @deprecated 4.9.80.p
2044
+	 */
2045
+	public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
2046
+	{
2047
+		EE_Error::doing_it_wrong(
2048
+			__FUNCTION__,
2049
+			esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
2050
+			'4.9.80.p',
2051
+			'5.0.0.p'
2052
+		);
2053
+		$this->decreaseReserved($qty);
2054
+	}
2055
+
2056
+
2057
+	/**
2058
+	 * Decreases reserved on related datetimes
2059
+	 *
2060
+	 * @param int $qty
2061
+	 * @return void
2062
+	 * @throws EE_Error
2063
+	 * @throws InvalidArgumentException
2064
+	 * @throws ReflectionException
2065
+	 * @throws InvalidDataTypeException
2066
+	 * @throws InvalidInterfaceException
2067
+	 * @deprecated 4.9.80.p
2068
+	 */
2069
+	protected function _decrease_reserved_for_datetimes($qty = 1)
2070
+	{
2071
+		EE_Error::doing_it_wrong(
2072
+			__FUNCTION__,
2073
+			esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
2074
+			'4.9.80.p',
2075
+			'5.0.0.p'
2076
+		);
2077
+		$this->decreaseReservedForDatetimes($qty);
2078
+	}
2079 2079
 }
Please login to merge, or discard this patch.
caffeinated/admin/new/pricing/espresso_events_Pricing_Hooks.class.php 2 patches
Indentation   +2143 added lines, -2143 removed lines patch added patch discarded remove patch
@@ -15,2205 +15,2205 @@
 block discarded – undo
15 15
 class espresso_events_Pricing_Hooks extends EE_Admin_Hooks
16 16
 {
17 17
 
18
-    /**
19
-     * This property is just used to hold the status of whether an event is currently being
20
-     * created (true) or edited (false)
21
-     *
22
-     * @access protected
23
-     * @var bool
24
-     */
25
-    protected $_is_creating_event;
18
+	/**
19
+	 * This property is just used to hold the status of whether an event is currently being
20
+	 * created (true) or edited (false)
21
+	 *
22
+	 * @access protected
23
+	 * @var bool
24
+	 */
25
+	protected $_is_creating_event;
26 26
 
27
-    /**
28
-     * Used to contain the format strings for date and time that will be used for php date and
29
-     * time.
30
-     * Is set in the _set_hooks_properties() method.
31
-     *
32
-     * @var array
33
-     */
34
-    protected $_date_format_strings;
27
+	/**
28
+	 * Used to contain the format strings for date and time that will be used for php date and
29
+	 * time.
30
+	 * Is set in the _set_hooks_properties() method.
31
+	 *
32
+	 * @var array
33
+	 */
34
+	protected $_date_format_strings;
35 35
 
36
-    /**
37
-     * @var string $_date_time_format
38
-     */
39
-    protected $_date_time_format;
36
+	/**
37
+	 * @var string $_date_time_format
38
+	 */
39
+	protected $_date_time_format;
40 40
 
41 41
 
42
-    /**
43
-     * @throws InvalidArgumentException
44
-     * @throws InvalidInterfaceException
45
-     * @throws InvalidDataTypeException
46
-     */
47
-    protected function _set_hooks_properties()
48
-    {
49
-        $this->_name = 'pricing';
50
-        // capability check
51
-        if (
52
-            $this->_adminpage_obj->adminConfig()->useAdvancedEditor()
53
-            || ! EE_Registry::instance()->CAP->current_user_can(
54
-                'ee_read_default_prices',
55
-                'advanced_ticket_datetime_metabox'
56
-            )
57
-        ) {
58
-            $this->_metaboxes      = [];
59
-            $this->_scripts_styles = [];
60
-            return;
61
-        }
62
-        $this->_setup_metaboxes();
63
-        $this->_set_date_time_formats();
64
-        $this->_validate_format_strings();
65
-        $this->_set_scripts_styles();
66
-        // commented out temporarily until logic is implemented in callback
67
-        // add_action(
68
-        //     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
69
-        //     array($this, 'autosave_handling')
70
-        // );
71
-        add_filter(
72
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
73
-            array($this, 'caf_updates')
74
-        );
75
-    }
42
+	/**
43
+	 * @throws InvalidArgumentException
44
+	 * @throws InvalidInterfaceException
45
+	 * @throws InvalidDataTypeException
46
+	 */
47
+	protected function _set_hooks_properties()
48
+	{
49
+		$this->_name = 'pricing';
50
+		// capability check
51
+		if (
52
+			$this->_adminpage_obj->adminConfig()->useAdvancedEditor()
53
+			|| ! EE_Registry::instance()->CAP->current_user_can(
54
+				'ee_read_default_prices',
55
+				'advanced_ticket_datetime_metabox'
56
+			)
57
+		) {
58
+			$this->_metaboxes      = [];
59
+			$this->_scripts_styles = [];
60
+			return;
61
+		}
62
+		$this->_setup_metaboxes();
63
+		$this->_set_date_time_formats();
64
+		$this->_validate_format_strings();
65
+		$this->_set_scripts_styles();
66
+		// commented out temporarily until logic is implemented in callback
67
+		// add_action(
68
+		//     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
69
+		//     array($this, 'autosave_handling')
70
+		// );
71
+		add_filter(
72
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
73
+			array($this, 'caf_updates')
74
+		);
75
+	}
76 76
 
77 77
 
78
-    /**
79
-     * @return void
80
-     */
81
-    protected function _setup_metaboxes()
82
-    {
83
-        // if we were going to add our own metaboxes we'd use the below.
84
-        $this->_metaboxes = array(
85
-            0 => array(
86
-                'page_route' => array('edit', 'create_new'),
87
-                'func'       => 'pricing_metabox',
88
-                'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
89
-                'priority'   => 'high',
90
-                'context'    => 'normal',
91
-            ),
92
-        );
93
-        $this->_remove_metaboxes = array(
94
-            0 => array(
95
-                'page_route' => array('edit', 'create_new'),
96
-                'id'         => 'espresso_event_editor_tickets',
97
-                'context'    => 'normal',
98
-            ),
99
-        );
100
-    }
78
+	/**
79
+	 * @return void
80
+	 */
81
+	protected function _setup_metaboxes()
82
+	{
83
+		// if we were going to add our own metaboxes we'd use the below.
84
+		$this->_metaboxes = array(
85
+			0 => array(
86
+				'page_route' => array('edit', 'create_new'),
87
+				'func'       => 'pricing_metabox',
88
+				'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
89
+				'priority'   => 'high',
90
+				'context'    => 'normal',
91
+			),
92
+		);
93
+		$this->_remove_metaboxes = array(
94
+			0 => array(
95
+				'page_route' => array('edit', 'create_new'),
96
+				'id'         => 'espresso_event_editor_tickets',
97
+				'context'    => 'normal',
98
+			),
99
+		);
100
+	}
101 101
 
102 102
 
103
-    /**
104
-     * @return void
105
-     */
106
-    protected function _set_date_time_formats()
107
-    {
108
-        /**
109
-         * Format strings for date and time.  Defaults are existing behaviour from 4.1.
110
-         * Note, that if you return null as the value for 'date', and 'time' in the array, then
111
-         * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
112
-         *
113
-         * @since 4.6.7
114
-         * @var array  Expected an array returned with 'date' and 'time' keys.
115
-         */
116
-        $this->_date_format_strings = apply_filters(
117
-            'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
118
-            array(
119
-                'date' => 'Y-m-d',
120
-                'time' => 'h:i a',
121
-            )
122
-        );
123
-        // validate
124
-        $this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
125
-            ? $this->_date_format_strings['date']
126
-            : null;
127
-        $this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
128
-            ? $this->_date_format_strings['time']
129
-            : null;
130
-        $this->_date_time_format = $this->_date_format_strings['date']
131
-                                   . ' '
132
-                                   . $this->_date_format_strings['time'];
133
-    }
103
+	/**
104
+	 * @return void
105
+	 */
106
+	protected function _set_date_time_formats()
107
+	{
108
+		/**
109
+		 * Format strings for date and time.  Defaults are existing behaviour from 4.1.
110
+		 * Note, that if you return null as the value for 'date', and 'time' in the array, then
111
+		 * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
112
+		 *
113
+		 * @since 4.6.7
114
+		 * @var array  Expected an array returned with 'date' and 'time' keys.
115
+		 */
116
+		$this->_date_format_strings = apply_filters(
117
+			'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
118
+			array(
119
+				'date' => 'Y-m-d',
120
+				'time' => 'h:i a',
121
+			)
122
+		);
123
+		// validate
124
+		$this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
125
+			? $this->_date_format_strings['date']
126
+			: null;
127
+		$this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
128
+			? $this->_date_format_strings['time']
129
+			: null;
130
+		$this->_date_time_format = $this->_date_format_strings['date']
131
+								   . ' '
132
+								   . $this->_date_format_strings['time'];
133
+	}
134 134
 
135 135
 
136
-    /**
137
-     * @return void
138
-     */
139
-    protected function _validate_format_strings()
140
-    {
141
-        // validate format strings
142
-        $format_validation = EEH_DTT_Helper::validate_format_string(
143
-            $this->_date_time_format
144
-        );
145
-        if (is_array($format_validation)) {
146
-            $msg = '<p>';
147
-            $msg .= sprintf(
148
-                esc_html__(
149
-                    'The format "%s" was likely added via a filter and is invalid for the following reasons:',
150
-                    'event_espresso'
151
-                ),
152
-                $this->_date_time_format
153
-            );
154
-            $msg .= '</p><ul>';
155
-            foreach ($format_validation as $error) {
156
-                $msg .= '<li>' . $error . '</li>';
157
-            }
158
-            $msg .= '</ul><p>';
159
-            $msg .= sprintf(
160
-                esc_html__(
161
-                    '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
162
-                    'event_espresso'
163
-                ),
164
-                '<span style="color:#D54E21;">',
165
-                '</span>'
166
-            );
167
-            $msg .= '</p>';
168
-            EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
169
-            $this->_date_format_strings = array(
170
-                'date' => 'Y-m-d',
171
-                'time' => 'h:i a',
172
-            );
173
-        }
174
-    }
136
+	/**
137
+	 * @return void
138
+	 */
139
+	protected function _validate_format_strings()
140
+	{
141
+		// validate format strings
142
+		$format_validation = EEH_DTT_Helper::validate_format_string(
143
+			$this->_date_time_format
144
+		);
145
+		if (is_array($format_validation)) {
146
+			$msg = '<p>';
147
+			$msg .= sprintf(
148
+				esc_html__(
149
+					'The format "%s" was likely added via a filter and is invalid for the following reasons:',
150
+					'event_espresso'
151
+				),
152
+				$this->_date_time_format
153
+			);
154
+			$msg .= '</p><ul>';
155
+			foreach ($format_validation as $error) {
156
+				$msg .= '<li>' . $error . '</li>';
157
+			}
158
+			$msg .= '</ul><p>';
159
+			$msg .= sprintf(
160
+				esc_html__(
161
+					'%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
162
+					'event_espresso'
163
+				),
164
+				'<span style="color:#D54E21;">',
165
+				'</span>'
166
+			);
167
+			$msg .= '</p>';
168
+			EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
169
+			$this->_date_format_strings = array(
170
+				'date' => 'Y-m-d',
171
+				'time' => 'h:i a',
172
+			);
173
+		}
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * @return void
179
-     */
180
-    protected function _set_scripts_styles()
181
-    {
182
-        $this->_scripts_styles = array(
183
-            'registers'   => array(
184
-                'ee-tickets-datetimes-css' => array(
185
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
186
-                    'type' => 'css',
187
-                ),
188
-                'ee-dtt-ticket-metabox'    => array(
189
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
190
-                    'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
191
-                ),
192
-            ),
193
-            'deregisters' => array(
194
-                'event-editor-css'       => array('type' => 'css'),
195
-                'event-datetime-metabox' => array('type' => 'js'),
196
-            ),
197
-            'enqueues'    => array(
198
-                'ee-tickets-datetimes-css' => array('edit', 'create_new'),
199
-                'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
200
-            ),
201
-            'localize'    => array(
202
-                'ee-dtt-ticket-metabox' => array(
203
-                    'DTT_TRASH_BLOCK'       => array(
204
-                        'main_warning'            => esc_html__(
205
-                            'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
206
-                            'event_espresso'
207
-                        ),
208
-                        'after_warning'           => esc_html__(
209
-                            'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
210
-                            'event_espresso'
211
-                        ),
212
-                        'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
213
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
214
-                        'close_button'            => '<button class="button-secondary ee-modal-cancel">'
215
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
216
-                        'single_warning_from_tkt' => esc_html__(
217
-                            '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.',
218
-                            'event_espresso'
219
-                        ),
220
-                        'single_warning_from_dtt' => esc_html__(
221
-                            '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.',
222
-                            'event_espresso'
223
-                        ),
224
-                        'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
225
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
226
-                    ),
227
-                    'DTT_ERROR_MSG'         => array(
228
-                        'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
229
-                        'dismiss_button' => '<div class="save-cancel-button-container">'
230
-                                            . '<button class="button-secondary ee-modal-cancel">'
231
-                                            . esc_html__('Dismiss', 'event_espresso')
232
-                                            . '</button></div>',
233
-                    ),
234
-                    'DTT_OVERSELL_WARNING'  => array(
235
-                        'datetime_ticket' => esc_html__(
236
-                            '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.',
237
-                            'event_espresso'
238
-                        ),
239
-                        'ticket_datetime' => esc_html__(
240
-                            '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.',
241
-                            'event_espresso'
242
-                        ),
243
-                    ),
244
-                    'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
245
-                        $this->_date_format_strings['date'],
246
-                        $this->_date_format_strings['time']
247
-                    ),
248
-                    'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
249
-                ),
250
-            ),
251
-        );
252
-    }
177
+	/**
178
+	 * @return void
179
+	 */
180
+	protected function _set_scripts_styles()
181
+	{
182
+		$this->_scripts_styles = array(
183
+			'registers'   => array(
184
+				'ee-tickets-datetimes-css' => array(
185
+					'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
186
+					'type' => 'css',
187
+				),
188
+				'ee-dtt-ticket-metabox'    => array(
189
+					'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
190
+					'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
191
+				),
192
+			),
193
+			'deregisters' => array(
194
+				'event-editor-css'       => array('type' => 'css'),
195
+				'event-datetime-metabox' => array('type' => 'js'),
196
+			),
197
+			'enqueues'    => array(
198
+				'ee-tickets-datetimes-css' => array('edit', 'create_new'),
199
+				'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
200
+			),
201
+			'localize'    => array(
202
+				'ee-dtt-ticket-metabox' => array(
203
+					'DTT_TRASH_BLOCK'       => array(
204
+						'main_warning'            => esc_html__(
205
+							'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
206
+							'event_espresso'
207
+						),
208
+						'after_warning'           => esc_html__(
209
+							'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
210
+							'event_espresso'
211
+						),
212
+						'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
213
+													 . esc_html__('Cancel', 'event_espresso') . '</button>',
214
+						'close_button'            => '<button class="button-secondary ee-modal-cancel">'
215
+													 . esc_html__('Close', 'event_espresso') . '</button>',
216
+						'single_warning_from_tkt' => esc_html__(
217
+							'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.',
218
+							'event_espresso'
219
+						),
220
+						'single_warning_from_dtt' => esc_html__(
221
+							'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.',
222
+							'event_espresso'
223
+						),
224
+						'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
225
+													 . esc_html__('Dismiss', 'event_espresso') . '</button>',
226
+					),
227
+					'DTT_ERROR_MSG'         => array(
228
+						'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
229
+						'dismiss_button' => '<div class="save-cancel-button-container">'
230
+											. '<button class="button-secondary ee-modal-cancel">'
231
+											. esc_html__('Dismiss', 'event_espresso')
232
+											. '</button></div>',
233
+					),
234
+					'DTT_OVERSELL_WARNING'  => array(
235
+						'datetime_ticket' => esc_html__(
236
+							'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.',
237
+							'event_espresso'
238
+						),
239
+						'ticket_datetime' => esc_html__(
240
+							'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.',
241
+							'event_espresso'
242
+						),
243
+					),
244
+					'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
245
+						$this->_date_format_strings['date'],
246
+						$this->_date_format_strings['time']
247
+					),
248
+					'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
249
+				),
250
+			),
251
+		);
252
+	}
253 253
 
254 254
 
255
-    /**
256
-     * @param array $update_callbacks
257
-     * @return array
258
-     */
259
-    public function caf_updates(array $update_callbacks)
260
-    {
261
-        unset($update_callbacks['_default_tickets_update']);
262
-        $update_callbacks['datetime_and_tickets_caf_update'] = array($this, 'datetime_and_tickets_caf_update');
263
-        return $update_callbacks;
264
-    }
255
+	/**
256
+	 * @param array $update_callbacks
257
+	 * @return array
258
+	 */
259
+	public function caf_updates(array $update_callbacks)
260
+	{
261
+		unset($update_callbacks['_default_tickets_update']);
262
+		$update_callbacks['datetime_and_tickets_caf_update'] = array($this, 'datetime_and_tickets_caf_update');
263
+		return $update_callbacks;
264
+	}
265 265
 
266 266
 
267
-    /**
268
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
269
-     *
270
-     * @param  EE_Event $event The Event object we're attaching data to
271
-     * @param  array    $data  The request data from the form
272
-     * @throws ReflectionException
273
-     * @throws Exception
274
-     * @throws InvalidInterfaceException
275
-     * @throws InvalidDataTypeException
276
-     * @throws EE_Error
277
-     * @throws InvalidArgumentException
278
-     */
279
-    public function datetime_and_tickets_caf_update($event, $data)
280
-    {
281
-        // first we need to start with datetimes cause they are the "root" items attached to events.
282
-        $saved_datetimes = $this->_update_datetimes($event, $data);
283
-        // next tackle the tickets (and prices?)
284
-        $this->_update_tickets($event, $saved_datetimes, $data);
285
-    }
267
+	/**
268
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
269
+	 *
270
+	 * @param  EE_Event $event The Event object we're attaching data to
271
+	 * @param  array    $data  The request data from the form
272
+	 * @throws ReflectionException
273
+	 * @throws Exception
274
+	 * @throws InvalidInterfaceException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws EE_Error
277
+	 * @throws InvalidArgumentException
278
+	 */
279
+	public function datetime_and_tickets_caf_update($event, $data)
280
+	{
281
+		// first we need to start with datetimes cause they are the "root" items attached to events.
282
+		$saved_datetimes = $this->_update_datetimes($event, $data);
283
+		// next tackle the tickets (and prices?)
284
+		$this->_update_tickets($event, $saved_datetimes, $data);
285
+	}
286 286
 
287 287
 
288
-    /**
289
-     * update event_datetimes
290
-     *
291
-     * @param  EE_Event $event Event being updated
292
-     * @param  array    $data  the request data from the form
293
-     * @return EE_Datetime[]
294
-     * @throws Exception
295
-     * @throws ReflectionException
296
-     * @throws InvalidInterfaceException
297
-     * @throws InvalidDataTypeException
298
-     * @throws InvalidArgumentException
299
-     * @throws EE_Error
300
-     */
301
-    protected function _update_datetimes($event, $data)
302
-    {
303
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
304
-        $saved_dtt_ids = array();
305
-        $saved_dtt_objs = array();
306
-        if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
307
-            throw new InvalidArgumentException(
308
-                esc_html__(
309
-                    'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
310
-                    'event_espresso'
311
-                )
312
-            );
313
-        }
314
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
315
-            // trim all values to ensure any excess whitespace is removed.
316
-            $datetime_data = array_map(
317
-                function ($datetime_data) {
318
-                    return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
319
-                },
320
-                $datetime_data
321
-            );
322
-            $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
323
-                                            && ! empty($datetime_data['DTT_EVT_end'])
324
-                ? $datetime_data['DTT_EVT_end']
325
-                : $datetime_data['DTT_EVT_start'];
326
-            $datetime_values = array(
327
-                'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
328
-                    ? $datetime_data['DTT_ID']
329
-                    : null,
330
-                'DTT_name'        => ! empty($datetime_data['DTT_name'])
331
-                    ? $datetime_data['DTT_name']
332
-                    : '',
333
-                'DTT_description' => ! empty($datetime_data['DTT_description'])
334
-                    ? $datetime_data['DTT_description']
335
-                    : '',
336
-                'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
337
-                'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
338
-                'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
339
-                    ? EE_INF
340
-                    : $datetime_data['DTT_reg_limit'],
341
-                'DTT_order'       => ! isset($datetime_data['DTT_order'])
342
-                    ? $row
343
-                    : $datetime_data['DTT_order'],
344
-            );
345
-            // if we have an id then let's get existing object first and then set the new values.
346
-            // Otherwise we instantiate a new object for save.
347
-            if (! empty($datetime_data['DTT_ID'])) {
348
-                $datetime = EE_Registry::instance()
349
-                                       ->load_model('Datetime', array($timezone))
350
-                                       ->get_one_by_ID($datetime_data['DTT_ID']);
351
-                // set date and time format according to what is set in this class.
352
-                $datetime->set_date_format($this->_date_format_strings['date']);
353
-                $datetime->set_time_format($this->_date_format_strings['time']);
354
-                foreach ($datetime_values as $field => $value) {
355
-                    $datetime->set($field, $value);
356
-                }
357
-                // make sure the $dtt_id here is saved just in case
358
-                // after the add_relation_to() the autosave replaces it.
359
-                // We need to do this so we dont' TRASH the parent DTT.
360
-                // (save the ID for both key and value to avoid duplications)
361
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
362
-            } else {
363
-                $datetime = EE_Registry::instance()->load_class(
364
-                    'Datetime',
365
-                    array(
366
-                        $datetime_values,
367
-                        $timezone,
368
-                        array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
369
-                    ),
370
-                    false,
371
-                    false
372
-                );
373
-                foreach ($datetime_values as $field => $value) {
374
-                    $datetime->set($field, $value);
375
-                }
376
-            }
377
-            $datetime->save();
378
-            do_action(
379
-                'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
380
-                $datetime,
381
-                $row,
382
-                $datetime_data,
383
-                $data
384
-            );
385
-            $datetime = $event->_add_relation_to($datetime, 'Datetime');
386
-            // before going any further make sure our dates are setup correctly
387
-            // so that the end date is always equal or greater than the start date.
388
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
389
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
390
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
391
-                $datetime->save();
392
-            }
393
-            // now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
394
-            // because it is possible there was a new one created for the autosave.
395
-            // (save the ID for both key and value to avoid duplications)
396
-            $DTT_ID = $datetime->ID();
397
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
398
-            $saved_dtt_objs[ $row ] = $datetime;
399
-            // @todo if ANY of these updates fail then we want the appropriate global error message.
400
-        }
401
-        $event->save();
402
-        // now we need to REMOVE any datetimes that got deleted.
403
-        // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
404
-        // So its safe to permanently delete at this point.
405
-        $old_datetimes = explode(',', $data['datetime_IDs']);
406
-        $old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
407
-        if (is_array($old_datetimes)) {
408
-            $datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
409
-            foreach ($datetimes_to_delete as $id) {
410
-                $id = absint($id);
411
-                if (empty($id)) {
412
-                    continue;
413
-                }
414
-                $dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
415
-                // remove tkt relationships.
416
-                $related_tickets = $dtt_to_remove->get_many_related('Ticket');
417
-                foreach ($related_tickets as $tkt) {
418
-                    $dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
419
-                }
420
-                $event->_remove_relation_to($id, 'Datetime');
421
-                $dtt_to_remove->refresh_cache_of_related_objects();
422
-            }
423
-        }
424
-        return $saved_dtt_objs;
425
-    }
288
+	/**
289
+	 * update event_datetimes
290
+	 *
291
+	 * @param  EE_Event $event Event being updated
292
+	 * @param  array    $data  the request data from the form
293
+	 * @return EE_Datetime[]
294
+	 * @throws Exception
295
+	 * @throws ReflectionException
296
+	 * @throws InvalidInterfaceException
297
+	 * @throws InvalidDataTypeException
298
+	 * @throws InvalidArgumentException
299
+	 * @throws EE_Error
300
+	 */
301
+	protected function _update_datetimes($event, $data)
302
+	{
303
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
304
+		$saved_dtt_ids = array();
305
+		$saved_dtt_objs = array();
306
+		if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
307
+			throw new InvalidArgumentException(
308
+				esc_html__(
309
+					'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
310
+					'event_espresso'
311
+				)
312
+			);
313
+		}
314
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
315
+			// trim all values to ensure any excess whitespace is removed.
316
+			$datetime_data = array_map(
317
+				function ($datetime_data) {
318
+					return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
319
+				},
320
+				$datetime_data
321
+			);
322
+			$datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
323
+											&& ! empty($datetime_data['DTT_EVT_end'])
324
+				? $datetime_data['DTT_EVT_end']
325
+				: $datetime_data['DTT_EVT_start'];
326
+			$datetime_values = array(
327
+				'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
328
+					? $datetime_data['DTT_ID']
329
+					: null,
330
+				'DTT_name'        => ! empty($datetime_data['DTT_name'])
331
+					? $datetime_data['DTT_name']
332
+					: '',
333
+				'DTT_description' => ! empty($datetime_data['DTT_description'])
334
+					? $datetime_data['DTT_description']
335
+					: '',
336
+				'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
337
+				'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
338
+				'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
339
+					? EE_INF
340
+					: $datetime_data['DTT_reg_limit'],
341
+				'DTT_order'       => ! isset($datetime_data['DTT_order'])
342
+					? $row
343
+					: $datetime_data['DTT_order'],
344
+			);
345
+			// if we have an id then let's get existing object first and then set the new values.
346
+			// Otherwise we instantiate a new object for save.
347
+			if (! empty($datetime_data['DTT_ID'])) {
348
+				$datetime = EE_Registry::instance()
349
+									   ->load_model('Datetime', array($timezone))
350
+									   ->get_one_by_ID($datetime_data['DTT_ID']);
351
+				// set date and time format according to what is set in this class.
352
+				$datetime->set_date_format($this->_date_format_strings['date']);
353
+				$datetime->set_time_format($this->_date_format_strings['time']);
354
+				foreach ($datetime_values as $field => $value) {
355
+					$datetime->set($field, $value);
356
+				}
357
+				// make sure the $dtt_id here is saved just in case
358
+				// after the add_relation_to() the autosave replaces it.
359
+				// We need to do this so we dont' TRASH the parent DTT.
360
+				// (save the ID for both key and value to avoid duplications)
361
+				$saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
362
+			} else {
363
+				$datetime = EE_Registry::instance()->load_class(
364
+					'Datetime',
365
+					array(
366
+						$datetime_values,
367
+						$timezone,
368
+						array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
369
+					),
370
+					false,
371
+					false
372
+				);
373
+				foreach ($datetime_values as $field => $value) {
374
+					$datetime->set($field, $value);
375
+				}
376
+			}
377
+			$datetime->save();
378
+			do_action(
379
+				'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
380
+				$datetime,
381
+				$row,
382
+				$datetime_data,
383
+				$data
384
+			);
385
+			$datetime = $event->_add_relation_to($datetime, 'Datetime');
386
+			// before going any further make sure our dates are setup correctly
387
+			// so that the end date is always equal or greater than the start date.
388
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
389
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
390
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
391
+				$datetime->save();
392
+			}
393
+			// now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
394
+			// because it is possible there was a new one created for the autosave.
395
+			// (save the ID for both key and value to avoid duplications)
396
+			$DTT_ID = $datetime->ID();
397
+			$saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
398
+			$saved_dtt_objs[ $row ] = $datetime;
399
+			// @todo if ANY of these updates fail then we want the appropriate global error message.
400
+		}
401
+		$event->save();
402
+		// now we need to REMOVE any datetimes that got deleted.
403
+		// Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
404
+		// So its safe to permanently delete at this point.
405
+		$old_datetimes = explode(',', $data['datetime_IDs']);
406
+		$old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
407
+		if (is_array($old_datetimes)) {
408
+			$datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
409
+			foreach ($datetimes_to_delete as $id) {
410
+				$id = absint($id);
411
+				if (empty($id)) {
412
+					continue;
413
+				}
414
+				$dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
415
+				// remove tkt relationships.
416
+				$related_tickets = $dtt_to_remove->get_many_related('Ticket');
417
+				foreach ($related_tickets as $tkt) {
418
+					$dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
419
+				}
420
+				$event->_remove_relation_to($id, 'Datetime');
421
+				$dtt_to_remove->refresh_cache_of_related_objects();
422
+			}
423
+		}
424
+		return $saved_dtt_objs;
425
+	}
426 426
 
427 427
 
428
-    /**
429
-     * update tickets
430
-     *
431
-     * @param  EE_Event      $event           Event object being updated
432
-     * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
433
-     * @param  array         $data            incoming request data
434
-     * @return EE_Ticket[]
435
-     * @throws Exception
436
-     * @throws ReflectionException
437
-     * @throws InvalidInterfaceException
438
-     * @throws InvalidDataTypeException
439
-     * @throws InvalidArgumentException
440
-     * @throws EE_Error
441
-     */
442
-    protected function _update_tickets($event, $saved_datetimes, $data)
443
-    {
444
-        $new_tkt = null;
445
-        $new_default = null;
446
-        // stripslashes because WP filtered the $_POST ($data) array to add slashes
447
-        $data = stripslashes_deep($data);
448
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
449
-        $saved_tickets = $datetimes_on_existing = array();
450
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
451
-        if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
452
-            throw new InvalidArgumentException(
453
-                esc_html__(
454
-                    'The "edit_tickets" array is invalid therefore the event can not be updated.',
455
-                    'event_espresso'
456
-                )
457
-            );
458
-        }
459
-        foreach ($data['edit_tickets'] as $row => $tkt) {
460
-            $update_prices = $create_new_TKT = false;
461
-            // figure out what datetimes were added to the ticket
462
-            // and what datetimes were removed from the ticket in the session.
463
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
464
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
465
-            $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
466
-            $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
467
-            // trim inputs to ensure any excess whitespace is removed.
468
-            $tkt = array_map(
469
-                function ($ticket_data) {
470
-                    return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
471
-                },
472
-                $tkt
473
-            );
474
-            // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
475
-            // because we're doing calculations prior to using the models.
476
-            // note incoming ['TKT_price'] value is already in standard notation (via js).
477
-            $ticket_price = isset($tkt['TKT_price'])
478
-                ? round((float) $tkt['TKT_price'], 3)
479
-                : 0;
480
-            // note incoming base price needs converted from localized value.
481
-            $base_price = isset($tkt['TKT_base_price'])
482
-                ? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
483
-                : 0;
484
-            // if ticket price == 0 and $base_price != 0 then ticket price == base_price
485
-            $ticket_price = $ticket_price === 0 && $base_price !== 0
486
-                ? $base_price
487
-                : $ticket_price;
488
-            $base_price_id = isset($tkt['TKT_base_price_ID'])
489
-                ? $tkt['TKT_base_price_ID']
490
-                : 0;
491
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
492
-                ? $data['edit_prices'][ $row ]
493
-                : array();
494
-            $now = null;
495
-            if (empty($tkt['TKT_start_date'])) {
496
-                // lets' use now in the set timezone.
497
-                $now = new DateTime('now', new DateTimeZone($event->get_timezone()));
498
-                $tkt['TKT_start_date'] = $now->format($this->_date_time_format);
499
-            }
500
-            if (empty($tkt['TKT_end_date'])) {
501
-                /**
502
-                 * set the TKT_end_date to the first datetime attached to the ticket.
503
-                 */
504
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
505
-                $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
506
-            }
507
-            $TKT_values = array(
508
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
509
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
510
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
511
-                'TKT_description' => ! empty($tkt['TKT_description'])
512
-                                     && $tkt['TKT_description'] !== esc_html__(
513
-                                         'You can modify this description',
514
-                                         'event_espresso'
515
-                                     )
516
-                    ? $tkt['TKT_description']
517
-                    : '',
518
-                'TKT_start_date'  => $tkt['TKT_start_date'],
519
-                'TKT_end_date'    => $tkt['TKT_end_date'],
520
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
521
-                    ? EE_INF
522
-                    : $tkt['TKT_qty'],
523
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
524
-                    ? EE_INF
525
-                    : $tkt['TKT_uses'],
526
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
527
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
528
-                'TKT_row'         => $row,
529
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : 0,
530
-                'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
531
-                'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
532
-                'TKT_price'       => $ticket_price,
533
-            );
534
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
535
-            // which means in turn that the prices will become new prices as well.
536
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
537
-                $TKT_values['TKT_ID'] = 0;
538
-                $TKT_values['TKT_is_default'] = 0;
539
-                $update_prices = true;
540
-            }
541
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
542
-            // we actually do our saves ahead of doing any add_relations to
543
-            // because its entirely possible that this ticket wasn't removed or added to any datetime in the session
544
-            // but DID have it's items modified.
545
-            // keep in mind that if the TKT has been sold (and we have changed pricing information),
546
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
547
-            if (absint($TKT_values['TKT_ID'])) {
548
-                $ticket = EE_Registry::instance()
549
-                                     ->load_model('Ticket', array($timezone))
550
-                                     ->get_one_by_ID($tkt['TKT_ID']);
551
-                if ($ticket instanceof EE_Ticket) {
552
-                    $ticket = $this->_update_ticket_datetimes(
553
-                        $ticket,
554
-                        $saved_datetimes,
555
-                        $datetimes_added,
556
-                        $datetimes_removed
557
-                    );
558
-                    // are there any registrations using this ticket ?
559
-                    $tickets_sold = $ticket->count_related(
560
-                        'Registration',
561
-                        array(
562
-                            array(
563
-                                'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
564
-                            ),
565
-                        )
566
-                    );
567
-                    // set ticket formats
568
-                    $ticket->set_date_format($this->_date_format_strings['date']);
569
-                    $ticket->set_time_format($this->_date_format_strings['time']);
570
-                    // let's just check the total price for the existing ticket
571
-                    // and determine if it matches the new total price.
572
-                    // if they are different then we create a new ticket (if tickets sold)
573
-                    // if they aren't different then we go ahead and modify existing ticket.
574
-                    $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
575
-                    // set new values
576
-                    foreach ($TKT_values as $field => $value) {
577
-                        if ($field === 'TKT_qty') {
578
-                            $ticket->set_qty($value);
579
-                        } else {
580
-                            $ticket->set($field, $value);
581
-                        }
582
-                    }
583
-                    // if $create_new_TKT is false then we can safely update the existing ticket.
584
-                    // Otherwise we have to create a new ticket.
585
-                    if ($create_new_TKT) {
586
-                        $new_tkt = $this->_duplicate_ticket(
587
-                            $ticket,
588
-                            $price_rows,
589
-                            $ticket_price,
590
-                            $base_price,
591
-                            $base_price_id
592
-                        );
593
-                    }
594
-                }
595
-            } else {
596
-                // no TKT_id so a new TKT
597
-                $ticket = EE_Ticket::new_instance(
598
-                    $TKT_values,
599
-                    $timezone,
600
-                    array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
601
-                );
602
-                if ($ticket instanceof EE_Ticket) {
603
-                    // make sure ticket has an ID of setting relations won't work
604
-                    $ticket->save();
605
-                    $ticket = $this->_update_ticket_datetimes(
606
-                        $ticket,
607
-                        $saved_datetimes,
608
-                        $datetimes_added,
609
-                        $datetimes_removed
610
-                    );
611
-                    $update_prices = true;
612
-                }
613
-            }
614
-            // make sure any current values have been saved.
615
-            // $ticket->save();
616
-            // before going any further make sure our dates are setup correctly
617
-            // so that the end date is always equal or greater than the start date.
618
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
619
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
620
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
621
-            }
622
-            // let's make sure the base price is handled
623
-            $ticket = ! $create_new_TKT
624
-                ? $this->_add_prices_to_ticket(
625
-                    array(),
626
-                    $ticket,
627
-                    $update_prices,
628
-                    $base_price,
629
-                    $base_price_id
630
-                )
631
-                : $ticket;
632
-            // add/update price_modifiers
633
-            $ticket = ! $create_new_TKT
634
-                ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
635
-                : $ticket;
636
-            // need to make sue that the TKT_price is accurate after saving the prices.
637
-            $ticket->ensure_TKT_Price_correct();
638
-            // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
639
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
640
-                $update_prices = true;
641
-                $new_default = clone $ticket;
642
-                $new_default->set('TKT_ID', 0);
643
-                $new_default->set('TKT_is_default', 1);
644
-                $new_default->set('TKT_row', 1);
645
-                $new_default->set('TKT_price', $ticket_price);
646
-                // remove any dtt relations cause we DON'T want dtt relations attached
647
-                // (note this is just removing the cached relations in the object)
648
-                $new_default->_remove_relations('Datetime');
649
-                // @todo we need to add the current attached prices as new prices to the new default ticket.
650
-                $new_default = $this->_add_prices_to_ticket(
651
-                    $price_rows,
652
-                    $new_default,
653
-                    $update_prices
654
-                );
655
-                // don't forget the base price!
656
-                $new_default = $this->_add_prices_to_ticket(
657
-                    array(),
658
-                    $new_default,
659
-                    $update_prices,
660
-                    $base_price,
661
-                    $base_price_id
662
-                );
663
-                $new_default->save();
664
-                do_action(
665
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
666
-                    $new_default,
667
-                    $row,
668
-                    $ticket,
669
-                    $data
670
-                );
671
-            }
672
-            // DO ALL dtt relationships for both current tickets and any archived tickets
673
-            // for the given dtt that are related to the current ticket.
674
-            // TODO... not sure exactly how we're going to do this considering we don't know
675
-            // what current ticket the archived tickets are related to
676
-            // (and TKT_parent is used for autosaves so that's not a field we can reliably use).
677
-            // let's assign any tickets that have been setup to the saved_tickets tracker
678
-            // save existing TKT
679
-            $ticket->save();
680
-            if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
681
-                // save new TKT
682
-                $new_tkt->save();
683
-                // add new ticket to array
684
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
685
-                do_action(
686
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
687
-                    $new_tkt,
688
-                    $row,
689
-                    $tkt,
690
-                    $data
691
-                );
692
-            } else {
693
-                // add tkt to saved tkts
694
-                $saved_tickets[ $ticket->ID() ] = $ticket;
695
-                do_action(
696
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
697
-                    $ticket,
698
-                    $row,
699
-                    $tkt,
700
-                    $data
701
-                );
702
-            }
703
-        }
704
-        // now we need to handle tickets actually "deleted permanently".
705
-        // There are cases where we'd want this to happen
706
-        // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
707
-        // Or a draft event was saved and in the process of editing a ticket is trashed.
708
-        // No sense in keeping all the related data in the db!
709
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
710
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
711
-        foreach ($tickets_removed as $id) {
712
-            $id = absint($id);
713
-            // get the ticket for this id
714
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
715
-            // if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
716
-            if ($tkt_to_remove->get('TKT_is_default')) {
717
-                continue;
718
-            }
719
-            // if this tkt has any registrations attached so then we just ARCHIVE
720
-            // because we don't actually permanently delete these tickets.
721
-            if ($tkt_to_remove->count_related('Registration') > 0) {
722
-                $tkt_to_remove->delete();
723
-                continue;
724
-            }
725
-            // need to get all the related datetimes on this ticket and remove from every single one of them
726
-            // (remember this process can ONLY kick off if there are NO tkts_sold)
727
-            $datetimes = $tkt_to_remove->get_many_related('Datetime');
728
-            foreach ($datetimes as $datetime) {
729
-                $tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
730
-            }
731
-            // need to do the same for prices (except these prices can also be deleted because again,
732
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
733
-            $tkt_to_remove->delete_related_permanently('Price');
734
-            do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
735
-            // finally let's delete this ticket
736
-            // (which should not be blocked at this point b/c we've removed all our relationships)
737
-            $tkt_to_remove->delete_permanently();
738
-        }
739
-        return $saved_tickets;
740
-    }
428
+	/**
429
+	 * update tickets
430
+	 *
431
+	 * @param  EE_Event      $event           Event object being updated
432
+	 * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
433
+	 * @param  array         $data            incoming request data
434
+	 * @return EE_Ticket[]
435
+	 * @throws Exception
436
+	 * @throws ReflectionException
437
+	 * @throws InvalidInterfaceException
438
+	 * @throws InvalidDataTypeException
439
+	 * @throws InvalidArgumentException
440
+	 * @throws EE_Error
441
+	 */
442
+	protected function _update_tickets($event, $saved_datetimes, $data)
443
+	{
444
+		$new_tkt = null;
445
+		$new_default = null;
446
+		// stripslashes because WP filtered the $_POST ($data) array to add slashes
447
+		$data = stripslashes_deep($data);
448
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
449
+		$saved_tickets = $datetimes_on_existing = array();
450
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
451
+		if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
452
+			throw new InvalidArgumentException(
453
+				esc_html__(
454
+					'The "edit_tickets" array is invalid therefore the event can not be updated.',
455
+					'event_espresso'
456
+				)
457
+			);
458
+		}
459
+		foreach ($data['edit_tickets'] as $row => $tkt) {
460
+			$update_prices = $create_new_TKT = false;
461
+			// figure out what datetimes were added to the ticket
462
+			// and what datetimes were removed from the ticket in the session.
463
+			$starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
464
+			$tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
465
+			$datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
466
+			$datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
467
+			// trim inputs to ensure any excess whitespace is removed.
468
+			$tkt = array_map(
469
+				function ($ticket_data) {
470
+					return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
471
+				},
472
+				$tkt
473
+			);
474
+			// note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
475
+			// because we're doing calculations prior to using the models.
476
+			// note incoming ['TKT_price'] value is already in standard notation (via js).
477
+			$ticket_price = isset($tkt['TKT_price'])
478
+				? round((float) $tkt['TKT_price'], 3)
479
+				: 0;
480
+			// note incoming base price needs converted from localized value.
481
+			$base_price = isset($tkt['TKT_base_price'])
482
+				? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
483
+				: 0;
484
+			// if ticket price == 0 and $base_price != 0 then ticket price == base_price
485
+			$ticket_price = $ticket_price === 0 && $base_price !== 0
486
+				? $base_price
487
+				: $ticket_price;
488
+			$base_price_id = isset($tkt['TKT_base_price_ID'])
489
+				? $tkt['TKT_base_price_ID']
490
+				: 0;
491
+			$price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
492
+				? $data['edit_prices'][ $row ]
493
+				: array();
494
+			$now = null;
495
+			if (empty($tkt['TKT_start_date'])) {
496
+				// lets' use now in the set timezone.
497
+				$now = new DateTime('now', new DateTimeZone($event->get_timezone()));
498
+				$tkt['TKT_start_date'] = $now->format($this->_date_time_format);
499
+			}
500
+			if (empty($tkt['TKT_end_date'])) {
501
+				/**
502
+				 * set the TKT_end_date to the first datetime attached to the ticket.
503
+				 */
504
+				$first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
505
+				$tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
506
+			}
507
+			$TKT_values = array(
508
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
509
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
510
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
511
+				'TKT_description' => ! empty($tkt['TKT_description'])
512
+									 && $tkt['TKT_description'] !== esc_html__(
513
+										 'You can modify this description',
514
+										 'event_espresso'
515
+									 )
516
+					? $tkt['TKT_description']
517
+					: '',
518
+				'TKT_start_date'  => $tkt['TKT_start_date'],
519
+				'TKT_end_date'    => $tkt['TKT_end_date'],
520
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
521
+					? EE_INF
522
+					: $tkt['TKT_qty'],
523
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
524
+					? EE_INF
525
+					: $tkt['TKT_uses'],
526
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
527
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
528
+				'TKT_row'         => $row,
529
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : 0,
530
+				'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
531
+				'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
532
+				'TKT_price'       => $ticket_price,
533
+			);
534
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
535
+			// which means in turn that the prices will become new prices as well.
536
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
537
+				$TKT_values['TKT_ID'] = 0;
538
+				$TKT_values['TKT_is_default'] = 0;
539
+				$update_prices = true;
540
+			}
541
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
542
+			// we actually do our saves ahead of doing any add_relations to
543
+			// because its entirely possible that this ticket wasn't removed or added to any datetime in the session
544
+			// but DID have it's items modified.
545
+			// keep in mind that if the TKT has been sold (and we have changed pricing information),
546
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
547
+			if (absint($TKT_values['TKT_ID'])) {
548
+				$ticket = EE_Registry::instance()
549
+									 ->load_model('Ticket', array($timezone))
550
+									 ->get_one_by_ID($tkt['TKT_ID']);
551
+				if ($ticket instanceof EE_Ticket) {
552
+					$ticket = $this->_update_ticket_datetimes(
553
+						$ticket,
554
+						$saved_datetimes,
555
+						$datetimes_added,
556
+						$datetimes_removed
557
+					);
558
+					// are there any registrations using this ticket ?
559
+					$tickets_sold = $ticket->count_related(
560
+						'Registration',
561
+						array(
562
+							array(
563
+								'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
564
+							),
565
+						)
566
+					);
567
+					// set ticket formats
568
+					$ticket->set_date_format($this->_date_format_strings['date']);
569
+					$ticket->set_time_format($this->_date_format_strings['time']);
570
+					// let's just check the total price for the existing ticket
571
+					// and determine if it matches the new total price.
572
+					// if they are different then we create a new ticket (if tickets sold)
573
+					// if they aren't different then we go ahead and modify existing ticket.
574
+					$create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
575
+					// set new values
576
+					foreach ($TKT_values as $field => $value) {
577
+						if ($field === 'TKT_qty') {
578
+							$ticket->set_qty($value);
579
+						} else {
580
+							$ticket->set($field, $value);
581
+						}
582
+					}
583
+					// if $create_new_TKT is false then we can safely update the existing ticket.
584
+					// Otherwise we have to create a new ticket.
585
+					if ($create_new_TKT) {
586
+						$new_tkt = $this->_duplicate_ticket(
587
+							$ticket,
588
+							$price_rows,
589
+							$ticket_price,
590
+							$base_price,
591
+							$base_price_id
592
+						);
593
+					}
594
+				}
595
+			} else {
596
+				// no TKT_id so a new TKT
597
+				$ticket = EE_Ticket::new_instance(
598
+					$TKT_values,
599
+					$timezone,
600
+					array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
601
+				);
602
+				if ($ticket instanceof EE_Ticket) {
603
+					// make sure ticket has an ID of setting relations won't work
604
+					$ticket->save();
605
+					$ticket = $this->_update_ticket_datetimes(
606
+						$ticket,
607
+						$saved_datetimes,
608
+						$datetimes_added,
609
+						$datetimes_removed
610
+					);
611
+					$update_prices = true;
612
+				}
613
+			}
614
+			// make sure any current values have been saved.
615
+			// $ticket->save();
616
+			// before going any further make sure our dates are setup correctly
617
+			// so that the end date is always equal or greater than the start date.
618
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
619
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
620
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
621
+			}
622
+			// let's make sure the base price is handled
623
+			$ticket = ! $create_new_TKT
624
+				? $this->_add_prices_to_ticket(
625
+					array(),
626
+					$ticket,
627
+					$update_prices,
628
+					$base_price,
629
+					$base_price_id
630
+				)
631
+				: $ticket;
632
+			// add/update price_modifiers
633
+			$ticket = ! $create_new_TKT
634
+				? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
635
+				: $ticket;
636
+			// need to make sue that the TKT_price is accurate after saving the prices.
637
+			$ticket->ensure_TKT_Price_correct();
638
+			// handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
639
+			if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
640
+				$update_prices = true;
641
+				$new_default = clone $ticket;
642
+				$new_default->set('TKT_ID', 0);
643
+				$new_default->set('TKT_is_default', 1);
644
+				$new_default->set('TKT_row', 1);
645
+				$new_default->set('TKT_price', $ticket_price);
646
+				// remove any dtt relations cause we DON'T want dtt relations attached
647
+				// (note this is just removing the cached relations in the object)
648
+				$new_default->_remove_relations('Datetime');
649
+				// @todo we need to add the current attached prices as new prices to the new default ticket.
650
+				$new_default = $this->_add_prices_to_ticket(
651
+					$price_rows,
652
+					$new_default,
653
+					$update_prices
654
+				);
655
+				// don't forget the base price!
656
+				$new_default = $this->_add_prices_to_ticket(
657
+					array(),
658
+					$new_default,
659
+					$update_prices,
660
+					$base_price,
661
+					$base_price_id
662
+				);
663
+				$new_default->save();
664
+				do_action(
665
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
666
+					$new_default,
667
+					$row,
668
+					$ticket,
669
+					$data
670
+				);
671
+			}
672
+			// DO ALL dtt relationships for both current tickets and any archived tickets
673
+			// for the given dtt that are related to the current ticket.
674
+			// TODO... not sure exactly how we're going to do this considering we don't know
675
+			// what current ticket the archived tickets are related to
676
+			// (and TKT_parent is used for autosaves so that's not a field we can reliably use).
677
+			// let's assign any tickets that have been setup to the saved_tickets tracker
678
+			// save existing TKT
679
+			$ticket->save();
680
+			if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
681
+				// save new TKT
682
+				$new_tkt->save();
683
+				// add new ticket to array
684
+				$saved_tickets[ $new_tkt->ID() ] = $new_tkt;
685
+				do_action(
686
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
687
+					$new_tkt,
688
+					$row,
689
+					$tkt,
690
+					$data
691
+				);
692
+			} else {
693
+				// add tkt to saved tkts
694
+				$saved_tickets[ $ticket->ID() ] = $ticket;
695
+				do_action(
696
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
697
+					$ticket,
698
+					$row,
699
+					$tkt,
700
+					$data
701
+				);
702
+			}
703
+		}
704
+		// now we need to handle tickets actually "deleted permanently".
705
+		// There are cases where we'd want this to happen
706
+		// (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
707
+		// Or a draft event was saved and in the process of editing a ticket is trashed.
708
+		// No sense in keeping all the related data in the db!
709
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
710
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
711
+		foreach ($tickets_removed as $id) {
712
+			$id = absint($id);
713
+			// get the ticket for this id
714
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
715
+			// if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
716
+			if ($tkt_to_remove->get('TKT_is_default')) {
717
+				continue;
718
+			}
719
+			// if this tkt has any registrations attached so then we just ARCHIVE
720
+			// because we don't actually permanently delete these tickets.
721
+			if ($tkt_to_remove->count_related('Registration') > 0) {
722
+				$tkt_to_remove->delete();
723
+				continue;
724
+			}
725
+			// need to get all the related datetimes on this ticket and remove from every single one of them
726
+			// (remember this process can ONLY kick off if there are NO tkts_sold)
727
+			$datetimes = $tkt_to_remove->get_many_related('Datetime');
728
+			foreach ($datetimes as $datetime) {
729
+				$tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
730
+			}
731
+			// need to do the same for prices (except these prices can also be deleted because again,
732
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
733
+			$tkt_to_remove->delete_related_permanently('Price');
734
+			do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
735
+			// finally let's delete this ticket
736
+			// (which should not be blocked at this point b/c we've removed all our relationships)
737
+			$tkt_to_remove->delete_permanently();
738
+		}
739
+		return $saved_tickets;
740
+	}
741 741
 
742 742
 
743
-    /**
744
-     * @access  protected
745
-     * @param EE_Ticket      $ticket
746
-     * @param \EE_Datetime[] $saved_datetimes
747
-     * @param \EE_Datetime[] $added_datetimes
748
-     * @param \EE_Datetime[] $removed_datetimes
749
-     * @return EE_Ticket
750
-     * @throws EE_Error
751
-     */
752
-    protected function _update_ticket_datetimes(
753
-        EE_Ticket $ticket,
754
-        $saved_datetimes = array(),
755
-        $added_datetimes = array(),
756
-        $removed_datetimes = array()
757
-    ) {
758
-        // to start we have to add the ticket to all the datetimes its supposed to be with,
759
-        // and removing the ticket from datetimes it got removed from.
760
-        // first let's add datetimes
761
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
762
-            foreach ($added_datetimes as $row_id) {
763
-                $row_id = (int) $row_id;
764
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
765
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
766
-                }
767
-            }
768
-        }
769
-        // then remove datetimes
770
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
771
-            foreach ($removed_datetimes as $row_id) {
772
-                $row_id = (int) $row_id;
773
-                // its entirely possible that a datetime got deleted (instead of just removed from relationship.
774
-                // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
775
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
776
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
777
-                }
778
-            }
779
-        }
780
-        // cap ticket qty by datetime reg limits
781
-        $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
782
-        return $ticket;
783
-    }
743
+	/**
744
+	 * @access  protected
745
+	 * @param EE_Ticket      $ticket
746
+	 * @param \EE_Datetime[] $saved_datetimes
747
+	 * @param \EE_Datetime[] $added_datetimes
748
+	 * @param \EE_Datetime[] $removed_datetimes
749
+	 * @return EE_Ticket
750
+	 * @throws EE_Error
751
+	 */
752
+	protected function _update_ticket_datetimes(
753
+		EE_Ticket $ticket,
754
+		$saved_datetimes = array(),
755
+		$added_datetimes = array(),
756
+		$removed_datetimes = array()
757
+	) {
758
+		// to start we have to add the ticket to all the datetimes its supposed to be with,
759
+		// and removing the ticket from datetimes it got removed from.
760
+		// first let's add datetimes
761
+		if (! empty($added_datetimes) && is_array($added_datetimes)) {
762
+			foreach ($added_datetimes as $row_id) {
763
+				$row_id = (int) $row_id;
764
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
765
+					$ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
766
+				}
767
+			}
768
+		}
769
+		// then remove datetimes
770
+		if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
771
+			foreach ($removed_datetimes as $row_id) {
772
+				$row_id = (int) $row_id;
773
+				// its entirely possible that a datetime got deleted (instead of just removed from relationship.
774
+				// So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
775
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
776
+					$ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
777
+				}
778
+			}
779
+		}
780
+		// cap ticket qty by datetime reg limits
781
+		$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
782
+		return $ticket;
783
+	}
784 784
 
785 785
 
786
-    /**
787
-     * @access  protected
788
-     * @param EE_Ticket $ticket
789
-     * @param array     $price_rows
790
-     * @param int       $ticket_price
791
-     * @param int       $base_price
792
-     * @param int       $base_price_id
793
-     * @return EE_Ticket
794
-     * @throws ReflectionException
795
-     * @throws InvalidArgumentException
796
-     * @throws InvalidInterfaceException
797
-     * @throws InvalidDataTypeException
798
-     * @throws EE_Error
799
-     */
800
-    protected function _duplicate_ticket(
801
-        EE_Ticket $ticket,
802
-        $price_rows = array(),
803
-        $ticket_price = 0,
804
-        $base_price = 0,
805
-        $base_price_id = 0
806
-    ) {
807
-        // create new ticket that's a copy of the existing
808
-        // except a new id of course (and not archived)
809
-        // AND has the new TKT_price associated with it.
810
-        $new_ticket = clone $ticket;
811
-        $new_ticket->set('TKT_ID', 0);
812
-        $new_ticket->set_deleted(0);
813
-        $new_ticket->set_price($ticket_price);
814
-        $new_ticket->set_sold(0);
815
-        // let's get a new ID for this ticket
816
-        $new_ticket->save();
817
-        // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
818
-        $datetimes_on_existing = $ticket->datetimes();
819
-        $new_ticket = $this->_update_ticket_datetimes(
820
-            $new_ticket,
821
-            $datetimes_on_existing,
822
-            array_keys($datetimes_on_existing)
823
-        );
824
-        // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
825
-        // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
826
-        // available.
827
-        if ($ticket->sold() > 0) {
828
-            $new_qty = $ticket->qty() - $ticket->sold();
829
-            $new_ticket->set_qty($new_qty);
830
-        }
831
-        // now we update the prices just for this ticket
832
-        $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
833
-        // and we update the base price
834
-        $new_ticket = $this->_add_prices_to_ticket(
835
-            array(),
836
-            $new_ticket,
837
-            true,
838
-            $base_price,
839
-            $base_price_id
840
-        );
841
-        return $new_ticket;
842
-    }
786
+	/**
787
+	 * @access  protected
788
+	 * @param EE_Ticket $ticket
789
+	 * @param array     $price_rows
790
+	 * @param int       $ticket_price
791
+	 * @param int       $base_price
792
+	 * @param int       $base_price_id
793
+	 * @return EE_Ticket
794
+	 * @throws ReflectionException
795
+	 * @throws InvalidArgumentException
796
+	 * @throws InvalidInterfaceException
797
+	 * @throws InvalidDataTypeException
798
+	 * @throws EE_Error
799
+	 */
800
+	protected function _duplicate_ticket(
801
+		EE_Ticket $ticket,
802
+		$price_rows = array(),
803
+		$ticket_price = 0,
804
+		$base_price = 0,
805
+		$base_price_id = 0
806
+	) {
807
+		// create new ticket that's a copy of the existing
808
+		// except a new id of course (and not archived)
809
+		// AND has the new TKT_price associated with it.
810
+		$new_ticket = clone $ticket;
811
+		$new_ticket->set('TKT_ID', 0);
812
+		$new_ticket->set_deleted(0);
813
+		$new_ticket->set_price($ticket_price);
814
+		$new_ticket->set_sold(0);
815
+		// let's get a new ID for this ticket
816
+		$new_ticket->save();
817
+		// we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
818
+		$datetimes_on_existing = $ticket->datetimes();
819
+		$new_ticket = $this->_update_ticket_datetimes(
820
+			$new_ticket,
821
+			$datetimes_on_existing,
822
+			array_keys($datetimes_on_existing)
823
+		);
824
+		// $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
825
+		// if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
826
+		// available.
827
+		if ($ticket->sold() > 0) {
828
+			$new_qty = $ticket->qty() - $ticket->sold();
829
+			$new_ticket->set_qty($new_qty);
830
+		}
831
+		// now we update the prices just for this ticket
832
+		$new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
833
+		// and we update the base price
834
+		$new_ticket = $this->_add_prices_to_ticket(
835
+			array(),
836
+			$new_ticket,
837
+			true,
838
+			$base_price,
839
+			$base_price_id
840
+		);
841
+		return $new_ticket;
842
+	}
843 843
 
844 844
 
845
-    /**
846
-     * This attaches a list of given prices to a ticket.
847
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
848
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
849
-     * price info and prices are automatically "archived" via the ticket.
850
-     *
851
-     * @access  private
852
-     * @param array     $prices        Array of prices from the form.
853
-     * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
854
-     * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
855
-     * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
856
-     * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
857
-     * @return EE_Ticket
858
-     * @throws ReflectionException
859
-     * @throws InvalidArgumentException
860
-     * @throws InvalidInterfaceException
861
-     * @throws InvalidDataTypeException
862
-     * @throws EE_Error
863
-     */
864
-    protected function _add_prices_to_ticket(
865
-        $prices = array(),
866
-        EE_Ticket $ticket,
867
-        $new_prices = false,
868
-        $base_price = false,
869
-        $base_price_id = false
870
-    ) {
871
-        // let's just get any current prices that may exist on the given ticket
872
-        // so we can remove any prices that got trashed in this session.
873
-        $current_prices_on_ticket = $base_price !== false
874
-            ? $ticket->base_price(true)
875
-            : $ticket->price_modifiers();
876
-        $updated_prices = array();
877
-        // if $base_price ! FALSE then updating a base price.
878
-        if ($base_price !== false) {
879
-            $prices[1] = array(
880
-                'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
881
-                'PRT_ID'     => 1,
882
-                'PRC_amount' => $base_price,
883
-                'PRC_name'   => $ticket->get('TKT_name'),
884
-                'PRC_desc'   => $ticket->get('TKT_description'),
885
-            );
886
-        }
887
-        // possibly need to save tkt
888
-        if (! $ticket->ID()) {
889
-            $ticket->save();
890
-        }
891
-        foreach ($prices as $row => $prc) {
892
-            $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
893
-            if (empty($prt_id)) {
894
-                continue;
895
-            } //prices MUST have a price type id.
896
-            $PRC_values = array(
897
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
898
-                'PRT_ID'         => $prt_id,
899
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
900
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
901
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
902
-                'PRC_is_default' => false,
903
-                // make sure we set PRC_is_default to false for all ticket saves from event_editor
904
-                'PRC_order'      => $row,
905
-            );
906
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
907
-                $PRC_values['PRC_ID'] = 0;
908
-                $price = EE_Registry::instance()->load_class(
909
-                    'Price',
910
-                    array($PRC_values),
911
-                    false,
912
-                    false
913
-                );
914
-            } else {
915
-                $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
916
-                // update this price with new values
917
-                foreach ($PRC_values as $field => $value) {
918
-                    $price->set($field, $value);
919
-                }
920
-            }
921
-            $price->save();
922
-            $updated_prices[ $price->ID() ] = $price;
923
-            $ticket->_add_relation_to($price, 'Price');
924
-        }
925
-        // now let's remove any prices that got removed from the ticket
926
-        if (! empty($current_prices_on_ticket)) {
927
-            $current = array_keys($current_prices_on_ticket);
928
-            $updated = array_keys($updated_prices);
929
-            $prices_to_remove = array_diff($current, $updated);
930
-            if (! empty($prices_to_remove)) {
931
-                foreach ($prices_to_remove as $prc_id) {
932
-                    $p = $current_prices_on_ticket[ $prc_id ];
933
-                    $ticket->_remove_relation_to($p, 'Price');
934
-                    // delete permanently the price
935
-                    $p->delete_permanently();
936
-                }
937
-            }
938
-        }
939
-        return $ticket;
940
-    }
845
+	/**
846
+	 * This attaches a list of given prices to a ticket.
847
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
848
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
849
+	 * price info and prices are automatically "archived" via the ticket.
850
+	 *
851
+	 * @access  private
852
+	 * @param array     $prices        Array of prices from the form.
853
+	 * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
854
+	 * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
855
+	 * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
856
+	 * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
857
+	 * @return EE_Ticket
858
+	 * @throws ReflectionException
859
+	 * @throws InvalidArgumentException
860
+	 * @throws InvalidInterfaceException
861
+	 * @throws InvalidDataTypeException
862
+	 * @throws EE_Error
863
+	 */
864
+	protected function _add_prices_to_ticket(
865
+		$prices = array(),
866
+		EE_Ticket $ticket,
867
+		$new_prices = false,
868
+		$base_price = false,
869
+		$base_price_id = false
870
+	) {
871
+		// let's just get any current prices that may exist on the given ticket
872
+		// so we can remove any prices that got trashed in this session.
873
+		$current_prices_on_ticket = $base_price !== false
874
+			? $ticket->base_price(true)
875
+			: $ticket->price_modifiers();
876
+		$updated_prices = array();
877
+		// if $base_price ! FALSE then updating a base price.
878
+		if ($base_price !== false) {
879
+			$prices[1] = array(
880
+				'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
881
+				'PRT_ID'     => 1,
882
+				'PRC_amount' => $base_price,
883
+				'PRC_name'   => $ticket->get('TKT_name'),
884
+				'PRC_desc'   => $ticket->get('TKT_description'),
885
+			);
886
+		}
887
+		// possibly need to save tkt
888
+		if (! $ticket->ID()) {
889
+			$ticket->save();
890
+		}
891
+		foreach ($prices as $row => $prc) {
892
+			$prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
893
+			if (empty($prt_id)) {
894
+				continue;
895
+			} //prices MUST have a price type id.
896
+			$PRC_values = array(
897
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
898
+				'PRT_ID'         => $prt_id,
899
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
900
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
901
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
902
+				'PRC_is_default' => false,
903
+				// make sure we set PRC_is_default to false for all ticket saves from event_editor
904
+				'PRC_order'      => $row,
905
+			);
906
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
907
+				$PRC_values['PRC_ID'] = 0;
908
+				$price = EE_Registry::instance()->load_class(
909
+					'Price',
910
+					array($PRC_values),
911
+					false,
912
+					false
913
+				);
914
+			} else {
915
+				$price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
916
+				// update this price with new values
917
+				foreach ($PRC_values as $field => $value) {
918
+					$price->set($field, $value);
919
+				}
920
+			}
921
+			$price->save();
922
+			$updated_prices[ $price->ID() ] = $price;
923
+			$ticket->_add_relation_to($price, 'Price');
924
+		}
925
+		// now let's remove any prices that got removed from the ticket
926
+		if (! empty($current_prices_on_ticket)) {
927
+			$current = array_keys($current_prices_on_ticket);
928
+			$updated = array_keys($updated_prices);
929
+			$prices_to_remove = array_diff($current, $updated);
930
+			if (! empty($prices_to_remove)) {
931
+				foreach ($prices_to_remove as $prc_id) {
932
+					$p = $current_prices_on_ticket[ $prc_id ];
933
+					$ticket->_remove_relation_to($p, 'Price');
934
+					// delete permanently the price
935
+					$p->delete_permanently();
936
+				}
937
+			}
938
+		}
939
+		return $ticket;
940
+	}
941 941
 
942 942
 
943
-    /**
944
-     * @param Events_Admin_Page $event_admin_obj
945
-     * @return Events_Admin_Page
946
-     */
947
-    public function autosave_handling(Events_Admin_Page $event_admin_obj)
948
-    {
949
-        return $event_admin_obj;
950
-        // doing nothing for the moment.
951
-        // todo when I get to this remember that I need to set the template args on the $event_admin_obj
952
-        // (use the set_template_args() method)
953
-        /**
954
-         * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
955
-         * 1. TKT_is_default_selector (visible)
956
-         * 2. TKT_is_default (hidden)
957
-         * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
958
-         * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
959
-         * this ticket to be saved as a default.
960
-         * The tricky part is, on an initial display on create or edit (or after manually updating),
961
-         * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
962
-         * if this is a create.  However, after an autosave, users will want some sort of indicator that
963
-         * the TKT HAS been saved as a default..
964
-         * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
965
-         * On Autosave:
966
-         * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
967
-         * then set the TKT_is_default to false.
968
-         * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
969
-         *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
970
-         * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
971
-         */
972
-    }
943
+	/**
944
+	 * @param Events_Admin_Page $event_admin_obj
945
+	 * @return Events_Admin_Page
946
+	 */
947
+	public function autosave_handling(Events_Admin_Page $event_admin_obj)
948
+	{
949
+		return $event_admin_obj;
950
+		// doing nothing for the moment.
951
+		// todo when I get to this remember that I need to set the template args on the $event_admin_obj
952
+		// (use the set_template_args() method)
953
+		/**
954
+		 * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
955
+		 * 1. TKT_is_default_selector (visible)
956
+		 * 2. TKT_is_default (hidden)
957
+		 * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
958
+		 * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
959
+		 * this ticket to be saved as a default.
960
+		 * The tricky part is, on an initial display on create or edit (or after manually updating),
961
+		 * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
962
+		 * if this is a create.  However, after an autosave, users will want some sort of indicator that
963
+		 * the TKT HAS been saved as a default..
964
+		 * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
965
+		 * On Autosave:
966
+		 * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
967
+		 * then set the TKT_is_default to false.
968
+		 * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
969
+		 *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
970
+		 * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
971
+		 */
972
+	}
973 973
 
974 974
 
975
-    /**
976
-     * @throws ReflectionException
977
-     * @throws InvalidArgumentException
978
-     * @throws InvalidInterfaceException
979
-     * @throws InvalidDataTypeException
980
-     * @throws DomainException
981
-     * @throws EE_Error
982
-     */
983
-    public function pricing_metabox()
984
-    {
985
-        $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
986
-        $event = $this->_adminpage_obj->get_cpt_model_obj();
987
-        // set is_creating_event property.
988
-        $EVT_ID = $event->ID();
989
-        $this->_is_creating_event = empty($this->_req_data['post']);
990
-        // default main template args
991
-        $main_template_args = array(
992
-            'event_datetime_help_link' => EEH_Template::get_help_tab_link(
993
-                'event_editor_event_datetimes_help_tab',
994
-                $this->_adminpage_obj->page_slug,
995
-                $this->_adminpage_obj->get_req_action(),
996
-                false,
997
-                false
998
-            ),
999
-            // todo need to add a filter to the template for the help text
1000
-            // in the Events_Admin_Page core file so we can add further help
1001
-            'existing_datetime_ids'    => '',
1002
-            'total_dtt_rows'           => 1,
1003
-            'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1004
-                'add_new_dtt_info',
1005
-                $this->_adminpage_obj->page_slug,
1006
-                $this->_adminpage_obj->get_req_action(),
1007
-                false,
1008
-                false
1009
-            ),
1010
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1011
-            'datetime_rows'            => '',
1012
-            'show_tickets_container'   => '',
1013
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1014
-            'ticket_rows'              => '',
1015
-            'existing_ticket_ids'      => '',
1016
-            'total_ticket_rows'        => 1,
1017
-            'ticket_js_structure'      => '',
1018
-            'ee_collapsible_status'    => ' ee-collapsible-open'
1019
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1020
-        );
1021
-        $timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1022
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1023
-        /**
1024
-         * 1. Start with retrieving Datetimes
1025
-         * 2. For each datetime get related tickets
1026
-         * 3. For each ticket get related prices
1027
-         */
1028
-        /** @var EEM_Datetime $datetime_model */
1029
-        $datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1030
-        $datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1031
-        $main_template_args['total_dtt_rows'] = count($datetimes);
1032
-        /**
1033
-         * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1034
-         * for why we are counting $datetime_row and then setting that on the Datetime object
1035
-         */
1036
-        $datetime_row = 1;
1037
-        foreach ($datetimes as $datetime) {
1038
-            $DTT_ID = $datetime->get('DTT_ID');
1039
-            $datetime->set('DTT_order', $datetime_row);
1040
-            $existing_datetime_ids[] = $DTT_ID;
1041
-            // tickets attached
1042
-            $related_tickets = $datetime->ID() > 0
1043
-                ? $datetime->get_many_related(
1044
-                    'Ticket',
1045
-                    array(
1046
-                        array(
1047
-                            'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1048
-                        ),
1049
-                        'default_where_conditions' => 'none',
1050
-                        'order_by'                 => array('TKT_order' => 'ASC'),
1051
-                    )
1052
-                )
1053
-                : array();
1054
-            // if there are no related tickets this is likely a new event OR autodraft
1055
-            // event so we need to generate the default tickets because datetimes
1056
-            // ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1057
-            // datetime on the event.
1058
-            if (empty($related_tickets) && count($datetimes) < 2) {
1059
-                /** @var EEM_Ticket $ticket_model */
1060
-                $ticket_model = EE_Registry::instance()->load_model('Ticket');
1061
-                $related_tickets = $ticket_model->get_all_default_tickets();
1062
-                // this should be ordered by TKT_ID, so let's grab the first default ticket
1063
-                // (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1064
-                $default_prices = EEM_Price::instance()->get_all_default_prices();
1065
-                $main_default_ticket = reset($related_tickets);
1066
-                if ($main_default_ticket instanceof EE_Ticket) {
1067
-                    foreach ($default_prices as $default_price) {
1068
-                        if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1069
-                            continue;
1070
-                        }
1071
-                        $main_default_ticket->cache('Price', $default_price);
1072
-                    }
1073
-                }
1074
-            }
1075
-            // we can't actually setup rows in this loop yet cause we don't know all
1076
-            // the unique tickets for this event yet (tickets are linked through all datetimes).
1077
-            // So we're going to temporarily cache some of that information.
1078
-            // loop through and setup the ticket rows and make sure the order is set.
1079
-            foreach ($related_tickets as $ticket) {
1080
-                $TKT_ID = $ticket->get('TKT_ID');
1081
-                $ticket_row = $ticket->get('TKT_row');
1082
-                // we only want unique tickets in our final display!!
1083
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1084
-                    $existing_ticket_ids[] = $TKT_ID;
1085
-                    $all_tickets[] = $ticket;
1086
-                }
1087
-                // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1088
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1089
-                // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1090
-                if (
1091
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1092
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1093
-                ) {
1094
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1095
-                }
1096
-            }
1097
-            $datetime_row++;
1098
-        }
1099
-        $main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1100
-        $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1101
-        $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1102
-        // sort $all_tickets by order
1103
-        usort(
1104
-            $all_tickets,
1105
-            function (EE_Ticket $a, EE_Ticket $b) {
1106
-                $a_order = (int) $a->get('TKT_order');
1107
-                $b_order = (int) $b->get('TKT_order');
1108
-                if ($a_order === $b_order) {
1109
-                    return 0;
1110
-                }
1111
-                return ($a_order < $b_order) ? -1 : 1;
1112
-            }
1113
-        );
1114
-        // k NOW we have all the data we need for setting up the dtt rows
1115
-        // and ticket rows so we start our dtt loop again.
1116
-        $datetime_row = 1;
1117
-        foreach ($datetimes as $datetime) {
1118
-            $main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1119
-                $datetime_row,
1120
-                $datetime,
1121
-                $datetime_tickets,
1122
-                $all_tickets,
1123
-                false,
1124
-                $datetimes
1125
-            );
1126
-            $datetime_row++;
1127
-        }
1128
-        // then loop through all tickets for the ticket rows.
1129
-        $ticket_row = 1;
1130
-        foreach ($all_tickets as $ticket) {
1131
-            $main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1132
-                $ticket_row,
1133
-                $ticket,
1134
-                $ticket_datetimes,
1135
-                $datetimes,
1136
-                false,
1137
-                $all_tickets
1138
-            );
1139
-            $ticket_row++;
1140
-        }
1141
-        $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
975
+	/**
976
+	 * @throws ReflectionException
977
+	 * @throws InvalidArgumentException
978
+	 * @throws InvalidInterfaceException
979
+	 * @throws InvalidDataTypeException
980
+	 * @throws DomainException
981
+	 * @throws EE_Error
982
+	 */
983
+	public function pricing_metabox()
984
+	{
985
+		$existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
986
+		$event = $this->_adminpage_obj->get_cpt_model_obj();
987
+		// set is_creating_event property.
988
+		$EVT_ID = $event->ID();
989
+		$this->_is_creating_event = empty($this->_req_data['post']);
990
+		// default main template args
991
+		$main_template_args = array(
992
+			'event_datetime_help_link' => EEH_Template::get_help_tab_link(
993
+				'event_editor_event_datetimes_help_tab',
994
+				$this->_adminpage_obj->page_slug,
995
+				$this->_adminpage_obj->get_req_action(),
996
+				false,
997
+				false
998
+			),
999
+			// todo need to add a filter to the template for the help text
1000
+			// in the Events_Admin_Page core file so we can add further help
1001
+			'existing_datetime_ids'    => '',
1002
+			'total_dtt_rows'           => 1,
1003
+			'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1004
+				'add_new_dtt_info',
1005
+				$this->_adminpage_obj->page_slug,
1006
+				$this->_adminpage_obj->get_req_action(),
1007
+				false,
1008
+				false
1009
+			),
1010
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1011
+			'datetime_rows'            => '',
1012
+			'show_tickets_container'   => '',
1013
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1014
+			'ticket_rows'              => '',
1015
+			'existing_ticket_ids'      => '',
1016
+			'total_ticket_rows'        => 1,
1017
+			'ticket_js_structure'      => '',
1018
+			'ee_collapsible_status'    => ' ee-collapsible-open'
1019
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1020
+		);
1021
+		$timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1022
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1023
+		/**
1024
+		 * 1. Start with retrieving Datetimes
1025
+		 * 2. For each datetime get related tickets
1026
+		 * 3. For each ticket get related prices
1027
+		 */
1028
+		/** @var EEM_Datetime $datetime_model */
1029
+		$datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1030
+		$datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1031
+		$main_template_args['total_dtt_rows'] = count($datetimes);
1032
+		/**
1033
+		 * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1034
+		 * for why we are counting $datetime_row and then setting that on the Datetime object
1035
+		 */
1036
+		$datetime_row = 1;
1037
+		foreach ($datetimes as $datetime) {
1038
+			$DTT_ID = $datetime->get('DTT_ID');
1039
+			$datetime->set('DTT_order', $datetime_row);
1040
+			$existing_datetime_ids[] = $DTT_ID;
1041
+			// tickets attached
1042
+			$related_tickets = $datetime->ID() > 0
1043
+				? $datetime->get_many_related(
1044
+					'Ticket',
1045
+					array(
1046
+						array(
1047
+							'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1048
+						),
1049
+						'default_where_conditions' => 'none',
1050
+						'order_by'                 => array('TKT_order' => 'ASC'),
1051
+					)
1052
+				)
1053
+				: array();
1054
+			// if there are no related tickets this is likely a new event OR autodraft
1055
+			// event so we need to generate the default tickets because datetimes
1056
+			// ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1057
+			// datetime on the event.
1058
+			if (empty($related_tickets) && count($datetimes) < 2) {
1059
+				/** @var EEM_Ticket $ticket_model */
1060
+				$ticket_model = EE_Registry::instance()->load_model('Ticket');
1061
+				$related_tickets = $ticket_model->get_all_default_tickets();
1062
+				// this should be ordered by TKT_ID, so let's grab the first default ticket
1063
+				// (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1064
+				$default_prices = EEM_Price::instance()->get_all_default_prices();
1065
+				$main_default_ticket = reset($related_tickets);
1066
+				if ($main_default_ticket instanceof EE_Ticket) {
1067
+					foreach ($default_prices as $default_price) {
1068
+						if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1069
+							continue;
1070
+						}
1071
+						$main_default_ticket->cache('Price', $default_price);
1072
+					}
1073
+				}
1074
+			}
1075
+			// we can't actually setup rows in this loop yet cause we don't know all
1076
+			// the unique tickets for this event yet (tickets are linked through all datetimes).
1077
+			// So we're going to temporarily cache some of that information.
1078
+			// loop through and setup the ticket rows and make sure the order is set.
1079
+			foreach ($related_tickets as $ticket) {
1080
+				$TKT_ID = $ticket->get('TKT_ID');
1081
+				$ticket_row = $ticket->get('TKT_row');
1082
+				// we only want unique tickets in our final display!!
1083
+				if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1084
+					$existing_ticket_ids[] = $TKT_ID;
1085
+					$all_tickets[] = $ticket;
1086
+				}
1087
+				// temporary cache of this ticket info for this datetime for later processing of datetime rows.
1088
+				$datetime_tickets[ $DTT_ID ][] = $ticket_row;
1089
+				// temporary cache of this datetime info for this ticket for later processing of ticket rows.
1090
+				if (
1091
+					! isset($ticket_datetimes[ $TKT_ID ])
1092
+					|| ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1093
+				) {
1094
+					$ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1095
+				}
1096
+			}
1097
+			$datetime_row++;
1098
+		}
1099
+		$main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1100
+		$main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1101
+		$main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1102
+		// sort $all_tickets by order
1103
+		usort(
1104
+			$all_tickets,
1105
+			function (EE_Ticket $a, EE_Ticket $b) {
1106
+				$a_order = (int) $a->get('TKT_order');
1107
+				$b_order = (int) $b->get('TKT_order');
1108
+				if ($a_order === $b_order) {
1109
+					return 0;
1110
+				}
1111
+				return ($a_order < $b_order) ? -1 : 1;
1112
+			}
1113
+		);
1114
+		// k NOW we have all the data we need for setting up the dtt rows
1115
+		// and ticket rows so we start our dtt loop again.
1116
+		$datetime_row = 1;
1117
+		foreach ($datetimes as $datetime) {
1118
+			$main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1119
+				$datetime_row,
1120
+				$datetime,
1121
+				$datetime_tickets,
1122
+				$all_tickets,
1123
+				false,
1124
+				$datetimes
1125
+			);
1126
+			$datetime_row++;
1127
+		}
1128
+		// then loop through all tickets for the ticket rows.
1129
+		$ticket_row = 1;
1130
+		foreach ($all_tickets as $ticket) {
1131
+			$main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1132
+				$ticket_row,
1133
+				$ticket,
1134
+				$ticket_datetimes,
1135
+				$datetimes,
1136
+				false,
1137
+				$all_tickets
1138
+			);
1139
+			$ticket_row++;
1140
+		}
1141
+		$main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1142 1142
 
1143
-        $status_change_notice = EventEspresso\core\services\loaders\LoaderFactory::getLoader()->getShared(
1144
-            'EventEspresso\core\admin\StatusChangeNotice'
1145
-        );
1146
-        if (! $status_change_notice->isDismissed()) {
1147
-            $main_template_args['status_change_notice'] = EEH_Template::display_template(
1148
-                EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
1149
-                ['context' => '__event-editor', 'page_slug' => 'espresso-events'],
1150
-                true
1151
-            );
1152
-        }
1143
+		$status_change_notice = EventEspresso\core\services\loaders\LoaderFactory::getLoader()->getShared(
1144
+			'EventEspresso\core\admin\StatusChangeNotice'
1145
+		);
1146
+		if (! $status_change_notice->isDismissed()) {
1147
+			$main_template_args['status_change_notice'] = EEH_Template::display_template(
1148
+				EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
1149
+				['context' => '__event-editor', 'page_slug' => 'espresso-events'],
1150
+				true
1151
+			);
1152
+		}
1153 1153
 
1154
-        EEH_Template::display_template(
1155
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1156
-            $main_template_args
1157
-        );
1158
-    }
1154
+		EEH_Template::display_template(
1155
+			PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1156
+			$main_template_args
1157
+		);
1158
+	}
1159 1159
 
1160 1160
 
1161
-    /**
1162
-     * @param int         $datetime_row
1163
-     * @param EE_Datetime $datetime
1164
-     * @param array       $datetime_tickets
1165
-     * @param array       $all_tickets
1166
-     * @param bool        $default
1167
-     * @param array       $all_datetimes
1168
-     * @return mixed
1169
-     * @throws DomainException
1170
-     * @throws EE_Error
1171
-     */
1172
-    protected function _get_datetime_row(
1173
-        $datetime_row,
1174
-        EE_Datetime $datetime,
1175
-        $datetime_tickets = array(),
1176
-        $all_tickets = array(),
1177
-        $default = false,
1178
-        $all_datetimes = array()
1179
-    ) {
1180
-        $dtt_display_template_args = array(
1181
-            'dtt_edit_row'             => $this->_get_dtt_edit_row(
1182
-                $datetime_row,
1183
-                $datetime,
1184
-                $default,
1185
-                $all_datetimes
1186
-            ),
1187
-            'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1188
-                $datetime_row,
1189
-                $datetime,
1190
-                $datetime_tickets,
1191
-                $all_tickets,
1192
-                $default
1193
-            ),
1194
-            'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1195
-        );
1196
-        return EEH_Template::display_template(
1197
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1198
-            $dtt_display_template_args,
1199
-            true
1200
-        );
1201
-    }
1161
+	/**
1162
+	 * @param int         $datetime_row
1163
+	 * @param EE_Datetime $datetime
1164
+	 * @param array       $datetime_tickets
1165
+	 * @param array       $all_tickets
1166
+	 * @param bool        $default
1167
+	 * @param array       $all_datetimes
1168
+	 * @return mixed
1169
+	 * @throws DomainException
1170
+	 * @throws EE_Error
1171
+	 */
1172
+	protected function _get_datetime_row(
1173
+		$datetime_row,
1174
+		EE_Datetime $datetime,
1175
+		$datetime_tickets = array(),
1176
+		$all_tickets = array(),
1177
+		$default = false,
1178
+		$all_datetimes = array()
1179
+	) {
1180
+		$dtt_display_template_args = array(
1181
+			'dtt_edit_row'             => $this->_get_dtt_edit_row(
1182
+				$datetime_row,
1183
+				$datetime,
1184
+				$default,
1185
+				$all_datetimes
1186
+			),
1187
+			'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1188
+				$datetime_row,
1189
+				$datetime,
1190
+				$datetime_tickets,
1191
+				$all_tickets,
1192
+				$default
1193
+			),
1194
+			'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1195
+		);
1196
+		return EEH_Template::display_template(
1197
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1198
+			$dtt_display_template_args,
1199
+			true
1200
+		);
1201
+	}
1202 1202
 
1203 1203
 
1204
-    /**
1205
-     * This method is used to generate a dtt fields  edit row.
1206
-     * The same row is used to generate a row with valid DTT objects
1207
-     * and the default row that is used as the skeleton by the js.
1208
-     *
1209
-     * @param int           $datetime_row  The row number for the row being generated.
1210
-     * @param EE_Datetime   $datetime
1211
-     * @param bool          $default       Whether a default row is being generated or not.
1212
-     * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1213
-     * @return string
1214
-     * @throws DomainException
1215
-     * @throws EE_Error
1216
-     */
1217
-    protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1218
-    {
1219
-        // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1220
-        $default = ! $datetime instanceof EE_Datetime ? true : $default;
1221
-        $template_args = array(
1222
-            'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1223
-            'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1224
-            'edit_dtt_expanded'    => '',
1225
-            'DTT_ID'               => $default ? '' : $datetime->ID(),
1226
-            'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1227
-            'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1228
-            'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1229
-            'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1230
-            'DTT_reg_limit'        => $default
1231
-                ? ''
1232
-                : $datetime->get_pretty(
1233
-                    'DTT_reg_limit',
1234
-                    'input'
1235
-                ),
1236
-            'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1237
-            'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1238
-            'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1239
-            'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1240
-                ? ''
1241
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1242
-            'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1243
-                ? 'ee-lock-icon'
1244
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1245
-            'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1246
-                ? ''
1247
-                : EE_Admin_Page::add_query_args_and_nonce(
1248
-                    array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1249
-                    REG_ADMIN_URL
1250
-                ),
1251
-        );
1252
-        $template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1253
-            ? ' style="display:none"'
1254
-            : '';
1255
-        // allow filtering of template args at this point.
1256
-        $template_args = apply_filters(
1257
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1258
-            $template_args,
1259
-            $datetime_row,
1260
-            $datetime,
1261
-            $default,
1262
-            $all_datetimes,
1263
-            $this->_is_creating_event
1264
-        );
1265
-        return EEH_Template::display_template(
1266
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1267
-            $template_args,
1268
-            true
1269
-        );
1270
-    }
1204
+	/**
1205
+	 * This method is used to generate a dtt fields  edit row.
1206
+	 * The same row is used to generate a row with valid DTT objects
1207
+	 * and the default row that is used as the skeleton by the js.
1208
+	 *
1209
+	 * @param int           $datetime_row  The row number for the row being generated.
1210
+	 * @param EE_Datetime   $datetime
1211
+	 * @param bool          $default       Whether a default row is being generated or not.
1212
+	 * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1213
+	 * @return string
1214
+	 * @throws DomainException
1215
+	 * @throws EE_Error
1216
+	 */
1217
+	protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1218
+	{
1219
+		// if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1220
+		$default = ! $datetime instanceof EE_Datetime ? true : $default;
1221
+		$template_args = array(
1222
+			'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1223
+			'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1224
+			'edit_dtt_expanded'    => '',
1225
+			'DTT_ID'               => $default ? '' : $datetime->ID(),
1226
+			'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1227
+			'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1228
+			'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1229
+			'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1230
+			'DTT_reg_limit'        => $default
1231
+				? ''
1232
+				: $datetime->get_pretty(
1233
+					'DTT_reg_limit',
1234
+					'input'
1235
+				),
1236
+			'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1237
+			'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1238
+			'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1239
+			'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1240
+				? ''
1241
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1242
+			'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1243
+				? 'ee-lock-icon'
1244
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1245
+			'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1246
+				? ''
1247
+				: EE_Admin_Page::add_query_args_and_nonce(
1248
+					array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1249
+					REG_ADMIN_URL
1250
+				),
1251
+		);
1252
+		$template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1253
+			? ' style="display:none"'
1254
+			: '';
1255
+		// allow filtering of template args at this point.
1256
+		$template_args = apply_filters(
1257
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1258
+			$template_args,
1259
+			$datetime_row,
1260
+			$datetime,
1261
+			$default,
1262
+			$all_datetimes,
1263
+			$this->_is_creating_event
1264
+		);
1265
+		return EEH_Template::display_template(
1266
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1267
+			$template_args,
1268
+			true
1269
+		);
1270
+	}
1271 1271
 
1272 1272
 
1273
-    /**
1274
-     * @param int         $datetime_row
1275
-     * @param EE_Datetime $datetime
1276
-     * @param array       $datetime_tickets
1277
-     * @param array       $all_tickets
1278
-     * @param bool        $default
1279
-     * @return mixed
1280
-     * @throws DomainException
1281
-     * @throws EE_Error
1282
-     */
1283
-    protected function _get_dtt_attached_tickets_row(
1284
-        $datetime_row,
1285
-        $datetime,
1286
-        $datetime_tickets = array(),
1287
-        $all_tickets = array(),
1288
-        $default
1289
-    ) {
1290
-        $template_args = array(
1291
-            'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1292
-            'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1293
-            'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1294
-            'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1295
-            'show_tickets_row'                  => ' style="display:none;"',
1296
-            'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1297
-                'add_new_ticket_via_datetime',
1298
-                $this->_adminpage_obj->page_slug,
1299
-                $this->_adminpage_obj->get_req_action(),
1300
-                false,
1301
-                false
1302
-            ),
1303
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1304
-            'DTT_ID'                            => $default ? '' : $datetime->ID(),
1305
-        );
1306
-        // need to setup the list items (but only if this isn't a default skeleton setup)
1307
-        if (! $default) {
1308
-            $ticket_row = 1;
1309
-            foreach ($all_tickets as $ticket) {
1310
-                $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1311
-                    $datetime_row,
1312
-                    $ticket_row,
1313
-                    $datetime,
1314
-                    $ticket,
1315
-                    $datetime_tickets,
1316
-                    $default
1317
-                );
1318
-                $ticket_row++;
1319
-            }
1320
-        }
1321
-        // filter template args at this point
1322
-        $template_args = apply_filters(
1323
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1324
-            $template_args,
1325
-            $datetime_row,
1326
-            $datetime,
1327
-            $datetime_tickets,
1328
-            $all_tickets,
1329
-            $default,
1330
-            $this->_is_creating_event
1331
-        );
1332
-        return EEH_Template::display_template(
1333
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1334
-            $template_args,
1335
-            true
1336
-        );
1337
-    }
1273
+	/**
1274
+	 * @param int         $datetime_row
1275
+	 * @param EE_Datetime $datetime
1276
+	 * @param array       $datetime_tickets
1277
+	 * @param array       $all_tickets
1278
+	 * @param bool        $default
1279
+	 * @return mixed
1280
+	 * @throws DomainException
1281
+	 * @throws EE_Error
1282
+	 */
1283
+	protected function _get_dtt_attached_tickets_row(
1284
+		$datetime_row,
1285
+		$datetime,
1286
+		$datetime_tickets = array(),
1287
+		$all_tickets = array(),
1288
+		$default
1289
+	) {
1290
+		$template_args = array(
1291
+			'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1292
+			'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1293
+			'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1294
+			'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1295
+			'show_tickets_row'                  => ' style="display:none;"',
1296
+			'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1297
+				'add_new_ticket_via_datetime',
1298
+				$this->_adminpage_obj->page_slug,
1299
+				$this->_adminpage_obj->get_req_action(),
1300
+				false,
1301
+				false
1302
+			),
1303
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1304
+			'DTT_ID'                            => $default ? '' : $datetime->ID(),
1305
+		);
1306
+		// need to setup the list items (but only if this isn't a default skeleton setup)
1307
+		if (! $default) {
1308
+			$ticket_row = 1;
1309
+			foreach ($all_tickets as $ticket) {
1310
+				$template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1311
+					$datetime_row,
1312
+					$ticket_row,
1313
+					$datetime,
1314
+					$ticket,
1315
+					$datetime_tickets,
1316
+					$default
1317
+				);
1318
+				$ticket_row++;
1319
+			}
1320
+		}
1321
+		// filter template args at this point
1322
+		$template_args = apply_filters(
1323
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1324
+			$template_args,
1325
+			$datetime_row,
1326
+			$datetime,
1327
+			$datetime_tickets,
1328
+			$all_tickets,
1329
+			$default,
1330
+			$this->_is_creating_event
1331
+		);
1332
+		return EEH_Template::display_template(
1333
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1334
+			$template_args,
1335
+			true
1336
+		);
1337
+	}
1338 1338
 
1339 1339
 
1340
-    /**
1341
-     * @param int         $datetime_row
1342
-     * @param int         $ticket_row
1343
-     * @param EE_Datetime $datetime
1344
-     * @param EE_Ticket   $ticket
1345
-     * @param array       $datetime_tickets
1346
-     * @param bool        $default
1347
-     * @return mixed
1348
-     * @throws DomainException
1349
-     * @throws EE_Error
1350
-     */
1351
-    protected function _get_datetime_tickets_list_item(
1352
-        $datetime_row,
1353
-        $ticket_row,
1354
-        $datetime,
1355
-        $ticket,
1356
-        $datetime_tickets = array(),
1357
-        $default
1358
-    ) {
1359
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1360
-            ? $datetime_tickets[ $datetime->ID() ]
1361
-            : array();
1362
-        $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1363
-        $no_ticket = $default && empty($ticket);
1364
-        $template_args = array(
1365
-            'dtt_row'                 => $default
1366
-                ? 'DTTNUM'
1367
-                : $datetime_row,
1368
-            'tkt_row'                 => $no_ticket
1369
-                ? 'TICKETNUM'
1370
-                : $ticket_row,
1371
-            'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1372
-                ? ' checked="checked"'
1373
-                : '',
1374
-            'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1375
-                ? ' ticket-selected'
1376
-                : '',
1377
-            'TKT_name'                => $no_ticket
1378
-                ? 'TKTNAME'
1379
-                : $ticket->get('TKT_name'),
1380
-            'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1381
-                ? ' tkt-status-' . EE_Ticket::onsale
1382
-                : ' tkt-status-' . $ticket->ticket_status(),
1383
-        );
1384
-        // filter template args
1385
-        $template_args = apply_filters(
1386
-            'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1387
-            $template_args,
1388
-            $datetime_row,
1389
-            $ticket_row,
1390
-            $datetime,
1391
-            $ticket,
1392
-            $datetime_tickets,
1393
-            $default,
1394
-            $this->_is_creating_event
1395
-        );
1396
-        return EEH_Template::display_template(
1397
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1398
-            $template_args,
1399
-            true
1400
-        );
1401
-    }
1340
+	/**
1341
+	 * @param int         $datetime_row
1342
+	 * @param int         $ticket_row
1343
+	 * @param EE_Datetime $datetime
1344
+	 * @param EE_Ticket   $ticket
1345
+	 * @param array       $datetime_tickets
1346
+	 * @param bool        $default
1347
+	 * @return mixed
1348
+	 * @throws DomainException
1349
+	 * @throws EE_Error
1350
+	 */
1351
+	protected function _get_datetime_tickets_list_item(
1352
+		$datetime_row,
1353
+		$ticket_row,
1354
+		$datetime,
1355
+		$ticket,
1356
+		$datetime_tickets = array(),
1357
+		$default
1358
+	) {
1359
+		$dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1360
+			? $datetime_tickets[ $datetime->ID() ]
1361
+			: array();
1362
+		$display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1363
+		$no_ticket = $default && empty($ticket);
1364
+		$template_args = array(
1365
+			'dtt_row'                 => $default
1366
+				? 'DTTNUM'
1367
+				: $datetime_row,
1368
+			'tkt_row'                 => $no_ticket
1369
+				? 'TICKETNUM'
1370
+				: $ticket_row,
1371
+			'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1372
+				? ' checked="checked"'
1373
+				: '',
1374
+			'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1375
+				? ' ticket-selected'
1376
+				: '',
1377
+			'TKT_name'                => $no_ticket
1378
+				? 'TKTNAME'
1379
+				: $ticket->get('TKT_name'),
1380
+			'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1381
+				? ' tkt-status-' . EE_Ticket::onsale
1382
+				: ' tkt-status-' . $ticket->ticket_status(),
1383
+		);
1384
+		// filter template args
1385
+		$template_args = apply_filters(
1386
+			'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1387
+			$template_args,
1388
+			$datetime_row,
1389
+			$ticket_row,
1390
+			$datetime,
1391
+			$ticket,
1392
+			$datetime_tickets,
1393
+			$default,
1394
+			$this->_is_creating_event
1395
+		);
1396
+		return EEH_Template::display_template(
1397
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1398
+			$template_args,
1399
+			true
1400
+		);
1401
+	}
1402 1402
 
1403 1403
 
1404
-    /**
1405
-     * This generates the ticket row for tickets.
1406
-     * This same method is used to generate both the actual rows and the js skeleton row
1407
-     * (when default === true)
1408
-     *
1409
-     * @param int           $ticket_row       Represents the row number being generated.
1410
-     * @param               $ticket
1411
-     * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1412
-     *                                        or empty for default
1413
-     * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1414
-     * @param bool          $default          Whether default row being generated or not.
1415
-     * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1416
-     *                                        (or empty in the case of defaults)
1417
-     * @return mixed
1418
-     * @throws InvalidArgumentException
1419
-     * @throws InvalidInterfaceException
1420
-     * @throws InvalidDataTypeException
1421
-     * @throws DomainException
1422
-     * @throws EE_Error
1423
-     * @throws ReflectionException
1424
-     */
1425
-    protected function _get_ticket_row(
1426
-        $ticket_row,
1427
-        $ticket,
1428
-        $ticket_datetimes,
1429
-        $all_datetimes,
1430
-        $default = false,
1431
-        $all_tickets = array()
1432
-    ) {
1433
-        // if $ticket is not an instance of EE_Ticket then force default to true.
1434
-        $default = ! $ticket instanceof EE_Ticket ? true : $default;
1435
-        $prices = ! empty($ticket) && ! $default
1436
-            ? $ticket->get_many_related(
1437
-                'Price',
1438
-                array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1439
-            )
1440
-            : array();
1441
-        // if there is only one price (which would be the base price)
1442
-        // or NO prices and this ticket is a default ticket,
1443
-        // let's just make sure there are no cached default prices on the object.
1444
-        // This is done by not including any query_params.
1445
-        if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1446
-            $prices = $ticket->prices();
1447
-        }
1448
-        // check if we're dealing with a default ticket in which case
1449
-        // we don't want any starting_ticket_datetime_row values set
1450
-        // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1451
-        // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1452
-        $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1453
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1454
-            ? $ticket_datetimes[ $ticket->ID() ]
1455
-            : array();
1456
-        $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1457
-        $base_price = $default ? null : $ticket->base_price();
1458
-        $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1459
-        // breaking out complicated condition for ticket_status
1460
-        if ($default) {
1461
-            $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1462
-        } else {
1463
-            $ticket_status_class = $ticket->is_default()
1464
-                ? ' tkt-status-' . EE_Ticket::onsale
1465
-                : ' tkt-status-' . $ticket->ticket_status();
1466
-        }
1467
-        // breaking out complicated condition for TKT_taxable
1468
-        if ($default) {
1469
-            $TKT_taxable = '';
1470
-        } else {
1471
-            $TKT_taxable = $ticket->taxable()
1472
-                ? ' checked="checked"'
1473
-                : '';
1474
-        }
1475
-        if ($default) {
1476
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1477
-        } elseif ($ticket->is_default()) {
1478
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1479
-        } else {
1480
-            $TKT_status = $ticket->ticket_status(true);
1481
-        }
1482
-        if ($default) {
1483
-            $TKT_min = '';
1484
-        } else {
1485
-            $TKT_min = $ticket->min();
1486
-            if ($TKT_min === -1 || $TKT_min === 0) {
1487
-                $TKT_min = '';
1488
-            }
1489
-        }
1490
-        $template_args = array(
1491
-            'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1492
-            'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1493
-            // on initial page load this will always be the correct order.
1494
-            'tkt_status_class'              => $ticket_status_class,
1495
-            'display_edit_tkt_row'          => ' style="display:none;"',
1496
-            'edit_tkt_expanded'             => '',
1497
-            'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1498
-            'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1499
-            'TKT_start_date'                => $default
1500
-                ? ''
1501
-                : $ticket->get_date('TKT_start_date', $this->_date_time_format),
1502
-            'TKT_end_date'                  => $default
1503
-                ? ''
1504
-                : $ticket->get_date('TKT_end_date', $this->_date_time_format),
1505
-            'TKT_status'                    => $TKT_status,
1506
-            'TKT_price'                     => $default
1507
-                ? ''
1508
-                : EEH_Template::format_currency(
1509
-                    $ticket->get_ticket_total_with_taxes(),
1510
-                    false,
1511
-                    false
1512
-                ),
1513
-            'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1514
-            'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1515
-            'TKT_qty'                       => $default
1516
-                ? ''
1517
-                : $ticket->get_pretty('TKT_qty', 'symbol'),
1518
-            'TKT_qty_for_input'             => $default
1519
-                ? ''
1520
-                : $ticket->get_pretty('TKT_qty', 'input'),
1521
-            'TKT_uses'                      => $default
1522
-                ? ''
1523
-                : $ticket->get_pretty('TKT_uses', 'input'),
1524
-            'TKT_min'                       => $TKT_min,
1525
-            'TKT_max'                       => $default
1526
-                ? ''
1527
-                : $ticket->get_pretty('TKT_max', 'input'),
1528
-            'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1529
-            'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1530
-            'TKT_registrations'             => $default
1531
-                ? 0
1532
-                : $ticket->count_registrations(
1533
-                    array(
1534
-                        array(
1535
-                            'STS_ID' => array(
1536
-                                '!=',
1537
-                                EEM_Registration::status_id_incomplete,
1538
-                            ),
1539
-                        ),
1540
-                    )
1541
-                ),
1542
-            'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1543
-            'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1544
-            'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1545
-            'TKT_required'                  => $default ? 0 : $ticket->required(),
1546
-            'TKT_is_default_selector'       => '',
1547
-            'ticket_price_rows'             => '',
1548
-            'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1549
-                ? ''
1550
-                : $base_price->get_pretty('PRC_amount', 'localized_float'),
1551
-            'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1552
-            'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1553
-                ? ''
1554
-                : ' style="display:none;"',
1555
-            'show_price_mod_button'         => count($prices) > 1
1556
-                                               || ($default && $count_price_mods > 0)
1557
-                                               || (! $default && $ticket->deleted())
1558
-                ? ' style="display:none;"'
1559
-                : '',
1560
-            'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1561
-            'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1562
-            'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1563
-            'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1564
-            'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1565
-            'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1566
-            'TKT_taxable'                   => $TKT_taxable,
1567
-            'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1568
-                ? ''
1569
-                : ' style="display:none"',
1570
-            'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1571
-            'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1572
-                $ticket_subtotal,
1573
-                false,
1574
-                false
1575
-            ),
1576
-            'TKT_subtotal_amount'           => $ticket_subtotal,
1577
-            'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1578
-            'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1579
-            'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1580
-                ? ' ticket-archived'
1581
-                : '',
1582
-            'trash_icon'                    => $ticket instanceof EE_Ticket
1583
-                                               && $ticket->deleted()
1584
-                                               && ! $ticket->is_permanently_deleteable()
1585
-                ? 'ee-lock-icon '
1586
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1587
-            'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1588
-                ? ''
1589
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1590
-        );
1591
-        $template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1592
-            ? ' style="display:none"'
1593
-            : '';
1594
-        // handle rows that should NOT be empty
1595
-        if (empty($template_args['TKT_start_date'])) {
1596
-            // if empty then the start date will be now.
1597
-            $template_args['TKT_start_date'] = date(
1598
-                $this->_date_time_format,
1599
-                current_time('timestamp')
1600
-            );
1601
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1602
-        }
1603
-        if (empty($template_args['TKT_end_date'])) {
1604
-            // get the earliest datetime (if present);
1605
-            $earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1606
-                ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1607
-                    'Datetime',
1608
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1609
-                )
1610
-                : null;
1611
-            if (! empty($earliest_dtt)) {
1612
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1613
-                    'DTT_EVT_start',
1614
-                    $this->_date_time_format
1615
-                );
1616
-            } else {
1617
-                // default so let's just use what's been set for the default date-time which is 30 days from now.
1618
-                $template_args['TKT_end_date'] = date(
1619
-                    $this->_date_time_format,
1620
-                    mktime(
1621
-                        24,
1622
-                        0,
1623
-                        0,
1624
-                        date('m'),
1625
-                        date('d') + 29,
1626
-                        date('Y')
1627
-                    )
1628
-                );
1629
-            }
1630
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1631
-        }
1632
-        // generate ticket_datetime items
1633
-        if (! $default) {
1634
-            $datetime_row = 1;
1635
-            foreach ($all_datetimes as $datetime) {
1636
-                $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1637
-                    $datetime_row,
1638
-                    $ticket_row,
1639
-                    $datetime,
1640
-                    $ticket,
1641
-                    $ticket_datetimes,
1642
-                    $default
1643
-                );
1644
-                $datetime_row++;
1645
-            }
1646
-        }
1647
-        $price_row = 1;
1648
-        foreach ($prices as $price) {
1649
-            if (! $price instanceof EE_Price) {
1650
-                continue;
1651
-            }
1652
-            if ($price->is_base_price()) {
1653
-                $price_row++;
1654
-                continue;
1655
-            }
1656
-            $show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1657
-            $show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1658
-            $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1659
-                $ticket_row,
1660
-                $price_row,
1661
-                $price,
1662
-                $default,
1663
-                $ticket,
1664
-                $show_trash,
1665
-                $show_create
1666
-            );
1667
-            $price_row++;
1668
-        }
1669
-        // filter $template_args
1670
-        $template_args = apply_filters(
1671
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1672
-            $template_args,
1673
-            $ticket_row,
1674
-            $ticket,
1675
-            $ticket_datetimes,
1676
-            $all_datetimes,
1677
-            $default,
1678
-            $all_tickets,
1679
-            $this->_is_creating_event
1680
-        );
1681
-        return EEH_Template::display_template(
1682
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1683
-            $template_args,
1684
-            true
1685
-        );
1686
-    }
1404
+	/**
1405
+	 * This generates the ticket row for tickets.
1406
+	 * This same method is used to generate both the actual rows and the js skeleton row
1407
+	 * (when default === true)
1408
+	 *
1409
+	 * @param int           $ticket_row       Represents the row number being generated.
1410
+	 * @param               $ticket
1411
+	 * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1412
+	 *                                        or empty for default
1413
+	 * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1414
+	 * @param bool          $default          Whether default row being generated or not.
1415
+	 * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1416
+	 *                                        (or empty in the case of defaults)
1417
+	 * @return mixed
1418
+	 * @throws InvalidArgumentException
1419
+	 * @throws InvalidInterfaceException
1420
+	 * @throws InvalidDataTypeException
1421
+	 * @throws DomainException
1422
+	 * @throws EE_Error
1423
+	 * @throws ReflectionException
1424
+	 */
1425
+	protected function _get_ticket_row(
1426
+		$ticket_row,
1427
+		$ticket,
1428
+		$ticket_datetimes,
1429
+		$all_datetimes,
1430
+		$default = false,
1431
+		$all_tickets = array()
1432
+	) {
1433
+		// if $ticket is not an instance of EE_Ticket then force default to true.
1434
+		$default = ! $ticket instanceof EE_Ticket ? true : $default;
1435
+		$prices = ! empty($ticket) && ! $default
1436
+			? $ticket->get_many_related(
1437
+				'Price',
1438
+				array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1439
+			)
1440
+			: array();
1441
+		// if there is only one price (which would be the base price)
1442
+		// or NO prices and this ticket is a default ticket,
1443
+		// let's just make sure there are no cached default prices on the object.
1444
+		// This is done by not including any query_params.
1445
+		if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1446
+			$prices = $ticket->prices();
1447
+		}
1448
+		// check if we're dealing with a default ticket in which case
1449
+		// we don't want any starting_ticket_datetime_row values set
1450
+		// (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1451
+		// This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1452
+		$default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1453
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1454
+			? $ticket_datetimes[ $ticket->ID() ]
1455
+			: array();
1456
+		$ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1457
+		$base_price = $default ? null : $ticket->base_price();
1458
+		$count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1459
+		// breaking out complicated condition for ticket_status
1460
+		if ($default) {
1461
+			$ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1462
+		} else {
1463
+			$ticket_status_class = $ticket->is_default()
1464
+				? ' tkt-status-' . EE_Ticket::onsale
1465
+				: ' tkt-status-' . $ticket->ticket_status();
1466
+		}
1467
+		// breaking out complicated condition for TKT_taxable
1468
+		if ($default) {
1469
+			$TKT_taxable = '';
1470
+		} else {
1471
+			$TKT_taxable = $ticket->taxable()
1472
+				? ' checked="checked"'
1473
+				: '';
1474
+		}
1475
+		if ($default) {
1476
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1477
+		} elseif ($ticket->is_default()) {
1478
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1479
+		} else {
1480
+			$TKT_status = $ticket->ticket_status(true);
1481
+		}
1482
+		if ($default) {
1483
+			$TKT_min = '';
1484
+		} else {
1485
+			$TKT_min = $ticket->min();
1486
+			if ($TKT_min === -1 || $TKT_min === 0) {
1487
+				$TKT_min = '';
1488
+			}
1489
+		}
1490
+		$template_args = array(
1491
+			'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1492
+			'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1493
+			// on initial page load this will always be the correct order.
1494
+			'tkt_status_class'              => $ticket_status_class,
1495
+			'display_edit_tkt_row'          => ' style="display:none;"',
1496
+			'edit_tkt_expanded'             => '',
1497
+			'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1498
+			'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1499
+			'TKT_start_date'                => $default
1500
+				? ''
1501
+				: $ticket->get_date('TKT_start_date', $this->_date_time_format),
1502
+			'TKT_end_date'                  => $default
1503
+				? ''
1504
+				: $ticket->get_date('TKT_end_date', $this->_date_time_format),
1505
+			'TKT_status'                    => $TKT_status,
1506
+			'TKT_price'                     => $default
1507
+				? ''
1508
+				: EEH_Template::format_currency(
1509
+					$ticket->get_ticket_total_with_taxes(),
1510
+					false,
1511
+					false
1512
+				),
1513
+			'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1514
+			'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1515
+			'TKT_qty'                       => $default
1516
+				? ''
1517
+				: $ticket->get_pretty('TKT_qty', 'symbol'),
1518
+			'TKT_qty_for_input'             => $default
1519
+				? ''
1520
+				: $ticket->get_pretty('TKT_qty', 'input'),
1521
+			'TKT_uses'                      => $default
1522
+				? ''
1523
+				: $ticket->get_pretty('TKT_uses', 'input'),
1524
+			'TKT_min'                       => $TKT_min,
1525
+			'TKT_max'                       => $default
1526
+				? ''
1527
+				: $ticket->get_pretty('TKT_max', 'input'),
1528
+			'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1529
+			'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1530
+			'TKT_registrations'             => $default
1531
+				? 0
1532
+				: $ticket->count_registrations(
1533
+					array(
1534
+						array(
1535
+							'STS_ID' => array(
1536
+								'!=',
1537
+								EEM_Registration::status_id_incomplete,
1538
+							),
1539
+						),
1540
+					)
1541
+				),
1542
+			'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1543
+			'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1544
+			'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1545
+			'TKT_required'                  => $default ? 0 : $ticket->required(),
1546
+			'TKT_is_default_selector'       => '',
1547
+			'ticket_price_rows'             => '',
1548
+			'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1549
+				? ''
1550
+				: $base_price->get_pretty('PRC_amount', 'localized_float'),
1551
+			'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1552
+			'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1553
+				? ''
1554
+				: ' style="display:none;"',
1555
+			'show_price_mod_button'         => count($prices) > 1
1556
+											   || ($default && $count_price_mods > 0)
1557
+											   || (! $default && $ticket->deleted())
1558
+				? ' style="display:none;"'
1559
+				: '',
1560
+			'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1561
+			'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1562
+			'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1563
+			'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1564
+			'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1565
+			'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1566
+			'TKT_taxable'                   => $TKT_taxable,
1567
+			'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1568
+				? ''
1569
+				: ' style="display:none"',
1570
+			'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1571
+			'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1572
+				$ticket_subtotal,
1573
+				false,
1574
+				false
1575
+			),
1576
+			'TKT_subtotal_amount'           => $ticket_subtotal,
1577
+			'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1578
+			'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1579
+			'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1580
+				? ' ticket-archived'
1581
+				: '',
1582
+			'trash_icon'                    => $ticket instanceof EE_Ticket
1583
+											   && $ticket->deleted()
1584
+											   && ! $ticket->is_permanently_deleteable()
1585
+				? 'ee-lock-icon '
1586
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1587
+			'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1588
+				? ''
1589
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1590
+		);
1591
+		$template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1592
+			? ' style="display:none"'
1593
+			: '';
1594
+		// handle rows that should NOT be empty
1595
+		if (empty($template_args['TKT_start_date'])) {
1596
+			// if empty then the start date will be now.
1597
+			$template_args['TKT_start_date'] = date(
1598
+				$this->_date_time_format,
1599
+				current_time('timestamp')
1600
+			);
1601
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1602
+		}
1603
+		if (empty($template_args['TKT_end_date'])) {
1604
+			// get the earliest datetime (if present);
1605
+			$earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1606
+				? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1607
+					'Datetime',
1608
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1609
+				)
1610
+				: null;
1611
+			if (! empty($earliest_dtt)) {
1612
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1613
+					'DTT_EVT_start',
1614
+					$this->_date_time_format
1615
+				);
1616
+			} else {
1617
+				// default so let's just use what's been set for the default date-time which is 30 days from now.
1618
+				$template_args['TKT_end_date'] = date(
1619
+					$this->_date_time_format,
1620
+					mktime(
1621
+						24,
1622
+						0,
1623
+						0,
1624
+						date('m'),
1625
+						date('d') + 29,
1626
+						date('Y')
1627
+					)
1628
+				);
1629
+			}
1630
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1631
+		}
1632
+		// generate ticket_datetime items
1633
+		if (! $default) {
1634
+			$datetime_row = 1;
1635
+			foreach ($all_datetimes as $datetime) {
1636
+				$template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1637
+					$datetime_row,
1638
+					$ticket_row,
1639
+					$datetime,
1640
+					$ticket,
1641
+					$ticket_datetimes,
1642
+					$default
1643
+				);
1644
+				$datetime_row++;
1645
+			}
1646
+		}
1647
+		$price_row = 1;
1648
+		foreach ($prices as $price) {
1649
+			if (! $price instanceof EE_Price) {
1650
+				continue;
1651
+			}
1652
+			if ($price->is_base_price()) {
1653
+				$price_row++;
1654
+				continue;
1655
+			}
1656
+			$show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1657
+			$show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1658
+			$template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1659
+				$ticket_row,
1660
+				$price_row,
1661
+				$price,
1662
+				$default,
1663
+				$ticket,
1664
+				$show_trash,
1665
+				$show_create
1666
+			);
1667
+			$price_row++;
1668
+		}
1669
+		// filter $template_args
1670
+		$template_args = apply_filters(
1671
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1672
+			$template_args,
1673
+			$ticket_row,
1674
+			$ticket,
1675
+			$ticket_datetimes,
1676
+			$all_datetimes,
1677
+			$default,
1678
+			$all_tickets,
1679
+			$this->_is_creating_event
1680
+		);
1681
+		return EEH_Template::display_template(
1682
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1683
+			$template_args,
1684
+			true
1685
+		);
1686
+	}
1687 1687
 
1688 1688
 
1689
-    /**
1690
-     * @param int            $ticket_row
1691
-     * @param EE_Ticket|null $ticket
1692
-     * @return string
1693
-     * @throws DomainException
1694
-     * @throws EE_Error
1695
-     */
1696
-    protected function _get_tax_rows($ticket_row, $ticket)
1697
-    {
1698
-        $tax_rows = '';
1699
-        /** @var EE_Price[] $taxes */
1700
-        $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1701
-        foreach ($taxes as $tax) {
1702
-            $tax_added = $this->_get_tax_added($tax, $ticket);
1703
-            $template_args = array(
1704
-                'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1705
-                    ? ''
1706
-                    : ' style="display:none;"',
1707
-                'tax_id'            => $tax->ID(),
1708
-                'tkt_row'           => $ticket_row,
1709
-                'tax_label'         => $tax->get('PRC_name'),
1710
-                'tax_added'         => $tax_added,
1711
-                'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1712
-                'tax_amount'        => $tax->get('PRC_amount'),
1713
-            );
1714
-            $template_args = apply_filters(
1715
-                'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1716
-                $template_args,
1717
-                $ticket_row,
1718
-                $ticket,
1719
-                $this->_is_creating_event
1720
-            );
1721
-            $tax_rows .= EEH_Template::display_template(
1722
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1723
-                $template_args,
1724
-                true
1725
-            );
1726
-        }
1727
-        return $tax_rows;
1728
-    }
1689
+	/**
1690
+	 * @param int            $ticket_row
1691
+	 * @param EE_Ticket|null $ticket
1692
+	 * @return string
1693
+	 * @throws DomainException
1694
+	 * @throws EE_Error
1695
+	 */
1696
+	protected function _get_tax_rows($ticket_row, $ticket)
1697
+	{
1698
+		$tax_rows = '';
1699
+		/** @var EE_Price[] $taxes */
1700
+		$taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1701
+		foreach ($taxes as $tax) {
1702
+			$tax_added = $this->_get_tax_added($tax, $ticket);
1703
+			$template_args = array(
1704
+				'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1705
+					? ''
1706
+					: ' style="display:none;"',
1707
+				'tax_id'            => $tax->ID(),
1708
+				'tkt_row'           => $ticket_row,
1709
+				'tax_label'         => $tax->get('PRC_name'),
1710
+				'tax_added'         => $tax_added,
1711
+				'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1712
+				'tax_amount'        => $tax->get('PRC_amount'),
1713
+			);
1714
+			$template_args = apply_filters(
1715
+				'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1716
+				$template_args,
1717
+				$ticket_row,
1718
+				$ticket,
1719
+				$this->_is_creating_event
1720
+			);
1721
+			$tax_rows .= EEH_Template::display_template(
1722
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1723
+				$template_args,
1724
+				true
1725
+			);
1726
+		}
1727
+		return $tax_rows;
1728
+	}
1729 1729
 
1730 1730
 
1731
-    /**
1732
-     * @param EE_Price       $tax
1733
-     * @param EE_Ticket|null $ticket
1734
-     * @return float|int
1735
-     * @throws EE_Error
1736
-     */
1737
-    protected function _get_tax_added(EE_Price $tax, $ticket)
1738
-    {
1739
-        $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1740
-        return $subtotal * $tax->get('PRC_amount') / 100;
1741
-    }
1731
+	/**
1732
+	 * @param EE_Price       $tax
1733
+	 * @param EE_Ticket|null $ticket
1734
+	 * @return float|int
1735
+	 * @throws EE_Error
1736
+	 */
1737
+	protected function _get_tax_added(EE_Price $tax, $ticket)
1738
+	{
1739
+		$subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1740
+		return $subtotal * $tax->get('PRC_amount') / 100;
1741
+	}
1742 1742
 
1743 1743
 
1744
-    /**
1745
-     * @param int            $ticket_row
1746
-     * @param int            $price_row
1747
-     * @param EE_Price|null  $price
1748
-     * @param bool           $default
1749
-     * @param EE_Ticket|null $ticket
1750
-     * @param bool           $show_trash
1751
-     * @param bool           $show_create
1752
-     * @return mixed
1753
-     * @throws InvalidArgumentException
1754
-     * @throws InvalidInterfaceException
1755
-     * @throws InvalidDataTypeException
1756
-     * @throws DomainException
1757
-     * @throws EE_Error
1758
-     * @throws ReflectionException
1759
-     */
1760
-    protected function _get_ticket_price_row(
1761
-        $ticket_row,
1762
-        $price_row,
1763
-        $price,
1764
-        $default,
1765
-        $ticket,
1766
-        $show_trash = true,
1767
-        $show_create = true
1768
-    ) {
1769
-        $send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1770
-        $template_args = array(
1771
-            'tkt_row'               => $default && empty($ticket)
1772
-                ? 'TICKETNUM'
1773
-                : $ticket_row,
1774
-            'PRC_order'             => $default && empty($price)
1775
-                ? 'PRICENUM'
1776
-                : $price_row,
1777
-            'edit_prices_name'      => $default && empty($price)
1778
-                ? 'PRICENAMEATTR'
1779
-                : 'edit_prices',
1780
-            'price_type_selector'   => $default && empty($price)
1781
-                ? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1782
-                : $this->_get_price_type_selector(
1783
-                    $ticket_row,
1784
-                    $price_row,
1785
-                    $price,
1786
-                    $default,
1787
-                    $send_disabled
1788
-                ),
1789
-            'PRC_ID'                => $default && empty($price)
1790
-                ? 0
1791
-                : $price->ID(),
1792
-            'PRC_is_default'        => $default && empty($price)
1793
-                ? 0
1794
-                : $price->get('PRC_is_default'),
1795
-            'PRC_name'              => $default && empty($price)
1796
-                ? ''
1797
-                : $price->get('PRC_name'),
1798
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1799
-            'show_plus_or_minus'    => $default && empty($price)
1800
-                ? ''
1801
-                : ' style="display:none;"',
1802
-            'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1803
-                ? ' style="display:none;"'
1804
-                : '',
1805
-            'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1806
-                ? ' style="display:none;"'
1807
-                : '',
1808
-            'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1809
-                ? ' style="display:none"'
1810
-                : '',
1811
-            'PRC_amount'            => $default && empty($price)
1812
-                ? 0
1813
-                : $price->get_pretty('PRC_amount', 'localized_float'),
1814
-            'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1815
-                ? ' style="display:none;"'
1816
-                : '',
1817
-            'show_trash_icon'       => $show_trash
1818
-                ? ''
1819
-                : ' style="display:none;"',
1820
-            'show_create_button'    => $show_create
1821
-                ? ''
1822
-                : ' style="display:none;"',
1823
-            'PRC_desc'              => $default && empty($price)
1824
-                ? ''
1825
-                : $price->get('PRC_desc'),
1826
-            'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1827
-        );
1828
-        $template_args = apply_filters(
1829
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1830
-            $template_args,
1831
-            $ticket_row,
1832
-            $price_row,
1833
-            $price,
1834
-            $default,
1835
-            $ticket,
1836
-            $show_trash,
1837
-            $show_create,
1838
-            $this->_is_creating_event
1839
-        );
1840
-        return EEH_Template::display_template(
1841
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1842
-            $template_args,
1843
-            true
1844
-        );
1845
-    }
1744
+	/**
1745
+	 * @param int            $ticket_row
1746
+	 * @param int            $price_row
1747
+	 * @param EE_Price|null  $price
1748
+	 * @param bool           $default
1749
+	 * @param EE_Ticket|null $ticket
1750
+	 * @param bool           $show_trash
1751
+	 * @param bool           $show_create
1752
+	 * @return mixed
1753
+	 * @throws InvalidArgumentException
1754
+	 * @throws InvalidInterfaceException
1755
+	 * @throws InvalidDataTypeException
1756
+	 * @throws DomainException
1757
+	 * @throws EE_Error
1758
+	 * @throws ReflectionException
1759
+	 */
1760
+	protected function _get_ticket_price_row(
1761
+		$ticket_row,
1762
+		$price_row,
1763
+		$price,
1764
+		$default,
1765
+		$ticket,
1766
+		$show_trash = true,
1767
+		$show_create = true
1768
+	) {
1769
+		$send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1770
+		$template_args = array(
1771
+			'tkt_row'               => $default && empty($ticket)
1772
+				? 'TICKETNUM'
1773
+				: $ticket_row,
1774
+			'PRC_order'             => $default && empty($price)
1775
+				? 'PRICENUM'
1776
+				: $price_row,
1777
+			'edit_prices_name'      => $default && empty($price)
1778
+				? 'PRICENAMEATTR'
1779
+				: 'edit_prices',
1780
+			'price_type_selector'   => $default && empty($price)
1781
+				? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1782
+				: $this->_get_price_type_selector(
1783
+					$ticket_row,
1784
+					$price_row,
1785
+					$price,
1786
+					$default,
1787
+					$send_disabled
1788
+				),
1789
+			'PRC_ID'                => $default && empty($price)
1790
+				? 0
1791
+				: $price->ID(),
1792
+			'PRC_is_default'        => $default && empty($price)
1793
+				? 0
1794
+				: $price->get('PRC_is_default'),
1795
+			'PRC_name'              => $default && empty($price)
1796
+				? ''
1797
+				: $price->get('PRC_name'),
1798
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1799
+			'show_plus_or_minus'    => $default && empty($price)
1800
+				? ''
1801
+				: ' style="display:none;"',
1802
+			'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1803
+				? ' style="display:none;"'
1804
+				: '',
1805
+			'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1806
+				? ' style="display:none;"'
1807
+				: '',
1808
+			'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1809
+				? ' style="display:none"'
1810
+				: '',
1811
+			'PRC_amount'            => $default && empty($price)
1812
+				? 0
1813
+				: $price->get_pretty('PRC_amount', 'localized_float'),
1814
+			'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1815
+				? ' style="display:none;"'
1816
+				: '',
1817
+			'show_trash_icon'       => $show_trash
1818
+				? ''
1819
+				: ' style="display:none;"',
1820
+			'show_create_button'    => $show_create
1821
+				? ''
1822
+				: ' style="display:none;"',
1823
+			'PRC_desc'              => $default && empty($price)
1824
+				? ''
1825
+				: $price->get('PRC_desc'),
1826
+			'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1827
+		);
1828
+		$template_args = apply_filters(
1829
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1830
+			$template_args,
1831
+			$ticket_row,
1832
+			$price_row,
1833
+			$price,
1834
+			$default,
1835
+			$ticket,
1836
+			$show_trash,
1837
+			$show_create,
1838
+			$this->_is_creating_event
1839
+		);
1840
+		return EEH_Template::display_template(
1841
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1842
+			$template_args,
1843
+			true
1844
+		);
1845
+	}
1846 1846
 
1847 1847
 
1848
-    /**
1849
-     * @param int      $ticket_row
1850
-     * @param int      $price_row
1851
-     * @param EE_Price $price
1852
-     * @param bool     $default
1853
-     * @param bool     $disabled
1854
-     * @return mixed
1855
-     * @throws ReflectionException
1856
-     * @throws InvalidArgumentException
1857
-     * @throws InvalidInterfaceException
1858
-     * @throws InvalidDataTypeException
1859
-     * @throws DomainException
1860
-     * @throws EE_Error
1861
-     */
1862
-    protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1863
-    {
1864
-        if ($price->is_base_price()) {
1865
-            return $this->_get_base_price_template(
1866
-                $ticket_row,
1867
-                $price_row,
1868
-                $price,
1869
-                $default
1870
-            );
1871
-        }
1872
-        return $this->_get_price_modifier_template(
1873
-            $ticket_row,
1874
-            $price_row,
1875
-            $price,
1876
-            $default,
1877
-            $disabled
1878
-        );
1879
-    }
1848
+	/**
1849
+	 * @param int      $ticket_row
1850
+	 * @param int      $price_row
1851
+	 * @param EE_Price $price
1852
+	 * @param bool     $default
1853
+	 * @param bool     $disabled
1854
+	 * @return mixed
1855
+	 * @throws ReflectionException
1856
+	 * @throws InvalidArgumentException
1857
+	 * @throws InvalidInterfaceException
1858
+	 * @throws InvalidDataTypeException
1859
+	 * @throws DomainException
1860
+	 * @throws EE_Error
1861
+	 */
1862
+	protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1863
+	{
1864
+		if ($price->is_base_price()) {
1865
+			return $this->_get_base_price_template(
1866
+				$ticket_row,
1867
+				$price_row,
1868
+				$price,
1869
+				$default
1870
+			);
1871
+		}
1872
+		return $this->_get_price_modifier_template(
1873
+			$ticket_row,
1874
+			$price_row,
1875
+			$price,
1876
+			$default,
1877
+			$disabled
1878
+		);
1879
+	}
1880 1880
 
1881 1881
 
1882
-    /**
1883
-     * @param int      $ticket_row
1884
-     * @param int      $price_row
1885
-     * @param EE_Price $price
1886
-     * @param bool     $default
1887
-     * @return mixed
1888
-     * @throws DomainException
1889
-     * @throws EE_Error
1890
-     */
1891
-    protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1892
-    {
1893
-        $template_args = array(
1894
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1895
-            'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1896
-            'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1897
-            'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1898
-            'price_selected_operator'   => '+',
1899
-            'price_selected_is_percent' => 0,
1900
-        );
1901
-        $template_args = apply_filters(
1902
-            'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1903
-            $template_args,
1904
-            $ticket_row,
1905
-            $price_row,
1906
-            $price,
1907
-            $default,
1908
-            $this->_is_creating_event
1909
-        );
1910
-        return EEH_Template::display_template(
1911
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1912
-            $template_args,
1913
-            true
1914
-        );
1915
-    }
1882
+	/**
1883
+	 * @param int      $ticket_row
1884
+	 * @param int      $price_row
1885
+	 * @param EE_Price $price
1886
+	 * @param bool     $default
1887
+	 * @return mixed
1888
+	 * @throws DomainException
1889
+	 * @throws EE_Error
1890
+	 */
1891
+	protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1892
+	{
1893
+		$template_args = array(
1894
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1895
+			'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1896
+			'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1897
+			'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1898
+			'price_selected_operator'   => '+',
1899
+			'price_selected_is_percent' => 0,
1900
+		);
1901
+		$template_args = apply_filters(
1902
+			'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1903
+			$template_args,
1904
+			$ticket_row,
1905
+			$price_row,
1906
+			$price,
1907
+			$default,
1908
+			$this->_is_creating_event
1909
+		);
1910
+		return EEH_Template::display_template(
1911
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1912
+			$template_args,
1913
+			true
1914
+		);
1915
+	}
1916 1916
 
1917 1917
 
1918
-    /**
1919
-     * @param int      $ticket_row
1920
-     * @param int      $price_row
1921
-     * @param EE_Price $price
1922
-     * @param bool     $default
1923
-     * @param bool     $disabled
1924
-     * @return mixed
1925
-     * @throws ReflectionException
1926
-     * @throws InvalidArgumentException
1927
-     * @throws InvalidInterfaceException
1928
-     * @throws InvalidDataTypeException
1929
-     * @throws DomainException
1930
-     * @throws EE_Error
1931
-     */
1932
-    protected function _get_price_modifier_template(
1933
-        $ticket_row,
1934
-        $price_row,
1935
-        $price,
1936
-        $default,
1937
-        $disabled = false
1938
-    ) {
1939
-        $select_name = $default && ! $price instanceof EE_Price
1940
-            ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1941
-            : 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1942
-        /** @var EEM_Price_Type $price_type_model */
1943
-        $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1944
-        $price_types = $price_type_model->get_all(array(
1945
-            array(
1946
-                'OR' => array(
1947
-                    'PBT_ID'  => '2',
1948
-                    'PBT_ID*' => '3',
1949
-                ),
1950
-            ),
1951
-        ));
1952
-        $all_price_types = $default && ! $price instanceof EE_Price
1953
-            ? array(esc_html__('Select Modifier', 'event_espresso'))
1954
-            : array();
1955
-        $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1956
-        $price_option_spans = '';
1957
-        // setup price types for selector
1958
-        foreach ($price_types as $price_type) {
1959
-            if (! $price_type instanceof EE_Price_Type) {
1960
-                continue;
1961
-            }
1962
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1963
-            // while we're in the loop let's setup the option spans used by js
1964
-            $span_args = array(
1965
-                'PRT_ID'         => $price_type->ID(),
1966
-                'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1967
-                'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1968
-            );
1969
-            $price_option_spans .= EEH_Template::display_template(
1970
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1971
-                $span_args,
1972
-                true
1973
-            );
1974
-        }
1975
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1976
-            : $select_name;
1977
-        $select_input = new EE_Select_Input(
1978
-            $all_price_types,
1979
-            array(
1980
-                'default'               => $selected_price_type_id,
1981
-                'html_name'             => $select_name,
1982
-                'html_class'            => 'edit-price-PRT_ID',
1983
-                'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1984
-            )
1985
-        );
1986
-        $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1987
-        $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1988
-        $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1989
-        $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1990
-        $template_args = array(
1991
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1992
-            'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1993
-            'price_modifier_selector'   => $select_input->get_html_for_input(),
1994
-            'main_name'                 => $select_name,
1995
-            'selected_price_type_id'    => $selected_price_type_id,
1996
-            'price_option_spans'        => $price_option_spans,
1997
-            'price_selected_operator'   => $price_selected_operator,
1998
-            'price_selected_is_percent' => $price_selected_is_percent,
1999
-            'disabled'                  => $disabled,
2000
-        );
2001
-        $template_args = apply_filters(
2002
-            'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
2003
-            $template_args,
2004
-            $ticket_row,
2005
-            $price_row,
2006
-            $price,
2007
-            $default,
2008
-            $disabled,
2009
-            $this->_is_creating_event
2010
-        );
2011
-        return EEH_Template::display_template(
2012
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2013
-            $template_args,
2014
-            true
2015
-        );
2016
-    }
1918
+	/**
1919
+	 * @param int      $ticket_row
1920
+	 * @param int      $price_row
1921
+	 * @param EE_Price $price
1922
+	 * @param bool     $default
1923
+	 * @param bool     $disabled
1924
+	 * @return mixed
1925
+	 * @throws ReflectionException
1926
+	 * @throws InvalidArgumentException
1927
+	 * @throws InvalidInterfaceException
1928
+	 * @throws InvalidDataTypeException
1929
+	 * @throws DomainException
1930
+	 * @throws EE_Error
1931
+	 */
1932
+	protected function _get_price_modifier_template(
1933
+		$ticket_row,
1934
+		$price_row,
1935
+		$price,
1936
+		$default,
1937
+		$disabled = false
1938
+	) {
1939
+		$select_name = $default && ! $price instanceof EE_Price
1940
+			? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1941
+			: 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1942
+		/** @var EEM_Price_Type $price_type_model */
1943
+		$price_type_model = EE_Registry::instance()->load_model('Price_Type');
1944
+		$price_types = $price_type_model->get_all(array(
1945
+			array(
1946
+				'OR' => array(
1947
+					'PBT_ID'  => '2',
1948
+					'PBT_ID*' => '3',
1949
+				),
1950
+			),
1951
+		));
1952
+		$all_price_types = $default && ! $price instanceof EE_Price
1953
+			? array(esc_html__('Select Modifier', 'event_espresso'))
1954
+			: array();
1955
+		$selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1956
+		$price_option_spans = '';
1957
+		// setup price types for selector
1958
+		foreach ($price_types as $price_type) {
1959
+			if (! $price_type instanceof EE_Price_Type) {
1960
+				continue;
1961
+			}
1962
+			$all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1963
+			// while we're in the loop let's setup the option spans used by js
1964
+			$span_args = array(
1965
+				'PRT_ID'         => $price_type->ID(),
1966
+				'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1967
+				'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1968
+			);
1969
+			$price_option_spans .= EEH_Template::display_template(
1970
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1971
+				$span_args,
1972
+				true
1973
+			);
1974
+		}
1975
+		$select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1976
+			: $select_name;
1977
+		$select_input = new EE_Select_Input(
1978
+			$all_price_types,
1979
+			array(
1980
+				'default'               => $selected_price_type_id,
1981
+				'html_name'             => $select_name,
1982
+				'html_class'            => 'edit-price-PRT_ID',
1983
+				'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1984
+			)
1985
+		);
1986
+		$price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1987
+		$price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1988
+		$price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1989
+		$price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1990
+		$template_args = array(
1991
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1992
+			'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1993
+			'price_modifier_selector'   => $select_input->get_html_for_input(),
1994
+			'main_name'                 => $select_name,
1995
+			'selected_price_type_id'    => $selected_price_type_id,
1996
+			'price_option_spans'        => $price_option_spans,
1997
+			'price_selected_operator'   => $price_selected_operator,
1998
+			'price_selected_is_percent' => $price_selected_is_percent,
1999
+			'disabled'                  => $disabled,
2000
+		);
2001
+		$template_args = apply_filters(
2002
+			'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
2003
+			$template_args,
2004
+			$ticket_row,
2005
+			$price_row,
2006
+			$price,
2007
+			$default,
2008
+			$disabled,
2009
+			$this->_is_creating_event
2010
+		);
2011
+		return EEH_Template::display_template(
2012
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2013
+			$template_args,
2014
+			true
2015
+		);
2016
+	}
2017 2017
 
2018 2018
 
2019
-    /**
2020
-     * @param int              $datetime_row
2021
-     * @param int              $ticket_row
2022
-     * @param EE_Datetime|null $datetime
2023
-     * @param EE_Ticket|null   $ticket
2024
-     * @param array            $ticket_datetimes
2025
-     * @param bool             $default
2026
-     * @return mixed
2027
-     * @throws DomainException
2028
-     * @throws EE_Error
2029
-     */
2030
-    protected function _get_ticket_datetime_list_item(
2031
-        $datetime_row,
2032
-        $ticket_row,
2033
-        $datetime,
2034
-        $ticket,
2035
-        $ticket_datetimes = array(),
2036
-        $default
2037
-    ) {
2038
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2039
-            ? $ticket_datetimes[ $ticket->ID() ]
2040
-            : array();
2041
-        $template_args = array(
2042
-            'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2043
-                ? 'DTTNUM'
2044
-                : $datetime_row,
2045
-            'tkt_row'                  => $default
2046
-                ? 'TICKETNUM'
2047
-                : $ticket_row,
2048
-            'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2049
-                ? ' ticket-selected'
2050
-                : '',
2051
-            'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2052
-                ? ' checked="checked"'
2053
-                : '',
2054
-            'DTT_name'                 => $default && empty($datetime)
2055
-                ? 'DTTNAME'
2056
-                : $datetime->get_dtt_display_name(true),
2057
-            'tkt_status_class'         => '',
2058
-        );
2059
-        $template_args = apply_filters(
2060
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2061
-            $template_args,
2062
-            $datetime_row,
2063
-            $ticket_row,
2064
-            $datetime,
2065
-            $ticket,
2066
-            $ticket_datetimes,
2067
-            $default,
2068
-            $this->_is_creating_event
2069
-        );
2070
-        return EEH_Template::display_template(
2071
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2072
-            $template_args,
2073
-            true
2074
-        );
2075
-    }
2019
+	/**
2020
+	 * @param int              $datetime_row
2021
+	 * @param int              $ticket_row
2022
+	 * @param EE_Datetime|null $datetime
2023
+	 * @param EE_Ticket|null   $ticket
2024
+	 * @param array            $ticket_datetimes
2025
+	 * @param bool             $default
2026
+	 * @return mixed
2027
+	 * @throws DomainException
2028
+	 * @throws EE_Error
2029
+	 */
2030
+	protected function _get_ticket_datetime_list_item(
2031
+		$datetime_row,
2032
+		$ticket_row,
2033
+		$datetime,
2034
+		$ticket,
2035
+		$ticket_datetimes = array(),
2036
+		$default
2037
+	) {
2038
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2039
+			? $ticket_datetimes[ $ticket->ID() ]
2040
+			: array();
2041
+		$template_args = array(
2042
+			'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2043
+				? 'DTTNUM'
2044
+				: $datetime_row,
2045
+			'tkt_row'                  => $default
2046
+				? 'TICKETNUM'
2047
+				: $ticket_row,
2048
+			'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2049
+				? ' ticket-selected'
2050
+				: '',
2051
+			'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2052
+				? ' checked="checked"'
2053
+				: '',
2054
+			'DTT_name'                 => $default && empty($datetime)
2055
+				? 'DTTNAME'
2056
+				: $datetime->get_dtt_display_name(true),
2057
+			'tkt_status_class'         => '',
2058
+		);
2059
+		$template_args = apply_filters(
2060
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2061
+			$template_args,
2062
+			$datetime_row,
2063
+			$ticket_row,
2064
+			$datetime,
2065
+			$ticket,
2066
+			$ticket_datetimes,
2067
+			$default,
2068
+			$this->_is_creating_event
2069
+		);
2070
+		return EEH_Template::display_template(
2071
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2072
+			$template_args,
2073
+			true
2074
+		);
2075
+	}
2076 2076
 
2077 2077
 
2078
-    /**
2079
-     * @param array $all_datetimes
2080
-     * @param array $all_tickets
2081
-     * @return mixed
2082
-     * @throws ReflectionException
2083
-     * @throws InvalidArgumentException
2084
-     * @throws InvalidInterfaceException
2085
-     * @throws InvalidDataTypeException
2086
-     * @throws DomainException
2087
-     * @throws EE_Error
2088
-     */
2089
-    protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2090
-    {
2091
-        $template_args = array(
2092
-            'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2093
-                'DTTNUM',
2094
-                null,
2095
-                true,
2096
-                $all_datetimes
2097
-            ),
2098
-            'default_ticket_row'                       => $this->_get_ticket_row(
2099
-                'TICKETNUM',
2100
-                null,
2101
-                array(),
2102
-                array(),
2103
-                true
2104
-            ),
2105
-            'default_price_row'                        => $this->_get_ticket_price_row(
2106
-                'TICKETNUM',
2107
-                'PRICENUM',
2108
-                null,
2109
-                true,
2110
-                null
2111
-            ),
2112
-            'default_price_rows'                       => '',
2113
-            'default_base_price_amount'                => 0,
2114
-            'default_base_price_name'                  => '',
2115
-            'default_base_price_description'           => '',
2116
-            'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2117
-                'TICKETNUM',
2118
-                'PRICENUM',
2119
-                null,
2120
-                true
2121
-            ),
2122
-            'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2123
-                'DTTNUM',
2124
-                null,
2125
-                array(),
2126
-                array(),
2127
-                true
2128
-            ),
2129
-            'existing_available_datetime_tickets_list' => '',
2130
-            'existing_available_ticket_datetimes_list' => '',
2131
-            'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2132
-                'DTTNUM',
2133
-                'TICKETNUM',
2134
-                null,
2135
-                null,
2136
-                array(),
2137
-                true
2138
-            ),
2139
-            'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2140
-                'DTTNUM',
2141
-                'TICKETNUM',
2142
-                null,
2143
-                null,
2144
-                array(),
2145
-                true
2146
-            ),
2147
-        );
2148
-        $ticket_row = 1;
2149
-        foreach ($all_tickets as $ticket) {
2150
-            $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2151
-                'DTTNUM',
2152
-                $ticket_row,
2153
-                null,
2154
-                $ticket,
2155
-                array(),
2156
-                true
2157
-            );
2158
-            $ticket_row++;
2159
-        }
2160
-        $datetime_row = 1;
2161
-        foreach ($all_datetimes as $datetime) {
2162
-            $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2163
-                $datetime_row,
2164
-                'TICKETNUM',
2165
-                $datetime,
2166
-                null,
2167
-                array(),
2168
-                true
2169
-            );
2170
-            $datetime_row++;
2171
-        }
2172
-        /** @var EEM_Price $price_model */
2173
-        $price_model = EE_Registry::instance()->load_model('Price');
2174
-        $default_prices = $price_model->get_all_default_prices();
2175
-        $price_row = 1;
2176
-        foreach ($default_prices as $price) {
2177
-            if (! $price instanceof EE_Price) {
2178
-                continue;
2179
-            }
2180
-            if ($price->is_base_price()) {
2181
-                $template_args['default_base_price_amount'] = $price->get_pretty(
2182
-                    'PRC_amount',
2183
-                    'localized_float'
2184
-                );
2185
-                $template_args['default_base_price_name'] = $price->get('PRC_name');
2186
-                $template_args['default_base_price_description'] = $price->get('PRC_desc');
2187
-                $price_row++;
2188
-                continue;
2189
-            }
2190
-            $show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2191
-                             || count($default_prices) === 1);
2192
-            $show_create = ! (count($default_prices) > 1
2193
-                              && count($default_prices)
2194
-                                 !== $price_row);
2195
-            $template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2196
-                'TICKETNUM',
2197
-                $price_row,
2198
-                $price,
2199
-                true,
2200
-                null,
2201
-                $show_trash,
2202
-                $show_create
2203
-            );
2204
-            $price_row++;
2205
-        }
2206
-        $template_args = apply_filters(
2207
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2208
-            $template_args,
2209
-            $all_datetimes,
2210
-            $all_tickets,
2211
-            $this->_is_creating_event
2212
-        );
2213
-        return EEH_Template::display_template(
2214
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2215
-            $template_args,
2216
-            true
2217
-        );
2218
-    }
2078
+	/**
2079
+	 * @param array $all_datetimes
2080
+	 * @param array $all_tickets
2081
+	 * @return mixed
2082
+	 * @throws ReflectionException
2083
+	 * @throws InvalidArgumentException
2084
+	 * @throws InvalidInterfaceException
2085
+	 * @throws InvalidDataTypeException
2086
+	 * @throws DomainException
2087
+	 * @throws EE_Error
2088
+	 */
2089
+	protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2090
+	{
2091
+		$template_args = array(
2092
+			'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2093
+				'DTTNUM',
2094
+				null,
2095
+				true,
2096
+				$all_datetimes
2097
+			),
2098
+			'default_ticket_row'                       => $this->_get_ticket_row(
2099
+				'TICKETNUM',
2100
+				null,
2101
+				array(),
2102
+				array(),
2103
+				true
2104
+			),
2105
+			'default_price_row'                        => $this->_get_ticket_price_row(
2106
+				'TICKETNUM',
2107
+				'PRICENUM',
2108
+				null,
2109
+				true,
2110
+				null
2111
+			),
2112
+			'default_price_rows'                       => '',
2113
+			'default_base_price_amount'                => 0,
2114
+			'default_base_price_name'                  => '',
2115
+			'default_base_price_description'           => '',
2116
+			'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2117
+				'TICKETNUM',
2118
+				'PRICENUM',
2119
+				null,
2120
+				true
2121
+			),
2122
+			'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2123
+				'DTTNUM',
2124
+				null,
2125
+				array(),
2126
+				array(),
2127
+				true
2128
+			),
2129
+			'existing_available_datetime_tickets_list' => '',
2130
+			'existing_available_ticket_datetimes_list' => '',
2131
+			'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2132
+				'DTTNUM',
2133
+				'TICKETNUM',
2134
+				null,
2135
+				null,
2136
+				array(),
2137
+				true
2138
+			),
2139
+			'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2140
+				'DTTNUM',
2141
+				'TICKETNUM',
2142
+				null,
2143
+				null,
2144
+				array(),
2145
+				true
2146
+			),
2147
+		);
2148
+		$ticket_row = 1;
2149
+		foreach ($all_tickets as $ticket) {
2150
+			$template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2151
+				'DTTNUM',
2152
+				$ticket_row,
2153
+				null,
2154
+				$ticket,
2155
+				array(),
2156
+				true
2157
+			);
2158
+			$ticket_row++;
2159
+		}
2160
+		$datetime_row = 1;
2161
+		foreach ($all_datetimes as $datetime) {
2162
+			$template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2163
+				$datetime_row,
2164
+				'TICKETNUM',
2165
+				$datetime,
2166
+				null,
2167
+				array(),
2168
+				true
2169
+			);
2170
+			$datetime_row++;
2171
+		}
2172
+		/** @var EEM_Price $price_model */
2173
+		$price_model = EE_Registry::instance()->load_model('Price');
2174
+		$default_prices = $price_model->get_all_default_prices();
2175
+		$price_row = 1;
2176
+		foreach ($default_prices as $price) {
2177
+			if (! $price instanceof EE_Price) {
2178
+				continue;
2179
+			}
2180
+			if ($price->is_base_price()) {
2181
+				$template_args['default_base_price_amount'] = $price->get_pretty(
2182
+					'PRC_amount',
2183
+					'localized_float'
2184
+				);
2185
+				$template_args['default_base_price_name'] = $price->get('PRC_name');
2186
+				$template_args['default_base_price_description'] = $price->get('PRC_desc');
2187
+				$price_row++;
2188
+				continue;
2189
+			}
2190
+			$show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2191
+							 || count($default_prices) === 1);
2192
+			$show_create = ! (count($default_prices) > 1
2193
+							  && count($default_prices)
2194
+								 !== $price_row);
2195
+			$template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2196
+				'TICKETNUM',
2197
+				$price_row,
2198
+				$price,
2199
+				true,
2200
+				null,
2201
+				$show_trash,
2202
+				$show_create
2203
+			);
2204
+			$price_row++;
2205
+		}
2206
+		$template_args = apply_filters(
2207
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2208
+			$template_args,
2209
+			$all_datetimes,
2210
+			$all_tickets,
2211
+			$this->_is_creating_event
2212
+		);
2213
+		return EEH_Template::display_template(
2214
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2215
+			$template_args,
2216
+			true
2217
+		);
2218
+	}
2219 2219
 }
Please login to merge, or discard this patch.
Spacing   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
             );
154 154
             $msg .= '</p><ul>';
155 155
             foreach ($format_validation as $error) {
156
-                $msg .= '<li>' . $error . '</li>';
156
+                $msg .= '<li>'.$error.'</li>';
157 157
             }
158 158
             $msg .= '</ul><p>';
159 159
             $msg .= sprintf(
@@ -182,11 +182,11 @@  discard block
 block discarded – undo
182 182
         $this->_scripts_styles = array(
183 183
             'registers'   => array(
184 184
                 'ee-tickets-datetimes-css' => array(
185
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
185
+                    'url'  => PRICING_ASSETS_URL.'event-tickets-datetimes.css',
186 186
                     'type' => 'css',
187 187
                 ),
188 188
                 'ee-dtt-ticket-metabox'    => array(
189
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
189
+                    'url'     => PRICING_ASSETS_URL.'ee-datetime-ticket-metabox.js',
190 190
                     'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
191 191
                 ),
192 192
             ),
@@ -210,9 +210,9 @@  discard block
 block discarded – undo
210 210
                             'event_espresso'
211 211
                         ),
212 212
                         'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
213
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
213
+                                                     . esc_html__('Cancel', 'event_espresso').'</button>',
214 214
                         'close_button'            => '<button class="button-secondary ee-modal-cancel">'
215
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
215
+                                                     . esc_html__('Close', 'event_espresso').'</button>',
216 216
                         'single_warning_from_tkt' => esc_html__(
217 217
                             '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.',
218 218
                             'event_espresso'
@@ -222,7 +222,7 @@  discard block
 block discarded – undo
222 222
                             'event_espresso'
223 223
                         ),
224 224
                         'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
225
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
225
+                                                     . esc_html__('Dismiss', 'event_espresso').'</button>',
226 226
                     ),
227 227
                     'DTT_ERROR_MSG'         => array(
228 228
                         'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
         foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
315 315
             // trim all values to ensure any excess whitespace is removed.
316 316
             $datetime_data = array_map(
317
-                function ($datetime_data) {
317
+                function($datetime_data) {
318 318
                     return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
319 319
                 },
320 320
                 $datetime_data
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
             );
345 345
             // if we have an id then let's get existing object first and then set the new values.
346 346
             // Otherwise we instantiate a new object for save.
347
-            if (! empty($datetime_data['DTT_ID'])) {
347
+            if ( ! empty($datetime_data['DTT_ID'])) {
348 348
                 $datetime = EE_Registry::instance()
349 349
                                        ->load_model('Datetime', array($timezone))
350 350
                                        ->get_one_by_ID($datetime_data['DTT_ID']);
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
                 // after the add_relation_to() the autosave replaces it.
359 359
                 // We need to do this so we dont' TRASH the parent DTT.
360 360
                 // (save the ID for both key and value to avoid duplications)
361
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
361
+                $saved_dtt_ids[$datetime->ID()] = $datetime->ID();
362 362
             } else {
363 363
                 $datetime = EE_Registry::instance()->load_class(
364 364
                     'Datetime',
@@ -394,8 +394,8 @@  discard block
 block discarded – undo
394 394
             // because it is possible there was a new one created for the autosave.
395 395
             // (save the ID for both key and value to avoid duplications)
396 396
             $DTT_ID = $datetime->ID();
397
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
398
-            $saved_dtt_objs[ $row ] = $datetime;
397
+            $saved_dtt_ids[$DTT_ID] = $DTT_ID;
398
+            $saved_dtt_objs[$row] = $datetime;
399 399
             // @todo if ANY of these updates fail then we want the appropriate global error message.
400 400
         }
401 401
         $event->save();
@@ -460,13 +460,13 @@  discard block
 block discarded – undo
460 460
             $update_prices = $create_new_TKT = false;
461 461
             // figure out what datetimes were added to the ticket
462 462
             // and what datetimes were removed from the ticket in the session.
463
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
464
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
463
+            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][$row]);
464
+            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][$row]);
465 465
             $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
466 466
             $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
467 467
             // trim inputs to ensure any excess whitespace is removed.
468 468
             $tkt = array_map(
469
-                function ($ticket_data) {
469
+                function($ticket_data) {
470 470
                     return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
471 471
                 },
472 472
                 $tkt
@@ -488,8 +488,8 @@  discard block
 block discarded – undo
488 488
             $base_price_id = isset($tkt['TKT_base_price_ID'])
489 489
                 ? $tkt['TKT_base_price_ID']
490 490
                 : 0;
491
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
492
-                ? $data['edit_prices'][ $row ]
491
+            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][$row])
492
+                ? $data['edit_prices'][$row]
493 493
                 : array();
494 494
             $now = null;
495 495
             if (empty($tkt['TKT_start_date'])) {
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
                 /**
502 502
                  * set the TKT_end_date to the first datetime attached to the ticket.
503 503
                  */
504
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
504
+                $first_dtt = $saved_datetimes[reset($tkt_dtt_rows)];
505 505
                 $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
506 506
             }
507 507
             $TKT_values = array(
@@ -636,7 +636,7 @@  discard block
 block discarded – undo
636 636
             // need to make sue that the TKT_price is accurate after saving the prices.
637 637
             $ticket->ensure_TKT_Price_correct();
638 638
             // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
639
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
639
+            if ( ! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
640 640
                 $update_prices = true;
641 641
                 $new_default = clone $ticket;
642 642
                 $new_default->set('TKT_ID', 0);
@@ -681,7 +681,7 @@  discard block
 block discarded – undo
681 681
                 // save new TKT
682 682
                 $new_tkt->save();
683 683
                 // add new ticket to array
684
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
684
+                $saved_tickets[$new_tkt->ID()] = $new_tkt;
685 685
                 do_action(
686 686
                     'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
687 687
                     $new_tkt,
@@ -691,7 +691,7 @@  discard block
 block discarded – undo
691 691
                 );
692 692
             } else {
693 693
                 // add tkt to saved tkts
694
-                $saved_tickets[ $ticket->ID() ] = $ticket;
694
+                $saved_tickets[$ticket->ID()] = $ticket;
695 695
                 do_action(
696 696
                     'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
697 697
                     $ticket,
@@ -758,22 +758,22 @@  discard block
 block discarded – undo
758 758
         // to start we have to add the ticket to all the datetimes its supposed to be with,
759 759
         // and removing the ticket from datetimes it got removed from.
760 760
         // first let's add datetimes
761
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
761
+        if ( ! empty($added_datetimes) && is_array($added_datetimes)) {
762 762
             foreach ($added_datetimes as $row_id) {
763 763
                 $row_id = (int) $row_id;
764
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
765
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
764
+                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
765
+                    $ticket->_add_relation_to($saved_datetimes[$row_id], 'Datetime');
766 766
                 }
767 767
             }
768 768
         }
769 769
         // then remove datetimes
770
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
770
+        if ( ! empty($removed_datetimes) && is_array($removed_datetimes)) {
771 771
             foreach ($removed_datetimes as $row_id) {
772 772
                 $row_id = (int) $row_id;
773 773
                 // its entirely possible that a datetime got deleted (instead of just removed from relationship.
774 774
                 // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
775
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
776
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
775
+                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
776
+                    $ticket->_remove_relation_to($saved_datetimes[$row_id], 'Datetime');
777 777
                 }
778 778
             }
779 779
         }
@@ -885,7 +885,7 @@  discard block
 block discarded – undo
885 885
             );
886 886
         }
887 887
         // possibly need to save tkt
888
-        if (! $ticket->ID()) {
888
+        if ( ! $ticket->ID()) {
889 889
             $ticket->save();
890 890
         }
891 891
         foreach ($prices as $row => $prc) {
@@ -919,17 +919,17 @@  discard block
 block discarded – undo
919 919
                 }
920 920
             }
921 921
             $price->save();
922
-            $updated_prices[ $price->ID() ] = $price;
922
+            $updated_prices[$price->ID()] = $price;
923 923
             $ticket->_add_relation_to($price, 'Price');
924 924
         }
925 925
         // now let's remove any prices that got removed from the ticket
926
-        if (! empty($current_prices_on_ticket)) {
926
+        if ( ! empty($current_prices_on_ticket)) {
927 927
             $current = array_keys($current_prices_on_ticket);
928 928
             $updated = array_keys($updated_prices);
929 929
             $prices_to_remove = array_diff($current, $updated);
930
-            if (! empty($prices_to_remove)) {
930
+            if ( ! empty($prices_to_remove)) {
931 931
                 foreach ($prices_to_remove as $prc_id) {
932
-                    $p = $current_prices_on_ticket[ $prc_id ];
932
+                    $p = $current_prices_on_ticket[$prc_id];
933 933
                     $ticket->_remove_relation_to($p, 'Price');
934 934
                     // delete permanently the price
935 935
                     $p->delete_permanently();
@@ -1080,18 +1080,18 @@  discard block
 block discarded – undo
1080 1080
                 $TKT_ID = $ticket->get('TKT_ID');
1081 1081
                 $ticket_row = $ticket->get('TKT_row');
1082 1082
                 // we only want unique tickets in our final display!!
1083
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1083
+                if ( ! in_array($TKT_ID, $existing_ticket_ids, true)) {
1084 1084
                     $existing_ticket_ids[] = $TKT_ID;
1085 1085
                     $all_tickets[] = $ticket;
1086 1086
                 }
1087 1087
                 // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1088
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1088
+                $datetime_tickets[$DTT_ID][] = $ticket_row;
1089 1089
                 // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1090 1090
                 if (
1091
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1092
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1091
+                    ! isset($ticket_datetimes[$TKT_ID])
1092
+                    || ! in_array($datetime_row, $ticket_datetimes[$TKT_ID], true)
1093 1093
                 ) {
1094
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1094
+                    $ticket_datetimes[$TKT_ID][] = $datetime_row;
1095 1095
                 }
1096 1096
             }
1097 1097
             $datetime_row++;
@@ -1102,7 +1102,7 @@  discard block
 block discarded – undo
1102 1102
         // sort $all_tickets by order
1103 1103
         usort(
1104 1104
             $all_tickets,
1105
-            function (EE_Ticket $a, EE_Ticket $b) {
1105
+            function(EE_Ticket $a, EE_Ticket $b) {
1106 1106
                 $a_order = (int) $a->get('TKT_order');
1107 1107
                 $b_order = (int) $b->get('TKT_order');
1108 1108
                 if ($a_order === $b_order) {
@@ -1143,16 +1143,16 @@  discard block
 block discarded – undo
1143 1143
         $status_change_notice = EventEspresso\core\services\loaders\LoaderFactory::getLoader()->getShared(
1144 1144
             'EventEspresso\core\admin\StatusChangeNotice'
1145 1145
         );
1146
-        if (! $status_change_notice->isDismissed()) {
1146
+        if ( ! $status_change_notice->isDismissed()) {
1147 1147
             $main_template_args['status_change_notice'] = EEH_Template::display_template(
1148
-                EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
1148
+                EE_ADMIN_TEMPLATE.'status_change_notice.template.php',
1149 1149
                 ['context' => '__event-editor', 'page_slug' => 'espresso-events'],
1150 1150
                 true
1151 1151
             );
1152 1152
         }
1153 1153
 
1154 1154
         EEH_Template::display_template(
1155
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1155
+            PRICING_TEMPLATE_PATH.'event_tickets_metabox_main.template.php',
1156 1156
             $main_template_args
1157 1157
         );
1158 1158
     }
@@ -1194,7 +1194,7 @@  discard block
 block discarded – undo
1194 1194
             'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1195 1195
         );
1196 1196
         return EEH_Template::display_template(
1197
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1197
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_row_wrapper.template.php',
1198 1198
             $dtt_display_template_args,
1199 1199
             true
1200 1200
         );
@@ -1263,7 +1263,7 @@  discard block
 block discarded – undo
1263 1263
             $this->_is_creating_event
1264 1264
         );
1265 1265
         return EEH_Template::display_template(
1266
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1266
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_edit_row.template.php',
1267 1267
             $template_args,
1268 1268
             true
1269 1269
         );
@@ -1304,7 +1304,7 @@  discard block
 block discarded – undo
1304 1304
             'DTT_ID'                            => $default ? '' : $datetime->ID(),
1305 1305
         );
1306 1306
         // need to setup the list items (but only if this isn't a default skeleton setup)
1307
-        if (! $default) {
1307
+        if ( ! $default) {
1308 1308
             $ticket_row = 1;
1309 1309
             foreach ($all_tickets as $ticket) {
1310 1310
                 $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
@@ -1330,7 +1330,7 @@  discard block
 block discarded – undo
1330 1330
             $this->_is_creating_event
1331 1331
         );
1332 1332
         return EEH_Template::display_template(
1333
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1333
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_attached_tickets_row.template.php',
1334 1334
             $template_args,
1335 1335
             true
1336 1336
         );
@@ -1356,8 +1356,8 @@  discard block
 block discarded – undo
1356 1356
         $datetime_tickets = array(),
1357 1357
         $default
1358 1358
     ) {
1359
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1360
-            ? $datetime_tickets[ $datetime->ID() ]
1359
+        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[$datetime->ID()])
1360
+            ? $datetime_tickets[$datetime->ID()]
1361 1361
             : array();
1362 1362
         $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1363 1363
         $no_ticket = $default && empty($ticket);
@@ -1378,8 +1378,8 @@  discard block
 block discarded – undo
1378 1378
                 ? 'TKTNAME'
1379 1379
                 : $ticket->get('TKT_name'),
1380 1380
             'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1381
-                ? ' tkt-status-' . EE_Ticket::onsale
1382
-                : ' tkt-status-' . $ticket->ticket_status(),
1381
+                ? ' tkt-status-'.EE_Ticket::onsale
1382
+                : ' tkt-status-'.$ticket->ticket_status(),
1383 1383
         );
1384 1384
         // filter template args
1385 1385
         $template_args = apply_filters(
@@ -1394,7 +1394,7 @@  discard block
 block discarded – undo
1394 1394
             $this->_is_creating_event
1395 1395
         );
1396 1396
         return EEH_Template::display_template(
1397
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1397
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_dtt_tickets_list.template.php',
1398 1398
             $template_args,
1399 1399
             true
1400 1400
         );
@@ -1450,19 +1450,19 @@  discard block
 block discarded – undo
1450 1450
         // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1451 1451
         // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1452 1452
         $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1453
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1454
-            ? $ticket_datetimes[ $ticket->ID() ]
1453
+        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1454
+            ? $ticket_datetimes[$ticket->ID()]
1455 1455
             : array();
1456 1456
         $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1457 1457
         $base_price = $default ? null : $ticket->base_price();
1458 1458
         $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1459 1459
         // breaking out complicated condition for ticket_status
1460 1460
         if ($default) {
1461
-            $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1461
+            $ticket_status_class = ' tkt-status-'.EE_Ticket::onsale;
1462 1462
         } else {
1463 1463
             $ticket_status_class = $ticket->is_default()
1464
-                ? ' tkt-status-' . EE_Ticket::onsale
1465
-                : ' tkt-status-' . $ticket->ticket_status();
1464
+                ? ' tkt-status-'.EE_Ticket::onsale
1465
+                : ' tkt-status-'.$ticket->ticket_status();
1466 1466
         }
1467 1467
         // breaking out complicated condition for TKT_taxable
1468 1468
         if ($default) {
@@ -1554,7 +1554,7 @@  discard block
 block discarded – undo
1554 1554
                 : ' style="display:none;"',
1555 1555
             'show_price_mod_button'         => count($prices) > 1
1556 1556
                                                || ($default && $count_price_mods > 0)
1557
-                                               || (! $default && $ticket->deleted())
1557
+                                               || ( ! $default && $ticket->deleted())
1558 1558
                 ? ' style="display:none;"'
1559 1559
                 : '',
1560 1560
             'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
@@ -1598,7 +1598,7 @@  discard block
 block discarded – undo
1598 1598
                 $this->_date_time_format,
1599 1599
                 current_time('timestamp')
1600 1600
             );
1601
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1601
+            $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale;
1602 1602
         }
1603 1603
         if (empty($template_args['TKT_end_date'])) {
1604 1604
             // get the earliest datetime (if present);
@@ -1608,7 +1608,7 @@  discard block
 block discarded – undo
1608 1608
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1609 1609
                 )
1610 1610
                 : null;
1611
-            if (! empty($earliest_dtt)) {
1611
+            if ( ! empty($earliest_dtt)) {
1612 1612
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1613 1613
                     'DTT_EVT_start',
1614 1614
                     $this->_date_time_format
@@ -1627,10 +1627,10 @@  discard block
 block discarded – undo
1627 1627
                     )
1628 1628
                 );
1629 1629
             }
1630
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1630
+            $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale;
1631 1631
         }
1632 1632
         // generate ticket_datetime items
1633
-        if (! $default) {
1633
+        if ( ! $default) {
1634 1634
             $datetime_row = 1;
1635 1635
             foreach ($all_datetimes as $datetime) {
1636 1636
                 $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
@@ -1646,7 +1646,7 @@  discard block
 block discarded – undo
1646 1646
         }
1647 1647
         $price_row = 1;
1648 1648
         foreach ($prices as $price) {
1649
-            if (! $price instanceof EE_Price) {
1649
+            if ( ! $price instanceof EE_Price) {
1650 1650
                 continue;
1651 1651
             }
1652 1652
             if ($price->is_base_price()) {
@@ -1679,7 +1679,7 @@  discard block
 block discarded – undo
1679 1679
             $this->_is_creating_event
1680 1680
         );
1681 1681
         return EEH_Template::display_template(
1682
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1682
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_row.template.php',
1683 1683
             $template_args,
1684 1684
             true
1685 1685
         );
@@ -1719,7 +1719,7 @@  discard block
 block discarded – undo
1719 1719
                 $this->_is_creating_event
1720 1720
             );
1721 1721
             $tax_rows .= EEH_Template::display_template(
1722
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1722
+                PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_tax_row.template.php',
1723 1723
                 $template_args,
1724 1724
                 true
1725 1725
             );
@@ -1838,7 +1838,7 @@  discard block
 block discarded – undo
1838 1838
             $this->_is_creating_event
1839 1839
         );
1840 1840
         return EEH_Template::display_template(
1841
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1841
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_price_row.template.php',
1842 1842
             $template_args,
1843 1843
             true
1844 1844
         );
@@ -1908,7 +1908,7 @@  discard block
 block discarded – undo
1908 1908
             $this->_is_creating_event
1909 1909
         );
1910 1910
         return EEH_Template::display_template(
1911
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1911
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_type_base.template.php',
1912 1912
             $template_args,
1913 1913
             true
1914 1914
         );
@@ -1938,7 +1938,7 @@  discard block
 block discarded – undo
1938 1938
     ) {
1939 1939
         $select_name = $default && ! $price instanceof EE_Price
1940 1940
             ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1941
-            : 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1941
+            : 'edit_prices['.$ticket_row.']['.$price_row.'][PRT_ID]';
1942 1942
         /** @var EEM_Price_Type $price_type_model */
1943 1943
         $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1944 1944
         $price_types = $price_type_model->get_all(array(
@@ -1956,10 +1956,10 @@  discard block
 block discarded – undo
1956 1956
         $price_option_spans = '';
1957 1957
         // setup price types for selector
1958 1958
         foreach ($price_types as $price_type) {
1959
-            if (! $price_type instanceof EE_Price_Type) {
1959
+            if ( ! $price_type instanceof EE_Price_Type) {
1960 1960
                 continue;
1961 1961
             }
1962
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1962
+            $all_price_types[$price_type->ID()] = $price_type->get('PRT_name');
1963 1963
             // while we're in the loop let's setup the option spans used by js
1964 1964
             $span_args = array(
1965 1965
                 'PRT_ID'         => $price_type->ID(),
@@ -1967,12 +1967,12 @@  discard block
 block discarded – undo
1967 1967
                 'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1968 1968
             );
1969 1969
             $price_option_spans .= EEH_Template::display_template(
1970
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1970
+                PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_option_span.template.php',
1971 1971
                 $span_args,
1972 1972
                 true
1973 1973
             );
1974 1974
         }
1975
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1975
+        $select_name = $disabled ? 'archive_price['.$ticket_row.']['.$price_row.'][PRT_ID]'
1976 1976
             : $select_name;
1977 1977
         $select_input = new EE_Select_Input(
1978 1978
             $all_price_types,
@@ -2009,7 +2009,7 @@  discard block
 block discarded – undo
2009 2009
             $this->_is_creating_event
2010 2010
         );
2011 2011
         return EEH_Template::display_template(
2012
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2012
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_modifier_selector.template.php',
2013 2013
             $template_args,
2014 2014
             true
2015 2015
         );
@@ -2035,8 +2035,8 @@  discard block
 block discarded – undo
2035 2035
         $ticket_datetimes = array(),
2036 2036
         $default
2037 2037
     ) {
2038
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2039
-            ? $ticket_datetimes[ $ticket->ID() ]
2038
+        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
2039
+            ? $ticket_datetimes[$ticket->ID()]
2040 2040
             : array();
2041 2041
         $template_args = array(
2042 2042
             'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
@@ -2068,7 +2068,7 @@  discard block
 block discarded – undo
2068 2068
             $this->_is_creating_event
2069 2069
         );
2070 2070
         return EEH_Template::display_template(
2071
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2071
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2072 2072
             $template_args,
2073 2073
             true
2074 2074
         );
@@ -2174,7 +2174,7 @@  discard block
 block discarded – undo
2174 2174
         $default_prices = $price_model->get_all_default_prices();
2175 2175
         $price_row = 1;
2176 2176
         foreach ($default_prices as $price) {
2177
-            if (! $price instanceof EE_Price) {
2177
+            if ( ! $price instanceof EE_Price) {
2178 2178
                 continue;
2179 2179
             }
2180 2180
             if ($price->is_base_price()) {
@@ -2211,7 +2211,7 @@  discard block
 block discarded – undo
2211 2211
             $this->_is_creating_event
2212 2212
         );
2213 2213
         return EEH_Template::display_template(
2214
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2214
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_js_structure.template.php',
2215 2215
             $template_args,
2216 2216
             true
2217 2217
         );
Please login to merge, or discard this patch.