Completed
Branch FET/update-event-admin-request... (79a891)
by
unknown
06:18 queued 04:30
created
core/db_classes/EE_Ticket.class.php 2 patches
Indentation   +1795 added lines, -1795 removed lines patch added patch discarded remove patch
@@ -14,1803 +14,1803 @@
 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
-     * The following constants are used by the ticket_status() method to indicate whether a ticket is on sale or not.
19
-     */
20
-    const sold_out = 'TKS';
21
-
22
-    /**
23
-     *
24
-     */
25
-    const expired = 'TKE';
26
-
27
-    /**
28
-     *
29
-     */
30
-    const archived = 'TKA';
31
-
32
-    /**
33
-     *
34
-     */
35
-    const pending = 'TKP';
36
-
37
-    /**
38
-     *
39
-     */
40
-    const onsale = 'TKO';
41
-
42
-    /**
43
-     * extra meta key for tracking ticket reservations
44
-     *
45
-     * @type string
46
-     */
47
-    const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
48
-
49
-    /**
50
-     * cached result from method of the same name
51
-     *
52
-     * @var float $_ticket_total_with_taxes
53
-     */
54
-    private $_ticket_total_with_taxes;
55
-
56
-
57
-    /**
58
-     * @param array  $props_n_values          incoming values
59
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
60
-     *                                        used.)
61
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
62
-     *                                        date_format and the second value is the time format
63
-     * @return EE_Ticket
64
-     * @throws EE_Error
65
-     * @throws ReflectionException
66
-     */
67
-    public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
68
-    {
69
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
70
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
71
-    }
72
-
73
-
74
-    /**
75
-     * @param array  $props_n_values  incoming values from the database
76
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
77
-     *                                the website will be used.
78
-     * @return EE_Ticket
79
-     * @throws EE_Error
80
-     * @throws ReflectionException
81
-     */
82
-    public static function new_instance_from_db($props_n_values = [], $timezone = null)
83
-    {
84
-        return new self($props_n_values, true, $timezone);
85
-    }
86
-
87
-
88
-    /**
89
-     * @return bool
90
-     * @throws EE_Error
91
-     * @throws ReflectionException
92
-     */
93
-    public function parent()
94
-    {
95
-        return $this->get('TKT_parent');
96
-    }
97
-
98
-
99
-    /**
100
-     * return if a ticket has quantities available for purchase
101
-     *
102
-     * @param int $DTT_ID the primary key for a particular datetime
103
-     * @return boolean
104
-     * @throws EE_Error
105
-     * @throws ReflectionException
106
-     */
107
-    public function available($DTT_ID = 0)
108
-    {
109
-        // are we checking availability for a particular datetime ?
110
-        if ($DTT_ID) {
111
-            // get that datetime object
112
-            $datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
113
-            // if  ticket sales for this datetime have exceeded the reg limit...
114
-            if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
115
-                return false;
116
-            }
117
-        }
118
-        // datetime is still open for registration, but is this ticket sold out ?
119
-        return $this->qty() < 1 || $this->qty() > $this->sold() ? true : false;
120
-    }
121
-
122
-
123
-    /**
124
-     * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
125
-     *
126
-     * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
127
-     *                               relevant status const
128
-     * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
129
-     *                               further processing
130
-     * @return mixed status int if the display string isn't requested
131
-     * @throws EE_Error
132
-     * @throws ReflectionException
133
-     */
134
-    public function ticket_status($display = false, $remaining = null)
135
-    {
136
-        $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
137
-        if (! $remaining) {
138
-            return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
139
-        }
140
-        if ($this->get('TKT_deleted')) {
141
-            return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
142
-        }
143
-        if ($this->is_expired()) {
144
-            return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
145
-        }
146
-        if ($this->is_pending()) {
147
-            return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
148
-        }
149
-        if ($this->is_on_sale()) {
150
-            return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
151
-        }
152
-        return '';
153
-    }
154
-
155
-
156
-    /**
157
-     * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
158
-     * considering ALL the factors used for figuring that out.
159
-     *
160
-     * @access public
161
-     * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
162
-     * @return boolean         true = tickets remaining, false not.
163
-     * @throws EE_Error
164
-     */
165
-    public function is_remaining($DTT_ID = 0)
166
-    {
167
-        $num_remaining = $this->remaining($DTT_ID);
168
-        if ($num_remaining === 0) {
169
-            return false;
170
-        }
171
-        if ($num_remaining > 0 && $num_remaining < $this->min()) {
172
-            return false;
173
-        }
174
-        return true;
175
-    }
176
-
177
-
178
-    /**
179
-     * return the total number of tickets available for purchase
180
-     *
181
-     * @param int $DTT_ID  the primary key for a particular datetime.
182
-     *                     set to 0 for all related datetimes
183
-     * @return int
184
-     * @throws EE_Error
185
-     */
186
-    public function remaining($DTT_ID = 0)
187
-    {
188
-        return $this->real_quantity_on_ticket('saleable', $DTT_ID);
189
-    }
190
-
191
-
192
-    /**
193
-     * Gets min
194
-     *
195
-     * @return int
196
-     * @throws EE_Error
197
-     * @throws ReflectionException
198
-     */
199
-    public function min()
200
-    {
201
-        return $this->get('TKT_min');
202
-    }
203
-
204
-
205
-    /**
206
-     * return if a ticket is no longer available cause its available dates have expired.
207
-     *
208
-     * @return boolean
209
-     * @throws EE_Error
210
-     * @throws ReflectionException
211
-     */
212
-    public function is_expired()
213
-    {
214
-        return ($this->get_raw('TKT_end_date') < time());
215
-    }
216
-
217
-
218
-    /**
219
-     * Return if a ticket is yet to go on sale or not
220
-     *
221
-     * @return boolean
222
-     * @throws EE_Error
223
-     * @throws ReflectionException
224
-     */
225
-    public function is_pending()
226
-    {
227
-        return ($this->get_raw('TKT_start_date') > time());
228
-    }
229
-
230
-
231
-    /**
232
-     * Return if a ticket is on sale or not
233
-     *
234
-     * @return boolean
235
-     * @throws EE_Error
236
-     * @throws ReflectionException
237
-     */
238
-    public function is_on_sale()
239
-    {
240
-        return ($this->get_raw('TKT_start_date') < time() && $this->get_raw('TKT_end_date') > time());
241
-    }
242
-
243
-
244
-    /**
245
-     * This returns the chronologically last datetime that this ticket is associated with
246
-     *
247
-     * @param string $dt_frmt
248
-     * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
249
-     *                            the end date ie: Jan 01 "to" Dec 31
250
-     * @return string
251
-     * @throws EE_Error
252
-     * @throws ReflectionException
253
-     */
254
-    public function date_range($dt_frmt = '', $conjunction = ' - ')
255
-    {
256
-        $dt_frmt    = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
257
-        $first_date = $this->first_datetime() instanceof EE_Datetime
258
-            ? $this->first_datetime()->get_i18n_datetime(
259
-                'DTT_EVT_start',
260
-                $dt_frmt
261
-            ) : '';
262
-        $last_date  =
263
-            $this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->get_i18n_datetime(
264
-                'DTT_EVT_end',
265
-                $dt_frmt
266
-            ) : '';
267
-
268
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
269
-    }
270
-
271
-
272
-    /**
273
-     * This returns the chronologically first datetime that this ticket is associated with
274
-     *
275
-     * @return EE_Datetime
276
-     * @throws EE_Error
277
-     */
278
-    public function first_datetime()
279
-    {
280
-        $datetimes = $this->datetimes(['limit' => 1]);
281
-        return reset($datetimes);
282
-    }
283
-
284
-
285
-    /**
286
-     * Gets all the datetimes this ticket can be used for attending.
287
-     * Unless otherwise specified, orders datetimes by start date.
288
-     *
289
-     * @param array $query_params @see
290
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
291
-     * @return EE_Datetime[]|EE_Base_Class[]
292
-     * @throws EE_Error
293
-     * @throws ReflectionException
294
-     */
295
-    public function datetimes($query_params = [])
296
-    {
297
-        if (! isset($query_params['order_by'])) {
298
-            $query_params['order_by']['DTT_order'] = 'ASC';
299
-        }
300
-        return $this->get_many_related('Datetime', $query_params);
301
-    }
302
-
303
-
304
-    /**
305
-     * This returns the chronologically last datetime that this ticket is associated with
306
-     *
307
-     * @return EE_Datetime
308
-     * @throws EE_Error
309
-     */
310
-    public function last_datetime()
311
-    {
312
-        $datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
313
-        return end($datetimes);
314
-    }
315
-
316
-
317
-    /**
318
-     * This returns the total tickets sold depending on the given parameters.
319
-     *
320
-     * @param string $what    Can be one of two options: 'ticket', 'datetime'.
321
-     *                        'ticket' = total ticket sales for all datetimes this ticket is related to
322
-     *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
323
-     *                        'datetime' = total ticket sales in the datetime_ticket table.
324
-     *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
325
-     *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
326
-     * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
327
-     * @return mixed (array|int)          how many tickets have sold
328
-     * @throws EE_Error
329
-     */
330
-    public function tickets_sold($what = 'ticket', $dtt_id = null)
331
-    {
332
-        $total        = 0;
333
-        $tickets_sold = $this->_all_tickets_sold();
334
-        switch ($what) {
335
-            case 'ticket':
336
-                return $tickets_sold['ticket'];
337
-                break;
338
-            case 'datetime':
339
-                if (empty($tickets_sold['datetime'])) {
340
-                    return $total;
341
-                }
342
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
343
-                    EE_Error::add_error(
344
-                        esc_html__(
345
-                            '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?',
346
-                            'event_espresso'
347
-                        ),
348
-                        __FILE__,
349
-                        __FUNCTION__,
350
-                        __LINE__
351
-                    );
352
-                    return $total;
353
-                }
354
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
355
-                break;
356
-            default:
357
-                return $total;
358
-        }
359
-    }
360
-
361
-
362
-    /**
363
-     * This returns an array indexed by datetime_id for tickets sold with this ticket.
364
-     *
365
-     * @return EE_Ticket[]
366
-     * @throws EE_Error
367
-     * @throws ReflectionException
368
-     */
369
-    protected function _all_tickets_sold()
370
-    {
371
-        $datetimes    = $this->get_many_related('Datetime');
372
-        $tickets_sold = [];
373
-        if (! empty($datetimes)) {
374
-            foreach ($datetimes as $datetime) {
375
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
376
-            }
377
-        }
378
-        // Tickets sold
379
-        $tickets_sold['ticket'] = $this->sold();
380
-        return $tickets_sold;
381
-    }
382
-
383
-
384
-    /**
385
-     * This returns the base price object for the ticket.
386
-     *
387
-     * @param bool $return_array whether to return as an array indexed by price id or just the object.
388
-     * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
389
-     * @throws EE_Error
390
-     * @throws ReflectionException
391
-     */
392
-    public function base_price($return_array = false)
393
-    {
394
-        $_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
395
-        return $return_array
396
-            ? $this->get_many_related('Price', [$_where])
397
-            : $this->get_first_related('Price', [$_where]);
398
-    }
399
-
400
-
401
-    /**
402
-     * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
403
-     *
404
-     * @access public
405
-     * @return EE_Price[]
406
-     * @throws EE_Error
407
-     */
408
-    public function price_modifiers()
409
-    {
410
-        $query_params = [
411
-            0 => [
412
-                'Price_Type.PBT_ID' => [
413
-                    'NOT IN',
414
-                    [EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
415
-                ],
416
-            ],
417
-        ];
418
-        return $this->prices($query_params);
419
-    }
420
-
421
-
422
-    /**
423
-     * Gets all the prices that combine to form the final price of this ticket
424
-     *
425
-     * @param array $query_params @see
426
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
427
-     * @return EE_Price[]|EE_Base_Class[]
428
-     * @throws EE_Error
429
-     * @throws ReflectionException
430
-     */
431
-    public function prices($query_params = [])
432
-    {
433
-        return $this->get_many_related('Price', $query_params);
434
-    }
435
-
436
-
437
-    /**
438
-     * Gets all the ticket applicabilities (ie, relations between datetimes and tickets)
439
-     *
440
-     * @param array $query_params @see
441
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
442
-     * @return EE_Datetime_Ticket|EE_Base_Class[]
443
-     * @throws EE_Error
444
-     * @throws ReflectionException
445
-     */
446
-    public function datetime_tickets($query_params = [])
447
-    {
448
-        return $this->get_many_related('Datetime_Ticket', $query_params);
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets all the datetimes from the db ordered by DTT_order
454
-     *
455
-     * @param boolean $show_expired
456
-     * @param boolean $show_deleted
457
-     * @return EE_Datetime[]
458
-     * @throws EE_Error
459
-     */
460
-    public function datetimes_ordered($show_expired = true, $show_deleted = false)
461
-    {
462
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
463
-            $this->ID(),
464
-            $show_expired,
465
-            $show_deleted
466
-        );
467
-    }
468
-
469
-
470
-    /**
471
-     * Gets ID
472
-     *
473
-     * @return int
474
-     * @throws EE_Error
475
-     * @throws ReflectionException
476
-     */
477
-    public function ID()
478
-    {
479
-        return (int) $this->get('TKT_ID');
480
-    }
481
-
482
-
483
-    /**
484
-     * get the author of the ticket.
485
-     *
486
-     * @return int
487
-     * @throws EE_Error
488
-     * @throws ReflectionException
489
-     * @since 4.5.0
490
-     */
491
-    public function wp_user()
492
-    {
493
-        return $this->get('TKT_wp_user');
494
-    }
495
-
496
-
497
-    /**
498
-     * Gets the template for the ticket
499
-     *
500
-     * @return EE_Ticket_Template|EE_Base_Class
501
-     * @throws EE_Error
502
-     * @throws ReflectionException
503
-     */
504
-    public function template()
505
-    {
506
-        return $this->get_first_related('Ticket_Template');
507
-    }
508
-
509
-
510
-    /**
511
-     * Simply returns an array of EE_Price objects that are taxes.
512
-     *
513
-     * @return EE_Price[]
514
-     * @throws EE_Error
515
-     */
516
-    public function get_ticket_taxes_for_admin()
517
-    {
518
-        return EE_Taxes::get_taxes_for_admin();
519
-    }
520
-
521
-
522
-    /**
523
-     * @return float
524
-     * @throws EE_Error
525
-     * @throws ReflectionException
526
-     */
527
-    public function ticket_price()
528
-    {
529
-        return $this->get('TKT_price');
530
-    }
531
-
532
-
533
-    /**
534
-     * @return mixed
535
-     * @throws EE_Error
536
-     * @throws ReflectionException
537
-     */
538
-    public function pretty_price()
539
-    {
540
-        return $this->get_pretty('TKT_price');
541
-    }
542
-
543
-
544
-    /**
545
-     * @return bool
546
-     * @throws EE_Error
547
-     */
548
-    public function is_free()
549
-    {
550
-        return $this->get_ticket_total_with_taxes() === (float) 0;
551
-    }
552
-
553
-
554
-    /**
555
-     * get_ticket_total_with_taxes
556
-     *
557
-     * @param bool $no_cache
558
-     * @return float
559
-     * @throws EE_Error
560
-     */
561
-    public function get_ticket_total_with_taxes($no_cache = false)
562
-    {
563
-        if ($this->_ticket_total_with_taxes === null || $no_cache) {
564
-            $this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
565
-        }
566
-        return (float) $this->_ticket_total_with_taxes;
567
-    }
568
-
569
-
570
-    public function ensure_TKT_Price_correct()
571
-    {
572
-        $this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
573
-        $this->save();
574
-    }
575
-
576
-
577
-    /**
578
-     * @return float
579
-     * @throws EE_Error
580
-     */
581
-    public function get_ticket_subtotal()
582
-    {
583
-        return EE_Taxes::get_subtotal_for_admin($this);
584
-    }
585
-
586
-
587
-    /**
588
-     * Returns the total taxes applied to this ticket
589
-     *
590
-     * @return float
591
-     * @throws EE_Error
592
-     */
593
-    public function get_ticket_taxes_total_for_admin()
594
-    {
595
-        return EE_Taxes::get_total_taxes_for_admin($this);
596
-    }
597
-
598
-
599
-    /**
600
-     * Sets name
601
-     *
602
-     * @param string $name
603
-     * @throws EE_Error
604
-     * @throws ReflectionException
605
-     */
606
-    public function set_name($name)
607
-    {
608
-        $this->set('TKT_name', $name);
609
-    }
610
-
611
-
612
-    /**
613
-     * Gets description
614
-     *
615
-     * @return string
616
-     * @throws EE_Error
617
-     * @throws ReflectionException
618
-     */
619
-    public function description()
620
-    {
621
-        return $this->get('TKT_description');
622
-    }
623
-
624
-
625
-    /**
626
-     * Sets description
627
-     *
628
-     * @param string $description
629
-     * @throws EE_Error
630
-     * @throws ReflectionException
631
-     */
632
-    public function set_description($description)
633
-    {
634
-        $this->set('TKT_description', $description);
635
-    }
636
-
637
-
638
-    /**
639
-     * Gets start_date
640
-     *
641
-     * @param string $dt_frmt
642
-     * @param string $tm_frmt
643
-     * @return string
644
-     * @throws EE_Error
645
-     * @throws ReflectionException
646
-     */
647
-    public function start_date($dt_frmt = '', $tm_frmt = '')
648
-    {
649
-        return $this->_get_datetime('TKT_start_date', $dt_frmt, $tm_frmt);
650
-    }
651
-
652
-
653
-    /**
654
-     * Sets start_date
655
-     *
656
-     * @param string $start_date
657
-     * @return void
658
-     * @throws EE_Error
659
-     * @throws ReflectionException
660
-     */
661
-    public function set_start_date($start_date)
662
-    {
663
-        $this->_set_date_time('B', $start_date, 'TKT_start_date');
664
-    }
665
-
666
-
667
-    /**
668
-     * Gets end_date
669
-     *
670
-     * @param string $dt_frmt
671
-     * @param string $tm_frmt
672
-     * @return string
673
-     * @throws EE_Error
674
-     * @throws ReflectionException
675
-     */
676
-    public function end_date($dt_frmt = '', $tm_frmt = '')
677
-    {
678
-        return $this->_get_datetime('TKT_end_date', $dt_frmt, $tm_frmt);
679
-    }
680
-
681
-
682
-    /**
683
-     * Sets end_date
684
-     *
685
-     * @param string $end_date
686
-     * @return void
687
-     * @throws EE_Error
688
-     * @throws ReflectionException
689
-     */
690
-    public function set_end_date($end_date)
691
-    {
692
-        $this->_set_date_time('B', $end_date, 'TKT_end_date');
693
-    }
694
-
695
-
696
-    /**
697
-     * Sets sell until time
698
-     *
699
-     * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
700
-     * @throws EE_Error*@throws ReflectionException
701
-     * @since 4.5.0
702
-     */
703
-    public function set_end_time($time)
704
-    {
705
-        $this->_set_time_for($time, 'TKT_end_date');
706
-    }
707
-
708
-
709
-    /**
710
-     * Sets min
711
-     *
712
-     * @param int $min
713
-     * @return void
714
-     * @throws EE_Error
715
-     * @throws ReflectionException
716
-     */
717
-    public function set_min($min)
718
-    {
719
-        $this->set('TKT_min', $min);
720
-    }
721
-
722
-
723
-    /**
724
-     * Gets max
725
-     *
726
-     * @return int
727
-     * @throws EE_Error
728
-     * @throws ReflectionException
729
-     */
730
-    public function max()
731
-    {
732
-        return $this->get('TKT_max');
733
-    }
734
-
735
-
736
-    /**
737
-     * Sets max
738
-     *
739
-     * @param int $max
740
-     * @return void
741
-     * @throws EE_Error
742
-     * @throws ReflectionException
743
-     */
744
-    public function set_max($max)
745
-    {
746
-        $this->set('TKT_max', $max);
747
-    }
748
-
749
-
750
-    /**
751
-     * Sets price
752
-     *
753
-     * @param float $price
754
-     * @return void
755
-     * @throws EE_Error
756
-     * @throws ReflectionException
757
-     */
758
-    public function set_price($price)
759
-    {
760
-        $this->set('TKT_price', $price);
761
-    }
762
-
763
-
764
-    /**
765
-     * Gets sold
766
-     *
767
-     * @return int
768
-     * @throws EE_Error
769
-     * @throws ReflectionException
770
-     */
771
-    public function sold()
772
-    {
773
-        return $this->get_raw('TKT_sold');
774
-    }
775
-
776
-
777
-    /**
778
-     * Sets sold
779
-     *
780
-     * @param int $sold
781
-     * @return void
782
-     * @throws EE_Error
783
-     * @throws ReflectionException
784
-     */
785
-    public function set_sold($sold)
786
-    {
787
-        // sold can not go below zero
788
-        $sold = max(0, $sold);
789
-        $this->set('TKT_sold', $sold);
790
-    }
791
-
792
-
793
-    /**
794
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
795
-     * associated datetimes.
796
-     *
797
-     * @param int $qty
798
-     * @return boolean
799
-     * @throws EE_Error
800
-     * @throws InvalidArgumentException
801
-     * @throws InvalidDataTypeException
802
-     * @throws InvalidInterfaceException
803
-     * @throws ReflectionException
804
-     * @since 4.9.80.p
805
-     */
806
-    public function increaseSold($qty = 1)
807
-    {
808
-        $qty = absint($qty);
809
-        // increment sold and decrement reserved datetime quantities simultaneously
810
-        // don't worry about failures, because they must have already had a spot reserved
811
-        $this->increaseSoldForDatetimes($qty);
812
-        // Increment and decrement ticket quantities simultaneously
813
-        $success = $this->adjustNumericFieldsInDb(
814
-            [
815
-                'TKT_reserved' => $qty * -1,
816
-                'TKT_sold'     => $qty,
817
-            ]
818
-        );
819
-        do_action(
820
-            'AHEE__EE_Ticket__increase_sold',
821
-            $this,
822
-            $qty,
823
-            $this->sold(),
824
-            $success
825
-        );
826
-        return $success;
827
-    }
828
-
829
-
830
-    /**
831
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
832
-     *
833
-     * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
834
-     *                           counts), Negative means to decreases old counts (and increase reserved counts).
835
-     * @param EE_Datetime[] $datetimes
836
-     * @throws EE_Error
837
-     * @throws InvalidArgumentException
838
-     * @throws InvalidDataTypeException
839
-     * @throws InvalidInterfaceException
840
-     * @throws ReflectionException
841
-     * @since 4.9.80.p
842
-     */
843
-    protected function increaseSoldForDatetimes($qty, array $datetimes = [])
844
-    {
845
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
846
-        foreach ($datetimes as $datetime) {
847
-            $datetime->increaseSold($qty);
848
-        }
849
-    }
850
-
851
-
852
-    /**
853
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
854
-     * DB and then updates the model objects.
855
-     * Does not affect the reserved counts.
856
-     *
857
-     * @param int $qty
858
-     * @return boolean
859
-     * @throws EE_Error
860
-     * @throws InvalidArgumentException
861
-     * @throws InvalidDataTypeException
862
-     * @throws InvalidInterfaceException
863
-     * @throws ReflectionException
864
-     * @since 4.9.80.p
865
-     */
866
-    public function decreaseSold($qty = 1)
867
-    {
868
-        $qty = absint($qty);
869
-        $this->decreaseSoldForDatetimes($qty);
870
-        $success = $this->adjustNumericFieldsInDb(
871
-            [
872
-                'TKT_sold' => $qty * -1,
873
-            ]
874
-        );
875
-        do_action(
876
-            'AHEE__EE_Ticket__decrease_sold',
877
-            $this,
878
-            $qty,
879
-            $this->sold(),
880
-            $success
881
-        );
882
-        return $success;
883
-    }
884
-
885
-
886
-    /**
887
-     * Decreases sold on related datetimes
888
-     *
889
-     * @param int           $qty
890
-     * @param EE_Datetime[] $datetimes
891
-     * @return void
892
-     * @throws EE_Error
893
-     * @throws InvalidArgumentException
894
-     * @throws InvalidDataTypeException
895
-     * @throws InvalidInterfaceException
896
-     * @throws ReflectionException
897
-     * @since 4.9.80.p
898
-     */
899
-    protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
900
-    {
901
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
902
-        if (is_array($datetimes)) {
903
-            foreach ($datetimes as $datetime) {
904
-                if ($datetime instanceof EE_Datetime) {
905
-                    $datetime->decreaseSold($qty);
906
-                }
907
-            }
908
-        }
909
-    }
910
-
911
-
912
-    /**
913
-     * Gets qty of reserved tickets
914
-     *
915
-     * @return int
916
-     * @throws EE_Error
917
-     * @throws ReflectionException
918
-     */
919
-    public function reserved()
920
-    {
921
-        return $this->get_raw('TKT_reserved');
922
-    }
923
-
924
-
925
-    /**
926
-     * Sets reserved
927
-     *
928
-     * @param int $reserved
929
-     * @return void
930
-     * @throws EE_Error
931
-     * @throws ReflectionException
932
-     */
933
-    public function set_reserved($reserved)
934
-    {
935
-        // reserved can not go below zero
936
-        $reserved = max(0, (int) $reserved);
937
-        $this->set('TKT_reserved', $reserved);
938
-    }
939
-
940
-
941
-    /**
942
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
943
-     *
944
-     * @param int    $qty
945
-     * @param string $source
946
-     * @return bool whether we successfully reserved the ticket or not.
947
-     * @throws EE_Error
948
-     * @throws InvalidArgumentException
949
-     * @throws ReflectionException
950
-     * @throws InvalidDataTypeException
951
-     * @throws InvalidInterfaceException
952
-     * @since 4.9.80.p
953
-     */
954
-    public function increaseReserved($qty = 1, $source = 'unknown')
955
-    {
956
-        $qty = absint($qty);
957
-        do_action(
958
-            'AHEE__EE_Ticket__increase_reserved__begin',
959
-            $this,
960
-            $qty,
961
-            $source
962
-        );
963
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
964
-        $success                         = false;
965
-        $datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
966
-        if ($datetimes_adjusted_successfully) {
967
-            $success = $this->incrementFieldConditionallyInDb(
968
-                'TKT_reserved',
969
-                'TKT_sold',
970
-                'TKT_qty',
971
-                $qty
972
-            );
973
-            if (! $success) {
974
-                // The datetimes were successfully bumped, but not the
975
-                // ticket. So we need to manually rollback the datetimes.
976
-                $this->decreaseReservedForDatetimes($qty);
977
-            }
978
-        }
979
-        do_action(
980
-            'AHEE__EE_Ticket__increase_reserved',
981
-            $this,
982
-            $qty,
983
-            $this->reserved(),
984
-            $success
985
-        );
986
-        return $success;
987
-    }
988
-
989
-
990
-    /**
991
-     * Increases reserved counts on related datetimes
992
-     *
993
-     * @param int           $qty
994
-     * @param EE_Datetime[] $datetimes
995
-     * @return boolean indicating success
996
-     * @throws EE_Error
997
-     * @throws InvalidArgumentException
998
-     * @throws InvalidDataTypeException
999
-     * @throws InvalidInterfaceException
1000
-     * @throws ReflectionException
1001
-     * @since 4.9.80.p
1002
-     */
1003
-    protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1004
-    {
1005
-        $datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1006
-        $datetimes_updated = [];
1007
-        $limit_exceeded    = false;
1008
-        if (is_array($datetimes)) {
1009
-            foreach ($datetimes as $datetime) {
1010
-                if ($datetime instanceof EE_Datetime) {
1011
-                    if ($datetime->increaseReserved($qty)) {
1012
-                        $datetimes_updated[] = $datetime;
1013
-                    } else {
1014
-                        $limit_exceeded = true;
1015
-                        break;
1016
-                    }
1017
-                }
1018
-            }
1019
-            // If somewhere along the way we detected a datetime whose
1020
-            // limit was exceeded, do a manual rollback.
1021
-            if ($limit_exceeded) {
1022
-                $this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1023
-                return false;
1024
-            }
1025
-        }
1026
-        return true;
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1032
-     *
1033
-     * @param int    $qty
1034
-     * @param bool   $adjust_datetimes
1035
-     * @param string $source
1036
-     * @return boolean
1037
-     * @throws EE_Error
1038
-     * @throws InvalidArgumentException
1039
-     * @throws ReflectionException
1040
-     * @throws InvalidDataTypeException
1041
-     * @throws InvalidInterfaceException
1042
-     * @since 4.9.80.p
1043
-     */
1044
-    public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1045
-    {
1046
-        $qty = absint($qty);
1047
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1048
-        if ($adjust_datetimes) {
1049
-            $this->decreaseReservedForDatetimes($qty);
1050
-        }
1051
-        $success = $this->adjustNumericFieldsInDb(
1052
-            [
1053
-                'TKT_reserved' => $qty * -1,
1054
-            ]
1055
-        );
1056
-        do_action(
1057
-            'AHEE__EE_Ticket__decrease_reserved',
1058
-            $this,
1059
-            $qty,
1060
-            $this->reserved(),
1061
-            $success
1062
-        );
1063
-        return $success;
1064
-    }
1065
-
1066
-
1067
-    /**
1068
-     * Decreases the reserved count on the specified datetimes.
1069
-     *
1070
-     * @param int           $qty
1071
-     * @param EE_Datetime[] $datetimes
1072
-     * @throws EE_Error
1073
-     * @throws InvalidArgumentException
1074
-     * @throws ReflectionException
1075
-     * @throws InvalidDataTypeException
1076
-     * @throws InvalidInterfaceException
1077
-     * @since 4.9.80.p
1078
-     */
1079
-    protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1080
-    {
1081
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1082
-        foreach ($datetimes as $datetime) {
1083
-            if ($datetime instanceof EE_Datetime) {
1084
-                $datetime->decreaseReserved($qty);
1085
-            }
1086
-        }
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * Gets ticket quantity
1092
-     *
1093
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1094
-     *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1095
-     *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1096
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1097
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1098
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1099
-     * @return int
1100
-     * @throws EE_Error
1101
-     * @throws ReflectionException
1102
-     */
1103
-    public function qty($context = '')
1104
-    {
1105
-        switch ($context) {
1106
-            case 'reg_limit':
1107
-                return $this->real_quantity_on_ticket();
1108
-            case 'saleable':
1109
-                return $this->real_quantity_on_ticket('saleable');
1110
-            default:
1111
-                return $this->get_raw('TKT_qty');
1112
-        }
1113
-    }
1114
-
1115
-
1116
-    /**
1117
-     * Gets ticket quantity
1118
-     *
1119
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1120
-     *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1121
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1122
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1123
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1124
-     * @param int    $DTT_ID      the primary key for a particular datetime.
1125
-     *                            set to 0 for all related datetimes
1126
-     * @return int
1127
-     * @throws EE_Error
1128
-     * @throws ReflectionException
1129
-     */
1130
-    public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1131
-    {
1132
-        $raw = $this->get_raw('TKT_qty');
1133
-        // return immediately if it's zero
1134
-        if ($raw === 0) {
1135
-            return $raw;
1136
-        }
1137
-        // echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1138
-        // ensure qty doesn't exceed raw value for THIS ticket
1139
-        $qty = min(EE_INF, $raw);
1140
-        // echo "\n . qty: " . $qty . '<br />';
1141
-        // calculate this ticket's total sales and reservations
1142
-        $sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1143
-        // echo "\n . sold: " . $this->sold() . '<br />';
1144
-        // echo "\n . reserved: " . $this->reserved() . '<br />';
1145
-        // echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1146
-        // first we need to calculate the maximum number of tickets available for the datetime
1147
-        // do we want data for one datetime or all of them ?
1148
-        $query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1149
-        $datetimes    = $this->datetimes($query_params);
1150
-        if (is_array($datetimes) && ! empty($datetimes)) {
1151
-            foreach ($datetimes as $datetime) {
1152
-                if ($datetime instanceof EE_Datetime) {
1153
-                    $datetime->refresh_from_db();
1154
-                    // echo "\n . . datetime name: " . $datetime->name() . '<br />';
1155
-                    // echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1156
-                    // initialize with no restrictions for each datetime
1157
-                    // but adjust datetime qty based on datetime reg limit
1158
-                    $datetime_qty = min(EE_INF, $datetime->reg_limit());
1159
-                    // echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1160
-                    // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1161
-                    // if we want the actual saleable amount, then we need to consider OTHER ticket sales
1162
-                    // and reservations for this datetime, that do NOT include sales and reservations
1163
-                    // for this ticket (so we add $this->sold() and $this->reserved() back in)
1164
-                    if ($context === 'saleable') {
1165
-                        $datetime_qty = max(
1166
-                            $datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1167
-                            0
1168
-                        );
1169
-                        // echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1170
-                        // echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1171
-                        // echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1172
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1173
-                        $datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1174
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1175
-                    }
1176
-                    $qty = min($datetime_qty, $qty);
1177
-                    // echo "\n . . qty: " . $qty . '<br />';
1178
-                }
1179
-            }
1180
-        }
1181
-        // NOW that we know the  maximum number of tickets available for the datetime
1182
-        // we can finally factor in the details for this specific ticket
1183
-        if ($qty > 0 && $context === 'saleable') {
1184
-            // and subtract the sales for THIS ticket
1185
-            $qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1186
-            // echo "\n . qty: " . $qty . '<br />';
1187
-        }
1188
-        // echo "\nFINAL QTY: " . $qty . "<br /><br />";
1189
-        return $qty;
1190
-    }
1191
-
1192
-
1193
-    /**
1194
-     * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1195
-     *
1196
-     * @param int $qty
1197
-     * @return void
1198
-     * @throws EE_Error
1199
-     * @throws ReflectionException
1200
-     */
1201
-    public function set_qty($qty)
1202
-    {
1203
-        $datetimes = $this->datetimes();
1204
-        foreach ($datetimes as $datetime) {
1205
-            if ($datetime instanceof EE_Datetime) {
1206
-                $qty = min($qty, $datetime->reg_limit());
1207
-            }
1208
-        }
1209
-        $this->set('TKT_qty', $qty);
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * Gets uses
1215
-     *
1216
-     * @return int
1217
-     * @throws EE_Error
1218
-     * @throws ReflectionException
1219
-     */
1220
-    public function uses()
1221
-    {
1222
-        return $this->get('TKT_uses');
1223
-    }
1224
-
1225
-
1226
-    /**
1227
-     * Sets uses
1228
-     *
1229
-     * @param int $uses
1230
-     * @return void
1231
-     * @throws EE_Error
1232
-     * @throws ReflectionException
1233
-     */
1234
-    public function set_uses($uses)
1235
-    {
1236
-        $this->set('TKT_uses', $uses);
1237
-    }
1238
-
1239
-
1240
-    /**
1241
-     * returns whether ticket is required or not.
1242
-     *
1243
-     * @return boolean
1244
-     * @throws EE_Error
1245
-     * @throws ReflectionException
1246
-     */
1247
-    public function required()
1248
-    {
1249
-        return $this->get('TKT_required');
1250
-    }
1251
-
1252
-
1253
-    /**
1254
-     * sets the TKT_required property
1255
-     *
1256
-     * @param boolean $required
1257
-     * @return void
1258
-     * @throws EE_Error
1259
-     * @throws ReflectionException
1260
-     */
1261
-    public function set_required($required)
1262
-    {
1263
-        $this->set('TKT_required', $required);
1264
-    }
1265
-
1266
-
1267
-    /**
1268
-     * Gets taxable
1269
-     *
1270
-     * @return boolean
1271
-     * @throws EE_Error
1272
-     * @throws ReflectionException
1273
-     */
1274
-    public function taxable()
1275
-    {
1276
-        return $this->get('TKT_taxable');
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * Sets taxable
1282
-     *
1283
-     * @param boolean $taxable
1284
-     * @return void
1285
-     * @throws EE_Error
1286
-     * @throws ReflectionException
1287
-     */
1288
-    public function set_taxable($taxable)
1289
-    {
1290
-        $this->set('TKT_taxable', $taxable);
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * Gets is_default
1296
-     *
1297
-     * @return boolean
1298
-     * @throws EE_Error
1299
-     * @throws ReflectionException
1300
-     */
1301
-    public function is_default()
1302
-    {
1303
-        return $this->get('TKT_is_default');
1304
-    }
1305
-
1306
-
1307
-    /**
1308
-     * Sets is_default
1309
-     *
1310
-     * @param boolean $is_default
1311
-     * @return void
1312
-     * @throws EE_Error
1313
-     * @throws ReflectionException
1314
-     */
1315
-    public function set_is_default($is_default)
1316
-    {
1317
-        $this->set('TKT_is_default', $is_default);
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     * Gets order
1323
-     *
1324
-     * @return int
1325
-     * @throws EE_Error
1326
-     * @throws ReflectionException
1327
-     */
1328
-    public function order()
1329
-    {
1330
-        return $this->get('TKT_order');
1331
-    }
1332
-
1333
-
1334
-    /**
1335
-     * Sets order
1336
-     *
1337
-     * @param int $order
1338
-     * @return void
1339
-     * @throws EE_Error
1340
-     * @throws ReflectionException
1341
-     */
1342
-    public function set_order($order)
1343
-    {
1344
-        $this->set('TKT_order', $order);
1345
-    }
1346
-
1347
-
1348
-    /**
1349
-     * Gets row
1350
-     *
1351
-     * @return int
1352
-     * @throws EE_Error
1353
-     * @throws ReflectionException
1354
-     */
1355
-    public function row()
1356
-    {
1357
-        return $this->get('TKT_row');
1358
-    }
1359
-
1360
-
1361
-    /**
1362
-     * Sets row
1363
-     *
1364
-     * @param int $row
1365
-     * @return void
1366
-     * @throws EE_Error
1367
-     * @throws ReflectionException
1368
-     */
1369
-    public function set_row($row)
1370
-    {
1371
-        $this->set('TKT_row', $row);
1372
-    }
1373
-
1374
-
1375
-    /**
1376
-     * Gets deleted
1377
-     *
1378
-     * @return boolean
1379
-     * @throws EE_Error
1380
-     * @throws ReflectionException
1381
-     */
1382
-    public function deleted()
1383
-    {
1384
-        return $this->get('TKT_deleted');
1385
-    }
1386
-
1387
-
1388
-    /**
1389
-     * Sets deleted
1390
-     *
1391
-     * @param boolean $deleted
1392
-     * @return void
1393
-     * @throws EE_Error
1394
-     * @throws ReflectionException
1395
-     */
1396
-    public function set_deleted($deleted)
1397
-    {
1398
-        $this->set('TKT_deleted', $deleted);
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * Gets parent
1404
-     *
1405
-     * @return int
1406
-     * @throws EE_Error
1407
-     * @throws ReflectionException
1408
-     */
1409
-    public function parent_ID()
1410
-    {
1411
-        return $this->get('TKT_parent');
1412
-    }
1413
-
1414
-
1415
-    /**
1416
-     * Sets parent
1417
-     *
1418
-     * @param int $parent
1419
-     * @return void
1420
-     * @throws EE_Error
1421
-     * @throws ReflectionException
1422
-     */
1423
-    public function set_parent_ID($parent)
1424
-    {
1425
-        $this->set('TKT_parent', $parent);
1426
-    }
1427
-
1428
-
1429
-    /**
1430
-     * Gets a string which is handy for showing in gateways etc that describes the ticket.
1431
-     *
1432
-     * @return string
1433
-     * @throws EE_Error
1434
-     * @throws ReflectionException
1435
-     */
1436
-    public function name_and_info()
1437
-    {
1438
-        $times = [];
1439
-        foreach ($this->datetimes() as $datetime) {
1440
-            $times[] = $datetime->start_date_and_time();
1441
-        }
1442
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1443
-    }
1444
-
1445
-
1446
-    /**
1447
-     * Gets name
1448
-     *
1449
-     * @return string
1450
-     * @throws EE_Error
1451
-     * @throws ReflectionException
1452
-     */
1453
-    public function name()
1454
-    {
1455
-        return $this->get('TKT_name');
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * Gets price
1461
-     *
1462
-     * @return float
1463
-     * @throws EE_Error
1464
-     * @throws ReflectionException
1465
-     */
1466
-    public function price()
1467
-    {
1468
-        return $this->get('TKT_price');
1469
-    }
1470
-
1471
-
1472
-    /**
1473
-     * Gets all the registrations for this ticket
1474
-     *
1475
-     * @param array $query_params @see
1476
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1477
-     * @return EE_Registration[]|EE_Base_Class[]
1478
-     * @throws EE_Error
1479
-     * @throws ReflectionException
1480
-     */
1481
-    public function registrations($query_params = [])
1482
-    {
1483
-        return $this->get_many_related('Registration', $query_params);
1484
-    }
1485
-
1486
-
1487
-    /**
1488
-     * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1489
-     *
1490
-     * @return int
1491
-     * @throws EE_Error
1492
-     * @throws ReflectionException
1493
-     */
1494
-    public function update_tickets_sold()
1495
-    {
1496
-        $count_regs_for_this_ticket = $this->count_registrations(
1497
-            [
1498
-                [
1499
-                    'STS_ID'      => EEM_Registration::status_id_approved,
1500
-                    'REG_deleted' => 0,
1501
-                ],
1502
-            ]
1503
-        );
1504
-        $this->set_sold($count_regs_for_this_ticket);
1505
-        $this->save();
1506
-        return $count_regs_for_this_ticket;
1507
-    }
1508
-
1509
-
1510
-    /**
1511
-     * Counts the registrations for this ticket
1512
-     *
1513
-     * @param array $query_params @see
1514
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1515
-     * @return int
1516
-     */
1517
-    public function count_registrations($query_params = [])
1518
-    {
1519
-        return $this->count_related('Registration', $query_params);
1520
-    }
1521
-
1522
-
1523
-    /**
1524
-     * Implementation for EEI_Has_Icon interface method.
1525
-     *
1526
-     * @return string
1527
-     * @see EEI_Visual_Representation for comments
1528
-     */
1529
-    public function get_icon()
1530
-    {
1531
-        return '<span class="dashicons dashicons-tickets-alt"></span>';
1532
-    }
1533
-
1534
-
1535
-    /**
1536
-     * Implementation of the EEI_Event_Relation interface method
1537
-     *
1538
-     * @return EE_Event
1539
-     * @throws EE_Error
1540
-     * @throws UnexpectedEntityException*@throws ReflectionException
1541
-     * @see EEI_Event_Relation for comments
1542
-     */
1543
-    public function get_related_event()
1544
-    {
1545
-        // get one datetime to use for getting the event
1546
-        $datetime = $this->first_datetime();
1547
-        if (! $datetime instanceof \EE_Datetime) {
1548
-            throw new UnexpectedEntityException(
1549
-                $datetime,
1550
-                'EE_Datetime',
1551
-                sprintf(
1552
-                    esc_html__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1553
-                    $this->name()
1554
-                )
1555
-            );
1556
-        }
1557
-        $event = $datetime->event();
1558
-        if (! $event instanceof \EE_Event) {
1559
-            throw new UnexpectedEntityException(
1560
-                $event,
1561
-                'EE_Event',
1562
-                sprintf(
1563
-                    esc_html__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1564
-                    $this->name()
1565
-                )
1566
-            );
1567
-        }
1568
-        return $event;
1569
-    }
1570
-
1571
-
1572
-    /**
1573
-     * Implementation of the EEI_Event_Relation interface method
1574
-     *
1575
-     * @return string
1576
-     * @throws UnexpectedEntityException
1577
-     * @throws EE_Error*@throws ReflectionException
1578
-     * @see EEI_Event_Relation for comments
1579
-     */
1580
-    public function get_event_name()
1581
-    {
1582
-        $event = $this->get_related_event();
1583
-        return $event instanceof EE_Event ? $event->name() : '';
1584
-    }
1585
-
1586
-
1587
-    /**
1588
-     * Implementation of the EEI_Event_Relation interface method
1589
-     *
1590
-     * @return int
1591
-     * @throws UnexpectedEntityException
1592
-     * @throws EE_Error*@throws ReflectionException
1593
-     * @see EEI_Event_Relation for comments
1594
-     */
1595
-    public function get_event_ID()
1596
-    {
1597
-        $event = $this->get_related_event();
1598
-        return $event instanceof EE_Event ? $event->ID() : 0;
1599
-    }
1600
-
1601
-
1602
-    /**
1603
-     * This simply returns whether a ticket can be permanently deleted or not.
1604
-     * The criteria for determining this is whether the ticket has any related registrations.
1605
-     * If there are none then it can be permanently deleted.
1606
-     *
1607
-     * @return bool
1608
-     */
1609
-    public function is_permanently_deleteable()
1610
-    {
1611
-        return $this->count_registrations() === 0;
1612
-    }
1613
-
1614
-
1615
-    /*******************************************************************
17
+	/**
18
+	 * The following constants are used by the ticket_status() method to indicate whether a ticket is on sale or not.
19
+	 */
20
+	const sold_out = 'TKS';
21
+
22
+	/**
23
+	 *
24
+	 */
25
+	const expired = 'TKE';
26
+
27
+	/**
28
+	 *
29
+	 */
30
+	const archived = 'TKA';
31
+
32
+	/**
33
+	 *
34
+	 */
35
+	const pending = 'TKP';
36
+
37
+	/**
38
+	 *
39
+	 */
40
+	const onsale = 'TKO';
41
+
42
+	/**
43
+	 * extra meta key for tracking ticket reservations
44
+	 *
45
+	 * @type string
46
+	 */
47
+	const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
48
+
49
+	/**
50
+	 * cached result from method of the same name
51
+	 *
52
+	 * @var float $_ticket_total_with_taxes
53
+	 */
54
+	private $_ticket_total_with_taxes;
55
+
56
+
57
+	/**
58
+	 * @param array  $props_n_values          incoming values
59
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
60
+	 *                                        used.)
61
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
62
+	 *                                        date_format and the second value is the time format
63
+	 * @return EE_Ticket
64
+	 * @throws EE_Error
65
+	 * @throws ReflectionException
66
+	 */
67
+	public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
68
+	{
69
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
70
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
71
+	}
72
+
73
+
74
+	/**
75
+	 * @param array  $props_n_values  incoming values from the database
76
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
77
+	 *                                the website will be used.
78
+	 * @return EE_Ticket
79
+	 * @throws EE_Error
80
+	 * @throws ReflectionException
81
+	 */
82
+	public static function new_instance_from_db($props_n_values = [], $timezone = null)
83
+	{
84
+		return new self($props_n_values, true, $timezone);
85
+	}
86
+
87
+
88
+	/**
89
+	 * @return bool
90
+	 * @throws EE_Error
91
+	 * @throws ReflectionException
92
+	 */
93
+	public function parent()
94
+	{
95
+		return $this->get('TKT_parent');
96
+	}
97
+
98
+
99
+	/**
100
+	 * return if a ticket has quantities available for purchase
101
+	 *
102
+	 * @param int $DTT_ID the primary key for a particular datetime
103
+	 * @return boolean
104
+	 * @throws EE_Error
105
+	 * @throws ReflectionException
106
+	 */
107
+	public function available($DTT_ID = 0)
108
+	{
109
+		// are we checking availability for a particular datetime ?
110
+		if ($DTT_ID) {
111
+			// get that datetime object
112
+			$datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
113
+			// if  ticket sales for this datetime have exceeded the reg limit...
114
+			if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
115
+				return false;
116
+			}
117
+		}
118
+		// datetime is still open for registration, but is this ticket sold out ?
119
+		return $this->qty() < 1 || $this->qty() > $this->sold() ? true : false;
120
+	}
121
+
122
+
123
+	/**
124
+	 * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
125
+	 *
126
+	 * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
127
+	 *                               relevant status const
128
+	 * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
129
+	 *                               further processing
130
+	 * @return mixed status int if the display string isn't requested
131
+	 * @throws EE_Error
132
+	 * @throws ReflectionException
133
+	 */
134
+	public function ticket_status($display = false, $remaining = null)
135
+	{
136
+		$remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
137
+		if (! $remaining) {
138
+			return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
139
+		}
140
+		if ($this->get('TKT_deleted')) {
141
+			return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
142
+		}
143
+		if ($this->is_expired()) {
144
+			return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
145
+		}
146
+		if ($this->is_pending()) {
147
+			return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
148
+		}
149
+		if ($this->is_on_sale()) {
150
+			return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
151
+		}
152
+		return '';
153
+	}
154
+
155
+
156
+	/**
157
+	 * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
158
+	 * considering ALL the factors used for figuring that out.
159
+	 *
160
+	 * @access public
161
+	 * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
162
+	 * @return boolean         true = tickets remaining, false not.
163
+	 * @throws EE_Error
164
+	 */
165
+	public function is_remaining($DTT_ID = 0)
166
+	{
167
+		$num_remaining = $this->remaining($DTT_ID);
168
+		if ($num_remaining === 0) {
169
+			return false;
170
+		}
171
+		if ($num_remaining > 0 && $num_remaining < $this->min()) {
172
+			return false;
173
+		}
174
+		return true;
175
+	}
176
+
177
+
178
+	/**
179
+	 * return the total number of tickets available for purchase
180
+	 *
181
+	 * @param int $DTT_ID  the primary key for a particular datetime.
182
+	 *                     set to 0 for all related datetimes
183
+	 * @return int
184
+	 * @throws EE_Error
185
+	 */
186
+	public function remaining($DTT_ID = 0)
187
+	{
188
+		return $this->real_quantity_on_ticket('saleable', $DTT_ID);
189
+	}
190
+
191
+
192
+	/**
193
+	 * Gets min
194
+	 *
195
+	 * @return int
196
+	 * @throws EE_Error
197
+	 * @throws ReflectionException
198
+	 */
199
+	public function min()
200
+	{
201
+		return $this->get('TKT_min');
202
+	}
203
+
204
+
205
+	/**
206
+	 * return if a ticket is no longer available cause its available dates have expired.
207
+	 *
208
+	 * @return boolean
209
+	 * @throws EE_Error
210
+	 * @throws ReflectionException
211
+	 */
212
+	public function is_expired()
213
+	{
214
+		return ($this->get_raw('TKT_end_date') < time());
215
+	}
216
+
217
+
218
+	/**
219
+	 * Return if a ticket is yet to go on sale or not
220
+	 *
221
+	 * @return boolean
222
+	 * @throws EE_Error
223
+	 * @throws ReflectionException
224
+	 */
225
+	public function is_pending()
226
+	{
227
+		return ($this->get_raw('TKT_start_date') > time());
228
+	}
229
+
230
+
231
+	/**
232
+	 * Return if a ticket is on sale or not
233
+	 *
234
+	 * @return boolean
235
+	 * @throws EE_Error
236
+	 * @throws ReflectionException
237
+	 */
238
+	public function is_on_sale()
239
+	{
240
+		return ($this->get_raw('TKT_start_date') < time() && $this->get_raw('TKT_end_date') > time());
241
+	}
242
+
243
+
244
+	/**
245
+	 * This returns the chronologically last datetime that this ticket is associated with
246
+	 *
247
+	 * @param string $dt_frmt
248
+	 * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
249
+	 *                            the end date ie: Jan 01 "to" Dec 31
250
+	 * @return string
251
+	 * @throws EE_Error
252
+	 * @throws ReflectionException
253
+	 */
254
+	public function date_range($dt_frmt = '', $conjunction = ' - ')
255
+	{
256
+		$dt_frmt    = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
257
+		$first_date = $this->first_datetime() instanceof EE_Datetime
258
+			? $this->first_datetime()->get_i18n_datetime(
259
+				'DTT_EVT_start',
260
+				$dt_frmt
261
+			) : '';
262
+		$last_date  =
263
+			$this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->get_i18n_datetime(
264
+				'DTT_EVT_end',
265
+				$dt_frmt
266
+			) : '';
267
+
268
+		return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
269
+	}
270
+
271
+
272
+	/**
273
+	 * This returns the chronologically first datetime that this ticket is associated with
274
+	 *
275
+	 * @return EE_Datetime
276
+	 * @throws EE_Error
277
+	 */
278
+	public function first_datetime()
279
+	{
280
+		$datetimes = $this->datetimes(['limit' => 1]);
281
+		return reset($datetimes);
282
+	}
283
+
284
+
285
+	/**
286
+	 * Gets all the datetimes this ticket can be used for attending.
287
+	 * Unless otherwise specified, orders datetimes by start date.
288
+	 *
289
+	 * @param array $query_params @see
290
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
291
+	 * @return EE_Datetime[]|EE_Base_Class[]
292
+	 * @throws EE_Error
293
+	 * @throws ReflectionException
294
+	 */
295
+	public function datetimes($query_params = [])
296
+	{
297
+		if (! isset($query_params['order_by'])) {
298
+			$query_params['order_by']['DTT_order'] = 'ASC';
299
+		}
300
+		return $this->get_many_related('Datetime', $query_params);
301
+	}
302
+
303
+
304
+	/**
305
+	 * This returns the chronologically last datetime that this ticket is associated with
306
+	 *
307
+	 * @return EE_Datetime
308
+	 * @throws EE_Error
309
+	 */
310
+	public function last_datetime()
311
+	{
312
+		$datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
313
+		return end($datetimes);
314
+	}
315
+
316
+
317
+	/**
318
+	 * This returns the total tickets sold depending on the given parameters.
319
+	 *
320
+	 * @param string $what    Can be one of two options: 'ticket', 'datetime'.
321
+	 *                        'ticket' = total ticket sales for all datetimes this ticket is related to
322
+	 *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
323
+	 *                        'datetime' = total ticket sales in the datetime_ticket table.
324
+	 *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
325
+	 *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
326
+	 * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
327
+	 * @return mixed (array|int)          how many tickets have sold
328
+	 * @throws EE_Error
329
+	 */
330
+	public function tickets_sold($what = 'ticket', $dtt_id = null)
331
+	{
332
+		$total        = 0;
333
+		$tickets_sold = $this->_all_tickets_sold();
334
+		switch ($what) {
335
+			case 'ticket':
336
+				return $tickets_sold['ticket'];
337
+				break;
338
+			case 'datetime':
339
+				if (empty($tickets_sold['datetime'])) {
340
+					return $total;
341
+				}
342
+				if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
343
+					EE_Error::add_error(
344
+						esc_html__(
345
+							'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?',
346
+							'event_espresso'
347
+						),
348
+						__FILE__,
349
+						__FUNCTION__,
350
+						__LINE__
351
+					);
352
+					return $total;
353
+				}
354
+				return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
355
+				break;
356
+			default:
357
+				return $total;
358
+		}
359
+	}
360
+
361
+
362
+	/**
363
+	 * This returns an array indexed by datetime_id for tickets sold with this ticket.
364
+	 *
365
+	 * @return EE_Ticket[]
366
+	 * @throws EE_Error
367
+	 * @throws ReflectionException
368
+	 */
369
+	protected function _all_tickets_sold()
370
+	{
371
+		$datetimes    = $this->get_many_related('Datetime');
372
+		$tickets_sold = [];
373
+		if (! empty($datetimes)) {
374
+			foreach ($datetimes as $datetime) {
375
+				$tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
376
+			}
377
+		}
378
+		// Tickets sold
379
+		$tickets_sold['ticket'] = $this->sold();
380
+		return $tickets_sold;
381
+	}
382
+
383
+
384
+	/**
385
+	 * This returns the base price object for the ticket.
386
+	 *
387
+	 * @param bool $return_array whether to return as an array indexed by price id or just the object.
388
+	 * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
389
+	 * @throws EE_Error
390
+	 * @throws ReflectionException
391
+	 */
392
+	public function base_price($return_array = false)
393
+	{
394
+		$_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
395
+		return $return_array
396
+			? $this->get_many_related('Price', [$_where])
397
+			: $this->get_first_related('Price', [$_where]);
398
+	}
399
+
400
+
401
+	/**
402
+	 * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
403
+	 *
404
+	 * @access public
405
+	 * @return EE_Price[]
406
+	 * @throws EE_Error
407
+	 */
408
+	public function price_modifiers()
409
+	{
410
+		$query_params = [
411
+			0 => [
412
+				'Price_Type.PBT_ID' => [
413
+					'NOT IN',
414
+					[EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
415
+				],
416
+			],
417
+		];
418
+		return $this->prices($query_params);
419
+	}
420
+
421
+
422
+	/**
423
+	 * Gets all the prices that combine to form the final price of this ticket
424
+	 *
425
+	 * @param array $query_params @see
426
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
427
+	 * @return EE_Price[]|EE_Base_Class[]
428
+	 * @throws EE_Error
429
+	 * @throws ReflectionException
430
+	 */
431
+	public function prices($query_params = [])
432
+	{
433
+		return $this->get_many_related('Price', $query_params);
434
+	}
435
+
436
+
437
+	/**
438
+	 * Gets all the ticket applicabilities (ie, relations between datetimes and tickets)
439
+	 *
440
+	 * @param array $query_params @see
441
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
442
+	 * @return EE_Datetime_Ticket|EE_Base_Class[]
443
+	 * @throws EE_Error
444
+	 * @throws ReflectionException
445
+	 */
446
+	public function datetime_tickets($query_params = [])
447
+	{
448
+		return $this->get_many_related('Datetime_Ticket', $query_params);
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets all the datetimes from the db ordered by DTT_order
454
+	 *
455
+	 * @param boolean $show_expired
456
+	 * @param boolean $show_deleted
457
+	 * @return EE_Datetime[]
458
+	 * @throws EE_Error
459
+	 */
460
+	public function datetimes_ordered($show_expired = true, $show_deleted = false)
461
+	{
462
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
463
+			$this->ID(),
464
+			$show_expired,
465
+			$show_deleted
466
+		);
467
+	}
468
+
469
+
470
+	/**
471
+	 * Gets ID
472
+	 *
473
+	 * @return int
474
+	 * @throws EE_Error
475
+	 * @throws ReflectionException
476
+	 */
477
+	public function ID()
478
+	{
479
+		return (int) $this->get('TKT_ID');
480
+	}
481
+
482
+
483
+	/**
484
+	 * get the author of the ticket.
485
+	 *
486
+	 * @return int
487
+	 * @throws EE_Error
488
+	 * @throws ReflectionException
489
+	 * @since 4.5.0
490
+	 */
491
+	public function wp_user()
492
+	{
493
+		return $this->get('TKT_wp_user');
494
+	}
495
+
496
+
497
+	/**
498
+	 * Gets the template for the ticket
499
+	 *
500
+	 * @return EE_Ticket_Template|EE_Base_Class
501
+	 * @throws EE_Error
502
+	 * @throws ReflectionException
503
+	 */
504
+	public function template()
505
+	{
506
+		return $this->get_first_related('Ticket_Template');
507
+	}
508
+
509
+
510
+	/**
511
+	 * Simply returns an array of EE_Price objects that are taxes.
512
+	 *
513
+	 * @return EE_Price[]
514
+	 * @throws EE_Error
515
+	 */
516
+	public function get_ticket_taxes_for_admin()
517
+	{
518
+		return EE_Taxes::get_taxes_for_admin();
519
+	}
520
+
521
+
522
+	/**
523
+	 * @return float
524
+	 * @throws EE_Error
525
+	 * @throws ReflectionException
526
+	 */
527
+	public function ticket_price()
528
+	{
529
+		return $this->get('TKT_price');
530
+	}
531
+
532
+
533
+	/**
534
+	 * @return mixed
535
+	 * @throws EE_Error
536
+	 * @throws ReflectionException
537
+	 */
538
+	public function pretty_price()
539
+	{
540
+		return $this->get_pretty('TKT_price');
541
+	}
542
+
543
+
544
+	/**
545
+	 * @return bool
546
+	 * @throws EE_Error
547
+	 */
548
+	public function is_free()
549
+	{
550
+		return $this->get_ticket_total_with_taxes() === (float) 0;
551
+	}
552
+
553
+
554
+	/**
555
+	 * get_ticket_total_with_taxes
556
+	 *
557
+	 * @param bool $no_cache
558
+	 * @return float
559
+	 * @throws EE_Error
560
+	 */
561
+	public function get_ticket_total_with_taxes($no_cache = false)
562
+	{
563
+		if ($this->_ticket_total_with_taxes === null || $no_cache) {
564
+			$this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
565
+		}
566
+		return (float) $this->_ticket_total_with_taxes;
567
+	}
568
+
569
+
570
+	public function ensure_TKT_Price_correct()
571
+	{
572
+		$this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
573
+		$this->save();
574
+	}
575
+
576
+
577
+	/**
578
+	 * @return float
579
+	 * @throws EE_Error
580
+	 */
581
+	public function get_ticket_subtotal()
582
+	{
583
+		return EE_Taxes::get_subtotal_for_admin($this);
584
+	}
585
+
586
+
587
+	/**
588
+	 * Returns the total taxes applied to this ticket
589
+	 *
590
+	 * @return float
591
+	 * @throws EE_Error
592
+	 */
593
+	public function get_ticket_taxes_total_for_admin()
594
+	{
595
+		return EE_Taxes::get_total_taxes_for_admin($this);
596
+	}
597
+
598
+
599
+	/**
600
+	 * Sets name
601
+	 *
602
+	 * @param string $name
603
+	 * @throws EE_Error
604
+	 * @throws ReflectionException
605
+	 */
606
+	public function set_name($name)
607
+	{
608
+		$this->set('TKT_name', $name);
609
+	}
610
+
611
+
612
+	/**
613
+	 * Gets description
614
+	 *
615
+	 * @return string
616
+	 * @throws EE_Error
617
+	 * @throws ReflectionException
618
+	 */
619
+	public function description()
620
+	{
621
+		return $this->get('TKT_description');
622
+	}
623
+
624
+
625
+	/**
626
+	 * Sets description
627
+	 *
628
+	 * @param string $description
629
+	 * @throws EE_Error
630
+	 * @throws ReflectionException
631
+	 */
632
+	public function set_description($description)
633
+	{
634
+		$this->set('TKT_description', $description);
635
+	}
636
+
637
+
638
+	/**
639
+	 * Gets start_date
640
+	 *
641
+	 * @param string $dt_frmt
642
+	 * @param string $tm_frmt
643
+	 * @return string
644
+	 * @throws EE_Error
645
+	 * @throws ReflectionException
646
+	 */
647
+	public function start_date($dt_frmt = '', $tm_frmt = '')
648
+	{
649
+		return $this->_get_datetime('TKT_start_date', $dt_frmt, $tm_frmt);
650
+	}
651
+
652
+
653
+	/**
654
+	 * Sets start_date
655
+	 *
656
+	 * @param string $start_date
657
+	 * @return void
658
+	 * @throws EE_Error
659
+	 * @throws ReflectionException
660
+	 */
661
+	public function set_start_date($start_date)
662
+	{
663
+		$this->_set_date_time('B', $start_date, 'TKT_start_date');
664
+	}
665
+
666
+
667
+	/**
668
+	 * Gets end_date
669
+	 *
670
+	 * @param string $dt_frmt
671
+	 * @param string $tm_frmt
672
+	 * @return string
673
+	 * @throws EE_Error
674
+	 * @throws ReflectionException
675
+	 */
676
+	public function end_date($dt_frmt = '', $tm_frmt = '')
677
+	{
678
+		return $this->_get_datetime('TKT_end_date', $dt_frmt, $tm_frmt);
679
+	}
680
+
681
+
682
+	/**
683
+	 * Sets end_date
684
+	 *
685
+	 * @param string $end_date
686
+	 * @return void
687
+	 * @throws EE_Error
688
+	 * @throws ReflectionException
689
+	 */
690
+	public function set_end_date($end_date)
691
+	{
692
+		$this->_set_date_time('B', $end_date, 'TKT_end_date');
693
+	}
694
+
695
+
696
+	/**
697
+	 * Sets sell until time
698
+	 *
699
+	 * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
700
+	 * @throws EE_Error*@throws ReflectionException
701
+	 * @since 4.5.0
702
+	 */
703
+	public function set_end_time($time)
704
+	{
705
+		$this->_set_time_for($time, 'TKT_end_date');
706
+	}
707
+
708
+
709
+	/**
710
+	 * Sets min
711
+	 *
712
+	 * @param int $min
713
+	 * @return void
714
+	 * @throws EE_Error
715
+	 * @throws ReflectionException
716
+	 */
717
+	public function set_min($min)
718
+	{
719
+		$this->set('TKT_min', $min);
720
+	}
721
+
722
+
723
+	/**
724
+	 * Gets max
725
+	 *
726
+	 * @return int
727
+	 * @throws EE_Error
728
+	 * @throws ReflectionException
729
+	 */
730
+	public function max()
731
+	{
732
+		return $this->get('TKT_max');
733
+	}
734
+
735
+
736
+	/**
737
+	 * Sets max
738
+	 *
739
+	 * @param int $max
740
+	 * @return void
741
+	 * @throws EE_Error
742
+	 * @throws ReflectionException
743
+	 */
744
+	public function set_max($max)
745
+	{
746
+		$this->set('TKT_max', $max);
747
+	}
748
+
749
+
750
+	/**
751
+	 * Sets price
752
+	 *
753
+	 * @param float $price
754
+	 * @return void
755
+	 * @throws EE_Error
756
+	 * @throws ReflectionException
757
+	 */
758
+	public function set_price($price)
759
+	{
760
+		$this->set('TKT_price', $price);
761
+	}
762
+
763
+
764
+	/**
765
+	 * Gets sold
766
+	 *
767
+	 * @return int
768
+	 * @throws EE_Error
769
+	 * @throws ReflectionException
770
+	 */
771
+	public function sold()
772
+	{
773
+		return $this->get_raw('TKT_sold');
774
+	}
775
+
776
+
777
+	/**
778
+	 * Sets sold
779
+	 *
780
+	 * @param int $sold
781
+	 * @return void
782
+	 * @throws EE_Error
783
+	 * @throws ReflectionException
784
+	 */
785
+	public function set_sold($sold)
786
+	{
787
+		// sold can not go below zero
788
+		$sold = max(0, $sold);
789
+		$this->set('TKT_sold', $sold);
790
+	}
791
+
792
+
793
+	/**
794
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
795
+	 * associated datetimes.
796
+	 *
797
+	 * @param int $qty
798
+	 * @return boolean
799
+	 * @throws EE_Error
800
+	 * @throws InvalidArgumentException
801
+	 * @throws InvalidDataTypeException
802
+	 * @throws InvalidInterfaceException
803
+	 * @throws ReflectionException
804
+	 * @since 4.9.80.p
805
+	 */
806
+	public function increaseSold($qty = 1)
807
+	{
808
+		$qty = absint($qty);
809
+		// increment sold and decrement reserved datetime quantities simultaneously
810
+		// don't worry about failures, because they must have already had a spot reserved
811
+		$this->increaseSoldForDatetimes($qty);
812
+		// Increment and decrement ticket quantities simultaneously
813
+		$success = $this->adjustNumericFieldsInDb(
814
+			[
815
+				'TKT_reserved' => $qty * -1,
816
+				'TKT_sold'     => $qty,
817
+			]
818
+		);
819
+		do_action(
820
+			'AHEE__EE_Ticket__increase_sold',
821
+			$this,
822
+			$qty,
823
+			$this->sold(),
824
+			$success
825
+		);
826
+		return $success;
827
+	}
828
+
829
+
830
+	/**
831
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
832
+	 *
833
+	 * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
834
+	 *                           counts), Negative means to decreases old counts (and increase reserved counts).
835
+	 * @param EE_Datetime[] $datetimes
836
+	 * @throws EE_Error
837
+	 * @throws InvalidArgumentException
838
+	 * @throws InvalidDataTypeException
839
+	 * @throws InvalidInterfaceException
840
+	 * @throws ReflectionException
841
+	 * @since 4.9.80.p
842
+	 */
843
+	protected function increaseSoldForDatetimes($qty, array $datetimes = [])
844
+	{
845
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
846
+		foreach ($datetimes as $datetime) {
847
+			$datetime->increaseSold($qty);
848
+		}
849
+	}
850
+
851
+
852
+	/**
853
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
854
+	 * DB and then updates the model objects.
855
+	 * Does not affect the reserved counts.
856
+	 *
857
+	 * @param int $qty
858
+	 * @return boolean
859
+	 * @throws EE_Error
860
+	 * @throws InvalidArgumentException
861
+	 * @throws InvalidDataTypeException
862
+	 * @throws InvalidInterfaceException
863
+	 * @throws ReflectionException
864
+	 * @since 4.9.80.p
865
+	 */
866
+	public function decreaseSold($qty = 1)
867
+	{
868
+		$qty = absint($qty);
869
+		$this->decreaseSoldForDatetimes($qty);
870
+		$success = $this->adjustNumericFieldsInDb(
871
+			[
872
+				'TKT_sold' => $qty * -1,
873
+			]
874
+		);
875
+		do_action(
876
+			'AHEE__EE_Ticket__decrease_sold',
877
+			$this,
878
+			$qty,
879
+			$this->sold(),
880
+			$success
881
+		);
882
+		return $success;
883
+	}
884
+
885
+
886
+	/**
887
+	 * Decreases sold on related datetimes
888
+	 *
889
+	 * @param int           $qty
890
+	 * @param EE_Datetime[] $datetimes
891
+	 * @return void
892
+	 * @throws EE_Error
893
+	 * @throws InvalidArgumentException
894
+	 * @throws InvalidDataTypeException
895
+	 * @throws InvalidInterfaceException
896
+	 * @throws ReflectionException
897
+	 * @since 4.9.80.p
898
+	 */
899
+	protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
900
+	{
901
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
902
+		if (is_array($datetimes)) {
903
+			foreach ($datetimes as $datetime) {
904
+				if ($datetime instanceof EE_Datetime) {
905
+					$datetime->decreaseSold($qty);
906
+				}
907
+			}
908
+		}
909
+	}
910
+
911
+
912
+	/**
913
+	 * Gets qty of reserved tickets
914
+	 *
915
+	 * @return int
916
+	 * @throws EE_Error
917
+	 * @throws ReflectionException
918
+	 */
919
+	public function reserved()
920
+	{
921
+		return $this->get_raw('TKT_reserved');
922
+	}
923
+
924
+
925
+	/**
926
+	 * Sets reserved
927
+	 *
928
+	 * @param int $reserved
929
+	 * @return void
930
+	 * @throws EE_Error
931
+	 * @throws ReflectionException
932
+	 */
933
+	public function set_reserved($reserved)
934
+	{
935
+		// reserved can not go below zero
936
+		$reserved = max(0, (int) $reserved);
937
+		$this->set('TKT_reserved', $reserved);
938
+	}
939
+
940
+
941
+	/**
942
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
943
+	 *
944
+	 * @param int    $qty
945
+	 * @param string $source
946
+	 * @return bool whether we successfully reserved the ticket or not.
947
+	 * @throws EE_Error
948
+	 * @throws InvalidArgumentException
949
+	 * @throws ReflectionException
950
+	 * @throws InvalidDataTypeException
951
+	 * @throws InvalidInterfaceException
952
+	 * @since 4.9.80.p
953
+	 */
954
+	public function increaseReserved($qty = 1, $source = 'unknown')
955
+	{
956
+		$qty = absint($qty);
957
+		do_action(
958
+			'AHEE__EE_Ticket__increase_reserved__begin',
959
+			$this,
960
+			$qty,
961
+			$source
962
+		);
963
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
964
+		$success                         = false;
965
+		$datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
966
+		if ($datetimes_adjusted_successfully) {
967
+			$success = $this->incrementFieldConditionallyInDb(
968
+				'TKT_reserved',
969
+				'TKT_sold',
970
+				'TKT_qty',
971
+				$qty
972
+			);
973
+			if (! $success) {
974
+				// The datetimes were successfully bumped, but not the
975
+				// ticket. So we need to manually rollback the datetimes.
976
+				$this->decreaseReservedForDatetimes($qty);
977
+			}
978
+		}
979
+		do_action(
980
+			'AHEE__EE_Ticket__increase_reserved',
981
+			$this,
982
+			$qty,
983
+			$this->reserved(),
984
+			$success
985
+		);
986
+		return $success;
987
+	}
988
+
989
+
990
+	/**
991
+	 * Increases reserved counts on related datetimes
992
+	 *
993
+	 * @param int           $qty
994
+	 * @param EE_Datetime[] $datetimes
995
+	 * @return boolean indicating success
996
+	 * @throws EE_Error
997
+	 * @throws InvalidArgumentException
998
+	 * @throws InvalidDataTypeException
999
+	 * @throws InvalidInterfaceException
1000
+	 * @throws ReflectionException
1001
+	 * @since 4.9.80.p
1002
+	 */
1003
+	protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1004
+	{
1005
+		$datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1006
+		$datetimes_updated = [];
1007
+		$limit_exceeded    = false;
1008
+		if (is_array($datetimes)) {
1009
+			foreach ($datetimes as $datetime) {
1010
+				if ($datetime instanceof EE_Datetime) {
1011
+					if ($datetime->increaseReserved($qty)) {
1012
+						$datetimes_updated[] = $datetime;
1013
+					} else {
1014
+						$limit_exceeded = true;
1015
+						break;
1016
+					}
1017
+				}
1018
+			}
1019
+			// If somewhere along the way we detected a datetime whose
1020
+			// limit was exceeded, do a manual rollback.
1021
+			if ($limit_exceeded) {
1022
+				$this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1023
+				return false;
1024
+			}
1025
+		}
1026
+		return true;
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1032
+	 *
1033
+	 * @param int    $qty
1034
+	 * @param bool   $adjust_datetimes
1035
+	 * @param string $source
1036
+	 * @return boolean
1037
+	 * @throws EE_Error
1038
+	 * @throws InvalidArgumentException
1039
+	 * @throws ReflectionException
1040
+	 * @throws InvalidDataTypeException
1041
+	 * @throws InvalidInterfaceException
1042
+	 * @since 4.9.80.p
1043
+	 */
1044
+	public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1045
+	{
1046
+		$qty = absint($qty);
1047
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1048
+		if ($adjust_datetimes) {
1049
+			$this->decreaseReservedForDatetimes($qty);
1050
+		}
1051
+		$success = $this->adjustNumericFieldsInDb(
1052
+			[
1053
+				'TKT_reserved' => $qty * -1,
1054
+			]
1055
+		);
1056
+		do_action(
1057
+			'AHEE__EE_Ticket__decrease_reserved',
1058
+			$this,
1059
+			$qty,
1060
+			$this->reserved(),
1061
+			$success
1062
+		);
1063
+		return $success;
1064
+	}
1065
+
1066
+
1067
+	/**
1068
+	 * Decreases the reserved count on the specified datetimes.
1069
+	 *
1070
+	 * @param int           $qty
1071
+	 * @param EE_Datetime[] $datetimes
1072
+	 * @throws EE_Error
1073
+	 * @throws InvalidArgumentException
1074
+	 * @throws ReflectionException
1075
+	 * @throws InvalidDataTypeException
1076
+	 * @throws InvalidInterfaceException
1077
+	 * @since 4.9.80.p
1078
+	 */
1079
+	protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1080
+	{
1081
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1082
+		foreach ($datetimes as $datetime) {
1083
+			if ($datetime instanceof EE_Datetime) {
1084
+				$datetime->decreaseReserved($qty);
1085
+			}
1086
+		}
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * Gets ticket quantity
1092
+	 *
1093
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1094
+	 *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1095
+	 *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1096
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1097
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1098
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1099
+	 * @return int
1100
+	 * @throws EE_Error
1101
+	 * @throws ReflectionException
1102
+	 */
1103
+	public function qty($context = '')
1104
+	{
1105
+		switch ($context) {
1106
+			case 'reg_limit':
1107
+				return $this->real_quantity_on_ticket();
1108
+			case 'saleable':
1109
+				return $this->real_quantity_on_ticket('saleable');
1110
+			default:
1111
+				return $this->get_raw('TKT_qty');
1112
+		}
1113
+	}
1114
+
1115
+
1116
+	/**
1117
+	 * Gets ticket quantity
1118
+	 *
1119
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1120
+	 *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1121
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1122
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1123
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1124
+	 * @param int    $DTT_ID      the primary key for a particular datetime.
1125
+	 *                            set to 0 for all related datetimes
1126
+	 * @return int
1127
+	 * @throws EE_Error
1128
+	 * @throws ReflectionException
1129
+	 */
1130
+	public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1131
+	{
1132
+		$raw = $this->get_raw('TKT_qty');
1133
+		// return immediately if it's zero
1134
+		if ($raw === 0) {
1135
+			return $raw;
1136
+		}
1137
+		// echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1138
+		// ensure qty doesn't exceed raw value for THIS ticket
1139
+		$qty = min(EE_INF, $raw);
1140
+		// echo "\n . qty: " . $qty . '<br />';
1141
+		// calculate this ticket's total sales and reservations
1142
+		$sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1143
+		// echo "\n . sold: " . $this->sold() . '<br />';
1144
+		// echo "\n . reserved: " . $this->reserved() . '<br />';
1145
+		// echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1146
+		// first we need to calculate the maximum number of tickets available for the datetime
1147
+		// do we want data for one datetime or all of them ?
1148
+		$query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1149
+		$datetimes    = $this->datetimes($query_params);
1150
+		if (is_array($datetimes) && ! empty($datetimes)) {
1151
+			foreach ($datetimes as $datetime) {
1152
+				if ($datetime instanceof EE_Datetime) {
1153
+					$datetime->refresh_from_db();
1154
+					// echo "\n . . datetime name: " . $datetime->name() . '<br />';
1155
+					// echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1156
+					// initialize with no restrictions for each datetime
1157
+					// but adjust datetime qty based on datetime reg limit
1158
+					$datetime_qty = min(EE_INF, $datetime->reg_limit());
1159
+					// echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1160
+					// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1161
+					// if we want the actual saleable amount, then we need to consider OTHER ticket sales
1162
+					// and reservations for this datetime, that do NOT include sales and reservations
1163
+					// for this ticket (so we add $this->sold() and $this->reserved() back in)
1164
+					if ($context === 'saleable') {
1165
+						$datetime_qty = max(
1166
+							$datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1167
+							0
1168
+						);
1169
+						// echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1170
+						// echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1171
+						// echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1172
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1173
+						$datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1174
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1175
+					}
1176
+					$qty = min($datetime_qty, $qty);
1177
+					// echo "\n . . qty: " . $qty . '<br />';
1178
+				}
1179
+			}
1180
+		}
1181
+		// NOW that we know the  maximum number of tickets available for the datetime
1182
+		// we can finally factor in the details for this specific ticket
1183
+		if ($qty > 0 && $context === 'saleable') {
1184
+			// and subtract the sales for THIS ticket
1185
+			$qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1186
+			// echo "\n . qty: " . $qty . '<br />';
1187
+		}
1188
+		// echo "\nFINAL QTY: " . $qty . "<br /><br />";
1189
+		return $qty;
1190
+	}
1191
+
1192
+
1193
+	/**
1194
+	 * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1195
+	 *
1196
+	 * @param int $qty
1197
+	 * @return void
1198
+	 * @throws EE_Error
1199
+	 * @throws ReflectionException
1200
+	 */
1201
+	public function set_qty($qty)
1202
+	{
1203
+		$datetimes = $this->datetimes();
1204
+		foreach ($datetimes as $datetime) {
1205
+			if ($datetime instanceof EE_Datetime) {
1206
+				$qty = min($qty, $datetime->reg_limit());
1207
+			}
1208
+		}
1209
+		$this->set('TKT_qty', $qty);
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * Gets uses
1215
+	 *
1216
+	 * @return int
1217
+	 * @throws EE_Error
1218
+	 * @throws ReflectionException
1219
+	 */
1220
+	public function uses()
1221
+	{
1222
+		return $this->get('TKT_uses');
1223
+	}
1224
+
1225
+
1226
+	/**
1227
+	 * Sets uses
1228
+	 *
1229
+	 * @param int $uses
1230
+	 * @return void
1231
+	 * @throws EE_Error
1232
+	 * @throws ReflectionException
1233
+	 */
1234
+	public function set_uses($uses)
1235
+	{
1236
+		$this->set('TKT_uses', $uses);
1237
+	}
1238
+
1239
+
1240
+	/**
1241
+	 * returns whether ticket is required or not.
1242
+	 *
1243
+	 * @return boolean
1244
+	 * @throws EE_Error
1245
+	 * @throws ReflectionException
1246
+	 */
1247
+	public function required()
1248
+	{
1249
+		return $this->get('TKT_required');
1250
+	}
1251
+
1252
+
1253
+	/**
1254
+	 * sets the TKT_required property
1255
+	 *
1256
+	 * @param boolean $required
1257
+	 * @return void
1258
+	 * @throws EE_Error
1259
+	 * @throws ReflectionException
1260
+	 */
1261
+	public function set_required($required)
1262
+	{
1263
+		$this->set('TKT_required', $required);
1264
+	}
1265
+
1266
+
1267
+	/**
1268
+	 * Gets taxable
1269
+	 *
1270
+	 * @return boolean
1271
+	 * @throws EE_Error
1272
+	 * @throws ReflectionException
1273
+	 */
1274
+	public function taxable()
1275
+	{
1276
+		return $this->get('TKT_taxable');
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * Sets taxable
1282
+	 *
1283
+	 * @param boolean $taxable
1284
+	 * @return void
1285
+	 * @throws EE_Error
1286
+	 * @throws ReflectionException
1287
+	 */
1288
+	public function set_taxable($taxable)
1289
+	{
1290
+		$this->set('TKT_taxable', $taxable);
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * Gets is_default
1296
+	 *
1297
+	 * @return boolean
1298
+	 * @throws EE_Error
1299
+	 * @throws ReflectionException
1300
+	 */
1301
+	public function is_default()
1302
+	{
1303
+		return $this->get('TKT_is_default');
1304
+	}
1305
+
1306
+
1307
+	/**
1308
+	 * Sets is_default
1309
+	 *
1310
+	 * @param boolean $is_default
1311
+	 * @return void
1312
+	 * @throws EE_Error
1313
+	 * @throws ReflectionException
1314
+	 */
1315
+	public function set_is_default($is_default)
1316
+	{
1317
+		$this->set('TKT_is_default', $is_default);
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 * Gets order
1323
+	 *
1324
+	 * @return int
1325
+	 * @throws EE_Error
1326
+	 * @throws ReflectionException
1327
+	 */
1328
+	public function order()
1329
+	{
1330
+		return $this->get('TKT_order');
1331
+	}
1332
+
1333
+
1334
+	/**
1335
+	 * Sets order
1336
+	 *
1337
+	 * @param int $order
1338
+	 * @return void
1339
+	 * @throws EE_Error
1340
+	 * @throws ReflectionException
1341
+	 */
1342
+	public function set_order($order)
1343
+	{
1344
+		$this->set('TKT_order', $order);
1345
+	}
1346
+
1347
+
1348
+	/**
1349
+	 * Gets row
1350
+	 *
1351
+	 * @return int
1352
+	 * @throws EE_Error
1353
+	 * @throws ReflectionException
1354
+	 */
1355
+	public function row()
1356
+	{
1357
+		return $this->get('TKT_row');
1358
+	}
1359
+
1360
+
1361
+	/**
1362
+	 * Sets row
1363
+	 *
1364
+	 * @param int $row
1365
+	 * @return void
1366
+	 * @throws EE_Error
1367
+	 * @throws ReflectionException
1368
+	 */
1369
+	public function set_row($row)
1370
+	{
1371
+		$this->set('TKT_row', $row);
1372
+	}
1373
+
1374
+
1375
+	/**
1376
+	 * Gets deleted
1377
+	 *
1378
+	 * @return boolean
1379
+	 * @throws EE_Error
1380
+	 * @throws ReflectionException
1381
+	 */
1382
+	public function deleted()
1383
+	{
1384
+		return $this->get('TKT_deleted');
1385
+	}
1386
+
1387
+
1388
+	/**
1389
+	 * Sets deleted
1390
+	 *
1391
+	 * @param boolean $deleted
1392
+	 * @return void
1393
+	 * @throws EE_Error
1394
+	 * @throws ReflectionException
1395
+	 */
1396
+	public function set_deleted($deleted)
1397
+	{
1398
+		$this->set('TKT_deleted', $deleted);
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * Gets parent
1404
+	 *
1405
+	 * @return int
1406
+	 * @throws EE_Error
1407
+	 * @throws ReflectionException
1408
+	 */
1409
+	public function parent_ID()
1410
+	{
1411
+		return $this->get('TKT_parent');
1412
+	}
1413
+
1414
+
1415
+	/**
1416
+	 * Sets parent
1417
+	 *
1418
+	 * @param int $parent
1419
+	 * @return void
1420
+	 * @throws EE_Error
1421
+	 * @throws ReflectionException
1422
+	 */
1423
+	public function set_parent_ID($parent)
1424
+	{
1425
+		$this->set('TKT_parent', $parent);
1426
+	}
1427
+
1428
+
1429
+	/**
1430
+	 * Gets a string which is handy for showing in gateways etc that describes the ticket.
1431
+	 *
1432
+	 * @return string
1433
+	 * @throws EE_Error
1434
+	 * @throws ReflectionException
1435
+	 */
1436
+	public function name_and_info()
1437
+	{
1438
+		$times = [];
1439
+		foreach ($this->datetimes() as $datetime) {
1440
+			$times[] = $datetime->start_date_and_time();
1441
+		}
1442
+		return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1443
+	}
1444
+
1445
+
1446
+	/**
1447
+	 * Gets name
1448
+	 *
1449
+	 * @return string
1450
+	 * @throws EE_Error
1451
+	 * @throws ReflectionException
1452
+	 */
1453
+	public function name()
1454
+	{
1455
+		return $this->get('TKT_name');
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * Gets price
1461
+	 *
1462
+	 * @return float
1463
+	 * @throws EE_Error
1464
+	 * @throws ReflectionException
1465
+	 */
1466
+	public function price()
1467
+	{
1468
+		return $this->get('TKT_price');
1469
+	}
1470
+
1471
+
1472
+	/**
1473
+	 * Gets all the registrations for this ticket
1474
+	 *
1475
+	 * @param array $query_params @see
1476
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1477
+	 * @return EE_Registration[]|EE_Base_Class[]
1478
+	 * @throws EE_Error
1479
+	 * @throws ReflectionException
1480
+	 */
1481
+	public function registrations($query_params = [])
1482
+	{
1483
+		return $this->get_many_related('Registration', $query_params);
1484
+	}
1485
+
1486
+
1487
+	/**
1488
+	 * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1489
+	 *
1490
+	 * @return int
1491
+	 * @throws EE_Error
1492
+	 * @throws ReflectionException
1493
+	 */
1494
+	public function update_tickets_sold()
1495
+	{
1496
+		$count_regs_for_this_ticket = $this->count_registrations(
1497
+			[
1498
+				[
1499
+					'STS_ID'      => EEM_Registration::status_id_approved,
1500
+					'REG_deleted' => 0,
1501
+				],
1502
+			]
1503
+		);
1504
+		$this->set_sold($count_regs_for_this_ticket);
1505
+		$this->save();
1506
+		return $count_regs_for_this_ticket;
1507
+	}
1508
+
1509
+
1510
+	/**
1511
+	 * Counts the registrations for this ticket
1512
+	 *
1513
+	 * @param array $query_params @see
1514
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1515
+	 * @return int
1516
+	 */
1517
+	public function count_registrations($query_params = [])
1518
+	{
1519
+		return $this->count_related('Registration', $query_params);
1520
+	}
1521
+
1522
+
1523
+	/**
1524
+	 * Implementation for EEI_Has_Icon interface method.
1525
+	 *
1526
+	 * @return string
1527
+	 * @see EEI_Visual_Representation for comments
1528
+	 */
1529
+	public function get_icon()
1530
+	{
1531
+		return '<span class="dashicons dashicons-tickets-alt"></span>';
1532
+	}
1533
+
1534
+
1535
+	/**
1536
+	 * Implementation of the EEI_Event_Relation interface method
1537
+	 *
1538
+	 * @return EE_Event
1539
+	 * @throws EE_Error
1540
+	 * @throws UnexpectedEntityException*@throws ReflectionException
1541
+	 * @see EEI_Event_Relation for comments
1542
+	 */
1543
+	public function get_related_event()
1544
+	{
1545
+		// get one datetime to use for getting the event
1546
+		$datetime = $this->first_datetime();
1547
+		if (! $datetime instanceof \EE_Datetime) {
1548
+			throw new UnexpectedEntityException(
1549
+				$datetime,
1550
+				'EE_Datetime',
1551
+				sprintf(
1552
+					esc_html__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1553
+					$this->name()
1554
+				)
1555
+			);
1556
+		}
1557
+		$event = $datetime->event();
1558
+		if (! $event instanceof \EE_Event) {
1559
+			throw new UnexpectedEntityException(
1560
+				$event,
1561
+				'EE_Event',
1562
+				sprintf(
1563
+					esc_html__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1564
+					$this->name()
1565
+				)
1566
+			);
1567
+		}
1568
+		return $event;
1569
+	}
1570
+
1571
+
1572
+	/**
1573
+	 * Implementation of the EEI_Event_Relation interface method
1574
+	 *
1575
+	 * @return string
1576
+	 * @throws UnexpectedEntityException
1577
+	 * @throws EE_Error*@throws ReflectionException
1578
+	 * @see EEI_Event_Relation for comments
1579
+	 */
1580
+	public function get_event_name()
1581
+	{
1582
+		$event = $this->get_related_event();
1583
+		return $event instanceof EE_Event ? $event->name() : '';
1584
+	}
1585
+
1586
+
1587
+	/**
1588
+	 * Implementation of the EEI_Event_Relation interface method
1589
+	 *
1590
+	 * @return int
1591
+	 * @throws UnexpectedEntityException
1592
+	 * @throws EE_Error*@throws ReflectionException
1593
+	 * @see EEI_Event_Relation for comments
1594
+	 */
1595
+	public function get_event_ID()
1596
+	{
1597
+		$event = $this->get_related_event();
1598
+		return $event instanceof EE_Event ? $event->ID() : 0;
1599
+	}
1600
+
1601
+
1602
+	/**
1603
+	 * This simply returns whether a ticket can be permanently deleted or not.
1604
+	 * The criteria for determining this is whether the ticket has any related registrations.
1605
+	 * If there are none then it can be permanently deleted.
1606
+	 *
1607
+	 * @return bool
1608
+	 */
1609
+	public function is_permanently_deleteable()
1610
+	{
1611
+		return $this->count_registrations() === 0;
1612
+	}
1613
+
1614
+
1615
+	/*******************************************************************
1616 1616
      ***********************  DEPRECATED METHODS  **********************
1617 1617
      *******************************************************************/
1618 1618
 
1619 1619
 
1620
-    /**
1621
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1622
-     * associated datetimes.
1623
-     *
1624
-     * @param int $qty
1625
-     * @return void
1626
-     * @throws EE_Error
1627
-     * @throws InvalidArgumentException
1628
-     * @throws InvalidDataTypeException
1629
-     * @throws InvalidInterfaceException
1630
-     * @throws ReflectionException
1631
-     * @deprecated 4.9.80.p
1632
-     */
1633
-    public function increase_sold($qty = 1)
1634
-    {
1635
-        EE_Error::doing_it_wrong(
1636
-            __FUNCTION__,
1637
-            esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1638
-            '4.9.80.p',
1639
-            '5.0.0.p'
1640
-        );
1641
-        $this->increaseSold($qty);
1642
-    }
1643
-
1644
-
1645
-    /**
1646
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1647
-     *
1648
-     * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1649
-     *                 Negative means to decreases old counts (and increase reserved counts).
1650
-     * @throws EE_Error
1651
-     * @throws InvalidArgumentException
1652
-     * @throws InvalidDataTypeException
1653
-     * @throws InvalidInterfaceException
1654
-     * @throws ReflectionException
1655
-     * @deprecated 4.9.80.p
1656
-     */
1657
-    protected function _increase_sold_for_datetimes($qty)
1658
-    {
1659
-        EE_Error::doing_it_wrong(
1660
-            __FUNCTION__,
1661
-            esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1662
-            '4.9.80.p',
1663
-            '5.0.0.p'
1664
-        );
1665
-        $this->increaseSoldForDatetimes($qty);
1666
-    }
1667
-
1668
-
1669
-    /**
1670
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1671
-     * DB and then updates the model objects.
1672
-     * Does not affect the reserved counts.
1673
-     *
1674
-     * @param int $qty
1675
-     * @return void
1676
-     * @throws EE_Error
1677
-     * @throws InvalidArgumentException
1678
-     * @throws InvalidDataTypeException
1679
-     * @throws InvalidInterfaceException
1680
-     * @throws ReflectionException
1681
-     * @deprecated 4.9.80.p
1682
-     */
1683
-    public function decrease_sold($qty = 1)
1684
-    {
1685
-        EE_Error::doing_it_wrong(
1686
-            __FUNCTION__,
1687
-            esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1688
-            '4.9.80.p',
1689
-            '5.0.0.p'
1690
-        );
1691
-        $this->decreaseSold($qty);
1692
-    }
1693
-
1694
-
1695
-    /**
1696
-     * Decreases sold on related datetimes
1697
-     *
1698
-     * @param int $qty
1699
-     * @return void
1700
-     * @throws EE_Error
1701
-     * @throws InvalidArgumentException
1702
-     * @throws InvalidDataTypeException
1703
-     * @throws InvalidInterfaceException
1704
-     * @throws ReflectionException
1705
-     * @deprecated 4.9.80.p
1706
-     */
1707
-    protected function _decrease_sold_for_datetimes($qty = 1)
1708
-    {
1709
-        EE_Error::doing_it_wrong(
1710
-            __FUNCTION__,
1711
-            esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1712
-            '4.9.80.p',
1713
-            '5.0.0.p'
1714
-        );
1715
-        $this->decreaseSoldForDatetimes($qty);
1716
-    }
1717
-
1718
-
1719
-    /**
1720
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1721
-     *
1722
-     * @param int    $qty
1723
-     * @param string $source
1724
-     * @return bool whether we successfully reserved the ticket or not.
1725
-     * @throws EE_Error
1726
-     * @throws InvalidArgumentException
1727
-     * @throws ReflectionException
1728
-     * @throws InvalidDataTypeException
1729
-     * @throws InvalidInterfaceException
1730
-     * @deprecated 4.9.80.p
1731
-     */
1732
-    public function increase_reserved($qty = 1, $source = 'unknown')
1733
-    {
1734
-        EE_Error::doing_it_wrong(
1735
-            __FUNCTION__,
1736
-            esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
1737
-            '4.9.80.p',
1738
-            '5.0.0.p'
1739
-        );
1740
-        return $this->increaseReserved($qty);
1741
-    }
1742
-
1743
-
1744
-    /**
1745
-     * Increases sold on related datetimes
1746
-     *
1747
-     * @param int $qty
1748
-     * @return boolean indicating success
1749
-     * @throws EE_Error
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws ReflectionException
1754
-     * @deprecated 4.9.80.p
1755
-     */
1756
-    protected function _increase_reserved_for_datetimes($qty = 1)
1757
-    {
1758
-        EE_Error::doing_it_wrong(
1759
-            __FUNCTION__,
1760
-            esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
1761
-            '4.9.80.p',
1762
-            '5.0.0.p'
1763
-        );
1764
-        return $this->increaseReservedForDatetimes($qty);
1765
-    }
1766
-
1767
-
1768
-    /**
1769
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1770
-     *
1771
-     * @param int    $qty
1772
-     * @param bool   $adjust_datetimes
1773
-     * @param string $source
1774
-     * @return void
1775
-     * @throws EE_Error
1776
-     * @throws InvalidArgumentException
1777
-     * @throws ReflectionException
1778
-     * @throws InvalidDataTypeException
1779
-     * @throws InvalidInterfaceException
1780
-     * @deprecated 4.9.80.p
1781
-     */
1782
-    public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1783
-    {
1784
-        EE_Error::doing_it_wrong(
1785
-            __FUNCTION__,
1786
-            esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
1787
-            '4.9.80.p',
1788
-            '5.0.0.p'
1789
-        );
1790
-        $this->decreaseReserved($qty);
1791
-    }
1792
-
1793
-
1794
-    /**
1795
-     * Decreases reserved on related datetimes
1796
-     *
1797
-     * @param int $qty
1798
-     * @return void
1799
-     * @throws EE_Error
1800
-     * @throws InvalidArgumentException
1801
-     * @throws ReflectionException
1802
-     * @throws InvalidDataTypeException
1803
-     * @throws InvalidInterfaceException
1804
-     * @deprecated 4.9.80.p
1805
-     */
1806
-    protected function _decrease_reserved_for_datetimes($qty = 1)
1807
-    {
1808
-        EE_Error::doing_it_wrong(
1809
-            __FUNCTION__,
1810
-            esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
1811
-            '4.9.80.p',
1812
-            '5.0.0.p'
1813
-        );
1814
-        $this->decreaseReservedForDatetimes($qty);
1815
-    }
1620
+	/**
1621
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1622
+	 * associated datetimes.
1623
+	 *
1624
+	 * @param int $qty
1625
+	 * @return void
1626
+	 * @throws EE_Error
1627
+	 * @throws InvalidArgumentException
1628
+	 * @throws InvalidDataTypeException
1629
+	 * @throws InvalidInterfaceException
1630
+	 * @throws ReflectionException
1631
+	 * @deprecated 4.9.80.p
1632
+	 */
1633
+	public function increase_sold($qty = 1)
1634
+	{
1635
+		EE_Error::doing_it_wrong(
1636
+			__FUNCTION__,
1637
+			esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1638
+			'4.9.80.p',
1639
+			'5.0.0.p'
1640
+		);
1641
+		$this->increaseSold($qty);
1642
+	}
1643
+
1644
+
1645
+	/**
1646
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1647
+	 *
1648
+	 * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1649
+	 *                 Negative means to decreases old counts (and increase reserved counts).
1650
+	 * @throws EE_Error
1651
+	 * @throws InvalidArgumentException
1652
+	 * @throws InvalidDataTypeException
1653
+	 * @throws InvalidInterfaceException
1654
+	 * @throws ReflectionException
1655
+	 * @deprecated 4.9.80.p
1656
+	 */
1657
+	protected function _increase_sold_for_datetimes($qty)
1658
+	{
1659
+		EE_Error::doing_it_wrong(
1660
+			__FUNCTION__,
1661
+			esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1662
+			'4.9.80.p',
1663
+			'5.0.0.p'
1664
+		);
1665
+		$this->increaseSoldForDatetimes($qty);
1666
+	}
1667
+
1668
+
1669
+	/**
1670
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1671
+	 * DB and then updates the model objects.
1672
+	 * Does not affect the reserved counts.
1673
+	 *
1674
+	 * @param int $qty
1675
+	 * @return void
1676
+	 * @throws EE_Error
1677
+	 * @throws InvalidArgumentException
1678
+	 * @throws InvalidDataTypeException
1679
+	 * @throws InvalidInterfaceException
1680
+	 * @throws ReflectionException
1681
+	 * @deprecated 4.9.80.p
1682
+	 */
1683
+	public function decrease_sold($qty = 1)
1684
+	{
1685
+		EE_Error::doing_it_wrong(
1686
+			__FUNCTION__,
1687
+			esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1688
+			'4.9.80.p',
1689
+			'5.0.0.p'
1690
+		);
1691
+		$this->decreaseSold($qty);
1692
+	}
1693
+
1694
+
1695
+	/**
1696
+	 * Decreases sold on related datetimes
1697
+	 *
1698
+	 * @param int $qty
1699
+	 * @return void
1700
+	 * @throws EE_Error
1701
+	 * @throws InvalidArgumentException
1702
+	 * @throws InvalidDataTypeException
1703
+	 * @throws InvalidInterfaceException
1704
+	 * @throws ReflectionException
1705
+	 * @deprecated 4.9.80.p
1706
+	 */
1707
+	protected function _decrease_sold_for_datetimes($qty = 1)
1708
+	{
1709
+		EE_Error::doing_it_wrong(
1710
+			__FUNCTION__,
1711
+			esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1712
+			'4.9.80.p',
1713
+			'5.0.0.p'
1714
+		);
1715
+		$this->decreaseSoldForDatetimes($qty);
1716
+	}
1717
+
1718
+
1719
+	/**
1720
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1721
+	 *
1722
+	 * @param int    $qty
1723
+	 * @param string $source
1724
+	 * @return bool whether we successfully reserved the ticket or not.
1725
+	 * @throws EE_Error
1726
+	 * @throws InvalidArgumentException
1727
+	 * @throws ReflectionException
1728
+	 * @throws InvalidDataTypeException
1729
+	 * @throws InvalidInterfaceException
1730
+	 * @deprecated 4.9.80.p
1731
+	 */
1732
+	public function increase_reserved($qty = 1, $source = 'unknown')
1733
+	{
1734
+		EE_Error::doing_it_wrong(
1735
+			__FUNCTION__,
1736
+			esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
1737
+			'4.9.80.p',
1738
+			'5.0.0.p'
1739
+		);
1740
+		return $this->increaseReserved($qty);
1741
+	}
1742
+
1743
+
1744
+	/**
1745
+	 * Increases sold on related datetimes
1746
+	 *
1747
+	 * @param int $qty
1748
+	 * @return boolean indicating success
1749
+	 * @throws EE_Error
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws ReflectionException
1754
+	 * @deprecated 4.9.80.p
1755
+	 */
1756
+	protected function _increase_reserved_for_datetimes($qty = 1)
1757
+	{
1758
+		EE_Error::doing_it_wrong(
1759
+			__FUNCTION__,
1760
+			esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
1761
+			'4.9.80.p',
1762
+			'5.0.0.p'
1763
+		);
1764
+		return $this->increaseReservedForDatetimes($qty);
1765
+	}
1766
+
1767
+
1768
+	/**
1769
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1770
+	 *
1771
+	 * @param int    $qty
1772
+	 * @param bool   $adjust_datetimes
1773
+	 * @param string $source
1774
+	 * @return void
1775
+	 * @throws EE_Error
1776
+	 * @throws InvalidArgumentException
1777
+	 * @throws ReflectionException
1778
+	 * @throws InvalidDataTypeException
1779
+	 * @throws InvalidInterfaceException
1780
+	 * @deprecated 4.9.80.p
1781
+	 */
1782
+	public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1783
+	{
1784
+		EE_Error::doing_it_wrong(
1785
+			__FUNCTION__,
1786
+			esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
1787
+			'4.9.80.p',
1788
+			'5.0.0.p'
1789
+		);
1790
+		$this->decreaseReserved($qty);
1791
+	}
1792
+
1793
+
1794
+	/**
1795
+	 * Decreases reserved on related datetimes
1796
+	 *
1797
+	 * @param int $qty
1798
+	 * @return void
1799
+	 * @throws EE_Error
1800
+	 * @throws InvalidArgumentException
1801
+	 * @throws ReflectionException
1802
+	 * @throws InvalidDataTypeException
1803
+	 * @throws InvalidInterfaceException
1804
+	 * @deprecated 4.9.80.p
1805
+	 */
1806
+	protected function _decrease_reserved_for_datetimes($qty = 1)
1807
+	{
1808
+		EE_Error::doing_it_wrong(
1809
+			__FUNCTION__,
1810
+			esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
1811
+			'4.9.80.p',
1812
+			'5.0.0.p'
1813
+		);
1814
+		$this->decreaseReservedForDatetimes($qty);
1815
+	}
1816 1816
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
     public function ticket_status($display = false, $remaining = null)
135 135
     {
136 136
         $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
137
-        if (! $remaining) {
137
+        if ( ! $remaining) {
138 138
             return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
139 139
         }
140 140
         if ($this->get('TKT_deleted')) {
@@ -259,13 +259,13 @@  discard block
 block discarded – undo
259 259
                 'DTT_EVT_start',
260 260
                 $dt_frmt
261 261
             ) : '';
262
-        $last_date  =
262
+        $last_date =
263 263
             $this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->get_i18n_datetime(
264 264
                 'DTT_EVT_end',
265 265
                 $dt_frmt
266 266
             ) : '';
267 267
 
268
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
268
+        return $first_date && $last_date ? $first_date.$conjunction.$last_date : '';
269 269
     }
270 270
 
271 271
 
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
      */
295 295
     public function datetimes($query_params = [])
296 296
     {
297
-        if (! isset($query_params['order_by'])) {
297
+        if ( ! isset($query_params['order_by'])) {
298 298
             $query_params['order_by']['DTT_order'] = 'ASC';
299 299
         }
300 300
         return $this->get_many_related('Datetime', $query_params);
@@ -339,7 +339,7 @@  discard block
 block discarded – undo
339 339
                 if (empty($tickets_sold['datetime'])) {
340 340
                     return $total;
341 341
                 }
342
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
342
+                if ( ! empty($dtt_id) && ! isset($tickets_sold['datetime'][$dtt_id])) {
343 343
                     EE_Error::add_error(
344 344
                         esc_html__(
345 345
                             '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?',
@@ -351,7 +351,7 @@  discard block
 block discarded – undo
351 351
                     );
352 352
                     return $total;
353 353
                 }
354
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
354
+                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][$dtt_id];
355 355
                 break;
356 356
             default:
357 357
                 return $total;
@@ -370,9 +370,9 @@  discard block
 block discarded – undo
370 370
     {
371 371
         $datetimes    = $this->get_many_related('Datetime');
372 372
         $tickets_sold = [];
373
-        if (! empty($datetimes)) {
373
+        if ( ! empty($datetimes)) {
374 374
             foreach ($datetimes as $datetime) {
375
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
375
+                $tickets_sold['datetime'][$datetime->ID()] = $datetime->get('DTT_sold');
376 376
             }
377 377
         }
378 378
         // Tickets sold
@@ -970,7 +970,7 @@  discard block
 block discarded – undo
970 970
                 'TKT_qty',
971 971
                 $qty
972 972
             );
973
-            if (! $success) {
973
+            if ( ! $success) {
974 974
                 // The datetimes were successfully bumped, but not the
975 975
                 // ticket. So we need to manually rollback the datetimes.
976 976
                 $this->decreaseReservedForDatetimes($qty);
@@ -1439,7 +1439,7 @@  discard block
 block discarded – undo
1439 1439
         foreach ($this->datetimes() as $datetime) {
1440 1440
             $times[] = $datetime->start_date_and_time();
1441 1441
         }
1442
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1442
+        return $this->name().' @ '.implode(', ', $times).' for '.$this->pretty_price();
1443 1443
     }
1444 1444
 
1445 1445
 
@@ -1544,7 +1544,7 @@  discard block
 block discarded – undo
1544 1544
     {
1545 1545
         // get one datetime to use for getting the event
1546 1546
         $datetime = $this->first_datetime();
1547
-        if (! $datetime instanceof \EE_Datetime) {
1547
+        if ( ! $datetime instanceof \EE_Datetime) {
1548 1548
             throw new UnexpectedEntityException(
1549 1549
                 $datetime,
1550 1550
                 'EE_Datetime',
@@ -1555,7 +1555,7 @@  discard block
 block discarded – undo
1555 1555
             );
1556 1556
         }
1557 1557
         $event = $datetime->event();
1558
-        if (! $event instanceof \EE_Event) {
1558
+        if ( ! $event instanceof \EE_Event) {
1559 1559
             throw new UnexpectedEntityException(
1560 1560
                 $event,
1561 1561
                 'EE_Event',
Please login to merge, or discard this patch.