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