Completed
Branch BUG/11405/ticket-reservations (9b2ea4)
by
unknown
27:02 queued 13:30
created
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 2 patches
Indentation   +1043 added lines, -1043 removed lines patch added patch discarded remove patch
@@ -23,1050 +23,1050 @@
 block discarded – undo
23 23
 class EED_Ticket_Sales_Monitor extends EED_Module
24 24
 {
25 25
 
26
-    const debug = false;    //	true false
27
-
28
-    /**
29
-     * an array of raw ticket data from EED_Ticket_Selector
30
-     *
31
-     * @var array $ticket_selections
32
-     */
33
-    protected $ticket_selections = array();
34
-
35
-    /**
36
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
37
-     * according to how they are displayed in the actual Ticket_Selector
38
-     * this tracks the current row being processed
39
-     *
40
-     * @var int $current_row
41
-     */
42
-    protected $current_row = 0;
43
-
44
-    /**
45
-     * an array for tracking names of tickets that have sold out
46
-     *
47
-     * @var array $sold_out_tickets
48
-     */
49
-    protected $sold_out_tickets = array();
50
-
51
-    /**
52
-     * an array for tracking names of tickets that have had their quantities reduced
53
-     *
54
-     * @var array $decremented_tickets
55
-     */
56
-    protected $decremented_tickets = array();
57
-
58
-
59
-
60
-    /**
61
-     * set_hooks - for hooking into EE Core, other modules, etc
62
-     *
63
-     * @return    void
64
-     */
65
-    public static function set_hooks()
66
-    {
67
-        // release tickets for expired carts
68
-        add_action(
69
-            'EED_Ticket_Selector__process_ticket_selections__before',
70
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
71
-            1
72
-        );
73
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
74
-        add_filter(
75
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
76
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
77
-            20,
78
-            3
79
-        );
80
-        // add notices for sold out tickets
81
-        add_action(
82
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
83
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
84
-            10
85
-        );
86
-        // handle ticket quantities adjusted in cart
87
-        //add_action(
88
-        //	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
89
-        //	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
90
-        //	10, 2
91
-        //);
92
-        // handle tickets deleted from cart
93
-        add_action(
94
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
95
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
96
-            10,
97
-            2
98
-        );
99
-        // handle emptied carts
100
-        add_action(
101
-            'AHEE__EE_Session__reset_cart__before_reset',
102
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
103
-            10,
104
-            1
105
-        );
106
-        add_action(
107
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
108
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
109
-            10,
110
-            1
111
-        );
112
-        // handle cancelled registrations
113
-        add_action(
114
-            'AHEE__EE_Session__reset_checkout__before_reset',
115
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
116
-            10,
117
-            1
118
-        );
119
-        // cron tasks
120
-        add_action(
121
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
122
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
123
-            10,
124
-            1
125
-        );
126
-        add_action(
127
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
128
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
129
-            10,
130
-            1
131
-        );
132
-        add_action(
133
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
134
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
135
-            10,
136
-            1
137
-        );
138
-    }
139
-
140
-
141
-
142
-    /**
143
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
144
-     *
145
-     * @return void
146
-     */
147
-    public static function set_hooks_admin()
148
-    {
149
-        EED_Ticket_Sales_Monitor::set_hooks();
150
-    }
151
-
152
-
153
-
154
-    /**
155
-     * @return EED_Ticket_Sales_Monitor|EED_Module
156
-     */
157
-    public static function instance()
158
-    {
159
-        return parent::get_instance(__CLASS__);
160
-    }
161
-
162
-
163
-
164
-    /**
165
-     * @param WP_Query $WP_Query
166
-     * @return    void
167
-     */
168
-    public function run($WP_Query)
169
-    {
170
-    }
171
-
172
-
173
-
174
-    /********************************** PRE_TICKET_SALES  **********************************/
175
-
176
-
177
-
178
-    /**
179
-     * Retrieves grand totals from the line items that have no TXN ID
180
-     * and timestamps less than the current time minus the session lifespan.
181
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
182
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
183
-     *
184
-     * @return void
185
-     * @throws DomainException
186
-     * @throws EE_Error
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidInterfaceException
190
-     * @throws UnexpectedEntityException
191
-     */
192
-    public static function release_tickets_for_expired_carts()
193
-    {
194
-        do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
195
-        $expired_ticket_IDs      = array();
196
-        $valid_ticket_line_items = array();
197
-        $total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
198
-        if (empty($total_line_items)) {
199
-            do_action(
200
-                'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
201
-                $total_line_items,
202
-                $valid_ticket_line_items,
203
-                $expired_ticket_IDs
204
-            );
205
-            return;
206
-        }
207
-        $expired = current_time('timestamp') - EE_Registry::instance()->SSN->lifespan();
208
-        foreach ($total_line_items as $total_line_item) {
209
-            /** @var EE_Line_Item $total_line_item */
210
-            $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
211
-            foreach ($ticket_line_items as $ticket_line_item) {
212
-                if (! $ticket_line_item instanceof EE_Line_Item) {
213
-                    continue;
214
-                }
215
-                if ($total_line_item->timestamp(true) <= $expired) {
216
-                    $expired_ticket_IDs[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item->OBJ_ID();
217
-                } else {
218
-                    $valid_ticket_line_items[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item;
219
-                }
220
-            }
221
-        }
222
-        if (! empty($expired_ticket_IDs)) {
223
-            EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
224
-                \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
225
-                $valid_ticket_line_items,
226
-                __FUNCTION__
227
-            );
228
-            // let's get rid of expired line items so that they can't interfere with tracking
229
-            add_action(
230
-                'shutdown',
231
-                array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
232
-                999
233
-            );
234
-        }
235
-        do_action(
236
-            'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
237
-            $total_line_items,
238
-            $valid_ticket_line_items,
239
-            $expired_ticket_IDs
240
-        );
241
-    }
242
-
243
-
244
-
245
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
246
-
247
-
248
-
249
-    /**
250
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
251
-     *
252
-     * @param int       $qty
253
-     * @param EE_Ticket $ticket
254
-     * @return bool
255
-     * @throws UnexpectedEntityException
256
-     * @throws EE_Error
257
-     */
258
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
259
-    {
260
-        $qty = absint($qty);
261
-        if ($qty > 0) {
262
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
263
-        }
264
-        if (self::debug) {
265
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
266
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
267
-        }
268
-        return $qty;
269
-    }
270
-
271
-
272
-
273
-    /**
274
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
275
-     *
276
-     * @param   EE_Ticket $ticket
277
-     * @param int         $qty
278
-     * @return int
279
-     * @throws UnexpectedEntityException
280
-     * @throws EE_Error
281
-     */
282
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
283
-    {
284
-        if (self::debug) {
285
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
286
-        }
287
-        if (! $ticket instanceof EE_Ticket) {
288
-            return 0;
289
-        }
290
-        if (self::debug) {
291
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
292
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
293
-        }
294
-        $ticket->refresh_from_db();
295
-        // first let's determine the ticket availability based on sales
296
-        $available = $ticket->qty('saleable');
297
-        if (self::debug) {
298
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
299
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
300
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
301
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
302
-            echo '<br /> . . . available: ' . $available;
303
-        }
304
-        if ($available < 1) {
305
-            $this->_ticket_sold_out($ticket);
306
-            return 0;
307
-        }
308
-        if (self::debug) {
309
-            echo '<br /> . . . qty: ' . $qty;
310
-        }
311
-        if ($available < $qty) {
312
-            $qty = $available;
313
-            if (self::debug) {
314
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
315
-            }
316
-            $this->_ticket_quantity_decremented($ticket);
317
-        }
318
-        $this->_reserve_ticket($ticket, $qty);
319
-        return $qty;
320
-    }
321
-
322
-
323
-
324
-    /**
325
-     * increments ticket reserved based on quantity passed
326
-     *
327
-     * @param    EE_Ticket $ticket
328
-     * @param int          $quantity
329
-     * @return bool
330
-     * @throws EE_Error
331
-     */
332
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
333
-    {
334
-        if (self::debug) {
335
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
336
-        }
337
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
338
-        return $ticket->save();
339
-    }
340
-
341
-
342
-
343
-    /**
344
-     * @param  EE_Ticket $ticket
345
-     * @param  int       $quantity
346
-     * @return bool
347
-     * @throws EE_Error
348
-     */
349
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
350
-    {
351
-        if (self::debug) {
352
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
353
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
354
-        }
355
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
356
-        if (self::debug) {
357
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
358
-        }
359
-        return $ticket->save() ? 1 : 0;
360
-    }
361
-
362
-
363
-
364
-    /**
365
-     * removes quantities within the ticket selector based on zero ticket availability
366
-     *
367
-     * @param    EE_Ticket $ticket
368
-     * @return    void
369
-     * @throws UnexpectedEntityException
370
-     * @throws EE_Error
371
-     */
372
-    protected function _ticket_sold_out(EE_Ticket $ticket)
373
-    {
374
-        if (self::debug) {
375
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
376
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
377
-        }
378
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
379
-    }
380
-
381
-
382
-
383
-    /**
384
-     * adjusts quantities within the ticket selector based on decreased ticket availability
385
-     *
386
-     * @param    EE_Ticket $ticket
387
-     * @return void
388
-     * @throws UnexpectedEntityException
389
-     * @throws EE_Error
390
-     */
391
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
392
-    {
393
-        if (self::debug) {
394
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
395
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
396
-        }
397
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
398
-    }
399
-
400
-
401
-
402
-    /**
403
-     * builds string out of ticket and event name
404
-     *
405
-     * @param    EE_Ticket $ticket
406
-     * @return string
407
-     * @throws UnexpectedEntityException
408
-     * @throws EE_Error
409
-     */
410
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
411
-    {
412
-        $event = $ticket->get_related_event();
413
-        if ($event instanceof EE_Event) {
414
-            $ticket_name = sprintf(
415
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
416
-                $ticket->name(),
417
-                $event->name()
418
-            );
419
-        } else {
420
-            $ticket_name = $ticket->name();
421
-        }
422
-        return $ticket_name;
423
-    }
424
-
425
-
426
-
427
-    /********************************** EVENT CART  **********************************/
428
-
429
-
430
-
431
-    /**
432
-     * releases or reserves ticket(s) based on quantity passed
433
-     *
434
-     * @param  EE_Line_Item $line_item
435
-     * @param  int          $quantity
436
-     * @return void
437
-     * @throws EE_Error
438
-     * @throws InvalidArgumentException
439
-     * @throws InvalidDataTypeException
440
-     * @throws InvalidInterfaceException
441
-     */
442
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
443
-    {
444
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
445
-        if ($ticket instanceof EE_Ticket) {
446
-            $ticket->add_extra_meta(
447
-                EE_Ticket::META_KEY_TICKET_RESERVATIONS,
448
-                __LINE__ . ') ' . __METHOD__ . '()'
449
-            );
450
-            if ($quantity > 0) {
451
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
452
-            } else {
453
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
454
-            }
455
-        }
456
-    }
457
-
458
-
459
-
460
-    /**
461
-     * releases reserved ticket(s) based on quantity passed
462
-     *
463
-     * @param  EE_Ticket $ticket
464
-     * @param  int       $quantity
465
-     * @return void
466
-     * @throws EE_Error
467
-     */
468
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
469
-    {
470
-        $ticket->add_extra_meta(
471
-            EE_Ticket::META_KEY_TICKET_RESERVATIONS,
472
-            __LINE__ . ') ' . __METHOD__ . '()'
473
-        );
474
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
475
-    }
476
-
477
-
478
-
479
-    /********************************** POST_NOTICES  **********************************/
480
-
481
-
482
-
483
-    /**
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws ReflectionException
488
-     * @throws InvalidDataTypeException
489
-     * @throws InvalidInterfaceException
490
-     */
491
-    public static function post_notices()
492
-    {
493
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
494
-    }
495
-
496
-
497
-
498
-    /**
499
-     * @return void
500
-     * @throws EE_Error
501
-     * @throws InvalidArgumentException
502
-     * @throws ReflectionException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     */
506
-    protected function _post_notices()
507
-    {
508
-        if (self::debug) {
509
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
510
-        }
511
-        $refresh_msg    = '';
512
-        $none_added_msg = '';
513
-        if (defined('DOING_AJAX') && DOING_AJAX) {
514
-            $refresh_msg    = __(
515
-                'Please refresh the page to view updated ticket quantities.',
516
-                'event_espresso'
517
-            );
518
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
519
-        }
520
-        if (! empty($this->sold_out_tickets)) {
521
-            EE_Error::add_attention(
522
-                sprintf(
523
-                    apply_filters(
524
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
525
-                        __(
526
-                            'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
527
-                            'event_espresso'
528
-                        )
529
-                    ),
530
-                    '<br />',
531
-                    implode('<br />', $this->sold_out_tickets),
532
-                    $none_added_msg,
533
-                    $refresh_msg
534
-                )
535
-            );
536
-            // alter code flow in the Ticket Selector for better UX
537
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
538
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
539
-            $this->sold_out_tickets = array();
540
-            // and reset the cart
541
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
542
-        }
543
-        if (! empty($this->decremented_tickets)) {
544
-            EE_Error::add_attention(
545
-                sprintf(
546
-                    apply_filters(
547
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
548
-                        __(
549
-                            'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
550
-                            'event_espresso'
551
-                        )
552
-                    ),
553
-                    '<br />',
554
-                    implode('<br />', $this->decremented_tickets),
555
-                    $none_added_msg,
556
-                    $refresh_msg
557
-                )
558
-            );
559
-            $this->decremented_tickets = array();
560
-        }
561
-    }
562
-
563
-
564
-
565
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
566
-
567
-
568
-
569
-    /**
570
-     * releases reserved tickets for all registrations of an EE_Transaction
571
-     * by default, will NOT release tickets for finalized transactions
572
-     *
573
-     * @param    EE_Transaction $transaction
574
-     * @return int
575
-     * @throws EE_Error
576
-     * @throws InvalidSessionDataException
577
-     */
578
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
579
-    {
580
-        if (self::debug) {
581
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
582
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
583
-            echo '<br /> . TXN status_ID: ' . $transaction->status_ID();
584
-        }
585
-        // check if 'finalize_registration' step has been completed...
586
-        $finalized = $transaction->reg_step_completed('finalize_registration');
587
-        if (self::debug) {
588
-            // DEBUG LOG
589
-            EEH_Debug_Tools::log(
590
-                __CLASS__,
591
-                __FUNCTION__,
592
-                __LINE__,
593
-                array('finalized' => $finalized),
594
-                false,
595
-                'EE_Transaction: ' . $transaction->ID()
596
-            );
597
-        }
598
-        // how many tickets were released
599
-        $count = 0;
600
-        if (self::debug) {
601
-            echo '<br /> . . . TXN finalized: ' . $finalized;
602
-        }
603
-        $release_tickets_with_TXN_status = array(
604
-            EEM_Transaction::failed_status_code,
605
-            EEM_Transaction::abandoned_status_code,
606
-            EEM_Transaction::incomplete_status_code,
607
-        );
608
-        $events = array();
609
-        // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
610
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
611
-            // cancel any reserved tickets for registrations that were not approved
612
-            $registrations = $transaction->registrations();
613
-            if (self::debug) {
614
-                echo '<br /> . . . # registrations: ' . count($registrations);
615
-                $reg    = reset($registrations);
616
-                $ticket = $reg->ticket();
617
-                if ($ticket instanceof EE_Ticket) {
618
-                    $ticket->add_extra_meta(
619
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
620
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
621
-                    );
622
-                }
623
-            }
624
-            if (! empty($registrations)) {
625
-                foreach ($registrations as $registration) {
626
-                    if (
627
-                        $registration instanceof EE_Registration
628
-                        && $this->_release_reserved_ticket_for_registration($registration, $transaction)
629
-                    ) {
630
-                        $count++;
631
-                        $events[ $registration->event_ID() ] = $registration->event();
632
-                    }
633
-                }
634
-            }
635
-        }
636
-        if ($events !== array()) {
637
-            foreach ($events as $event) {
638
-                /** @var EE_Event $event */
639
-                $event->perform_sold_out_status_check();
640
-            }
641
-        }
642
-        return $count;
643
-    }
644
-
645
-
646
-
647
-    /**
648
-     * releases reserved tickets for an EE_Registration
649
-     * by default, will NOT release tickets for APPROVED registrations
650
-     *
651
-     * @param EE_Registration $registration
652
-     * @param EE_Transaction  $transaction
653
-     * @return int
654
-     * @throws EE_Error
655
-     */
656
-    protected function _release_reserved_ticket_for_registration(
657
-        EE_Registration $registration,
658
-        EE_Transaction $transaction
659
-    ) {
660
-        $STS_ID = $transaction->status_ID();
661
-        if (self::debug) {
662
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
663
-            echo '<br /> . . registration->ID: ' . $registration->ID();
664
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
665
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
666
-        }
667
-        if (
668
-            // release Tickets for Failed Transactions and Abandoned Transactions
669
-            $STS_ID === EEM_Transaction::failed_status_code
670
-            || $STS_ID === EEM_Transaction::abandoned_status_code
671
-            || (
672
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
673
-                $STS_ID === EEM_Transaction::incomplete_status_code
674
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
675
-            )
676
-        ) {
677
-            if (self::debug) {
678
-                echo '<br /><br /> . . RELEASE RESERVED TICKET';
679
-                $rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
680
-                echo '<br /> . . . registration HAS_RESERVED_TICKET_KEY: ';
681
-                var_dump($rsrvd);
682
-            }
683
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
684
-            return 1;
685
-        }
686
-        return 0;
687
-    }
688
-
689
-
690
-
691
-    /********************************** SESSION_CART_RESET  **********************************/
692
-
693
-
694
-
695
-    /**
696
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
697
-     *
698
-     * @param EE_Session $session
699
-     * @return void
700
-     * @throws EE_Error
701
-     * @throws InvalidArgumentException
702
-     * @throws ReflectionException
703
-     * @throws InvalidDataTypeException
704
-     * @throws InvalidInterfaceException
705
-     */
706
-    public static function session_cart_reset(EE_Session $session)
707
-    {
708
-        if (self::debug) {
709
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
710
-        }
711
-        // first check of the session has a valid Checkout object
712
-        $checkout = $session->checkout();
713
-        if ($checkout instanceof EE_Checkout) {
714
-            // and use that to clear ticket reservations because it will update the associated registration meta data
715
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
716
-            return;
717
-        }
718
-        $cart = $session->cart();
719
-        if ($cart instanceof EE_Cart) {
720
-            if (self::debug) {
721
-                echo '<br /><br /> cart instance of EE_Cart: ';
722
-            }
723
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
724
-        } else {
725
-            if (self::debug) {
726
-                echo '<br /><br /> invalid EE_Cart: ';
727
-                var_export($cart, true);
728
-            }
729
-        }
730
-    }
731
-
732
-
733
-
734
-    /**
735
-     * releases reserved tickets in the EE_Cart
736
-     *
737
-     * @param EE_Cart $cart
738
-     * @return void
739
-     * @throws EE_Error
740
-     * @throws InvalidArgumentException
741
-     * @throws ReflectionException
742
-     * @throws InvalidDataTypeException
743
-     * @throws InvalidInterfaceException
744
-     */
745
-    protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
746
-    {
747
-        if (self::debug) {
748
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
749
-        }
750
-        EE_Registry::instance()->load_helper('Line_Item');
751
-        $ticket_line_items = $cart->get_tickets();
752
-        if (empty($ticket_line_items)) {
753
-            return;
754
-        }
755
-        foreach ($ticket_line_items as $ticket_line_item) {
756
-            if (self::debug) {
757
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
758
-            }
759
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
760
-                if (self::debug) {
761
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
762
-                }
763
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
764
-                if ($ticket instanceof EE_Ticket) {
765
-                    if (self::debug) {
766
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
767
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
768
-                    }
769
-                    $ticket->add_extra_meta(
770
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
771
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
772
-                    );
773
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
774
-                }
775
-            }
776
-        }
777
-        if (self::debug) {
778
-            echo '<br /><br /> RESET COMPLETED ';
779
-        }
780
-    }
781
-
782
-
783
-
784
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
785
-
786
-
787
-
788
-    /**
789
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
790
-     *
791
-     * @param EE_Session $session
792
-     * @return void
793
-     * @throws EE_Error
794
-     * @throws InvalidSessionDataException
795
-     */
796
-    public static function session_checkout_reset(EE_Session $session)
797
-    {
798
-        $checkout = $session->checkout();
799
-        if ($checkout instanceof EE_Checkout) {
800
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
801
-        }
802
-    }
803
-
804
-
805
-
806
-    /**
807
-     * releases reserved tickets for the EE_Checkout->transaction
808
-     *
809
-     * @param EE_Checkout $checkout
810
-     * @return void
811
-     * @throws EE_Error
812
-     * @throws InvalidSessionDataException
813
-     */
814
-    protected function _session_checkout_reset(EE_Checkout $checkout)
815
-    {
816
-        if (self::debug) {
817
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
818
-        }
819
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
820
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
821
-            return;
822
-        }
823
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
824
-    }
825
-
826
-
827
-
828
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
829
-
830
-
831
-
832
-    /**
833
-     * @param    EE_Session $session
834
-     * @return    void
835
-     */
836
-    public static function session_expired_reset(EE_Session $session)
837
-    {
838
-    }
839
-
840
-
841
-
842
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
843
-
844
-
845
-
846
-    /**
847
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
848
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
849
-     *
850
-     * @param EE_Transaction $transaction
851
-     * @return void
852
-     * @throws EE_Error
853
-     * @throws InvalidSessionDataException
854
-     */
855
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
856
-    {
857
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
858
-        if ($transaction->is_free() || $transaction->paid() > 0) {
859
-            if (self::debug) {
860
-                // DEBUG LOG
861
-                EEH_Debug_Tools::log(
862
-                    __CLASS__,
863
-                    __FUNCTION__,
864
-                    __LINE__,
865
-                    array($transaction),
866
-                    false,
867
-                    'EE_Transaction: ' . $transaction->ID()
868
-                );
869
-            }
870
-            return;
871
-        }
872
-        // have their been any successful payments made ?
873
-        $payments = $transaction->payments();
874
-        foreach ($payments as $payment) {
875
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
876
-                if (self::debug) {
877
-                    // DEBUG LOG
878
-                    EEH_Debug_Tools::log(
879
-                        __CLASS__,
880
-                        __FUNCTION__,
881
-                        __LINE__,
882
-                        array($payment),
883
-                        false,
884
-                        'EE_Transaction: ' . $transaction->ID()
885
-                    );
886
-                }
887
-                return;
888
-            }
889
-        }
890
-        // since you haven't even attempted to pay for your ticket...
891
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
892
-    }
893
-
894
-
895
-
896
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
897
-
898
-
899
-
900
-    /**
901
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
902
-     *
903
-     * @param EE_Transaction $transaction
904
-     * @return void
905
-     * @throws EE_Error
906
-     * @throws InvalidSessionDataException
907
-     */
908
-    public static function process_failed_transactions(EE_Transaction $transaction)
909
-    {
910
-        // since you haven't even attempted to pay for your ticket...
911
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
912
-    }
913
-
914
-
915
-
916
-    /********************************** RESET RESERVATION COUNTS  *********************************/
917
-
918
-
919
-
920
-    /**
921
-     * Resets all ticket and datetime reserved counts to zero
922
-     * Tickets that are currently associated with a Transaction that is in progress
923
-     *
924
-     * @throws EE_Error
925
-     * @throws DomainException
926
-     * @throws InvalidDataTypeException
927
-     * @throws InvalidInterfaceException
928
-     * @throws InvalidArgumentException
929
-     * @throws UnexpectedEntityException
930
-     */
931
-    public static function reset_reservation_counts()
932
-    {
933
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
934
-        $valid_reserved_tickets = array();
935
-        /** @var EE_Transaction[] $transactions_not_in_progress */
936
-        $transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
937
-        foreach ($transactions_not_in_progress as $transaction) {
938
-            // if this TXN has been fully completed, then skip it
939
-            if ($transaction->reg_step_completed('finalize_registration')) {
940
-                continue;
941
-            }
942
-            $total_line_item = $transaction->total_line_item();
943
-            // $transaction_in_progress->line
944
-            if (! $total_line_item instanceof EE_Line_Item) {
945
-                throw new DomainException(
946
-                    esc_html__(
947
-                        'Transaction does not have a valid Total Line Item associated with it.',
948
-                        'event_espresso'
949
-                    )
950
-                );
951
-            }
952
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
953
-                $total_line_item
954
-            );
955
-        }
956
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
957
-        foreach ($total_line_items as $total_line_item) {
958
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
959
-                $total_line_item
960
-            );
961
-        }
962
-        $tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
963
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
964
-            $tickets_with_reservations,
965
-            $valid_reserved_tickets,
966
-            __FUNCTION__
967
-        );
968
-    }
969
-
970
-
971
-
972
-    /**
973
-     * @param EE_Line_Item $total_line_item
974
-     * @return EE_Line_Item[]
975
-     */
976
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
977
-    {
978
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
979
-        $valid_reserved_tickets = array();
980
-        $ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
981
-        foreach ($ticket_line_items as $ticket_line_item) {
982
-            if ($ticket_line_item instanceof EE_Line_Item) {
983
-                $valid_reserved_tickets[] = $ticket_line_item;
984
-            }
985
-        }
986
-        return $valid_reserved_tickets;
987
-    }
988
-
989
-
990
-
991
-    /**
992
-     * @param EE_Ticket[]    $tickets_with_reservations
993
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
994
-     * @return int
995
-     * @throws UnexpectedEntityException
996
-     * @throws DomainException
997
-     * @throws EE_Error
998
-     */
999
-    private static function release_reservations_for_tickets(
1000
-        array $tickets_with_reservations,
1001
-        array $valid_reserved_ticket_line_items = array(),
1002
-        $source
1003
-    ) {
1004
-        $total_tickets_released = 0;
1005
-        $sold_out_events = array();
1006
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
1007
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1008
-                continue;
1009
-            }
1010
-            $reserved_qty = $ticket_with_reservations->reserved();
1011
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1012
-                if (
1013
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
1014
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1015
-                ) {
1016
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1017
-                }
1018
-            }
1019
-            if ($reserved_qty > 0) {
1020
-                $ticket_with_reservations->add_extra_meta(
1021
-                    EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1022
-                    __LINE__ . ') ' . $source . '()'
1023
-                );
1024
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1025
-                $ticket_with_reservations->save();
1026
-                $total_tickets_released += $reserved_qty;
1027
-                $event = $ticket_with_reservations->get_related_event();
1028
-                // track sold out events
1029
-                if ($event instanceof EE_Event && $event->is_sold_out()) {
1030
-                    $sold_out_events[] = $event;
1031
-                }
1032
-            }
1033
-        }
1034
-        // double check whether sold out events should remain sold out after releasing tickets
1035
-        if($sold_out_events !== array()){
1036
-            foreach ($sold_out_events as $sold_out_event) {
1037
-                /** @var EE_Event $sold_out_event */
1038
-                $sold_out_event->perform_sold_out_status_check();
1039
-            }
1040
-        }
1041
-        return $total_tickets_released;
1042
-    }
1043
-
1044
-
1045
-
1046
-    /********************************** SHUTDOWN  **********************************/
1047
-
1048
-
1049
-
1050
-    /**
1051
-     * @return false|int
1052
-     * @throws EE_Error
1053
-     * @throws InvalidArgumentException
1054
-     * @throws InvalidDataTypeException
1055
-     * @throws InvalidInterfaceException
1056
-     */
1057
-    public static function clear_expired_line_items_with_no_transaction()
1058
-    {
1059
-        /** @type WPDB $wpdb */
1060
-        global $wpdb;
1061
-        return $wpdb->query(
1062
-            $wpdb->prepare(
1063
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
26
+	const debug = false;    //	true false
27
+
28
+	/**
29
+	 * an array of raw ticket data from EED_Ticket_Selector
30
+	 *
31
+	 * @var array $ticket_selections
32
+	 */
33
+	protected $ticket_selections = array();
34
+
35
+	/**
36
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
37
+	 * according to how they are displayed in the actual Ticket_Selector
38
+	 * this tracks the current row being processed
39
+	 *
40
+	 * @var int $current_row
41
+	 */
42
+	protected $current_row = 0;
43
+
44
+	/**
45
+	 * an array for tracking names of tickets that have sold out
46
+	 *
47
+	 * @var array $sold_out_tickets
48
+	 */
49
+	protected $sold_out_tickets = array();
50
+
51
+	/**
52
+	 * an array for tracking names of tickets that have had their quantities reduced
53
+	 *
54
+	 * @var array $decremented_tickets
55
+	 */
56
+	protected $decremented_tickets = array();
57
+
58
+
59
+
60
+	/**
61
+	 * set_hooks - for hooking into EE Core, other modules, etc
62
+	 *
63
+	 * @return    void
64
+	 */
65
+	public static function set_hooks()
66
+	{
67
+		// release tickets for expired carts
68
+		add_action(
69
+			'EED_Ticket_Selector__process_ticket_selections__before',
70
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
71
+			1
72
+		);
73
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
74
+		add_filter(
75
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
76
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
77
+			20,
78
+			3
79
+		);
80
+		// add notices for sold out tickets
81
+		add_action(
82
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
83
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
84
+			10
85
+		);
86
+		// handle ticket quantities adjusted in cart
87
+		//add_action(
88
+		//	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
89
+		//	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
90
+		//	10, 2
91
+		//);
92
+		// handle tickets deleted from cart
93
+		add_action(
94
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
95
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
96
+			10,
97
+			2
98
+		);
99
+		// handle emptied carts
100
+		add_action(
101
+			'AHEE__EE_Session__reset_cart__before_reset',
102
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
103
+			10,
104
+			1
105
+		);
106
+		add_action(
107
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
108
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
109
+			10,
110
+			1
111
+		);
112
+		// handle cancelled registrations
113
+		add_action(
114
+			'AHEE__EE_Session__reset_checkout__before_reset',
115
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
116
+			10,
117
+			1
118
+		);
119
+		// cron tasks
120
+		add_action(
121
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
122
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
123
+			10,
124
+			1
125
+		);
126
+		add_action(
127
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
128
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
129
+			10,
130
+			1
131
+		);
132
+		add_action(
133
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
134
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
135
+			10,
136
+			1
137
+		);
138
+	}
139
+
140
+
141
+
142
+	/**
143
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
144
+	 *
145
+	 * @return void
146
+	 */
147
+	public static function set_hooks_admin()
148
+	{
149
+		EED_Ticket_Sales_Monitor::set_hooks();
150
+	}
151
+
152
+
153
+
154
+	/**
155
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
156
+	 */
157
+	public static function instance()
158
+	{
159
+		return parent::get_instance(__CLASS__);
160
+	}
161
+
162
+
163
+
164
+	/**
165
+	 * @param WP_Query $WP_Query
166
+	 * @return    void
167
+	 */
168
+	public function run($WP_Query)
169
+	{
170
+	}
171
+
172
+
173
+
174
+	/********************************** PRE_TICKET_SALES  **********************************/
175
+
176
+
177
+
178
+	/**
179
+	 * Retrieves grand totals from the line items that have no TXN ID
180
+	 * and timestamps less than the current time minus the session lifespan.
181
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
182
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
183
+	 *
184
+	 * @return void
185
+	 * @throws DomainException
186
+	 * @throws EE_Error
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidInterfaceException
190
+	 * @throws UnexpectedEntityException
191
+	 */
192
+	public static function release_tickets_for_expired_carts()
193
+	{
194
+		do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
195
+		$expired_ticket_IDs      = array();
196
+		$valid_ticket_line_items = array();
197
+		$total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
198
+		if (empty($total_line_items)) {
199
+			do_action(
200
+				'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
201
+				$total_line_items,
202
+				$valid_ticket_line_items,
203
+				$expired_ticket_IDs
204
+			);
205
+			return;
206
+		}
207
+		$expired = current_time('timestamp') - EE_Registry::instance()->SSN->lifespan();
208
+		foreach ($total_line_items as $total_line_item) {
209
+			/** @var EE_Line_Item $total_line_item */
210
+			$ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
211
+			foreach ($ticket_line_items as $ticket_line_item) {
212
+				if (! $ticket_line_item instanceof EE_Line_Item) {
213
+					continue;
214
+				}
215
+				if ($total_line_item->timestamp(true) <= $expired) {
216
+					$expired_ticket_IDs[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item->OBJ_ID();
217
+				} else {
218
+					$valid_ticket_line_items[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item;
219
+				}
220
+			}
221
+		}
222
+		if (! empty($expired_ticket_IDs)) {
223
+			EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
224
+				\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
225
+				$valid_ticket_line_items,
226
+				__FUNCTION__
227
+			);
228
+			// let's get rid of expired line items so that they can't interfere with tracking
229
+			add_action(
230
+				'shutdown',
231
+				array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
232
+				999
233
+			);
234
+		}
235
+		do_action(
236
+			'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
237
+			$total_line_items,
238
+			$valid_ticket_line_items,
239
+			$expired_ticket_IDs
240
+		);
241
+	}
242
+
243
+
244
+
245
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
246
+
247
+
248
+
249
+	/**
250
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
251
+	 *
252
+	 * @param int       $qty
253
+	 * @param EE_Ticket $ticket
254
+	 * @return bool
255
+	 * @throws UnexpectedEntityException
256
+	 * @throws EE_Error
257
+	 */
258
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
259
+	{
260
+		$qty = absint($qty);
261
+		if ($qty > 0) {
262
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
263
+		}
264
+		if (self::debug) {
265
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
266
+			echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
267
+		}
268
+		return $qty;
269
+	}
270
+
271
+
272
+
273
+	/**
274
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
275
+	 *
276
+	 * @param   EE_Ticket $ticket
277
+	 * @param int         $qty
278
+	 * @return int
279
+	 * @throws UnexpectedEntityException
280
+	 * @throws EE_Error
281
+	 */
282
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
283
+	{
284
+		if (self::debug) {
285
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
286
+		}
287
+		if (! $ticket instanceof EE_Ticket) {
288
+			return 0;
289
+		}
290
+		if (self::debug) {
291
+			echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
292
+			echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
293
+		}
294
+		$ticket->refresh_from_db();
295
+		// first let's determine the ticket availability based on sales
296
+		$available = $ticket->qty('saleable');
297
+		if (self::debug) {
298
+			echo '<br /> . . . ticket->qty: ' . $ticket->qty();
299
+			echo '<br /> . . . ticket->sold: ' . $ticket->sold();
300
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
301
+			echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
302
+			echo '<br /> . . . available: ' . $available;
303
+		}
304
+		if ($available < 1) {
305
+			$this->_ticket_sold_out($ticket);
306
+			return 0;
307
+		}
308
+		if (self::debug) {
309
+			echo '<br /> . . . qty: ' . $qty;
310
+		}
311
+		if ($available < $qty) {
312
+			$qty = $available;
313
+			if (self::debug) {
314
+				echo '<br /> . . . QTY ADJUSTED: ' . $qty;
315
+			}
316
+			$this->_ticket_quantity_decremented($ticket);
317
+		}
318
+		$this->_reserve_ticket($ticket, $qty);
319
+		return $qty;
320
+	}
321
+
322
+
323
+
324
+	/**
325
+	 * increments ticket reserved based on quantity passed
326
+	 *
327
+	 * @param    EE_Ticket $ticket
328
+	 * @param int          $quantity
329
+	 * @return bool
330
+	 * @throws EE_Error
331
+	 */
332
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
333
+	{
334
+		if (self::debug) {
335
+			echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
336
+		}
337
+		$ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
338
+		return $ticket->save();
339
+	}
340
+
341
+
342
+
343
+	/**
344
+	 * @param  EE_Ticket $ticket
345
+	 * @param  int       $quantity
346
+	 * @return bool
347
+	 * @throws EE_Error
348
+	 */
349
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
350
+	{
351
+		if (self::debug) {
352
+			echo '<br /> . . . ticket->ID: ' . $ticket->ID();
353
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
354
+		}
355
+		$ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
356
+		if (self::debug) {
357
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
358
+		}
359
+		return $ticket->save() ? 1 : 0;
360
+	}
361
+
362
+
363
+
364
+	/**
365
+	 * removes quantities within the ticket selector based on zero ticket availability
366
+	 *
367
+	 * @param    EE_Ticket $ticket
368
+	 * @return    void
369
+	 * @throws UnexpectedEntityException
370
+	 * @throws EE_Error
371
+	 */
372
+	protected function _ticket_sold_out(EE_Ticket $ticket)
373
+	{
374
+		if (self::debug) {
375
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
376
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
377
+		}
378
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
379
+	}
380
+
381
+
382
+
383
+	/**
384
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
385
+	 *
386
+	 * @param    EE_Ticket $ticket
387
+	 * @return void
388
+	 * @throws UnexpectedEntityException
389
+	 * @throws EE_Error
390
+	 */
391
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
392
+	{
393
+		if (self::debug) {
394
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
395
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
396
+		}
397
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
398
+	}
399
+
400
+
401
+
402
+	/**
403
+	 * builds string out of ticket and event name
404
+	 *
405
+	 * @param    EE_Ticket $ticket
406
+	 * @return string
407
+	 * @throws UnexpectedEntityException
408
+	 * @throws EE_Error
409
+	 */
410
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
411
+	{
412
+		$event = $ticket->get_related_event();
413
+		if ($event instanceof EE_Event) {
414
+			$ticket_name = sprintf(
415
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
416
+				$ticket->name(),
417
+				$event->name()
418
+			);
419
+		} else {
420
+			$ticket_name = $ticket->name();
421
+		}
422
+		return $ticket_name;
423
+	}
424
+
425
+
426
+
427
+	/********************************** EVENT CART  **********************************/
428
+
429
+
430
+
431
+	/**
432
+	 * releases or reserves ticket(s) based on quantity passed
433
+	 *
434
+	 * @param  EE_Line_Item $line_item
435
+	 * @param  int          $quantity
436
+	 * @return void
437
+	 * @throws EE_Error
438
+	 * @throws InvalidArgumentException
439
+	 * @throws InvalidDataTypeException
440
+	 * @throws InvalidInterfaceException
441
+	 */
442
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
443
+	{
444
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
445
+		if ($ticket instanceof EE_Ticket) {
446
+			$ticket->add_extra_meta(
447
+				EE_Ticket::META_KEY_TICKET_RESERVATIONS,
448
+				__LINE__ . ') ' . __METHOD__ . '()'
449
+			);
450
+			if ($quantity > 0) {
451
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
452
+			} else {
453
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
454
+			}
455
+		}
456
+	}
457
+
458
+
459
+
460
+	/**
461
+	 * releases reserved ticket(s) based on quantity passed
462
+	 *
463
+	 * @param  EE_Ticket $ticket
464
+	 * @param  int       $quantity
465
+	 * @return void
466
+	 * @throws EE_Error
467
+	 */
468
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
469
+	{
470
+		$ticket->add_extra_meta(
471
+			EE_Ticket::META_KEY_TICKET_RESERVATIONS,
472
+			__LINE__ . ') ' . __METHOD__ . '()'
473
+		);
474
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
475
+	}
476
+
477
+
478
+
479
+	/********************************** POST_NOTICES  **********************************/
480
+
481
+
482
+
483
+	/**
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws ReflectionException
488
+	 * @throws InvalidDataTypeException
489
+	 * @throws InvalidInterfaceException
490
+	 */
491
+	public static function post_notices()
492
+	{
493
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
494
+	}
495
+
496
+
497
+
498
+	/**
499
+	 * @return void
500
+	 * @throws EE_Error
501
+	 * @throws InvalidArgumentException
502
+	 * @throws ReflectionException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 */
506
+	protected function _post_notices()
507
+	{
508
+		if (self::debug) {
509
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
510
+		}
511
+		$refresh_msg    = '';
512
+		$none_added_msg = '';
513
+		if (defined('DOING_AJAX') && DOING_AJAX) {
514
+			$refresh_msg    = __(
515
+				'Please refresh the page to view updated ticket quantities.',
516
+				'event_espresso'
517
+			);
518
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
519
+		}
520
+		if (! empty($this->sold_out_tickets)) {
521
+			EE_Error::add_attention(
522
+				sprintf(
523
+					apply_filters(
524
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
525
+						__(
526
+							'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
527
+							'event_espresso'
528
+						)
529
+					),
530
+					'<br />',
531
+					implode('<br />', $this->sold_out_tickets),
532
+					$none_added_msg,
533
+					$refresh_msg
534
+				)
535
+			);
536
+			// alter code flow in the Ticket Selector for better UX
537
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
538
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
539
+			$this->sold_out_tickets = array();
540
+			// and reset the cart
541
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
542
+		}
543
+		if (! empty($this->decremented_tickets)) {
544
+			EE_Error::add_attention(
545
+				sprintf(
546
+					apply_filters(
547
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
548
+						__(
549
+							'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
550
+							'event_espresso'
551
+						)
552
+					),
553
+					'<br />',
554
+					implode('<br />', $this->decremented_tickets),
555
+					$none_added_msg,
556
+					$refresh_msg
557
+				)
558
+			);
559
+			$this->decremented_tickets = array();
560
+		}
561
+	}
562
+
563
+
564
+
565
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
566
+
567
+
568
+
569
+	/**
570
+	 * releases reserved tickets for all registrations of an EE_Transaction
571
+	 * by default, will NOT release tickets for finalized transactions
572
+	 *
573
+	 * @param    EE_Transaction $transaction
574
+	 * @return int
575
+	 * @throws EE_Error
576
+	 * @throws InvalidSessionDataException
577
+	 */
578
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
579
+	{
580
+		if (self::debug) {
581
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
582
+			echo '<br /> . transaction->ID: ' . $transaction->ID();
583
+			echo '<br /> . TXN status_ID: ' . $transaction->status_ID();
584
+		}
585
+		// check if 'finalize_registration' step has been completed...
586
+		$finalized = $transaction->reg_step_completed('finalize_registration');
587
+		if (self::debug) {
588
+			// DEBUG LOG
589
+			EEH_Debug_Tools::log(
590
+				__CLASS__,
591
+				__FUNCTION__,
592
+				__LINE__,
593
+				array('finalized' => $finalized),
594
+				false,
595
+				'EE_Transaction: ' . $transaction->ID()
596
+			);
597
+		}
598
+		// how many tickets were released
599
+		$count = 0;
600
+		if (self::debug) {
601
+			echo '<br /> . . . TXN finalized: ' . $finalized;
602
+		}
603
+		$release_tickets_with_TXN_status = array(
604
+			EEM_Transaction::failed_status_code,
605
+			EEM_Transaction::abandoned_status_code,
606
+			EEM_Transaction::incomplete_status_code,
607
+		);
608
+		$events = array();
609
+		// if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
610
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
611
+			// cancel any reserved tickets for registrations that were not approved
612
+			$registrations = $transaction->registrations();
613
+			if (self::debug) {
614
+				echo '<br /> . . . # registrations: ' . count($registrations);
615
+				$reg    = reset($registrations);
616
+				$ticket = $reg->ticket();
617
+				if ($ticket instanceof EE_Ticket) {
618
+					$ticket->add_extra_meta(
619
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
620
+						__LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
621
+					);
622
+				}
623
+			}
624
+			if (! empty($registrations)) {
625
+				foreach ($registrations as $registration) {
626
+					if (
627
+						$registration instanceof EE_Registration
628
+						&& $this->_release_reserved_ticket_for_registration($registration, $transaction)
629
+					) {
630
+						$count++;
631
+						$events[ $registration->event_ID() ] = $registration->event();
632
+					}
633
+				}
634
+			}
635
+		}
636
+		if ($events !== array()) {
637
+			foreach ($events as $event) {
638
+				/** @var EE_Event $event */
639
+				$event->perform_sold_out_status_check();
640
+			}
641
+		}
642
+		return $count;
643
+	}
644
+
645
+
646
+
647
+	/**
648
+	 * releases reserved tickets for an EE_Registration
649
+	 * by default, will NOT release tickets for APPROVED registrations
650
+	 *
651
+	 * @param EE_Registration $registration
652
+	 * @param EE_Transaction  $transaction
653
+	 * @return int
654
+	 * @throws EE_Error
655
+	 */
656
+	protected function _release_reserved_ticket_for_registration(
657
+		EE_Registration $registration,
658
+		EE_Transaction $transaction
659
+	) {
660
+		$STS_ID = $transaction->status_ID();
661
+		if (self::debug) {
662
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
663
+			echo '<br /> . . registration->ID: ' . $registration->ID();
664
+			echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
665
+			echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
666
+		}
667
+		if (
668
+			// release Tickets for Failed Transactions and Abandoned Transactions
669
+			$STS_ID === EEM_Transaction::failed_status_code
670
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
671
+			|| (
672
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
673
+				$STS_ID === EEM_Transaction::incomplete_status_code
674
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
675
+			)
676
+		) {
677
+			if (self::debug) {
678
+				echo '<br /><br /> . . RELEASE RESERVED TICKET';
679
+				$rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
680
+				echo '<br /> . . . registration HAS_RESERVED_TICKET_KEY: ';
681
+				var_dump($rsrvd);
682
+			}
683
+			$registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
684
+			return 1;
685
+		}
686
+		return 0;
687
+	}
688
+
689
+
690
+
691
+	/********************************** SESSION_CART_RESET  **********************************/
692
+
693
+
694
+
695
+	/**
696
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
697
+	 *
698
+	 * @param EE_Session $session
699
+	 * @return void
700
+	 * @throws EE_Error
701
+	 * @throws InvalidArgumentException
702
+	 * @throws ReflectionException
703
+	 * @throws InvalidDataTypeException
704
+	 * @throws InvalidInterfaceException
705
+	 */
706
+	public static function session_cart_reset(EE_Session $session)
707
+	{
708
+		if (self::debug) {
709
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
710
+		}
711
+		// first check of the session has a valid Checkout object
712
+		$checkout = $session->checkout();
713
+		if ($checkout instanceof EE_Checkout) {
714
+			// and use that to clear ticket reservations because it will update the associated registration meta data
715
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
716
+			return;
717
+		}
718
+		$cart = $session->cart();
719
+		if ($cart instanceof EE_Cart) {
720
+			if (self::debug) {
721
+				echo '<br /><br /> cart instance of EE_Cart: ';
722
+			}
723
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
724
+		} else {
725
+			if (self::debug) {
726
+				echo '<br /><br /> invalid EE_Cart: ';
727
+				var_export($cart, true);
728
+			}
729
+		}
730
+	}
731
+
732
+
733
+
734
+	/**
735
+	 * releases reserved tickets in the EE_Cart
736
+	 *
737
+	 * @param EE_Cart $cart
738
+	 * @return void
739
+	 * @throws EE_Error
740
+	 * @throws InvalidArgumentException
741
+	 * @throws ReflectionException
742
+	 * @throws InvalidDataTypeException
743
+	 * @throws InvalidInterfaceException
744
+	 */
745
+	protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
746
+	{
747
+		if (self::debug) {
748
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
749
+		}
750
+		EE_Registry::instance()->load_helper('Line_Item');
751
+		$ticket_line_items = $cart->get_tickets();
752
+		if (empty($ticket_line_items)) {
753
+			return;
754
+		}
755
+		foreach ($ticket_line_items as $ticket_line_item) {
756
+			if (self::debug) {
757
+				echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
758
+			}
759
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
760
+				if (self::debug) {
761
+					echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
762
+				}
763
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
764
+				if ($ticket instanceof EE_Ticket) {
765
+					if (self::debug) {
766
+						echo '<br /> . . ticket->ID(): ' . $ticket->ID();
767
+						echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
768
+					}
769
+					$ticket->add_extra_meta(
770
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
771
+						__LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
772
+					);
773
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
774
+				}
775
+			}
776
+		}
777
+		if (self::debug) {
778
+			echo '<br /><br /> RESET COMPLETED ';
779
+		}
780
+	}
781
+
782
+
783
+
784
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
785
+
786
+
787
+
788
+	/**
789
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
790
+	 *
791
+	 * @param EE_Session $session
792
+	 * @return void
793
+	 * @throws EE_Error
794
+	 * @throws InvalidSessionDataException
795
+	 */
796
+	public static function session_checkout_reset(EE_Session $session)
797
+	{
798
+		$checkout = $session->checkout();
799
+		if ($checkout instanceof EE_Checkout) {
800
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
801
+		}
802
+	}
803
+
804
+
805
+
806
+	/**
807
+	 * releases reserved tickets for the EE_Checkout->transaction
808
+	 *
809
+	 * @param EE_Checkout $checkout
810
+	 * @return void
811
+	 * @throws EE_Error
812
+	 * @throws InvalidSessionDataException
813
+	 */
814
+	protected function _session_checkout_reset(EE_Checkout $checkout)
815
+	{
816
+		if (self::debug) {
817
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
818
+		}
819
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
820
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
821
+			return;
822
+		}
823
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
824
+	}
825
+
826
+
827
+
828
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
829
+
830
+
831
+
832
+	/**
833
+	 * @param    EE_Session $session
834
+	 * @return    void
835
+	 */
836
+	public static function session_expired_reset(EE_Session $session)
837
+	{
838
+	}
839
+
840
+
841
+
842
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
843
+
844
+
845
+
846
+	/**
847
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
848
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
849
+	 *
850
+	 * @param EE_Transaction $transaction
851
+	 * @return void
852
+	 * @throws EE_Error
853
+	 * @throws InvalidSessionDataException
854
+	 */
855
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
856
+	{
857
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
858
+		if ($transaction->is_free() || $transaction->paid() > 0) {
859
+			if (self::debug) {
860
+				// DEBUG LOG
861
+				EEH_Debug_Tools::log(
862
+					__CLASS__,
863
+					__FUNCTION__,
864
+					__LINE__,
865
+					array($transaction),
866
+					false,
867
+					'EE_Transaction: ' . $transaction->ID()
868
+				);
869
+			}
870
+			return;
871
+		}
872
+		// have their been any successful payments made ?
873
+		$payments = $transaction->payments();
874
+		foreach ($payments as $payment) {
875
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
876
+				if (self::debug) {
877
+					// DEBUG LOG
878
+					EEH_Debug_Tools::log(
879
+						__CLASS__,
880
+						__FUNCTION__,
881
+						__LINE__,
882
+						array($payment),
883
+						false,
884
+						'EE_Transaction: ' . $transaction->ID()
885
+					);
886
+				}
887
+				return;
888
+			}
889
+		}
890
+		// since you haven't even attempted to pay for your ticket...
891
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
892
+	}
893
+
894
+
895
+
896
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
897
+
898
+
899
+
900
+	/**
901
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
902
+	 *
903
+	 * @param EE_Transaction $transaction
904
+	 * @return void
905
+	 * @throws EE_Error
906
+	 * @throws InvalidSessionDataException
907
+	 */
908
+	public static function process_failed_transactions(EE_Transaction $transaction)
909
+	{
910
+		// since you haven't even attempted to pay for your ticket...
911
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
912
+	}
913
+
914
+
915
+
916
+	/********************************** RESET RESERVATION COUNTS  *********************************/
917
+
918
+
919
+
920
+	/**
921
+	 * Resets all ticket and datetime reserved counts to zero
922
+	 * Tickets that are currently associated with a Transaction that is in progress
923
+	 *
924
+	 * @throws EE_Error
925
+	 * @throws DomainException
926
+	 * @throws InvalidDataTypeException
927
+	 * @throws InvalidInterfaceException
928
+	 * @throws InvalidArgumentException
929
+	 * @throws UnexpectedEntityException
930
+	 */
931
+	public static function reset_reservation_counts()
932
+	{
933
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
934
+		$valid_reserved_tickets = array();
935
+		/** @var EE_Transaction[] $transactions_not_in_progress */
936
+		$transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
937
+		foreach ($transactions_not_in_progress as $transaction) {
938
+			// if this TXN has been fully completed, then skip it
939
+			if ($transaction->reg_step_completed('finalize_registration')) {
940
+				continue;
941
+			}
942
+			$total_line_item = $transaction->total_line_item();
943
+			// $transaction_in_progress->line
944
+			if (! $total_line_item instanceof EE_Line_Item) {
945
+				throw new DomainException(
946
+					esc_html__(
947
+						'Transaction does not have a valid Total Line Item associated with it.',
948
+						'event_espresso'
949
+					)
950
+				);
951
+			}
952
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
953
+				$total_line_item
954
+			);
955
+		}
956
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
957
+		foreach ($total_line_items as $total_line_item) {
958
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
959
+				$total_line_item
960
+			);
961
+		}
962
+		$tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
963
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
964
+			$tickets_with_reservations,
965
+			$valid_reserved_tickets,
966
+			__FUNCTION__
967
+		);
968
+	}
969
+
970
+
971
+
972
+	/**
973
+	 * @param EE_Line_Item $total_line_item
974
+	 * @return EE_Line_Item[]
975
+	 */
976
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
977
+	{
978
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
979
+		$valid_reserved_tickets = array();
980
+		$ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
981
+		foreach ($ticket_line_items as $ticket_line_item) {
982
+			if ($ticket_line_item instanceof EE_Line_Item) {
983
+				$valid_reserved_tickets[] = $ticket_line_item;
984
+			}
985
+		}
986
+		return $valid_reserved_tickets;
987
+	}
988
+
989
+
990
+
991
+	/**
992
+	 * @param EE_Ticket[]    $tickets_with_reservations
993
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
994
+	 * @return int
995
+	 * @throws UnexpectedEntityException
996
+	 * @throws DomainException
997
+	 * @throws EE_Error
998
+	 */
999
+	private static function release_reservations_for_tickets(
1000
+		array $tickets_with_reservations,
1001
+		array $valid_reserved_ticket_line_items = array(),
1002
+		$source
1003
+	) {
1004
+		$total_tickets_released = 0;
1005
+		$sold_out_events = array();
1006
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
1007
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
1008
+				continue;
1009
+			}
1010
+			$reserved_qty = $ticket_with_reservations->reserved();
1011
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1012
+				if (
1013
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
1014
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1015
+				) {
1016
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1017
+				}
1018
+			}
1019
+			if ($reserved_qty > 0) {
1020
+				$ticket_with_reservations->add_extra_meta(
1021
+					EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1022
+					__LINE__ . ') ' . $source . '()'
1023
+				);
1024
+				$ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1025
+				$ticket_with_reservations->save();
1026
+				$total_tickets_released += $reserved_qty;
1027
+				$event = $ticket_with_reservations->get_related_event();
1028
+				// track sold out events
1029
+				if ($event instanceof EE_Event && $event->is_sold_out()) {
1030
+					$sold_out_events[] = $event;
1031
+				}
1032
+			}
1033
+		}
1034
+		// double check whether sold out events should remain sold out after releasing tickets
1035
+		if($sold_out_events !== array()){
1036
+			foreach ($sold_out_events as $sold_out_event) {
1037
+				/** @var EE_Event $sold_out_event */
1038
+				$sold_out_event->perform_sold_out_status_check();
1039
+			}
1040
+		}
1041
+		return $total_tickets_released;
1042
+	}
1043
+
1044
+
1045
+
1046
+	/********************************** SHUTDOWN  **********************************/
1047
+
1048
+
1049
+
1050
+	/**
1051
+	 * @return false|int
1052
+	 * @throws EE_Error
1053
+	 * @throws InvalidArgumentException
1054
+	 * @throws InvalidDataTypeException
1055
+	 * @throws InvalidInterfaceException
1056
+	 */
1057
+	public static function clear_expired_line_items_with_no_transaction()
1058
+	{
1059
+		/** @type WPDB $wpdb */
1060
+		global $wpdb;
1061
+		return $wpdb->query(
1062
+			$wpdb->prepare(
1063
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1064 1064
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1065
-                // use GMT time because that's what LIN_timestamps are in
1066
-                date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
1067
-            )
1068
-        );
1069
-    }
1065
+				// use GMT time because that's what LIN_timestamps are in
1066
+				date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
1067
+			)
1068
+		);
1069
+	}
1070 1070
 
1071 1071
 }
1072 1072
 // End of file EED_Ticket_Sales_Monitor.module.php
Please login to merge, or discard this patch.
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@  discard block
 block discarded – undo
23 23
 class EED_Ticket_Sales_Monitor extends EED_Module
24 24
 {
25 25
 
26
-    const debug = false;    //	true false
26
+    const debug = false; //	true false
27 27
 
28 28
     /**
29 29
      * an array of raw ticket data from EED_Ticket_Selector
@@ -209,17 +209,17 @@  discard block
 block discarded – undo
209 209
             /** @var EE_Line_Item $total_line_item */
210 210
             $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
211 211
             foreach ($ticket_line_items as $ticket_line_item) {
212
-                if (! $ticket_line_item instanceof EE_Line_Item) {
212
+                if ( ! $ticket_line_item instanceof EE_Line_Item) {
213 213
                     continue;
214 214
                 }
215 215
                 if ($total_line_item->timestamp(true) <= $expired) {
216
-                    $expired_ticket_IDs[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item->OBJ_ID();
216
+                    $expired_ticket_IDs[$ticket_line_item->OBJ_ID()] = $ticket_line_item->OBJ_ID();
217 217
                 } else {
218
-                    $valid_ticket_line_items[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item;
218
+                    $valid_ticket_line_items[$ticket_line_item->OBJ_ID()] = $ticket_line_item;
219 219
                 }
220 220
             }
221 221
         }
222
-        if (! empty($expired_ticket_IDs)) {
222
+        if ( ! empty($expired_ticket_IDs)) {
223 223
             EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
224 224
                 \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
225 225
                 $valid_ticket_line_items,
@@ -262,8 +262,8 @@  discard block
 block discarded – undo
262 262
             $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
263 263
         }
264 264
         if (self::debug) {
265
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
266
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
265
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'()';
266
+            echo '<br /><br /><b> RETURNED QTY: '.$qty.'</b>';
267 267
         }
268 268
         return $qty;
269 269
     }
@@ -282,36 +282,36 @@  discard block
 block discarded – undo
282 282
     protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
283 283
     {
284 284
         if (self::debug) {
285
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
285
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
286 286
         }
287
-        if (! $ticket instanceof EE_Ticket) {
287
+        if ( ! $ticket instanceof EE_Ticket) {
288 288
             return 0;
289 289
         }
290 290
         if (self::debug) {
291
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
292
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
291
+            echo '<br /><b> . ticket->ID: '.$ticket->ID().'</b>';
292
+            echo '<br /> . original ticket->reserved: '.$ticket->reserved();
293 293
         }
294 294
         $ticket->refresh_from_db();
295 295
         // first let's determine the ticket availability based on sales
296 296
         $available = $ticket->qty('saleable');
297 297
         if (self::debug) {
298
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
299
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
300
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
301
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
302
-            echo '<br /> . . . available: ' . $available;
298
+            echo '<br /> . . . ticket->qty: '.$ticket->qty();
299
+            echo '<br /> . . . ticket->sold: '.$ticket->sold();
300
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
301
+            echo '<br /> . . . ticket->qty(saleable): '.$ticket->qty('saleable');
302
+            echo '<br /> . . . available: '.$available;
303 303
         }
304 304
         if ($available < 1) {
305 305
             $this->_ticket_sold_out($ticket);
306 306
             return 0;
307 307
         }
308 308
         if (self::debug) {
309
-            echo '<br /> . . . qty: ' . $qty;
309
+            echo '<br /> . . . qty: '.$qty;
310 310
         }
311 311
         if ($available < $qty) {
312 312
             $qty = $available;
313 313
             if (self::debug) {
314
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
314
+                echo '<br /> . . . QTY ADJUSTED: '.$qty;
315 315
             }
316 316
             $this->_ticket_quantity_decremented($ticket);
317 317
         }
@@ -332,9 +332,9 @@  discard block
 block discarded – undo
332 332
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
333 333
     {
334 334
         if (self::debug) {
335
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
335
+            echo '<br /><br /> . . . INCREASE RESERVED: '.$quantity;
336 336
         }
337
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
337
+        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'.__LINE__);
338 338
         return $ticket->save();
339 339
     }
340 340
 
@@ -349,12 +349,12 @@  discard block
 block discarded – undo
349 349
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
350 350
     {
351 351
         if (self::debug) {
352
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
353
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
352
+            echo '<br /> . . . ticket->ID: '.$ticket->ID();
353
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
354 354
         }
355
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
355
+        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'.__LINE__);
356 356
         if (self::debug) {
357
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
357
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
358 358
         }
359 359
         return $ticket->save() ? 1 : 0;
360 360
     }
@@ -372,8 +372,8 @@  discard block
 block discarded – undo
372 372
     protected function _ticket_sold_out(EE_Ticket $ticket)
373 373
     {
374 374
         if (self::debug) {
375
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
376
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
375
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
376
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
377 377
         }
378 378
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
379 379
     }
@@ -391,8 +391,8 @@  discard block
 block discarded – undo
391 391
     protected function _ticket_quantity_decremented(EE_Ticket $ticket)
392 392
     {
393 393
         if (self::debug) {
394
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
395
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
394
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
395
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
396 396
         }
397 397
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
398 398
     }
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
         if ($ticket instanceof EE_Ticket) {
446 446
             $ticket->add_extra_meta(
447 447
                 EE_Ticket::META_KEY_TICKET_RESERVATIONS,
448
-                __LINE__ . ') ' . __METHOD__ . '()'
448
+                __LINE__.') '.__METHOD__.'()'
449 449
             );
450 450
             if ($quantity > 0) {
451 451
                 EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
@@ -469,7 +469,7 @@  discard block
 block discarded – undo
469 469
     {
470 470
         $ticket->add_extra_meta(
471 471
             EE_Ticket::META_KEY_TICKET_RESERVATIONS,
472
-            __LINE__ . ') ' . __METHOD__ . '()'
472
+            __LINE__.') '.__METHOD__.'()'
473 473
         );
474 474
         EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
475 475
     }
@@ -506,18 +506,18 @@  discard block
 block discarded – undo
506 506
     protected function _post_notices()
507 507
     {
508 508
         if (self::debug) {
509
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
509
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
510 510
         }
511 511
         $refresh_msg    = '';
512 512
         $none_added_msg = '';
513 513
         if (defined('DOING_AJAX') && DOING_AJAX) {
514
-            $refresh_msg    = __(
514
+            $refresh_msg = __(
515 515
                 'Please refresh the page to view updated ticket quantities.',
516 516
                 'event_espresso'
517 517
             );
518 518
             $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
519 519
         }
520
-        if (! empty($this->sold_out_tickets)) {
520
+        if ( ! empty($this->sold_out_tickets)) {
521 521
             EE_Error::add_attention(
522 522
                 sprintf(
523 523
                     apply_filters(
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
             // and reset the cart
541 541
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
542 542
         }
543
-        if (! empty($this->decremented_tickets)) {
543
+        if ( ! empty($this->decremented_tickets)) {
544 544
             EE_Error::add_attention(
545 545
                 sprintf(
546 546
                     apply_filters(
@@ -578,9 +578,9 @@  discard block
 block discarded – undo
578 578
     protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
579 579
     {
580 580
         if (self::debug) {
581
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
582
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
583
-            echo '<br /> . TXN status_ID: ' . $transaction->status_ID();
581
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
582
+            echo '<br /> . transaction->ID: '.$transaction->ID();
583
+            echo '<br /> . TXN status_ID: '.$transaction->status_ID();
584 584
         }
585 585
         // check if 'finalize_registration' step has been completed...
586 586
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -592,13 +592,13 @@  discard block
 block discarded – undo
592 592
                 __LINE__,
593 593
                 array('finalized' => $finalized),
594 594
                 false,
595
-                'EE_Transaction: ' . $transaction->ID()
595
+                'EE_Transaction: '.$transaction->ID()
596 596
             );
597 597
         }
598 598
         // how many tickets were released
599 599
         $count = 0;
600 600
         if (self::debug) {
601
-            echo '<br /> . . . TXN finalized: ' . $finalized;
601
+            echo '<br /> . . . TXN finalized: '.$finalized;
602 602
         }
603 603
         $release_tickets_with_TXN_status = array(
604 604
             EEM_Transaction::failed_status_code,
@@ -607,28 +607,28 @@  discard block
 block discarded – undo
607 607
         );
608 608
         $events = array();
609 609
         // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
610
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
610
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
611 611
             // cancel any reserved tickets for registrations that were not approved
612 612
             $registrations = $transaction->registrations();
613 613
             if (self::debug) {
614
-                echo '<br /> . . . # registrations: ' . count($registrations);
614
+                echo '<br /> . . . # registrations: '.count($registrations);
615 615
                 $reg    = reset($registrations);
616 616
                 $ticket = $reg->ticket();
617 617
                 if ($ticket instanceof EE_Ticket) {
618 618
                     $ticket->add_extra_meta(
619 619
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
620
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
620
+                        __LINE__.') Release All Tickets TXN:'.$transaction->ID()
621 621
                     );
622 622
                 }
623 623
             }
624
-            if (! empty($registrations)) {
624
+            if ( ! empty($registrations)) {
625 625
                 foreach ($registrations as $registration) {
626 626
                     if (
627 627
                         $registration instanceof EE_Registration
628 628
                         && $this->_release_reserved_ticket_for_registration($registration, $transaction)
629 629
                     ) {
630 630
                         $count++;
631
-                        $events[ $registration->event_ID() ] = $registration->event();
631
+                        $events[$registration->event_ID()] = $registration->event();
632 632
                     }
633 633
                 }
634 634
             }
@@ -659,10 +659,10 @@  discard block
 block discarded – undo
659 659
     ) {
660 660
         $STS_ID = $transaction->status_ID();
661 661
         if (self::debug) {
662
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
663
-            echo '<br /> . . registration->ID: ' . $registration->ID();
664
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
665
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
662
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
663
+            echo '<br /> . . registration->ID: '.$registration->ID();
664
+            echo '<br /> . . registration->status_ID: '.$registration->status_ID();
665
+            echo '<br /> . . transaction->status_ID(): '.$STS_ID;
666 666
         }
667 667
         if (
668 668
             // release Tickets for Failed Transactions and Abandoned Transactions
@@ -680,7 +680,7 @@  discard block
 block discarded – undo
680 680
                 echo '<br /> . . . registration HAS_RESERVED_TICKET_KEY: ';
681 681
                 var_dump($rsrvd);
682 682
             }
683
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
683
+            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'.__LINE__);
684 684
             return 1;
685 685
         }
686 686
         return 0;
@@ -706,7 +706,7 @@  discard block
 block discarded – undo
706 706
     public static function session_cart_reset(EE_Session $session)
707 707
     {
708 708
         if (self::debug) {
709
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
709
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
710 710
         }
711 711
         // first check of the session has a valid Checkout object
712 712
         $checkout = $session->checkout();
@@ -745,7 +745,7 @@  discard block
 block discarded – undo
745 745
     protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
746 746
     {
747 747
         if (self::debug) {
748
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
748
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
749 749
         }
750 750
         EE_Registry::instance()->load_helper('Line_Item');
751 751
         $ticket_line_items = $cart->get_tickets();
@@ -754,21 +754,21 @@  discard block
 block discarded – undo
754 754
         }
755 755
         foreach ($ticket_line_items as $ticket_line_item) {
756 756
             if (self::debug) {
757
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
757
+                echo '<br /> . ticket_line_item->ID(): '.$ticket_line_item->ID();
758 758
             }
759 759
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
760 760
                 if (self::debug) {
761
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
761
+                    echo '<br /> . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
762 762
                 }
763 763
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
764 764
                 if ($ticket instanceof EE_Ticket) {
765 765
                     if (self::debug) {
766
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
767
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
766
+                        echo '<br /> . . ticket->ID(): '.$ticket->ID();
767
+                        echo '<br /> . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
768 768
                     }
769 769
                     $ticket->add_extra_meta(
770 770
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
771
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
771
+                        __LINE__.') '.__METHOD__.'() SID = '.$session->id()
772 772
                     );
773 773
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
774 774
                 }
@@ -814,7 +814,7 @@  discard block
 block discarded – undo
814 814
     protected function _session_checkout_reset(EE_Checkout $checkout)
815 815
     {
816 816
         if (self::debug) {
817
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
817
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
818 818
         }
819 819
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
820 820
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -864,7 +864,7 @@  discard block
 block discarded – undo
864 864
                     __LINE__,
865 865
                     array($transaction),
866 866
                     false,
867
-                    'EE_Transaction: ' . $transaction->ID()
867
+                    'EE_Transaction: '.$transaction->ID()
868 868
                 );
869 869
             }
870 870
             return;
@@ -881,7 +881,7 @@  discard block
 block discarded – undo
881 881
                         __LINE__,
882 882
                         array($payment),
883 883
                         false,
884
-                        'EE_Transaction: ' . $transaction->ID()
884
+                        'EE_Transaction: '.$transaction->ID()
885 885
                     );
886 886
                 }
887 887
                 return;
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
             }
942 942
             $total_line_item = $transaction->total_line_item();
943 943
             // $transaction_in_progress->line
944
-            if (! $total_line_item instanceof EE_Line_Item) {
944
+            if ( ! $total_line_item instanceof EE_Line_Item) {
945 945
                 throw new DomainException(
946 946
                     esc_html__(
947 947
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -1004,7 +1004,7 @@  discard block
 block discarded – undo
1004 1004
         $total_tickets_released = 0;
1005 1005
         $sold_out_events = array();
1006 1006
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
1007
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1007
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
1008 1008
                 continue;
1009 1009
             }
1010 1010
             $reserved_qty = $ticket_with_reservations->reserved();
@@ -1019,9 +1019,9 @@  discard block
 block discarded – undo
1019 1019
             if ($reserved_qty > 0) {
1020 1020
                 $ticket_with_reservations->add_extra_meta(
1021 1021
                     EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1022
-                    __LINE__ . ') ' . $source . '()'
1022
+                    __LINE__.') '.$source.'()'
1023 1023
                 );
1024
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1024
+                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'.__LINE__);
1025 1025
                 $ticket_with_reservations->save();
1026 1026
                 $total_tickets_released += $reserved_qty;
1027 1027
                 $event = $ticket_with_reservations->get_related_event();
@@ -1032,7 +1032,7 @@  discard block
 block discarded – undo
1032 1032
             }
1033 1033
         }
1034 1034
         // double check whether sold out events should remain sold out after releasing tickets
1035
-        if($sold_out_events !== array()){
1035
+        if ($sold_out_events !== array()) {
1036 1036
             foreach ($sold_out_events as $sold_out_event) {
1037 1037
                 /** @var EE_Event $sold_out_event */
1038 1038
                 $sold_out_event->perform_sold_out_status_check();
@@ -1060,7 +1060,7 @@  discard block
 block discarded – undo
1060 1060
         global $wpdb;
1061 1061
         return $wpdb->query(
1062 1062
             $wpdb->prepare(
1063
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1063
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
1064 1064
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1065 1065
                 // use GMT time because that's what LIN_timestamps are in
1066 1066
                 date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
Please login to merge, or discard this patch.
core/domain/services/registration/CreateRegistrationService.php 2 patches
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
 use OutOfRangeException;
18 18
 
19 19
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
20
-    exit('No direct script access allowed');
20
+	exit('No direct script access allowed');
21 21
 }
22 22
 
23 23
 
@@ -41,54 +41,54 @@  discard block
 block discarded – undo
41 41
 	 * @param EE_Line_Item   $ticket_line_item
42 42
 	 * @param                 $reg_count
43 43
 	 * @param                 $reg_group_size
44
-     * @param string          $reg_status
45
-     * @return EE_Registration
44
+	 * @param string          $reg_status
45
+	 * @return EE_Registration
46 46
 	 * @throws OutOfRangeException
47 47
 	 * @throws EE_Error
48 48
 	 * @throws UnexpectedEntityException
49 49
 	 */
50
-    public function create(
51
-        EE_Event $event,
52
-        EE_Transaction $transaction,
53
-        EE_Ticket $ticket,
54
-        EE_Line_Item $ticket_line_item,
55
-        $reg_count,
56
-        $reg_group_size,
57
-        $reg_status = EEM_Registration::status_id_incomplete
58
-    ) {
59
-        $registrations = $transaction->registrations();
60
-        $reg_count = $reg_count ? $reg_count : count($registrations) + 1;
61
-        $reg_url_link = new RegUrlLink($reg_count, $ticket_line_item);
62
-        $reg_code = new RegCode($reg_url_link, $transaction, $ticket);
63
-        // generate new EE_Registration
64
-        $registration = EE_Registration::new_instance(
65
-            array(
66
-                'EVT_ID'          => $event->ID(),
67
-                'TXN_ID'          => $transaction->ID(),
68
-                'TKT_ID'          => $ticket->ID(),
69
-                'STS_ID'          => $reg_status,
70
-                'REG_final_price' => $this->resolveFinalPrice($transaction, $ticket, $ticket_line_item),
71
-                'REG_session'     => EE_Registry::instance()->SSN->id(),
72
-                'REG_count'       => $reg_count,
73
-                'REG_group_size'  => $reg_group_size ? $reg_group_size : $this->incrementRegCount($registrations),
74
-                'REG_url_link'    => $reg_url_link,
75
-                'REG_code'        => $reg_code,
76
-            )
77
-        );
78
-        if ( ! $registration instanceof EE_Registration) {
79
-            throw new UnexpectedEntityException($registration, 'EE_Registration');
80
-        }
81
-        // save registration so that we have an ID
82
-        $registration->save();
83
-        // track reservation on reg but don't adjust ticket and datetime reserved counts
84
-        // because that is done as soon as the tickets are added/removed from the cart
85
-        $registration->reserve_ticket(false, 'CreateRegistrationService:'. __LINE__);
86
-        $registration->_add_relation_to($event, 'Event', array(), $event->ID());
87
-        $registration->_add_relation_to($ticket, 'Ticket', array(), $ticket->ID());
88
-        $transaction->_add_relation_to($registration, 'Registration', array(), $registration->ID());
89
-        $registration->save();
90
-        return $registration;
91
-    }
50
+	public function create(
51
+		EE_Event $event,
52
+		EE_Transaction $transaction,
53
+		EE_Ticket $ticket,
54
+		EE_Line_Item $ticket_line_item,
55
+		$reg_count,
56
+		$reg_group_size,
57
+		$reg_status = EEM_Registration::status_id_incomplete
58
+	) {
59
+		$registrations = $transaction->registrations();
60
+		$reg_count = $reg_count ? $reg_count : count($registrations) + 1;
61
+		$reg_url_link = new RegUrlLink($reg_count, $ticket_line_item);
62
+		$reg_code = new RegCode($reg_url_link, $transaction, $ticket);
63
+		// generate new EE_Registration
64
+		$registration = EE_Registration::new_instance(
65
+			array(
66
+				'EVT_ID'          => $event->ID(),
67
+				'TXN_ID'          => $transaction->ID(),
68
+				'TKT_ID'          => $ticket->ID(),
69
+				'STS_ID'          => $reg_status,
70
+				'REG_final_price' => $this->resolveFinalPrice($transaction, $ticket, $ticket_line_item),
71
+				'REG_session'     => EE_Registry::instance()->SSN->id(),
72
+				'REG_count'       => $reg_count,
73
+				'REG_group_size'  => $reg_group_size ? $reg_group_size : $this->incrementRegCount($registrations),
74
+				'REG_url_link'    => $reg_url_link,
75
+				'REG_code'        => $reg_code,
76
+			)
77
+		);
78
+		if ( ! $registration instanceof EE_Registration) {
79
+			throw new UnexpectedEntityException($registration, 'EE_Registration');
80
+		}
81
+		// save registration so that we have an ID
82
+		$registration->save();
83
+		// track reservation on reg but don't adjust ticket and datetime reserved counts
84
+		// because that is done as soon as the tickets are added/removed from the cart
85
+		$registration->reserve_ticket(false, 'CreateRegistrationService:'. __LINE__);
86
+		$registration->_add_relation_to($event, 'Event', array(), $event->ID());
87
+		$registration->_add_relation_to($ticket, 'Ticket', array(), $ticket->ID());
88
+		$transaction->_add_relation_to($registration, 'Registration', array(), $registration->ID());
89
+		$registration->save();
90
+		return $registration;
91
+	}
92 92
 
93 93
 
94 94
 
@@ -100,40 +100,40 @@  discard block
 block discarded – undo
100 100
 	 * @throws EE_Error
101 101
 	 * @throws OutOfRangeException
102 102
 	 */
103
-    protected function resolveFinalPrice(
104
-        EE_Transaction $transaction,
105
-        EE_Ticket $ticket,
106
-        EE_Line_Item $ticket_line_item
107
-    ) {
108
-        $final_price = EEH_Line_Item::calculate_final_price_for_ticket_line_item(
109
-            $transaction->total_line_item(),
110
-            $ticket_line_item
111
-        );
112
-        $final_price = $final_price !== null ? $final_price : $ticket->get_ticket_total_with_taxes();
113
-        return (float)$final_price;
114
-    }
103
+	protected function resolveFinalPrice(
104
+		EE_Transaction $transaction,
105
+		EE_Ticket $ticket,
106
+		EE_Line_Item $ticket_line_item
107
+	) {
108
+		$final_price = EEH_Line_Item::calculate_final_price_for_ticket_line_item(
109
+			$transaction->total_line_item(),
110
+			$ticket_line_item
111
+		);
112
+		$final_price = $final_price !== null ? $final_price : $ticket->get_ticket_total_with_taxes();
113
+		return (float)$final_price;
114
+	}
115 115
 
116 116
 
117 117
 
118
-    /**
119
-     * @param  EE_Registration[] $registrations
120
-     * @param  boolean            $update_existing_registrations
121
-     * @return int
122
-     * @throws EE_Error
123
-     */
124
-    protected function incrementRegCount(array $registrations, $update_existing_registrations = true)
125
-    {
126
-        $new_reg_count = count($registrations) + 1;
127
-        if ($update_existing_registrations) {
128
-            foreach ($registrations as $registration) {
129
-                if ($registration instanceof EE_Registration) {
130
-                    $registration->set_count($new_reg_count);
131
-                    $registration->save();
132
-                }
133
-            }
134
-        }
135
-        return $new_reg_count;
136
-    }
118
+	/**
119
+	 * @param  EE_Registration[] $registrations
120
+	 * @param  boolean            $update_existing_registrations
121
+	 * @return int
122
+	 * @throws EE_Error
123
+	 */
124
+	protected function incrementRegCount(array $registrations, $update_existing_registrations = true)
125
+	{
126
+		$new_reg_count = count($registrations) + 1;
127
+		if ($update_existing_registrations) {
128
+			foreach ($registrations as $registration) {
129
+				if ($registration instanceof EE_Registration) {
130
+					$registration->set_count($new_reg_count);
131
+					$registration->save();
132
+				}
133
+			}
134
+		}
135
+		return $new_reg_count;
136
+	}
137 137
 
138 138
 
139 139
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
         $registration->save();
83 83
         // track reservation on reg but don't adjust ticket and datetime reserved counts
84 84
         // because that is done as soon as the tickets are added/removed from the cart
85
-        $registration->reserve_ticket(false, 'CreateRegistrationService:'. __LINE__);
85
+        $registration->reserve_ticket(false, 'CreateRegistrationService:'.__LINE__);
86 86
         $registration->_add_relation_to($event, 'Event', array(), $event->ID());
87 87
         $registration->_add_relation_to($ticket, 'Ticket', array(), $ticket->ID());
88 88
         $transaction->_add_relation_to($registration, 'Registration', array(), $registration->ID());
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
             $ticket_line_item
111 111
         );
112 112
         $final_price = $final_price !== null ? $final_price : $ticket->get_ticket_total_with_taxes();
113
-        return (float)$final_price;
113
+        return (float) $final_price;
114 114
     }
115 115
 
116 116
 
Please login to merge, or discard this patch.
core/business/EE_Registration_Processor.class.php 2 patches
Indentation   +775 added lines, -775 removed lines patch added patch discarded remove patch
@@ -27,781 +27,781 @@
 block discarded – undo
27 27
 class EE_Registration_Processor extends EE_Processor_Base
28 28
 {
29 29
 
30
-    /**
31
-     * @var EE_Registration_Processor $_instance
32
-     * @access    private
33
-     */
34
-    private static $_instance;
35
-
36
-    /**
37
-     * initial reg status at the beginning of this request.
38
-     * indexed by registration ID
39
-     *
40
-     * @var array
41
-     */
42
-    protected $_old_reg_status = array();
43
-
44
-    /**
45
-     * reg status at the end of the request after all processing.
46
-     * indexed by registration ID
47
-     *
48
-     * @var array
49
-     */
50
-    protected $_new_reg_status = array();
51
-
52
-    /**
53
-     * amounts paid at the end of the request after all processing.
54
-     * indexed by registration ID
55
-     *
56
-     * @var array
57
-     */
58
-    protected static $_amount_paid = array();
59
-
60
-    /**
61
-     * Cache of the reg final price for registrations corresponding to a ticket line item
62
-     *
63
-     * @deprecated
64
-     * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
-     */
66
-    protected $_reg_final_price_per_tkt_line_item;
67
-
68
-    /**
69
-     * @var EE_Request $request
70
-     */
71
-    protected $request;
72
-
73
-
74
-
75
-    /**
76
-     * @singleton method used to instantiate class object
77
-     * @param EE_Request|null $request
78
-     * @return EE_Registration_Processor instance
79
-     * @throws \InvalidArgumentException
80
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
-     */
83
-    public static function instance(EE_Request $request = null)
84
-    {
85
-        // check if class object is instantiated
86
-        if (! self::$_instance instanceof EE_Registration_Processor) {
87
-            if(! $request instanceof EE_Request) {
88
-                $request = LoaderFactory::getLoader()->getShared('EE_Request');
89
-            }
90
-            self::$_instance = new self($request);
91
-        }
92
-        return self::$_instance;
93
-    }
94
-
95
-
96
-    /**
97
-     * EE_Registration_Processor constructor.
98
-     *
99
-     * @param EE_Request $request
100
-     */
101
-    public function __construct(EE_Request $request)
102
-    {
103
-        $this->request = $request;
104
-    }
105
-
106
-
107
-
108
-    /**
109
-     * @param int $REG_ID
110
-     * @return string
111
-     */
112
-    public function old_reg_status($REG_ID)
113
-    {
114
-        return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
-    }
116
-
117
-
118
-
119
-    /**
120
-     * @param int    $REG_ID
121
-     * @param string $old_reg_status
122
-     */
123
-    public function set_old_reg_status($REG_ID, $old_reg_status)
124
-    {
125
-        // only set the first time
126
-        if (! isset($this->_old_reg_status[$REG_ID])) {
127
-            $this->_old_reg_status[$REG_ID] = $old_reg_status;
128
-        }
129
-    }
130
-
131
-
132
-
133
-    /**
134
-     * @param int $REG_ID
135
-     * @return string
136
-     */
137
-    public function new_reg_status($REG_ID)
138
-    {
139
-        return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     * @param int    $REG_ID
146
-     * @param string $new_reg_status
147
-     */
148
-    public function set_new_reg_status($REG_ID, $new_reg_status)
149
-    {
150
-        $this->_new_reg_status[$REG_ID] = $new_reg_status;
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * reg_status_updated
157
-     *
158
-     * @param int $REG_ID
159
-     * @return bool
160
-     */
161
-    public function reg_status_updated($REG_ID)
162
-    {
163
-        return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * @param EE_Registration $registration
170
-     * @throws EE_Error
171
-     * @throws EntityNotFoundException
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     * @throws ReflectionException
176
-     * @throws RuntimeException
177
-     */
178
-    public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
-    {
180
-        $this->toggle_incomplete_registration_status_to_default($registration, false);
181
-        $this->toggle_registration_status_for_default_approved_events($registration, false);
182
-        $this->toggle_registration_status_if_no_monies_owing($registration, false);
183
-        $registration->save();
184
-        // trigger notifications
185
-        $this->trigger_registration_update_notifications($registration);
186
-    }
187
-
188
-
189
-
190
-    /**
191
-     *    manually_update_registration_status
192
-     *
193
-     * @access public
194
-     * @param EE_Registration $registration
195
-     * @param string          $new_reg_status
196
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
-     *                              to client code
198
-     * @return bool
199
-     * @throws EE_Error
200
-     * @throws EntityNotFoundException
201
-     * @throws InvalidArgumentException
202
-     * @throws InvalidDataTypeException
203
-     * @throws InvalidInterfaceException
204
-     * @throws ReflectionException
205
-     * @throws RuntimeException
206
-     */
207
-    public function manually_update_registration_status(
208
-        EE_Registration $registration,
209
-        $new_reg_status = '',
210
-        $save = true
211
-    ) {
212
-        // set initial REG_Status
213
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
-        // set incoming REG_Status
215
-        $this->set_new_reg_status($registration->ID(), $new_reg_status);
216
-        // toggle reg status but only if it has changed and the user can do so
217
-        if (
218
-            $this->reg_status_updated($registration->ID())
219
-            && (
220
-                (! $this->request->isAdmin() || $this->request->isFrontAjax())
221
-                || EE_Registry::instance()->CAP->current_user_can(
222
-                    'ee_edit_registration',
223
-                    'toggle_registration_status',
224
-                    $registration->ID()
225
-                )
226
-            )
227
-        ) {
228
-            // change status to new value
229
-            $updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
-            if ($updated && $save) {
231
-                $registration->save();
232
-            }
233
-            return true;
234
-        }
235
-        return false;
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     *    toggle_incomplete_registration_status_to_default
242
-     *        changes any incomplete registrations to either the event or global default registration status
243
-     *
244
-     * @access public
245
-     * @param EE_Registration $registration
246
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
-     *                              to client code
248
-     * @param ContextInterface|null    $context
249
-     * @return void
250
-     * @throws EE_Error
251
-     * @throws InvalidArgumentException
252
-     * @throws ReflectionException
253
-     * @throws RuntimeException
254
-     * @throws EntityNotFoundException
255
-     * @throws InvalidDataTypeException
256
-     * @throws InvalidInterfaceException
257
-     */
258
-    public function toggle_incomplete_registration_status_to_default(
259
-        EE_Registration $registration,
260
-        $save = true,
261
-        ContextInterface $context = null
262
-    ) {
263
-        $existing_reg_status = $registration->status_ID();
264
-        // set initial REG_Status
265
-        $this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
-        // is the registration currently incomplete ?
267
-        if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
-            // grab default reg status for the event, if set
269
-            $event_default_registration_status = $registration->event()->default_registration_status();
270
-            // if no default reg status is set for the event, then use the global value
271
-            $STS_ID = ! empty($event_default_registration_status)
272
-                ? $event_default_registration_status
273
-                : EE_Registry::instance()->CFG->registration->default_STS_ID;
274
-            // if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
-            $STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
-                : $STS_ID;
277
-            // set incoming REG_Status
278
-            $this->set_new_reg_status($registration->ID(), $STS_ID);
279
-            $registration->set_status($STS_ID, false, $context);
280
-            if ($save) {
281
-                $registration->save();
282
-            }
283
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
-            if (! EE_Processor_Base::$IPN) {
285
-                // otherwise, send out notifications
286
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
-            }
288
-            // DEBUG LOG
289
-            //$this->log(
290
-            //	__CLASS__, __FUNCTION__, __LINE__,
291
-            //	$registration->transaction(),
292
-            //	array(
293
-            //		'IPN'                   => EE_Processor_Base::$IPN,
294
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
-            //	)
296
-            //);
297
-        }
298
-    }
299
-
300
-
301
-
302
-    /**
303
-     *    toggle_registration_status_for_default_approved_events
304
-     *
305
-     * @access public
306
-     * @param EE_Registration $registration
307
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
-     *                              to client code
309
-     * @return bool
310
-     * @throws EE_Error
311
-     * @throws EntityNotFoundException
312
-     * @throws InvalidArgumentException
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws ReflectionException
316
-     * @throws RuntimeException
317
-     */
318
-    public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
-    {
320
-        $reg_status = $registration->status_ID();
321
-        // set initial REG_Status
322
-        $this->set_old_reg_status($registration->ID(), $reg_status);
323
-        // if not already, toggle reg status to approved IF the event default reg status is approved
324
-        // ( as long as the registration wasn't cancelled or declined at some point )
325
-        if (
326
-            $reg_status !== EEM_Registration::status_id_cancelled
327
-            && $reg_status
328
-               !== EEM_Registration::status_id_declined
329
-            && $reg_status !== EEM_Registration::status_id_approved
330
-            && $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
-        ) {
332
-            // set incoming REG_Status
333
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
-            // toggle status to approved
335
-            $registration->set_status(EEM_Registration::status_id_approved);
336
-            if ($save) {
337
-                $registration->save();
338
-            }
339
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
-            if (! EE_Processor_Base::$IPN) {
341
-                // otherwise, send out notifications
342
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
-            }
344
-            // DEBUG LOG
345
-            //$this->log(
346
-            //	__CLASS__, __FUNCTION__, __LINE__,
347
-            //	$registration->transaction(),
348
-            //	array(
349
-            //		'IPN'                   => EE_Processor_Base::$IPN,
350
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
-            //	)
352
-            //);
353
-            return true;
354
-        }
355
-        return false;
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     *    toggle_registration_statuses_if_no_monies_owing
362
-     *
363
-     * @access public
364
-     * @param EE_Registration $registration
365
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
-     *                              to client code
367
-     * @param array           $additional_details
368
-     * @return bool
369
-     * @throws EE_Error
370
-     * @throws EntityNotFoundException
371
-     * @throws InvalidArgumentException
372
-     * @throws InvalidDataTypeException
373
-     * @throws InvalidInterfaceException
374
-     * @throws ReflectionException
375
-     * @throws RuntimeException
376
-     */
377
-    public function toggle_registration_status_if_no_monies_owing(
378
-        EE_Registration $registration,
379
-        $save = true,
380
-        array $additional_details = array()
381
-    ) {
382
-        // set initial REG_Status
383
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
-        // was a payment just made ?
385
-        $payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
-                      && $additional_details['payment_updates']
387
-                      && $additional_details['last_payment'] instanceof EE_Payment
388
-            ? $additional_details['last_payment']
389
-            : null;
390
-        $total_paid = array_sum(self::$_amount_paid);
391
-        // toggle reg status to approved IF
392
-        if (
393
-            // REG status is pending payment
394
-            $registration->status_ID() === EEM_Registration::status_id_pending_payment
395
-            // AND no monies are owing
396
-            && (
397
-                (
398
-                    $registration->transaction()->is_completed()
399
-                    || $registration->transaction()->is_overpaid()
400
-                    || $registration->transaction()->is_free()
401
-                    || apply_filters(
402
-                        'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
-                        false,
404
-                        $registration
405
-                    )
406
-                )
407
-                || (
408
-                    $payment instanceof EE_Payment && $payment->is_approved()
409
-                    && // this specific registration has not yet been paid for
410
-                    ! isset(self::$_amount_paid[$registration->ID()])
411
-                    && // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
-                    $payment->amount() - $total_paid >= $registration->final_price()
413
-                )
414
-            )
415
-        ) {
416
-            // mark as paid
417
-            self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
-            // track new REG_Status
419
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
-            // toggle status to approved
421
-            $registration->set_status(EEM_Registration::status_id_approved);
422
-            if ($save) {
423
-                $registration->save();
424
-            }
425
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
-            if (! EE_Processor_Base::$IPN) {
427
-                // otherwise, send out notifications
428
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
-            }
430
-            // DEBUG LOG
431
-            //$this->log(
432
-            //	__CLASS__, __FUNCTION__, __LINE__,
433
-            //	$registration->transaction(),
434
-            //	array(
435
-            //		'IPN'                   => EE_Processor_Base::$IPN,
436
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
-            //	)
438
-            //);
439
-            return true;
440
-        }
441
-        return false;
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     *    registration_status_changed
448
-     *
449
-     * @access public
450
-     * @param EE_Registration $registration
451
-     * @param array           $additional_details
452
-     * @return void
453
-     */
454
-    public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
-    {
456
-        try {
457
-            if (! $registration instanceof EE_Registration) {
458
-                throw new EE_Error(
459
-                    esc_html__('An invalid registration was received.', 'event_espresso')
460
-                );
461
-            }
462
-            // EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
-            // EEH_Debug_Tools::log(
464
-            // 	__CLASS__,
465
-            // 	__FUNCTION__,
466
-            // 	__LINE__,
467
-            // 	array( $registration->transaction(), $additional_details ),
468
-            // 	false,
469
-            // 	'EE_Transaction: ' . $registration->transaction()->ID()
470
-            // );
471
-            if (! $registration->is_primary_registrant()) {
472
-                return;
473
-            }
474
-            do_action(
475
-                'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
-                $registration,
477
-                $additional_details
478
-            );
479
-        } catch (Exception $e) {
480
-            EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
-        }
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
-     *
489
-     * @param EE_Registration $registration
490
-     * @param array           $additional_details
491
-     * @return bool
492
-     * @throws EE_Error
493
-     * @throws EntityNotFoundException
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidDataTypeException
496
-     * @throws InvalidInterfaceException
497
-     * @throws ReflectionException
498
-     * @throws RuntimeException
499
-     */
500
-    public function update_registration_after_checkout_or_payment(
501
-        EE_Registration $registration,
502
-        array $additional_details = array()
503
-    ) {
504
-        // set initial REG_Status
505
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
-        // if the registration status gets updated, then save the registration
507
-        if (
508
-            $this->toggle_registration_status_for_default_approved_events($registration, false)
509
-            || $this->toggle_registration_status_if_no_monies_owing(
510
-                $registration,
511
-                false,
512
-                $additional_details
513
-            )
514
-        ) {
515
-            $registration->save();
516
-        }
517
-        // set new  REG_Status
518
-        $this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
-        return $this->reg_status_updated($registration->ID())
520
-               && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     * Updates the registration' final prices based on the current line item tree (taking into account
527
-     * discounts, taxes, and other line items unrelated to tickets.)
528
-     *
529
-     * @param EE_Transaction $transaction
530
-     * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
-     * @return void
532
-     * @throws EE_Error
533
-     * @throws InvalidArgumentException
534
-     * @throws InvalidDataTypeException
535
-     * @throws InvalidInterfaceException
536
-     * @throws RuntimeException
537
-     */
538
-    public function update_registration_final_prices($transaction, $save_regs = true)
539
-    {
540
-        $reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
-            $transaction->total_line_item()
542
-        );
543
-        foreach ($transaction->registrations() as $registration) {
544
-            /** @var EE_Line_Item $line_item */
545
-            $line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
-            if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
-                $registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
-                if ($save_regs) {
549
-                    $registration->save();
550
-                }
551
-            }
552
-        }
553
-        //and make sure there's no rounding problem
554
-        $this->fix_reg_final_price_rounding_issue($transaction);
555
-    }
556
-
557
-
558
-
559
-    /**
560
-     * Makes sure there is no rounding errors for the REG_final_prices.
561
-     * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
-     * they will each be for $0.99333333, which gets rounded to $1 again.
563
-     * So the transaction total will be $2.99, but each registration will be for $1,
564
-     * so if each registrant paid individually they will have overpaid by $0.01.
565
-     * So in order to overcome this, we check for any difference, and if there is a difference
566
-     * we just grab one registrant at random and make them responsible for it.
567
-     * This should be used after setting REG_final_prices (it's done automatically as part of
568
-     * EE_Registration_Processor::update_registration_final_prices())
569
-     *
570
-     * @param EE_Transaction $transaction
571
-     * @return bool success verifying that there is NO difference after this method is done
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws InvalidDataTypeException
575
-     * @throws InvalidInterfaceException
576
-     */
577
-    public function fix_reg_final_price_rounding_issue($transaction)
578
-    {
579
-        $reg_final_price_sum = EEM_Registration::instance()->sum(
580
-            array(
581
-                array(
582
-                    'TXN_ID' => $transaction->ID(),
583
-                ),
584
-            ),
585
-            'REG_final_price'
586
-        );
587
-        $diff = $transaction->total() - $reg_final_price_sum;
588
-        //ok then, just grab one of the registrations
589
-        if ($diff !== 0) {
590
-            $a_reg   = EEM_Registration::instance()->get_one(
591
-                array(
592
-                    array(
593
-                        'TXN_ID' => $transaction->ID(),
594
-                    ),
595
-                )
596
-            );
597
-            return $a_reg instanceof EE_Registration
598
-                ? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
-                : false;
600
-        }
601
-        return true;
602
-    }
603
-
604
-
605
-
606
-    /**
607
-     * update_registration_after_being_canceled_or_declined
608
-     *
609
-     * @param EE_Registration $registration
610
-     * @param array           $closed_reg_statuses
611
-     * @param bool            $update_reg
612
-     * @return bool
613
-     * @throws EE_Error
614
-     * @throws RuntimeException
615
-     */
616
-    public function update_registration_after_being_canceled_or_declined(
617
-        EE_Registration $registration,
618
-        array $closed_reg_statuses = array(),
619
-        $update_reg = true
620
-    ) {
621
-        // these reg statuses should not be considered in any calculations involving monies owing
622
-        $closed_reg_statuses = ! empty($closed_reg_statuses)
623
-            ? $closed_reg_statuses
624
-            : EEM_Registration::closed_reg_statuses();
625
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
-            return false;
627
-        }
628
-        // release a reserved ticket by decrementing ticket and datetime reserved values
629
-        $registration->release_reserved_ticket(true, 'RegProcessor:'. __LINE__);
630
-        $registration->set_final_price(0);
631
-        if ($update_reg) {
632
-            $registration->save();
633
-        }
634
-        return true;
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     * update_canceled_or_declined_registration_after_being_reinstated
641
-     *
642
-     * @param EE_Registration $registration
643
-     * @param array           $closed_reg_statuses
644
-     * @param bool            $update_reg
645
-     * @return bool
646
-     * @throws EE_Error
647
-     * @throws RuntimeException
648
-     */
649
-    public function update_canceled_or_declined_registration_after_being_reinstated(
650
-        EE_Registration $registration,
651
-        array $closed_reg_statuses = array(),
652
-        $update_reg = true
653
-    ) {
654
-        // these reg statuses should not be considered in any calculations involving monies owing
655
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
-            : EEM_Registration::closed_reg_statuses();
657
-        if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
-            return false;
659
-        }
660
-        $ticket = $registration->ticket();
661
-        if (! $ticket instanceof EE_Ticket) {
662
-            throw new EE_Error(
663
-                sprintf(
664
-                    esc_html__(
665
-                        'The Ticket for Registration %1$d was not found or is invalid.',
666
-                        'event_espresso'
667
-                    ),
668
-                    $registration->ticket_ID()
669
-                )
670
-            );
671
-        }
672
-        $registration->set_final_price($ticket->price());
673
-        if ($update_reg) {
674
-            $registration->save();
675
-        }
676
-        return true;
677
-    }
678
-
679
-
680
-
681
-    /**
682
-     * generate_ONE_registration_from_line_item
683
-     * Although a ticket line item may have a quantity greater than 1,
684
-     * this method will ONLY CREATE ONE REGISTRATION !!!
685
-     * Regardless of the ticket line item quantity.
686
-     * This means that any code calling this method is responsible for ensuring
687
-     * that the final registration count matches the ticket line item quantity.
688
-     * This was done to make it easier to match the number of registrations
689
-     * to the number of tickets in the cart, when the cart has been edited
690
-     * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
-     * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
-     *
693
-     * @deprecated
694
-     * @since 4.9.1
695
-     * @param EE_Line_Item    $line_item
696
-     * @param \EE_Transaction $transaction
697
-     * @param int             $att_nmbr
698
-     * @param int             $total_ticket_count
699
-     * @return EE_Registration | null
700
-     * @throws \OutOfRangeException
701
-     * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
-     * @throws \EE_Error
703
-     */
704
-    public function generate_ONE_registration_from_line_item(
705
-        EE_Line_Item $line_item,
706
-        EE_Transaction $transaction,
707
-        $att_nmbr = 1,
708
-        $total_ticket_count = 1
709
-    ) {
710
-        EE_Error::doing_it_wrong(
711
-            __CLASS__ . '::' . __FUNCTION__,
712
-            sprintf(
713
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
-                '\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
-            ),
716
-            '4.9.1',
717
-            '5.0.0'
718
-        );
719
-        // grab the related ticket object for this line_item
720
-        $ticket = $line_item->ticket();
721
-        if (! $ticket instanceof EE_Ticket) {
722
-            EE_Error::add_error(
723
-                sprintf(
724
-                    esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
-                    $line_item->ID()
726
-                ),
727
-                __FILE__,
728
-                __FUNCTION__,
729
-                __LINE__
730
-            );
731
-            return null;
732
-        }
733
-        $registration_service = new CreateRegistrationService();
734
-        // then generate a new registration from that
735
-        return $registration_service->create(
736
-            $ticket->get_related_event(),
737
-            $transaction,
738
-            $ticket,
739
-            $line_item,
740
-            $att_nmbr,
741
-            $total_ticket_count
742
-        );
743
-    }
744
-
745
-
746
-
747
-    /**
748
-     * generates reg_url_link
749
-     *
750
-     * @deprecated
751
-     * @since 4.9.1
752
-     * @param int                   $att_nmbr
753
-     * @param EE_Line_Item | string $item
754
-     * @return string
755
-     * @throws InvalidArgumentException
756
-     */
757
-    public function generate_reg_url_link($att_nmbr, $item)
758
-    {
759
-        EE_Error::doing_it_wrong(
760
-            __CLASS__ . '::' . __FUNCTION__,
761
-            sprintf(
762
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
-                'EventEspresso\core\domain\entities\RegUrlLink'
764
-            ),
765
-            '4.9.1',
766
-            '5.0.0'
767
-        );
768
-        return new RegUrlLink($att_nmbr, $item);
769
-    }
770
-
771
-
772
-
773
-    /**
774
-     * generates reg code
775
-     *
776
-     * @deprecated
777
-     * @since 4.9.1
778
-     * @param EE_Registration $registration
779
-     * @return string
780
-     * @throws EE_Error
781
-     * @throws EntityNotFoundException
782
-     * @throws InvalidArgumentException
783
-     */
784
-    public function generate_reg_code(EE_Registration $registration)
785
-    {
786
-        EE_Error::doing_it_wrong(
787
-            __CLASS__ . '::' . __FUNCTION__,
788
-            sprintf(
789
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
-                'EventEspresso\core\domain\entities\RegCode'
791
-            ),
792
-            '4.9.1',
793
-            '5.0.0'
794
-        );
795
-        return apply_filters(
796
-            'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
-            new RegCode(
798
-                RegUrlLink::fromRegistration($registration),
799
-                $registration->transaction(),
800
-                $registration->ticket()
801
-            ),
802
-            $registration
803
-        );
804
-    }
30
+	/**
31
+	 * @var EE_Registration_Processor $_instance
32
+	 * @access    private
33
+	 */
34
+	private static $_instance;
35
+
36
+	/**
37
+	 * initial reg status at the beginning of this request.
38
+	 * indexed by registration ID
39
+	 *
40
+	 * @var array
41
+	 */
42
+	protected $_old_reg_status = array();
43
+
44
+	/**
45
+	 * reg status at the end of the request after all processing.
46
+	 * indexed by registration ID
47
+	 *
48
+	 * @var array
49
+	 */
50
+	protected $_new_reg_status = array();
51
+
52
+	/**
53
+	 * amounts paid at the end of the request after all processing.
54
+	 * indexed by registration ID
55
+	 *
56
+	 * @var array
57
+	 */
58
+	protected static $_amount_paid = array();
59
+
60
+	/**
61
+	 * Cache of the reg final price for registrations corresponding to a ticket line item
62
+	 *
63
+	 * @deprecated
64
+	 * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
+	 */
66
+	protected $_reg_final_price_per_tkt_line_item;
67
+
68
+	/**
69
+	 * @var EE_Request $request
70
+	 */
71
+	protected $request;
72
+
73
+
74
+
75
+	/**
76
+	 * @singleton method used to instantiate class object
77
+	 * @param EE_Request|null $request
78
+	 * @return EE_Registration_Processor instance
79
+	 * @throws \InvalidArgumentException
80
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
+	 */
83
+	public static function instance(EE_Request $request = null)
84
+	{
85
+		// check if class object is instantiated
86
+		if (! self::$_instance instanceof EE_Registration_Processor) {
87
+			if(! $request instanceof EE_Request) {
88
+				$request = LoaderFactory::getLoader()->getShared('EE_Request');
89
+			}
90
+			self::$_instance = new self($request);
91
+		}
92
+		return self::$_instance;
93
+	}
94
+
95
+
96
+	/**
97
+	 * EE_Registration_Processor constructor.
98
+	 *
99
+	 * @param EE_Request $request
100
+	 */
101
+	public function __construct(EE_Request $request)
102
+	{
103
+		$this->request = $request;
104
+	}
105
+
106
+
107
+
108
+	/**
109
+	 * @param int $REG_ID
110
+	 * @return string
111
+	 */
112
+	public function old_reg_status($REG_ID)
113
+	{
114
+		return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
+	}
116
+
117
+
118
+
119
+	/**
120
+	 * @param int    $REG_ID
121
+	 * @param string $old_reg_status
122
+	 */
123
+	public function set_old_reg_status($REG_ID, $old_reg_status)
124
+	{
125
+		// only set the first time
126
+		if (! isset($this->_old_reg_status[$REG_ID])) {
127
+			$this->_old_reg_status[$REG_ID] = $old_reg_status;
128
+		}
129
+	}
130
+
131
+
132
+
133
+	/**
134
+	 * @param int $REG_ID
135
+	 * @return string
136
+	 */
137
+	public function new_reg_status($REG_ID)
138
+	{
139
+		return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 * @param int    $REG_ID
146
+	 * @param string $new_reg_status
147
+	 */
148
+	public function set_new_reg_status($REG_ID, $new_reg_status)
149
+	{
150
+		$this->_new_reg_status[$REG_ID] = $new_reg_status;
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * reg_status_updated
157
+	 *
158
+	 * @param int $REG_ID
159
+	 * @return bool
160
+	 */
161
+	public function reg_status_updated($REG_ID)
162
+	{
163
+		return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * @param EE_Registration $registration
170
+	 * @throws EE_Error
171
+	 * @throws EntityNotFoundException
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws ReflectionException
176
+	 * @throws RuntimeException
177
+	 */
178
+	public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
+	{
180
+		$this->toggle_incomplete_registration_status_to_default($registration, false);
181
+		$this->toggle_registration_status_for_default_approved_events($registration, false);
182
+		$this->toggle_registration_status_if_no_monies_owing($registration, false);
183
+		$registration->save();
184
+		// trigger notifications
185
+		$this->trigger_registration_update_notifications($registration);
186
+	}
187
+
188
+
189
+
190
+	/**
191
+	 *    manually_update_registration_status
192
+	 *
193
+	 * @access public
194
+	 * @param EE_Registration $registration
195
+	 * @param string          $new_reg_status
196
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
+	 *                              to client code
198
+	 * @return bool
199
+	 * @throws EE_Error
200
+	 * @throws EntityNotFoundException
201
+	 * @throws InvalidArgumentException
202
+	 * @throws InvalidDataTypeException
203
+	 * @throws InvalidInterfaceException
204
+	 * @throws ReflectionException
205
+	 * @throws RuntimeException
206
+	 */
207
+	public function manually_update_registration_status(
208
+		EE_Registration $registration,
209
+		$new_reg_status = '',
210
+		$save = true
211
+	) {
212
+		// set initial REG_Status
213
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
+		// set incoming REG_Status
215
+		$this->set_new_reg_status($registration->ID(), $new_reg_status);
216
+		// toggle reg status but only if it has changed and the user can do so
217
+		if (
218
+			$this->reg_status_updated($registration->ID())
219
+			&& (
220
+				(! $this->request->isAdmin() || $this->request->isFrontAjax())
221
+				|| EE_Registry::instance()->CAP->current_user_can(
222
+					'ee_edit_registration',
223
+					'toggle_registration_status',
224
+					$registration->ID()
225
+				)
226
+			)
227
+		) {
228
+			// change status to new value
229
+			$updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
+			if ($updated && $save) {
231
+				$registration->save();
232
+			}
233
+			return true;
234
+		}
235
+		return false;
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 *    toggle_incomplete_registration_status_to_default
242
+	 *        changes any incomplete registrations to either the event or global default registration status
243
+	 *
244
+	 * @access public
245
+	 * @param EE_Registration $registration
246
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
+	 *                              to client code
248
+	 * @param ContextInterface|null    $context
249
+	 * @return void
250
+	 * @throws EE_Error
251
+	 * @throws InvalidArgumentException
252
+	 * @throws ReflectionException
253
+	 * @throws RuntimeException
254
+	 * @throws EntityNotFoundException
255
+	 * @throws InvalidDataTypeException
256
+	 * @throws InvalidInterfaceException
257
+	 */
258
+	public function toggle_incomplete_registration_status_to_default(
259
+		EE_Registration $registration,
260
+		$save = true,
261
+		ContextInterface $context = null
262
+	) {
263
+		$existing_reg_status = $registration->status_ID();
264
+		// set initial REG_Status
265
+		$this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
+		// is the registration currently incomplete ?
267
+		if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
+			// grab default reg status for the event, if set
269
+			$event_default_registration_status = $registration->event()->default_registration_status();
270
+			// if no default reg status is set for the event, then use the global value
271
+			$STS_ID = ! empty($event_default_registration_status)
272
+				? $event_default_registration_status
273
+				: EE_Registry::instance()->CFG->registration->default_STS_ID;
274
+			// if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
+			$STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
+				: $STS_ID;
277
+			// set incoming REG_Status
278
+			$this->set_new_reg_status($registration->ID(), $STS_ID);
279
+			$registration->set_status($STS_ID, false, $context);
280
+			if ($save) {
281
+				$registration->save();
282
+			}
283
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
+			if (! EE_Processor_Base::$IPN) {
285
+				// otherwise, send out notifications
286
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
+			}
288
+			// DEBUG LOG
289
+			//$this->log(
290
+			//	__CLASS__, __FUNCTION__, __LINE__,
291
+			//	$registration->transaction(),
292
+			//	array(
293
+			//		'IPN'                   => EE_Processor_Base::$IPN,
294
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
+			//	)
296
+			//);
297
+		}
298
+	}
299
+
300
+
301
+
302
+	/**
303
+	 *    toggle_registration_status_for_default_approved_events
304
+	 *
305
+	 * @access public
306
+	 * @param EE_Registration $registration
307
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
+	 *                              to client code
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 * @throws EntityNotFoundException
312
+	 * @throws InvalidArgumentException
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws ReflectionException
316
+	 * @throws RuntimeException
317
+	 */
318
+	public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
+	{
320
+		$reg_status = $registration->status_ID();
321
+		// set initial REG_Status
322
+		$this->set_old_reg_status($registration->ID(), $reg_status);
323
+		// if not already, toggle reg status to approved IF the event default reg status is approved
324
+		// ( as long as the registration wasn't cancelled or declined at some point )
325
+		if (
326
+			$reg_status !== EEM_Registration::status_id_cancelled
327
+			&& $reg_status
328
+			   !== EEM_Registration::status_id_declined
329
+			&& $reg_status !== EEM_Registration::status_id_approved
330
+			&& $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
+		) {
332
+			// set incoming REG_Status
333
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
+			// toggle status to approved
335
+			$registration->set_status(EEM_Registration::status_id_approved);
336
+			if ($save) {
337
+				$registration->save();
338
+			}
339
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
+			if (! EE_Processor_Base::$IPN) {
341
+				// otherwise, send out notifications
342
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
+			}
344
+			// DEBUG LOG
345
+			//$this->log(
346
+			//	__CLASS__, __FUNCTION__, __LINE__,
347
+			//	$registration->transaction(),
348
+			//	array(
349
+			//		'IPN'                   => EE_Processor_Base::$IPN,
350
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
+			//	)
352
+			//);
353
+			return true;
354
+		}
355
+		return false;
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 *    toggle_registration_statuses_if_no_monies_owing
362
+	 *
363
+	 * @access public
364
+	 * @param EE_Registration $registration
365
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
+	 *                              to client code
367
+	 * @param array           $additional_details
368
+	 * @return bool
369
+	 * @throws EE_Error
370
+	 * @throws EntityNotFoundException
371
+	 * @throws InvalidArgumentException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws InvalidInterfaceException
374
+	 * @throws ReflectionException
375
+	 * @throws RuntimeException
376
+	 */
377
+	public function toggle_registration_status_if_no_monies_owing(
378
+		EE_Registration $registration,
379
+		$save = true,
380
+		array $additional_details = array()
381
+	) {
382
+		// set initial REG_Status
383
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
+		// was a payment just made ?
385
+		$payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
+					  && $additional_details['payment_updates']
387
+					  && $additional_details['last_payment'] instanceof EE_Payment
388
+			? $additional_details['last_payment']
389
+			: null;
390
+		$total_paid = array_sum(self::$_amount_paid);
391
+		// toggle reg status to approved IF
392
+		if (
393
+			// REG status is pending payment
394
+			$registration->status_ID() === EEM_Registration::status_id_pending_payment
395
+			// AND no monies are owing
396
+			&& (
397
+				(
398
+					$registration->transaction()->is_completed()
399
+					|| $registration->transaction()->is_overpaid()
400
+					|| $registration->transaction()->is_free()
401
+					|| apply_filters(
402
+						'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
+						false,
404
+						$registration
405
+					)
406
+				)
407
+				|| (
408
+					$payment instanceof EE_Payment && $payment->is_approved()
409
+					&& // this specific registration has not yet been paid for
410
+					! isset(self::$_amount_paid[$registration->ID()])
411
+					&& // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
+					$payment->amount() - $total_paid >= $registration->final_price()
413
+				)
414
+			)
415
+		) {
416
+			// mark as paid
417
+			self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
+			// track new REG_Status
419
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
+			// toggle status to approved
421
+			$registration->set_status(EEM_Registration::status_id_approved);
422
+			if ($save) {
423
+				$registration->save();
424
+			}
425
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
+			if (! EE_Processor_Base::$IPN) {
427
+				// otherwise, send out notifications
428
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
+			}
430
+			// DEBUG LOG
431
+			//$this->log(
432
+			//	__CLASS__, __FUNCTION__, __LINE__,
433
+			//	$registration->transaction(),
434
+			//	array(
435
+			//		'IPN'                   => EE_Processor_Base::$IPN,
436
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
+			//	)
438
+			//);
439
+			return true;
440
+		}
441
+		return false;
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 *    registration_status_changed
448
+	 *
449
+	 * @access public
450
+	 * @param EE_Registration $registration
451
+	 * @param array           $additional_details
452
+	 * @return void
453
+	 */
454
+	public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
+	{
456
+		try {
457
+			if (! $registration instanceof EE_Registration) {
458
+				throw new EE_Error(
459
+					esc_html__('An invalid registration was received.', 'event_espresso')
460
+				);
461
+			}
462
+			// EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
+			// EEH_Debug_Tools::log(
464
+			// 	__CLASS__,
465
+			// 	__FUNCTION__,
466
+			// 	__LINE__,
467
+			// 	array( $registration->transaction(), $additional_details ),
468
+			// 	false,
469
+			// 	'EE_Transaction: ' . $registration->transaction()->ID()
470
+			// );
471
+			if (! $registration->is_primary_registrant()) {
472
+				return;
473
+			}
474
+			do_action(
475
+				'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
+				$registration,
477
+				$additional_details
478
+			);
479
+		} catch (Exception $e) {
480
+			EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
+		}
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
+	 *
489
+	 * @param EE_Registration $registration
490
+	 * @param array           $additional_details
491
+	 * @return bool
492
+	 * @throws EE_Error
493
+	 * @throws EntityNotFoundException
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws InvalidInterfaceException
497
+	 * @throws ReflectionException
498
+	 * @throws RuntimeException
499
+	 */
500
+	public function update_registration_after_checkout_or_payment(
501
+		EE_Registration $registration,
502
+		array $additional_details = array()
503
+	) {
504
+		// set initial REG_Status
505
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
+		// if the registration status gets updated, then save the registration
507
+		if (
508
+			$this->toggle_registration_status_for_default_approved_events($registration, false)
509
+			|| $this->toggle_registration_status_if_no_monies_owing(
510
+				$registration,
511
+				false,
512
+				$additional_details
513
+			)
514
+		) {
515
+			$registration->save();
516
+		}
517
+		// set new  REG_Status
518
+		$this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
+		return $this->reg_status_updated($registration->ID())
520
+			   && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 * Updates the registration' final prices based on the current line item tree (taking into account
527
+	 * discounts, taxes, and other line items unrelated to tickets.)
528
+	 *
529
+	 * @param EE_Transaction $transaction
530
+	 * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
+	 * @return void
532
+	 * @throws EE_Error
533
+	 * @throws InvalidArgumentException
534
+	 * @throws InvalidDataTypeException
535
+	 * @throws InvalidInterfaceException
536
+	 * @throws RuntimeException
537
+	 */
538
+	public function update_registration_final_prices($transaction, $save_regs = true)
539
+	{
540
+		$reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
+			$transaction->total_line_item()
542
+		);
543
+		foreach ($transaction->registrations() as $registration) {
544
+			/** @var EE_Line_Item $line_item */
545
+			$line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
+			if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
+				$registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
+				if ($save_regs) {
549
+					$registration->save();
550
+				}
551
+			}
552
+		}
553
+		//and make sure there's no rounding problem
554
+		$this->fix_reg_final_price_rounding_issue($transaction);
555
+	}
556
+
557
+
558
+
559
+	/**
560
+	 * Makes sure there is no rounding errors for the REG_final_prices.
561
+	 * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
+	 * they will each be for $0.99333333, which gets rounded to $1 again.
563
+	 * So the transaction total will be $2.99, but each registration will be for $1,
564
+	 * so if each registrant paid individually they will have overpaid by $0.01.
565
+	 * So in order to overcome this, we check for any difference, and if there is a difference
566
+	 * we just grab one registrant at random and make them responsible for it.
567
+	 * This should be used after setting REG_final_prices (it's done automatically as part of
568
+	 * EE_Registration_Processor::update_registration_final_prices())
569
+	 *
570
+	 * @param EE_Transaction $transaction
571
+	 * @return bool success verifying that there is NO difference after this method is done
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws InvalidInterfaceException
576
+	 */
577
+	public function fix_reg_final_price_rounding_issue($transaction)
578
+	{
579
+		$reg_final_price_sum = EEM_Registration::instance()->sum(
580
+			array(
581
+				array(
582
+					'TXN_ID' => $transaction->ID(),
583
+				),
584
+			),
585
+			'REG_final_price'
586
+		);
587
+		$diff = $transaction->total() - $reg_final_price_sum;
588
+		//ok then, just grab one of the registrations
589
+		if ($diff !== 0) {
590
+			$a_reg   = EEM_Registration::instance()->get_one(
591
+				array(
592
+					array(
593
+						'TXN_ID' => $transaction->ID(),
594
+					),
595
+				)
596
+			);
597
+			return $a_reg instanceof EE_Registration
598
+				? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
+				: false;
600
+		}
601
+		return true;
602
+	}
603
+
604
+
605
+
606
+	/**
607
+	 * update_registration_after_being_canceled_or_declined
608
+	 *
609
+	 * @param EE_Registration $registration
610
+	 * @param array           $closed_reg_statuses
611
+	 * @param bool            $update_reg
612
+	 * @return bool
613
+	 * @throws EE_Error
614
+	 * @throws RuntimeException
615
+	 */
616
+	public function update_registration_after_being_canceled_or_declined(
617
+		EE_Registration $registration,
618
+		array $closed_reg_statuses = array(),
619
+		$update_reg = true
620
+	) {
621
+		// these reg statuses should not be considered in any calculations involving monies owing
622
+		$closed_reg_statuses = ! empty($closed_reg_statuses)
623
+			? $closed_reg_statuses
624
+			: EEM_Registration::closed_reg_statuses();
625
+		if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
+			return false;
627
+		}
628
+		// release a reserved ticket by decrementing ticket and datetime reserved values
629
+		$registration->release_reserved_ticket(true, 'RegProcessor:'. __LINE__);
630
+		$registration->set_final_price(0);
631
+		if ($update_reg) {
632
+			$registration->save();
633
+		}
634
+		return true;
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 * update_canceled_or_declined_registration_after_being_reinstated
641
+	 *
642
+	 * @param EE_Registration $registration
643
+	 * @param array           $closed_reg_statuses
644
+	 * @param bool            $update_reg
645
+	 * @return bool
646
+	 * @throws EE_Error
647
+	 * @throws RuntimeException
648
+	 */
649
+	public function update_canceled_or_declined_registration_after_being_reinstated(
650
+		EE_Registration $registration,
651
+		array $closed_reg_statuses = array(),
652
+		$update_reg = true
653
+	) {
654
+		// these reg statuses should not be considered in any calculations involving monies owing
655
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
+			: EEM_Registration::closed_reg_statuses();
657
+		if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
+			return false;
659
+		}
660
+		$ticket = $registration->ticket();
661
+		if (! $ticket instanceof EE_Ticket) {
662
+			throw new EE_Error(
663
+				sprintf(
664
+					esc_html__(
665
+						'The Ticket for Registration %1$d was not found or is invalid.',
666
+						'event_espresso'
667
+					),
668
+					$registration->ticket_ID()
669
+				)
670
+			);
671
+		}
672
+		$registration->set_final_price($ticket->price());
673
+		if ($update_reg) {
674
+			$registration->save();
675
+		}
676
+		return true;
677
+	}
678
+
679
+
680
+
681
+	/**
682
+	 * generate_ONE_registration_from_line_item
683
+	 * Although a ticket line item may have a quantity greater than 1,
684
+	 * this method will ONLY CREATE ONE REGISTRATION !!!
685
+	 * Regardless of the ticket line item quantity.
686
+	 * This means that any code calling this method is responsible for ensuring
687
+	 * that the final registration count matches the ticket line item quantity.
688
+	 * This was done to make it easier to match the number of registrations
689
+	 * to the number of tickets in the cart, when the cart has been edited
690
+	 * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
+	 * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
+	 *
693
+	 * @deprecated
694
+	 * @since 4.9.1
695
+	 * @param EE_Line_Item    $line_item
696
+	 * @param \EE_Transaction $transaction
697
+	 * @param int             $att_nmbr
698
+	 * @param int             $total_ticket_count
699
+	 * @return EE_Registration | null
700
+	 * @throws \OutOfRangeException
701
+	 * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
+	 * @throws \EE_Error
703
+	 */
704
+	public function generate_ONE_registration_from_line_item(
705
+		EE_Line_Item $line_item,
706
+		EE_Transaction $transaction,
707
+		$att_nmbr = 1,
708
+		$total_ticket_count = 1
709
+	) {
710
+		EE_Error::doing_it_wrong(
711
+			__CLASS__ . '::' . __FUNCTION__,
712
+			sprintf(
713
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
+				'\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
+			),
716
+			'4.9.1',
717
+			'5.0.0'
718
+		);
719
+		// grab the related ticket object for this line_item
720
+		$ticket = $line_item->ticket();
721
+		if (! $ticket instanceof EE_Ticket) {
722
+			EE_Error::add_error(
723
+				sprintf(
724
+					esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
+					$line_item->ID()
726
+				),
727
+				__FILE__,
728
+				__FUNCTION__,
729
+				__LINE__
730
+			);
731
+			return null;
732
+		}
733
+		$registration_service = new CreateRegistrationService();
734
+		// then generate a new registration from that
735
+		return $registration_service->create(
736
+			$ticket->get_related_event(),
737
+			$transaction,
738
+			$ticket,
739
+			$line_item,
740
+			$att_nmbr,
741
+			$total_ticket_count
742
+		);
743
+	}
744
+
745
+
746
+
747
+	/**
748
+	 * generates reg_url_link
749
+	 *
750
+	 * @deprecated
751
+	 * @since 4.9.1
752
+	 * @param int                   $att_nmbr
753
+	 * @param EE_Line_Item | string $item
754
+	 * @return string
755
+	 * @throws InvalidArgumentException
756
+	 */
757
+	public function generate_reg_url_link($att_nmbr, $item)
758
+	{
759
+		EE_Error::doing_it_wrong(
760
+			__CLASS__ . '::' . __FUNCTION__,
761
+			sprintf(
762
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
+				'EventEspresso\core\domain\entities\RegUrlLink'
764
+			),
765
+			'4.9.1',
766
+			'5.0.0'
767
+		);
768
+		return new RegUrlLink($att_nmbr, $item);
769
+	}
770
+
771
+
772
+
773
+	/**
774
+	 * generates reg code
775
+	 *
776
+	 * @deprecated
777
+	 * @since 4.9.1
778
+	 * @param EE_Registration $registration
779
+	 * @return string
780
+	 * @throws EE_Error
781
+	 * @throws EntityNotFoundException
782
+	 * @throws InvalidArgumentException
783
+	 */
784
+	public function generate_reg_code(EE_Registration $registration)
785
+	{
786
+		EE_Error::doing_it_wrong(
787
+			__CLASS__ . '::' . __FUNCTION__,
788
+			sprintf(
789
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
+				'EventEspresso\core\domain\entities\RegCode'
791
+			),
792
+			'4.9.1',
793
+			'5.0.0'
794
+		);
795
+		return apply_filters(
796
+			'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
+			new RegCode(
798
+				RegUrlLink::fromRegistration($registration),
799
+				$registration->transaction(),
800
+				$registration->ticket()
801
+			),
802
+			$registration
803
+		);
804
+	}
805 805
 
806 806
 
807 807
 
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -83,8 +83,8 @@  discard block
 block discarded – undo
83 83
     public static function instance(EE_Request $request = null)
84 84
     {
85 85
         // check if class object is instantiated
86
-        if (! self::$_instance instanceof EE_Registration_Processor) {
87
-            if(! $request instanceof EE_Request) {
86
+        if ( ! self::$_instance instanceof EE_Registration_Processor) {
87
+            if ( ! $request instanceof EE_Request) {
88 88
                 $request = LoaderFactory::getLoader()->getShared('EE_Request');
89 89
             }
90 90
             self::$_instance = new self($request);
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
     public function set_old_reg_status($REG_ID, $old_reg_status)
124 124
     {
125 125
         // only set the first time
126
-        if (! isset($this->_old_reg_status[$REG_ID])) {
126
+        if ( ! isset($this->_old_reg_status[$REG_ID])) {
127 127
             $this->_old_reg_status[$REG_ID] = $old_reg_status;
128 128
         }
129 129
     }
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
         if (
218 218
             $this->reg_status_updated($registration->ID())
219 219
             && (
220
-                (! $this->request->isAdmin() || $this->request->isFrontAjax())
220
+                ( ! $this->request->isAdmin() || $this->request->isFrontAjax())
221 221
                 || EE_Registry::instance()->CAP->current_user_can(
222 222
                     'ee_edit_registration',
223 223
                     'toggle_registration_status',
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
                 $registration->save();
282 282
             }
283 283
             // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
-            if (! EE_Processor_Base::$IPN) {
284
+            if ( ! EE_Processor_Base::$IPN) {
285 285
                 // otherwise, send out notifications
286 286
                 add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287 287
             }
@@ -337,7 +337,7 @@  discard block
 block discarded – undo
337 337
                 $registration->save();
338 338
             }
339 339
             // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
-            if (! EE_Processor_Base::$IPN) {
340
+            if ( ! EE_Processor_Base::$IPN) {
341 341
                 // otherwise, send out notifications
342 342
                 add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343 343
             }
@@ -382,7 +382,7 @@  discard block
 block discarded – undo
382 382
         // set initial REG_Status
383 383
         $this->set_old_reg_status($registration->ID(), $registration->status_ID());
384 384
         // was a payment just made ?
385
-        $payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
385
+        $payment = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386 386
                       && $additional_details['payment_updates']
387 387
                       && $additional_details['last_payment'] instanceof EE_Payment
388 388
             ? $additional_details['last_payment']
@@ -423,7 +423,7 @@  discard block
 block discarded – undo
423 423
                 $registration->save();
424 424
             }
425 425
             // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
-            if (! EE_Processor_Base::$IPN) {
426
+            if ( ! EE_Processor_Base::$IPN) {
427 427
                 // otherwise, send out notifications
428 428
                 add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429 429
             }
@@ -454,7 +454,7 @@  discard block
 block discarded – undo
454 454
     public function trigger_registration_update_notifications($registration, array $additional_details = array())
455 455
     {
456 456
         try {
457
-            if (! $registration instanceof EE_Registration) {
457
+            if ( ! $registration instanceof EE_Registration) {
458 458
                 throw new EE_Error(
459 459
                     esc_html__('An invalid registration was received.', 'event_espresso')
460 460
                 );
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
             // 	false,
469 469
             // 	'EE_Transaction: ' . $registration->transaction()->ID()
470 470
             // );
471
-            if (! $registration->is_primary_registrant()) {
471
+            if ( ! $registration->is_primary_registrant()) {
472 472
                 return;
473 473
             }
474 474
             do_action(
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
         $diff = $transaction->total() - $reg_final_price_sum;
588 588
         //ok then, just grab one of the registrations
589 589
         if ($diff !== 0) {
590
-            $a_reg   = EEM_Registration::instance()->get_one(
590
+            $a_reg = EEM_Registration::instance()->get_one(
591 591
                 array(
592 592
                     array(
593 593
                         'TXN_ID' => $transaction->ID(),
@@ -622,11 +622,11 @@  discard block
 block discarded – undo
622 622
         $closed_reg_statuses = ! empty($closed_reg_statuses)
623 623
             ? $closed_reg_statuses
624 624
             : EEM_Registration::closed_reg_statuses();
625
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
625
+        if ( ! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626 626
             return false;
627 627
         }
628 628
         // release a reserved ticket by decrementing ticket and datetime reserved values
629
-        $registration->release_reserved_ticket(true, 'RegProcessor:'. __LINE__);
629
+        $registration->release_reserved_ticket(true, 'RegProcessor:'.__LINE__);
630 630
         $registration->set_final_price(0);
631 631
         if ($update_reg) {
632 632
             $registration->save();
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
             return false;
659 659
         }
660 660
         $ticket = $registration->ticket();
661
-        if (! $ticket instanceof EE_Ticket) {
661
+        if ( ! $ticket instanceof EE_Ticket) {
662 662
             throw new EE_Error(
663 663
                 sprintf(
664 664
                     esc_html__(
@@ -708,7 +708,7 @@  discard block
 block discarded – undo
708 708
         $total_ticket_count = 1
709 709
     ) {
710 710
         EE_Error::doing_it_wrong(
711
-            __CLASS__ . '::' . __FUNCTION__,
711
+            __CLASS__.'::'.__FUNCTION__,
712 712
             sprintf(
713 713
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714 714
                 '\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
@@ -718,7 +718,7 @@  discard block
 block discarded – undo
718 718
         );
719 719
         // grab the related ticket object for this line_item
720 720
         $ticket = $line_item->ticket();
721
-        if (! $ticket instanceof EE_Ticket) {
721
+        if ( ! $ticket instanceof EE_Ticket) {
722 722
             EE_Error::add_error(
723 723
                 sprintf(
724 724
                     esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
@@ -757,7 +757,7 @@  discard block
 block discarded – undo
757 757
     public function generate_reg_url_link($att_nmbr, $item)
758 758
     {
759 759
         EE_Error::doing_it_wrong(
760
-            __CLASS__ . '::' . __FUNCTION__,
760
+            __CLASS__.'::'.__FUNCTION__,
761 761
             sprintf(
762 762
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763 763
                 'EventEspresso\core\domain\entities\RegUrlLink'
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
     public function generate_reg_code(EE_Registration $registration)
785 785
     {
786 786
         EE_Error::doing_it_wrong(
787
-            __CLASS__ . '::' . __FUNCTION__,
787
+            __CLASS__.'::'.__FUNCTION__,
788 788
             sprintf(
789 789
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790 790
                 'EventEspresso\core\domain\entities\RegCode'
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 2 patches
Indentation   +2017 added lines, -2017 removed lines patch added patch discarded remove patch
@@ -18,2023 +18,2023 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * Used to reference when a registration has never been checked in.
23
-     *
24
-     * @deprecated use \EE_Checkin::status_checked_never instead
25
-     * @type int
26
-     */
27
-    const checkin_status_never = 2;
28
-
29
-    /**
30
-     * Used to reference when a registration has been checked in.
31
-     *
32
-     * @deprecated use \EE_Checkin::status_checked_in instead
33
-     * @type int
34
-     */
35
-    const checkin_status_in = 1;
36
-
37
-
38
-    /**
39
-     * Used to reference when a registration has been checked out.
40
-     *
41
-     * @deprecated use \EE_Checkin::status_checked_out instead
42
-     * @type int
43
-     */
44
-    const checkin_status_out = 0;
45
-
46
-
47
-    /**
48
-     * extra meta key for tracking reg status os trashed registrations
49
-     *
50
-     * @type string
51
-     */
52
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
-
54
-
55
-    /**
56
-     * extra meta key for tracking if registration has reserved ticket
57
-     *
58
-     * @type string
59
-     */
60
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
-
62
-
63
-    /**
64
-     * @param array  $props_n_values          incoming values
65
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
-     *                                        used.)
67
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
-     *                                        date_format and the second value is the time format
69
-     * @return EE_Registration
70
-     * @throws EE_Error
71
-     */
72
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
-    {
74
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Registration
84
-     */
85
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
-    {
87
-        return new self($props_n_values, true, $timezone);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Event ID
93
-     *
94
-     * @param        int $EVT_ID Event ID
95
-     * @throws EE_Error
96
-     * @throws RuntimeException
97
-     */
98
-    public function set_event($EVT_ID = 0)
99
-    {
100
-        $this->set('EVT_ID', $EVT_ID);
101
-    }
102
-
103
-
104
-    /**
105
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
-     * be routed to internal methods
107
-     *
108
-     * @param string $field_name
109
-     * @param mixed  $field_value
110
-     * @param bool   $use_default
111
-     * @throws EE_Error
112
-     * @throws EntityNotFoundException
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     * @throws ReflectionException
117
-     * @throws RuntimeException
118
-     */
119
-    public function set($field_name, $field_value, $use_default = false)
120
-    {
121
-        switch ($field_name) {
122
-            case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
124
-                    $this->set_reg_code($field_value, $use_default);
125
-                }
126
-                break;
127
-            case 'STS_ID':
128
-                $this->set_status($field_value, $use_default);
129
-                break;
130
-            default:
131
-                parent::set($field_name, $field_value, $use_default);
132
-        }
133
-    }
134
-
135
-
136
-    /**
137
-     * Set Status ID
138
-     * updates the registration status and ALSO...
139
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
-     *
142
-     * @param string       $new_STS_ID
143
-     * @param boolean      $use_default
144
-     * @param ContextInterface|null $context
145
-     * @return bool
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws ReflectionException
150
-     * @throws RuntimeException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     */
154
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
155
-    {
156
-        // get current REG_Status
157
-        $old_STS_ID = $this->status_ID();
158
-        // if status has changed
159
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
-            && ! empty($old_STS_ID) // and that old status is actually set
161
-            && ! empty($new_STS_ID) // as well as the new status
162
-            && $this->ID() // ensure registration is in the db
163
-        ) {
164
-            // TO approved
165
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
-                // reserve a space by incrementing ticket and datetime sold values
167
-                $this->_reserve_registration_space();
168
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
-                // OR FROM  approved
170
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
-                // release a space by decrementing ticket and datetime sold values
172
-                $this->_release_registration_space();
173
-                do_action(
174
-                    'AHEE__EE_Registration__set_status__from_approved',
175
-                    $this,
176
-                    $old_STS_ID,
177
-                    $new_STS_ID,
178
-                    $context
179
-                );
180
-            }
181
-            // update status
182
-            parent::set('STS_ID', $new_STS_ID, $use_default);
183
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
185
-                $this->updateTransactionAfterStatusChange();
186
-            }
187
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
-            return true;
189
-        }
190
-        //even though the old value matches the new value, it's still good to
191
-        //allow the parent set method to have a say
192
-        parent::set('STS_ID', $new_STS_ID, $use_default);
193
-        return true;
194
-    }
195
-
196
-
197
-    /**
198
-     * update REGs and TXN when cancelled or declined registrations involved
199
-     *
200
-     * @param string       $new_STS_ID
201
-     * @param string       $old_STS_ID
202
-     * @param ContextInterface|null $context
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws ReflectionException
208
-     */
209
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
210
-    {
211
-        // these reg statuses should not be considered in any calculations involving monies owing
212
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
-        // true if registration has been cancelled or declined
214
-        $this->updateIfCanceled(
215
-            $closed_reg_statuses,
216
-            $new_STS_ID,
217
-            $old_STS_ID,
218
-            $context
219
-        );
220
-        $this->updateIfDeclined(
221
-            $closed_reg_statuses,
222
-            $new_STS_ID,
223
-            $old_STS_ID,
224
-            $context
225
-        );
226
-    }
227
-
228
-
229
-    /**
230
-     * update REGs and TXN when cancelled or declined registrations involved
231
-     *
232
-     * @param array        $closed_reg_statuses
233
-     * @param string       $new_STS_ID
234
-     * @param string       $old_STS_ID
235
-     * @param ContextInterface|null $context
236
-     * @throws EE_Error
237
-     * @throws InvalidArgumentException
238
-     * @throws InvalidDataTypeException
239
-     * @throws InvalidInterfaceException
240
-     * @throws ReflectionException
241
-     */
242
-    private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
243
-    {
244
-        // true if registration has been cancelled or declined
245
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
-        ) {
248
-            /** @type EE_Registration_Processor $registration_processor */
249
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
-            /** @type EE_Transaction_Processor $transaction_processor */
251
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
-            // cancelled or declined registration
253
-            $registration_processor->update_registration_after_being_canceled_or_declined(
254
-                $this,
255
-                $closed_reg_statuses
256
-            );
257
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
-                $this,
259
-                $closed_reg_statuses,
260
-                false
261
-            );
262
-            do_action(
263
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
264
-                $this,
265
-                $old_STS_ID,
266
-                $new_STS_ID,
267
-                $context
268
-            );
269
-            return;
270
-        }
271
-    }
272
-
273
-
274
-    /**
275
-     * update REGs and TXN when cancelled or declined registrations involved
276
-     *
277
-     * @param array        $closed_reg_statuses
278
-     * @param string       $new_STS_ID
279
-     * @param string       $old_STS_ID
280
-     * @param ContextInterface|null $context
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
288
-    {
289
-        // true if reinstating cancelled or declined registration
290
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
-        ) {
293
-            /** @type EE_Registration_Processor $registration_processor */
294
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
-            /** @type EE_Transaction_Processor $transaction_processor */
296
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
-            // reinstating cancelled or declined registration
298
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
-                $this,
300
-                $closed_reg_statuses
301
-            );
302
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
-                $this,
304
-                $closed_reg_statuses,
305
-                false
306
-            );
307
-            do_action(
308
-                'AHEE__EE_Registration__set_status__after_reinstated',
309
-                $this,
310
-                $old_STS_ID,
311
-                $new_STS_ID,
312
-                $context
313
-            );
314
-        }
315
-    }
316
-
317
-
318
-    /**
319
-     * @param ContextInterface|null $context
320
-     * @return bool
321
-     */
322
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
323
-    {
324
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
325
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
-            array('spco_reg_step_attendee_information_process_registrations'),
327
-            $context,
328
-            $this
329
-        );
330
-        return ! (
331
-            $context instanceof ContextInterface
332
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
-        );
334
-    }
335
-
336
-
337
-    /**
338
-     * @throws EE_Error
339
-     * @throws EntityNotFoundException
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     * @throws RuntimeException
345
-     */
346
-    private function updateTransactionAfterStatusChange()
347
-    {
348
-        /** @type EE_Transaction_Payments $transaction_payments */
349
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
-        $this->transaction()->update_status_based_on_total_paid(true);
352
-    }
353
-
354
-
355
-    /**
356
-     *        get Status ID
357
-     */
358
-    public function status_ID()
359
-    {
360
-        return $this->get('STS_ID');
361
-    }
362
-
363
-
364
-    /**
365
-     * increments this registration's related ticket sold and corresponding datetime sold values
366
-     *
367
-     * @return void
368
-     * @throws EE_Error
369
-     * @throws EntityNotFoundException
370
-     */
371
-    private function _reserve_registration_space()
372
-    {
373
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
374
-        // so stop tracking that this reg has a ticket reserved
375
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:". __LINE__ . ')');
376
-        $ticket = $this->ticket();
377
-        $ticket->increase_sold();
378
-        $ticket->save();
379
-        // possibly set event status to sold out
380
-        $this->event()->perform_sold_out_status_check();
381
-    }
382
-
383
-
384
-    /**
385
-     * Gets the ticket this registration is for
386
-     *
387
-     * @param boolean $include_archived whether to include archived tickets or not.
388
-     *
389
-     * @return EE_Ticket|EE_Base_Class
390
-     * @throws EE_Error
391
-     */
392
-    public function ticket($include_archived = true)
393
-    {
394
-        $query_params = array();
395
-        if ($include_archived) {
396
-            $query_params['default_where_conditions'] = 'none';
397
-        }
398
-        return $this->get_first_related('Ticket', $query_params);
399
-    }
400
-
401
-
402
-    /**
403
-     * Gets the event this registration is for
404
-     *
405
-     * @return EE_Event
406
-     * @throws EE_Error
407
-     * @throws EntityNotFoundException
408
-     */
409
-    public function event()
410
-    {
411
-        $event = $this->get_first_related('Event');
412
-        if (! $event instanceof \EE_Event) {
413
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
414
-        }
415
-        return $event;
416
-    }
417
-
418
-
419
-    /**
420
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
421
-     * with the author of the event this registration is for.
422
-     *
423
-     * @since 4.5.0
424
-     * @return int
425
-     * @throws EE_Error
426
-     * @throws EntityNotFoundException
427
-     */
428
-    public function wp_user()
429
-    {
430
-        $event = $this->event();
431
-        if ($event instanceof EE_Event) {
432
-            return $event->wp_user();
433
-        }
434
-        return 0;
435
-    }
436
-
437
-
438
-    /**
439
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
440
-     *
441
-     * @return void
442
-     * @throws EE_Error
443
-     */
444
-    private function _release_registration_space()
445
-    {
446
-        $ticket = $this->ticket();
447
-        $ticket->decrease_sold();
448
-        $ticket->save();
449
-    }
450
-
451
-
452
-    /**
453
-     * tracks this registration's ticket reservation in extra meta
454
-     * and can increment related ticket reserved and corresponding datetime reserved values
455
-     *
456
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
457
-     * @return void
458
-     * @throws EE_Error
459
-     * @throws InvalidArgumentException
460
-     * @throws InvalidDataTypeException
461
-     * @throws InvalidInterfaceException
462
-     * @throws ReflectionException
463
-     */
464
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
465
-    {
466
-        // only reserve ticket if space is not currently reserved
467
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
468
-            $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
469
-            // IMPORTANT !!!
470
-            // although checking $update_ticket first would be more efficient,
471
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
472
-            if (
473
-                $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
474
-                && $update_ticket
475
-            ) {
476
-                $ticket = $this->ticket();
477
-                $ticket->increase_reserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
478
-                $ticket->save();
479
-            }
480
-        }
481
-    }
482
-
483
-
484
-    /**
485
-     * stops tracking this registration's ticket reservation in extra meta
486
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
487
-     *
488
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
489
-     * @return void
490
-     * @throws EE_Error
491
-     * @throws InvalidArgumentException
492
-     * @throws InvalidDataTypeException
493
-     * @throws InvalidInterfaceException
494
-     * @throws ReflectionException
495
-     */
496
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
497
-    {
498
-        // only release ticket if space is currently reserved
499
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
500
-            $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
501
-            // IMPORTANT !!!
502
-            // although checking $update_ticket first would be more efficient,
503
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
504
-            if (
505
-                $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
506
-                && $update_ticket
507
-            ) {
508
-                $ticket = $this->ticket();
509
-                $ticket->decrease_reserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
510
-                $ticket->save();
511
-            }
512
-        }
513
-    }
514
-
515
-
516
-    /**
517
-     * Set Attendee ID
518
-     *
519
-     * @param        int $ATT_ID Attendee ID
520
-     * @throws EE_Error
521
-     * @throws RuntimeException
522
-     */
523
-    public function set_attendee_id($ATT_ID = 0)
524
-    {
525
-        $this->set('ATT_ID', $ATT_ID);
526
-    }
527
-
528
-
529
-    /**
530
-     *        Set Transaction ID
531
-     *
532
-     * @param        int $TXN_ID Transaction ID
533
-     * @throws EE_Error
534
-     * @throws RuntimeException
535
-     */
536
-    public function set_transaction_id($TXN_ID = 0)
537
-    {
538
-        $this->set('TXN_ID', $TXN_ID);
539
-    }
540
-
541
-
542
-    /**
543
-     *        Set Session
544
-     *
545
-     * @param    string $REG_session PHP Session ID
546
-     * @throws EE_Error
547
-     * @throws RuntimeException
548
-     */
549
-    public function set_session($REG_session = '')
550
-    {
551
-        $this->set('REG_session', $REG_session);
552
-    }
553
-
554
-
555
-    /**
556
-     *        Set Registration URL Link
557
-     *
558
-     * @param    string $REG_url_link Registration URL Link
559
-     * @throws EE_Error
560
-     * @throws RuntimeException
561
-     */
562
-    public function set_reg_url_link($REG_url_link = '')
563
-    {
564
-        $this->set('REG_url_link', $REG_url_link);
565
-    }
566
-
567
-
568
-    /**
569
-     *        Set Attendee Counter
570
-     *
571
-     * @param        int $REG_count Primary Attendee
572
-     * @throws EE_Error
573
-     * @throws RuntimeException
574
-     */
575
-    public function set_count($REG_count = 1)
576
-    {
577
-        $this->set('REG_count', $REG_count);
578
-    }
579
-
580
-
581
-    /**
582
-     *        Set Group Size
583
-     *
584
-     * @param        boolean $REG_group_size Group Registration
585
-     * @throws EE_Error
586
-     * @throws RuntimeException
587
-     */
588
-    public function set_group_size($REG_group_size = false)
589
-    {
590
-        $this->set('REG_group_size', $REG_group_size);
591
-    }
592
-
593
-
594
-    /**
595
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
596
-     *    EEM_Registration::status_id_not_approved
597
-     *
598
-     * @return        boolean
599
-     */
600
-    public function is_not_approved()
601
-    {
602
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
603
-    }
604
-
605
-
606
-    /**
607
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
608
-     *    EEM_Registration::status_id_pending_payment
609
-     *
610
-     * @return        boolean
611
-     */
612
-    public function is_pending_payment()
613
-    {
614
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
615
-    }
616
-
617
-
618
-    /**
619
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
620
-     *
621
-     * @return        boolean
622
-     */
623
-    public function is_approved()
624
-    {
625
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
626
-    }
627
-
628
-
629
-    /**
630
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
631
-     *
632
-     * @return        boolean
633
-     */
634
-    public function is_cancelled()
635
-    {
636
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
637
-    }
638
-
639
-
640
-    /**
641
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
642
-     *
643
-     * @return        boolean
644
-     */
645
-    public function is_declined()
646
-    {
647
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
648
-    }
649
-
650
-
651
-    /**
652
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
653
-     *    EEM_Registration::status_id_incomplete
654
-     *
655
-     * @return        boolean
656
-     */
657
-    public function is_incomplete()
658
-    {
659
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
660
-    }
661
-
662
-
663
-    /**
664
-     *        Set Registration Date
665
-     *
666
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
667
-     *                                                 Date
668
-     * @throws EE_Error
669
-     * @throws RuntimeException
670
-     */
671
-    public function set_reg_date($REG_date = false)
672
-    {
673
-        $this->set('REG_date', $REG_date);
674
-    }
675
-
676
-
677
-    /**
678
-     *    Set final price owing for this registration after all ticket/price modifications
679
-     *
680
-     * @access    public
681
-     * @param    float $REG_final_price
682
-     * @throws EE_Error
683
-     * @throws RuntimeException
684
-     */
685
-    public function set_final_price($REG_final_price = 0.00)
686
-    {
687
-        $this->set('REG_final_price', $REG_final_price);
688
-    }
689
-
690
-
691
-    /**
692
-     *    Set amount paid towards this registration's final price
693
-     *
694
-     * @access    public
695
-     * @param    float $REG_paid
696
-     * @throws EE_Error
697
-     * @throws RuntimeException
698
-     */
699
-    public function set_paid($REG_paid = 0.00)
700
-    {
701
-        $this->set('REG_paid', $REG_paid);
702
-    }
703
-
704
-
705
-    /**
706
-     *        Attendee Is Going
707
-     *
708
-     * @param        boolean $REG_att_is_going Attendee Is Going
709
-     * @throws EE_Error
710
-     * @throws RuntimeException
711
-     */
712
-    public function set_att_is_going($REG_att_is_going = false)
713
-    {
714
-        $this->set('REG_att_is_going', $REG_att_is_going);
715
-    }
716
-
717
-
718
-    /**
719
-     * Gets the related attendee
720
-     *
721
-     * @return EE_Attendee
722
-     * @throws EE_Error
723
-     */
724
-    public function attendee()
725
-    {
726
-        return $this->get_first_related('Attendee');
727
-    }
728
-
729
-
730
-    /**
731
-     *        get Event ID
732
-     */
733
-    public function event_ID()
734
-    {
735
-        return $this->get('EVT_ID');
736
-    }
737
-
738
-
739
-    /**
740
-     *        get Event ID
741
-     */
742
-    public function event_name()
743
-    {
744
-        $event = $this->event_obj();
745
-        if ($event) {
746
-            return $event->name();
747
-        } else {
748
-            return null;
749
-        }
750
-    }
751
-
752
-
753
-    /**
754
-     * Fetches the event this registration is for
755
-     *
756
-     * @return EE_Event
757
-     * @throws EE_Error
758
-     */
759
-    public function event_obj()
760
-    {
761
-        return $this->get_first_related('Event');
762
-    }
763
-
764
-
765
-    /**
766
-     *        get Attendee ID
767
-     */
768
-    public function attendee_ID()
769
-    {
770
-        return $this->get('ATT_ID');
771
-    }
772
-
773
-
774
-    /**
775
-     *        get PHP Session ID
776
-     */
777
-    public function session_ID()
778
-    {
779
-        return $this->get('REG_session');
780
-    }
781
-
782
-
783
-    /**
784
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
785
-     *
786
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
787
-     * @return string
788
-     */
789
-    public function receipt_url($messenger = 'html')
790
-    {
791
-
792
-        /**
793
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
794
-         * already in use on old system.  If there is then we just return the standard url for it.
795
-         *
796
-         * @since 4.5.0
797
-         */
798
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
799
-        $has_custom             = EEH_Template::locate_template(
800
-            $template_relative_path,
801
-            array(),
802
-            true,
803
-            true,
804
-            true
805
-        );
806
-
807
-        if ($has_custom) {
808
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
809
-        }
810
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
811
-    }
812
-
813
-
814
-    /**
815
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
816
-     *
817
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
818
-     * @return string
819
-     * @throws EE_Error
820
-     */
821
-    public function invoice_url($messenger = 'html')
822
-    {
823
-        /**
824
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
825
-         * already in use on old system.  If there is then we just return the standard url for it.
826
-         *
827
-         * @since 4.5.0
828
-         */
829
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
830
-        $has_custom             = EEH_Template::locate_template(
831
-            $template_relative_path,
832
-            array(),
833
-            true,
834
-            true,
835
-            true
836
-        );
837
-
838
-        if ($has_custom) {
839
-            if ($messenger == 'html') {
840
-                return $this->invoice_url('launch');
841
-            }
842
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
843
-
844
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
845
-            if ($messenger == 'html') {
846
-                $query_args['html'] = true;
847
-            }
848
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
849
-        }
850
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
851
-    }
852
-
853
-
854
-    /**
855
-     * get Registration URL Link
856
-     *
857
-     * @access public
858
-     * @return string
859
-     * @throws EE_Error
860
-     */
861
-    public function reg_url_link()
862
-    {
863
-        return (string) $this->get('REG_url_link');
864
-    }
865
-
866
-
867
-    /**
868
-     * Echoes out invoice_url()
869
-     *
870
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
871
-     * @return void
872
-     * @throws EE_Error
873
-     */
874
-    public function e_invoice_url($type = 'launch')
875
-    {
876
-        echo $this->invoice_url($type);
877
-    }
878
-
879
-
880
-    /**
881
-     * Echoes out payment_overview_url
882
-     */
883
-    public function e_payment_overview_url()
884
-    {
885
-        echo $this->payment_overview_url();
886
-    }
887
-
888
-
889
-    /**
890
-     * Gets the URL for the checkout payment options reg step
891
-     * with this registration's REG_url_link added as a query parameter
892
-     *
893
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
894
-     *                            payment overview url.
895
-     * @return string
896
-     * @throws InvalidInterfaceException
897
-     * @throws InvalidDataTypeException
898
-     * @throws EE_Error
899
-     * @throws InvalidArgumentException
900
-     */
901
-    public function payment_overview_url($clear_session = false)
902
-    {
903
-        return add_query_arg(
904
-            (array) apply_filters(
905
-                'FHEE__EE_Registration__payment_overview_url__query_args',
906
-                array(
907
-                    'e_reg_url_link' => $this->reg_url_link(),
908
-                    'step'           => 'payment_options',
909
-                    'revisit'        => true,
910
-                    'clear_session'  => (bool) $clear_session,
911
-                ),
912
-                $this
913
-            ),
914
-            EE_Registry::instance()->CFG->core->reg_page_url()
915
-        );
916
-    }
917
-
918
-
919
-    /**
920
-     * Gets the URL for the checkout attendee information reg step
921
-     * with this registration's REG_url_link added as a query parameter
922
-     *
923
-     * @return string
924
-     * @throws InvalidInterfaceException
925
-     * @throws InvalidDataTypeException
926
-     * @throws EE_Error
927
-     * @throws InvalidArgumentException
928
-     */
929
-    public function edit_attendee_information_url()
930
-    {
931
-        return add_query_arg(
932
-            (array) apply_filters(
933
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
934
-                array(
935
-                    'e_reg_url_link' => $this->reg_url_link(),
936
-                    'step'           => 'attendee_information',
937
-                    'revisit'        => true,
938
-                ),
939
-                $this
940
-            ),
941
-            EE_Registry::instance()->CFG->core->reg_page_url()
942
-        );
943
-    }
944
-
945
-
946
-    /**
947
-     * Simply generates and returns the appropriate admin_url link to edit this registration
948
-     *
949
-     * @return string
950
-     * @throws EE_Error
951
-     */
952
-    public function get_admin_edit_url()
953
-    {
954
-        return EEH_URL::add_query_args_and_nonce(array(
955
-            'page'    => 'espresso_registrations',
956
-            'action'  => 'view_registration',
957
-            '_REG_ID' => $this->ID(),
958
-        ), admin_url('admin.php'));
959
-    }
960
-
961
-
962
-    /**
963
-     *    is_primary_registrant?
964
-     */
965
-    public function is_primary_registrant()
966
-    {
967
-        return $this->get('REG_count') == 1 ? true : false;
968
-    }
969
-
970
-
971
-    /**
972
-     * This returns the primary registration object for this registration group (which may be this object).
973
-     *
974
-     * @return EE_Registration
975
-     * @throws EE_Error
976
-     */
977
-    public function get_primary_registration()
978
-    {
979
-        if ($this->is_primary_registrant()) {
980
-            return $this;
981
-        }
982
-
983
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
984
-        /** @var EE_Registration $primary_registrant */
985
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
986
-            array(
987
-                'TXN_ID'    => $this->transaction_ID(),
988
-                'REG_count' => 1,
989
-            ),
990
-        ));
991
-        return $primary_registrant;
992
-    }
993
-
994
-
995
-    /**
996
-     *        get  Attendee Number
997
-     *
998
-     * @access        public
999
-     */
1000
-    public function count()
1001
-    {
1002
-        return $this->get('REG_count');
1003
-    }
1004
-
1005
-
1006
-    /**
1007
-     *        get Group Size
1008
-     */
1009
-    public function group_size()
1010
-    {
1011
-        return $this->get('REG_group_size');
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     *        get Registration Date
1017
-     */
1018
-    public function date()
1019
-    {
1020
-        return $this->get('REG_date');
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     * gets a pretty date
1026
-     *
1027
-     * @param string $date_format
1028
-     * @param string $time_format
1029
-     * @return string
1030
-     * @throws EE_Error
1031
-     */
1032
-    public function pretty_date($date_format = null, $time_format = null)
1033
-    {
1034
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1035
-    }
1036
-
1037
-
1038
-    /**
1039
-     * final_price
1040
-     * the registration's share of the transaction total, so that the
1041
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1042
-     *
1043
-     * @return float
1044
-     * @throws EE_Error
1045
-     */
1046
-    public function final_price()
1047
-    {
1048
-        return $this->get('REG_final_price');
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * pretty_final_price
1054
-     *  final price as formatted string, with correct decimal places and currency symbol
1055
-     *
1056
-     * @return string
1057
-     * @throws EE_Error
1058
-     */
1059
-    public function pretty_final_price()
1060
-    {
1061
-        return $this->get_pretty('REG_final_price');
1062
-    }
1063
-
1064
-
1065
-    /**
1066
-     * get paid (yeah)
1067
-     *
1068
-     * @return float
1069
-     * @throws EE_Error
1070
-     */
1071
-    public function paid()
1072
-    {
1073
-        return $this->get('REG_paid');
1074
-    }
1075
-
1076
-
1077
-    /**
1078
-     * pretty_paid
1079
-     *
1080
-     * @return float
1081
-     * @throws EE_Error
1082
-     */
1083
-    public function pretty_paid()
1084
-    {
1085
-        return $this->get_pretty('REG_paid');
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * owes_monies_and_can_pay
1091
-     * whether or not this registration has monies owing and it's' status allows payment
1092
-     *
1093
-     * @param array $requires_payment
1094
-     * @return bool
1095
-     * @throws EE_Error
1096
-     */
1097
-    public function owes_monies_and_can_pay($requires_payment = array())
1098
-    {
1099
-        // these reg statuses require payment (if event is not free)
1100
-        $requires_payment = ! empty($requires_payment)
1101
-            ? $requires_payment
1102
-            : EEM_Registration::reg_statuses_that_allow_payment();
1103
-        if (in_array($this->status_ID(), $requires_payment) &&
1104
-            $this->final_price() != 0 &&
1105
-            $this->final_price() != $this->paid()
1106
-        ) {
1107
-            return true;
1108
-        } else {
1109
-            return false;
1110
-        }
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * Prints out the return value of $this->pretty_status()
1116
-     *
1117
-     * @param bool $show_icons
1118
-     * @return void
1119
-     * @throws EE_Error
1120
-     */
1121
-    public function e_pretty_status($show_icons = false)
1122
-    {
1123
-        echo $this->pretty_status($show_icons);
1124
-    }
1125
-
1126
-
1127
-    /**
1128
-     * Returns a nice version of the status for displaying to customers
1129
-     *
1130
-     * @param bool $show_icons
1131
-     * @return string
1132
-     * @throws EE_Error
1133
-     */
1134
-    public function pretty_status($show_icons = false)
1135
-    {
1136
-        $status = EEM_Status::instance()->localized_status(
1137
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1138
-            false,
1139
-            'sentence'
1140
-        );
1141
-        $icon   = '';
1142
-        switch ($this->status_ID()) {
1143
-            case EEM_Registration::status_id_approved:
1144
-                $icon = $show_icons
1145
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1146
-                    : '';
1147
-                break;
1148
-            case EEM_Registration::status_id_pending_payment:
1149
-                $icon = $show_icons
1150
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1151
-                    : '';
1152
-                break;
1153
-            case EEM_Registration::status_id_not_approved:
1154
-                $icon = $show_icons
1155
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1156
-                    : '';
1157
-                break;
1158
-            case EEM_Registration::status_id_cancelled:
1159
-                $icon = $show_icons
1160
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1161
-                    : '';
1162
-                break;
1163
-            case EEM_Registration::status_id_incomplete:
1164
-                $icon = $show_icons
1165
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1166
-                    : '';
1167
-                break;
1168
-            case EEM_Registration::status_id_declined:
1169
-                $icon = $show_icons
1170
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1171
-                    : '';
1172
-                break;
1173
-            case EEM_Registration::status_id_wait_list:
1174
-                $icon = $show_icons
1175
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1176
-                    : '';
1177
-                break;
1178
-        }
1179
-        return $icon . $status[$this->status_ID()];
1180
-    }
1181
-
1182
-
1183
-    /**
1184
-     *        get Attendee Is Going
1185
-     */
1186
-    public function att_is_going()
1187
-    {
1188
-        return $this->get('REG_att_is_going');
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * Gets related answers
1194
-     *
1195
-     * @param array $query_params like EEM_Base::get_all
1196
-     * @return EE_Answer[]
1197
-     * @throws EE_Error
1198
-     */
1199
-    public function answers($query_params = null)
1200
-    {
1201
-        return $this->get_many_related('Answer', $query_params);
1202
-    }
1203
-
1204
-
1205
-    /**
1206
-     * Gets the registration's answer value to the specified question
1207
-     * (either the question's ID or a question object)
1208
-     *
1209
-     * @param EE_Question|int $question
1210
-     * @param bool            $pretty_value
1211
-     * @return array|string if pretty_value= true, the result will always be a string
1212
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1213
-     * will convert it into some kind of string)
1214
-     * @throws EE_Error
1215
-     */
1216
-    public function answer_value_to_question($question, $pretty_value = true)
1217
-    {
1218
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1219
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * question_groups
1225
-     * returns an array of EE_Question_Group objects for this registration
1226
-     *
1227
-     * @return EE_Question_Group[]
1228
-     * @throws EE_Error
1229
-     * @throws EntityNotFoundException
1230
-     */
1231
-    public function question_groups()
1232
-    {
1233
-        $question_groups = array();
1234
-        if ($this->event() instanceof EE_Event) {
1235
-            $question_groups = $this->event()->question_groups(
1236
-                array(
1237
-                    array(
1238
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1239
-                    ),
1240
-                    'order_by' => array('QSG_order' => 'ASC'),
1241
-                )
1242
-            );
1243
-        }
1244
-        return $question_groups;
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * count_question_groups
1250
-     * returns a count of the number of EE_Question_Group objects for this registration
1251
-     *
1252
-     * @return int
1253
-     * @throws EE_Error
1254
-     * @throws EntityNotFoundException
1255
-     */
1256
-    public function count_question_groups()
1257
-    {
1258
-        $qg_count = 0;
1259
-        if ($this->event() instanceof EE_Event) {
1260
-            $qg_count = $this->event()->count_related(
1261
-                'Question_Group',
1262
-                array(
1263
-                    array(
1264
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1265
-                    ),
1266
-                )
1267
-            );
1268
-        }
1269
-        return $qg_count;
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     * Returns the registration date in the 'standard' string format
1275
-     * (function may be improved in the future to allow for different formats and timezones)
1276
-     *
1277
-     * @return string
1278
-     * @throws EE_Error
1279
-     */
1280
-    public function reg_date()
1281
-    {
1282
-        return $this->get_datetime('REG_date');
1283
-    }
1284
-
1285
-
1286
-    /**
1287
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1288
-     * the ticket this registration purchased, or the datetime they have registered
1289
-     * to attend)
1290
-     *
1291
-     * @return EE_Datetime_Ticket
1292
-     * @throws EE_Error
1293
-     */
1294
-    public function datetime_ticket()
1295
-    {
1296
-        return $this->get_first_related('Datetime_Ticket');
1297
-    }
1298
-
1299
-
1300
-    /**
1301
-     * Sets the registration's datetime_ticket.
1302
-     *
1303
-     * @param EE_Datetime_Ticket $datetime_ticket
1304
-     * @return EE_Datetime_Ticket
1305
-     * @throws EE_Error
1306
-     */
1307
-    public function set_datetime_ticket($datetime_ticket)
1308
-    {
1309
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1310
-    }
1311
-
1312
-    /**
1313
-     * Gets deleted
1314
-     *
1315
-     * @return bool
1316
-     * @throws EE_Error
1317
-     */
1318
-    public function deleted()
1319
-    {
1320
-        return $this->get('REG_deleted');
1321
-    }
1322
-
1323
-    /**
1324
-     * Sets deleted
1325
-     *
1326
-     * @param boolean $deleted
1327
-     * @return bool
1328
-     * @throws EE_Error
1329
-     * @throws RuntimeException
1330
-     */
1331
-    public function set_deleted($deleted)
1332
-    {
1333
-        if ($deleted) {
1334
-            $this->delete();
1335
-        } else {
1336
-            $this->restore();
1337
-        }
1338
-    }
1339
-
1340
-
1341
-    /**
1342
-     * Get the status object of this object
1343
-     *
1344
-     * @return EE_Status
1345
-     * @throws EE_Error
1346
-     */
1347
-    public function status_obj()
1348
-    {
1349
-        return $this->get_first_related('Status');
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Returns the number of times this registration has checked into any of the datetimes
1355
-     * its available for
1356
-     *
1357
-     * @return int
1358
-     * @throws EE_Error
1359
-     */
1360
-    public function count_checkins()
1361
-    {
1362
-        return $this->get_model()->count_related($this, 'Checkin');
1363
-    }
1364
-
1365
-
1366
-    /**
1367
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1368
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1369
-     *
1370
-     * @return int
1371
-     * @throws EE_Error
1372
-     */
1373
-    public function count_checkins_not_checkedout()
1374
-    {
1375
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1376
-    }
1377
-
1378
-
1379
-    /**
1380
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1381
-     *
1382
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1383
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1384
-     *                                          consider registration status as well as datetime access.
1385
-     * @return bool
1386
-     * @throws EE_Error
1387
-     */
1388
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1389
-    {
1390
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1391
-
1392
-        //first check registration status
1393
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1394
-            return false;
1395
-        }
1396
-        //is there a datetime ticket that matches this dtt_ID?
1397
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1398
-            array(
1399
-                'TKT_ID' => $this->get('TKT_ID'),
1400
-                'DTT_ID' => $DTT_ID,
1401
-            ),
1402
-        )))
1403
-        ) {
1404
-            return false;
1405
-        }
1406
-
1407
-        //final check is against TKT_uses
1408
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1409
-    }
1410
-
1411
-
1412
-    /**
1413
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1414
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1415
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1416
-     * then return false.  Otherwise return true.
1417
-     *
1418
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1419
-     * @return bool true means can checkin.  false means cannot checkin.
1420
-     * @throws EE_Error
1421
-     */
1422
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1423
-    {
1424
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1425
-
1426
-        if (! $DTT_ID) {
1427
-            return false;
1428
-        }
1429
-
1430
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1431
-
1432
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1433
-        // check-in or not.
1434
-        if (! $max_uses || $max_uses === EE_INF) {
1435
-            return true;
1436
-        }
1437
-
1438
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1439
-        //go ahead and toggle.
1440
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1441
-            return true;
1442
-        }
1443
-
1444
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1445
-        //disallows further check-ins.
1446
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1447
-            array(
1448
-                'REG_ID' => $this->ID(),
1449
-                'CHK_in' => true,
1450
-            ),
1451
-        ), 'DTT_ID', true);
1452
-        // checkins have already reached their max number of uses
1453
-        // so registrant can NOT checkin
1454
-        if ($count_unique_dtt_checkins >= $max_uses) {
1455
-            EE_Error::add_error(
1456
-                esc_html__(
1457
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1458
-                    'event_espresso'
1459
-                ),
1460
-                __FILE__,
1461
-                __FUNCTION__,
1462
-                __LINE__
1463
-            );
1464
-            return false;
1465
-        }
1466
-        return true;
1467
-    }
1468
-
1469
-
1470
-    /**
1471
-     * toggle Check-in status for this registration
1472
-     * Check-ins are toggled in the following order:
1473
-     * never checked in -> checked in
1474
-     * checked in -> checked out
1475
-     * checked out -> checked in
1476
-     *
1477
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1478
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1479
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1480
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1481
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1482
-     * @throws EE_Error
1483
-     */
1484
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1485
-    {
1486
-        if (empty($DTT_ID)) {
1487
-            $datetime = $this->get_latest_related_datetime();
1488
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1489
-            // verify the registration can checkin for the given DTT_ID
1490
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1491
-            EE_Error::add_error(
1492
-                sprintf(
1493
-                    esc_html__(
1494
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1495
-                        'event_espresso'
1496
-                    ),
1497
-                    $this->ID(),
1498
-                    $DTT_ID
1499
-                ),
1500
-                __FILE__,
1501
-                __FUNCTION__,
1502
-                __LINE__
1503
-            );
1504
-            return false;
1505
-        }
1506
-        $status_paths = array(
1507
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1508
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1509
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1510
-        );
1511
-        //start by getting the current status so we know what status we'll be changing to.
1512
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1513
-        $status_to  = $status_paths[$cur_status];
1514
-        // database only records true for checked IN or false for checked OUT
1515
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1516
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1517
-        // add relation - note Check-ins are always creating new rows
1518
-        // because we are keeping track of Check-ins over time.
1519
-        // Eventually we'll probably want to show a list table
1520
-        // for the individual Check-ins so that they can be managed.
1521
-        $checkin = EE_Checkin::new_instance(array(
1522
-            'REG_ID' => $this->ID(),
1523
-            'DTT_ID' => $DTT_ID,
1524
-            'CHK_in' => $new_status,
1525
-        ));
1526
-        // if the record could not be saved then return false
1527
-        if ($checkin->save() === 0) {
1528
-            if (WP_DEBUG) {
1529
-                global $wpdb;
1530
-                $error = sprintf(
1531
-                    esc_html__(
1532
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1533
-                        'event_espresso'
1534
-                    ),
1535
-                    '<br />',
1536
-                    $wpdb->last_error
1537
-                );
1538
-            } else {
1539
-                $error = esc_html__(
1540
-                    'Registration check in update failed because of an unknown database error',
1541
-                    'event_espresso'
1542
-                );
1543
-            }
1544
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1545
-            return false;
1546
-        }
1547
-        return $status_to;
1548
-    }
1549
-
1550
-
1551
-    /**
1552
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1553
-     * "Latest" is defined by the `DTT_EVT_start` column.
1554
-     *
1555
-     * @return EE_Datetime|null
1556
-     * @throws EE_Error
1557
-     */
1558
-    public function get_latest_related_datetime()
1559
-    {
1560
-        return EEM_Datetime::instance()->get_one(
1561
-            array(
1562
-                array(
1563
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1564
-                ),
1565
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1566
-            )
1567
-        );
1568
-    }
1569
-
1570
-
1571
-    /**
1572
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1573
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1574
-     *
1575
-     * @throws EE_Error
1576
-     */
1577
-    public function get_earliest_related_datetime()
1578
-    {
1579
-        return EEM_Datetime::instance()->get_one(
1580
-            array(
1581
-                array(
1582
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1583
-                ),
1584
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1585
-            )
1586
-        );
1587
-    }
1588
-
1589
-
1590
-    /**
1591
-     * This method simply returns the check-in status for this registration and the given datetime.
1592
-     * If neither the datetime nor the checkin values are provided as arguments,
1593
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1594
-     *
1595
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1596
-     *                            (if empty we'll get the primary datetime for
1597
-     *                            this registration (via event) and use it's ID);
1598
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1599
-     *
1600
-     * @return int                Integer representing Check-in status.
1601
-     * @throws EE_Error
1602
-     */
1603
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1604
-    {
1605
-        $checkin_query_params = array(
1606
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1607
-        );
1608
-
1609
-        if ($DTT_ID > 0) {
1610
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1611
-        }
1612
-
1613
-        //get checkin object (if exists)
1614
-        $checkin = $checkin instanceof EE_Checkin
1615
-            ? $checkin
1616
-            : $this->get_first_related('Checkin', $checkin_query_params);
1617
-        if ($checkin instanceof EE_Checkin) {
1618
-            if ($checkin->get('CHK_in')) {
1619
-                return EE_Checkin::status_checked_in; //checked in
1620
-            }
1621
-            return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1622
-        }
1623
-        return EE_Checkin::status_checked_never; //never been checked in
1624
-    }
1625
-
1626
-
1627
-    /**
1628
-     * This method returns a localized message for the toggled Check-in message.
1629
-     *
1630
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1631
-     *                     then it is assumed Check-in for primary datetime was toggled.
1632
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1633
-     *                     message can be customized with the attendee name.
1634
-     * @return string internationalized message
1635
-     * @throws EE_Error
1636
-     */
1637
-    public function get_checkin_msg($DTT_ID, $error = false)
1638
-    {
1639
-        //let's get the attendee first so we can include the name of the attendee
1640
-        $attendee = $this->get_first_related('Attendee');
1641
-        if ($attendee instanceof EE_Attendee) {
1642
-            if ($error) {
1643
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1644
-            }
1645
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1646
-            //what is the status message going to be?
1647
-            switch ($cur_status) {
1648
-                case EE_Checkin::status_checked_never:
1649
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1650
-                        $attendee->full_name());
1651
-                    break;
1652
-                case EE_Checkin::status_checked_in:
1653
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1654
-                    break;
1655
-                case EE_Checkin::status_checked_out:
1656
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1657
-                    break;
1658
-            }
1659
-        }
1660
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1661
-    }
1662
-
1663
-
1664
-    /**
1665
-     * Returns the related EE_Transaction to this registration
1666
-     *
1667
-     * @return EE_Transaction
1668
-     * @throws EE_Error
1669
-     * @throws EntityNotFoundException
1670
-     */
1671
-    public function transaction()
1672
-    {
1673
-        $transaction = $this->get_first_related('Transaction');
1674
-        if (! $transaction instanceof \EE_Transaction) {
1675
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1676
-        }
1677
-        return $transaction;
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     *        get Registration Code
1683
-     */
1684
-    public function reg_code()
1685
-    {
1686
-        return $this->get('REG_code');
1687
-    }
1688
-
1689
-
1690
-    /**
1691
-     *        get Transaction ID
1692
-     */
1693
-    public function transaction_ID()
1694
-    {
1695
-        return $this->get('TXN_ID');
1696
-    }
1697
-
1698
-
1699
-    /**
1700
-     * @return int
1701
-     * @throws EE_Error
1702
-     */
1703
-    public function ticket_ID()
1704
-    {
1705
-        return $this->get('TKT_ID');
1706
-    }
1707
-
1708
-
1709
-    /**
1710
-     *        Set Registration Code
1711
-     *
1712
-     * @access    public
1713
-     * @param    string  $REG_code Registration Code
1714
-     * @param    boolean $use_default
1715
-     * @throws EE_Error
1716
-     */
1717
-    public function set_reg_code($REG_code, $use_default = false)
1718
-    {
1719
-        if (empty($REG_code)) {
1720
-            EE_Error::add_error(
1721
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1722
-                __FILE__,
1723
-                __FUNCTION__,
1724
-                __LINE__
1725
-            );
1726
-            return;
1727
-        }
1728
-        if (! $this->reg_code()) {
1729
-            parent::set('REG_code', $REG_code, $use_default);
1730
-        } else {
1731
-            EE_Error::doing_it_wrong(
1732
-                __CLASS__ . '::' . __FUNCTION__,
1733
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1734
-                '4.6.0'
1735
-            );
1736
-        }
1737
-    }
1738
-
1739
-
1740
-    /**
1741
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1742
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1743
-     *    $registration->transaction()->registrations();
1744
-     *
1745
-     * @since 4.5.0
1746
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1747
-     * @throws EE_Error
1748
-     */
1749
-    public function get_all_other_registrations_in_group()
1750
-    {
1751
-        if ($this->group_size() < 2) {
1752
-            return array();
1753
-        }
1754
-
1755
-        $query[0] = array(
1756
-            'TXN_ID' => $this->transaction_ID(),
1757
-            'REG_ID' => array('!=', $this->ID()),
1758
-            'TKT_ID' => $this->ticket_ID(),
1759
-        );
1760
-        /** @var EE_Registration[] $registrations */
1761
-        $registrations = $this->get_model()->get_all($query);
1762
-        return $registrations;
1763
-    }
1764
-
1765
-    /**
1766
-     * Return the link to the admin details for the object.
1767
-     *
1768
-     * @return string
1769
-     * @throws EE_Error
1770
-     */
1771
-    public function get_admin_details_link()
1772
-    {
1773
-        EE_Registry::instance()->load_helper('URL');
1774
-        return EEH_URL::add_query_args_and_nonce(
1775
-            array(
1776
-                'page'    => 'espresso_registrations',
1777
-                'action'  => 'view_registration',
1778
-                '_REG_ID' => $this->ID(),
1779
-            ),
1780
-            admin_url('admin.php')
1781
-        );
1782
-    }
1783
-
1784
-    /**
1785
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1786
-     *
1787
-     * @return string
1788
-     * @throws EE_Error
1789
-     */
1790
-    public function get_admin_edit_link()
1791
-    {
1792
-        return $this->get_admin_details_link();
1793
-    }
1794
-
1795
-    /**
1796
-     * Returns the link to a settings page for the object.
1797
-     *
1798
-     * @return string
1799
-     * @throws EE_Error
1800
-     */
1801
-    public function get_admin_settings_link()
1802
-    {
1803
-        return $this->get_admin_details_link();
1804
-    }
1805
-
1806
-    /**
1807
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1808
-     *
1809
-     * @return string
1810
-     */
1811
-    public function get_admin_overview_link()
1812
-    {
1813
-        EE_Registry::instance()->load_helper('URL');
1814
-        return EEH_URL::add_query_args_and_nonce(
1815
-            array(
1816
-                'page' => 'espresso_registrations',
1817
-            ),
1818
-            admin_url('admin.php')
1819
-        );
1820
-    }
1821
-
1822
-
1823
-    /**
1824
-     * @param array $query_params
1825
-     *
1826
-     * @return \EE_Registration[]
1827
-     * @throws EE_Error
1828
-     */
1829
-    public function payments($query_params = array())
1830
-    {
1831
-        return $this->get_many_related('Payment', $query_params);
1832
-    }
1833
-
1834
-
1835
-    /**
1836
-     * @param array $query_params
1837
-     *
1838
-     * @return \EE_Registration_Payment[]
1839
-     * @throws EE_Error
1840
-     */
1841
-    public function registration_payments($query_params = array())
1842
-    {
1843
-        return $this->get_many_related('Registration_Payment', $query_params);
1844
-    }
1845
-
1846
-
1847
-    /**
1848
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1849
-     * Note: if there are no payments on the registration there will be no payment method returned.
1850
-     *
1851
-     * @return EE_Payment_Method|null
1852
-     */
1853
-    public function payment_method()
1854
-    {
1855
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1856
-    }
1857
-
1858
-
1859
-    /**
1860
-     * @return \EE_Line_Item
1861
-     * @throws EntityNotFoundException
1862
-     * @throws EE_Error
1863
-     */
1864
-    public function ticket_line_item()
1865
-    {
1866
-        $ticket            = $this->ticket();
1867
-        $transaction       = $this->transaction();
1868
-        $line_item         = null;
1869
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1870
-            $transaction->total_line_item(),
1871
-            'Ticket',
1872
-            array($ticket->ID())
1873
-        );
1874
-        foreach ($ticket_line_items as $ticket_line_item) {
1875
-            if (
1876
-                $ticket_line_item instanceof \EE_Line_Item
1877
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1878
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1879
-            ) {
1880
-                $line_item = $ticket_line_item;
1881
-                break;
1882
-            }
1883
-        }
1884
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1885
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1886
-        }
1887
-        return $line_item;
1888
-    }
1889
-
1890
-
1891
-    /**
1892
-     * Soft Deletes this model object.
1893
-     *
1894
-     * @return boolean | int
1895
-     * @throws RuntimeException
1896
-     * @throws EE_Error
1897
-     */
1898
-    public function delete()
1899
-    {
1900
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1901
-            $this->set_status(EEM_Registration::status_id_cancelled);
1902
-        }
1903
-        return parent::delete();
1904
-    }
1905
-
1906
-
1907
-    /**
1908
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1909
-     *
1910
-     * @throws EE_Error
1911
-     * @throws RuntimeException
1912
-     */
1913
-    public function restore()
1914
-    {
1915
-        $previous_status = $this->get_extra_meta(
1916
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1917
-            true,
1918
-            EEM_Registration::status_id_cancelled
1919
-        );
1920
-        if ($previous_status) {
1921
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1922
-            $this->set_status($previous_status);
1923
-        }
1924
-        return parent::restore();
1925
-    }
1926
-
1927
-
1928
-    /**
1929
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1930
-     *
1931
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1932
-     *                                           depending on whether the reg status changes to or from "Approved"
1933
-     * @return boolean whether the Registration status was updated
1934
-     * @throws EE_Error
1935
-     * @throws RuntimeException
1936
-     */
1937
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1938
-    {
1939
-        $paid = $this->paid();
1940
-        $price = $this->final_price();
1941
-        switch(true) {
1942
-            // overpaid or paid
1943
-            case EEH_Money::compare_floats($paid, $price, '>'):
1944
-            case EEH_Money::compare_floats($paid, $price):
1945
-                $new_status = EEM_Registration::status_id_approved;
1946
-                break;
1947
-            //  underpaid
1948
-            case EEH_Money::compare_floats($paid, $price, '<'):
1949
-                $new_status = EEM_Registration::status_id_pending_payment;
1950
-                break;
1951
-            // uhhh Houston...
1952
-            default:
1953
-                throw new RuntimeException(
1954
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1955
-                );
1956
-        }
1957
-        if ($new_status !== $this->status_ID()) {
1958
-            if ($trigger_set_status_logic) {
1959
-                return $this->set_status($new_status);
1960
-            }
1961
-            parent::set('STS_ID', $new_status);
1962
-            return true;
1963
-        }
1964
-        return false;
1965
-    }
1966
-
1967
-
1968
-    /*************************** DEPRECATED ***************************/
1969
-
1970
-
1971
-    /**
1972
-     * @deprecated
1973
-     * @since     4.7.0
1974
-     * @access    public
1975
-     */
1976
-    public function price_paid()
1977
-    {
1978
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1979
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1980
-            '4.7.0');
1981
-        return $this->final_price();
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * @deprecated
1987
-     * @since     4.7.0
1988
-     * @access    public
1989
-     * @param    float $REG_final_price
1990
-     * @throws EE_Error
1991
-     * @throws RuntimeException
1992
-     */
1993
-    public function set_price_paid($REG_final_price = 0.00)
1994
-    {
1995
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1996
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1997
-            '4.7.0');
1998
-        $this->set_final_price($REG_final_price);
1999
-    }
2000
-
2001
-
2002
-    /**
2003
-     * @deprecated
2004
-     * @since 4.7.0
2005
-     * @return string
2006
-     * @throws EE_Error
2007
-     */
2008
-    public function pretty_price_paid()
2009
-    {
2010
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
2011
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2012
-                'event_espresso'), '4.7.0');
2013
-        return $this->pretty_final_price();
2014
-    }
2015
-
2016
-
2017
-    /**
2018
-     * Gets the primary datetime related to this registration via the related Event to this registration
2019
-     *
2020
-     * @deprecated 4.9.17
2021
-     * @return EE_Datetime
2022
-     * @throws EE_Error
2023
-     * @throws EntityNotFoundException
2024
-     */
2025
-    public function get_related_primary_datetime()
2026
-    {
2027
-        EE_Error::doing_it_wrong(
2028
-            __METHOD__,
2029
-            esc_html__(
2030
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2031
-                'event_espresso'
2032
-            ),
2033
-            '4.9.17',
2034
-            '5.0.0'
2035
-        );
2036
-        return $this->event()->primary_datetime();
2037
-    }
21
+	/**
22
+	 * Used to reference when a registration has never been checked in.
23
+	 *
24
+	 * @deprecated use \EE_Checkin::status_checked_never instead
25
+	 * @type int
26
+	 */
27
+	const checkin_status_never = 2;
28
+
29
+	/**
30
+	 * Used to reference when a registration has been checked in.
31
+	 *
32
+	 * @deprecated use \EE_Checkin::status_checked_in instead
33
+	 * @type int
34
+	 */
35
+	const checkin_status_in = 1;
36
+
37
+
38
+	/**
39
+	 * Used to reference when a registration has been checked out.
40
+	 *
41
+	 * @deprecated use \EE_Checkin::status_checked_out instead
42
+	 * @type int
43
+	 */
44
+	const checkin_status_out = 0;
45
+
46
+
47
+	/**
48
+	 * extra meta key for tracking reg status os trashed registrations
49
+	 *
50
+	 * @type string
51
+	 */
52
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
+
54
+
55
+	/**
56
+	 * extra meta key for tracking if registration has reserved ticket
57
+	 *
58
+	 * @type string
59
+	 */
60
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
+
62
+
63
+	/**
64
+	 * @param array  $props_n_values          incoming values
65
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
+	 *                                        used.)
67
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
+	 *                                        date_format and the second value is the time format
69
+	 * @return EE_Registration
70
+	 * @throws EE_Error
71
+	 */
72
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
+	{
74
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Registration
84
+	 */
85
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
+	{
87
+		return new self($props_n_values, true, $timezone);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Event ID
93
+	 *
94
+	 * @param        int $EVT_ID Event ID
95
+	 * @throws EE_Error
96
+	 * @throws RuntimeException
97
+	 */
98
+	public function set_event($EVT_ID = 0)
99
+	{
100
+		$this->set('EVT_ID', $EVT_ID);
101
+	}
102
+
103
+
104
+	/**
105
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
+	 * be routed to internal methods
107
+	 *
108
+	 * @param string $field_name
109
+	 * @param mixed  $field_value
110
+	 * @param bool   $use_default
111
+	 * @throws EE_Error
112
+	 * @throws EntityNotFoundException
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 * @throws ReflectionException
117
+	 * @throws RuntimeException
118
+	 */
119
+	public function set($field_name, $field_value, $use_default = false)
120
+	{
121
+		switch ($field_name) {
122
+			case 'REG_code':
123
+				if (! empty($field_value) && $this->reg_code() === null) {
124
+					$this->set_reg_code($field_value, $use_default);
125
+				}
126
+				break;
127
+			case 'STS_ID':
128
+				$this->set_status($field_value, $use_default);
129
+				break;
130
+			default:
131
+				parent::set($field_name, $field_value, $use_default);
132
+		}
133
+	}
134
+
135
+
136
+	/**
137
+	 * Set Status ID
138
+	 * updates the registration status and ALSO...
139
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
+	 *
142
+	 * @param string       $new_STS_ID
143
+	 * @param boolean      $use_default
144
+	 * @param ContextInterface|null $context
145
+	 * @return bool
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws ReflectionException
150
+	 * @throws RuntimeException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 */
154
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
155
+	{
156
+		// get current REG_Status
157
+		$old_STS_ID = $this->status_ID();
158
+		// if status has changed
159
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
+			&& ! empty($old_STS_ID) // and that old status is actually set
161
+			&& ! empty($new_STS_ID) // as well as the new status
162
+			&& $this->ID() // ensure registration is in the db
163
+		) {
164
+			// TO approved
165
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
+				// reserve a space by incrementing ticket and datetime sold values
167
+				$this->_reserve_registration_space();
168
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
+				// OR FROM  approved
170
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
+				// release a space by decrementing ticket and datetime sold values
172
+				$this->_release_registration_space();
173
+				do_action(
174
+					'AHEE__EE_Registration__set_status__from_approved',
175
+					$this,
176
+					$old_STS_ID,
177
+					$new_STS_ID,
178
+					$context
179
+				);
180
+			}
181
+			// update status
182
+			parent::set('STS_ID', $new_STS_ID, $use_default);
183
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
+			if($this->statusChangeUpdatesTransaction($context)) {
185
+				$this->updateTransactionAfterStatusChange();
186
+			}
187
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
+			return true;
189
+		}
190
+		//even though the old value matches the new value, it's still good to
191
+		//allow the parent set method to have a say
192
+		parent::set('STS_ID', $new_STS_ID, $use_default);
193
+		return true;
194
+	}
195
+
196
+
197
+	/**
198
+	 * update REGs and TXN when cancelled or declined registrations involved
199
+	 *
200
+	 * @param string       $new_STS_ID
201
+	 * @param string       $old_STS_ID
202
+	 * @param ContextInterface|null $context
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws ReflectionException
208
+	 */
209
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
210
+	{
211
+		// these reg statuses should not be considered in any calculations involving monies owing
212
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
+		// true if registration has been cancelled or declined
214
+		$this->updateIfCanceled(
215
+			$closed_reg_statuses,
216
+			$new_STS_ID,
217
+			$old_STS_ID,
218
+			$context
219
+		);
220
+		$this->updateIfDeclined(
221
+			$closed_reg_statuses,
222
+			$new_STS_ID,
223
+			$old_STS_ID,
224
+			$context
225
+		);
226
+	}
227
+
228
+
229
+	/**
230
+	 * update REGs and TXN when cancelled or declined registrations involved
231
+	 *
232
+	 * @param array        $closed_reg_statuses
233
+	 * @param string       $new_STS_ID
234
+	 * @param string       $old_STS_ID
235
+	 * @param ContextInterface|null $context
236
+	 * @throws EE_Error
237
+	 * @throws InvalidArgumentException
238
+	 * @throws InvalidDataTypeException
239
+	 * @throws InvalidInterfaceException
240
+	 * @throws ReflectionException
241
+	 */
242
+	private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
243
+	{
244
+		// true if registration has been cancelled or declined
245
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
+		) {
248
+			/** @type EE_Registration_Processor $registration_processor */
249
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
+			/** @type EE_Transaction_Processor $transaction_processor */
251
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
+			// cancelled or declined registration
253
+			$registration_processor->update_registration_after_being_canceled_or_declined(
254
+				$this,
255
+				$closed_reg_statuses
256
+			);
257
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
+				$this,
259
+				$closed_reg_statuses,
260
+				false
261
+			);
262
+			do_action(
263
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
264
+				$this,
265
+				$old_STS_ID,
266
+				$new_STS_ID,
267
+				$context
268
+			);
269
+			return;
270
+		}
271
+	}
272
+
273
+
274
+	/**
275
+	 * update REGs and TXN when cancelled or declined registrations involved
276
+	 *
277
+	 * @param array        $closed_reg_statuses
278
+	 * @param string       $new_STS_ID
279
+	 * @param string       $old_STS_ID
280
+	 * @param ContextInterface|null $context
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
288
+	{
289
+		// true if reinstating cancelled or declined registration
290
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
+		) {
293
+			/** @type EE_Registration_Processor $registration_processor */
294
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
+			/** @type EE_Transaction_Processor $transaction_processor */
296
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
+			// reinstating cancelled or declined registration
298
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
+				$this,
300
+				$closed_reg_statuses
301
+			);
302
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
+				$this,
304
+				$closed_reg_statuses,
305
+				false
306
+			);
307
+			do_action(
308
+				'AHEE__EE_Registration__set_status__after_reinstated',
309
+				$this,
310
+				$old_STS_ID,
311
+				$new_STS_ID,
312
+				$context
313
+			);
314
+		}
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param ContextInterface|null $context
320
+	 * @return bool
321
+	 */
322
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
323
+	{
324
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
325
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
+			array('spco_reg_step_attendee_information_process_registrations'),
327
+			$context,
328
+			$this
329
+		);
330
+		return ! (
331
+			$context instanceof ContextInterface
332
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
+		);
334
+	}
335
+
336
+
337
+	/**
338
+	 * @throws EE_Error
339
+	 * @throws EntityNotFoundException
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 * @throws RuntimeException
345
+	 */
346
+	private function updateTransactionAfterStatusChange()
347
+	{
348
+		/** @type EE_Transaction_Payments $transaction_payments */
349
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
+		$this->transaction()->update_status_based_on_total_paid(true);
352
+	}
353
+
354
+
355
+	/**
356
+	 *        get Status ID
357
+	 */
358
+	public function status_ID()
359
+	{
360
+		return $this->get('STS_ID');
361
+	}
362
+
363
+
364
+	/**
365
+	 * increments this registration's related ticket sold and corresponding datetime sold values
366
+	 *
367
+	 * @return void
368
+	 * @throws EE_Error
369
+	 * @throws EntityNotFoundException
370
+	 */
371
+	private function _reserve_registration_space()
372
+	{
373
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
374
+		// so stop tracking that this reg has a ticket reserved
375
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:". __LINE__ . ')');
376
+		$ticket = $this->ticket();
377
+		$ticket->increase_sold();
378
+		$ticket->save();
379
+		// possibly set event status to sold out
380
+		$this->event()->perform_sold_out_status_check();
381
+	}
382
+
383
+
384
+	/**
385
+	 * Gets the ticket this registration is for
386
+	 *
387
+	 * @param boolean $include_archived whether to include archived tickets or not.
388
+	 *
389
+	 * @return EE_Ticket|EE_Base_Class
390
+	 * @throws EE_Error
391
+	 */
392
+	public function ticket($include_archived = true)
393
+	{
394
+		$query_params = array();
395
+		if ($include_archived) {
396
+			$query_params['default_where_conditions'] = 'none';
397
+		}
398
+		return $this->get_first_related('Ticket', $query_params);
399
+	}
400
+
401
+
402
+	/**
403
+	 * Gets the event this registration is for
404
+	 *
405
+	 * @return EE_Event
406
+	 * @throws EE_Error
407
+	 * @throws EntityNotFoundException
408
+	 */
409
+	public function event()
410
+	{
411
+		$event = $this->get_first_related('Event');
412
+		if (! $event instanceof \EE_Event) {
413
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
414
+		}
415
+		return $event;
416
+	}
417
+
418
+
419
+	/**
420
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
421
+	 * with the author of the event this registration is for.
422
+	 *
423
+	 * @since 4.5.0
424
+	 * @return int
425
+	 * @throws EE_Error
426
+	 * @throws EntityNotFoundException
427
+	 */
428
+	public function wp_user()
429
+	{
430
+		$event = $this->event();
431
+		if ($event instanceof EE_Event) {
432
+			return $event->wp_user();
433
+		}
434
+		return 0;
435
+	}
436
+
437
+
438
+	/**
439
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
440
+	 *
441
+	 * @return void
442
+	 * @throws EE_Error
443
+	 */
444
+	private function _release_registration_space()
445
+	{
446
+		$ticket = $this->ticket();
447
+		$ticket->decrease_sold();
448
+		$ticket->save();
449
+	}
450
+
451
+
452
+	/**
453
+	 * tracks this registration's ticket reservation in extra meta
454
+	 * and can increment related ticket reserved and corresponding datetime reserved values
455
+	 *
456
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
457
+	 * @return void
458
+	 * @throws EE_Error
459
+	 * @throws InvalidArgumentException
460
+	 * @throws InvalidDataTypeException
461
+	 * @throws InvalidInterfaceException
462
+	 * @throws ReflectionException
463
+	 */
464
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
465
+	{
466
+		// only reserve ticket if space is not currently reserved
467
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
468
+			$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
469
+			// IMPORTANT !!!
470
+			// although checking $update_ticket first would be more efficient,
471
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
472
+			if (
473
+				$this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
474
+				&& $update_ticket
475
+			) {
476
+				$ticket = $this->ticket();
477
+				$ticket->increase_reserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
478
+				$ticket->save();
479
+			}
480
+		}
481
+	}
482
+
483
+
484
+	/**
485
+	 * stops tracking this registration's ticket reservation in extra meta
486
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
487
+	 *
488
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
489
+	 * @return void
490
+	 * @throws EE_Error
491
+	 * @throws InvalidArgumentException
492
+	 * @throws InvalidDataTypeException
493
+	 * @throws InvalidInterfaceException
494
+	 * @throws ReflectionException
495
+	 */
496
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
497
+	{
498
+		// only release ticket if space is currently reserved
499
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
500
+			$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
501
+			// IMPORTANT !!!
502
+			// although checking $update_ticket first would be more efficient,
503
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
504
+			if (
505
+				$this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
506
+				&& $update_ticket
507
+			) {
508
+				$ticket = $this->ticket();
509
+				$ticket->decrease_reserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
510
+				$ticket->save();
511
+			}
512
+		}
513
+	}
514
+
515
+
516
+	/**
517
+	 * Set Attendee ID
518
+	 *
519
+	 * @param        int $ATT_ID Attendee ID
520
+	 * @throws EE_Error
521
+	 * @throws RuntimeException
522
+	 */
523
+	public function set_attendee_id($ATT_ID = 0)
524
+	{
525
+		$this->set('ATT_ID', $ATT_ID);
526
+	}
527
+
528
+
529
+	/**
530
+	 *        Set Transaction ID
531
+	 *
532
+	 * @param        int $TXN_ID Transaction ID
533
+	 * @throws EE_Error
534
+	 * @throws RuntimeException
535
+	 */
536
+	public function set_transaction_id($TXN_ID = 0)
537
+	{
538
+		$this->set('TXN_ID', $TXN_ID);
539
+	}
540
+
541
+
542
+	/**
543
+	 *        Set Session
544
+	 *
545
+	 * @param    string $REG_session PHP Session ID
546
+	 * @throws EE_Error
547
+	 * @throws RuntimeException
548
+	 */
549
+	public function set_session($REG_session = '')
550
+	{
551
+		$this->set('REG_session', $REG_session);
552
+	}
553
+
554
+
555
+	/**
556
+	 *        Set Registration URL Link
557
+	 *
558
+	 * @param    string $REG_url_link Registration URL Link
559
+	 * @throws EE_Error
560
+	 * @throws RuntimeException
561
+	 */
562
+	public function set_reg_url_link($REG_url_link = '')
563
+	{
564
+		$this->set('REG_url_link', $REG_url_link);
565
+	}
566
+
567
+
568
+	/**
569
+	 *        Set Attendee Counter
570
+	 *
571
+	 * @param        int $REG_count Primary Attendee
572
+	 * @throws EE_Error
573
+	 * @throws RuntimeException
574
+	 */
575
+	public function set_count($REG_count = 1)
576
+	{
577
+		$this->set('REG_count', $REG_count);
578
+	}
579
+
580
+
581
+	/**
582
+	 *        Set Group Size
583
+	 *
584
+	 * @param        boolean $REG_group_size Group Registration
585
+	 * @throws EE_Error
586
+	 * @throws RuntimeException
587
+	 */
588
+	public function set_group_size($REG_group_size = false)
589
+	{
590
+		$this->set('REG_group_size', $REG_group_size);
591
+	}
592
+
593
+
594
+	/**
595
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
596
+	 *    EEM_Registration::status_id_not_approved
597
+	 *
598
+	 * @return        boolean
599
+	 */
600
+	public function is_not_approved()
601
+	{
602
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
603
+	}
604
+
605
+
606
+	/**
607
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
608
+	 *    EEM_Registration::status_id_pending_payment
609
+	 *
610
+	 * @return        boolean
611
+	 */
612
+	public function is_pending_payment()
613
+	{
614
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
615
+	}
616
+
617
+
618
+	/**
619
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
620
+	 *
621
+	 * @return        boolean
622
+	 */
623
+	public function is_approved()
624
+	{
625
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
626
+	}
627
+
628
+
629
+	/**
630
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
631
+	 *
632
+	 * @return        boolean
633
+	 */
634
+	public function is_cancelled()
635
+	{
636
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
637
+	}
638
+
639
+
640
+	/**
641
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
642
+	 *
643
+	 * @return        boolean
644
+	 */
645
+	public function is_declined()
646
+	{
647
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
648
+	}
649
+
650
+
651
+	/**
652
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
653
+	 *    EEM_Registration::status_id_incomplete
654
+	 *
655
+	 * @return        boolean
656
+	 */
657
+	public function is_incomplete()
658
+	{
659
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
660
+	}
661
+
662
+
663
+	/**
664
+	 *        Set Registration Date
665
+	 *
666
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
667
+	 *                                                 Date
668
+	 * @throws EE_Error
669
+	 * @throws RuntimeException
670
+	 */
671
+	public function set_reg_date($REG_date = false)
672
+	{
673
+		$this->set('REG_date', $REG_date);
674
+	}
675
+
676
+
677
+	/**
678
+	 *    Set final price owing for this registration after all ticket/price modifications
679
+	 *
680
+	 * @access    public
681
+	 * @param    float $REG_final_price
682
+	 * @throws EE_Error
683
+	 * @throws RuntimeException
684
+	 */
685
+	public function set_final_price($REG_final_price = 0.00)
686
+	{
687
+		$this->set('REG_final_price', $REG_final_price);
688
+	}
689
+
690
+
691
+	/**
692
+	 *    Set amount paid towards this registration's final price
693
+	 *
694
+	 * @access    public
695
+	 * @param    float $REG_paid
696
+	 * @throws EE_Error
697
+	 * @throws RuntimeException
698
+	 */
699
+	public function set_paid($REG_paid = 0.00)
700
+	{
701
+		$this->set('REG_paid', $REG_paid);
702
+	}
703
+
704
+
705
+	/**
706
+	 *        Attendee Is Going
707
+	 *
708
+	 * @param        boolean $REG_att_is_going Attendee Is Going
709
+	 * @throws EE_Error
710
+	 * @throws RuntimeException
711
+	 */
712
+	public function set_att_is_going($REG_att_is_going = false)
713
+	{
714
+		$this->set('REG_att_is_going', $REG_att_is_going);
715
+	}
716
+
717
+
718
+	/**
719
+	 * Gets the related attendee
720
+	 *
721
+	 * @return EE_Attendee
722
+	 * @throws EE_Error
723
+	 */
724
+	public function attendee()
725
+	{
726
+		return $this->get_first_related('Attendee');
727
+	}
728
+
729
+
730
+	/**
731
+	 *        get Event ID
732
+	 */
733
+	public function event_ID()
734
+	{
735
+		return $this->get('EVT_ID');
736
+	}
737
+
738
+
739
+	/**
740
+	 *        get Event ID
741
+	 */
742
+	public function event_name()
743
+	{
744
+		$event = $this->event_obj();
745
+		if ($event) {
746
+			return $event->name();
747
+		} else {
748
+			return null;
749
+		}
750
+	}
751
+
752
+
753
+	/**
754
+	 * Fetches the event this registration is for
755
+	 *
756
+	 * @return EE_Event
757
+	 * @throws EE_Error
758
+	 */
759
+	public function event_obj()
760
+	{
761
+		return $this->get_first_related('Event');
762
+	}
763
+
764
+
765
+	/**
766
+	 *        get Attendee ID
767
+	 */
768
+	public function attendee_ID()
769
+	{
770
+		return $this->get('ATT_ID');
771
+	}
772
+
773
+
774
+	/**
775
+	 *        get PHP Session ID
776
+	 */
777
+	public function session_ID()
778
+	{
779
+		return $this->get('REG_session');
780
+	}
781
+
782
+
783
+	/**
784
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
785
+	 *
786
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
787
+	 * @return string
788
+	 */
789
+	public function receipt_url($messenger = 'html')
790
+	{
791
+
792
+		/**
793
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
794
+		 * already in use on old system.  If there is then we just return the standard url for it.
795
+		 *
796
+		 * @since 4.5.0
797
+		 */
798
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
799
+		$has_custom             = EEH_Template::locate_template(
800
+			$template_relative_path,
801
+			array(),
802
+			true,
803
+			true,
804
+			true
805
+		);
806
+
807
+		if ($has_custom) {
808
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
809
+		}
810
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
811
+	}
812
+
813
+
814
+	/**
815
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
816
+	 *
817
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
818
+	 * @return string
819
+	 * @throws EE_Error
820
+	 */
821
+	public function invoice_url($messenger = 'html')
822
+	{
823
+		/**
824
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
825
+		 * already in use on old system.  If there is then we just return the standard url for it.
826
+		 *
827
+		 * @since 4.5.0
828
+		 */
829
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
830
+		$has_custom             = EEH_Template::locate_template(
831
+			$template_relative_path,
832
+			array(),
833
+			true,
834
+			true,
835
+			true
836
+		);
837
+
838
+		if ($has_custom) {
839
+			if ($messenger == 'html') {
840
+				return $this->invoice_url('launch');
841
+			}
842
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
843
+
844
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
845
+			if ($messenger == 'html') {
846
+				$query_args['html'] = true;
847
+			}
848
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
849
+		}
850
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
851
+	}
852
+
853
+
854
+	/**
855
+	 * get Registration URL Link
856
+	 *
857
+	 * @access public
858
+	 * @return string
859
+	 * @throws EE_Error
860
+	 */
861
+	public function reg_url_link()
862
+	{
863
+		return (string) $this->get('REG_url_link');
864
+	}
865
+
866
+
867
+	/**
868
+	 * Echoes out invoice_url()
869
+	 *
870
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
871
+	 * @return void
872
+	 * @throws EE_Error
873
+	 */
874
+	public function e_invoice_url($type = 'launch')
875
+	{
876
+		echo $this->invoice_url($type);
877
+	}
878
+
879
+
880
+	/**
881
+	 * Echoes out payment_overview_url
882
+	 */
883
+	public function e_payment_overview_url()
884
+	{
885
+		echo $this->payment_overview_url();
886
+	}
887
+
888
+
889
+	/**
890
+	 * Gets the URL for the checkout payment options reg step
891
+	 * with this registration's REG_url_link added as a query parameter
892
+	 *
893
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
894
+	 *                            payment overview url.
895
+	 * @return string
896
+	 * @throws InvalidInterfaceException
897
+	 * @throws InvalidDataTypeException
898
+	 * @throws EE_Error
899
+	 * @throws InvalidArgumentException
900
+	 */
901
+	public function payment_overview_url($clear_session = false)
902
+	{
903
+		return add_query_arg(
904
+			(array) apply_filters(
905
+				'FHEE__EE_Registration__payment_overview_url__query_args',
906
+				array(
907
+					'e_reg_url_link' => $this->reg_url_link(),
908
+					'step'           => 'payment_options',
909
+					'revisit'        => true,
910
+					'clear_session'  => (bool) $clear_session,
911
+				),
912
+				$this
913
+			),
914
+			EE_Registry::instance()->CFG->core->reg_page_url()
915
+		);
916
+	}
917
+
918
+
919
+	/**
920
+	 * Gets the URL for the checkout attendee information reg step
921
+	 * with this registration's REG_url_link added as a query parameter
922
+	 *
923
+	 * @return string
924
+	 * @throws InvalidInterfaceException
925
+	 * @throws InvalidDataTypeException
926
+	 * @throws EE_Error
927
+	 * @throws InvalidArgumentException
928
+	 */
929
+	public function edit_attendee_information_url()
930
+	{
931
+		return add_query_arg(
932
+			(array) apply_filters(
933
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
934
+				array(
935
+					'e_reg_url_link' => $this->reg_url_link(),
936
+					'step'           => 'attendee_information',
937
+					'revisit'        => true,
938
+				),
939
+				$this
940
+			),
941
+			EE_Registry::instance()->CFG->core->reg_page_url()
942
+		);
943
+	}
944
+
945
+
946
+	/**
947
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
948
+	 *
949
+	 * @return string
950
+	 * @throws EE_Error
951
+	 */
952
+	public function get_admin_edit_url()
953
+	{
954
+		return EEH_URL::add_query_args_and_nonce(array(
955
+			'page'    => 'espresso_registrations',
956
+			'action'  => 'view_registration',
957
+			'_REG_ID' => $this->ID(),
958
+		), admin_url('admin.php'));
959
+	}
960
+
961
+
962
+	/**
963
+	 *    is_primary_registrant?
964
+	 */
965
+	public function is_primary_registrant()
966
+	{
967
+		return $this->get('REG_count') == 1 ? true : false;
968
+	}
969
+
970
+
971
+	/**
972
+	 * This returns the primary registration object for this registration group (which may be this object).
973
+	 *
974
+	 * @return EE_Registration
975
+	 * @throws EE_Error
976
+	 */
977
+	public function get_primary_registration()
978
+	{
979
+		if ($this->is_primary_registrant()) {
980
+			return $this;
981
+		}
982
+
983
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
984
+		/** @var EE_Registration $primary_registrant */
985
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
986
+			array(
987
+				'TXN_ID'    => $this->transaction_ID(),
988
+				'REG_count' => 1,
989
+			),
990
+		));
991
+		return $primary_registrant;
992
+	}
993
+
994
+
995
+	/**
996
+	 *        get  Attendee Number
997
+	 *
998
+	 * @access        public
999
+	 */
1000
+	public function count()
1001
+	{
1002
+		return $this->get('REG_count');
1003
+	}
1004
+
1005
+
1006
+	/**
1007
+	 *        get Group Size
1008
+	 */
1009
+	public function group_size()
1010
+	{
1011
+		return $this->get('REG_group_size');
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 *        get Registration Date
1017
+	 */
1018
+	public function date()
1019
+	{
1020
+		return $this->get('REG_date');
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 * gets a pretty date
1026
+	 *
1027
+	 * @param string $date_format
1028
+	 * @param string $time_format
1029
+	 * @return string
1030
+	 * @throws EE_Error
1031
+	 */
1032
+	public function pretty_date($date_format = null, $time_format = null)
1033
+	{
1034
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1035
+	}
1036
+
1037
+
1038
+	/**
1039
+	 * final_price
1040
+	 * the registration's share of the transaction total, so that the
1041
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1042
+	 *
1043
+	 * @return float
1044
+	 * @throws EE_Error
1045
+	 */
1046
+	public function final_price()
1047
+	{
1048
+		return $this->get('REG_final_price');
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * pretty_final_price
1054
+	 *  final price as formatted string, with correct decimal places and currency symbol
1055
+	 *
1056
+	 * @return string
1057
+	 * @throws EE_Error
1058
+	 */
1059
+	public function pretty_final_price()
1060
+	{
1061
+		return $this->get_pretty('REG_final_price');
1062
+	}
1063
+
1064
+
1065
+	/**
1066
+	 * get paid (yeah)
1067
+	 *
1068
+	 * @return float
1069
+	 * @throws EE_Error
1070
+	 */
1071
+	public function paid()
1072
+	{
1073
+		return $this->get('REG_paid');
1074
+	}
1075
+
1076
+
1077
+	/**
1078
+	 * pretty_paid
1079
+	 *
1080
+	 * @return float
1081
+	 * @throws EE_Error
1082
+	 */
1083
+	public function pretty_paid()
1084
+	{
1085
+		return $this->get_pretty('REG_paid');
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * owes_monies_and_can_pay
1091
+	 * whether or not this registration has monies owing and it's' status allows payment
1092
+	 *
1093
+	 * @param array $requires_payment
1094
+	 * @return bool
1095
+	 * @throws EE_Error
1096
+	 */
1097
+	public function owes_monies_and_can_pay($requires_payment = array())
1098
+	{
1099
+		// these reg statuses require payment (if event is not free)
1100
+		$requires_payment = ! empty($requires_payment)
1101
+			? $requires_payment
1102
+			: EEM_Registration::reg_statuses_that_allow_payment();
1103
+		if (in_array($this->status_ID(), $requires_payment) &&
1104
+			$this->final_price() != 0 &&
1105
+			$this->final_price() != $this->paid()
1106
+		) {
1107
+			return true;
1108
+		} else {
1109
+			return false;
1110
+		}
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * Prints out the return value of $this->pretty_status()
1116
+	 *
1117
+	 * @param bool $show_icons
1118
+	 * @return void
1119
+	 * @throws EE_Error
1120
+	 */
1121
+	public function e_pretty_status($show_icons = false)
1122
+	{
1123
+		echo $this->pretty_status($show_icons);
1124
+	}
1125
+
1126
+
1127
+	/**
1128
+	 * Returns a nice version of the status for displaying to customers
1129
+	 *
1130
+	 * @param bool $show_icons
1131
+	 * @return string
1132
+	 * @throws EE_Error
1133
+	 */
1134
+	public function pretty_status($show_icons = false)
1135
+	{
1136
+		$status = EEM_Status::instance()->localized_status(
1137
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1138
+			false,
1139
+			'sentence'
1140
+		);
1141
+		$icon   = '';
1142
+		switch ($this->status_ID()) {
1143
+			case EEM_Registration::status_id_approved:
1144
+				$icon = $show_icons
1145
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1146
+					: '';
1147
+				break;
1148
+			case EEM_Registration::status_id_pending_payment:
1149
+				$icon = $show_icons
1150
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1151
+					: '';
1152
+				break;
1153
+			case EEM_Registration::status_id_not_approved:
1154
+				$icon = $show_icons
1155
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1156
+					: '';
1157
+				break;
1158
+			case EEM_Registration::status_id_cancelled:
1159
+				$icon = $show_icons
1160
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1161
+					: '';
1162
+				break;
1163
+			case EEM_Registration::status_id_incomplete:
1164
+				$icon = $show_icons
1165
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1166
+					: '';
1167
+				break;
1168
+			case EEM_Registration::status_id_declined:
1169
+				$icon = $show_icons
1170
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1171
+					: '';
1172
+				break;
1173
+			case EEM_Registration::status_id_wait_list:
1174
+				$icon = $show_icons
1175
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1176
+					: '';
1177
+				break;
1178
+		}
1179
+		return $icon . $status[$this->status_ID()];
1180
+	}
1181
+
1182
+
1183
+	/**
1184
+	 *        get Attendee Is Going
1185
+	 */
1186
+	public function att_is_going()
1187
+	{
1188
+		return $this->get('REG_att_is_going');
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * Gets related answers
1194
+	 *
1195
+	 * @param array $query_params like EEM_Base::get_all
1196
+	 * @return EE_Answer[]
1197
+	 * @throws EE_Error
1198
+	 */
1199
+	public function answers($query_params = null)
1200
+	{
1201
+		return $this->get_many_related('Answer', $query_params);
1202
+	}
1203
+
1204
+
1205
+	/**
1206
+	 * Gets the registration's answer value to the specified question
1207
+	 * (either the question's ID or a question object)
1208
+	 *
1209
+	 * @param EE_Question|int $question
1210
+	 * @param bool            $pretty_value
1211
+	 * @return array|string if pretty_value= true, the result will always be a string
1212
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1213
+	 * will convert it into some kind of string)
1214
+	 * @throws EE_Error
1215
+	 */
1216
+	public function answer_value_to_question($question, $pretty_value = true)
1217
+	{
1218
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1219
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * question_groups
1225
+	 * returns an array of EE_Question_Group objects for this registration
1226
+	 *
1227
+	 * @return EE_Question_Group[]
1228
+	 * @throws EE_Error
1229
+	 * @throws EntityNotFoundException
1230
+	 */
1231
+	public function question_groups()
1232
+	{
1233
+		$question_groups = array();
1234
+		if ($this->event() instanceof EE_Event) {
1235
+			$question_groups = $this->event()->question_groups(
1236
+				array(
1237
+					array(
1238
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1239
+					),
1240
+					'order_by' => array('QSG_order' => 'ASC'),
1241
+				)
1242
+			);
1243
+		}
1244
+		return $question_groups;
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * count_question_groups
1250
+	 * returns a count of the number of EE_Question_Group objects for this registration
1251
+	 *
1252
+	 * @return int
1253
+	 * @throws EE_Error
1254
+	 * @throws EntityNotFoundException
1255
+	 */
1256
+	public function count_question_groups()
1257
+	{
1258
+		$qg_count = 0;
1259
+		if ($this->event() instanceof EE_Event) {
1260
+			$qg_count = $this->event()->count_related(
1261
+				'Question_Group',
1262
+				array(
1263
+					array(
1264
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1265
+					),
1266
+				)
1267
+			);
1268
+		}
1269
+		return $qg_count;
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 * Returns the registration date in the 'standard' string format
1275
+	 * (function may be improved in the future to allow for different formats and timezones)
1276
+	 *
1277
+	 * @return string
1278
+	 * @throws EE_Error
1279
+	 */
1280
+	public function reg_date()
1281
+	{
1282
+		return $this->get_datetime('REG_date');
1283
+	}
1284
+
1285
+
1286
+	/**
1287
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1288
+	 * the ticket this registration purchased, or the datetime they have registered
1289
+	 * to attend)
1290
+	 *
1291
+	 * @return EE_Datetime_Ticket
1292
+	 * @throws EE_Error
1293
+	 */
1294
+	public function datetime_ticket()
1295
+	{
1296
+		return $this->get_first_related('Datetime_Ticket');
1297
+	}
1298
+
1299
+
1300
+	/**
1301
+	 * Sets the registration's datetime_ticket.
1302
+	 *
1303
+	 * @param EE_Datetime_Ticket $datetime_ticket
1304
+	 * @return EE_Datetime_Ticket
1305
+	 * @throws EE_Error
1306
+	 */
1307
+	public function set_datetime_ticket($datetime_ticket)
1308
+	{
1309
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1310
+	}
1311
+
1312
+	/**
1313
+	 * Gets deleted
1314
+	 *
1315
+	 * @return bool
1316
+	 * @throws EE_Error
1317
+	 */
1318
+	public function deleted()
1319
+	{
1320
+		return $this->get('REG_deleted');
1321
+	}
1322
+
1323
+	/**
1324
+	 * Sets deleted
1325
+	 *
1326
+	 * @param boolean $deleted
1327
+	 * @return bool
1328
+	 * @throws EE_Error
1329
+	 * @throws RuntimeException
1330
+	 */
1331
+	public function set_deleted($deleted)
1332
+	{
1333
+		if ($deleted) {
1334
+			$this->delete();
1335
+		} else {
1336
+			$this->restore();
1337
+		}
1338
+	}
1339
+
1340
+
1341
+	/**
1342
+	 * Get the status object of this object
1343
+	 *
1344
+	 * @return EE_Status
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	public function status_obj()
1348
+	{
1349
+		return $this->get_first_related('Status');
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Returns the number of times this registration has checked into any of the datetimes
1355
+	 * its available for
1356
+	 *
1357
+	 * @return int
1358
+	 * @throws EE_Error
1359
+	 */
1360
+	public function count_checkins()
1361
+	{
1362
+		return $this->get_model()->count_related($this, 'Checkin');
1363
+	}
1364
+
1365
+
1366
+	/**
1367
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1368
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1369
+	 *
1370
+	 * @return int
1371
+	 * @throws EE_Error
1372
+	 */
1373
+	public function count_checkins_not_checkedout()
1374
+	{
1375
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1376
+	}
1377
+
1378
+
1379
+	/**
1380
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1381
+	 *
1382
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1383
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1384
+	 *                                          consider registration status as well as datetime access.
1385
+	 * @return bool
1386
+	 * @throws EE_Error
1387
+	 */
1388
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1389
+	{
1390
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1391
+
1392
+		//first check registration status
1393
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1394
+			return false;
1395
+		}
1396
+		//is there a datetime ticket that matches this dtt_ID?
1397
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1398
+			array(
1399
+				'TKT_ID' => $this->get('TKT_ID'),
1400
+				'DTT_ID' => $DTT_ID,
1401
+			),
1402
+		)))
1403
+		) {
1404
+			return false;
1405
+		}
1406
+
1407
+		//final check is against TKT_uses
1408
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1409
+	}
1410
+
1411
+
1412
+	/**
1413
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1414
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1415
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1416
+	 * then return false.  Otherwise return true.
1417
+	 *
1418
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1419
+	 * @return bool true means can checkin.  false means cannot checkin.
1420
+	 * @throws EE_Error
1421
+	 */
1422
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1423
+	{
1424
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1425
+
1426
+		if (! $DTT_ID) {
1427
+			return false;
1428
+		}
1429
+
1430
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1431
+
1432
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1433
+		// check-in or not.
1434
+		if (! $max_uses || $max_uses === EE_INF) {
1435
+			return true;
1436
+		}
1437
+
1438
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1439
+		//go ahead and toggle.
1440
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1441
+			return true;
1442
+		}
1443
+
1444
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1445
+		//disallows further check-ins.
1446
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1447
+			array(
1448
+				'REG_ID' => $this->ID(),
1449
+				'CHK_in' => true,
1450
+			),
1451
+		), 'DTT_ID', true);
1452
+		// checkins have already reached their max number of uses
1453
+		// so registrant can NOT checkin
1454
+		if ($count_unique_dtt_checkins >= $max_uses) {
1455
+			EE_Error::add_error(
1456
+				esc_html__(
1457
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1458
+					'event_espresso'
1459
+				),
1460
+				__FILE__,
1461
+				__FUNCTION__,
1462
+				__LINE__
1463
+			);
1464
+			return false;
1465
+		}
1466
+		return true;
1467
+	}
1468
+
1469
+
1470
+	/**
1471
+	 * toggle Check-in status for this registration
1472
+	 * Check-ins are toggled in the following order:
1473
+	 * never checked in -> checked in
1474
+	 * checked in -> checked out
1475
+	 * checked out -> checked in
1476
+	 *
1477
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1478
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1479
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1480
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1481
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1482
+	 * @throws EE_Error
1483
+	 */
1484
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1485
+	{
1486
+		if (empty($DTT_ID)) {
1487
+			$datetime = $this->get_latest_related_datetime();
1488
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1489
+			// verify the registration can checkin for the given DTT_ID
1490
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1491
+			EE_Error::add_error(
1492
+				sprintf(
1493
+					esc_html__(
1494
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1495
+						'event_espresso'
1496
+					),
1497
+					$this->ID(),
1498
+					$DTT_ID
1499
+				),
1500
+				__FILE__,
1501
+				__FUNCTION__,
1502
+				__LINE__
1503
+			);
1504
+			return false;
1505
+		}
1506
+		$status_paths = array(
1507
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1508
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1509
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1510
+		);
1511
+		//start by getting the current status so we know what status we'll be changing to.
1512
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1513
+		$status_to  = $status_paths[$cur_status];
1514
+		// database only records true for checked IN or false for checked OUT
1515
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1516
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1517
+		// add relation - note Check-ins are always creating new rows
1518
+		// because we are keeping track of Check-ins over time.
1519
+		// Eventually we'll probably want to show a list table
1520
+		// for the individual Check-ins so that they can be managed.
1521
+		$checkin = EE_Checkin::new_instance(array(
1522
+			'REG_ID' => $this->ID(),
1523
+			'DTT_ID' => $DTT_ID,
1524
+			'CHK_in' => $new_status,
1525
+		));
1526
+		// if the record could not be saved then return false
1527
+		if ($checkin->save() === 0) {
1528
+			if (WP_DEBUG) {
1529
+				global $wpdb;
1530
+				$error = sprintf(
1531
+					esc_html__(
1532
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1533
+						'event_espresso'
1534
+					),
1535
+					'<br />',
1536
+					$wpdb->last_error
1537
+				);
1538
+			} else {
1539
+				$error = esc_html__(
1540
+					'Registration check in update failed because of an unknown database error',
1541
+					'event_espresso'
1542
+				);
1543
+			}
1544
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1545
+			return false;
1546
+		}
1547
+		return $status_to;
1548
+	}
1549
+
1550
+
1551
+	/**
1552
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1553
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1554
+	 *
1555
+	 * @return EE_Datetime|null
1556
+	 * @throws EE_Error
1557
+	 */
1558
+	public function get_latest_related_datetime()
1559
+	{
1560
+		return EEM_Datetime::instance()->get_one(
1561
+			array(
1562
+				array(
1563
+					'Ticket.Registration.REG_ID' => $this->ID(),
1564
+				),
1565
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1566
+			)
1567
+		);
1568
+	}
1569
+
1570
+
1571
+	/**
1572
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1573
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1574
+	 *
1575
+	 * @throws EE_Error
1576
+	 */
1577
+	public function get_earliest_related_datetime()
1578
+	{
1579
+		return EEM_Datetime::instance()->get_one(
1580
+			array(
1581
+				array(
1582
+					'Ticket.Registration.REG_ID' => $this->ID(),
1583
+				),
1584
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1585
+			)
1586
+		);
1587
+	}
1588
+
1589
+
1590
+	/**
1591
+	 * This method simply returns the check-in status for this registration and the given datetime.
1592
+	 * If neither the datetime nor the checkin values are provided as arguments,
1593
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1594
+	 *
1595
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1596
+	 *                            (if empty we'll get the primary datetime for
1597
+	 *                            this registration (via event) and use it's ID);
1598
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1599
+	 *
1600
+	 * @return int                Integer representing Check-in status.
1601
+	 * @throws EE_Error
1602
+	 */
1603
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1604
+	{
1605
+		$checkin_query_params = array(
1606
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1607
+		);
1608
+
1609
+		if ($DTT_ID > 0) {
1610
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1611
+		}
1612
+
1613
+		//get checkin object (if exists)
1614
+		$checkin = $checkin instanceof EE_Checkin
1615
+			? $checkin
1616
+			: $this->get_first_related('Checkin', $checkin_query_params);
1617
+		if ($checkin instanceof EE_Checkin) {
1618
+			if ($checkin->get('CHK_in')) {
1619
+				return EE_Checkin::status_checked_in; //checked in
1620
+			}
1621
+			return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1622
+		}
1623
+		return EE_Checkin::status_checked_never; //never been checked in
1624
+	}
1625
+
1626
+
1627
+	/**
1628
+	 * This method returns a localized message for the toggled Check-in message.
1629
+	 *
1630
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1631
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1632
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1633
+	 *                     message can be customized with the attendee name.
1634
+	 * @return string internationalized message
1635
+	 * @throws EE_Error
1636
+	 */
1637
+	public function get_checkin_msg($DTT_ID, $error = false)
1638
+	{
1639
+		//let's get the attendee first so we can include the name of the attendee
1640
+		$attendee = $this->get_first_related('Attendee');
1641
+		if ($attendee instanceof EE_Attendee) {
1642
+			if ($error) {
1643
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1644
+			}
1645
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1646
+			//what is the status message going to be?
1647
+			switch ($cur_status) {
1648
+				case EE_Checkin::status_checked_never:
1649
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1650
+						$attendee->full_name());
1651
+					break;
1652
+				case EE_Checkin::status_checked_in:
1653
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1654
+					break;
1655
+				case EE_Checkin::status_checked_out:
1656
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1657
+					break;
1658
+			}
1659
+		}
1660
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1661
+	}
1662
+
1663
+
1664
+	/**
1665
+	 * Returns the related EE_Transaction to this registration
1666
+	 *
1667
+	 * @return EE_Transaction
1668
+	 * @throws EE_Error
1669
+	 * @throws EntityNotFoundException
1670
+	 */
1671
+	public function transaction()
1672
+	{
1673
+		$transaction = $this->get_first_related('Transaction');
1674
+		if (! $transaction instanceof \EE_Transaction) {
1675
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1676
+		}
1677
+		return $transaction;
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 *        get Registration Code
1683
+	 */
1684
+	public function reg_code()
1685
+	{
1686
+		return $this->get('REG_code');
1687
+	}
1688
+
1689
+
1690
+	/**
1691
+	 *        get Transaction ID
1692
+	 */
1693
+	public function transaction_ID()
1694
+	{
1695
+		return $this->get('TXN_ID');
1696
+	}
1697
+
1698
+
1699
+	/**
1700
+	 * @return int
1701
+	 * @throws EE_Error
1702
+	 */
1703
+	public function ticket_ID()
1704
+	{
1705
+		return $this->get('TKT_ID');
1706
+	}
1707
+
1708
+
1709
+	/**
1710
+	 *        Set Registration Code
1711
+	 *
1712
+	 * @access    public
1713
+	 * @param    string  $REG_code Registration Code
1714
+	 * @param    boolean $use_default
1715
+	 * @throws EE_Error
1716
+	 */
1717
+	public function set_reg_code($REG_code, $use_default = false)
1718
+	{
1719
+		if (empty($REG_code)) {
1720
+			EE_Error::add_error(
1721
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1722
+				__FILE__,
1723
+				__FUNCTION__,
1724
+				__LINE__
1725
+			);
1726
+			return;
1727
+		}
1728
+		if (! $this->reg_code()) {
1729
+			parent::set('REG_code', $REG_code, $use_default);
1730
+		} else {
1731
+			EE_Error::doing_it_wrong(
1732
+				__CLASS__ . '::' . __FUNCTION__,
1733
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1734
+				'4.6.0'
1735
+			);
1736
+		}
1737
+	}
1738
+
1739
+
1740
+	/**
1741
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1742
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1743
+	 *    $registration->transaction()->registrations();
1744
+	 *
1745
+	 * @since 4.5.0
1746
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1747
+	 * @throws EE_Error
1748
+	 */
1749
+	public function get_all_other_registrations_in_group()
1750
+	{
1751
+		if ($this->group_size() < 2) {
1752
+			return array();
1753
+		}
1754
+
1755
+		$query[0] = array(
1756
+			'TXN_ID' => $this->transaction_ID(),
1757
+			'REG_ID' => array('!=', $this->ID()),
1758
+			'TKT_ID' => $this->ticket_ID(),
1759
+		);
1760
+		/** @var EE_Registration[] $registrations */
1761
+		$registrations = $this->get_model()->get_all($query);
1762
+		return $registrations;
1763
+	}
1764
+
1765
+	/**
1766
+	 * Return the link to the admin details for the object.
1767
+	 *
1768
+	 * @return string
1769
+	 * @throws EE_Error
1770
+	 */
1771
+	public function get_admin_details_link()
1772
+	{
1773
+		EE_Registry::instance()->load_helper('URL');
1774
+		return EEH_URL::add_query_args_and_nonce(
1775
+			array(
1776
+				'page'    => 'espresso_registrations',
1777
+				'action'  => 'view_registration',
1778
+				'_REG_ID' => $this->ID(),
1779
+			),
1780
+			admin_url('admin.php')
1781
+		);
1782
+	}
1783
+
1784
+	/**
1785
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1786
+	 *
1787
+	 * @return string
1788
+	 * @throws EE_Error
1789
+	 */
1790
+	public function get_admin_edit_link()
1791
+	{
1792
+		return $this->get_admin_details_link();
1793
+	}
1794
+
1795
+	/**
1796
+	 * Returns the link to a settings page for the object.
1797
+	 *
1798
+	 * @return string
1799
+	 * @throws EE_Error
1800
+	 */
1801
+	public function get_admin_settings_link()
1802
+	{
1803
+		return $this->get_admin_details_link();
1804
+	}
1805
+
1806
+	/**
1807
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1808
+	 *
1809
+	 * @return string
1810
+	 */
1811
+	public function get_admin_overview_link()
1812
+	{
1813
+		EE_Registry::instance()->load_helper('URL');
1814
+		return EEH_URL::add_query_args_and_nonce(
1815
+			array(
1816
+				'page' => 'espresso_registrations',
1817
+			),
1818
+			admin_url('admin.php')
1819
+		);
1820
+	}
1821
+
1822
+
1823
+	/**
1824
+	 * @param array $query_params
1825
+	 *
1826
+	 * @return \EE_Registration[]
1827
+	 * @throws EE_Error
1828
+	 */
1829
+	public function payments($query_params = array())
1830
+	{
1831
+		return $this->get_many_related('Payment', $query_params);
1832
+	}
1833
+
1834
+
1835
+	/**
1836
+	 * @param array $query_params
1837
+	 *
1838
+	 * @return \EE_Registration_Payment[]
1839
+	 * @throws EE_Error
1840
+	 */
1841
+	public function registration_payments($query_params = array())
1842
+	{
1843
+		return $this->get_many_related('Registration_Payment', $query_params);
1844
+	}
1845
+
1846
+
1847
+	/**
1848
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1849
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1850
+	 *
1851
+	 * @return EE_Payment_Method|null
1852
+	 */
1853
+	public function payment_method()
1854
+	{
1855
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1856
+	}
1857
+
1858
+
1859
+	/**
1860
+	 * @return \EE_Line_Item
1861
+	 * @throws EntityNotFoundException
1862
+	 * @throws EE_Error
1863
+	 */
1864
+	public function ticket_line_item()
1865
+	{
1866
+		$ticket            = $this->ticket();
1867
+		$transaction       = $this->transaction();
1868
+		$line_item         = null;
1869
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1870
+			$transaction->total_line_item(),
1871
+			'Ticket',
1872
+			array($ticket->ID())
1873
+		);
1874
+		foreach ($ticket_line_items as $ticket_line_item) {
1875
+			if (
1876
+				$ticket_line_item instanceof \EE_Line_Item
1877
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1878
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1879
+			) {
1880
+				$line_item = $ticket_line_item;
1881
+				break;
1882
+			}
1883
+		}
1884
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1885
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1886
+		}
1887
+		return $line_item;
1888
+	}
1889
+
1890
+
1891
+	/**
1892
+	 * Soft Deletes this model object.
1893
+	 *
1894
+	 * @return boolean | int
1895
+	 * @throws RuntimeException
1896
+	 * @throws EE_Error
1897
+	 */
1898
+	public function delete()
1899
+	{
1900
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1901
+			$this->set_status(EEM_Registration::status_id_cancelled);
1902
+		}
1903
+		return parent::delete();
1904
+	}
1905
+
1906
+
1907
+	/**
1908
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1909
+	 *
1910
+	 * @throws EE_Error
1911
+	 * @throws RuntimeException
1912
+	 */
1913
+	public function restore()
1914
+	{
1915
+		$previous_status = $this->get_extra_meta(
1916
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1917
+			true,
1918
+			EEM_Registration::status_id_cancelled
1919
+		);
1920
+		if ($previous_status) {
1921
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1922
+			$this->set_status($previous_status);
1923
+		}
1924
+		return parent::restore();
1925
+	}
1926
+
1927
+
1928
+	/**
1929
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1930
+	 *
1931
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1932
+	 *                                           depending on whether the reg status changes to or from "Approved"
1933
+	 * @return boolean whether the Registration status was updated
1934
+	 * @throws EE_Error
1935
+	 * @throws RuntimeException
1936
+	 */
1937
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1938
+	{
1939
+		$paid = $this->paid();
1940
+		$price = $this->final_price();
1941
+		switch(true) {
1942
+			// overpaid or paid
1943
+			case EEH_Money::compare_floats($paid, $price, '>'):
1944
+			case EEH_Money::compare_floats($paid, $price):
1945
+				$new_status = EEM_Registration::status_id_approved;
1946
+				break;
1947
+			//  underpaid
1948
+			case EEH_Money::compare_floats($paid, $price, '<'):
1949
+				$new_status = EEM_Registration::status_id_pending_payment;
1950
+				break;
1951
+			// uhhh Houston...
1952
+			default:
1953
+				throw new RuntimeException(
1954
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1955
+				);
1956
+		}
1957
+		if ($new_status !== $this->status_ID()) {
1958
+			if ($trigger_set_status_logic) {
1959
+				return $this->set_status($new_status);
1960
+			}
1961
+			parent::set('STS_ID', $new_status);
1962
+			return true;
1963
+		}
1964
+		return false;
1965
+	}
1966
+
1967
+
1968
+	/*************************** DEPRECATED ***************************/
1969
+
1970
+
1971
+	/**
1972
+	 * @deprecated
1973
+	 * @since     4.7.0
1974
+	 * @access    public
1975
+	 */
1976
+	public function price_paid()
1977
+	{
1978
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1979
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1980
+			'4.7.0');
1981
+		return $this->final_price();
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * @deprecated
1987
+	 * @since     4.7.0
1988
+	 * @access    public
1989
+	 * @param    float $REG_final_price
1990
+	 * @throws EE_Error
1991
+	 * @throws RuntimeException
1992
+	 */
1993
+	public function set_price_paid($REG_final_price = 0.00)
1994
+	{
1995
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1996
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1997
+			'4.7.0');
1998
+		$this->set_final_price($REG_final_price);
1999
+	}
2000
+
2001
+
2002
+	/**
2003
+	 * @deprecated
2004
+	 * @since 4.7.0
2005
+	 * @return string
2006
+	 * @throws EE_Error
2007
+	 */
2008
+	public function pretty_price_paid()
2009
+	{
2010
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
2011
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2012
+				'event_espresso'), '4.7.0');
2013
+		return $this->pretty_final_price();
2014
+	}
2015
+
2016
+
2017
+	/**
2018
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2019
+	 *
2020
+	 * @deprecated 4.9.17
2021
+	 * @return EE_Datetime
2022
+	 * @throws EE_Error
2023
+	 * @throws EntityNotFoundException
2024
+	 */
2025
+	public function get_related_primary_datetime()
2026
+	{
2027
+		EE_Error::doing_it_wrong(
2028
+			__METHOD__,
2029
+			esc_html__(
2030
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2031
+				'event_espresso'
2032
+			),
2033
+			'4.9.17',
2034
+			'5.0.0'
2035
+		);
2036
+		return $this->event()->primary_datetime();
2037
+	}
2038 2038
 
2039 2039
 
2040 2040
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
     {
121 121
         switch ($field_name) {
122 122
             case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
123
+                if ( ! empty($field_value) && $this->reg_code() === null) {
124 124
                     $this->set_reg_code($field_value, $use_default);
125 125
                 }
126 126
                 break;
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
             // update status
182 182
             parent::set('STS_ID', $new_STS_ID, $use_default);
183 183
             $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
184
+            if ($this->statusChangeUpdatesTransaction($context)) {
185 185
                 $this->updateTransactionAfterStatusChange();
186 186
             }
187 187
             do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
@@ -372,7 +372,7 @@  discard block
 block discarded – undo
372 372
     {
373 373
         // reserved ticket and datetime counts will be decremented as sold counts are incremented
374 374
         // so stop tracking that this reg has a ticket reserved
375
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:". __LINE__ . ')');
375
+        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:".__LINE__.')');
376 376
         $ticket = $this->ticket();
377 377
         $ticket->increase_sold();
378 378
         $ticket->save();
@@ -409,7 +409,7 @@  discard block
 block discarded – undo
409 409
     public function event()
410 410
     {
411 411
         $event = $this->get_first_related('Event');
412
-        if (! $event instanceof \EE_Event) {
412
+        if ( ! $event instanceof \EE_Event) {
413 413
             throw new EntityNotFoundException('Event ID', $this->event_ID());
414 414
         }
415 415
         return $event;
@@ -474,7 +474,7 @@  discard block
 block discarded – undo
474 474
                 && $update_ticket
475 475
             ) {
476 476
                 $ticket = $this->ticket();
477
-                $ticket->increase_reserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
477
+                $ticket->increase_reserved(1, "REG: {$this->ID()} (ln:".__LINE__.')');
478 478
                 $ticket->save();
479 479
             }
480 480
         }
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
                 && $update_ticket
507 507
             ) {
508 508
                 $ticket = $this->ticket();
509
-                $ticket->decrease_reserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
509
+                $ticket->decrease_reserved(1, true, "REG: {$this->ID()} (ln:".__LINE__.')');
510 510
                 $ticket->save();
511 511
             }
512 512
         }
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
             false,
1139 1139
             'sentence'
1140 1140
         );
1141
-        $icon   = '';
1141
+        $icon = '';
1142 1142
         switch ($this->status_ID()) {
1143 1143
             case EEM_Registration::status_id_approved:
1144 1144
                 $icon = $show_icons
@@ -1176,7 +1176,7 @@  discard block
 block discarded – undo
1176 1176
                     : '';
1177 1177
                 break;
1178 1178
         }
1179
-        return $icon . $status[$this->status_ID()];
1179
+        return $icon.$status[$this->status_ID()];
1180 1180
     }
1181 1181
 
1182 1182
 
@@ -1394,7 +1394,7 @@  discard block
 block discarded – undo
1394 1394
             return false;
1395 1395
         }
1396 1396
         //is there a datetime ticket that matches this dtt_ID?
1397
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1397
+        if ( ! (EEM_Datetime_Ticket::instance()->exists(array(
1398 1398
             array(
1399 1399
                 'TKT_ID' => $this->get('TKT_ID'),
1400 1400
                 'DTT_ID' => $DTT_ID,
@@ -1423,7 +1423,7 @@  discard block
 block discarded – undo
1423 1423
     {
1424 1424
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1425 1425
 
1426
-        if (! $DTT_ID) {
1426
+        if ( ! $DTT_ID) {
1427 1427
             return false;
1428 1428
         }
1429 1429
 
@@ -1431,7 +1431,7 @@  discard block
 block discarded – undo
1431 1431
 
1432 1432
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1433 1433
         // check-in or not.
1434
-        if (! $max_uses || $max_uses === EE_INF) {
1434
+        if ( ! $max_uses || $max_uses === EE_INF) {
1435 1435
             return true;
1436 1436
         }
1437 1437
 
@@ -1487,7 +1487,7 @@  discard block
 block discarded – undo
1487 1487
             $datetime = $this->get_latest_related_datetime();
1488 1488
             $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1489 1489
             // verify the registration can checkin for the given DTT_ID
1490
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1490
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1491 1491
             EE_Error::add_error(
1492 1492
                 sprintf(
1493 1493
                     esc_html__(
@@ -1671,7 +1671,7 @@  discard block
 block discarded – undo
1671 1671
     public function transaction()
1672 1672
     {
1673 1673
         $transaction = $this->get_first_related('Transaction');
1674
-        if (! $transaction instanceof \EE_Transaction) {
1674
+        if ( ! $transaction instanceof \EE_Transaction) {
1675 1675
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1676 1676
         }
1677 1677
         return $transaction;
@@ -1725,11 +1725,11 @@  discard block
 block discarded – undo
1725 1725
             );
1726 1726
             return;
1727 1727
         }
1728
-        if (! $this->reg_code()) {
1728
+        if ( ! $this->reg_code()) {
1729 1729
             parent::set('REG_code', $REG_code, $use_default);
1730 1730
         } else {
1731 1731
             EE_Error::doing_it_wrong(
1732
-                __CLASS__ . '::' . __FUNCTION__,
1732
+                __CLASS__.'::'.__FUNCTION__,
1733 1733
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1734 1734
                 '4.6.0'
1735 1735
             );
@@ -1881,7 +1881,7 @@  discard block
 block discarded – undo
1881 1881
                 break;
1882 1882
             }
1883 1883
         }
1884
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1884
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1885 1885
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1886 1886
         }
1887 1887
         return $line_item;
@@ -1938,7 +1938,7 @@  discard block
 block discarded – undo
1938 1938
     {
1939 1939
         $paid = $this->paid();
1940 1940
         $price = $this->final_price();
1941
-        switch(true) {
1941
+        switch (true) {
1942 1942
             // overpaid or paid
1943 1943
             case EEH_Money::compare_floats($paid, $price, '>'):
1944 1944
             case EEH_Money::compare_floats($paid, $price):
Please login to merge, or discard this patch.
core/db_classes/EE_Ticket.class.php 1 patch
Spacing   +198 added lines, -198 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\exceptions\UnexpectedEntityException;
2 2
 
3
-if ( !defined( 'EVENT_ESPRESSO_VERSION' ) ) {
4
-	exit( 'No direct script access allowed' );
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 /**
7 7
  * Event Espresso
@@ -77,9 +77,9 @@  discard block
 block discarded – undo
77 77
      * @return EE_Ticket
78 78
      * @throws \EE_Error
79 79
      */
80
-	public static function new_instance( $props_n_values = array(), $timezone = null, $date_formats = array() ) {
81
-		$has_object = parent::_check_for_object( $props_n_values, __CLASS__, $timezone, $date_formats );
82
-		return $has_object ? $has_object : new self( $props_n_values, false, $timezone, $date_formats );
80
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) {
81
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
82
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
83 83
 	}
84 84
 
85 85
 
@@ -91,8 +91,8 @@  discard block
 block discarded – undo
91 91
      * @return EE_Ticket
92 92
      * @throws \EE_Error
93 93
      */
94
-	public static function new_instance_from_db( $props_n_values = array(), $timezone = null ) {
95
-		return new self( $props_n_values, TRUE, $timezone );
94
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null) {
95
+		return new self($props_n_values, TRUE, $timezone);
96 96
 	}
97 97
 
98 98
 
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
      * @throws \EE_Error
103 103
      */
104 104
 	public function parent() {
105
-		return $this->get( 'TKT_parent' );
105
+		return $this->get('TKT_parent');
106 106
 	}
107 107
 
108 108
 
@@ -114,13 +114,13 @@  discard block
 block discarded – undo
114 114
      * @return boolean
115 115
      * @throws \EE_Error
116 116
      */
117
-	public function available( $DTT_ID = 0 ) {
117
+	public function available($DTT_ID = 0) {
118 118
 		// are we checking availability for a particular datetime ?
119
-		if ( $DTT_ID ) {
119
+		if ($DTT_ID) {
120 120
 			// get that datetime object
121
-			$datetime = $this->get_first_related( 'Datetime', array( array( 'DTT_ID' => $DTT_ID ) ) );
121
+			$datetime = $this->get_first_related('Datetime', array(array('DTT_ID' => $DTT_ID)));
122 122
 			// if  ticket sales for this datetime have exceeded the reg limit...
123
-			if ( $datetime instanceof EE_Datetime && $datetime->sold_out() ) {
123
+			if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
124 124
 				return FALSE;
125 125
 			}
126 126
 		}
@@ -138,22 +138,22 @@  discard block
 block discarded – undo
138 138
      * @return mixed status int if the display string isn't requested
139 139
      * @throws \EE_Error
140 140
      */
141
-	public function ticket_status( $display = FALSE, $remaining = null ) {
142
-		$remaining = is_bool( $remaining ) ? $remaining : $this->is_remaining();
143
-		if ( ! $remaining ) {
144
-			return $display ? EEH_Template::pretty_status( EE_Ticket::sold_out, FALSE, 'sentence' ) : EE_Ticket::sold_out;
141
+	public function ticket_status($display = FALSE, $remaining = null) {
142
+		$remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
143
+		if ( ! $remaining) {
144
+			return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, FALSE, 'sentence') : EE_Ticket::sold_out;
145 145
 		}
146
-		if ( $this->get( 'TKT_deleted' ) ) {
147
-			return $display ? EEH_Template::pretty_status( EE_Ticket::archived, FALSE, 'sentence' ) : EE_Ticket::archived;
146
+		if ($this->get('TKT_deleted')) {
147
+			return $display ? EEH_Template::pretty_status(EE_Ticket::archived, FALSE, 'sentence') : EE_Ticket::archived;
148 148
 		}
149
-		if ( $this->is_expired() ) {
150
-			return $display ? EEH_Template::pretty_status( EE_Ticket::expired, FALSE, 'sentence' ) : EE_Ticket::expired;
149
+		if ($this->is_expired()) {
150
+			return $display ? EEH_Template::pretty_status(EE_Ticket::expired, FALSE, 'sentence') : EE_Ticket::expired;
151 151
 		}
152
-		if ( $this->is_pending() ) {
153
-			return $display ? EEH_Template::pretty_status( EE_Ticket::pending, FALSE, 'sentence' ) : EE_Ticket::pending;
152
+		if ($this->is_pending()) {
153
+			return $display ? EEH_Template::pretty_status(EE_Ticket::pending, FALSE, 'sentence') : EE_Ticket::pending;
154 154
 		}
155
-		if ( $this->is_on_sale() ) {
156
-			return $display ? EEH_Template::pretty_status( EE_Ticket::onsale, FALSE, 'sentence' ) : EE_Ticket::onsale;
155
+		if ($this->is_on_sale()) {
156
+			return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, FALSE, 'sentence') : EE_Ticket::onsale;
157 157
 		}
158 158
 		return '';
159 159
 	}
@@ -168,12 +168,12 @@  discard block
 block discarded – undo
168 168
      * @return boolean         true = tickets remaining, false not.
169 169
      * @throws \EE_Error
170 170
      */
171
-	public function is_remaining( $DTT_ID = 0 ) {
172
-		$num_remaining = $this->remaining( $DTT_ID );
173
-		if ( $num_remaining === 0 ) {
171
+	public function is_remaining($DTT_ID = 0) {
172
+		$num_remaining = $this->remaining($DTT_ID);
173
+		if ($num_remaining === 0) {
174 174
 			return FALSE;
175 175
 		}
176
-		if ( $num_remaining > 0 && $num_remaining < $this->min() ) {
176
+		if ($num_remaining > 0 && $num_remaining < $this->min()) {
177 177
 			return FALSE;
178 178
 		}
179 179
 		return TRUE;
@@ -189,8 +189,8 @@  discard block
 block discarded – undo
189 189
      * @return int
190 190
      * @throws \EE_Error
191 191
      */
192
-	public function remaining( $DTT_ID = 0 ) {
193
-		return $this->real_quantity_on_ticket('saleable', $DTT_ID );
192
+	public function remaining($DTT_ID = 0) {
193
+		return $this->real_quantity_on_ticket('saleable', $DTT_ID);
194 194
 	}
195 195
 
196 196
 
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
      * @throws \EE_Error
203 203
      */
204 204
 	public function min() {
205
-		return $this->get( 'TKT_min' );
205
+		return $this->get('TKT_min');
206 206
 	}
207 207
 
208 208
 
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
      * @throws \EE_Error
215 215
      */
216 216
 	public function is_expired() {
217
-		return ( $this->get_raw( 'TKT_end_date' ) < time() );
217
+		return ($this->get_raw('TKT_end_date') < time());
218 218
 	}
219 219
 
220 220
 
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
      * @throws \EE_Error
227 227
      */
228 228
 	public function is_pending() {
229
-		return ( $this->get_raw( 'TKT_start_date' ) > time() );
229
+		return ($this->get_raw('TKT_start_date') > time());
230 230
 	}
231 231
 
232 232
 
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
      * @throws \EE_Error
239 239
      */
240 240
 	public function is_on_sale() {
241
-		return ( $this->get_raw( 'TKT_start_date' ) < time() && $this->get_raw( 'TKT_end_date' ) > time() );
241
+		return ($this->get_raw('TKT_start_date') < time() && $this->get_raw('TKT_end_date') > time());
242 242
 	}
243 243
 
244 244
 
@@ -251,11 +251,11 @@  discard block
 block discarded – undo
251 251
      * @return string
252 252
      * @throws \EE_Error
253 253
      */
254
-	public function date_range( $dt_frmt = '', $conjunction = ' - ' ) {
255
-		$first_date = $this->first_datetime() instanceof EE_Datetime ? $this->first_datetime()->start_date( $dt_frmt ) : '';
256
-		$last_date = $this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->end_date( $dt_frmt ) : '';
254
+	public function date_range($dt_frmt = '', $conjunction = ' - ') {
255
+		$first_date = $this->first_datetime() instanceof EE_Datetime ? $this->first_datetime()->start_date($dt_frmt) : '';
256
+		$last_date = $this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->end_date($dt_frmt) : '';
257 257
 
258
-		return $first_date && $last_date ? $first_date . $conjunction  . $last_date : '';
258
+		return $first_date && $last_date ? $first_date.$conjunction.$last_date : '';
259 259
 	}
260 260
 
261 261
 
@@ -267,8 +267,8 @@  discard block
 block discarded – undo
267 267
      * @throws \EE_Error
268 268
      */
269 269
 	public function first_datetime() {
270
-		$datetimes = $this->datetimes( array( 'limit' => 1 ) );
271
-		return reset( $datetimes );
270
+		$datetimes = $this->datetimes(array('limit' => 1));
271
+		return reset($datetimes);
272 272
 	}
273 273
 
274 274
 
@@ -281,11 +281,11 @@  discard block
 block discarded – undo
281 281
      * @return EE_Datetime[]|EE_Base_Class[]
282 282
      * @throws \EE_Error
283 283
      */
284
-	public function datetimes( $query_params = array() ) {
285
-		if ( ! isset( $query_params[ 'order_by' ] ) ) {
286
-			$query_params[ 'order_by' ][ 'DTT_order' ] = 'ASC';
284
+	public function datetimes($query_params = array()) {
285
+		if ( ! isset($query_params['order_by'])) {
286
+			$query_params['order_by']['DTT_order'] = 'ASC';
287 287
 		}
288
-		return $this->get_many_related( 'Datetime', $query_params );
288
+		return $this->get_many_related('Datetime', $query_params);
289 289
 	}
290 290
 
291 291
 
@@ -297,8 +297,8 @@  discard block
 block discarded – undo
297 297
      * @throws \EE_Error
298 298
      */
299 299
 	public function last_datetime() {
300
-		$datetimes = $this->datetimes( array( 'limit' => 1, 'order_by' => array( 'DTT_EVT_start' => 'DESC' ) ) );
301
-		return end( $datetimes );
300
+		$datetimes = $this->datetimes(array('limit' => 1, 'order_by' => array('DTT_EVT_start' => 'DESC')));
301
+		return end($datetimes);
302 302
 	}
303 303
 
304 304
 
@@ -316,22 +316,22 @@  discard block
 block discarded – undo
316 316
      * @return mixed (array|int)          how many tickets have sold
317 317
      * @throws \EE_Error
318 318
      */
319
-	public function tickets_sold( $what = 'ticket', $dtt_id = NULL ) {
319
+	public function tickets_sold($what = 'ticket', $dtt_id = NULL) {
320 320
 		$total = 0;
321 321
 		$tickets_sold = $this->_all_tickets_sold();
322
-		switch ( $what ) {
322
+		switch ($what) {
323 323
 			case 'ticket' :
324
-				return $tickets_sold[ 'ticket' ];
324
+				return $tickets_sold['ticket'];
325 325
 				break;
326 326
 			case 'datetime' :
327
-				if ( empty( $tickets_sold[ 'datetime' ] ) ) {
327
+				if (empty($tickets_sold['datetime'])) {
328 328
 					return $total;
329 329
 				}
330
-				if ( ! empty( $dtt_id ) && ! isset( $tickets_sold[ 'datetime' ][ $dtt_id ] ) ) {
331
-					EE_Error::add_error( __( '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?', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
330
+				if ( ! empty($dtt_id) && ! isset($tickets_sold['datetime'][$dtt_id])) {
331
+					EE_Error::add_error(__('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?', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
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;
@@ -347,15 +347,15 @@  discard block
 block discarded – undo
347 347
      * @throws \EE_Error
348 348
      */
349 349
 	protected function _all_tickets_sold() {
350
-		$datetimes = $this->get_many_related( 'Datetime' );
350
+		$datetimes = $this->get_many_related('Datetime');
351 351
 		$tickets_sold = array();
352
-		if ( ! empty( $datetimes ) ) {
353
-			foreach ( $datetimes as $datetime ) {
354
-				$tickets_sold[ 'datetime' ][ $datetime->ID() ] = $datetime->get( 'DTT_sold' );
352
+		if ( ! empty($datetimes)) {
353
+			foreach ($datetimes as $datetime) {
354
+				$tickets_sold['datetime'][$datetime->ID()] = $datetime->get('DTT_sold');
355 355
 			}
356 356
 		}
357 357
 		//Tickets sold
358
-		$tickets_sold[ 'ticket' ] = $this->sold();
358
+		$tickets_sold['ticket'] = $this->sold();
359 359
 		return $tickets_sold;
360 360
 	}
361 361
 
@@ -368,11 +368,11 @@  discard block
 block discarded – undo
368 368
      * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
369 369
      * @throws \EE_Error
370 370
      */
371
-	public function base_price( $return_array = FALSE ) {
372
-		$_where = array( 'Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price );
371
+	public function base_price($return_array = FALSE) {
372
+		$_where = array('Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price);
373 373
 		return $return_array
374
-            ? $this->get_many_related( 'Price', array( $_where ) )
375
-            : $this->get_first_related( 'Price', array( $_where ) );
374
+            ? $this->get_many_related('Price', array($_where))
375
+            : $this->get_first_related('Price', array($_where));
376 376
 	}
377 377
 
378 378
 
@@ -385,8 +385,8 @@  discard block
 block discarded – undo
385 385
      * @throws \EE_Error
386 386
      */
387 387
 	public function price_modifiers() {
388
-		$query_params = array( 0 => array( 'Price_Type.PBT_ID' => array( 'NOT IN', array( EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax ) ) ) );
389
-		return $this->prices( $query_params );
388
+		$query_params = array(0 => array('Price_Type.PBT_ID' => array('NOT IN', array(EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax))));
389
+		return $this->prices($query_params);
390 390
 	}
391 391
 
392 392
 
@@ -398,8 +398,8 @@  discard block
 block discarded – undo
398 398
      * @return EE_Price[]|EE_Base_Class[]
399 399
      * @throws \EE_Error
400 400
      */
401
-	public function prices( $query_params = array() ) {
402
-		return $this->get_many_related( 'Price', $query_params );
401
+	public function prices($query_params = array()) {
402
+		return $this->get_many_related('Price', $query_params);
403 403
 	}
404 404
 
405 405
 
@@ -411,8 +411,8 @@  discard block
 block discarded – undo
411 411
      * @return EE_Datetime_Ticket|EE_Base_Class[]
412 412
      * @throws \EE_Error
413 413
      */
414
-	public function datetime_tickets( $query_params = array() ) {
415
-		return $this->get_many_related( 'Datetime_Ticket', $query_params );
414
+	public function datetime_tickets($query_params = array()) {
415
+		return $this->get_many_related('Datetime_Ticket', $query_params);
416 416
 	}
417 417
 
418 418
 
@@ -425,8 +425,8 @@  discard block
 block discarded – undo
425 425
      * @return EE_Datetime[]
426 426
      * @throws \EE_Error
427 427
      */
428
-	public function datetimes_ordered( $show_expired = TRUE, $show_deleted = FALSE ) {
429
-		return EEM_Datetime::instance( $this->_timezone )->get_datetimes_for_ticket_ordered_by_DTT_order( $this->ID(), $show_expired, $show_deleted );
428
+	public function datetimes_ordered($show_expired = TRUE, $show_deleted = FALSE) {
429
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order($this->ID(), $show_expired, $show_deleted);
430 430
 	}
431 431
 
432 432
 
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
      * @throws \EE_Error
439 439
      */
440 440
 	public function ID() {
441
-		return $this->get( 'TKT_ID' );
441
+		return $this->get('TKT_ID');
442 442
 	}
443 443
 
444 444
 
@@ -463,7 +463,7 @@  discard block
 block discarded – undo
463 463
      * @throws \EE_Error
464 464
      */
465 465
 	public function template() {
466
-		return $this->get_first_related( 'Ticket_Template' );
466
+		return $this->get_first_related('Ticket_Template');
467 467
 	}
468 468
 
469 469
 
@@ -485,7 +485,7 @@  discard block
 block discarded – undo
485 485
      * @throws \EE_Error
486 486
      */
487 487
 	public function ticket_price() {
488
-		return $this->get( 'TKT_price' );
488
+		return $this->get('TKT_price');
489 489
 	}
490 490
 
491 491
 
@@ -495,7 +495,7 @@  discard block
 block discarded – undo
495 495
      * @throws \EE_Error
496 496
      */
497 497
 	public function pretty_price() {
498
-		return $this->get_pretty( 'TKT_price' );
498
+		return $this->get_pretty('TKT_price');
499 499
 	}
500 500
 
501 501
 
@@ -517,8 +517,8 @@  discard block
 block discarded – undo
517 517
      * @return float
518 518
      * @throws \EE_Error
519 519
      */
520
-	public function get_ticket_total_with_taxes( $no_cache = FALSE ) {
521
-		if ($this->_ticket_total_with_taxes === null || $no_cache ) {
520
+	public function get_ticket_total_with_taxes($no_cache = FALSE) {
521
+		if ($this->_ticket_total_with_taxes === null || $no_cache) {
522 522
 			$this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
523 523
 		}
524 524
 		return (float) $this->_ticket_total_with_taxes;
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
 
528 528
 
529 529
 	public function ensure_TKT_Price_correct() {
530
-		$this->set( 'TKT_price', EE_Taxes::get_subtotal_for_admin( $this ) );
530
+		$this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
531 531
 		$this->save();
532 532
 	}
533 533
 
@@ -538,7 +538,7 @@  discard block
 block discarded – undo
538 538
      * @throws \EE_Error
539 539
      */
540 540
 	public function get_ticket_subtotal() {
541
-		return EE_Taxes::get_subtotal_for_admin( $this );
541
+		return EE_Taxes::get_subtotal_for_admin($this);
542 542
 	}
543 543
 
544 544
 
@@ -550,7 +550,7 @@  discard block
 block discarded – undo
550 550
      * @throws \EE_Error
551 551
      */
552 552
 	public function get_ticket_taxes_total_for_admin() {
553
-		return EE_Taxes::get_total_taxes_for_admin( $this );
553
+		return EE_Taxes::get_total_taxes_for_admin($this);
554 554
 	}
555 555
 
556 556
 
@@ -561,8 +561,8 @@  discard block
 block discarded – undo
561 561
      * @param string $name
562 562
      * @throws \EE_Error
563 563
      */
564
-	public function set_name( $name ) {
565
-		$this->set( 'TKT_name', $name );
564
+	public function set_name($name) {
565
+		$this->set('TKT_name', $name);
566 566
 	}
567 567
 
568 568
 
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
      * @throws \EE_Error
575 575
      */
576 576
 	public function description() {
577
-		return $this->get( 'TKT_description' );
577
+		return $this->get('TKT_description');
578 578
 	}
579 579
 
580 580
 
@@ -585,8 +585,8 @@  discard block
 block discarded – undo
585 585
      * @param string $description
586 586
      * @throws \EE_Error
587 587
      */
588
-	public function set_description( $description ) {
589
-		$this->set( 'TKT_description', $description );
588
+	public function set_description($description) {
589
+		$this->set('TKT_description', $description);
590 590
 	}
591 591
 
592 592
 
@@ -599,8 +599,8 @@  discard block
 block discarded – undo
599 599
      * @return string
600 600
      * @throws \EE_Error
601 601
      */
602
-	public function start_date( $dt_frmt = '', $tm_frmt = '' ) {
603
-		return $this->_get_datetime( 'TKT_start_date', $dt_frmt, $tm_frmt );
602
+	public function start_date($dt_frmt = '', $tm_frmt = '') {
603
+		return $this->_get_datetime('TKT_start_date', $dt_frmt, $tm_frmt);
604 604
 	}
605 605
 
606 606
 
@@ -612,8 +612,8 @@  discard block
 block discarded – undo
612 612
      * @return void
613 613
      * @throws \EE_Error
614 614
      */
615
-	public function set_start_date( $start_date ) {
616
-		$this->_set_date_time( 'B', $start_date, 'TKT_start_date' );
615
+	public function set_start_date($start_date) {
616
+		$this->_set_date_time('B', $start_date, 'TKT_start_date');
617 617
 	}
618 618
 
619 619
 
@@ -626,8 +626,8 @@  discard block
 block discarded – undo
626 626
      * @return string
627 627
      * @throws \EE_Error
628 628
      */
629
-	public function end_date( $dt_frmt = '', $tm_frmt = '' ) {
630
-		return $this->_get_datetime( 'TKT_end_date', $dt_frmt, $tm_frmt );
629
+	public function end_date($dt_frmt = '', $tm_frmt = '') {
630
+		return $this->_get_datetime('TKT_end_date', $dt_frmt, $tm_frmt);
631 631
 	}
632 632
 
633 633
 
@@ -639,8 +639,8 @@  discard block
 block discarded – undo
639 639
      * @return void
640 640
      * @throws \EE_Error
641 641
      */
642
-	public function set_end_date( $end_date ) {
643
-		$this->_set_date_time( 'B', $end_date, 'TKT_end_date' );
642
+	public function set_end_date($end_date) {
643
+		$this->_set_date_time('B', $end_date, 'TKT_end_date');
644 644
 	}
645 645
 
646 646
 
@@ -652,8 +652,8 @@  discard block
 block discarded – undo
652 652
      * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
653 653
      * @throws \EE_Error
654 654
      */
655
-	public function set_end_time( $time ) {
656
-		$this->_set_time_for( $time, 'TKT_end_date' );
655
+	public function set_end_time($time) {
656
+		$this->_set_time_for($time, 'TKT_end_date');
657 657
 	}
658 658
 
659 659
 
@@ -665,8 +665,8 @@  discard block
 block discarded – undo
665 665
      * @return void
666 666
      * @throws \EE_Error
667 667
      */
668
-	public function set_min( $min ) {
669
-		$this->set( 'TKT_min', $min );
668
+	public function set_min($min) {
669
+		$this->set('TKT_min', $min);
670 670
 	}
671 671
 
672 672
 
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
      * @throws \EE_Error
679 679
      */
680 680
 	public function max() {
681
-		return $this->get( 'TKT_max' );
681
+		return $this->get('TKT_max');
682 682
 	}
683 683
 
684 684
 
@@ -690,8 +690,8 @@  discard block
 block discarded – undo
690 690
      * @return void
691 691
      * @throws \EE_Error
692 692
      */
693
-	public function set_max( $max ) {
694
-		$this->set( 'TKT_max', $max );
693
+	public function set_max($max) {
694
+		$this->set('TKT_max', $max);
695 695
 	}
696 696
 
697 697
 
@@ -703,8 +703,8 @@  discard block
 block discarded – undo
703 703
      * @return void
704 704
      * @throws \EE_Error
705 705
      */
706
-	public function set_price( $price ) {
707
-		$this->set( 'TKT_price', $price );
706
+	public function set_price($price) {
707
+		$this->set('TKT_price', $price);
708 708
 	}
709 709
 
710 710
 
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
      * @throws \EE_Error
717 717
      */
718 718
 	public function sold() {
719
-		return $this->get_raw( 'TKT_sold' );
719
+		return $this->get_raw('TKT_sold');
720 720
 	}
721 721
 
722 722
 
@@ -728,10 +728,10 @@  discard block
 block discarded – undo
728 728
      * @return void
729 729
      * @throws \EE_Error
730 730
      */
731
-	public function set_sold( $sold ) {
731
+	public function set_sold($sold) {
732 732
 		// sold can not go below zero
733
-		$sold = max( 0, $sold );
734
-		$this->set( 'TKT_sold', $sold );
733
+		$sold = max(0, $sold);
734
+		$this->set('TKT_sold', $sold);
735 735
 	}
736 736
 
737 737
 
@@ -743,13 +743,13 @@  discard block
 block discarded – undo
743 743
      * @return void
744 744
      * @throws \EE_Error
745 745
      */
746
-	public function increase_sold( $qty = 1 ) {
746
+	public function increase_sold($qty = 1) {
747 747
 		$sold = $this->sold() + $qty;
748 748
 		// remove ticket reservation, but don't adjust datetime reservations,  because that will happen
749 749
 		// via \EE_Datetime::increase_sold() when \EE_Ticket::_increase_sold_for_datetimes() is called
750
-		$this->decrease_reserved( $qty, false, "TKT: {$this->ID()} (ln:" . __LINE__ . ')');
751
-		$this->_increase_sold_for_datetimes( $qty );
752
-		$this->set_sold( $sold );
750
+		$this->decrease_reserved($qty, false, "TKT: {$this->ID()} (ln:".__LINE__.')');
751
+		$this->_increase_sold_for_datetimes($qty);
752
+		$this->set_sold($sold);
753 753
 		do_action(
754 754
 		    'AHEE__EE_Ticket__increase_sold',
755 755
             $this,
@@ -767,12 +767,12 @@  discard block
 block discarded – undo
767 767
      * @return void
768 768
      * @throws \EE_Error
769 769
      */
770
-	protected function _increase_sold_for_datetimes( $qty = 1 ) {
770
+	protected function _increase_sold_for_datetimes($qty = 1) {
771 771
 		$datetimes = $this->datetimes();
772
-		if ( is_array( $datetimes ) ) {
773
-			foreach ( $datetimes as $datetime ) {
774
-				if ( $datetime instanceof EE_Datetime ) {
775
-					$datetime->increase_sold( $qty );
772
+		if (is_array($datetimes)) {
773
+			foreach ($datetimes as $datetime) {
774
+				if ($datetime instanceof EE_Datetime) {
775
+					$datetime->increase_sold($qty);
776 776
 					$datetime->save();
777 777
 				}
778 778
 			}
@@ -788,10 +788,10 @@  discard block
 block discarded – undo
788 788
      * @return void
789 789
      * @throws \EE_Error
790 790
      */
791
-	public function decrease_sold( $qty = 1 ) {
791
+	public function decrease_sold($qty = 1) {
792 792
 		$sold = $this->sold() - $qty;
793
-		$this->_decrease_sold_for_datetimes( $qty );
794
-		$this->set_sold( $sold );
793
+		$this->_decrease_sold_for_datetimes($qty);
794
+		$this->set_sold($sold);
795 795
         do_action(
796 796
             'AHEE__EE_Ticket__decrease_sold',
797 797
             $this,
@@ -809,12 +809,12 @@  discard block
 block discarded – undo
809 809
      * @return void
810 810
      * @throws \EE_Error
811 811
      */
812
-	protected function _decrease_sold_for_datetimes( $qty = 1 ) {
812
+	protected function _decrease_sold_for_datetimes($qty = 1) {
813 813
 		$datetimes = $this->datetimes();
814
-		if ( is_array( $datetimes ) ) {
815
-			foreach ( $datetimes as $datetime ) {
816
-				if ( $datetime instanceof EE_Datetime ) {
817
-					$datetime->decrease_sold( $qty );
814
+		if (is_array($datetimes)) {
815
+			foreach ($datetimes as $datetime) {
816
+				if ($datetime instanceof EE_Datetime) {
817
+					$datetime->decrease_sold($qty);
818 818
 					$datetime->save();
819 819
 				}
820 820
 			}
@@ -830,7 +830,7 @@  discard block
 block discarded – undo
830 830
      * @throws \EE_Error
831 831
      */
832 832
 	public function reserved() {
833
-		return $this->get_raw( 'TKT_reserved' );
833
+		return $this->get_raw('TKT_reserved');
834 834
 	}
835 835
 
836 836
 
@@ -842,10 +842,10 @@  discard block
 block discarded – undo
842 842
      * @return void
843 843
      * @throws \EE_Error
844 844
      */
845
-	public function set_reserved( $reserved ) {
845
+	public function set_reserved($reserved) {
846 846
 		// reserved can not go below zero
847
-		$reserved = max( 0, (int) $reserved );
848
-		$this->set( 'TKT_reserved', $reserved );
847
+		$reserved = max(0, (int) $reserved);
848
+		$this->set('TKT_reserved', $reserved);
849 849
 	}
850 850
 
851 851
 
@@ -861,8 +861,8 @@  discard block
 block discarded – undo
861 861
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
862 862
      * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
863 863
      */
864
-	public function increase_reserved( $qty = 1, $source = 'unknown' ) {
865
-		$qty = absint( $qty );
864
+	public function increase_reserved($qty = 1, $source = 'unknown') {
865
+		$qty = absint($qty);
866 866
 		$reserved = $this->reserved() + $qty;
867 867
         if (
868 868
             $reserved
@@ -891,12 +891,12 @@  discard block
 block discarded – undo
891 891
      * @return void
892 892
      * @throws \EE_Error
893 893
      */
894
-	protected function _increase_reserved_for_datetimes( $qty = 1 ) {
894
+	protected function _increase_reserved_for_datetimes($qty = 1) {
895 895
 		$datetimes = $this->datetimes();
896
-		if ( is_array( $datetimes ) ) {
897
-			foreach ( $datetimes as $datetime ) {
898
-				if ( $datetime instanceof EE_Datetime ) {
899
-					$datetime->increase_reserved( $qty );
896
+		if (is_array($datetimes)) {
897
+			foreach ($datetimes as $datetime) {
898
+				if ($datetime instanceof EE_Datetime) {
899
+					$datetime->increase_reserved($qty);
900 900
 					$datetime->save();
901 901
 				}
902 902
 			}
@@ -917,8 +917,8 @@  discard block
 block discarded – undo
917 917
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918 918
      * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919 919
      */
920
-	public function decrease_reserved( $qty = 1, $adjust_datetimes = true, $source = 'unknown' ) {
921
-		$reserved = $this->reserved() - absint( $qty );
920
+	public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown') {
921
+		$reserved = $this->reserved() - absint($qty);
922 922
         if (
923 923
             $this->add_extra_meta(
924 924
                 EE_Ticket::META_KEY_TICKET_RESERVATIONS,
@@ -947,12 +947,12 @@  discard block
 block discarded – undo
947 947
      * @return void
948 948
      * @throws \EE_Error
949 949
      */
950
-	protected function _decrease_reserved_for_datetimes( $qty = 1 ) {
950
+	protected function _decrease_reserved_for_datetimes($qty = 1) {
951 951
 		$datetimes = $this->datetimes();
952
-		if ( is_array( $datetimes ) ) {
953
-			foreach ( $datetimes as $datetime ) {
954
-				if ( $datetime instanceof EE_Datetime ) {
955
-					$datetime->decrease_reserved( $qty );
952
+		if (is_array($datetimes)) {
953
+			foreach ($datetimes as $datetime) {
954
+				if ($datetime instanceof EE_Datetime) {
955
+					$datetime->decrease_reserved($qty);
956 956
 					$datetime->save();
957 957
 				}
958 958
 			}
@@ -973,14 +973,14 @@  discard block
 block discarded – undo
973 973
      * @return int
974 974
      * @throws \EE_Error
975 975
      */
976
-	public function qty( $context = '' ) {
977
-		switch ( $context ) {
976
+	public function qty($context = '') {
977
+		switch ($context) {
978 978
 			case 'reg_limit' :
979 979
 				return $this->real_quantity_on_ticket();
980 980
 			case 'saleable' :
981
-				return $this->real_quantity_on_ticket( 'saleable' );
981
+				return $this->real_quantity_on_ticket('saleable');
982 982
 			default:
983
-				return $this->get_raw( 'TKT_qty' );
983
+				return $this->get_raw('TKT_qty');
984 984
 		}
985 985
 	}
986 986
 
@@ -999,15 +999,15 @@  discard block
 block discarded – undo
999 999
      * @return int
1000 1000
      * @throws \EE_Error
1001 1001
      */
1002
-	public function real_quantity_on_ticket( $context = 'reg_limit', $DTT_ID = 0 ) {
1003
-		$raw = $this->get_raw( 'TKT_qty' );
1002
+	public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0) {
1003
+		$raw = $this->get_raw('TKT_qty');
1004 1004
 		// return immediately if it's zero
1005
-		if ( $raw === 0 ) {
1005
+		if ($raw === 0) {
1006 1006
 			return $raw;
1007 1007
 		}
1008 1008
 		//echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1009 1009
 		// ensure qty doesn't exceed raw value for THIS ticket
1010
-		$qty = min( EE_INF, $raw );
1010
+		$qty = min(EE_INF, $raw);
1011 1011
 		//echo "\n . qty: " . $qty . '<br />';
1012 1012
 		// calculate this ticket's total sales and reservations
1013 1013
 		$sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
@@ -1016,23 +1016,23 @@  discard block
 block discarded – undo
1016 1016
 		//echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1017 1017
 		// first we need to calculate the maximum number of tickets available for the datetime
1018 1018
 		// do we want data for one datetime or all of them ?
1019
-		$query_params = $DTT_ID ? array( array( 'DTT_ID' => $DTT_ID ) ) : array();
1020
-		$datetimes = $this->datetimes( $query_params );
1021
-		if ( is_array( $datetimes ) && ! empty( $datetimes ) ) {
1022
-			foreach ( $datetimes as $datetime ) {
1023
-				if ( $datetime instanceof EE_Datetime ) {
1019
+		$query_params = $DTT_ID ? array(array('DTT_ID' => $DTT_ID)) : array();
1020
+		$datetimes = $this->datetimes($query_params);
1021
+		if (is_array($datetimes) && ! empty($datetimes)) {
1022
+			foreach ($datetimes as $datetime) {
1023
+				if ($datetime instanceof EE_Datetime) {
1024 1024
 					$datetime->refresh_from_db();
1025 1025
 					//echo "\n . . datetime name: " . $datetime->name() . '<br />';
1026 1026
 					//echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1027 1027
 					// initialize with no restrictions for each datetime
1028 1028
 					// but adjust datetime qty based on datetime reg limit
1029
-					$datetime_qty = min( EE_INF, $datetime->reg_limit() );
1029
+					$datetime_qty = min(EE_INF, $datetime->reg_limit());
1030 1030
 					//echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1031 1031
 					//echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1032 1032
 					// if we want the actual saleable amount, then we need to consider OTHER ticket sales
1033 1033
 					// and reservations for this datetime, that do NOT include sales and reservations
1034 1034
 					// for this ticket (so we add $this->sold() and $this->reserved() back in)
1035
-					if ( $context === 'saleable' ) {
1035
+					if ($context === 'saleable') {
1036 1036
 						$datetime_qty = max(
1037 1037
 							$datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1038 1038
 							0
@@ -1044,16 +1044,16 @@  discard block
 block discarded – undo
1044 1044
 						$datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1045 1045
 						//echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1046 1046
 					}
1047
-					$qty = min( $datetime_qty, $qty );
1047
+					$qty = min($datetime_qty, $qty);
1048 1048
 					//echo "\n . . qty: " . $qty . '<br />';
1049 1049
 				}
1050 1050
 			}
1051 1051
 		}
1052 1052
 		// NOW that we know the  maximum number of tickets available for the datetime
1053 1053
 		// we can finally factor in the details for this specific ticket
1054
-		if ( $qty > 0 && $context === 'saleable' ) {
1054
+		if ($qty > 0 && $context === 'saleable') {
1055 1055
 			// and subtract the sales for THIS ticket
1056
-			$qty = max( $qty - $sold_and_reserved_for_this_ticket, 0 );
1056
+			$qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1057 1057
 			//echo "\n . qty: " . $qty . '<br />';
1058 1058
 		}
1059 1059
 		//echo "\nFINAL QTY: " . $qty . "<br /><br />";
@@ -1069,14 +1069,14 @@  discard block
 block discarded – undo
1069 1069
 	 * @return void
1070 1070
 	 * @throws \EE_Error
1071 1071
 	 */
1072
-	public function set_qty( $qty ) {
1072
+	public function set_qty($qty) {
1073 1073
 		$datetimes = $this->datetimes();
1074
-		foreach ( $datetimes as $datetime ) {
1075
-			if ( $datetime instanceof EE_Datetime ) {
1076
-				$qty = min( $qty, $datetime->reg_limit() );
1074
+		foreach ($datetimes as $datetime) {
1075
+			if ($datetime instanceof EE_Datetime) {
1076
+				$qty = min($qty, $datetime->reg_limit());
1077 1077
 			}
1078 1078
 		}
1079
-		$this->set( 'TKT_qty', $qty );
1079
+		$this->set('TKT_qty', $qty);
1080 1080
 	}
1081 1081
 
1082 1082
 
@@ -1088,7 +1088,7 @@  discard block
 block discarded – undo
1088 1088
      * @throws \EE_Error
1089 1089
      */
1090 1090
 	public function uses() {
1091
-		return $this->get( 'TKT_uses' );
1091
+		return $this->get('TKT_uses');
1092 1092
 	}
1093 1093
 
1094 1094
 
@@ -1100,8 +1100,8 @@  discard block
 block discarded – undo
1100 1100
      * @return void
1101 1101
      * @throws \EE_Error
1102 1102
      */
1103
-	public function set_uses( $uses ) {
1104
-		$this->set( 'TKT_uses', $uses );
1103
+	public function set_uses($uses) {
1104
+		$this->set('TKT_uses', $uses);
1105 1105
 	}
1106 1106
 
1107 1107
 
@@ -1113,7 +1113,7 @@  discard block
 block discarded – undo
1113 1113
      * @throws \EE_Error
1114 1114
      */
1115 1115
 	public function required() {
1116
-		return $this->get( 'TKT_required' );
1116
+		return $this->get('TKT_required');
1117 1117
 	}
1118 1118
 
1119 1119
 
@@ -1125,8 +1125,8 @@  discard block
 block discarded – undo
1125 1125
      * @return void
1126 1126
      * @throws \EE_Error
1127 1127
      */
1128
-	public function set_required( $required ) {
1129
-		$this->set( 'TKT_required', $required );
1128
+	public function set_required($required) {
1129
+		$this->set('TKT_required', $required);
1130 1130
 	}
1131 1131
 
1132 1132
 
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
      * @throws \EE_Error
1139 1139
      */
1140 1140
 	public function taxable() {
1141
-		return $this->get( 'TKT_taxable' );
1141
+		return $this->get('TKT_taxable');
1142 1142
 	}
1143 1143
 
1144 1144
 
@@ -1150,8 +1150,8 @@  discard block
 block discarded – undo
1150 1150
      * @return void
1151 1151
      * @throws \EE_Error
1152 1152
      */
1153
-	public function set_taxable( $taxable ) {
1154
-		$this->set( 'TKT_taxable', $taxable );
1153
+	public function set_taxable($taxable) {
1154
+		$this->set('TKT_taxable', $taxable);
1155 1155
 	}
1156 1156
 
1157 1157
 
@@ -1163,7 +1163,7 @@  discard block
 block discarded – undo
1163 1163
      * @throws \EE_Error
1164 1164
      */
1165 1165
 	public function is_default() {
1166
-		return $this->get( 'TKT_is_default' );
1166
+		return $this->get('TKT_is_default');
1167 1167
 	}
1168 1168
 
1169 1169
 
@@ -1175,8 +1175,8 @@  discard block
 block discarded – undo
1175 1175
      * @return void
1176 1176
      * @throws \EE_Error
1177 1177
      */
1178
-	public function set_is_default( $is_default ) {
1179
-		$this->set( 'TKT_is_default', $is_default );
1178
+	public function set_is_default($is_default) {
1179
+		$this->set('TKT_is_default', $is_default);
1180 1180
 	}
1181 1181
 
1182 1182
 
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
      * @throws \EE_Error
1189 1189
      */
1190 1190
 	public function order() {
1191
-		return $this->get( 'TKT_order' );
1191
+		return $this->get('TKT_order');
1192 1192
 	}
1193 1193
 
1194 1194
 
@@ -1200,8 +1200,8 @@  discard block
 block discarded – undo
1200 1200
      * @return void
1201 1201
      * @throws \EE_Error
1202 1202
      */
1203
-	public function set_order( $order ) {
1204
-		$this->set( 'TKT_order', $order );
1203
+	public function set_order($order) {
1204
+		$this->set('TKT_order', $order);
1205 1205
 	}
1206 1206
 
1207 1207
 
@@ -1213,7 +1213,7 @@  discard block
 block discarded – undo
1213 1213
      * @throws \EE_Error
1214 1214
      */
1215 1215
 	public function row() {
1216
-		return $this->get( 'TKT_row' );
1216
+		return $this->get('TKT_row');
1217 1217
 	}
1218 1218
 
1219 1219
 
@@ -1225,8 +1225,8 @@  discard block
 block discarded – undo
1225 1225
      * @return void
1226 1226
      * @throws \EE_Error
1227 1227
      */
1228
-	public function set_row( $row ) {
1229
-		$this->set( 'TKT_row', $row );
1228
+	public function set_row($row) {
1229
+		$this->set('TKT_row', $row);
1230 1230
 	}
1231 1231
 
1232 1232
 
@@ -1238,7 +1238,7 @@  discard block
 block discarded – undo
1238 1238
      * @throws \EE_Error
1239 1239
      */
1240 1240
 	public function deleted() {
1241
-		return $this->get( 'TKT_deleted' );
1241
+		return $this->get('TKT_deleted');
1242 1242
 	}
1243 1243
 
1244 1244
 
@@ -1250,8 +1250,8 @@  discard block
 block discarded – undo
1250 1250
      * @return void
1251 1251
      * @throws \EE_Error
1252 1252
      */
1253
-	public function set_deleted( $deleted ) {
1254
-		$this->set( 'TKT_deleted', $deleted );
1253
+	public function set_deleted($deleted) {
1254
+		$this->set('TKT_deleted', $deleted);
1255 1255
 	}
1256 1256
 
1257 1257
 
@@ -1263,7 +1263,7 @@  discard block
 block discarded – undo
1263 1263
      * @throws \EE_Error
1264 1264
      */
1265 1265
 	public function parent_ID() {
1266
-		return $this->get( 'TKT_parent' );
1266
+		return $this->get('TKT_parent');
1267 1267
 	}
1268 1268
 
1269 1269
 
@@ -1275,8 +1275,8 @@  discard block
 block discarded – undo
1275 1275
      * @return void
1276 1276
      * @throws \EE_Error
1277 1277
      */
1278
-	public function set_parent_ID( $parent ) {
1279
-		$this->set( 'TKT_parent', $parent );
1278
+	public function set_parent_ID($parent) {
1279
+		$this->set('TKT_parent', $parent);
1280 1280
 	}
1281 1281
 
1282 1282
 
@@ -1289,10 +1289,10 @@  discard block
 block discarded – undo
1289 1289
      */
1290 1290
 	public function name_and_info() {
1291 1291
 		$times = array();
1292
-		foreach ( $this->datetimes() as $datetime ) {
1292
+		foreach ($this->datetimes() as $datetime) {
1293 1293
 			$times[] = $datetime->start_date_and_time();
1294 1294
 		}
1295
-		return $this->name() . ' @ ' . implode( ', ', $times ) . ' for ' . $this->pretty_price();
1295
+		return $this->name().' @ '.implode(', ', $times).' for '.$this->pretty_price();
1296 1296
 	}
1297 1297
 
1298 1298
 
@@ -1304,7 +1304,7 @@  discard block
 block discarded – undo
1304 1304
      * @throws \EE_Error
1305 1305
      */
1306 1306
 	public function name() {
1307
-		return $this->get( 'TKT_name' );
1307
+		return $this->get('TKT_name');
1308 1308
 	}
1309 1309
 
1310 1310
 
@@ -1316,7 +1316,7 @@  discard block
 block discarded – undo
1316 1316
      * @throws \EE_Error
1317 1317
      */
1318 1318
 	public function price() {
1319
-		return $this->get( 'TKT_price' );
1319
+		return $this->get('TKT_price');
1320 1320
 	}
1321 1321
 
1322 1322
 
@@ -1328,8 +1328,8 @@  discard block
 block discarded – undo
1328 1328
      * @return EE_Registration[]|EE_Base_Class[]
1329 1329
      * @throws \EE_Error
1330 1330
      */
1331
-	public function registrations( $query_params = array() ) {
1332
-		return $this->get_many_related( 'Registration', $query_params );
1331
+	public function registrations($query_params = array()) {
1332
+		return $this->get_many_related('Registration', $query_params);
1333 1333
 	}
1334 1334
 
1335 1335
 
@@ -1368,7 +1368,7 @@  discard block
 block discarded – undo
1368 1368
 	 * @param array $query_params like EEM_Base::get_all's
1369 1369
 	 * @return int
1370 1370
 	 */
1371
-	public function count_registrations( $query_params = array() ) {
1371
+	public function count_registrations($query_params = array()) {
1372 1372
 		return $this->count_related('Registration', $query_params);
1373 1373
 	}
1374 1374
 
@@ -1396,23 +1396,23 @@  discard block
 block discarded – undo
1396 1396
 	public function get_related_event() {
1397 1397
 		//get one datetime to use for getting the event
1398 1398
 		$datetime = $this->first_datetime();
1399
-		if ( ! $datetime instanceof \EE_Datetime ) {
1399
+		if ( ! $datetime instanceof \EE_Datetime) {
1400 1400
 			throw new UnexpectedEntityException(
1401 1401
 				$datetime,
1402 1402
                 'EE_Datetime',
1403 1403
 				sprintf(
1404
-					__( 'The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1404
+					__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1405 1405
 					$this->name()
1406 1406
 				)
1407 1407
 			);
1408 1408
 		}
1409 1409
 		$event = $datetime->event();
1410
-		if ( ! $event instanceof \EE_Event ) {
1410
+		if ( ! $event instanceof \EE_Event) {
1411 1411
 			throw new UnexpectedEntityException(
1412 1412
 				$event,
1413 1413
                 'EE_Event',
1414 1414
 				sprintf(
1415
-					__( 'The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1415
+					__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1416 1416
 					$this->name()
1417 1417
 				)
1418 1418
 			);
Please login to merge, or discard this patch.