Completed
Pull Request — master (#331)
by Darren
20:37
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
@@ -20,1048 +20,1048 @@
 block discarded – undo
20 20
 class EED_Ticket_Sales_Monitor extends EED_Module
21 21
 {
22 22
 
23
-    const debug = false;
24
-
25
-    private static $nl = '';
26
-
27
-    /**
28
-     * an array of raw ticket data from EED_Ticket_Selector
29
-     *
30
-     * @var array $ticket_selections
31
-     */
32
-    protected $ticket_selections = array();
33
-
34
-    /**
35
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
36
-     * according to how they are displayed in the actual Ticket_Selector
37
-     * this tracks the current row being processed
38
-     *
39
-     * @var int $current_row
40
-     */
41
-    protected $current_row = 0;
42
-
43
-    /**
44
-     * an array for tracking names of tickets that have sold out
45
-     *
46
-     * @var array $sold_out_tickets
47
-     */
48
-    protected $sold_out_tickets = array();
49
-
50
-    /**
51
-     * an array for tracking names of tickets that have had their quantities reduced
52
-     *
53
-     * @var array $decremented_tickets
54
-     */
55
-    protected $decremented_tickets = array();
56
-
57
-
58
-    /**
59
-     * set_hooks - for hooking into EE Core, other modules, etc
60
-     *
61
-     * @return    void
62
-     */
63
-    public static function set_hooks()
64
-    {
65
-        self::$nl = defined('EE_TESTS_DIR') ? "\n" : '<br />';
66
-        // release tickets for expired carts
67
-        add_action(
68
-            'EED_Ticket_Selector__process_ticket_selections__before',
69
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
70
-            1
71
-        );
72
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
73
-        add_filter(
74
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
75
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
76
-            20,
77
-            3
78
-        );
79
-        // add notices for sold out tickets
80
-        add_action(
81
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
82
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
83
-            10
84
-        );
85
-
86
-        // handle tickets deleted from cart
87
-        add_action(
88
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
89
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
90
-            10,
91
-            2
92
-        );
93
-        // handle emptied carts
94
-        add_action(
95
-            'AHEE__EE_Session__reset_cart__before_reset',
96
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
97
-            10,
98
-            1
99
-        );
100
-        add_action(
101
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
102
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
103
-            10,
104
-            1
105
-        );
106
-        // handle cancelled registrations
107
-        add_action(
108
-            'AHEE__EE_Session__reset_checkout__before_reset',
109
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
110
-            10,
111
-            1
112
-        );
113
-        // cron tasks
114
-        add_action(
115
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
116
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
117
-            10,
118
-            1
119
-        );
120
-        add_action(
121
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_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__failed_transaction',
128
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
129
-            10,
130
-            1
131
-        );
132
-    }
133
-
134
-
135
-    /**
136
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
137
-     *
138
-     * @return void
139
-     */
140
-    public static function set_hooks_admin()
141
-    {
142
-        EED_Ticket_Sales_Monitor::set_hooks();
143
-    }
144
-
145
-
146
-    /**
147
-     * @return EED_Ticket_Sales_Monitor|EED_Module
148
-     */
149
-    public static function instance()
150
-    {
151
-        return parent::get_instance(__CLASS__);
152
-    }
153
-
154
-
155
-    /**
156
-     * @param WP_Query $WP_Query
157
-     * @return    void
158
-     */
159
-    public function run($WP_Query)
160
-    {
161
-    }
162
-
163
-
164
-
165
-    /********************************** PRE_TICKET_SALES  **********************************/
166
-
167
-
168
-    /**
169
-     * Retrieves grand totals from the line items that have no TXN ID
170
-     * and timestamps less than the current time minus the session lifespan.
171
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
172
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
173
-     *
174
-     * @return void
175
-     * @throws DomainException
176
-     * @throws EE_Error
177
-     * @throws InvalidArgumentException
178
-     * @throws InvalidDataTypeException
179
-     * @throws InvalidInterfaceException
180
-     * @throws UnexpectedEntityException
181
-     */
182
-    public static function release_tickets_for_expired_carts()
183
-    {
184
-        if (self::debug) {
185
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
186
-        }
187
-        do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
188
-        $expired_ticket_IDs = array();
189
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
190
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
191
-            'EventEspresso\core\domain\values\session\SessionLifespan'
192
-        );
193
-        $timestamp = $session_lifespan->expiration();
194
-        $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
195
-        if (self::debug) {
196
-            echo self::$nl . ' . time(): ' . time();
197
-            echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
198
-            echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
199
-            echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
200
-            echo self::$nl . ' . timestamp: ' . $timestamp;
201
-            echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
202
-        }
203
-        if (! empty($expired_ticket_line_items)) {
204
-            foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
205
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
206
-                    continue;
207
-                }
208
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
209
-                if (self::debug) {
210
-                    echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
211
-                    echo self::$nl . ' . $expired_ticket_line_item->timestamp(): '
212
-                         . date(
213
-                             'Y-m-d h:i a',
214
-                             $expired_ticket_line_item->timestamp(true)
215
-                         );
216
-                }
217
-            }
218
-            if (! empty($expired_ticket_IDs)) {
219
-                EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
220
-                    \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
221
-                    array(),
222
-                    __FUNCTION__
223
-                );
224
-                // now  let's get rid of expired line items so that they can't interfere with tracking
225
-                EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
226
-            }
227
-        }
228
-        do_action(
229
-            'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
230
-            $expired_ticket_IDs,
231
-            $expired_ticket_line_items
232
-        );
233
-    }
234
-
235
-
236
-
237
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
238
-
239
-
240
-    /**
241
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
242
-     *
243
-     * @param int       $qty
244
-     * @param EE_Ticket $ticket
245
-     * @return bool
246
-     * @throws UnexpectedEntityException
247
-     * @throws EE_Error
248
-     */
249
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
250
-    {
251
-        $qty = absint($qty);
252
-        if ($qty > 0) {
253
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
254
-        }
255
-        if (self::debug) {
256
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
257
-            echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
258
-        }
259
-        return $qty;
260
-    }
261
-
262
-
263
-    /**
264
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
265
-     *
266
-     * @param   EE_Ticket $ticket
267
-     * @param int         $qty
268
-     * @return int
269
-     * @throws UnexpectedEntityException
270
-     * @throws EE_Error
271
-     */
272
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
273
-    {
274
-        if (self::debug) {
275
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
276
-        }
277
-        if (! $ticket instanceof EE_Ticket) {
278
-            return 0;
279
-        }
280
-        if (self::debug) {
281
-            echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
282
-            echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
283
-        }
284
-        $ticket->refresh_from_db();
285
-        // first let's determine the ticket availability based on sales
286
-        $available = $ticket->qty('saleable');
287
-        if (self::debug) {
288
-            echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
289
-            echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
290
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
291
-            echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
292
-            echo self::$nl . ' . . . available: ' . $available;
293
-        }
294
-        if ($available < 1) {
295
-            $this->_ticket_sold_out($ticket);
296
-            return 0;
297
-        }
298
-        if (self::debug) {
299
-            echo self::$nl . ' . . . qty: ' . $qty;
300
-        }
301
-        if ($available < $qty) {
302
-            $qty = $available;
303
-            if (self::debug) {
304
-                echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
305
-            }
306
-            $this->_ticket_quantity_decremented($ticket);
307
-        }
308
-        $this->_reserve_ticket($ticket, $qty);
309
-        return $qty;
310
-    }
311
-
312
-
313
-    /**
314
-     * increments ticket reserved based on quantity passed
315
-     *
316
-     * @param    EE_Ticket $ticket
317
-     * @param int          $quantity
318
-     * @return bool
319
-     * @throws EE_Error
320
-     */
321
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
322
-    {
323
-        if (self::debug) {
324
-            echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
325
-        }
326
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:' . __LINE__);
327
-        return $ticket->save();
328
-    }
329
-
330
-
331
-    /**
332
-     * @param  EE_Ticket $ticket
333
-     * @param  int       $quantity
334
-     * @return bool
335
-     * @throws EE_Error
336
-     */
337
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
338
-    {
339
-        if (self::debug) {
340
-            echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
341
-            echo self::$nl . ' . . . ticket->reserved before: ' . $ticket->reserved();
342
-        }
343
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:' . __LINE__);
344
-        if (self::debug) {
345
-            echo self::$nl . ' . . . ticket->reserved after: ' . $ticket->reserved();
346
-        }
347
-        return $ticket->save() ? 1 : 0;
348
-    }
349
-
350
-
351
-    /**
352
-     * removes quantities within the ticket selector based on zero ticket availability
353
-     *
354
-     * @param    EE_Ticket $ticket
355
-     * @return    void
356
-     * @throws UnexpectedEntityException
357
-     * @throws EE_Error
358
-     */
359
-    protected function _ticket_sold_out(EE_Ticket $ticket)
360
-    {
361
-        if (self::debug) {
362
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
363
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
364
-        }
365
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
366
-    }
367
-
368
-
369
-    /**
370
-     * adjusts quantities within the ticket selector based on decreased ticket availability
371
-     *
372
-     * @param    EE_Ticket $ticket
373
-     * @return void
374
-     * @throws UnexpectedEntityException
375
-     * @throws EE_Error
376
-     */
377
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
378
-    {
379
-        if (self::debug) {
380
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
381
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
382
-        }
383
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
384
-    }
385
-
386
-
387
-    /**
388
-     * builds string out of ticket and event name
389
-     *
390
-     * @param    EE_Ticket $ticket
391
-     * @return string
392
-     * @throws UnexpectedEntityException
393
-     * @throws EE_Error
394
-     */
395
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
396
-    {
397
-        $event = $ticket->get_related_event();
398
-        if ($event instanceof EE_Event) {
399
-            $ticket_name = sprintf(
400
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
401
-                $ticket->name(),
402
-                $event->name()
403
-            );
404
-        } else {
405
-            $ticket_name = $ticket->name();
406
-        }
407
-        return $ticket_name;
408
-    }
409
-
410
-
411
-
412
-    /********************************** EVENT CART  **********************************/
413
-
414
-
415
-    /**
416
-     * releases or reserves ticket(s) based on quantity passed
417
-     *
418
-     * @param  EE_Line_Item $line_item
419
-     * @param  int          $quantity
420
-     * @return void
421
-     * @throws EE_Error
422
-     * @throws InvalidArgumentException
423
-     * @throws InvalidDataTypeException
424
-     * @throws InvalidInterfaceException
425
-     */
426
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
427
-    {
428
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
429
-        if ($ticket instanceof EE_Ticket) {
430
-            $ticket->add_extra_meta(
431
-                EE_Ticket::META_KEY_TICKET_RESERVATIONS,
432
-                __LINE__ . ') ' . __METHOD__ . '()'
433
-            );
434
-            if ($quantity > 0) {
435
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
436
-            } else {
437
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
438
-            }
439
-        }
440
-    }
441
-
442
-
443
-    /**
444
-     * releases reserved ticket(s) based on quantity passed
445
-     *
446
-     * @param  EE_Ticket $ticket
447
-     * @param  int       $quantity
448
-     * @return void
449
-     * @throws EE_Error
450
-     */
451
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
452
-    {
453
-        $ticket->add_extra_meta(
454
-            EE_Ticket::META_KEY_TICKET_RESERVATIONS,
455
-            __LINE__ . ') ' . __METHOD__ . '()'
456
-        );
457
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
458
-    }
459
-
460
-
461
-
462
-    /********************************** POST_NOTICES  **********************************/
463
-
464
-
465
-    /**
466
-     * @return void
467
-     * @throws EE_Error
468
-     * @throws InvalidArgumentException
469
-     * @throws ReflectionException
470
-     * @throws InvalidDataTypeException
471
-     * @throws InvalidInterfaceException
472
-     */
473
-    public static function post_notices()
474
-    {
475
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
476
-    }
477
-
478
-
479
-    /**
480
-     * @return void
481
-     * @throws EE_Error
482
-     * @throws InvalidArgumentException
483
-     * @throws ReflectionException
484
-     * @throws InvalidDataTypeException
485
-     * @throws InvalidInterfaceException
486
-     */
487
-    protected function _post_notices()
488
-    {
489
-        if (self::debug) {
490
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
491
-        }
492
-        $refresh_msg = '';
493
-        $none_added_msg = '';
494
-        if (defined('DOING_AJAX') && DOING_AJAX) {
495
-            $refresh_msg = __(
496
-                'Please refresh the page to view updated ticket quantities.',
497
-                'event_espresso'
498
-            );
499
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
500
-        }
501
-        if (! empty($this->sold_out_tickets)) {
502
-            EE_Error::add_attention(
503
-                sprintf(
504
-                    apply_filters(
505
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
506
-                        __(
507
-                            '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',
508
-                            'event_espresso'
509
-                        )
510
-                    ),
511
-                    '<br />',
512
-                    implode('<br />', $this->sold_out_tickets),
513
-                    $none_added_msg,
514
-                    $refresh_msg
515
-                )
516
-            );
517
-            // alter code flow in the Ticket Selector for better UX
518
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
519
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
520
-            $this->sold_out_tickets = array();
521
-            // and reset the cart
522
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
523
-        }
524
-        if (! empty($this->decremented_tickets)) {
525
-            EE_Error::add_attention(
526
-                sprintf(
527
-                    apply_filters(
528
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
529
-                        __(
530
-                            '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',
531
-                            'event_espresso'
532
-                        )
533
-                    ),
534
-                    '<br />',
535
-                    implode('<br />', $this->decremented_tickets),
536
-                    $none_added_msg,
537
-                    $refresh_msg
538
-                )
539
-            );
540
-            $this->decremented_tickets = array();
541
-        }
542
-    }
543
-
544
-
545
-
546
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
547
-
548
-
549
-    /**
550
-     * releases reserved tickets for all registrations of an EE_Transaction
551
-     * by default, will NOT release tickets for finalized transactions
552
-     *
553
-     * @param    EE_Transaction $transaction
554
-     * @return int
555
-     * @throws EE_Error
556
-     * @throws InvalidSessionDataException
557
-     */
558
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
559
-    {
560
-        if (self::debug) {
561
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
562
-            echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
563
-            echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
564
-        }
565
-        // check if 'finalize_registration' step has been completed...
566
-        $finalized = $transaction->reg_step_completed('finalize_registration');
567
-        if (self::debug) {
568
-            // DEBUG LOG
569
-            EEH_Debug_Tools::log(
570
-                __CLASS__,
571
-                __FUNCTION__,
572
-                __LINE__,
573
-                array('finalized' => $finalized),
574
-                false,
575
-                'EE_Transaction: ' . $transaction->ID()
576
-            );
577
-        }
578
-        // how many tickets were released
579
-        $count = 0;
580
-        if (self::debug) {
581
-            echo self::$nl . ' . . . TXN finalized: ' . $finalized;
582
-        }
583
-        $release_tickets_with_TXN_status = array(
584
-            EEM_Transaction::failed_status_code,
585
-            EEM_Transaction::abandoned_status_code,
586
-            EEM_Transaction::incomplete_status_code,
587
-        );
588
-        $events = array();
589
-        // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
590
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
591
-            // cancel any reserved tickets for registrations that were not approved
592
-            $registrations = $transaction->registrations();
593
-            if (self::debug) {
594
-                echo self::$nl . ' . . . # registrations: ' . count($registrations);
595
-                $reg = reset($registrations);
596
-                $ticket = $reg->ticket();
597
-                if ($ticket instanceof EE_Ticket) {
598
-                    $ticket->add_extra_meta(
599
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
600
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
601
-                    );
602
-                }
603
-            }
604
-            if (! empty($registrations)) {
605
-                foreach ($registrations as $registration) {
606
-                    if ($registration instanceof EE_Registration
607
-                        && $this->_release_reserved_ticket_for_registration($registration, $transaction)
608
-                    ) {
609
-                        $count++;
610
-                        $events[ $registration->event_ID() ] = $registration->event();
611
-                    }
612
-                }
613
-            }
614
-        }
615
-        if ($events !== array()) {
616
-            foreach ($events as $event) {
617
-                /** @var EE_Event $event */
618
-                $event->perform_sold_out_status_check();
619
-            }
620
-        }
621
-        return $count;
622
-    }
623
-
624
-
625
-    /**
626
-     * releases reserved tickets for an EE_Registration
627
-     * by default, will NOT release tickets for APPROVED registrations
628
-     *
629
-     * @param EE_Registration $registration
630
-     * @param EE_Transaction  $transaction
631
-     * @return int
632
-     * @throws EE_Error
633
-     */
634
-    protected function _release_reserved_ticket_for_registration(
635
-        EE_Registration $registration,
636
-        EE_Transaction $transaction
637
-    ) {
638
-        $STS_ID = $transaction->status_ID();
639
-        if (self::debug) {
640
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
641
-            echo self::$nl . ' . . registration->ID: ' . $registration->ID();
642
-            echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
643
-            echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
644
-        }
645
-        if (// release Tickets for Failed Transactions and Abandoned Transactions
646
-            $STS_ID === EEM_Transaction::failed_status_code
647
-            || $STS_ID === EEM_Transaction::abandoned_status_code
648
-            || (
649
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
650
-                $STS_ID === EEM_Transaction::incomplete_status_code
651
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
652
-            )
653
-        ) {
654
-            if (self::debug) {
655
-                echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
656
-                $rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
657
-                echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
658
-                var_dump($rsrvd);
659
-            }
660
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:' . __LINE__);
661
-            return 1;
662
-        }
663
-        return 0;
664
-    }
665
-
666
-
667
-
668
-    /********************************** SESSION_CART_RESET  **********************************/
669
-
670
-
671
-    /**
672
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
673
-     *
674
-     * @param EE_Session $session
675
-     * @return void
676
-     * @throws EE_Error
677
-     * @throws InvalidArgumentException
678
-     * @throws ReflectionException
679
-     * @throws InvalidDataTypeException
680
-     * @throws InvalidInterfaceException
681
-     */
682
-    public static function session_cart_reset(EE_Session $session)
683
-    {
684
-        // don't release tickets if checkout was already reset
685
-        if (did_action('AHEE__EE_Session__reset_checkout__before_reset')) {
686
-            return;
687
-        }
688
-        if (self::debug) {
689
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
690
-        }
691
-        // first check of the session has a valid Checkout object
692
-        $checkout = $session->checkout();
693
-        if ($checkout instanceof EE_Checkout) {
694
-            // and use that to clear ticket reservations because it will update the associated registration meta data
695
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
696
-            return;
697
-        }
698
-        $cart = $session->cart();
699
-        if ($cart instanceof EE_Cart) {
700
-            if (self::debug) {
701
-                echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
702
-            }
703
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
704
-        } else {
705
-            if (self::debug) {
706
-                echo self::$nl . self::$nl . ' invalid EE_Cart: ';
707
-                var_export($cart, true);
708
-            }
709
-        }
710
-    }
711
-
712
-
713
-    /**
714
-     * releases reserved tickets in the EE_Cart
715
-     *
716
-     * @param EE_Cart $cart
717
-     * @return void
718
-     * @throws EE_Error
719
-     * @throws InvalidArgumentException
720
-     * @throws ReflectionException
721
-     * @throws InvalidDataTypeException
722
-     * @throws InvalidInterfaceException
723
-     */
724
-    protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
725
-    {
726
-        if (self::debug) {
727
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
728
-        }
729
-        $ticket_line_items = $cart->get_tickets();
730
-        if (empty($ticket_line_items)) {
731
-            return;
732
-        }
733
-        if (self::debug) {
734
-            echo '<br /> . ticket_line_item count: ' . count($ticket_line_items);
735
-        }
736
-        foreach ($ticket_line_items as $ticket_line_item) {
737
-            if (self::debug) {
738
-                echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
739
-            }
740
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
741
-                if (self::debug) {
742
-                    echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
743
-                }
744
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
745
-                if ($ticket instanceof EE_Ticket) {
746
-                    if (self::debug) {
747
-                        echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
748
-                        echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
749
-                    }
750
-                    $ticket->add_extra_meta(
751
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
752
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
753
-                    );
754
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
755
-                }
756
-            }
757
-        }
758
-        if (self::debug) {
759
-            echo self::$nl . self::$nl . ' RESET COMPLETED ';
760
-        }
761
-    }
762
-
763
-
764
-
765
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
766
-
767
-
768
-    /**
769
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
770
-     *
771
-     * @param EE_Session $session
772
-     * @return void
773
-     * @throws EE_Error
774
-     * @throws InvalidSessionDataException
775
-     */
776
-    public static function session_checkout_reset(EE_Session $session)
777
-    {
778
-        // don't release tickets if cart was already reset
779
-        if (did_action('AHEE__EE_Session__reset_cart__before_reset')) {
780
-            return;
781
-        }
782
-        $checkout = $session->checkout();
783
-        if ($checkout instanceof EE_Checkout) {
784
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
785
-        }
786
-    }
787
-
788
-
789
-    /**
790
-     * releases reserved tickets for the EE_Checkout->transaction
791
-     *
792
-     * @param EE_Checkout $checkout
793
-     * @return void
794
-     * @throws EE_Error
795
-     * @throws InvalidSessionDataException
796
-     */
797
-    protected function _session_checkout_reset(EE_Checkout $checkout)
798
-    {
799
-        if (self::debug) {
800
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
801
-        }
802
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
803
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
804
-            return;
805
-        }
806
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
807
-    }
808
-
809
-
810
-
811
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
812
-
813
-
814
-    /**
815
-     * @param    EE_Session $session
816
-     * @return    void
817
-     */
818
-    public static function session_expired_reset(EE_Session $session)
819
-    {
820
-    }
821
-
822
-
823
-
824
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
825
-
826
-
827
-    /**
828
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
829
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
830
-     *
831
-     * @param EE_Transaction $transaction
832
-     * @return void
833
-     * @throws EE_Error
834
-     * @throws InvalidSessionDataException
835
-     */
836
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
837
-    {
838
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
839
-        if ($transaction->is_free() || $transaction->paid() > 0) {
840
-            if (self::debug) {
841
-                // DEBUG LOG
842
-                EEH_Debug_Tools::log(
843
-                    __CLASS__,
844
-                    __FUNCTION__,
845
-                    __LINE__,
846
-                    array($transaction),
847
-                    false,
848
-                    'EE_Transaction: ' . $transaction->ID()
849
-                );
850
-            }
851
-            return;
852
-        }
853
-        // have their been any successful payments made ?
854
-        $payments = $transaction->payments();
855
-        foreach ($payments as $payment) {
856
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
857
-                if (self::debug) {
858
-                    // DEBUG LOG
859
-                    EEH_Debug_Tools::log(
860
-                        __CLASS__,
861
-                        __FUNCTION__,
862
-                        __LINE__,
863
-                        array($payment),
864
-                        false,
865
-                        'EE_Transaction: ' . $transaction->ID()
866
-                    );
867
-                }
868
-                return;
869
-            }
870
-        }
871
-        // since you haven't even attempted to pay for your ticket...
872
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
873
-    }
874
-
875
-
876
-
877
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
878
-
879
-
880
-    /**
881
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
882
-     *
883
-     * @param EE_Transaction $transaction
884
-     * @return void
885
-     * @throws EE_Error
886
-     * @throws InvalidSessionDataException
887
-     */
888
-    public static function process_failed_transactions(EE_Transaction $transaction)
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
-    /********************************** RESET RESERVATION COUNTS  *********************************/
897
-
898
-
899
-    /**
900
-     * Resets all ticket and datetime reserved counts to zero
901
-     * Tickets that are currently associated with a Transaction that is in progress
902
-     *
903
-     * @throws EE_Error
904
-     * @throws DomainException
905
-     * @throws InvalidDataTypeException
906
-     * @throws InvalidInterfaceException
907
-     * @throws InvalidArgumentException
908
-     * @throws UnexpectedEntityException
909
-     */
910
-    public static function reset_reservation_counts()
911
-    {
912
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
913
-        $valid_reserved_tickets = array();
914
-        /** @var EE_Transaction[] $transactions_not_in_progress */
915
-        $transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
916
-        foreach ($transactions_not_in_progress as $transaction) {
917
-            // if this TXN has been fully completed, then skip it
918
-            if ($transaction->reg_step_completed('finalize_registration')) {
919
-                continue;
920
-            }
921
-            $total_line_item = $transaction->total_line_item();
922
-            // $transaction_in_progress->line
923
-            if (! $total_line_item instanceof EE_Line_Item) {
924
-                throw new DomainException(
925
-                    esc_html__(
926
-                        'Transaction does not have a valid Total Line Item associated with it.',
927
-                        'event_espresso'
928
-                    )
929
-                );
930
-            }
931
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
932
-                $total_line_item
933
-            );
934
-        }
935
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
936
-        foreach ($total_line_items as $total_line_item) {
937
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
938
-                $total_line_item
939
-            );
940
-        }
941
-        $tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
942
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
943
-            $tickets_with_reservations,
944
-            $valid_reserved_tickets,
945
-            __FUNCTION__
946
-        );
947
-    }
948
-
949
-
950
-    /**
951
-     * @param EE_Line_Item $total_line_item
952
-     * @return EE_Line_Item[]
953
-     */
954
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
955
-    {
956
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
957
-        $valid_reserved_tickets = array();
958
-        $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
959
-        foreach ($ticket_line_items as $ticket_line_item) {
960
-            if ($ticket_line_item instanceof EE_Line_Item) {
961
-                $valid_reserved_tickets[] = $ticket_line_item;
962
-            }
963
-        }
964
-        return $valid_reserved_tickets;
965
-    }
966
-
967
-
968
-    /**
969
-     * @param EE_Ticket[]    $tickets_with_reservations
970
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
971
-     * @return int
972
-     * @throws UnexpectedEntityException
973
-     * @throws DomainException
974
-     * @throws EE_Error
975
-     */
976
-    private static function release_reservations_for_tickets(
977
-        array $tickets_with_reservations,
978
-        array $valid_reserved_ticket_line_items = array(),
979
-        $source
980
-    ) {
981
-        if (self::debug) {
982
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
983
-        }
984
-        $total_tickets_released = 0;
985
-        $sold_out_events = array();
986
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
987
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
988
-                continue;
989
-            }
990
-            $reserved_qty = $ticket_with_reservations->reserved();
991
-            if (self::debug) {
992
-                echo self::$nl . ' . $ticket_with_reservations->ID(): ' . $ticket_with_reservations->ID();
993
-                echo self::$nl . ' . $reserved_qty: ' . $reserved_qty;
994
-            }
995
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
996
-                if ($valid_reserved_ticket_line_item instanceof EE_Line_Item
997
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
998
-                ) {
999
-                    if (self::debug) {
1000
-                        echo self::$nl . ' . $valid_reserved_ticket_line_item->quantity(): '
1001
-                             . $valid_reserved_ticket_line_item->quantity();
1002
-                    }
1003
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1004
-                }
1005
-            }
1006
-            if ($reserved_qty > 0) {
1007
-                $ticket_with_reservations->add_extra_meta(
1008
-                    EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1009
-                    __LINE__ . ') ' . $source . '()'
1010
-                );
1011
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:' . __LINE__);
1012
-                $ticket_with_reservations->save();
1013
-                $total_tickets_released += $reserved_qty;
1014
-                $event = $ticket_with_reservations->get_related_event();
1015
-                // track sold out events
1016
-                if ($event instanceof EE_Event && $event->is_sold_out()) {
1017
-                    $sold_out_events[] = $event;
1018
-                }
1019
-            }
1020
-        }
1021
-        if (self::debug) {
1022
-            echo self::$nl . ' . $total_tickets_released: ' . $total_tickets_released;
1023
-        }
1024
-        // double check whether sold out events should remain sold out after releasing tickets
1025
-        if ($sold_out_events !== array()) {
1026
-            foreach ($sold_out_events as $sold_out_event) {
1027
-                /** @var EE_Event $sold_out_event */
1028
-                $sold_out_event->perform_sold_out_status_check();
1029
-            }
1030
-        }
1031
-        return $total_tickets_released;
1032
-    }
1033
-
1034
-
1035
-
1036
-    /********************************** SHUTDOWN  **********************************/
1037
-
1038
-
1039
-    /**
1040
-     * @param int $timestamp
1041
-     * @return false|int
1042
-     * @throws EE_Error
1043
-     * @throws InvalidArgumentException
1044
-     * @throws InvalidDataTypeException
1045
-     * @throws InvalidInterfaceException
1046
-     */
1047
-    public static function clear_expired_line_items_with_no_transaction($timestamp = 0)
1048
-    {
1049
-        /** @type WPDB $wpdb */
1050
-        global $wpdb;
1051
-        if (! absint($timestamp)) {
1052
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1053
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
1054
-                'EventEspresso\core\domain\values\session\SessionLifespan'
1055
-            );
1056
-            $timestamp = $session_lifespan->expiration();
1057
-        }
1058
-        return $wpdb->query(
1059
-            $wpdb->prepare(
1060
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
23
+	const debug = false;
24
+
25
+	private static $nl = '';
26
+
27
+	/**
28
+	 * an array of raw ticket data from EED_Ticket_Selector
29
+	 *
30
+	 * @var array $ticket_selections
31
+	 */
32
+	protected $ticket_selections = array();
33
+
34
+	/**
35
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
36
+	 * according to how they are displayed in the actual Ticket_Selector
37
+	 * this tracks the current row being processed
38
+	 *
39
+	 * @var int $current_row
40
+	 */
41
+	protected $current_row = 0;
42
+
43
+	/**
44
+	 * an array for tracking names of tickets that have sold out
45
+	 *
46
+	 * @var array $sold_out_tickets
47
+	 */
48
+	protected $sold_out_tickets = array();
49
+
50
+	/**
51
+	 * an array for tracking names of tickets that have had their quantities reduced
52
+	 *
53
+	 * @var array $decremented_tickets
54
+	 */
55
+	protected $decremented_tickets = array();
56
+
57
+
58
+	/**
59
+	 * set_hooks - for hooking into EE Core, other modules, etc
60
+	 *
61
+	 * @return    void
62
+	 */
63
+	public static function set_hooks()
64
+	{
65
+		self::$nl = defined('EE_TESTS_DIR') ? "\n" : '<br />';
66
+		// release tickets for expired carts
67
+		add_action(
68
+			'EED_Ticket_Selector__process_ticket_selections__before',
69
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
70
+			1
71
+		);
72
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
73
+		add_filter(
74
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
75
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
76
+			20,
77
+			3
78
+		);
79
+		// add notices for sold out tickets
80
+		add_action(
81
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
82
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
83
+			10
84
+		);
85
+
86
+		// handle tickets deleted from cart
87
+		add_action(
88
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
89
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
90
+			10,
91
+			2
92
+		);
93
+		// handle emptied carts
94
+		add_action(
95
+			'AHEE__EE_Session__reset_cart__before_reset',
96
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
97
+			10,
98
+			1
99
+		);
100
+		add_action(
101
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
102
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
103
+			10,
104
+			1
105
+		);
106
+		// handle cancelled registrations
107
+		add_action(
108
+			'AHEE__EE_Session__reset_checkout__before_reset',
109
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
110
+			10,
111
+			1
112
+		);
113
+		// cron tasks
114
+		add_action(
115
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
116
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
117
+			10,
118
+			1
119
+		);
120
+		add_action(
121
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_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__failed_transaction',
128
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
129
+			10,
130
+			1
131
+		);
132
+	}
133
+
134
+
135
+	/**
136
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
137
+	 *
138
+	 * @return void
139
+	 */
140
+	public static function set_hooks_admin()
141
+	{
142
+		EED_Ticket_Sales_Monitor::set_hooks();
143
+	}
144
+
145
+
146
+	/**
147
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
148
+	 */
149
+	public static function instance()
150
+	{
151
+		return parent::get_instance(__CLASS__);
152
+	}
153
+
154
+
155
+	/**
156
+	 * @param WP_Query $WP_Query
157
+	 * @return    void
158
+	 */
159
+	public function run($WP_Query)
160
+	{
161
+	}
162
+
163
+
164
+
165
+	/********************************** PRE_TICKET_SALES  **********************************/
166
+
167
+
168
+	/**
169
+	 * Retrieves grand totals from the line items that have no TXN ID
170
+	 * and timestamps less than the current time minus the session lifespan.
171
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
172
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
173
+	 *
174
+	 * @return void
175
+	 * @throws DomainException
176
+	 * @throws EE_Error
177
+	 * @throws InvalidArgumentException
178
+	 * @throws InvalidDataTypeException
179
+	 * @throws InvalidInterfaceException
180
+	 * @throws UnexpectedEntityException
181
+	 */
182
+	public static function release_tickets_for_expired_carts()
183
+	{
184
+		if (self::debug) {
185
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
186
+		}
187
+		do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
188
+		$expired_ticket_IDs = array();
189
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
190
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
191
+			'EventEspresso\core\domain\values\session\SessionLifespan'
192
+		);
193
+		$timestamp = $session_lifespan->expiration();
194
+		$expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
195
+		if (self::debug) {
196
+			echo self::$nl . ' . time(): ' . time();
197
+			echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
198
+			echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
199
+			echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
200
+			echo self::$nl . ' . timestamp: ' . $timestamp;
201
+			echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
202
+		}
203
+		if (! empty($expired_ticket_line_items)) {
204
+			foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
205
+				if (! $expired_ticket_line_item instanceof EE_Line_Item) {
206
+					continue;
207
+				}
208
+				$expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
209
+				if (self::debug) {
210
+					echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
211
+					echo self::$nl . ' . $expired_ticket_line_item->timestamp(): '
212
+						 . date(
213
+							 'Y-m-d h:i a',
214
+							 $expired_ticket_line_item->timestamp(true)
215
+						 );
216
+				}
217
+			}
218
+			if (! empty($expired_ticket_IDs)) {
219
+				EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
220
+					\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
221
+					array(),
222
+					__FUNCTION__
223
+				);
224
+				// now  let's get rid of expired line items so that they can't interfere with tracking
225
+				EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
226
+			}
227
+		}
228
+		do_action(
229
+			'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
230
+			$expired_ticket_IDs,
231
+			$expired_ticket_line_items
232
+		);
233
+	}
234
+
235
+
236
+
237
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
238
+
239
+
240
+	/**
241
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
242
+	 *
243
+	 * @param int       $qty
244
+	 * @param EE_Ticket $ticket
245
+	 * @return bool
246
+	 * @throws UnexpectedEntityException
247
+	 * @throws EE_Error
248
+	 */
249
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
250
+	{
251
+		$qty = absint($qty);
252
+		if ($qty > 0) {
253
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
254
+		}
255
+		if (self::debug) {
256
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
257
+			echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
258
+		}
259
+		return $qty;
260
+	}
261
+
262
+
263
+	/**
264
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
265
+	 *
266
+	 * @param   EE_Ticket $ticket
267
+	 * @param int         $qty
268
+	 * @return int
269
+	 * @throws UnexpectedEntityException
270
+	 * @throws EE_Error
271
+	 */
272
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
273
+	{
274
+		if (self::debug) {
275
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
276
+		}
277
+		if (! $ticket instanceof EE_Ticket) {
278
+			return 0;
279
+		}
280
+		if (self::debug) {
281
+			echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
282
+			echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
283
+		}
284
+		$ticket->refresh_from_db();
285
+		// first let's determine the ticket availability based on sales
286
+		$available = $ticket->qty('saleable');
287
+		if (self::debug) {
288
+			echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
289
+			echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
290
+			echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
291
+			echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
292
+			echo self::$nl . ' . . . available: ' . $available;
293
+		}
294
+		if ($available < 1) {
295
+			$this->_ticket_sold_out($ticket);
296
+			return 0;
297
+		}
298
+		if (self::debug) {
299
+			echo self::$nl . ' . . . qty: ' . $qty;
300
+		}
301
+		if ($available < $qty) {
302
+			$qty = $available;
303
+			if (self::debug) {
304
+				echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
305
+			}
306
+			$this->_ticket_quantity_decremented($ticket);
307
+		}
308
+		$this->_reserve_ticket($ticket, $qty);
309
+		return $qty;
310
+	}
311
+
312
+
313
+	/**
314
+	 * increments ticket reserved based on quantity passed
315
+	 *
316
+	 * @param    EE_Ticket $ticket
317
+	 * @param int          $quantity
318
+	 * @return bool
319
+	 * @throws EE_Error
320
+	 */
321
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
322
+	{
323
+		if (self::debug) {
324
+			echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
325
+		}
326
+		$ticket->increase_reserved($quantity, 'TicketSalesMonitor:' . __LINE__);
327
+		return $ticket->save();
328
+	}
329
+
330
+
331
+	/**
332
+	 * @param  EE_Ticket $ticket
333
+	 * @param  int       $quantity
334
+	 * @return bool
335
+	 * @throws EE_Error
336
+	 */
337
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
338
+	{
339
+		if (self::debug) {
340
+			echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
341
+			echo self::$nl . ' . . . ticket->reserved before: ' . $ticket->reserved();
342
+		}
343
+		$ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:' . __LINE__);
344
+		if (self::debug) {
345
+			echo self::$nl . ' . . . ticket->reserved after: ' . $ticket->reserved();
346
+		}
347
+		return $ticket->save() ? 1 : 0;
348
+	}
349
+
350
+
351
+	/**
352
+	 * removes quantities within the ticket selector based on zero ticket availability
353
+	 *
354
+	 * @param    EE_Ticket $ticket
355
+	 * @return    void
356
+	 * @throws UnexpectedEntityException
357
+	 * @throws EE_Error
358
+	 */
359
+	protected function _ticket_sold_out(EE_Ticket $ticket)
360
+	{
361
+		if (self::debug) {
362
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
363
+			echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
364
+		}
365
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
366
+	}
367
+
368
+
369
+	/**
370
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
371
+	 *
372
+	 * @param    EE_Ticket $ticket
373
+	 * @return void
374
+	 * @throws UnexpectedEntityException
375
+	 * @throws EE_Error
376
+	 */
377
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
378
+	{
379
+		if (self::debug) {
380
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
381
+			echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
382
+		}
383
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
384
+	}
385
+
386
+
387
+	/**
388
+	 * builds string out of ticket and event name
389
+	 *
390
+	 * @param    EE_Ticket $ticket
391
+	 * @return string
392
+	 * @throws UnexpectedEntityException
393
+	 * @throws EE_Error
394
+	 */
395
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
396
+	{
397
+		$event = $ticket->get_related_event();
398
+		if ($event instanceof EE_Event) {
399
+			$ticket_name = sprintf(
400
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
401
+				$ticket->name(),
402
+				$event->name()
403
+			);
404
+		} else {
405
+			$ticket_name = $ticket->name();
406
+		}
407
+		return $ticket_name;
408
+	}
409
+
410
+
411
+
412
+	/********************************** EVENT CART  **********************************/
413
+
414
+
415
+	/**
416
+	 * releases or reserves ticket(s) based on quantity passed
417
+	 *
418
+	 * @param  EE_Line_Item $line_item
419
+	 * @param  int          $quantity
420
+	 * @return void
421
+	 * @throws EE_Error
422
+	 * @throws InvalidArgumentException
423
+	 * @throws InvalidDataTypeException
424
+	 * @throws InvalidInterfaceException
425
+	 */
426
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
427
+	{
428
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
429
+		if ($ticket instanceof EE_Ticket) {
430
+			$ticket->add_extra_meta(
431
+				EE_Ticket::META_KEY_TICKET_RESERVATIONS,
432
+				__LINE__ . ') ' . __METHOD__ . '()'
433
+			);
434
+			if ($quantity > 0) {
435
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
436
+			} else {
437
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
438
+			}
439
+		}
440
+	}
441
+
442
+
443
+	/**
444
+	 * releases reserved ticket(s) based on quantity passed
445
+	 *
446
+	 * @param  EE_Ticket $ticket
447
+	 * @param  int       $quantity
448
+	 * @return void
449
+	 * @throws EE_Error
450
+	 */
451
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
452
+	{
453
+		$ticket->add_extra_meta(
454
+			EE_Ticket::META_KEY_TICKET_RESERVATIONS,
455
+			__LINE__ . ') ' . __METHOD__ . '()'
456
+		);
457
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
458
+	}
459
+
460
+
461
+
462
+	/********************************** POST_NOTICES  **********************************/
463
+
464
+
465
+	/**
466
+	 * @return void
467
+	 * @throws EE_Error
468
+	 * @throws InvalidArgumentException
469
+	 * @throws ReflectionException
470
+	 * @throws InvalidDataTypeException
471
+	 * @throws InvalidInterfaceException
472
+	 */
473
+	public static function post_notices()
474
+	{
475
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
476
+	}
477
+
478
+
479
+	/**
480
+	 * @return void
481
+	 * @throws EE_Error
482
+	 * @throws InvalidArgumentException
483
+	 * @throws ReflectionException
484
+	 * @throws InvalidDataTypeException
485
+	 * @throws InvalidInterfaceException
486
+	 */
487
+	protected function _post_notices()
488
+	{
489
+		if (self::debug) {
490
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
491
+		}
492
+		$refresh_msg = '';
493
+		$none_added_msg = '';
494
+		if (defined('DOING_AJAX') && DOING_AJAX) {
495
+			$refresh_msg = __(
496
+				'Please refresh the page to view updated ticket quantities.',
497
+				'event_espresso'
498
+			);
499
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
500
+		}
501
+		if (! empty($this->sold_out_tickets)) {
502
+			EE_Error::add_attention(
503
+				sprintf(
504
+					apply_filters(
505
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
506
+						__(
507
+							'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',
508
+							'event_espresso'
509
+						)
510
+					),
511
+					'<br />',
512
+					implode('<br />', $this->sold_out_tickets),
513
+					$none_added_msg,
514
+					$refresh_msg
515
+				)
516
+			);
517
+			// alter code flow in the Ticket Selector for better UX
518
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
519
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
520
+			$this->sold_out_tickets = array();
521
+			// and reset the cart
522
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
523
+		}
524
+		if (! empty($this->decremented_tickets)) {
525
+			EE_Error::add_attention(
526
+				sprintf(
527
+					apply_filters(
528
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
529
+						__(
530
+							'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',
531
+							'event_espresso'
532
+						)
533
+					),
534
+					'<br />',
535
+					implode('<br />', $this->decremented_tickets),
536
+					$none_added_msg,
537
+					$refresh_msg
538
+				)
539
+			);
540
+			$this->decremented_tickets = array();
541
+		}
542
+	}
543
+
544
+
545
+
546
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
547
+
548
+
549
+	/**
550
+	 * releases reserved tickets for all registrations of an EE_Transaction
551
+	 * by default, will NOT release tickets for finalized transactions
552
+	 *
553
+	 * @param    EE_Transaction $transaction
554
+	 * @return int
555
+	 * @throws EE_Error
556
+	 * @throws InvalidSessionDataException
557
+	 */
558
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
559
+	{
560
+		if (self::debug) {
561
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
562
+			echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
563
+			echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
564
+		}
565
+		// check if 'finalize_registration' step has been completed...
566
+		$finalized = $transaction->reg_step_completed('finalize_registration');
567
+		if (self::debug) {
568
+			// DEBUG LOG
569
+			EEH_Debug_Tools::log(
570
+				__CLASS__,
571
+				__FUNCTION__,
572
+				__LINE__,
573
+				array('finalized' => $finalized),
574
+				false,
575
+				'EE_Transaction: ' . $transaction->ID()
576
+			);
577
+		}
578
+		// how many tickets were released
579
+		$count = 0;
580
+		if (self::debug) {
581
+			echo self::$nl . ' . . . TXN finalized: ' . $finalized;
582
+		}
583
+		$release_tickets_with_TXN_status = array(
584
+			EEM_Transaction::failed_status_code,
585
+			EEM_Transaction::abandoned_status_code,
586
+			EEM_Transaction::incomplete_status_code,
587
+		);
588
+		$events = array();
589
+		// if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
590
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
591
+			// cancel any reserved tickets for registrations that were not approved
592
+			$registrations = $transaction->registrations();
593
+			if (self::debug) {
594
+				echo self::$nl . ' . . . # registrations: ' . count($registrations);
595
+				$reg = reset($registrations);
596
+				$ticket = $reg->ticket();
597
+				if ($ticket instanceof EE_Ticket) {
598
+					$ticket->add_extra_meta(
599
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
600
+						__LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
601
+					);
602
+				}
603
+			}
604
+			if (! empty($registrations)) {
605
+				foreach ($registrations as $registration) {
606
+					if ($registration instanceof EE_Registration
607
+						&& $this->_release_reserved_ticket_for_registration($registration, $transaction)
608
+					) {
609
+						$count++;
610
+						$events[ $registration->event_ID() ] = $registration->event();
611
+					}
612
+				}
613
+			}
614
+		}
615
+		if ($events !== array()) {
616
+			foreach ($events as $event) {
617
+				/** @var EE_Event $event */
618
+				$event->perform_sold_out_status_check();
619
+			}
620
+		}
621
+		return $count;
622
+	}
623
+
624
+
625
+	/**
626
+	 * releases reserved tickets for an EE_Registration
627
+	 * by default, will NOT release tickets for APPROVED registrations
628
+	 *
629
+	 * @param EE_Registration $registration
630
+	 * @param EE_Transaction  $transaction
631
+	 * @return int
632
+	 * @throws EE_Error
633
+	 */
634
+	protected function _release_reserved_ticket_for_registration(
635
+		EE_Registration $registration,
636
+		EE_Transaction $transaction
637
+	) {
638
+		$STS_ID = $transaction->status_ID();
639
+		if (self::debug) {
640
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
641
+			echo self::$nl . ' . . registration->ID: ' . $registration->ID();
642
+			echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
643
+			echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
644
+		}
645
+		if (// release Tickets for Failed Transactions and Abandoned Transactions
646
+			$STS_ID === EEM_Transaction::failed_status_code
647
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
648
+			|| (
649
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
650
+				$STS_ID === EEM_Transaction::incomplete_status_code
651
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
652
+			)
653
+		) {
654
+			if (self::debug) {
655
+				echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
656
+				$rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
657
+				echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
658
+				var_dump($rsrvd);
659
+			}
660
+			$registration->release_reserved_ticket(true, 'TicketSalesMonitor:' . __LINE__);
661
+			return 1;
662
+		}
663
+		return 0;
664
+	}
665
+
666
+
667
+
668
+	/********************************** SESSION_CART_RESET  **********************************/
669
+
670
+
671
+	/**
672
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
673
+	 *
674
+	 * @param EE_Session $session
675
+	 * @return void
676
+	 * @throws EE_Error
677
+	 * @throws InvalidArgumentException
678
+	 * @throws ReflectionException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws InvalidInterfaceException
681
+	 */
682
+	public static function session_cart_reset(EE_Session $session)
683
+	{
684
+		// don't release tickets if checkout was already reset
685
+		if (did_action('AHEE__EE_Session__reset_checkout__before_reset')) {
686
+			return;
687
+		}
688
+		if (self::debug) {
689
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
690
+		}
691
+		// first check of the session has a valid Checkout object
692
+		$checkout = $session->checkout();
693
+		if ($checkout instanceof EE_Checkout) {
694
+			// and use that to clear ticket reservations because it will update the associated registration meta data
695
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
696
+			return;
697
+		}
698
+		$cart = $session->cart();
699
+		if ($cart instanceof EE_Cart) {
700
+			if (self::debug) {
701
+				echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
702
+			}
703
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
704
+		} else {
705
+			if (self::debug) {
706
+				echo self::$nl . self::$nl . ' invalid EE_Cart: ';
707
+				var_export($cart, true);
708
+			}
709
+		}
710
+	}
711
+
712
+
713
+	/**
714
+	 * releases reserved tickets in the EE_Cart
715
+	 *
716
+	 * @param EE_Cart $cart
717
+	 * @return void
718
+	 * @throws EE_Error
719
+	 * @throws InvalidArgumentException
720
+	 * @throws ReflectionException
721
+	 * @throws InvalidDataTypeException
722
+	 * @throws InvalidInterfaceException
723
+	 */
724
+	protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
725
+	{
726
+		if (self::debug) {
727
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
728
+		}
729
+		$ticket_line_items = $cart->get_tickets();
730
+		if (empty($ticket_line_items)) {
731
+			return;
732
+		}
733
+		if (self::debug) {
734
+			echo '<br /> . ticket_line_item count: ' . count($ticket_line_items);
735
+		}
736
+		foreach ($ticket_line_items as $ticket_line_item) {
737
+			if (self::debug) {
738
+				echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
739
+			}
740
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
741
+				if (self::debug) {
742
+					echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
743
+				}
744
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
745
+				if ($ticket instanceof EE_Ticket) {
746
+					if (self::debug) {
747
+						echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
748
+						echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
749
+					}
750
+					$ticket->add_extra_meta(
751
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
752
+						__LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
753
+					);
754
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
755
+				}
756
+			}
757
+		}
758
+		if (self::debug) {
759
+			echo self::$nl . self::$nl . ' RESET COMPLETED ';
760
+		}
761
+	}
762
+
763
+
764
+
765
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
766
+
767
+
768
+	/**
769
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
770
+	 *
771
+	 * @param EE_Session $session
772
+	 * @return void
773
+	 * @throws EE_Error
774
+	 * @throws InvalidSessionDataException
775
+	 */
776
+	public static function session_checkout_reset(EE_Session $session)
777
+	{
778
+		// don't release tickets if cart was already reset
779
+		if (did_action('AHEE__EE_Session__reset_cart__before_reset')) {
780
+			return;
781
+		}
782
+		$checkout = $session->checkout();
783
+		if ($checkout instanceof EE_Checkout) {
784
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
785
+		}
786
+	}
787
+
788
+
789
+	/**
790
+	 * releases reserved tickets for the EE_Checkout->transaction
791
+	 *
792
+	 * @param EE_Checkout $checkout
793
+	 * @return void
794
+	 * @throws EE_Error
795
+	 * @throws InvalidSessionDataException
796
+	 */
797
+	protected function _session_checkout_reset(EE_Checkout $checkout)
798
+	{
799
+		if (self::debug) {
800
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
801
+		}
802
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
803
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
804
+			return;
805
+		}
806
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
807
+	}
808
+
809
+
810
+
811
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
812
+
813
+
814
+	/**
815
+	 * @param    EE_Session $session
816
+	 * @return    void
817
+	 */
818
+	public static function session_expired_reset(EE_Session $session)
819
+	{
820
+	}
821
+
822
+
823
+
824
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
825
+
826
+
827
+	/**
828
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
829
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
830
+	 *
831
+	 * @param EE_Transaction $transaction
832
+	 * @return void
833
+	 * @throws EE_Error
834
+	 * @throws InvalidSessionDataException
835
+	 */
836
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
837
+	{
838
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
839
+		if ($transaction->is_free() || $transaction->paid() > 0) {
840
+			if (self::debug) {
841
+				// DEBUG LOG
842
+				EEH_Debug_Tools::log(
843
+					__CLASS__,
844
+					__FUNCTION__,
845
+					__LINE__,
846
+					array($transaction),
847
+					false,
848
+					'EE_Transaction: ' . $transaction->ID()
849
+				);
850
+			}
851
+			return;
852
+		}
853
+		// have their been any successful payments made ?
854
+		$payments = $transaction->payments();
855
+		foreach ($payments as $payment) {
856
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
857
+				if (self::debug) {
858
+					// DEBUG LOG
859
+					EEH_Debug_Tools::log(
860
+						__CLASS__,
861
+						__FUNCTION__,
862
+						__LINE__,
863
+						array($payment),
864
+						false,
865
+						'EE_Transaction: ' . $transaction->ID()
866
+					);
867
+				}
868
+				return;
869
+			}
870
+		}
871
+		// since you haven't even attempted to pay for your ticket...
872
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
873
+	}
874
+
875
+
876
+
877
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
878
+
879
+
880
+	/**
881
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
882
+	 *
883
+	 * @param EE_Transaction $transaction
884
+	 * @return void
885
+	 * @throws EE_Error
886
+	 * @throws InvalidSessionDataException
887
+	 */
888
+	public static function process_failed_transactions(EE_Transaction $transaction)
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
+	/********************************** RESET RESERVATION COUNTS  *********************************/
897
+
898
+
899
+	/**
900
+	 * Resets all ticket and datetime reserved counts to zero
901
+	 * Tickets that are currently associated with a Transaction that is in progress
902
+	 *
903
+	 * @throws EE_Error
904
+	 * @throws DomainException
905
+	 * @throws InvalidDataTypeException
906
+	 * @throws InvalidInterfaceException
907
+	 * @throws InvalidArgumentException
908
+	 * @throws UnexpectedEntityException
909
+	 */
910
+	public static function reset_reservation_counts()
911
+	{
912
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
913
+		$valid_reserved_tickets = array();
914
+		/** @var EE_Transaction[] $transactions_not_in_progress */
915
+		$transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
916
+		foreach ($transactions_not_in_progress as $transaction) {
917
+			// if this TXN has been fully completed, then skip it
918
+			if ($transaction->reg_step_completed('finalize_registration')) {
919
+				continue;
920
+			}
921
+			$total_line_item = $transaction->total_line_item();
922
+			// $transaction_in_progress->line
923
+			if (! $total_line_item instanceof EE_Line_Item) {
924
+				throw new DomainException(
925
+					esc_html__(
926
+						'Transaction does not have a valid Total Line Item associated with it.',
927
+						'event_espresso'
928
+					)
929
+				);
930
+			}
931
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
932
+				$total_line_item
933
+			);
934
+		}
935
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
936
+		foreach ($total_line_items as $total_line_item) {
937
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
938
+				$total_line_item
939
+			);
940
+		}
941
+		$tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
942
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
943
+			$tickets_with_reservations,
944
+			$valid_reserved_tickets,
945
+			__FUNCTION__
946
+		);
947
+	}
948
+
949
+
950
+	/**
951
+	 * @param EE_Line_Item $total_line_item
952
+	 * @return EE_Line_Item[]
953
+	 */
954
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
955
+	{
956
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
957
+		$valid_reserved_tickets = array();
958
+		$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
959
+		foreach ($ticket_line_items as $ticket_line_item) {
960
+			if ($ticket_line_item instanceof EE_Line_Item) {
961
+				$valid_reserved_tickets[] = $ticket_line_item;
962
+			}
963
+		}
964
+		return $valid_reserved_tickets;
965
+	}
966
+
967
+
968
+	/**
969
+	 * @param EE_Ticket[]    $tickets_with_reservations
970
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
971
+	 * @return int
972
+	 * @throws UnexpectedEntityException
973
+	 * @throws DomainException
974
+	 * @throws EE_Error
975
+	 */
976
+	private static function release_reservations_for_tickets(
977
+		array $tickets_with_reservations,
978
+		array $valid_reserved_ticket_line_items = array(),
979
+		$source
980
+	) {
981
+		if (self::debug) {
982
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
983
+		}
984
+		$total_tickets_released = 0;
985
+		$sold_out_events = array();
986
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
987
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
988
+				continue;
989
+			}
990
+			$reserved_qty = $ticket_with_reservations->reserved();
991
+			if (self::debug) {
992
+				echo self::$nl . ' . $ticket_with_reservations->ID(): ' . $ticket_with_reservations->ID();
993
+				echo self::$nl . ' . $reserved_qty: ' . $reserved_qty;
994
+			}
995
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
996
+				if ($valid_reserved_ticket_line_item instanceof EE_Line_Item
997
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
998
+				) {
999
+					if (self::debug) {
1000
+						echo self::$nl . ' . $valid_reserved_ticket_line_item->quantity(): '
1001
+							 . $valid_reserved_ticket_line_item->quantity();
1002
+					}
1003
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1004
+				}
1005
+			}
1006
+			if ($reserved_qty > 0) {
1007
+				$ticket_with_reservations->add_extra_meta(
1008
+					EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1009
+					__LINE__ . ') ' . $source . '()'
1010
+				);
1011
+				$ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:' . __LINE__);
1012
+				$ticket_with_reservations->save();
1013
+				$total_tickets_released += $reserved_qty;
1014
+				$event = $ticket_with_reservations->get_related_event();
1015
+				// track sold out events
1016
+				if ($event instanceof EE_Event && $event->is_sold_out()) {
1017
+					$sold_out_events[] = $event;
1018
+				}
1019
+			}
1020
+		}
1021
+		if (self::debug) {
1022
+			echo self::$nl . ' . $total_tickets_released: ' . $total_tickets_released;
1023
+		}
1024
+		// double check whether sold out events should remain sold out after releasing tickets
1025
+		if ($sold_out_events !== array()) {
1026
+			foreach ($sold_out_events as $sold_out_event) {
1027
+				/** @var EE_Event $sold_out_event */
1028
+				$sold_out_event->perform_sold_out_status_check();
1029
+			}
1030
+		}
1031
+		return $total_tickets_released;
1032
+	}
1033
+
1034
+
1035
+
1036
+	/********************************** SHUTDOWN  **********************************/
1037
+
1038
+
1039
+	/**
1040
+	 * @param int $timestamp
1041
+	 * @return false|int
1042
+	 * @throws EE_Error
1043
+	 * @throws InvalidArgumentException
1044
+	 * @throws InvalidDataTypeException
1045
+	 * @throws InvalidInterfaceException
1046
+	 */
1047
+	public static function clear_expired_line_items_with_no_transaction($timestamp = 0)
1048
+	{
1049
+		/** @type WPDB $wpdb */
1050
+		global $wpdb;
1051
+		if (! absint($timestamp)) {
1052
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1053
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
1054
+				'EventEspresso\core\domain\values\session\SessionLifespan'
1055
+			);
1056
+			$timestamp = $session_lifespan->expiration();
1057
+		}
1058
+		return $wpdb->query(
1059
+			$wpdb->prepare(
1060
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1061 1061
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1062
-                // use GMT time because that's what LIN_timestamps are in
1063
-                date('Y-m-d H:i:s', $timestamp)
1064
-            )
1065
-        );
1066
-    }
1062
+				// use GMT time because that's what LIN_timestamps are in
1063
+				date('Y-m-d H:i:s', $timestamp)
1064
+			)
1065
+		);
1066
+	}
1067 1067
 }
Please login to merge, or discard this patch.
Spacing   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
     public static function release_tickets_for_expired_carts()
183 183
     {
184 184
         if (self::debug) {
185
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
185
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
186 186
         }
187 187
         do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
188 188
         $expired_ticket_IDs = array();
@@ -193,29 +193,29 @@  discard block
 block discarded – undo
193 193
         $timestamp = $session_lifespan->expiration();
194 194
         $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
195 195
         if (self::debug) {
196
-            echo self::$nl . ' . time(): ' . time();
197
-            echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
198
-            echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
199
-            echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
200
-            echo self::$nl . ' . timestamp: ' . $timestamp;
201
-            echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
196
+            echo self::$nl.' . time(): '.time();
197
+            echo self::$nl.' . time() as date: '.date('Y-m-d H:i a');
198
+            echo self::$nl.' . session expiration: '.$session_lifespan->expiration();
199
+            echo self::$nl.' . session expiration as date: '.date('Y-m-d H:i a', $session_lifespan->expiration());
200
+            echo self::$nl.' . timestamp: '.$timestamp;
201
+            echo self::$nl.' . $expired_ticket_line_items: '.count($expired_ticket_line_items);
202 202
         }
203
-        if (! empty($expired_ticket_line_items)) {
203
+        if ( ! empty($expired_ticket_line_items)) {
204 204
             foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
205
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
205
+                if ( ! $expired_ticket_line_item instanceof EE_Line_Item) {
206 206
                     continue;
207 207
                 }
208
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
208
+                $expired_ticket_IDs[$expired_ticket_line_item->OBJ_ID()] = $expired_ticket_line_item->OBJ_ID();
209 209
                 if (self::debug) {
210
-                    echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
211
-                    echo self::$nl . ' . $expired_ticket_line_item->timestamp(): '
210
+                    echo self::$nl.' . $expired_ticket_line_item->OBJ_ID(): '.$expired_ticket_line_item->OBJ_ID();
211
+                    echo self::$nl.' . $expired_ticket_line_item->timestamp(): '
212 212
                          . date(
213 213
                              'Y-m-d h:i a',
214 214
                              $expired_ticket_line_item->timestamp(true)
215 215
                          );
216 216
                 }
217 217
             }
218
-            if (! empty($expired_ticket_IDs)) {
218
+            if ( ! empty($expired_ticket_IDs)) {
219 219
                 EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
220 220
                     \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
221 221
                     array(),
@@ -253,8 +253,8 @@  discard block
 block discarded – undo
253 253
             $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
254 254
         }
255 255
         if (self::debug) {
256
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
257
-            echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
256
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
257
+            echo self::$nl.self::$nl.'<b> RETURNED QTY: '.$qty.'</b>';
258 258
         }
259 259
         return $qty;
260 260
     }
@@ -272,36 +272,36 @@  discard block
 block discarded – undo
272 272
     protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
273 273
     {
274 274
         if (self::debug) {
275
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
275
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
276 276
         }
277
-        if (! $ticket instanceof EE_Ticket) {
277
+        if ( ! $ticket instanceof EE_Ticket) {
278 278
             return 0;
279 279
         }
280 280
         if (self::debug) {
281
-            echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
282
-            echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
281
+            echo self::$nl.'<b> . ticket->ID: '.$ticket->ID().'</b>';
282
+            echo self::$nl.' . original ticket->reserved: '.$ticket->reserved();
283 283
         }
284 284
         $ticket->refresh_from_db();
285 285
         // first let's determine the ticket availability based on sales
286 286
         $available = $ticket->qty('saleable');
287 287
         if (self::debug) {
288
-            echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
289
-            echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
290
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
291
-            echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
292
-            echo self::$nl . ' . . . available: ' . $available;
288
+            echo self::$nl.' . . . ticket->qty: '.$ticket->qty();
289
+            echo self::$nl.' . . . ticket->sold: '.$ticket->sold();
290
+            echo self::$nl.' . . . ticket->reserved: '.$ticket->reserved();
291
+            echo self::$nl.' . . . ticket->qty(saleable): '.$ticket->qty('saleable');
292
+            echo self::$nl.' . . . available: '.$available;
293 293
         }
294 294
         if ($available < 1) {
295 295
             $this->_ticket_sold_out($ticket);
296 296
             return 0;
297 297
         }
298 298
         if (self::debug) {
299
-            echo self::$nl . ' . . . qty: ' . $qty;
299
+            echo self::$nl.' . . . qty: '.$qty;
300 300
         }
301 301
         if ($available < $qty) {
302 302
             $qty = $available;
303 303
             if (self::debug) {
304
-                echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
304
+                echo self::$nl.' . . . QTY ADJUSTED: '.$qty;
305 305
             }
306 306
             $this->_ticket_quantity_decremented($ticket);
307 307
         }
@@ -321,9 +321,9 @@  discard block
 block discarded – undo
321 321
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
322 322
     {
323 323
         if (self::debug) {
324
-            echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
324
+            echo self::$nl.self::$nl.' . . . INCREASE RESERVED: '.$quantity;
325 325
         }
326
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:' . __LINE__);
326
+        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'.__LINE__);
327 327
         return $ticket->save();
328 328
     }
329 329
 
@@ -337,12 +337,12 @@  discard block
 block discarded – undo
337 337
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
338 338
     {
339 339
         if (self::debug) {
340
-            echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
341
-            echo self::$nl . ' . . . ticket->reserved before: ' . $ticket->reserved();
340
+            echo self::$nl.' . . . ticket->ID: '.$ticket->ID();
341
+            echo self::$nl.' . . . ticket->reserved before: '.$ticket->reserved();
342 342
         }
343
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:' . __LINE__);
343
+        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'.__LINE__);
344 344
         if (self::debug) {
345
-            echo self::$nl . ' . . . ticket->reserved after: ' . $ticket->reserved();
345
+            echo self::$nl.' . . . ticket->reserved after: '.$ticket->reserved();
346 346
         }
347 347
         return $ticket->save() ? 1 : 0;
348 348
     }
@@ -359,8 +359,8 @@  discard block
 block discarded – undo
359 359
     protected function _ticket_sold_out(EE_Ticket $ticket)
360 360
     {
361 361
         if (self::debug) {
362
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
363
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
362
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
363
+            echo self::$nl.' . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
364 364
         }
365 365
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
366 366
     }
@@ -377,8 +377,8 @@  discard block
 block discarded – undo
377 377
     protected function _ticket_quantity_decremented(EE_Ticket $ticket)
378 378
     {
379 379
         if (self::debug) {
380
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
381
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
380
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
381
+            echo self::$nl.' . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
382 382
         }
383 383
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
384 384
     }
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
         if ($ticket instanceof EE_Ticket) {
430 430
             $ticket->add_extra_meta(
431 431
                 EE_Ticket::META_KEY_TICKET_RESERVATIONS,
432
-                __LINE__ . ') ' . __METHOD__ . '()'
432
+                __LINE__.') '.__METHOD__.'()'
433 433
             );
434 434
             if ($quantity > 0) {
435 435
                 EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
     {
453 453
         $ticket->add_extra_meta(
454 454
             EE_Ticket::META_KEY_TICKET_RESERVATIONS,
455
-            __LINE__ . ') ' . __METHOD__ . '()'
455
+            __LINE__.') '.__METHOD__.'()'
456 456
         );
457 457
         EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
458 458
     }
@@ -487,7 +487,7 @@  discard block
 block discarded – undo
487 487
     protected function _post_notices()
488 488
     {
489 489
         if (self::debug) {
490
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
490
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
491 491
         }
492 492
         $refresh_msg = '';
493 493
         $none_added_msg = '';
@@ -498,7 +498,7 @@  discard block
 block discarded – undo
498 498
             );
499 499
             $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
500 500
         }
501
-        if (! empty($this->sold_out_tickets)) {
501
+        if ( ! empty($this->sold_out_tickets)) {
502 502
             EE_Error::add_attention(
503 503
                 sprintf(
504 504
                     apply_filters(
@@ -521,7 +521,7 @@  discard block
 block discarded – undo
521 521
             // and reset the cart
522 522
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
523 523
         }
524
-        if (! empty($this->decremented_tickets)) {
524
+        if ( ! empty($this->decremented_tickets)) {
525 525
             EE_Error::add_attention(
526 526
                 sprintf(
527 527
                     apply_filters(
@@ -558,9 +558,9 @@  discard block
 block discarded – undo
558 558
     protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
559 559
     {
560 560
         if (self::debug) {
561
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
562
-            echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
563
-            echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
561
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
562
+            echo self::$nl.' . transaction->ID: '.$transaction->ID();
563
+            echo self::$nl.' . TXN status_ID: '.$transaction->status_ID();
564 564
         }
565 565
         // check if 'finalize_registration' step has been completed...
566 566
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -572,13 +572,13 @@  discard block
 block discarded – undo
572 572
                 __LINE__,
573 573
                 array('finalized' => $finalized),
574 574
                 false,
575
-                'EE_Transaction: ' . $transaction->ID()
575
+                'EE_Transaction: '.$transaction->ID()
576 576
             );
577 577
         }
578 578
         // how many tickets were released
579 579
         $count = 0;
580 580
         if (self::debug) {
581
-            echo self::$nl . ' . . . TXN finalized: ' . $finalized;
581
+            echo self::$nl.' . . . TXN finalized: '.$finalized;
582 582
         }
583 583
         $release_tickets_with_TXN_status = array(
584 584
             EEM_Transaction::failed_status_code,
@@ -587,27 +587,27 @@  discard block
 block discarded – undo
587 587
         );
588 588
         $events = array();
589 589
         // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
590
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
590
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
591 591
             // cancel any reserved tickets for registrations that were not approved
592 592
             $registrations = $transaction->registrations();
593 593
             if (self::debug) {
594
-                echo self::$nl . ' . . . # registrations: ' . count($registrations);
594
+                echo self::$nl.' . . . # registrations: '.count($registrations);
595 595
                 $reg = reset($registrations);
596 596
                 $ticket = $reg->ticket();
597 597
                 if ($ticket instanceof EE_Ticket) {
598 598
                     $ticket->add_extra_meta(
599 599
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
600
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
600
+                        __LINE__.') Release All Tickets TXN:'.$transaction->ID()
601 601
                     );
602 602
                 }
603 603
             }
604
-            if (! empty($registrations)) {
604
+            if ( ! empty($registrations)) {
605 605
                 foreach ($registrations as $registration) {
606 606
                     if ($registration instanceof EE_Registration
607 607
                         && $this->_release_reserved_ticket_for_registration($registration, $transaction)
608 608
                     ) {
609 609
                         $count++;
610
-                        $events[ $registration->event_ID() ] = $registration->event();
610
+                        $events[$registration->event_ID()] = $registration->event();
611 611
                     }
612 612
                 }
613 613
             }
@@ -637,10 +637,10 @@  discard block
 block discarded – undo
637 637
     ) {
638 638
         $STS_ID = $transaction->status_ID();
639 639
         if (self::debug) {
640
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
641
-            echo self::$nl . ' . . registration->ID: ' . $registration->ID();
642
-            echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
643
-            echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
640
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
641
+            echo self::$nl.' . . registration->ID: '.$registration->ID();
642
+            echo self::$nl.' . . registration->status_ID: '.$registration->status_ID();
643
+            echo self::$nl.' . . transaction->status_ID(): '.$STS_ID;
644 644
         }
645 645
         if (// release Tickets for Failed Transactions and Abandoned Transactions
646 646
             $STS_ID === EEM_Transaction::failed_status_code
@@ -652,12 +652,12 @@  discard block
 block discarded – undo
652 652
             )
653 653
         ) {
654 654
             if (self::debug) {
655
-                echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
655
+                echo self::$nl.self::$nl.' . . RELEASE RESERVED TICKET';
656 656
                 $rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
657
-                echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
657
+                echo self::$nl.' . . . registration HAS_RESERVED_TICKET_KEY: ';
658 658
                 var_dump($rsrvd);
659 659
             }
660
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:' . __LINE__);
660
+            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'.__LINE__);
661 661
             return 1;
662 662
         }
663 663
         return 0;
@@ -686,7 +686,7 @@  discard block
 block discarded – undo
686 686
             return;
687 687
         }
688 688
         if (self::debug) {
689
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
689
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
690 690
         }
691 691
         // first check of the session has a valid Checkout object
692 692
         $checkout = $session->checkout();
@@ -698,12 +698,12 @@  discard block
 block discarded – undo
698 698
         $cart = $session->cart();
699 699
         if ($cart instanceof EE_Cart) {
700 700
             if (self::debug) {
701
-                echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
701
+                echo self::$nl.self::$nl.' cart instance of EE_Cart: ';
702 702
             }
703 703
             EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
704 704
         } else {
705 705
             if (self::debug) {
706
-                echo self::$nl . self::$nl . ' invalid EE_Cart: ';
706
+                echo self::$nl.self::$nl.' invalid EE_Cart: ';
707 707
                 var_export($cart, true);
708 708
             }
709 709
         }
@@ -724,39 +724,39 @@  discard block
 block discarded – undo
724 724
     protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
725 725
     {
726 726
         if (self::debug) {
727
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
727
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
728 728
         }
729 729
         $ticket_line_items = $cart->get_tickets();
730 730
         if (empty($ticket_line_items)) {
731 731
             return;
732 732
         }
733 733
         if (self::debug) {
734
-            echo '<br /> . ticket_line_item count: ' . count($ticket_line_items);
734
+            echo '<br /> . ticket_line_item count: '.count($ticket_line_items);
735 735
         }
736 736
         foreach ($ticket_line_items as $ticket_line_item) {
737 737
             if (self::debug) {
738
-                echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
738
+                echo self::$nl.' . ticket_line_item->ID(): '.$ticket_line_item->ID();
739 739
             }
740 740
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
741 741
                 if (self::debug) {
742
-                    echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
742
+                    echo self::$nl.' . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
743 743
                 }
744 744
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
745 745
                 if ($ticket instanceof EE_Ticket) {
746 746
                     if (self::debug) {
747
-                        echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
748
-                        echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
747
+                        echo self::$nl.' . . ticket->ID(): '.$ticket->ID();
748
+                        echo self::$nl.' . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
749 749
                     }
750 750
                     $ticket->add_extra_meta(
751 751
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
752
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
752
+                        __LINE__.') '.__METHOD__.'() SID = '.$session->id()
753 753
                     );
754 754
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
755 755
                 }
756 756
             }
757 757
         }
758 758
         if (self::debug) {
759
-            echo self::$nl . self::$nl . ' RESET COMPLETED ';
759
+            echo self::$nl.self::$nl.' RESET COMPLETED ';
760 760
         }
761 761
     }
762 762
 
@@ -797,7 +797,7 @@  discard block
 block discarded – undo
797 797
     protected function _session_checkout_reset(EE_Checkout $checkout)
798 798
     {
799 799
         if (self::debug) {
800
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
800
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
801 801
         }
802 802
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
803 803
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -845,7 +845,7 @@  discard block
 block discarded – undo
845 845
                     __LINE__,
846 846
                     array($transaction),
847 847
                     false,
848
-                    'EE_Transaction: ' . $transaction->ID()
848
+                    'EE_Transaction: '.$transaction->ID()
849 849
                 );
850 850
             }
851 851
             return;
@@ -862,7 +862,7 @@  discard block
 block discarded – undo
862 862
                         __LINE__,
863 863
                         array($payment),
864 864
                         false,
865
-                        'EE_Transaction: ' . $transaction->ID()
865
+                        'EE_Transaction: '.$transaction->ID()
866 866
                     );
867 867
                 }
868 868
                 return;
@@ -920,7 +920,7 @@  discard block
 block discarded – undo
920 920
             }
921 921
             $total_line_item = $transaction->total_line_item();
922 922
             // $transaction_in_progress->line
923
-            if (! $total_line_item instanceof EE_Line_Item) {
923
+            if ( ! $total_line_item instanceof EE_Line_Item) {
924 924
                 throw new DomainException(
925 925
                     esc_html__(
926 926
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -979,25 +979,25 @@  discard block
 block discarded – undo
979 979
         $source
980 980
     ) {
981 981
         if (self::debug) {
982
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
982
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
983 983
         }
984 984
         $total_tickets_released = 0;
985 985
         $sold_out_events = array();
986 986
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
987
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
987
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
988 988
                 continue;
989 989
             }
990 990
             $reserved_qty = $ticket_with_reservations->reserved();
991 991
             if (self::debug) {
992
-                echo self::$nl . ' . $ticket_with_reservations->ID(): ' . $ticket_with_reservations->ID();
993
-                echo self::$nl . ' . $reserved_qty: ' . $reserved_qty;
992
+                echo self::$nl.' . $ticket_with_reservations->ID(): '.$ticket_with_reservations->ID();
993
+                echo self::$nl.' . $reserved_qty: '.$reserved_qty;
994 994
             }
995 995
             foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
996 996
                 if ($valid_reserved_ticket_line_item instanceof EE_Line_Item
997 997
                     && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
998 998
                 ) {
999 999
                     if (self::debug) {
1000
-                        echo self::$nl . ' . $valid_reserved_ticket_line_item->quantity(): '
1000
+                        echo self::$nl.' . $valid_reserved_ticket_line_item->quantity(): '
1001 1001
                              . $valid_reserved_ticket_line_item->quantity();
1002 1002
                     }
1003 1003
                     $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
@@ -1006,9 +1006,9 @@  discard block
 block discarded – undo
1006 1006
             if ($reserved_qty > 0) {
1007 1007
                 $ticket_with_reservations->add_extra_meta(
1008 1008
                     EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1009
-                    __LINE__ . ') ' . $source . '()'
1009
+                    __LINE__.') '.$source.'()'
1010 1010
                 );
1011
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:' . __LINE__);
1011
+                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'.__LINE__);
1012 1012
                 $ticket_with_reservations->save();
1013 1013
                 $total_tickets_released += $reserved_qty;
1014 1014
                 $event = $ticket_with_reservations->get_related_event();
@@ -1019,7 +1019,7 @@  discard block
 block discarded – undo
1019 1019
             }
1020 1020
         }
1021 1021
         if (self::debug) {
1022
-            echo self::$nl . ' . $total_tickets_released: ' . $total_tickets_released;
1022
+            echo self::$nl.' . $total_tickets_released: '.$total_tickets_released;
1023 1023
         }
1024 1024
         // double check whether sold out events should remain sold out after releasing tickets
1025 1025
         if ($sold_out_events !== array()) {
@@ -1048,7 +1048,7 @@  discard block
 block discarded – undo
1048 1048
     {
1049 1049
         /** @type WPDB $wpdb */
1050 1050
         global $wpdb;
1051
-        if (! absint($timestamp)) {
1051
+        if ( ! absint($timestamp)) {
1052 1052
             /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1053 1053
             $session_lifespan = LoaderFactory::getLoader()->getShared(
1054 1054
                 'EventEspresso\core\domain\values\session\SessionLifespan'
@@ -1057,7 +1057,7 @@  discard block
 block discarded – undo
1057 1057
         }
1058 1058
         return $wpdb->query(
1059 1059
             $wpdb->prepare(
1060
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1060
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
1061 1061
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1062 1062
                 // use GMT time because that's what LIN_timestamps are in
1063 1063
                 date('Y-m-d H:i:s', $timestamp)
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -622,7 +622,7 @@
 block discarded – undo
622 622
     /**
623 623
      * @param EE_Registration $registration
624 624
      * @param EE_Question     $question
625
-     * @param                 $answer
625
+     * @param                 EE_Answer $answer
626 626
      * @return EE_Form_Input_Base
627 627
      * @throws EE_Error
628 628
      * @throws InvalidArgumentException
Please login to merge, or discard this patch.
Indentation   +1315 added lines, -1315 removed lines patch added patch discarded remove patch
@@ -17,1382 +17,1382 @@
 block discarded – undo
17 17
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step
18 18
 {
19 19
 
20
-    /**
21
-     * @type bool $_print_copy_info
22
-     */
23
-    private $_print_copy_info = false;
20
+	/**
21
+	 * @type bool $_print_copy_info
22
+	 */
23
+	private $_print_copy_info = false;
24 24
 
25
-    /**
26
-     * @type array $_attendee_data
27
-     */
28
-    private $_attendee_data = array();
25
+	/**
26
+	 * @type array $_attendee_data
27
+	 */
28
+	private $_attendee_data = array();
29 29
 
30
-    /**
31
-     * @type array $_required_questions
32
-     */
33
-    private $_required_questions = array();
30
+	/**
31
+	 * @type array $_required_questions
32
+	 */
33
+	private $_required_questions = array();
34 34
 
35
-    /**
36
-     * @type array $_registration_answers
37
-     */
38
-    private $_registration_answers = array();
35
+	/**
36
+	 * @type array $_registration_answers
37
+	 */
38
+	private $_registration_answers = array();
39 39
 
40 40
 
41
-    /**
42
-     *    class constructor
43
-     *
44
-     * @access    public
45
-     * @param    EE_Checkout $checkout
46
-     */
47
-    public function __construct(EE_Checkout $checkout)
48
-    {
49
-        $this->_slug = 'attendee_information';
50
-        $this->_name = esc_html__('Attendee Information', 'event_espresso');
51
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
-        $this->checkout = $checkout;
53
-        $this->_reset_success_message();
54
-        $this->set_instructions(
55
-            esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
-        );
57
-    }
41
+	/**
42
+	 *    class constructor
43
+	 *
44
+	 * @access    public
45
+	 * @param    EE_Checkout $checkout
46
+	 */
47
+	public function __construct(EE_Checkout $checkout)
48
+	{
49
+		$this->_slug = 'attendee_information';
50
+		$this->_name = esc_html__('Attendee Information', 'event_espresso');
51
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
+		$this->checkout = $checkout;
53
+		$this->_reset_success_message();
54
+		$this->set_instructions(
55
+			esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
+		);
57
+	}
58 58
 
59 59
 
60
-    public function translate_js_strings()
61
-    {
62
-        EE_Registry::$i18n_js_strings['required_field'] = esc_html__(
63
-            ' is a required question.',
64
-            'event_espresso'
65
-        );
66
-        EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__(
67
-            ' is a required question. Please enter a value for at least one of the options.',
68
-            'event_espresso'
69
-        );
70
-        EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
-            'Please answer all required questions correctly before proceeding.',
72
-            'event_espresso'
73
-        );
74
-        EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf(
75
-            esc_html_x(
76
-                'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
-                'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
78
-                'event_espresso'
79
-            ),
80
-            '<br/>'
81
-        );
82
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__(
83
-            'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
84
-            'event_espresso'
85
-        );
86
-        EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__(
87
-            'You must enter a valid email address.',
88
-            'event_espresso'
89
-        );
90
-        EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
91
-            'You must enter a valid email address and answer all other required questions before you can proceed.',
92
-            'event_espresso'
93
-        );
94
-    }
60
+	public function translate_js_strings()
61
+	{
62
+		EE_Registry::$i18n_js_strings['required_field'] = esc_html__(
63
+			' is a required question.',
64
+			'event_espresso'
65
+		);
66
+		EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__(
67
+			' is a required question. Please enter a value for at least one of the options.',
68
+			'event_espresso'
69
+		);
70
+		EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
+			'Please answer all required questions correctly before proceeding.',
72
+			'event_espresso'
73
+		);
74
+		EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf(
75
+			esc_html_x(
76
+				'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
+				'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
78
+				'event_espresso'
79
+			),
80
+			'<br/>'
81
+		);
82
+		EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__(
83
+			'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
84
+			'event_espresso'
85
+		);
86
+		EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__(
87
+			'You must enter a valid email address.',
88
+			'event_espresso'
89
+		);
90
+		EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
91
+			'You must enter a valid email address and answer all other required questions before you can proceed.',
92
+			'event_espresso'
93
+		);
94
+	}
95 95
 
96 96
 
97
-    public function enqueue_styles_and_scripts()
98
-    {
99
-    }
97
+	public function enqueue_styles_and_scripts()
98
+	{
99
+	}
100 100
 
101 101
 
102
-    /**
103
-     * @return boolean
104
-     */
105
-    public function initialize_reg_step()
106
-    {
107
-        return true;
108
-    }
102
+	/**
103
+	 * @return boolean
104
+	 */
105
+	public function initialize_reg_step()
106
+	{
107
+		return true;
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * @return EE_Form_Section_Proper
113
-     * @throws DomainException
114
-     * @throws EE_Error
115
-     * @throws InvalidArgumentException
116
-     * @throws ReflectionException
117
-     * @throws EntityNotFoundException
118
-     * @throws InvalidDataTypeException
119
-     * @throws InvalidInterfaceException
120
-     */
121
-    public function generate_reg_form()
122
-    {
123
-        $this->_print_copy_info = false;
124
-        $primary_registrant = null;
125
-        // autoload Line_Item_Display classes
126
-        EEH_Autoloader::register_line_item_display_autoloaders();
127
-        $Line_Item_Display = new EE_Line_Item_Display();
128
-        // calculate taxes
129
-        $Line_Item_Display->display_line_item(
130
-            $this->checkout->cart->get_grand_total(),
131
-            array('set_tax_rate' => true)
132
-        );
133
-        /** @var $subsections EE_Form_Section_Proper[] */
134
-        $subsections = array(
135
-            'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
136
-        );
137
-        $template_args = array(
138
-            'revisit'       => $this->checkout->revisit,
139
-            'registrations' => array(),
140
-            'ticket_count'  => array(),
141
-        );
142
-        // grab the saved registrations from the transaction
143
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
144
-        if ($registrations) {
145
-            foreach ($registrations as $registration) {
146
-                // can this registration be processed during this visit ?
147
-                if ($registration instanceof EE_Registration
148
-                    && $this->checkout->visit_allows_processing_of_this_registration($registration)
149
-                ) {
150
-                    $subsections[ $registration->reg_url_link() ] = $this->_registrations_reg_form($registration);
151
-                    if (! $this->checkout->admin_request) {
152
-                        $template_args['registrations'][ $registration->reg_url_link() ] = $registration;
153
-                        $template_args['ticket_count'][ $registration->ticket()->ID() ] = isset(
154
-                            $template_args['ticket_count'][ $registration->ticket()->ID() ]
155
-                        )
156
-                            ? $template_args['ticket_count'][ $registration->ticket()->ID() ] + 1
157
-                            : 1;
158
-                        $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
159
-                            $this->checkout->cart->get_grand_total(),
160
-                            'Ticket',
161
-                            array($registration->ticket()->ID())
162
-                        );
163
-                        $ticket_line_item = is_array($ticket_line_item)
164
-                            ? reset($ticket_line_item)
165
-                            : $ticket_line_item;
166
-                        $template_args['ticket_line_item'][ $registration->ticket()->ID() ] =
167
-                            $Line_Item_Display->display_line_item($ticket_line_item);
168
-                    }
169
-                    if ($registration->is_primary_registrant()) {
170
-                        $primary_registrant = $registration->reg_url_link();
171
-                    }
172
-                }
173
-            }
174
-            // print_copy_info ?
175
-            if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
176
-                // TODO: add admin option for toggling copy attendee info,
177
-                // then use that value to change $this->_print_copy_info
178
-                $copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
179
-                    ? $this->_copy_attendee_info_form()
180
-                    : $this->_auto_copy_attendee_info();
181
-                // generate hidden input
182
-                if (isset($subsections[ $primary_registrant ])
183
-                    && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
184
-                ) {
185
-                    $subsections[ $primary_registrant ]->add_subsections(
186
-                        $copy_options,
187
-                        'primary_registrant',
188
-                        false
189
-                    );
190
-                }
191
-            }
192
-        }
193
-        return new EE_Form_Section_Proper(
194
-            array(
195
-                'name'            => $this->reg_form_name(),
196
-                'html_id'         => $this->reg_form_name(),
197
-                'subsections'     => $subsections,
198
-                'layout_strategy' => $this->checkout->admin_request
199
-                    ?
200
-                    new EE_Div_Per_Section_Layout()
201
-                    :
202
-                    new EE_Template_Layout(
203
-                        array(
204
-                            'layout_template_file' => $this->_template, // layout_template
205
-                            'template_args'        => $template_args,
206
-                        )
207
-                    ),
208
-            )
209
-        );
210
-    }
111
+	/**
112
+	 * @return EE_Form_Section_Proper
113
+	 * @throws DomainException
114
+	 * @throws EE_Error
115
+	 * @throws InvalidArgumentException
116
+	 * @throws ReflectionException
117
+	 * @throws EntityNotFoundException
118
+	 * @throws InvalidDataTypeException
119
+	 * @throws InvalidInterfaceException
120
+	 */
121
+	public function generate_reg_form()
122
+	{
123
+		$this->_print_copy_info = false;
124
+		$primary_registrant = null;
125
+		// autoload Line_Item_Display classes
126
+		EEH_Autoloader::register_line_item_display_autoloaders();
127
+		$Line_Item_Display = new EE_Line_Item_Display();
128
+		// calculate taxes
129
+		$Line_Item_Display->display_line_item(
130
+			$this->checkout->cart->get_grand_total(),
131
+			array('set_tax_rate' => true)
132
+		);
133
+		/** @var $subsections EE_Form_Section_Proper[] */
134
+		$subsections = array(
135
+			'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
136
+		);
137
+		$template_args = array(
138
+			'revisit'       => $this->checkout->revisit,
139
+			'registrations' => array(),
140
+			'ticket_count'  => array(),
141
+		);
142
+		// grab the saved registrations from the transaction
143
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
144
+		if ($registrations) {
145
+			foreach ($registrations as $registration) {
146
+				// can this registration be processed during this visit ?
147
+				if ($registration instanceof EE_Registration
148
+					&& $this->checkout->visit_allows_processing_of_this_registration($registration)
149
+				) {
150
+					$subsections[ $registration->reg_url_link() ] = $this->_registrations_reg_form($registration);
151
+					if (! $this->checkout->admin_request) {
152
+						$template_args['registrations'][ $registration->reg_url_link() ] = $registration;
153
+						$template_args['ticket_count'][ $registration->ticket()->ID() ] = isset(
154
+							$template_args['ticket_count'][ $registration->ticket()->ID() ]
155
+						)
156
+							? $template_args['ticket_count'][ $registration->ticket()->ID() ] + 1
157
+							: 1;
158
+						$ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
159
+							$this->checkout->cart->get_grand_total(),
160
+							'Ticket',
161
+							array($registration->ticket()->ID())
162
+						);
163
+						$ticket_line_item = is_array($ticket_line_item)
164
+							? reset($ticket_line_item)
165
+							: $ticket_line_item;
166
+						$template_args['ticket_line_item'][ $registration->ticket()->ID() ] =
167
+							$Line_Item_Display->display_line_item($ticket_line_item);
168
+					}
169
+					if ($registration->is_primary_registrant()) {
170
+						$primary_registrant = $registration->reg_url_link();
171
+					}
172
+				}
173
+			}
174
+			// print_copy_info ?
175
+			if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
176
+				// TODO: add admin option for toggling copy attendee info,
177
+				// then use that value to change $this->_print_copy_info
178
+				$copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
179
+					? $this->_copy_attendee_info_form()
180
+					: $this->_auto_copy_attendee_info();
181
+				// generate hidden input
182
+				if (isset($subsections[ $primary_registrant ])
183
+					&& $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
184
+				) {
185
+					$subsections[ $primary_registrant ]->add_subsections(
186
+						$copy_options,
187
+						'primary_registrant',
188
+						false
189
+					);
190
+				}
191
+			}
192
+		}
193
+		return new EE_Form_Section_Proper(
194
+			array(
195
+				'name'            => $this->reg_form_name(),
196
+				'html_id'         => $this->reg_form_name(),
197
+				'subsections'     => $subsections,
198
+				'layout_strategy' => $this->checkout->admin_request
199
+					?
200
+					new EE_Div_Per_Section_Layout()
201
+					:
202
+					new EE_Template_Layout(
203
+						array(
204
+							'layout_template_file' => $this->_template, // layout_template
205
+							'template_args'        => $template_args,
206
+						)
207
+					),
208
+			)
209
+		);
210
+	}
211 211
 
212 212
 
213
-    /**
214
-     * @param EE_Registration $registration
215
-     * @return EE_Form_Section_Base
216
-     * @throws EE_Error
217
-     * @throws InvalidArgumentException
218
-     * @throws EntityNotFoundException
219
-     * @throws InvalidDataTypeException
220
-     * @throws InvalidInterfaceException
221
-     * @throws ReflectionException
222
-     */
223
-    private function _registrations_reg_form(EE_Registration $registration)
224
-    {
225
-        static $attendee_nmbr = 1;
226
-        $form_args = array();
227
-        // verify that registration has valid event
228
-        if ($registration->event() instanceof EE_Event) {
229
-            $question_groups = $registration->event()->question_groups(
230
-                apply_filters(
231
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
232
-                    array(
233
-                        array(
234
-                            'Event.EVT_ID'                     => $registration->event()->ID(),
235
-                            'Event_Question_Group.EQG_primary' => $registration->count() === 1,
236
-                        ),
237
-                        'order_by' => array('QSG_order' => 'ASC'),
238
-                    ),
239
-                    $registration,
240
-                    $this
241
-                )
242
-            );
243
-            if ($question_groups) {
244
-                // array of params to pass to parent constructor
245
-                $form_args = array(
246
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
247
-                    'html_class'      => 'ee-reg-form-attendee-dv',
248
-                    'html_style'      => $this->checkout->admin_request
249
-                        ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
250
-                        : '',
251
-                    'subsections'     => array(),
252
-                    'layout_strategy' => new EE_Fieldset_Section_Layout(
253
-                        array(
254
-                            'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
255
-                            'legend_text'  => sprintf(
256
-                                esc_html_x(
257
-                                    'Attendee %d',
258
-                                    'Attendee 123',
259
-                                    'event_espresso'
260
-                                ),
261
-                                $attendee_nmbr
262
-                            ),
263
-                        )
264
-                    ),
265
-                );
266
-                foreach ($question_groups as $question_group) {
267
-                    if ($question_group instanceof EE_Question_Group) {
268
-                        $form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
269
-                            $registration,
270
-                            $question_group
271
-                        );
272
-                    }
273
-                }
274
-                // add hidden input
275
-                $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
276
-                    $registration
277
-                );
278
-                // if we have question groups for additional attendees, then display the copy options
279
-                $this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
280
-                if ($registration->is_primary_registrant()) {
281
-                    // generate hidden input
282
-                    $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
283
-                        $registration
284
-                    );
285
-                }
286
-            }
287
-        }
288
-        $attendee_nmbr++;
289
-        return ! empty($form_args)
290
-            ? new EE_Form_Section_Proper($form_args)
291
-            : new EE_Form_Section_HTML();
292
-    }
213
+	/**
214
+	 * @param EE_Registration $registration
215
+	 * @return EE_Form_Section_Base
216
+	 * @throws EE_Error
217
+	 * @throws InvalidArgumentException
218
+	 * @throws EntityNotFoundException
219
+	 * @throws InvalidDataTypeException
220
+	 * @throws InvalidInterfaceException
221
+	 * @throws ReflectionException
222
+	 */
223
+	private function _registrations_reg_form(EE_Registration $registration)
224
+	{
225
+		static $attendee_nmbr = 1;
226
+		$form_args = array();
227
+		// verify that registration has valid event
228
+		if ($registration->event() instanceof EE_Event) {
229
+			$question_groups = $registration->event()->question_groups(
230
+				apply_filters(
231
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
232
+					array(
233
+						array(
234
+							'Event.EVT_ID'                     => $registration->event()->ID(),
235
+							'Event_Question_Group.EQG_primary' => $registration->count() === 1,
236
+						),
237
+						'order_by' => array('QSG_order' => 'ASC'),
238
+					),
239
+					$registration,
240
+					$this
241
+				)
242
+			);
243
+			if ($question_groups) {
244
+				// array of params to pass to parent constructor
245
+				$form_args = array(
246
+					'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
247
+					'html_class'      => 'ee-reg-form-attendee-dv',
248
+					'html_style'      => $this->checkout->admin_request
249
+						? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
250
+						: '',
251
+					'subsections'     => array(),
252
+					'layout_strategy' => new EE_Fieldset_Section_Layout(
253
+						array(
254
+							'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
255
+							'legend_text'  => sprintf(
256
+								esc_html_x(
257
+									'Attendee %d',
258
+									'Attendee 123',
259
+									'event_espresso'
260
+								),
261
+								$attendee_nmbr
262
+							),
263
+						)
264
+					),
265
+				);
266
+				foreach ($question_groups as $question_group) {
267
+					if ($question_group instanceof EE_Question_Group) {
268
+						$form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
269
+							$registration,
270
+							$question_group
271
+						);
272
+					}
273
+				}
274
+				// add hidden input
275
+				$form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
276
+					$registration
277
+				);
278
+				// if we have question groups for additional attendees, then display the copy options
279
+				$this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
280
+				if ($registration->is_primary_registrant()) {
281
+					// generate hidden input
282
+					$form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
283
+						$registration
284
+					);
285
+				}
286
+			}
287
+		}
288
+		$attendee_nmbr++;
289
+		return ! empty($form_args)
290
+			? new EE_Form_Section_Proper($form_args)
291
+			: new EE_Form_Section_HTML();
292
+	}
293 293
 
294 294
 
295
-    /**
296
-     * @param EE_Registration $registration
297
-     * @param bool            $additional_attendee_reg_info
298
-     * @return EE_Form_Input_Base
299
-     * @throws EE_Error
300
-     */
301
-    private function _additional_attendee_reg_info_input(
302
-        EE_Registration $registration,
303
-        $additional_attendee_reg_info = true
304
-    ) {
305
-        // generate hidden input
306
-        return new EE_Hidden_Input(
307
-            array(
308
-                'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
309
-                'default' => $additional_attendee_reg_info,
310
-            )
311
-        );
312
-    }
295
+	/**
296
+	 * @param EE_Registration $registration
297
+	 * @param bool            $additional_attendee_reg_info
298
+	 * @return EE_Form_Input_Base
299
+	 * @throws EE_Error
300
+	 */
301
+	private function _additional_attendee_reg_info_input(
302
+		EE_Registration $registration,
303
+		$additional_attendee_reg_info = true
304
+	) {
305
+		// generate hidden input
306
+		return new EE_Hidden_Input(
307
+			array(
308
+				'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
309
+				'default' => $additional_attendee_reg_info,
310
+			)
311
+		);
312
+	}
313 313
 
314 314
 
315
-    /**
316
-     * @param EE_Registration   $registration
317
-     * @param EE_Question_Group $question_group
318
-     * @return EE_Form_Section_Proper
319
-     * @throws EE_Error
320
-     * @throws InvalidArgumentException
321
-     * @throws InvalidDataTypeException
322
-     * @throws InvalidInterfaceException
323
-     * @throws ReflectionException
324
-     */
325
-    private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
326
-    {
327
-        // array of params to pass to parent constructor
328
-        $form_args = array(
329
-            'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(),
330
-            'html_class'      => $this->checkout->admin_request
331
-                ? 'form-table ee-reg-form-qstn-grp-dv'
332
-                : 'ee-reg-form-qstn-grp-dv',
333
-            'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-'
334
-                                 . $registration->ID() . '-lbl',
335
-            'subsections'     => array(
336
-                'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
337
-            ),
338
-            'layout_strategy' => $this->checkout->admin_request
339
-                ? new EE_Admin_Two_Column_Layout()
340
-                : new EE_Div_Per_Section_Layout(),
341
-        );
342
-        // where params
343
-        $query_params = array('QST_deleted' => 0);
344
-        // don't load admin only questions on the frontend
345
-        if (! $this->checkout->admin_request) {
346
-            $query_params['QST_admin_only'] = array('!=', true);
347
-        }
348
-        $questions = $question_group->get_many_related(
349
-            'Question',
350
-            apply_filters(
351
-                'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
352
-                array(
353
-                    $query_params,
354
-                    'order_by' => array(
355
-                        'Question_Group_Question.QGQ_order' => 'ASC',
356
-                    ),
357
-                ),
358
-                $question_group,
359
-                $registration,
360
-                $this
361
-            )
362
-        );
363
-        // filter for additional content before questions
364
-        $form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
365
-            apply_filters(
366
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
367
-                '',
368
-                $registration,
369
-                $question_group,
370
-                $this
371
-            )
372
-        );
373
-        // loop thru questions
374
-        foreach ($questions as $question) {
375
-            if ($question instanceof EE_Question) {
376
-                $identifier = $question->is_system_question()
377
-                    ? $question->system_ID()
378
-                    : $question->ID();
379
-                $form_args['subsections'][ $identifier ] = $this->reg_form_question($registration, $question);
380
-            }
381
-        }
382
-        $form_args['subsections'] = apply_filters(
383
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
384
-            $form_args['subsections'],
385
-            $registration,
386
-            $question_group,
387
-            $this
388
-        );
389
-        // filter for additional content after questions
390
-        $form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
391
-            apply_filters(
392
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
393
-                '',
394
-                $registration,
395
-                $question_group,
396
-                $this
397
-            )
398
-        );
399
-        // d($form_args);
400
-        $question_group_reg_form = new EE_Form_Section_Proper($form_args);
401
-        return apply_filters(
402
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
403
-            $question_group_reg_form,
404
-            $registration,
405
-            $question_group,
406
-            $this
407
-        );
408
-    }
315
+	/**
316
+	 * @param EE_Registration   $registration
317
+	 * @param EE_Question_Group $question_group
318
+	 * @return EE_Form_Section_Proper
319
+	 * @throws EE_Error
320
+	 * @throws InvalidArgumentException
321
+	 * @throws InvalidDataTypeException
322
+	 * @throws InvalidInterfaceException
323
+	 * @throws ReflectionException
324
+	 */
325
+	private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
326
+	{
327
+		// array of params to pass to parent constructor
328
+		$form_args = array(
329
+			'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(),
330
+			'html_class'      => $this->checkout->admin_request
331
+				? 'form-table ee-reg-form-qstn-grp-dv'
332
+				: 'ee-reg-form-qstn-grp-dv',
333
+			'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-'
334
+								 . $registration->ID() . '-lbl',
335
+			'subsections'     => array(
336
+				'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
337
+			),
338
+			'layout_strategy' => $this->checkout->admin_request
339
+				? new EE_Admin_Two_Column_Layout()
340
+				: new EE_Div_Per_Section_Layout(),
341
+		);
342
+		// where params
343
+		$query_params = array('QST_deleted' => 0);
344
+		// don't load admin only questions on the frontend
345
+		if (! $this->checkout->admin_request) {
346
+			$query_params['QST_admin_only'] = array('!=', true);
347
+		}
348
+		$questions = $question_group->get_many_related(
349
+			'Question',
350
+			apply_filters(
351
+				'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
352
+				array(
353
+					$query_params,
354
+					'order_by' => array(
355
+						'Question_Group_Question.QGQ_order' => 'ASC',
356
+					),
357
+				),
358
+				$question_group,
359
+				$registration,
360
+				$this
361
+			)
362
+		);
363
+		// filter for additional content before questions
364
+		$form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
365
+			apply_filters(
366
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
367
+				'',
368
+				$registration,
369
+				$question_group,
370
+				$this
371
+			)
372
+		);
373
+		// loop thru questions
374
+		foreach ($questions as $question) {
375
+			if ($question instanceof EE_Question) {
376
+				$identifier = $question->is_system_question()
377
+					? $question->system_ID()
378
+					: $question->ID();
379
+				$form_args['subsections'][ $identifier ] = $this->reg_form_question($registration, $question);
380
+			}
381
+		}
382
+		$form_args['subsections'] = apply_filters(
383
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
384
+			$form_args['subsections'],
385
+			$registration,
386
+			$question_group,
387
+			$this
388
+		);
389
+		// filter for additional content after questions
390
+		$form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
391
+			apply_filters(
392
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
393
+				'',
394
+				$registration,
395
+				$question_group,
396
+				$this
397
+			)
398
+		);
399
+		// d($form_args);
400
+		$question_group_reg_form = new EE_Form_Section_Proper($form_args);
401
+		return apply_filters(
402
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
403
+			$question_group_reg_form,
404
+			$registration,
405
+			$question_group,
406
+			$this
407
+		);
408
+	}
409 409
 
410 410
 
411
-    /**
412
-     * @param EE_Question_Group $question_group
413
-     * @return    EE_Form_Section_HTML
414
-     */
415
-    private function _question_group_header(EE_Question_Group $question_group)
416
-    {
417
-        $html = '';
418
-        // group_name
419
-        if ($question_group->show_group_name() && $question_group->name() !== '') {
420
-            if ($this->checkout->admin_request) {
421
-                $html .= EEH_HTML::br();
422
-                $html .= EEH_HTML::h3(
423
-                    $question_group->name(),
424
-                    '',
425
-                    'ee-reg-form-qstn-grp-title title',
426
-                    'font-size: 1.3em; padding-left:0;'
427
-                );
428
-            } else {
429
-                $html .= EEH_HTML::h4(
430
-                    $question_group->name(),
431
-                    '',
432
-                    'ee-reg-form-qstn-grp-title section-title'
433
-                );
434
-            }
435
-        }
436
-        // group_desc
437
-        if ($question_group->show_group_desc() && $question_group->desc() !== '') {
438
-            $html .= EEH_HTML::p(
439
-                $question_group->desc(),
440
-                '',
441
-                $this->checkout->admin_request
442
-                    ? 'ee-reg-form-qstn-grp-desc-pg'
443
-                    : 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
444
-            );
445
-        }
446
-        return new EE_Form_Section_HTML($html);
447
-    }
411
+	/**
412
+	 * @param EE_Question_Group $question_group
413
+	 * @return    EE_Form_Section_HTML
414
+	 */
415
+	private function _question_group_header(EE_Question_Group $question_group)
416
+	{
417
+		$html = '';
418
+		// group_name
419
+		if ($question_group->show_group_name() && $question_group->name() !== '') {
420
+			if ($this->checkout->admin_request) {
421
+				$html .= EEH_HTML::br();
422
+				$html .= EEH_HTML::h3(
423
+					$question_group->name(),
424
+					'',
425
+					'ee-reg-form-qstn-grp-title title',
426
+					'font-size: 1.3em; padding-left:0;'
427
+				);
428
+			} else {
429
+				$html .= EEH_HTML::h4(
430
+					$question_group->name(),
431
+					'',
432
+					'ee-reg-form-qstn-grp-title section-title'
433
+				);
434
+			}
435
+		}
436
+		// group_desc
437
+		if ($question_group->show_group_desc() && $question_group->desc() !== '') {
438
+			$html .= EEH_HTML::p(
439
+				$question_group->desc(),
440
+				'',
441
+				$this->checkout->admin_request
442
+					? 'ee-reg-form-qstn-grp-desc-pg'
443
+					: 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
444
+			);
445
+		}
446
+		return new EE_Form_Section_HTML($html);
447
+	}
448 448
 
449 449
 
450
-    /**
451
-     * @return    EE_Form_Section_Proper
452
-     * @throws EE_Error
453
-     * @throws InvalidArgumentException
454
-     * @throws ReflectionException
455
-     * @throws InvalidDataTypeException
456
-     * @throws InvalidInterfaceException
457
-     */
458
-    private function _copy_attendee_info_form()
459
-    {
460
-        // array of params to pass to parent constructor
461
-        return new EE_Form_Section_Proper(
462
-            array(
463
-                'subsections'     => $this->_copy_attendee_info_inputs(),
464
-                'layout_strategy' => new EE_Template_Layout(
465
-                    array(
466
-                        'layout_template_file'     => SPCO_REG_STEPS_PATH
467
-                                                      . $this->_slug
468
-                                                      . DS
469
-                                                      . 'copy_attendee_info.template.php',
470
-                        'begin_template_file'      => null,
471
-                        'input_template_file'      => null,
472
-                        'subsection_template_file' => null,
473
-                        'end_template_file'        => null,
474
-                    )
475
-                ),
476
-            )
477
-        );
478
-    }
450
+	/**
451
+	 * @return    EE_Form_Section_Proper
452
+	 * @throws EE_Error
453
+	 * @throws InvalidArgumentException
454
+	 * @throws ReflectionException
455
+	 * @throws InvalidDataTypeException
456
+	 * @throws InvalidInterfaceException
457
+	 */
458
+	private function _copy_attendee_info_form()
459
+	{
460
+		// array of params to pass to parent constructor
461
+		return new EE_Form_Section_Proper(
462
+			array(
463
+				'subsections'     => $this->_copy_attendee_info_inputs(),
464
+				'layout_strategy' => new EE_Template_Layout(
465
+					array(
466
+						'layout_template_file'     => SPCO_REG_STEPS_PATH
467
+													  . $this->_slug
468
+													  . DS
469
+													  . 'copy_attendee_info.template.php',
470
+						'begin_template_file'      => null,
471
+						'input_template_file'      => null,
472
+						'subsection_template_file' => null,
473
+						'end_template_file'        => null,
474
+					)
475
+				),
476
+			)
477
+		);
478
+	}
479 479
 
480 480
 
481
-    /**
482
-     * @return EE_Form_Section_HTML
483
-     * @throws DomainException
484
-     * @throws InvalidArgumentException
485
-     * @throws InvalidDataTypeException
486
-     * @throws InvalidInterfaceException
487
-     */
488
-    private function _auto_copy_attendee_info()
489
-    {
490
-        return new EE_Form_Section_HTML(
491
-            EEH_Template::locate_template(
492
-                SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
493
-                apply_filters(
494
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
495
-                    array()
496
-                ),
497
-                true,
498
-                true
499
-            )
500
-        );
501
-    }
481
+	/**
482
+	 * @return EE_Form_Section_HTML
483
+	 * @throws DomainException
484
+	 * @throws InvalidArgumentException
485
+	 * @throws InvalidDataTypeException
486
+	 * @throws InvalidInterfaceException
487
+	 */
488
+	private function _auto_copy_attendee_info()
489
+	{
490
+		return new EE_Form_Section_HTML(
491
+			EEH_Template::locate_template(
492
+				SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
493
+				apply_filters(
494
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
495
+					array()
496
+				),
497
+				true,
498
+				true
499
+			)
500
+		);
501
+	}
502 502
 
503 503
 
504
-    /**
505
-     * @return array
506
-     * @throws EE_Error
507
-     * @throws InvalidArgumentException
508
-     * @throws ReflectionException
509
-     * @throws InvalidDataTypeException
510
-     * @throws InvalidInterfaceException
511
-     */
512
-    private function _copy_attendee_info_inputs()
513
-    {
514
-        $copy_attendee_info_inputs = array();
515
-        $prev_ticket = null;
516
-        // grab the saved registrations from the transaction
517
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
518
-        foreach ($registrations as $registration) {
519
-            // for all  attendees other than the primary attendee
520
-            if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
521
-                // if this is a new ticket OR if this is the very first additional attendee after the primary attendee
522
-                if ($registration->ticket()->ID() !== $prev_ticket) {
523
-                    $item_name = $registration->ticket()->name();
524
-                    $item_name .= $registration->ticket()->description() !== ''
525
-                        ? ' - ' . $registration->ticket()->description()
526
-                        : '';
527
-                    $copy_attendee_info_inputs[ 'spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']' ] =
528
-                        new EE_Form_Section_HTML(
529
-                            '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
530
-                        );
531
-                    $prev_ticket = $registration->ticket()->ID();
532
-                }
504
+	/**
505
+	 * @return array
506
+	 * @throws EE_Error
507
+	 * @throws InvalidArgumentException
508
+	 * @throws ReflectionException
509
+	 * @throws InvalidDataTypeException
510
+	 * @throws InvalidInterfaceException
511
+	 */
512
+	private function _copy_attendee_info_inputs()
513
+	{
514
+		$copy_attendee_info_inputs = array();
515
+		$prev_ticket = null;
516
+		// grab the saved registrations from the transaction
517
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
518
+		foreach ($registrations as $registration) {
519
+			// for all  attendees other than the primary attendee
520
+			if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
521
+				// if this is a new ticket OR if this is the very first additional attendee after the primary attendee
522
+				if ($registration->ticket()->ID() !== $prev_ticket) {
523
+					$item_name = $registration->ticket()->name();
524
+					$item_name .= $registration->ticket()->description() !== ''
525
+						? ' - ' . $registration->ticket()->description()
526
+						: '';
527
+					$copy_attendee_info_inputs[ 'spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']' ] =
528
+						new EE_Form_Section_HTML(
529
+							'<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
530
+						);
531
+					$prev_ticket = $registration->ticket()->ID();
532
+				}
533 533
 
534
-                $copy_attendee_info_inputs[ 'spco_copy_attendee_chk[' . $registration->ID() . ']' ] =
535
-                    new EE_Checkbox_Multi_Input(
536
-                        array(
537
-                            $registration->ID() => sprintf(
538
-                                esc_html_x('Attendee #%s', 'Attendee #123', 'event_espresso'),
539
-                                $registration->count()
540
-                            ),
541
-                        ),
542
-                        array(
543
-                            'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
544
-                            'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
545
-                            'display_html_label_text' => false,
546
-                        )
547
-                    );
548
-            }
549
-        }
550
-        return $copy_attendee_info_inputs;
551
-    }
534
+				$copy_attendee_info_inputs[ 'spco_copy_attendee_chk[' . $registration->ID() . ']' ] =
535
+					new EE_Checkbox_Multi_Input(
536
+						array(
537
+							$registration->ID() => sprintf(
538
+								esc_html_x('Attendee #%s', 'Attendee #123', 'event_espresso'),
539
+								$registration->count()
540
+							),
541
+						),
542
+						array(
543
+							'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
544
+							'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
545
+							'display_html_label_text' => false,
546
+						)
547
+					);
548
+			}
549
+		}
550
+		return $copy_attendee_info_inputs;
551
+	}
552 552
 
553 553
 
554
-    /**
555
-     * @param EE_Registration $registration
556
-     * @return    EE_Form_Input_Base
557
-     * @throws EE_Error
558
-     */
559
-    private function _additional_primary_registrant_inputs(EE_Registration $registration)
560
-    {
561
-        // generate hidden input
562
-        return new EE_Hidden_Input(
563
-            array(
564
-                'html_id' => 'primary_registrant',
565
-                'default' => $registration->reg_url_link(),
566
-            )
567
-        );
568
-    }
554
+	/**
555
+	 * @param EE_Registration $registration
556
+	 * @return    EE_Form_Input_Base
557
+	 * @throws EE_Error
558
+	 */
559
+	private function _additional_primary_registrant_inputs(EE_Registration $registration)
560
+	{
561
+		// generate hidden input
562
+		return new EE_Hidden_Input(
563
+			array(
564
+				'html_id' => 'primary_registrant',
565
+				'default' => $registration->reg_url_link(),
566
+			)
567
+		);
568
+	}
569 569
 
570 570
 
571
-    /**
572
-     * @param EE_Registration $registration
573
-     * @param EE_Question     $question
574
-     * @return EE_Form_Input_Base
575
-     * @throws EE_Error
576
-     * @throws InvalidArgumentException
577
-     * @throws InvalidDataTypeException
578
-     * @throws InvalidInterfaceException
579
-     * @throws ReflectionException
580
-     */
581
-    public function reg_form_question(EE_Registration $registration, EE_Question $question)
582
-    {
571
+	/**
572
+	 * @param EE_Registration $registration
573
+	 * @param EE_Question     $question
574
+	 * @return EE_Form_Input_Base
575
+	 * @throws EE_Error
576
+	 * @throws InvalidArgumentException
577
+	 * @throws InvalidDataTypeException
578
+	 * @throws InvalidInterfaceException
579
+	 * @throws ReflectionException
580
+	 */
581
+	public function reg_form_question(EE_Registration $registration, EE_Question $question)
582
+	{
583 583
 
584
-        // if this question was for an attendee detail, then check for that answer
585
-        $answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
586
-            $registration,
587
-            $question->system_ID()
588
-        );
589
-        $answer = $answer_value === null
590
-            ? EEM_Answer::instance()->get_one(
591
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
592
-            )
593
-            : null;
594
-        // if NOT returning to edit an existing registration
595
-        // OR if this question is for an attendee property
596
-        // OR we still don't have an EE_Answer object
597
-        if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
598
-            // create an EE_Answer object for storing everything in
599
-            $answer = EE_Answer::new_instance(
600
-                array(
601
-                    'QST_ID' => $question->ID(),
602
-                    'REG_ID' => $registration->ID(),
603
-                )
604
-            );
605
-        }
606
-        // verify instance
607
-        if ($answer instanceof EE_Answer) {
608
-            if (! empty($answer_value)) {
609
-                $answer->set('ANS_value', $answer_value);
610
-            }
611
-            $answer->cache('Question', $question);
612
-            // remember system ID had a bug where sometimes it could be null
613
-            $answer_cache_id = $question->is_system_question()
614
-                ? $question->system_ID() . '-' . $registration->reg_url_link()
615
-                : $question->ID() . '-' . $registration->reg_url_link();
616
-            $registration->cache('Answer', $answer, $answer_cache_id);
617
-        }
618
-        return $this->_generate_question_input($registration, $question, $answer);
619
-    }
584
+		// if this question was for an attendee detail, then check for that answer
585
+		$answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
586
+			$registration,
587
+			$question->system_ID()
588
+		);
589
+		$answer = $answer_value === null
590
+			? EEM_Answer::instance()->get_one(
591
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
592
+			)
593
+			: null;
594
+		// if NOT returning to edit an existing registration
595
+		// OR if this question is for an attendee property
596
+		// OR we still don't have an EE_Answer object
597
+		if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
598
+			// create an EE_Answer object for storing everything in
599
+			$answer = EE_Answer::new_instance(
600
+				array(
601
+					'QST_ID' => $question->ID(),
602
+					'REG_ID' => $registration->ID(),
603
+				)
604
+			);
605
+		}
606
+		// verify instance
607
+		if ($answer instanceof EE_Answer) {
608
+			if (! empty($answer_value)) {
609
+				$answer->set('ANS_value', $answer_value);
610
+			}
611
+			$answer->cache('Question', $question);
612
+			// remember system ID had a bug where sometimes it could be null
613
+			$answer_cache_id = $question->is_system_question()
614
+				? $question->system_ID() . '-' . $registration->reg_url_link()
615
+				: $question->ID() . '-' . $registration->reg_url_link();
616
+			$registration->cache('Answer', $answer, $answer_cache_id);
617
+		}
618
+		return $this->_generate_question_input($registration, $question, $answer);
619
+	}
620 620
 
621 621
 
622
-    /**
623
-     * @param EE_Registration $registration
624
-     * @param EE_Question     $question
625
-     * @param                 $answer
626
-     * @return EE_Form_Input_Base
627
-     * @throws EE_Error
628
-     * @throws InvalidArgumentException
629
-     * @throws ReflectionException
630
-     * @throws InvalidDataTypeException
631
-     * @throws InvalidInterfaceException
632
-     */
633
-    private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
634
-    {
635
-        $identifier = $question->is_system_question()
636
-            ? $question->system_ID()
637
-            : $question->ID();
638
-        $this->_required_questions[ $identifier ] = $question->required() ? true : false;
639
-        add_filter(
640
-            'FHEE__EE_Question__generate_form_input__country_options',
641
-            array($this, 'use_cached_countries_for_form_input'),
642
-            10,
643
-            4
644
-        );
645
-        add_filter(
646
-            'FHEE__EE_Question__generate_form_input__state_options',
647
-            array($this, 'use_cached_states_for_form_input'),
648
-            10,
649
-            4
650
-        );
651
-        $input_constructor_args = array(
652
-            'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
653
-            'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
654
-            'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
655
-            'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
656
-            'html_label_class' => 'ee-reg-qstn',
657
-        );
658
-        $input_constructor_args['html_label_id'] .= '-lbl';
659
-        if ($answer instanceof EE_Answer && $answer->ID()) {
660
-            $input_constructor_args['html_name'] .= '[' . $answer->ID() . ']';
661
-            $input_constructor_args['html_id'] .= '-' . $answer->ID();
662
-            $input_constructor_args['html_label_id'] .= '-' . $answer->ID();
663
-        }
664
-        $form_input = $question->generate_form_input(
665
-            $registration,
666
-            $answer,
667
-            $input_constructor_args
668
-        );
669
-        remove_filter(
670
-            'FHEE__EE_Question__generate_form_input__country_options',
671
-            array($this, 'use_cached_countries_for_form_input')
672
-        );
673
-        remove_filter(
674
-            'FHEE__EE_Question__generate_form_input__state_options',
675
-            array($this, 'use_cached_states_for_form_input')
676
-        );
677
-        return $form_input;
678
-    }
622
+	/**
623
+	 * @param EE_Registration $registration
624
+	 * @param EE_Question     $question
625
+	 * @param                 $answer
626
+	 * @return EE_Form_Input_Base
627
+	 * @throws EE_Error
628
+	 * @throws InvalidArgumentException
629
+	 * @throws ReflectionException
630
+	 * @throws InvalidDataTypeException
631
+	 * @throws InvalidInterfaceException
632
+	 */
633
+	private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
634
+	{
635
+		$identifier = $question->is_system_question()
636
+			? $question->system_ID()
637
+			: $question->ID();
638
+		$this->_required_questions[ $identifier ] = $question->required() ? true : false;
639
+		add_filter(
640
+			'FHEE__EE_Question__generate_form_input__country_options',
641
+			array($this, 'use_cached_countries_for_form_input'),
642
+			10,
643
+			4
644
+		);
645
+		add_filter(
646
+			'FHEE__EE_Question__generate_form_input__state_options',
647
+			array($this, 'use_cached_states_for_form_input'),
648
+			10,
649
+			4
650
+		);
651
+		$input_constructor_args = array(
652
+			'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
653
+			'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
654
+			'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
655
+			'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
656
+			'html_label_class' => 'ee-reg-qstn',
657
+		);
658
+		$input_constructor_args['html_label_id'] .= '-lbl';
659
+		if ($answer instanceof EE_Answer && $answer->ID()) {
660
+			$input_constructor_args['html_name'] .= '[' . $answer->ID() . ']';
661
+			$input_constructor_args['html_id'] .= '-' . $answer->ID();
662
+			$input_constructor_args['html_label_id'] .= '-' . $answer->ID();
663
+		}
664
+		$form_input = $question->generate_form_input(
665
+			$registration,
666
+			$answer,
667
+			$input_constructor_args
668
+		);
669
+		remove_filter(
670
+			'FHEE__EE_Question__generate_form_input__country_options',
671
+			array($this, 'use_cached_countries_for_form_input')
672
+		);
673
+		remove_filter(
674
+			'FHEE__EE_Question__generate_form_input__state_options',
675
+			array($this, 'use_cached_states_for_form_input')
676
+		);
677
+		return $form_input;
678
+	}
679 679
 
680 680
 
681
-    /**
682
-     * Gets the list of countries for the form input
683
-     *
684
-     * @param array|null      $countries_list
685
-     * @param EE_Question     $question
686
-     * @param EE_Registration $registration
687
-     * @param EE_Answer       $answer
688
-     * @return array 2d keys are country IDs, values are their names
689
-     * @throws EE_Error
690
-     * @throws InvalidArgumentException
691
-     * @throws InvalidDataTypeException
692
-     * @throws InvalidInterfaceException
693
-     * @throws ReflectionException
694
-     */
695
-    public function use_cached_countries_for_form_input(
696
-        $countries_list,
697
-        EE_Question $question = null,
698
-        EE_Registration $registration = null,
699
-        EE_Answer $answer = null
700
-    ) {
701
-        $country_options = array('' => '');
702
-        // get possibly cached list of countries
703
-        $countries = $this->checkout->action === 'process_reg_step'
704
-            ? EEM_Country::instance()->get_all_countries()
705
-            : EEM_Country::instance()->get_all_active_countries();
706
-        if (! empty($countries)) {
707
-            foreach ($countries as $country) {
708
-                if ($country instanceof EE_Country) {
709
-                    $country_options[ $country->ID() ] = $country->name();
710
-                }
711
-            }
712
-        }
713
-        if ($question instanceof EE_Question && $registration instanceof EE_Registration) {
714
-            $answer = EEM_Answer::instance()->get_one(
715
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
716
-            );
717
-        } else {
718
-            $answer = EE_Answer::new_instance();
719
-        }
720
-        $country_options = apply_filters(
721
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
722
-            $country_options,
723
-            $this,
724
-            $registration,
725
-            $question,
726
-            $answer
727
-        );
728
-        return $country_options;
729
-    }
681
+	/**
682
+	 * Gets the list of countries for the form input
683
+	 *
684
+	 * @param array|null      $countries_list
685
+	 * @param EE_Question     $question
686
+	 * @param EE_Registration $registration
687
+	 * @param EE_Answer       $answer
688
+	 * @return array 2d keys are country IDs, values are their names
689
+	 * @throws EE_Error
690
+	 * @throws InvalidArgumentException
691
+	 * @throws InvalidDataTypeException
692
+	 * @throws InvalidInterfaceException
693
+	 * @throws ReflectionException
694
+	 */
695
+	public function use_cached_countries_for_form_input(
696
+		$countries_list,
697
+		EE_Question $question = null,
698
+		EE_Registration $registration = null,
699
+		EE_Answer $answer = null
700
+	) {
701
+		$country_options = array('' => '');
702
+		// get possibly cached list of countries
703
+		$countries = $this->checkout->action === 'process_reg_step'
704
+			? EEM_Country::instance()->get_all_countries()
705
+			: EEM_Country::instance()->get_all_active_countries();
706
+		if (! empty($countries)) {
707
+			foreach ($countries as $country) {
708
+				if ($country instanceof EE_Country) {
709
+					$country_options[ $country->ID() ] = $country->name();
710
+				}
711
+			}
712
+		}
713
+		if ($question instanceof EE_Question && $registration instanceof EE_Registration) {
714
+			$answer = EEM_Answer::instance()->get_one(
715
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
716
+			);
717
+		} else {
718
+			$answer = EE_Answer::new_instance();
719
+		}
720
+		$country_options = apply_filters(
721
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
722
+			$country_options,
723
+			$this,
724
+			$registration,
725
+			$question,
726
+			$answer
727
+		);
728
+		return $country_options;
729
+	}
730 730
 
731 731
 
732
-    /**
733
-     * Gets the list of states for the form input
734
-     *
735
-     * @param array|null      $states_list
736
-     * @param EE_Question     $question
737
-     * @param EE_Registration $registration
738
-     * @param EE_Answer       $answer
739
-     * @return array 2d keys are state IDs, values are their names
740
-     * @throws EE_Error
741
-     * @throws InvalidArgumentException
742
-     * @throws InvalidDataTypeException
743
-     * @throws InvalidInterfaceException
744
-     * @throws ReflectionException
745
-     */
746
-    public function use_cached_states_for_form_input(
747
-        $states_list,
748
-        EE_Question $question = null,
749
-        EE_Registration $registration = null,
750
-        EE_Answer $answer = null
751
-    ) {
752
-        $state_options = array('' => array('' => ''));
753
-        $states = $this->checkout->action === 'process_reg_step'
754
-            ? EEM_State::instance()->get_all_states()
755
-            : EEM_State::instance()->get_all_active_states();
756
-        if (! empty($states)) {
757
-            foreach ($states as $state) {
758
-                if ($state instanceof EE_State) {
759
-                    $state_options[ $state->country()->name() ][ $state->ID() ] = $state->name();
760
-                }
761
-            }
762
-        }
763
-        $state_options = apply_filters(
764
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
765
-            $state_options,
766
-            $this,
767
-            $registration,
768
-            $question,
769
-            $answer
770
-        );
771
-        return $state_options;
772
-    }
732
+	/**
733
+	 * Gets the list of states for the form input
734
+	 *
735
+	 * @param array|null      $states_list
736
+	 * @param EE_Question     $question
737
+	 * @param EE_Registration $registration
738
+	 * @param EE_Answer       $answer
739
+	 * @return array 2d keys are state IDs, values are their names
740
+	 * @throws EE_Error
741
+	 * @throws InvalidArgumentException
742
+	 * @throws InvalidDataTypeException
743
+	 * @throws InvalidInterfaceException
744
+	 * @throws ReflectionException
745
+	 */
746
+	public function use_cached_states_for_form_input(
747
+		$states_list,
748
+		EE_Question $question = null,
749
+		EE_Registration $registration = null,
750
+		EE_Answer $answer = null
751
+	) {
752
+		$state_options = array('' => array('' => ''));
753
+		$states = $this->checkout->action === 'process_reg_step'
754
+			? EEM_State::instance()->get_all_states()
755
+			: EEM_State::instance()->get_all_active_states();
756
+		if (! empty($states)) {
757
+			foreach ($states as $state) {
758
+				if ($state instanceof EE_State) {
759
+					$state_options[ $state->country()->name() ][ $state->ID() ] = $state->name();
760
+				}
761
+			}
762
+		}
763
+		$state_options = apply_filters(
764
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
765
+			$state_options,
766
+			$this,
767
+			$registration,
768
+			$question,
769
+			$answer
770
+		);
771
+		return $state_options;
772
+	}
773 773
 
774 774
 
775
-    /********************************************************************************************************/
776
-    /****************************************  PROCESS REG STEP  ****************************************/
777
-    /********************************************************************************************************/
775
+	/********************************************************************************************************/
776
+	/****************************************  PROCESS REG STEP  ****************************************/
777
+	/********************************************************************************************************/
778 778
 
779 779
 
780
-    /**
781
-     * @return bool
782
-     * @throws EE_Error
783
-     * @throws InvalidArgumentException
784
-     * @throws ReflectionException
785
-     * @throws RuntimeException
786
-     * @throws InvalidDataTypeException
787
-     * @throws InvalidInterfaceException
788
-     */
789
-    public function process_reg_step()
790
-    {
791
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
792
-        // grab validated data from form
793
-        $valid_data = $this->checkout->current_step->valid_data();
794
-        // EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
795
-        // EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
796
-        // if we don't have any $valid_data then something went TERRIBLY WRONG !!!
797
-        if (empty($valid_data)) {
798
-            EE_Error::add_error(
799
-                esc_html__('No valid question responses were received.', 'event_espresso'),
800
-                __FILE__,
801
-                __FUNCTION__,
802
-                __LINE__
803
-            );
804
-            return false;
805
-        }
806
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
807
-            EE_Error::add_error(
808
-                esc_html__(
809
-                    'A valid transaction could not be initiated for processing your registrations.',
810
-                    'event_espresso'
811
-                ),
812
-                __FILE__,
813
-                __FUNCTION__,
814
-                __LINE__
815
-            );
816
-            return false;
817
-        }
818
-        // get cached registrations
819
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
820
-        // verify we got the goods
821
-        if (empty($registrations)) {
822
-            // combine the old translated string with a new one, in order to not break translations
823
-            $error_message = esc_html__(
824
-                'Your form data could not be applied to any valid registrations.',
825
-                'event_espresso'
826
-            )
827
-            . sprintf(
828
-                esc_html_x(
829
-                    '%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.',
830
-                    '(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
831
-                    'event_espresso'
832
-                ),
833
-                '<a href="' . get_post_type_archive_link('espresso_events') . '" >',
834
-                '</a>',
835
-                '<br />'
836
-            );
837
-            EE_Error::add_error(
838
-                $error_message,
839
-                __FILE__,
840
-                __FUNCTION__,
841
-                __LINE__
842
-            );
843
-            return false;
844
-        }
845
-        // extract attendee info from form data and save to model objects
846
-        $registrations_processed = $this->_process_registrations($registrations, $valid_data);
847
-        // if first pass thru SPCO,
848
-        // then let's check processed registrations against the total number of tickets in the cart
849
-        if ($registrations_processed === false) {
850
-            // but return immediately if the previous step exited early due to errors
851
-            return false;
852
-        }
853
-        if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
854
-            // generate a correctly translated string for all possible singular/plural combinations
855
-            if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
856
-                $error_msg = sprintf(
857
-                    esc_html_x(
858
-                        'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
859
-                        'There was 1 ticket in the Event Queue, but 2 registrations were processed',
860
-                        'event_espresso'
861
-                    ),
862
-                    $this->checkout->total_ticket_count,
863
-                    $registrations_processed
864
-                );
865
-            } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
866
-                $error_msg = sprintf(
867
-                    esc_html_x(
868
-                        'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
869
-                        'There was a total of 2 tickets in the Event Queue, but only 1 registration was processed',
870
-                        'event_espresso'
871
-                    ),
872
-                    $this->checkout->total_ticket_count,
873
-                    $registrations_processed
874
-                );
875
-            } else {
876
-                $error_msg = sprintf(
877
-                    esc_html__(
878
-                        'There was a total of 2 tickets in the Event Queue, but 2 registrations were processed',
879
-                        'event_espresso'
880
-                    ),
881
-                    $this->checkout->total_ticket_count,
882
-                    $registrations_processed
883
-                );
884
-            }
885
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
886
-            return false;
887
-        }
888
-        // mark this reg step as completed
889
-        $this->set_completed();
890
-        $this->_set_success_message(
891
-            esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
892
-        );
893
-        // do action in case a plugin wants to do something with the data submitted in step 1.
894
-        // passes EE_Single_Page_Checkout, and it's posted data
895
-        do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
896
-        return true;
897
-    }
780
+	/**
781
+	 * @return bool
782
+	 * @throws EE_Error
783
+	 * @throws InvalidArgumentException
784
+	 * @throws ReflectionException
785
+	 * @throws RuntimeException
786
+	 * @throws InvalidDataTypeException
787
+	 * @throws InvalidInterfaceException
788
+	 */
789
+	public function process_reg_step()
790
+	{
791
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
792
+		// grab validated data from form
793
+		$valid_data = $this->checkout->current_step->valid_data();
794
+		// EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
795
+		// EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
796
+		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
797
+		if (empty($valid_data)) {
798
+			EE_Error::add_error(
799
+				esc_html__('No valid question responses were received.', 'event_espresso'),
800
+				__FILE__,
801
+				__FUNCTION__,
802
+				__LINE__
803
+			);
804
+			return false;
805
+		}
806
+		if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
807
+			EE_Error::add_error(
808
+				esc_html__(
809
+					'A valid transaction could not be initiated for processing your registrations.',
810
+					'event_espresso'
811
+				),
812
+				__FILE__,
813
+				__FUNCTION__,
814
+				__LINE__
815
+			);
816
+			return false;
817
+		}
818
+		// get cached registrations
819
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
820
+		// verify we got the goods
821
+		if (empty($registrations)) {
822
+			// combine the old translated string with a new one, in order to not break translations
823
+			$error_message = esc_html__(
824
+				'Your form data could not be applied to any valid registrations.',
825
+				'event_espresso'
826
+			)
827
+			. sprintf(
828
+				esc_html_x(
829
+					'%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.',
830
+					'(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
831
+					'event_espresso'
832
+				),
833
+				'<a href="' . get_post_type_archive_link('espresso_events') . '" >',
834
+				'</a>',
835
+				'<br />'
836
+			);
837
+			EE_Error::add_error(
838
+				$error_message,
839
+				__FILE__,
840
+				__FUNCTION__,
841
+				__LINE__
842
+			);
843
+			return false;
844
+		}
845
+		// extract attendee info from form data and save to model objects
846
+		$registrations_processed = $this->_process_registrations($registrations, $valid_data);
847
+		// if first pass thru SPCO,
848
+		// then let's check processed registrations against the total number of tickets in the cart
849
+		if ($registrations_processed === false) {
850
+			// but return immediately if the previous step exited early due to errors
851
+			return false;
852
+		}
853
+		if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
854
+			// generate a correctly translated string for all possible singular/plural combinations
855
+			if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
856
+				$error_msg = sprintf(
857
+					esc_html_x(
858
+						'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
859
+						'There was 1 ticket in the Event Queue, but 2 registrations were processed',
860
+						'event_espresso'
861
+					),
862
+					$this->checkout->total_ticket_count,
863
+					$registrations_processed
864
+				);
865
+			} elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
866
+				$error_msg = sprintf(
867
+					esc_html_x(
868
+						'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
869
+						'There was a total of 2 tickets in the Event Queue, but only 1 registration was processed',
870
+						'event_espresso'
871
+					),
872
+					$this->checkout->total_ticket_count,
873
+					$registrations_processed
874
+				);
875
+			} else {
876
+				$error_msg = sprintf(
877
+					esc_html__(
878
+						'There was a total of 2 tickets in the Event Queue, but 2 registrations were processed',
879
+						'event_espresso'
880
+					),
881
+					$this->checkout->total_ticket_count,
882
+					$registrations_processed
883
+				);
884
+			}
885
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
886
+			return false;
887
+		}
888
+		// mark this reg step as completed
889
+		$this->set_completed();
890
+		$this->_set_success_message(
891
+			esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
892
+		);
893
+		// do action in case a plugin wants to do something with the data submitted in step 1.
894
+		// passes EE_Single_Page_Checkout, and it's posted data
895
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
896
+		return true;
897
+	}
898 898
 
899 899
 
900
-    /**
901
-     *    _process_registrations
902
-     *
903
-     * @param EE_Registration[] $registrations
904
-     * @param array[][]         $valid_data
905
-     * @return bool|int
906
-     * @throws EntityNotFoundException
907
-     * @throws EE_Error
908
-     * @throws InvalidArgumentException
909
-     * @throws ReflectionException
910
-     * @throws RuntimeException
911
-     * @throws InvalidDataTypeException
912
-     * @throws InvalidInterfaceException
913
-     */
914
-    private function _process_registrations($registrations = array(), $valid_data = array())
915
-    {
916
-        // load resources and set some defaults
917
-        EE_Registry::instance()->load_model('Attendee');
918
-        // holder for primary registrant attendee object
919
-        $this->checkout->primary_attendee_obj = null;
920
-        // array for tracking reg form data for the primary registrant
921
-        $primary_registrant = array(
922
-            'line_item_id' => null,
923
-        );
924
-        $copy_primary = false;
925
-        // reg form sections that do not contain inputs
926
-        $non_input_form_sections = array(
927
-            'primary_registrant',
928
-            'additional_attendee_reg_info',
929
-            'spco_copy_attendee_chk',
930
-        );
931
-        // attendee counter
932
-        $att_nmbr = 0;
933
-        // grab the saved registrations from the transaction
934
-        foreach ($registrations as $registration) {
935
-            // verify EE_Registration object
936
-            if (! $registration instanceof EE_Registration) {
937
-                EE_Error::add_error(
938
-                    esc_html__(
939
-                        'An invalid Registration object was discovered when attempting to process your registration information.',
940
-                        'event_espresso'
941
-                    ),
942
-                    __FILE__,
943
-                    __FUNCTION__,
944
-                    __LINE__
945
-                );
946
-                return false;
947
-            }
948
-            /** @var string $reg_url_link */
949
-            $reg_url_link = $registration->reg_url_link();
950
-            // reg_url_link exists ?
951
-            if (! empty($reg_url_link)) {
952
-                // should this registration be processed during this visit ?
953
-                if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
954
-                    // if NOT revisiting, then let's save the registration now,
955
-                    // so that we have a REG_ID to use when generating other objects
956
-                    if (! $this->checkout->revisit) {
957
-                        $registration->save();
958
-                    }
959
-                    /**
960
-                     * This allows plugins to trigger a fail on processing of a
961
-                     * registration for any conditions they may have for it to pass.
962
-                     *
963
-                     * @var bool   if true is returned by the plugin then the
964
-                     *            registration processing is halted.
965
-                     */
966
-                    if (apply_filters(
967
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
968
-                        false,
969
-                        $att_nmbr,
970
-                        $registration,
971
-                        $registrations,
972
-                        $valid_data,
973
-                        $this
974
-                    )) {
975
-                        return false;
976
-                    }
900
+	/**
901
+	 *    _process_registrations
902
+	 *
903
+	 * @param EE_Registration[] $registrations
904
+	 * @param array[][]         $valid_data
905
+	 * @return bool|int
906
+	 * @throws EntityNotFoundException
907
+	 * @throws EE_Error
908
+	 * @throws InvalidArgumentException
909
+	 * @throws ReflectionException
910
+	 * @throws RuntimeException
911
+	 * @throws InvalidDataTypeException
912
+	 * @throws InvalidInterfaceException
913
+	 */
914
+	private function _process_registrations($registrations = array(), $valid_data = array())
915
+	{
916
+		// load resources and set some defaults
917
+		EE_Registry::instance()->load_model('Attendee');
918
+		// holder for primary registrant attendee object
919
+		$this->checkout->primary_attendee_obj = null;
920
+		// array for tracking reg form data for the primary registrant
921
+		$primary_registrant = array(
922
+			'line_item_id' => null,
923
+		);
924
+		$copy_primary = false;
925
+		// reg form sections that do not contain inputs
926
+		$non_input_form_sections = array(
927
+			'primary_registrant',
928
+			'additional_attendee_reg_info',
929
+			'spco_copy_attendee_chk',
930
+		);
931
+		// attendee counter
932
+		$att_nmbr = 0;
933
+		// grab the saved registrations from the transaction
934
+		foreach ($registrations as $registration) {
935
+			// verify EE_Registration object
936
+			if (! $registration instanceof EE_Registration) {
937
+				EE_Error::add_error(
938
+					esc_html__(
939
+						'An invalid Registration object was discovered when attempting to process your registration information.',
940
+						'event_espresso'
941
+					),
942
+					__FILE__,
943
+					__FUNCTION__,
944
+					__LINE__
945
+				);
946
+				return false;
947
+			}
948
+			/** @var string $reg_url_link */
949
+			$reg_url_link = $registration->reg_url_link();
950
+			// reg_url_link exists ?
951
+			if (! empty($reg_url_link)) {
952
+				// should this registration be processed during this visit ?
953
+				if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
954
+					// if NOT revisiting, then let's save the registration now,
955
+					// so that we have a REG_ID to use when generating other objects
956
+					if (! $this->checkout->revisit) {
957
+						$registration->save();
958
+					}
959
+					/**
960
+					 * This allows plugins to trigger a fail on processing of a
961
+					 * registration for any conditions they may have for it to pass.
962
+					 *
963
+					 * @var bool   if true is returned by the plugin then the
964
+					 *            registration processing is halted.
965
+					 */
966
+					if (apply_filters(
967
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
968
+						false,
969
+						$att_nmbr,
970
+						$registration,
971
+						$registrations,
972
+						$valid_data,
973
+						$this
974
+					)) {
975
+						return false;
976
+					}
977 977
 
978
-                    // Houston, we have a registration!
979
-                    $att_nmbr++;
980
-                    $this->_attendee_data[ $reg_url_link ] = array();
981
-                    // grab any existing related answer objects
982
-                    $this->_registration_answers = $registration->answers();
983
-                    // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
984
-                    if (isset($valid_data[ $reg_url_link ])) {
985
-                        // do we need to copy basic info from primary attendee ?
986
-                        $copy_primary = isset($valid_data[ $reg_url_link ]['additional_attendee_reg_info'])
987
-                                        && absint($valid_data[ $reg_url_link ]['additional_attendee_reg_info']) === 0;
988
-                        // filter form input data for this registration
989
-                        $valid_data[ $reg_url_link ] = (array) apply_filters(
990
-                            'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
991
-                            $valid_data[ $reg_url_link ]
992
-                        );
993
-                        if (isset($valid_data['primary_attendee'])) {
994
-                            $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
995
-                                ? $valid_data['primary_attendee']
996
-                                : false;
997
-                            unset($valid_data['primary_attendee']);
998
-                        }
999
-                        // now loop through our array of valid post data && process attendee reg forms
1000
-                        foreach ($valid_data[ $reg_url_link ] as $form_section => $form_inputs) {
1001
-                            if (! in_array($form_section, $non_input_form_sections, true)) {
1002
-                                foreach ($form_inputs as $form_input => $input_value) {
1003
-                                    // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
1004
-                                    // check for critical inputs
1005
-                                    if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
1006
-                                        $form_input,
1007
-                                        $input_value
1008
-                                    )
1009
-                                    ) {
1010
-                                        return false;
1011
-                                    }
1012
-                                    // store a bit of data about the primary attendee
1013
-                                    if ($att_nmbr === 1
1014
-                                        && ! empty($input_value)
1015
-                                        && $reg_url_link === $primary_registrant['line_item_id']
1016
-                                    ) {
1017
-                                        $primary_registrant[ $form_input ] = $input_value;
1018
-                                    } elseif ($copy_primary
1019
-                                              && $input_value === null
1020
-                                              && isset($primary_registrant[ $form_input ])
1021
-                                    ) {
1022
-                                        $input_value = $primary_registrant[ $form_input ];
1023
-                                    }
1024
-                                    // now attempt to save the input data
1025
-                                    if (! $this->_save_registration_form_input(
1026
-                                        $registration,
1027
-                                        $form_input,
1028
-                                        $input_value
1029
-                                    )
1030
-                                    ) {
1031
-                                        EE_Error::add_error(
1032
-                                            sprintf(
1033
-                                                esc_html_x(
1034
-                                                    'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1035
-                                                    'Unable to save registration form data for the form input: "form input name" with the submitted value: "form input value"',
1036
-                                                    'event_espresso'
1037
-                                                ),
1038
-                                                $form_input,
1039
-                                                $input_value
1040
-                                            ),
1041
-                                            __FILE__,
1042
-                                            __FUNCTION__,
1043
-                                            __LINE__
1044
-                                        );
1045
-                                        return false;
1046
-                                    }
1047
-                                }
1048
-                            }
1049
-                        }  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1050
-                    }
1051
-                    // EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1052
-                    // this registration does not require additional attendee information ?
1053
-                    if ($copy_primary
1054
-                        && $att_nmbr > 1
1055
-                        && $this->checkout->primary_attendee_obj instanceof EE_Attendee
1056
-                    ) {
1057
-                        // just copy the primary registrant
1058
-                        $attendee = $this->checkout->primary_attendee_obj;
1059
-                    } else {
1060
-                        // ensure critical details are set for additional attendees
1061
-                        $this->_attendee_data[ $reg_url_link ] = $att_nmbr > 1
1062
-                            ? $this->_copy_critical_attendee_details_from_primary_registrant(
1063
-                                $this->_attendee_data[ $reg_url_link ]
1064
-                            )
1065
-                            : $this->_attendee_data[ $reg_url_link ];
1066
-                        // execute create attendee command (which may return an existing attendee)
1067
-                        $attendee = EE_Registry::instance()->BUS->execute(
1068
-                            new CreateAttendeeCommand(
1069
-                                $this->_attendee_data[ $reg_url_link ],
1070
-                                $registration
1071
-                            )
1072
-                        );
1073
-                        // who's #1 ?
1074
-                        if ($att_nmbr === 1) {
1075
-                            $this->checkout->primary_attendee_obj = $attendee;
1076
-                        }
1077
-                    }
1078
-                    // EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1079
-                    // add relation to registration, set attendee ID, and cache attendee
1080
-                    $this->_associate_attendee_with_registration($registration, $attendee);
1081
-                    // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1082
-                    if (! $registration->attendee() instanceof EE_Attendee) {
1083
-                        EE_Error::add_error(
1084
-                            sprintf(
1085
-                                esc_html_x(
1086
-                                    'Registration %s has an invalid or missing Attendee object.',
1087
-                                    'Registration 123-456-789 has an invalid or missing Attendee object.',
1088
-                                    'event_espresso'
1089
-                                ),
1090
-                                $reg_url_link
1091
-                            ),
1092
-                            __FILE__,
1093
-                            __FUNCTION__,
1094
-                            __LINE__
1095
-                        );
1096
-                        return false;
1097
-                    }
1098
-                    /** @type EE_Registration_Processor $registration_processor */
1099
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1100
-                    // at this point, we should have enough details about the registrant to consider the registration
1101
-                    // NOT incomplete
1102
-                    $registration_processor->toggle_incomplete_registration_status_to_default(
1103
-                        $registration,
1104
-                        false,
1105
-                        new Context(
1106
-                            'spco_reg_step_attendee_information_process_registrations',
1107
-                            esc_html__(
1108
-                                'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1109
-                                'event_espresso'
1110
-                            )
1111
-                        )
1112
-                    );
1113
-                    // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1114
-                    // abandoned
1115
-                    $this->checkout->transaction->toggle_failed_transaction_status();
1116
-                    // if we've gotten this far, then let's save what we have
1117
-                    $registration->save();
1118
-                    // add relation between TXN and registration
1119
-                    $this->_associate_registration_with_transaction($registration);
1120
-                }
1121
-            } else {
1122
-                EE_Error::add_error(
1123
-                    esc_html__(
1124
-                        'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1125
-                        'event_espresso'
1126
-                    ),
1127
-                    __FILE__,
1128
-                    __FUNCTION__,
1129
-                    __LINE__
1130
-                );
1131
-                // remove malformed data
1132
-                unset($valid_data[ $reg_url_link ]);
1133
-                return false;
1134
-            }
1135
-        } // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1136
-        return $att_nmbr;
1137
-    }
978
+					// Houston, we have a registration!
979
+					$att_nmbr++;
980
+					$this->_attendee_data[ $reg_url_link ] = array();
981
+					// grab any existing related answer objects
982
+					$this->_registration_answers = $registration->answers();
983
+					// unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
984
+					if (isset($valid_data[ $reg_url_link ])) {
985
+						// do we need to copy basic info from primary attendee ?
986
+						$copy_primary = isset($valid_data[ $reg_url_link ]['additional_attendee_reg_info'])
987
+										&& absint($valid_data[ $reg_url_link ]['additional_attendee_reg_info']) === 0;
988
+						// filter form input data for this registration
989
+						$valid_data[ $reg_url_link ] = (array) apply_filters(
990
+							'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
991
+							$valid_data[ $reg_url_link ]
992
+						);
993
+						if (isset($valid_data['primary_attendee'])) {
994
+							$primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
995
+								? $valid_data['primary_attendee']
996
+								: false;
997
+							unset($valid_data['primary_attendee']);
998
+						}
999
+						// now loop through our array of valid post data && process attendee reg forms
1000
+						foreach ($valid_data[ $reg_url_link ] as $form_section => $form_inputs) {
1001
+							if (! in_array($form_section, $non_input_form_sections, true)) {
1002
+								foreach ($form_inputs as $form_input => $input_value) {
1003
+									// \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
1004
+									// check for critical inputs
1005
+									if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
1006
+										$form_input,
1007
+										$input_value
1008
+									)
1009
+									) {
1010
+										return false;
1011
+									}
1012
+									// store a bit of data about the primary attendee
1013
+									if ($att_nmbr === 1
1014
+										&& ! empty($input_value)
1015
+										&& $reg_url_link === $primary_registrant['line_item_id']
1016
+									) {
1017
+										$primary_registrant[ $form_input ] = $input_value;
1018
+									} elseif ($copy_primary
1019
+											  && $input_value === null
1020
+											  && isset($primary_registrant[ $form_input ])
1021
+									) {
1022
+										$input_value = $primary_registrant[ $form_input ];
1023
+									}
1024
+									// now attempt to save the input data
1025
+									if (! $this->_save_registration_form_input(
1026
+										$registration,
1027
+										$form_input,
1028
+										$input_value
1029
+									)
1030
+									) {
1031
+										EE_Error::add_error(
1032
+											sprintf(
1033
+												esc_html_x(
1034
+													'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1035
+													'Unable to save registration form data for the form input: "form input name" with the submitted value: "form input value"',
1036
+													'event_espresso'
1037
+												),
1038
+												$form_input,
1039
+												$input_value
1040
+											),
1041
+											__FILE__,
1042
+											__FUNCTION__,
1043
+											__LINE__
1044
+										);
1045
+										return false;
1046
+									}
1047
+								}
1048
+							}
1049
+						}  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1050
+					}
1051
+					// EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1052
+					// this registration does not require additional attendee information ?
1053
+					if ($copy_primary
1054
+						&& $att_nmbr > 1
1055
+						&& $this->checkout->primary_attendee_obj instanceof EE_Attendee
1056
+					) {
1057
+						// just copy the primary registrant
1058
+						$attendee = $this->checkout->primary_attendee_obj;
1059
+					} else {
1060
+						// ensure critical details are set for additional attendees
1061
+						$this->_attendee_data[ $reg_url_link ] = $att_nmbr > 1
1062
+							? $this->_copy_critical_attendee_details_from_primary_registrant(
1063
+								$this->_attendee_data[ $reg_url_link ]
1064
+							)
1065
+							: $this->_attendee_data[ $reg_url_link ];
1066
+						// execute create attendee command (which may return an existing attendee)
1067
+						$attendee = EE_Registry::instance()->BUS->execute(
1068
+							new CreateAttendeeCommand(
1069
+								$this->_attendee_data[ $reg_url_link ],
1070
+								$registration
1071
+							)
1072
+						);
1073
+						// who's #1 ?
1074
+						if ($att_nmbr === 1) {
1075
+							$this->checkout->primary_attendee_obj = $attendee;
1076
+						}
1077
+					}
1078
+					// EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1079
+					// add relation to registration, set attendee ID, and cache attendee
1080
+					$this->_associate_attendee_with_registration($registration, $attendee);
1081
+					// \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1082
+					if (! $registration->attendee() instanceof EE_Attendee) {
1083
+						EE_Error::add_error(
1084
+							sprintf(
1085
+								esc_html_x(
1086
+									'Registration %s has an invalid or missing Attendee object.',
1087
+									'Registration 123-456-789 has an invalid or missing Attendee object.',
1088
+									'event_espresso'
1089
+								),
1090
+								$reg_url_link
1091
+							),
1092
+							__FILE__,
1093
+							__FUNCTION__,
1094
+							__LINE__
1095
+						);
1096
+						return false;
1097
+					}
1098
+					/** @type EE_Registration_Processor $registration_processor */
1099
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1100
+					// at this point, we should have enough details about the registrant to consider the registration
1101
+					// NOT incomplete
1102
+					$registration_processor->toggle_incomplete_registration_status_to_default(
1103
+						$registration,
1104
+						false,
1105
+						new Context(
1106
+							'spco_reg_step_attendee_information_process_registrations',
1107
+							esc_html__(
1108
+								'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1109
+								'event_espresso'
1110
+							)
1111
+						)
1112
+					);
1113
+					// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1114
+					// abandoned
1115
+					$this->checkout->transaction->toggle_failed_transaction_status();
1116
+					// if we've gotten this far, then let's save what we have
1117
+					$registration->save();
1118
+					// add relation between TXN and registration
1119
+					$this->_associate_registration_with_transaction($registration);
1120
+				}
1121
+			} else {
1122
+				EE_Error::add_error(
1123
+					esc_html__(
1124
+						'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1125
+						'event_espresso'
1126
+					),
1127
+					__FILE__,
1128
+					__FUNCTION__,
1129
+					__LINE__
1130
+				);
1131
+				// remove malformed data
1132
+				unset($valid_data[ $reg_url_link ]);
1133
+				return false;
1134
+			}
1135
+		} // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1136
+		return $att_nmbr;
1137
+	}
1138 1138
 
1139 1139
 
1140
-    /**
1141
-     *    _save_registration_form_input
1142
-     *
1143
-     * @param EE_Registration $registration
1144
-     * @param string          $form_input
1145
-     * @param string          $input_value
1146
-     * @return bool
1147
-     * @throws EE_Error
1148
-     * @throws InvalidArgumentException
1149
-     * @throws InvalidDataTypeException
1150
-     * @throws InvalidInterfaceException
1151
-     * @throws ReflectionException
1152
-     */
1153
-    private function _save_registration_form_input(
1154
-        EE_Registration $registration,
1155
-        $form_input = '',
1156
-        $input_value = ''
1157
-    ) {
1158
-        // \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1159
-        // \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1160
-        // \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1161
-        // allow for plugins to hook in and do their own processing of the form input.
1162
-        // For plugins to bypass normal processing here, they just need to return a boolean value.
1163
-        if (apply_filters(
1164
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1165
-            false,
1166
-            $registration,
1167
-            $form_input,
1168
-            $input_value,
1169
-            $this
1170
-        )) {
1171
-            return true;
1172
-        }
1173
-        /*
1140
+	/**
1141
+	 *    _save_registration_form_input
1142
+	 *
1143
+	 * @param EE_Registration $registration
1144
+	 * @param string          $form_input
1145
+	 * @param string          $input_value
1146
+	 * @return bool
1147
+	 * @throws EE_Error
1148
+	 * @throws InvalidArgumentException
1149
+	 * @throws InvalidDataTypeException
1150
+	 * @throws InvalidInterfaceException
1151
+	 * @throws ReflectionException
1152
+	 */
1153
+	private function _save_registration_form_input(
1154
+		EE_Registration $registration,
1155
+		$form_input = '',
1156
+		$input_value = ''
1157
+	) {
1158
+		// \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1159
+		// \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1160
+		// \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1161
+		// allow for plugins to hook in and do their own processing of the form input.
1162
+		// For plugins to bypass normal processing here, they just need to return a boolean value.
1163
+		if (apply_filters(
1164
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1165
+			false,
1166
+			$registration,
1167
+			$form_input,
1168
+			$input_value,
1169
+			$this
1170
+		)) {
1171
+			return true;
1172
+		}
1173
+		/*
1174 1174
          * $answer_cache_id is the key used to find the EE_Answer we want
1175 1175
          * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477
1176 1176
          */
1177
-        $answer_cache_id = $this->checkout->reg_url_link
1178
-            ? $form_input . '-' . $registration->reg_url_link()
1179
-            : $form_input;
1180
-        $answer_is_obj = isset($this->_registration_answers[ $answer_cache_id ])
1181
-                         && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer;
1182
-        // rename form_inputs if they are EE_Attendee properties
1183
-        switch ((string) $form_input) {
1184
-            case 'state':
1185
-            case 'STA_ID':
1186
-                $attendee_property = true;
1187
-                $form_input = 'STA_ID';
1188
-                break;
1177
+		$answer_cache_id = $this->checkout->reg_url_link
1178
+			? $form_input . '-' . $registration->reg_url_link()
1179
+			: $form_input;
1180
+		$answer_is_obj = isset($this->_registration_answers[ $answer_cache_id ])
1181
+						 && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer;
1182
+		// rename form_inputs if they are EE_Attendee properties
1183
+		switch ((string) $form_input) {
1184
+			case 'state':
1185
+			case 'STA_ID':
1186
+				$attendee_property = true;
1187
+				$form_input = 'STA_ID';
1188
+				break;
1189 1189
 
1190
-            case 'country':
1191
-            case 'CNT_ISO':
1192
-                $attendee_property = true;
1193
-                $form_input = 'CNT_ISO';
1194
-                break;
1190
+			case 'country':
1191
+			case 'CNT_ISO':
1192
+				$attendee_property = true;
1193
+				$form_input = 'CNT_ISO';
1194
+				break;
1195 1195
 
1196
-            default:
1197
-                $ATT_input = 'ATT_' . $form_input;
1198
-                // EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1199
-                $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1200
-                $form_input = $attendee_property ? 'ATT_' . $form_input : $form_input;
1201
-        }
1202
-        // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1203
-        // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1204
-        // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1205
-        // if this form input has a corresponding attendee property
1206
-        if ($attendee_property) {
1207
-            $this->_attendee_data[ $registration->reg_url_link() ][ $form_input ] = $input_value;
1208
-            if ($answer_is_obj) {
1209
-                // and delete the corresponding answer since we won't be storing this data in that object
1210
-                $registration->_remove_relation_to($this->_registration_answers[ $answer_cache_id ], 'Answer');
1211
-                $this->_registration_answers[ $answer_cache_id ]->delete_permanently();
1212
-            }
1213
-            return true;
1214
-        }
1215
-        if ($answer_is_obj) {
1216
-            // save this data to the answer object
1217
-            $this->_registration_answers[ $answer_cache_id ]->set_value($input_value);
1218
-            $result = $this->_registration_answers[ $answer_cache_id ]->save();
1219
-            return $result !== false;
1220
-        }
1221
-        foreach ($this->_registration_answers as $answer) {
1222
-            if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1223
-                $answer->set_value($input_value);
1224
-                $result = $answer->save();
1225
-                return $result !== false;
1226
-            }
1227
-        }
1228
-        return false;
1229
-    }
1196
+			default:
1197
+				$ATT_input = 'ATT_' . $form_input;
1198
+				// EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1199
+				$attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1200
+				$form_input = $attendee_property ? 'ATT_' . $form_input : $form_input;
1201
+		}
1202
+		// EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1203
+		// EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1204
+		// EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1205
+		// if this form input has a corresponding attendee property
1206
+		if ($attendee_property) {
1207
+			$this->_attendee_data[ $registration->reg_url_link() ][ $form_input ] = $input_value;
1208
+			if ($answer_is_obj) {
1209
+				// and delete the corresponding answer since we won't be storing this data in that object
1210
+				$registration->_remove_relation_to($this->_registration_answers[ $answer_cache_id ], 'Answer');
1211
+				$this->_registration_answers[ $answer_cache_id ]->delete_permanently();
1212
+			}
1213
+			return true;
1214
+		}
1215
+		if ($answer_is_obj) {
1216
+			// save this data to the answer object
1217
+			$this->_registration_answers[ $answer_cache_id ]->set_value($input_value);
1218
+			$result = $this->_registration_answers[ $answer_cache_id ]->save();
1219
+			return $result !== false;
1220
+		}
1221
+		foreach ($this->_registration_answers as $answer) {
1222
+			if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1223
+				$answer->set_value($input_value);
1224
+				$result = $answer->save();
1225
+				return $result !== false;
1226
+			}
1227
+		}
1228
+		return false;
1229
+	}
1230 1230
 
1231 1231
 
1232
-    /**
1233
-     *    _verify_critical_attendee_details_are_set
1234
-     *
1235
-     * @param string $form_input
1236
-     * @param string $input_value
1237
-     * @return boolean
1238
-     */
1239
-    private function _verify_critical_attendee_details_are_set_and_validate_email(
1240
-        $form_input = '',
1241
-        $input_value = ''
1242
-    ) {
1243
-        if (empty($input_value)) {
1244
-            // if the form input isn't marked as being required, then just return
1245
-            if (! isset($this->_required_questions[ $form_input ]) || ! $this->_required_questions[ $form_input ]) {
1246
-                return true;
1247
-            }
1248
-            switch ($form_input) {
1249
-                case 'fname':
1250
-                    EE_Error::add_error(
1251
-                        esc_html__('First Name is a required value.', 'event_espresso'),
1252
-                        __FILE__,
1253
-                        __FUNCTION__,
1254
-                        __LINE__
1255
-                    );
1256
-                    return false;
1257
-                    break;
1258
-                case 'lname':
1259
-                    EE_Error::add_error(
1260
-                        esc_html__('Last Name is a required value.', 'event_espresso'),
1261
-                        __FILE__,
1262
-                        __FUNCTION__,
1263
-                        __LINE__
1264
-                    );
1265
-                    return false;
1266
-                    break;
1267
-                case 'email':
1268
-                    EE_Error::add_error(
1269
-                        esc_html__('Please enter a valid email address.', 'event_espresso'),
1270
-                        __FILE__,
1271
-                        __FUNCTION__,
1272
-                        __LINE__
1273
-                    );
1274
-                    return false;
1275
-                    break;
1276
-            }
1277
-        }
1278
-        return true;
1279
-    }
1232
+	/**
1233
+	 *    _verify_critical_attendee_details_are_set
1234
+	 *
1235
+	 * @param string $form_input
1236
+	 * @param string $input_value
1237
+	 * @return boolean
1238
+	 */
1239
+	private function _verify_critical_attendee_details_are_set_and_validate_email(
1240
+		$form_input = '',
1241
+		$input_value = ''
1242
+	) {
1243
+		if (empty($input_value)) {
1244
+			// if the form input isn't marked as being required, then just return
1245
+			if (! isset($this->_required_questions[ $form_input ]) || ! $this->_required_questions[ $form_input ]) {
1246
+				return true;
1247
+			}
1248
+			switch ($form_input) {
1249
+				case 'fname':
1250
+					EE_Error::add_error(
1251
+						esc_html__('First Name is a required value.', 'event_espresso'),
1252
+						__FILE__,
1253
+						__FUNCTION__,
1254
+						__LINE__
1255
+					);
1256
+					return false;
1257
+					break;
1258
+				case 'lname':
1259
+					EE_Error::add_error(
1260
+						esc_html__('Last Name is a required value.', 'event_espresso'),
1261
+						__FILE__,
1262
+						__FUNCTION__,
1263
+						__LINE__
1264
+					);
1265
+					return false;
1266
+					break;
1267
+				case 'email':
1268
+					EE_Error::add_error(
1269
+						esc_html__('Please enter a valid email address.', 'event_espresso'),
1270
+						__FILE__,
1271
+						__FUNCTION__,
1272
+						__LINE__
1273
+					);
1274
+					return false;
1275
+					break;
1276
+			}
1277
+		}
1278
+		return true;
1279
+	}
1280 1280
 
1281 1281
 
1282
-    /**
1283
-     *    _associate_attendee_with_registration
1284
-     *
1285
-     * @param EE_Registration $registration
1286
-     * @param EE_Attendee     $attendee
1287
-     * @return void
1288
-     * @throws EE_Error
1289
-     * @throws InvalidArgumentException
1290
-     * @throws ReflectionException
1291
-     * @throws RuntimeException
1292
-     * @throws InvalidDataTypeException
1293
-     * @throws InvalidInterfaceException
1294
-     */
1295
-    private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1296
-    {
1297
-        // add relation to attendee
1298
-        $registration->_add_relation_to($attendee, 'Attendee');
1299
-        $registration->set_attendee_id($attendee->ID());
1300
-        $registration->update_cache_after_object_save('Attendee', $attendee);
1301
-    }
1282
+	/**
1283
+	 *    _associate_attendee_with_registration
1284
+	 *
1285
+	 * @param EE_Registration $registration
1286
+	 * @param EE_Attendee     $attendee
1287
+	 * @return void
1288
+	 * @throws EE_Error
1289
+	 * @throws InvalidArgumentException
1290
+	 * @throws ReflectionException
1291
+	 * @throws RuntimeException
1292
+	 * @throws InvalidDataTypeException
1293
+	 * @throws InvalidInterfaceException
1294
+	 */
1295
+	private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1296
+	{
1297
+		// add relation to attendee
1298
+		$registration->_add_relation_to($attendee, 'Attendee');
1299
+		$registration->set_attendee_id($attendee->ID());
1300
+		$registration->update_cache_after_object_save('Attendee', $attendee);
1301
+	}
1302 1302
 
1303 1303
 
1304
-    /**
1305
-     *    _associate_registration_with_transaction
1306
-     *
1307
-     * @param EE_Registration $registration
1308
-     * @return void
1309
-     * @throws EE_Error
1310
-     * @throws InvalidArgumentException
1311
-     * @throws ReflectionException
1312
-     * @throws InvalidDataTypeException
1313
-     * @throws InvalidInterfaceException
1314
-     */
1315
-    private function _associate_registration_with_transaction(EE_Registration $registration)
1316
-    {
1317
-        // add relation to registration
1318
-        $this->checkout->transaction->_add_relation_to($registration, 'Registration');
1319
-        $this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1320
-    }
1304
+	/**
1305
+	 *    _associate_registration_with_transaction
1306
+	 *
1307
+	 * @param EE_Registration $registration
1308
+	 * @return void
1309
+	 * @throws EE_Error
1310
+	 * @throws InvalidArgumentException
1311
+	 * @throws ReflectionException
1312
+	 * @throws InvalidDataTypeException
1313
+	 * @throws InvalidInterfaceException
1314
+	 */
1315
+	private function _associate_registration_with_transaction(EE_Registration $registration)
1316
+	{
1317
+		// add relation to registration
1318
+		$this->checkout->transaction->_add_relation_to($registration, 'Registration');
1319
+		$this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1320
+	}
1321 1321
 
1322 1322
 
1323
-    /**
1324
-     *    _copy_critical_attendee_details_from_primary_registrant
1325
-     *    ensures that all attendees at least have data for first name, last name, and email address
1326
-     *
1327
-     * @param array $attendee_data
1328
-     * @return array
1329
-     * @throws EE_Error
1330
-     * @throws InvalidArgumentException
1331
-     * @throws ReflectionException
1332
-     * @throws InvalidDataTypeException
1333
-     * @throws InvalidInterfaceException
1334
-     */
1335
-    private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1336
-    {
1337
-        // bare minimum critical details include first name, last name, email address
1338
-        $critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1339
-        // add address info to critical details?
1340
-        if (apply_filters(
1341
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1342
-            false
1343
-        )) {
1344
-            $address_details = array(
1345
-                'ATT_address',
1346
-                'ATT_address2',
1347
-                'ATT_city',
1348
-                'STA_ID',
1349
-                'CNT_ISO',
1350
-                'ATT_zip',
1351
-                'ATT_phone',
1352
-            );
1353
-            $critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1354
-        }
1355
-        foreach ($critical_attendee_details as $critical_attendee_detail) {
1356
-            if (! isset($attendee_data[ $critical_attendee_detail ])
1357
-                || empty($attendee_data[ $critical_attendee_detail ])
1358
-            ) {
1359
-                $attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1360
-                    $critical_attendee_detail
1361
-                );
1362
-            }
1363
-        }
1364
-        return $attendee_data;
1365
-    }
1323
+	/**
1324
+	 *    _copy_critical_attendee_details_from_primary_registrant
1325
+	 *    ensures that all attendees at least have data for first name, last name, and email address
1326
+	 *
1327
+	 * @param array $attendee_data
1328
+	 * @return array
1329
+	 * @throws EE_Error
1330
+	 * @throws InvalidArgumentException
1331
+	 * @throws ReflectionException
1332
+	 * @throws InvalidDataTypeException
1333
+	 * @throws InvalidInterfaceException
1334
+	 */
1335
+	private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1336
+	{
1337
+		// bare minimum critical details include first name, last name, email address
1338
+		$critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1339
+		// add address info to critical details?
1340
+		if (apply_filters(
1341
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1342
+			false
1343
+		)) {
1344
+			$address_details = array(
1345
+				'ATT_address',
1346
+				'ATT_address2',
1347
+				'ATT_city',
1348
+				'STA_ID',
1349
+				'CNT_ISO',
1350
+				'ATT_zip',
1351
+				'ATT_phone',
1352
+			);
1353
+			$critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1354
+		}
1355
+		foreach ($critical_attendee_details as $critical_attendee_detail) {
1356
+			if (! isset($attendee_data[ $critical_attendee_detail ])
1357
+				|| empty($attendee_data[ $critical_attendee_detail ])
1358
+			) {
1359
+				$attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1360
+					$critical_attendee_detail
1361
+				);
1362
+			}
1363
+		}
1364
+		return $attendee_data;
1365
+	}
1366 1366
 
1367 1367
 
1368
-    /**
1369
-     *    update_reg_step
1370
-     *    this is the final step after a user  revisits the site to edit their attendee information
1371
-     *    this gets called AFTER the process_reg_step() method above
1372
-     *
1373
-     * @return bool
1374
-     * @throws EE_Error
1375
-     * @throws InvalidArgumentException
1376
-     * @throws ReflectionException
1377
-     * @throws RuntimeException
1378
-     * @throws InvalidDataTypeException
1379
-     * @throws InvalidInterfaceException
1380
-     */
1381
-    public function update_reg_step()
1382
-    {
1383
-        // save everything
1384
-        if ($this->process_reg_step()) {
1385
-            $this->checkout->redirect = true;
1386
-            $this->checkout->redirect_url = add_query_arg(
1387
-                array(
1388
-                    'e_reg_url_link' => $this->checkout->reg_url_link,
1389
-                    'revisit'        => true,
1390
-                ),
1391
-                $this->checkout->thank_you_page_url
1392
-            );
1393
-            $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1394
-            return true;
1395
-        }
1396
-        return false;
1397
-    }
1368
+	/**
1369
+	 *    update_reg_step
1370
+	 *    this is the final step after a user  revisits the site to edit their attendee information
1371
+	 *    this gets called AFTER the process_reg_step() method above
1372
+	 *
1373
+	 * @return bool
1374
+	 * @throws EE_Error
1375
+	 * @throws InvalidArgumentException
1376
+	 * @throws ReflectionException
1377
+	 * @throws RuntimeException
1378
+	 * @throws InvalidDataTypeException
1379
+	 * @throws InvalidInterfaceException
1380
+	 */
1381
+	public function update_reg_step()
1382
+	{
1383
+		// save everything
1384
+		if ($this->process_reg_step()) {
1385
+			$this->checkout->redirect = true;
1386
+			$this->checkout->redirect_url = add_query_arg(
1387
+				array(
1388
+					'e_reg_url_link' => $this->checkout->reg_url_link,
1389
+					'revisit'        => true,
1390
+				),
1391
+				$this->checkout->thank_you_page_url
1392
+			);
1393
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1394
+			return true;
1395
+		}
1396
+		return false;
1397
+	}
1398 1398
 }
Please login to merge, or discard this patch.
Spacing   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
     {
49 49
         $this->_slug = 'attendee_information';
50 50
         $this->_name = esc_html__('Attendee Information', 'event_espresso');
51
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
51
+        $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.DS.'attendee_info_main.template.php';
52 52
         $this->checkout = $checkout;
53 53
         $this->_reset_success_message();
54 54
         $this->set_instructions(
@@ -147,13 +147,13 @@  discard block
 block discarded – undo
147 147
                 if ($registration instanceof EE_Registration
148 148
                     && $this->checkout->visit_allows_processing_of_this_registration($registration)
149 149
                 ) {
150
-                    $subsections[ $registration->reg_url_link() ] = $this->_registrations_reg_form($registration);
151
-                    if (! $this->checkout->admin_request) {
152
-                        $template_args['registrations'][ $registration->reg_url_link() ] = $registration;
153
-                        $template_args['ticket_count'][ $registration->ticket()->ID() ] = isset(
154
-                            $template_args['ticket_count'][ $registration->ticket()->ID() ]
150
+                    $subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
151
+                    if ( ! $this->checkout->admin_request) {
152
+                        $template_args['registrations'][$registration->reg_url_link()] = $registration;
153
+                        $template_args['ticket_count'][$registration->ticket()->ID()] = isset(
154
+                            $template_args['ticket_count'][$registration->ticket()->ID()]
155 155
                         )
156
-                            ? $template_args['ticket_count'][ $registration->ticket()->ID() ] + 1
156
+                            ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
157 157
                             : 1;
158 158
                         $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
159 159
                             $this->checkout->cart->get_grand_total(),
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
                         $ticket_line_item = is_array($ticket_line_item)
164 164
                             ? reset($ticket_line_item)
165 165
                             : $ticket_line_item;
166
-                        $template_args['ticket_line_item'][ $registration->ticket()->ID() ] =
166
+                        $template_args['ticket_line_item'][$registration->ticket()->ID()] =
167 167
                             $Line_Item_Display->display_line_item($ticket_line_item);
168 168
                     }
169 169
                     if ($registration->is_primary_registrant()) {
@@ -179,10 +179,10 @@  discard block
 block discarded – undo
179 179
                     ? $this->_copy_attendee_info_form()
180 180
                     : $this->_auto_copy_attendee_info();
181 181
                 // generate hidden input
182
-                if (isset($subsections[ $primary_registrant ])
183
-                    && $subsections[ $primary_registrant ] instanceof EE_Form_Section_Proper
182
+                if (isset($subsections[$primary_registrant])
183
+                    && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
184 184
                 ) {
185
-                    $subsections[ $primary_registrant ]->add_subsections(
185
+                    $subsections[$primary_registrant]->add_subsections(
186 186
                         $copy_options,
187 187
                         'primary_registrant',
188 188
                         false
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
             if ($question_groups) {
244 244
                 // array of params to pass to parent constructor
245 245
                 $form_args = array(
246
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
246
+                    'html_id'         => 'ee-registration-'.$registration->reg_url_link(),
247 247
                     'html_class'      => 'ee-reg-form-attendee-dv',
248 248
                     'html_style'      => $this->checkout->admin_request
249 249
                         ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
                 );
266 266
                 foreach ($question_groups as $question_group) {
267 267
                     if ($question_group instanceof EE_Question_Group) {
268
-                        $form_args['subsections'][ $question_group->identifier() ] = $this->_question_group_reg_form(
268
+                        $form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
269 269
                             $registration,
270 270
                             $question_group
271 271
                         );
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
         // generate hidden input
306 306
         return new EE_Hidden_Input(
307 307
             array(
308
-                'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
308
+                'html_id' => 'additional-attendee-reg-info-'.$registration->reg_url_link(),
309 309
                 'default' => $additional_attendee_reg_info,
310 310
             )
311 311
         );
@@ -326,12 +326,12 @@  discard block
 block discarded – undo
326 326
     {
327 327
         // array of params to pass to parent constructor
328 328
         $form_args = array(
329
-            'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(),
329
+            'html_id'         => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-'.$registration->ID(),
330 330
             'html_class'      => $this->checkout->admin_request
331 331
                 ? 'form-table ee-reg-form-qstn-grp-dv'
332 332
                 : 'ee-reg-form-qstn-grp-dv',
333
-            'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-'
334
-                                 . $registration->ID() . '-lbl',
333
+            'html_label_id'   => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-'
334
+                                 . $registration->ID().'-lbl',
335 335
             'subsections'     => array(
336 336
                 'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
337 337
             ),
@@ -342,7 +342,7 @@  discard block
 block discarded – undo
342 342
         // where params
343 343
         $query_params = array('QST_deleted' => 0);
344 344
         // don't load admin only questions on the frontend
345
-        if (! $this->checkout->admin_request) {
345
+        if ( ! $this->checkout->admin_request) {
346 346
             $query_params['QST_admin_only'] = array('!=', true);
347 347
         }
348 348
         $questions = $question_group->get_many_related(
@@ -376,7 +376,7 @@  discard block
 block discarded – undo
376 376
                 $identifier = $question->is_system_question()
377 377
                     ? $question->system_ID()
378 378
                     : $question->ID();
379
-                $form_args['subsections'][ $identifier ] = $this->reg_form_question($registration, $question);
379
+                $form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
380 380
             }
381 381
         }
382 382
         $form_args['subsections'] = apply_filters(
@@ -489,7 +489,7 @@  discard block
 block discarded – undo
489 489
     {
490 490
         return new EE_Form_Section_HTML(
491 491
             EEH_Template::locate_template(
492
-                SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
492
+                SPCO_REG_STEPS_PATH.$this->_slug.DS.'_auto_copy_attendee_info.template.php',
493 493
                 apply_filters(
494 494
                     'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
495 495
                     array()
@@ -522,16 +522,16 @@  discard block
 block discarded – undo
522 522
                 if ($registration->ticket()->ID() !== $prev_ticket) {
523 523
                     $item_name = $registration->ticket()->name();
524 524
                     $item_name .= $registration->ticket()->description() !== ''
525
-                        ? ' - ' . $registration->ticket()->description()
525
+                        ? ' - '.$registration->ticket()->description()
526 526
                         : '';
527
-                    $copy_attendee_info_inputs[ 'spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']' ] =
527
+                    $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-'.$registration->ticket()->ID().']'] =
528 528
                         new EE_Form_Section_HTML(
529
-                            '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
529
+                            '<h6 class="spco-copy-attendee-event-hdr">'.$item_name.'</h6>'
530 530
                         );
531 531
                     $prev_ticket = $registration->ticket()->ID();
532 532
                 }
533 533
 
534
-                $copy_attendee_info_inputs[ 'spco_copy_attendee_chk[' . $registration->ID() . ']' ] =
534
+                $copy_attendee_info_inputs['spco_copy_attendee_chk['.$registration->ID().']'] =
535 535
                     new EE_Checkbox_Multi_Input(
536 536
                         array(
537 537
                             $registration->ID() => sprintf(
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
                             ),
541 541
                         ),
542 542
                         array(
543
-                            'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
543
+                            'html_id'                 => 'spco-copy-attendee-chk-'.$registration->reg_url_link(),
544 544
                             'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
545 545
                             'display_html_label_text' => false,
546 546
                         )
@@ -605,14 +605,14 @@  discard block
 block discarded – undo
605 605
         }
606 606
         // verify instance
607 607
         if ($answer instanceof EE_Answer) {
608
-            if (! empty($answer_value)) {
608
+            if ( ! empty($answer_value)) {
609 609
                 $answer->set('ANS_value', $answer_value);
610 610
             }
611 611
             $answer->cache('Question', $question);
612 612
             // remember system ID had a bug where sometimes it could be null
613 613
             $answer_cache_id = $question->is_system_question()
614
-                ? $question->system_ID() . '-' . $registration->reg_url_link()
615
-                : $question->ID() . '-' . $registration->reg_url_link();
614
+                ? $question->system_ID().'-'.$registration->reg_url_link()
615
+                : $question->ID().'-'.$registration->reg_url_link();
616 616
             $registration->cache('Answer', $answer, $answer_cache_id);
617 617
         }
618 618
         return $this->_generate_question_input($registration, $question, $answer);
@@ -635,7 +635,7 @@  discard block
 block discarded – undo
635 635
         $identifier = $question->is_system_question()
636 636
             ? $question->system_ID()
637 637
             : $question->ID();
638
-        $this->_required_questions[ $identifier ] = $question->required() ? true : false;
638
+        $this->_required_questions[$identifier] = $question->required() ? true : false;
639 639
         add_filter(
640 640
             'FHEE__EE_Question__generate_form_input__country_options',
641 641
             array($this, 'use_cached_countries_for_form_input'),
@@ -649,17 +649,17 @@  discard block
 block discarded – undo
649 649
             4
650 650
         );
651 651
         $input_constructor_args = array(
652
-            'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
653
-            'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
654
-            'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
655
-            'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
652
+            'html_name'        => 'ee_reg_qstn['.$registration->ID().']['.$identifier.']',
653
+            'html_id'          => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
654
+            'html_class'       => 'ee-reg-qstn ee-reg-qstn-'.$identifier,
655
+            'html_label_id'    => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
656 656
             'html_label_class' => 'ee-reg-qstn',
657 657
         );
658 658
         $input_constructor_args['html_label_id'] .= '-lbl';
659 659
         if ($answer instanceof EE_Answer && $answer->ID()) {
660
-            $input_constructor_args['html_name'] .= '[' . $answer->ID() . ']';
661
-            $input_constructor_args['html_id'] .= '-' . $answer->ID();
662
-            $input_constructor_args['html_label_id'] .= '-' . $answer->ID();
660
+            $input_constructor_args['html_name'] .= '['.$answer->ID().']';
661
+            $input_constructor_args['html_id'] .= '-'.$answer->ID();
662
+            $input_constructor_args['html_label_id'] .= '-'.$answer->ID();
663 663
         }
664 664
         $form_input = $question->generate_form_input(
665 665
             $registration,
@@ -703,10 +703,10 @@  discard block
 block discarded – undo
703 703
         $countries = $this->checkout->action === 'process_reg_step'
704 704
             ? EEM_Country::instance()->get_all_countries()
705 705
             : EEM_Country::instance()->get_all_active_countries();
706
-        if (! empty($countries)) {
706
+        if ( ! empty($countries)) {
707 707
             foreach ($countries as $country) {
708 708
                 if ($country instanceof EE_Country) {
709
-                    $country_options[ $country->ID() ] = $country->name();
709
+                    $country_options[$country->ID()] = $country->name();
710 710
                 }
711 711
             }
712 712
         }
@@ -753,10 +753,10 @@  discard block
 block discarded – undo
753 753
         $states = $this->checkout->action === 'process_reg_step'
754 754
             ? EEM_State::instance()->get_all_states()
755 755
             : EEM_State::instance()->get_all_active_states();
756
-        if (! empty($states)) {
756
+        if ( ! empty($states)) {
757 757
             foreach ($states as $state) {
758 758
                 if ($state instanceof EE_State) {
759
-                    $state_options[ $state->country()->name() ][ $state->ID() ] = $state->name();
759
+                    $state_options[$state->country()->name()][$state->ID()] = $state->name();
760 760
                 }
761 761
             }
762 762
         }
@@ -803,7 +803,7 @@  discard block
 block discarded – undo
803 803
             );
804 804
             return false;
805 805
         }
806
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
806
+        if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
807 807
             EE_Error::add_error(
808 808
                 esc_html__(
809 809
                     'A valid transaction could not be initiated for processing your registrations.',
@@ -830,7 +830,7 @@  discard block
 block discarded – undo
830 830
                     '(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
831 831
                     'event_espresso'
832 832
                 ),
833
-                '<a href="' . get_post_type_archive_link('espresso_events') . '" >',
833
+                '<a href="'.get_post_type_archive_link('espresso_events').'" >',
834 834
                 '</a>',
835 835
                 '<br />'
836 836
             );
@@ -850,7 +850,7 @@  discard block
 block discarded – undo
850 850
             // but return immediately if the previous step exited early due to errors
851 851
             return false;
852 852
         }
853
-        if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
853
+        if ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
854 854
             // generate a correctly translated string for all possible singular/plural combinations
855 855
             if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
856 856
                 $error_msg = sprintf(
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
         // grab the saved registrations from the transaction
934 934
         foreach ($registrations as $registration) {
935 935
             // verify EE_Registration object
936
-            if (! $registration instanceof EE_Registration) {
936
+            if ( ! $registration instanceof EE_Registration) {
937 937
                 EE_Error::add_error(
938 938
                     esc_html__(
939 939
                         'An invalid Registration object was discovered when attempting to process your registration information.',
@@ -948,12 +948,12 @@  discard block
 block discarded – undo
948 948
             /** @var string $reg_url_link */
949 949
             $reg_url_link = $registration->reg_url_link();
950 950
             // reg_url_link exists ?
951
-            if (! empty($reg_url_link)) {
951
+            if ( ! empty($reg_url_link)) {
952 952
                 // should this registration be processed during this visit ?
953 953
                 if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
954 954
                     // if NOT revisiting, then let's save the registration now,
955 955
                     // so that we have a REG_ID to use when generating other objects
956
-                    if (! $this->checkout->revisit) {
956
+                    if ( ! $this->checkout->revisit) {
957 957
                         $registration->save();
958 958
                     }
959 959
                     /**
@@ -977,18 +977,18 @@  discard block
 block discarded – undo
977 977
 
978 978
                     // Houston, we have a registration!
979 979
                     $att_nmbr++;
980
-                    $this->_attendee_data[ $reg_url_link ] = array();
980
+                    $this->_attendee_data[$reg_url_link] = array();
981 981
                     // grab any existing related answer objects
982 982
                     $this->_registration_answers = $registration->answers();
983 983
                     // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
984
-                    if (isset($valid_data[ $reg_url_link ])) {
984
+                    if (isset($valid_data[$reg_url_link])) {
985 985
                         // do we need to copy basic info from primary attendee ?
986
-                        $copy_primary = isset($valid_data[ $reg_url_link ]['additional_attendee_reg_info'])
987
-                                        && absint($valid_data[ $reg_url_link ]['additional_attendee_reg_info']) === 0;
986
+                        $copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
987
+                                        && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0;
988 988
                         // filter form input data for this registration
989
-                        $valid_data[ $reg_url_link ] = (array) apply_filters(
989
+                        $valid_data[$reg_url_link] = (array) apply_filters(
990 990
                             'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
991
-                            $valid_data[ $reg_url_link ]
991
+                            $valid_data[$reg_url_link]
992 992
                         );
993 993
                         if (isset($valid_data['primary_attendee'])) {
994 994
                             $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
@@ -997,12 +997,12 @@  discard block
 block discarded – undo
997 997
                             unset($valid_data['primary_attendee']);
998 998
                         }
999 999
                         // now loop through our array of valid post data && process attendee reg forms
1000
-                        foreach ($valid_data[ $reg_url_link ] as $form_section => $form_inputs) {
1001
-                            if (! in_array($form_section, $non_input_form_sections, true)) {
1000
+                        foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
1001
+                            if ( ! in_array($form_section, $non_input_form_sections, true)) {
1002 1002
                                 foreach ($form_inputs as $form_input => $input_value) {
1003 1003
                                     // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
1004 1004
                                     // check for critical inputs
1005
-                                    if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
1005
+                                    if ( ! $this->_verify_critical_attendee_details_are_set_and_validate_email(
1006 1006
                                         $form_input,
1007 1007
                                         $input_value
1008 1008
                                     )
@@ -1014,15 +1014,15 @@  discard block
 block discarded – undo
1014 1014
                                         && ! empty($input_value)
1015 1015
                                         && $reg_url_link === $primary_registrant['line_item_id']
1016 1016
                                     ) {
1017
-                                        $primary_registrant[ $form_input ] = $input_value;
1017
+                                        $primary_registrant[$form_input] = $input_value;
1018 1018
                                     } elseif ($copy_primary
1019 1019
                                               && $input_value === null
1020
-                                              && isset($primary_registrant[ $form_input ])
1020
+                                              && isset($primary_registrant[$form_input])
1021 1021
                                     ) {
1022
-                                        $input_value = $primary_registrant[ $form_input ];
1022
+                                        $input_value = $primary_registrant[$form_input];
1023 1023
                                     }
1024 1024
                                     // now attempt to save the input data
1025
-                                    if (! $this->_save_registration_form_input(
1025
+                                    if ( ! $this->_save_registration_form_input(
1026 1026
                                         $registration,
1027 1027
                                         $form_input,
1028 1028
                                         $input_value
@@ -1058,15 +1058,15 @@  discard block
 block discarded – undo
1058 1058
                         $attendee = $this->checkout->primary_attendee_obj;
1059 1059
                     } else {
1060 1060
                         // ensure critical details are set for additional attendees
1061
-                        $this->_attendee_data[ $reg_url_link ] = $att_nmbr > 1
1061
+                        $this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1062 1062
                             ? $this->_copy_critical_attendee_details_from_primary_registrant(
1063
-                                $this->_attendee_data[ $reg_url_link ]
1063
+                                $this->_attendee_data[$reg_url_link]
1064 1064
                             )
1065
-                            : $this->_attendee_data[ $reg_url_link ];
1065
+                            : $this->_attendee_data[$reg_url_link];
1066 1066
                         // execute create attendee command (which may return an existing attendee)
1067 1067
                         $attendee = EE_Registry::instance()->BUS->execute(
1068 1068
                             new CreateAttendeeCommand(
1069
-                                $this->_attendee_data[ $reg_url_link ],
1069
+                                $this->_attendee_data[$reg_url_link],
1070 1070
                                 $registration
1071 1071
                             )
1072 1072
                         );
@@ -1079,7 +1079,7 @@  discard block
 block discarded – undo
1079 1079
                     // add relation to registration, set attendee ID, and cache attendee
1080 1080
                     $this->_associate_attendee_with_registration($registration, $attendee);
1081 1081
                     // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1082
-                    if (! $registration->attendee() instanceof EE_Attendee) {
1082
+                    if ( ! $registration->attendee() instanceof EE_Attendee) {
1083 1083
                         EE_Error::add_error(
1084 1084
                             sprintf(
1085 1085
                                 esc_html_x(
@@ -1129,7 +1129,7 @@  discard block
 block discarded – undo
1129 1129
                     __LINE__
1130 1130
                 );
1131 1131
                 // remove malformed data
1132
-                unset($valid_data[ $reg_url_link ]);
1132
+                unset($valid_data[$reg_url_link]);
1133 1133
                 return false;
1134 1134
             }
1135 1135
         } // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
@@ -1175,10 +1175,10 @@  discard block
 block discarded – undo
1175 1175
          * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477
1176 1176
          */
1177 1177
         $answer_cache_id = $this->checkout->reg_url_link
1178
-            ? $form_input . '-' . $registration->reg_url_link()
1178
+            ? $form_input.'-'.$registration->reg_url_link()
1179 1179
             : $form_input;
1180
-        $answer_is_obj = isset($this->_registration_answers[ $answer_cache_id ])
1181
-                         && $this->_registration_answers[ $answer_cache_id ] instanceof EE_Answer;
1180
+        $answer_is_obj = isset($this->_registration_answers[$answer_cache_id])
1181
+                         && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer;
1182 1182
         // rename form_inputs if they are EE_Attendee properties
1183 1183
         switch ((string) $form_input) {
1184 1184
             case 'state':
@@ -1194,28 +1194,28 @@  discard block
 block discarded – undo
1194 1194
                 break;
1195 1195
 
1196 1196
             default:
1197
-                $ATT_input = 'ATT_' . $form_input;
1197
+                $ATT_input = 'ATT_'.$form_input;
1198 1198
                 // EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1199 1199
                 $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1200
-                $form_input = $attendee_property ? 'ATT_' . $form_input : $form_input;
1200
+                $form_input = $attendee_property ? 'ATT_'.$form_input : $form_input;
1201 1201
         }
1202 1202
         // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1203 1203
         // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1204 1204
         // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1205 1205
         // if this form input has a corresponding attendee property
1206 1206
         if ($attendee_property) {
1207
-            $this->_attendee_data[ $registration->reg_url_link() ][ $form_input ] = $input_value;
1207
+            $this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1208 1208
             if ($answer_is_obj) {
1209 1209
                 // and delete the corresponding answer since we won't be storing this data in that object
1210
-                $registration->_remove_relation_to($this->_registration_answers[ $answer_cache_id ], 'Answer');
1211
-                $this->_registration_answers[ $answer_cache_id ]->delete_permanently();
1210
+                $registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1211
+                $this->_registration_answers[$answer_cache_id]->delete_permanently();
1212 1212
             }
1213 1213
             return true;
1214 1214
         }
1215 1215
         if ($answer_is_obj) {
1216 1216
             // save this data to the answer object
1217
-            $this->_registration_answers[ $answer_cache_id ]->set_value($input_value);
1218
-            $result = $this->_registration_answers[ $answer_cache_id ]->save();
1217
+            $this->_registration_answers[$answer_cache_id]->set_value($input_value);
1218
+            $result = $this->_registration_answers[$answer_cache_id]->save();
1219 1219
             return $result !== false;
1220 1220
         }
1221 1221
         foreach ($this->_registration_answers as $answer) {
@@ -1242,7 +1242,7 @@  discard block
 block discarded – undo
1242 1242
     ) {
1243 1243
         if (empty($input_value)) {
1244 1244
             // if the form input isn't marked as being required, then just return
1245
-            if (! isset($this->_required_questions[ $form_input ]) || ! $this->_required_questions[ $form_input ]) {
1245
+            if ( ! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1246 1246
                 return true;
1247 1247
             }
1248 1248
             switch ($form_input) {
@@ -1353,10 +1353,10 @@  discard block
 block discarded – undo
1353 1353
             $critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1354 1354
         }
1355 1355
         foreach ($critical_attendee_details as $critical_attendee_detail) {
1356
-            if (! isset($attendee_data[ $critical_attendee_detail ])
1357
-                || empty($attendee_data[ $critical_attendee_detail ])
1356
+            if ( ! isset($attendee_data[$critical_attendee_detail])
1357
+                || empty($attendee_data[$critical_attendee_detail])
1358 1358
             ) {
1359
-                $attendee_data[ $critical_attendee_detail ] = $this->checkout->primary_attendee_obj->get(
1359
+                $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1360 1360
                     $critical_attendee_detail
1361 1361
                 );
1362 1362
             }
Please login to merge, or discard this patch.
core/EE_System.core.php 1 patch
Indentation   +1256 added lines, -1256 removed lines patch added patch discarded remove patch
@@ -28,1260 +28,1260 @@
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
33
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
34
-     */
35
-    const req_type_normal = 0;
36
-
37
-    /**
38
-     * Indicates this is a brand new installation of EE so we should install
39
-     * tables and default data etc
40
-     */
41
-    const req_type_new_activation = 1;
42
-
43
-    /**
44
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
45
-     * and we just exited maintenance mode). We MUST check the database is setup properly
46
-     * and that default data is setup too
47
-     */
48
-    const req_type_reactivation = 2;
49
-
50
-    /**
51
-     * indicates that EE has been upgraded since its previous request.
52
-     * We may have data migration scripts to call and will want to trigger maintenance mode
53
-     */
54
-    const req_type_upgrade = 3;
55
-
56
-    /**
57
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
58
-     */
59
-    const req_type_downgrade = 4;
60
-
61
-    /**
62
-     * @deprecated since version 4.6.0.dev.006
63
-     * Now whenever a new_activation is detected the request type is still just
64
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
65
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
66
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
67
-     * (Specifically, when the migration manager indicates migrations are finished
68
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
69
-     */
70
-    const req_type_activation_but_not_installed = 5;
71
-
72
-    /**
73
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
74
-     */
75
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
76
-
77
-
78
-    /**
79
-     * @var EE_System $_instance
80
-     */
81
-    private static $_instance;
82
-
83
-    /**
84
-     * @var EE_Registry $registry
85
-     */
86
-    private $registry;
87
-
88
-    /**
89
-     * @var LoaderInterface $loader
90
-     */
91
-    private $loader;
92
-
93
-    /**
94
-     * @var EE_Capabilities $capabilities
95
-     */
96
-    private $capabilities;
97
-
98
-    /**
99
-     * @var RequestInterface $request
100
-     */
101
-    private $request;
102
-
103
-    /**
104
-     * @var EE_Maintenance_Mode $maintenance_mode
105
-     */
106
-    private $maintenance_mode;
107
-
108
-    /**
109
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
110
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
111
-     *
112
-     * @var int $_req_type
113
-     */
114
-    private $_req_type;
115
-
116
-    /**
117
-     * Whether or not there was a non-micro version change in EE core version during this request
118
-     *
119
-     * @var boolean $_major_version_change
120
-     */
121
-    private $_major_version_change = false;
122
-
123
-    /**
124
-     * A Context DTO dedicated solely to identifying the current request type.
125
-     *
126
-     * @var RequestTypeContextCheckerInterface $request_type
127
-     */
128
-    private $request_type;
129
-
130
-
131
-    /**
132
-     * @singleton method used to instantiate class object
133
-     * @param EE_Registry|null         $registry
134
-     * @param LoaderInterface|null     $loader
135
-     * @param RequestInterface|null    $request
136
-     * @param EE_Maintenance_Mode|null $maintenance_mode
137
-     * @return EE_System
138
-     */
139
-    public static function instance(
140
-        EE_Registry $registry = null,
141
-        LoaderInterface $loader = null,
142
-        RequestInterface $request = null,
143
-        EE_Maintenance_Mode $maintenance_mode = null
144
-    ) {
145
-        // check if class object is instantiated
146
-        if (! self::$_instance instanceof EE_System) {
147
-            self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
148
-        }
149
-        return self::$_instance;
150
-    }
151
-
152
-
153
-    /**
154
-     * resets the instance and returns it
155
-     *
156
-     * @return EE_System
157
-     */
158
-    public static function reset()
159
-    {
160
-        self::$_instance->_req_type = null;
161
-        // make sure none of the old hooks are left hanging around
162
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
163
-        // we need to reset the migration manager in order for it to detect DMSs properly
164
-        EE_Data_Migration_Manager::reset();
165
-        self::instance()->detect_activations_or_upgrades();
166
-        self::instance()->perform_activations_upgrades_and_migrations();
167
-        return self::instance();
168
-    }
169
-
170
-
171
-    /**
172
-     * sets hooks for running rest of system
173
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
174
-     * starting EE Addons from any other point may lead to problems
175
-     *
176
-     * @param EE_Registry         $registry
177
-     * @param LoaderInterface     $loader
178
-     * @param RequestInterface    $request
179
-     * @param EE_Maintenance_Mode $maintenance_mode
180
-     */
181
-    private function __construct(
182
-        EE_Registry $registry,
183
-        LoaderInterface $loader,
184
-        RequestInterface $request,
185
-        EE_Maintenance_Mode $maintenance_mode
186
-    ) {
187
-        $this->registry = $registry;
188
-        $this->loader = $loader;
189
-        $this->request = $request;
190
-        $this->maintenance_mode = $maintenance_mode;
191
-        do_action('AHEE__EE_System__construct__begin', $this);
192
-        add_action(
193
-            'AHEE__EE_Bootstrap__load_espresso_addons',
194
-            array($this, 'loadCapabilities'),
195
-            5
196
-        );
197
-        add_action(
198
-            'AHEE__EE_Bootstrap__load_espresso_addons',
199
-            array($this, 'loadCommandBus'),
200
-            7
201
-        );
202
-        add_action(
203
-            'AHEE__EE_Bootstrap__load_espresso_addons',
204
-            array($this, 'loadPluginApi'),
205
-            9
206
-        );
207
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
208
-        add_action(
209
-            'AHEE__EE_Bootstrap__load_espresso_addons',
210
-            array($this, 'load_espresso_addons')
211
-        );
212
-        // when an ee addon is activated, we want to call the core hook(s) again
213
-        // because the newly-activated addon didn't get a chance to run at all
214
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
215
-        // detect whether install or upgrade
216
-        add_action(
217
-            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
218
-            array($this, 'detect_activations_or_upgrades'),
219
-            3
220
-        );
221
-        // load EE_Config, EE_Textdomain, etc
222
-        add_action(
223
-            'AHEE__EE_Bootstrap__load_core_configuration',
224
-            array($this, 'load_core_configuration'),
225
-            5
226
-        );
227
-        // load EE_Config, EE_Textdomain, etc
228
-        add_action(
229
-            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
230
-            array($this, 'register_shortcodes_modules_and_widgets'),
231
-            7
232
-        );
233
-        // you wanna get going? I wanna get going... let's get going!
234
-        add_action(
235
-            'AHEE__EE_Bootstrap__brew_espresso',
236
-            array($this, 'brew_espresso'),
237
-            9
238
-        );
239
-        // other housekeeping
240
-        // exclude EE critical pages from wp_list_pages
241
-        add_filter(
242
-            'wp_list_pages_excludes',
243
-            array($this, 'remove_pages_from_wp_list_pages'),
244
-            10
245
-        );
246
-        // ALL EE Addons should use the following hook point to attach their initial setup too
247
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
248
-        do_action('AHEE__EE_System__construct__complete', $this);
249
-    }
250
-
251
-
252
-    /**
253
-     * load and setup EE_Capabilities
254
-     *
255
-     * @return void
256
-     * @throws EE_Error
257
-     */
258
-    public function loadCapabilities()
259
-    {
260
-        $this->capabilities = $this->loader->getShared('EE_Capabilities');
261
-        add_action(
262
-            'AHEE__EE_Capabilities__init_caps__before_initialization',
263
-            function () {
264
-                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
265
-            }
266
-        );
267
-    }
268
-
269
-
270
-    /**
271
-     * create and cache the CommandBus, and also add middleware
272
-     * The CapChecker middleware requires the use of EE_Capabilities
273
-     * which is why we need to load the CommandBus after Caps are set up
274
-     *
275
-     * @return void
276
-     * @throws EE_Error
277
-     */
278
-    public function loadCommandBus()
279
-    {
280
-        $this->loader->getShared(
281
-            'CommandBusInterface',
282
-            array(
283
-                null,
284
-                apply_filters(
285
-                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
286
-                    array(
287
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
288
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
289
-                    )
290
-                ),
291
-            )
292
-        );
293
-    }
294
-
295
-
296
-    /**
297
-     * @return void
298
-     * @throws EE_Error
299
-     */
300
-    public function loadPluginApi()
301
-    {
302
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
303
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
304
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
305
-        $this->loader->getShared('EE_Request_Handler');
306
-    }
307
-
308
-
309
-    /**
310
-     * @param string $addon_name
311
-     * @param string $version_constant
312
-     * @param string $min_version_required
313
-     * @param string $load_callback
314
-     * @param string $plugin_file_constant
315
-     * @return void
316
-     */
317
-    private function deactivateIncompatibleAddon(
318
-        $addon_name,
319
-        $version_constant,
320
-        $min_version_required,
321
-        $load_callback,
322
-        $plugin_file_constant
323
-    ) {
324
-        if (! defined($version_constant)) {
325
-            return;
326
-        }
327
-        $addon_version = constant($version_constant);
328
-        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
329
-            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
330
-            if (! function_exists('deactivate_plugins')) {
331
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
332
-            }
333
-            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
334
-            unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
335
-            EE_Error::add_error(
336
-                sprintf(
337
-                    esc_html__(
338
-                        'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
339
-                        'event_espresso'
340
-                    ),
341
-                    $addon_name,
342
-                    $min_version_required
343
-                ),
344
-                __FILE__,
345
-                __FUNCTION__ . "({$addon_name})",
346
-                __LINE__
347
-            );
348
-            EE_Error::get_notices(false, true);
349
-        }
350
-    }
351
-
352
-
353
-    /**
354
-     * load_espresso_addons
355
-     * allow addons to load first so that they can set hooks for running DMS's, etc
356
-     * this is hooked into both:
357
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
358
-     *        which runs during the WP 'plugins_loaded' action at priority 5
359
-     *    and the WP 'activate_plugin' hook point
360
-     *
361
-     * @access public
362
-     * @return void
363
-     */
364
-    public function load_espresso_addons()
365
-    {
366
-        $this->deactivateIncompatibleAddon(
367
-            'Wait Lists',
368
-            'EE_WAIT_LISTS_VERSION',
369
-            '1.0.0.beta.074',
370
-            'load_espresso_wait_lists',
371
-            'EE_WAIT_LISTS_PLUGIN_FILE'
372
-        );
373
-        $this->deactivateIncompatibleAddon(
374
-            'Automated Upcoming Event Notifications',
375
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
376
-            '1.0.0.beta.091',
377
-            'load_espresso_automated_upcoming_event_notification',
378
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
379
-        );
380
-        do_action('AHEE__EE_System__load_espresso_addons');
381
-        // if the WP API basic auth plugin isn't already loaded, load it now.
382
-        // We want it for mobile apps. Just include the entire plugin
383
-        // also, don't load the basic auth when a plugin is getting activated, because
384
-        // it could be the basic auth plugin, and it doesn't check if its methods are already defined
385
-        // and causes a fatal error
386
-        if ($this->request->getRequestParam('activate') !== 'true'
387
-            && ! function_exists('json_basic_auth_handler')
388
-            && ! function_exists('json_basic_auth_error')
389
-            && ! in_array(
390
-                $this->request->getRequestParam('action'),
391
-                array('activate', 'activate-selected'),
392
-                true
393
-            )
394
-        ) {
395
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
396
-        }
397
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
398
-    }
399
-
400
-
401
-    /**
402
-     * detect_activations_or_upgrades
403
-     * Checks for activation or upgrade of core first;
404
-     * then also checks if any registered addons have been activated or upgraded
405
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
406
-     * which runs during the WP 'plugins_loaded' action at priority 3
407
-     *
408
-     * @access public
409
-     * @return void
410
-     */
411
-    public function detect_activations_or_upgrades()
412
-    {
413
-        // first off: let's make sure to handle core
414
-        $this->detect_if_activation_or_upgrade();
415
-        foreach ($this->registry->addons as $addon) {
416
-            if ($addon instanceof EE_Addon) {
417
-                // detect teh request type for that addon
418
-                $addon->detect_activation_or_upgrade();
419
-            }
420
-        }
421
-    }
422
-
423
-
424
-    /**
425
-     * detect_if_activation_or_upgrade
426
-     * Takes care of detecting whether this is a brand new install or code upgrade,
427
-     * and either setting up the DB or setting up maintenance mode etc.
428
-     *
429
-     * @access public
430
-     * @return void
431
-     */
432
-    public function detect_if_activation_or_upgrade()
433
-    {
434
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
435
-        // check if db has been updated, or if its a brand-new installation
436
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
437
-        $request_type = $this->detect_req_type($espresso_db_update);
438
-        // EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
439
-        switch ($request_type) {
440
-            case EE_System::req_type_new_activation:
441
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
442
-                $this->_handle_core_version_change($espresso_db_update);
443
-                break;
444
-            case EE_System::req_type_reactivation:
445
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
446
-                $this->_handle_core_version_change($espresso_db_update);
447
-                break;
448
-            case EE_System::req_type_upgrade:
449
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
450
-                // migrations may be required now that we've upgraded
451
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
452
-                $this->_handle_core_version_change($espresso_db_update);
453
-                break;
454
-            case EE_System::req_type_downgrade:
455
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
456
-                // its possible migrations are no longer required
457
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
458
-                $this->_handle_core_version_change($espresso_db_update);
459
-                break;
460
-            case EE_System::req_type_normal:
461
-            default:
462
-                break;
463
-        }
464
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
465
-    }
466
-
467
-
468
-    /**
469
-     * Updates the list of installed versions and sets hooks for
470
-     * initializing the database later during the request
471
-     *
472
-     * @param array $espresso_db_update
473
-     */
474
-    private function _handle_core_version_change($espresso_db_update)
475
-    {
476
-        $this->update_list_of_installed_versions($espresso_db_update);
477
-        // get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
478
-        add_action(
479
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
480
-            array($this, 'initialize_db_if_no_migrations_required')
481
-        );
482
-    }
483
-
484
-
485
-    /**
486
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
487
-     * information about what versions of EE have been installed and activated,
488
-     * NOT necessarily the state of the database
489
-     *
490
-     * @param mixed $espresso_db_update           the value of the WordPress option.
491
-     *                                            If not supplied, fetches it from the options table
492
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
493
-     */
494
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
495
-    {
496
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
497
-        if (! $espresso_db_update) {
498
-            $espresso_db_update = get_option('espresso_db_update');
499
-        }
500
-        // check that option is an array
501
-        if (! is_array($espresso_db_update)) {
502
-            // if option is FALSE, then it never existed
503
-            if ($espresso_db_update === false) {
504
-                // make $espresso_db_update an array and save option with autoload OFF
505
-                $espresso_db_update = array();
506
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
507
-            } else {
508
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
509
-                $espresso_db_update = array($espresso_db_update => array());
510
-                update_option('espresso_db_update', $espresso_db_update);
511
-            }
512
-        } else {
513
-            $corrected_db_update = array();
514
-            // if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
515
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
516
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
517
-                    // the key is an int, and the value IS NOT an array
518
-                    // so it must be numerically-indexed, where values are versions installed...
519
-                    // fix it!
520
-                    $version_string = $should_be_array;
521
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
522
-                } else {
523
-                    // ok it checks out
524
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
525
-                }
526
-            }
527
-            $espresso_db_update = $corrected_db_update;
528
-            update_option('espresso_db_update', $espresso_db_update);
529
-        }
530
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
531
-        return $espresso_db_update;
532
-    }
533
-
534
-
535
-    /**
536
-     * Does the traditional work of setting up the plugin's database and adding default data.
537
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
538
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
539
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
540
-     * so that it will be done when migrations are finished
541
-     *
542
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
543
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
544
-     *                                       This is a resource-intensive job
545
-     *                                       so we prefer to only do it when necessary
546
-     * @return void
547
-     * @throws EE_Error
548
-     */
549
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
550
-    {
551
-        $request_type = $this->detect_req_type();
552
-        // only initialize system if we're not in maintenance mode.
553
-        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
554
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
555
-            $rewrite_rules = $this->loader->getShared(
556
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
557
-            );
558
-            $rewrite_rules->flush();
559
-            if ($verify_schema) {
560
-                EEH_Activation::initialize_db_and_folders();
561
-            }
562
-            EEH_Activation::initialize_db_content();
563
-            EEH_Activation::system_initialization();
564
-            if ($initialize_addons_too) {
565
-                $this->initialize_addons();
566
-            }
567
-        } else {
568
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
569
-        }
570
-        if ($request_type === EE_System::req_type_new_activation
571
-            || $request_type === EE_System::req_type_reactivation
572
-            || (
573
-                $request_type === EE_System::req_type_upgrade
574
-                && $this->is_major_version_change()
575
-            )
576
-        ) {
577
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
578
-        }
579
-    }
580
-
581
-
582
-    /**
583
-     * Initializes the db for all registered addons
584
-     *
585
-     * @throws EE_Error
586
-     */
587
-    public function initialize_addons()
588
-    {
589
-        // foreach registered addon, make sure its db is up-to-date too
590
-        foreach ($this->registry->addons as $addon) {
591
-            if ($addon instanceof EE_Addon) {
592
-                $addon->initialize_db_if_no_migrations_required();
593
-            }
594
-        }
595
-    }
596
-
597
-
598
-    /**
599
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
600
-     *
601
-     * @param    array  $version_history
602
-     * @param    string $current_version_to_add version to be added to the version history
603
-     * @return    boolean success as to whether or not this option was changed
604
-     */
605
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
606
-    {
607
-        if (! $version_history) {
608
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
609
-        }
610
-        if ($current_version_to_add === null) {
611
-            $current_version_to_add = espresso_version();
612
-        }
613
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
614
-        // re-save
615
-        return update_option('espresso_db_update', $version_history);
616
-    }
617
-
618
-
619
-    /**
620
-     * Detects if the current version indicated in the has existed in the list of
621
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
622
-     *
623
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
624
-     *                                  If not supplied, fetches it from the options table.
625
-     *                                  Also, caches its result so later parts of the code can also know whether
626
-     *                                  there's been an update or not. This way we can add the current version to
627
-     *                                  espresso_db_update, but still know if this is a new install or not
628
-     * @return int one of the constants on EE_System::req_type_
629
-     */
630
-    public function detect_req_type($espresso_db_update = null)
631
-    {
632
-        if ($this->_req_type === null) {
633
-            $espresso_db_update = ! empty($espresso_db_update)
634
-                ? $espresso_db_update
635
-                : $this->fix_espresso_db_upgrade_option();
636
-            $this->_req_type = EE_System::detect_req_type_given_activation_history(
637
-                $espresso_db_update,
638
-                'ee_espresso_activation',
639
-                espresso_version()
640
-            );
641
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
642
-            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
643
-        }
644
-        return $this->_req_type;
645
-    }
646
-
647
-
648
-    /**
649
-     * Returns whether or not there was a non-micro version change (ie, change in either
650
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
651
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
652
-     *
653
-     * @param $activation_history
654
-     * @return bool
655
-     */
656
-    private function _detect_major_version_change($activation_history)
657
-    {
658
-        $previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
659
-        $previous_version_parts = explode('.', $previous_version);
660
-        $current_version_parts = explode('.', espresso_version());
661
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
662
-               && ($previous_version_parts[0] !== $current_version_parts[0]
663
-                   || $previous_version_parts[1] !== $current_version_parts[1]
664
-               );
665
-    }
666
-
667
-
668
-    /**
669
-     * Returns true if either the major or minor version of EE changed during this request.
670
-     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
671
-     *
672
-     * @return bool
673
-     */
674
-    public function is_major_version_change()
675
-    {
676
-        return $this->_major_version_change;
677
-    }
678
-
679
-
680
-    /**
681
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
682
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
683
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
684
-     * just activated to (for core that will always be espresso_version())
685
-     *
686
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
687
-     *                                                 ee plugin. for core that's 'espresso_db_update'
688
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
689
-     *                                                 indicate that this plugin was just activated
690
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
691
-     *                                                 espresso_version())
692
-     * @return int one of the constants on EE_System::req_type_*
693
-     */
694
-    public static function detect_req_type_given_activation_history(
695
-        $activation_history_for_addon,
696
-        $activation_indicator_option_name,
697
-        $version_to_upgrade_to
698
-    ) {
699
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
700
-        if ($activation_history_for_addon) {
701
-            // it exists, so this isn't a completely new install
702
-            // check if this version already in that list of previously installed versions
703
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
704
-                // it a version we haven't seen before
705
-                if ($version_is_higher === 1) {
706
-                    $req_type = EE_System::req_type_upgrade;
707
-                } else {
708
-                    $req_type = EE_System::req_type_downgrade;
709
-                }
710
-                delete_option($activation_indicator_option_name);
711
-            } else {
712
-                // its not an update. maybe a reactivation?
713
-                if (get_option($activation_indicator_option_name, false)) {
714
-                    if ($version_is_higher === -1) {
715
-                        $req_type = EE_System::req_type_downgrade;
716
-                    } elseif ($version_is_higher === 0) {
717
-                        // we've seen this version before, but it's an activation. must be a reactivation
718
-                        $req_type = EE_System::req_type_reactivation;
719
-                    } else {// $version_is_higher === 1
720
-                        $req_type = EE_System::req_type_upgrade;
721
-                    }
722
-                    delete_option($activation_indicator_option_name);
723
-                } else {
724
-                    // we've seen this version before and the activation indicate doesn't show it was just activated
725
-                    if ($version_is_higher === -1) {
726
-                        $req_type = EE_System::req_type_downgrade;
727
-                    } elseif ($version_is_higher === 0) {
728
-                        // we've seen this version before and it's not an activation. its normal request
729
-                        $req_type = EE_System::req_type_normal;
730
-                    } else {// $version_is_higher === 1
731
-                        $req_type = EE_System::req_type_upgrade;
732
-                    }
733
-                }
734
-            }
735
-        } else {
736
-            // brand new install
737
-            $req_type = EE_System::req_type_new_activation;
738
-            delete_option($activation_indicator_option_name);
739
-        }
740
-        return $req_type;
741
-    }
742
-
743
-
744
-    /**
745
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
746
-     * the $activation_history_for_addon
747
-     *
748
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
749
-     *                                             sometimes containing 'unknown-date'
750
-     * @param string $version_to_upgrade_to        (current version)
751
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
752
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
753
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
754
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
755
-     */
756
-    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
757
-    {
758
-        // find the most recently-activated version
759
-        $most_recently_active_version =
760
-            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
761
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
762
-    }
763
-
764
-
765
-    /**
766
-     * Gets the most recently active version listed in the activation history,
767
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
768
-     *
769
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
770
-     *                                   sometimes containing 'unknown-date'
771
-     * @return string
772
-     */
773
-    private static function _get_most_recently_active_version_from_activation_history($activation_history)
774
-    {
775
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
776
-        $most_recently_active_version = '0.0.0.dev.000';
777
-        if (is_array($activation_history)) {
778
-            foreach ($activation_history as $version => $times_activated) {
779
-                // check there is a record of when this version was activated. Otherwise,
780
-                // mark it as unknown
781
-                if (! $times_activated) {
782
-                    $times_activated = array('unknown-date');
783
-                }
784
-                if (is_string($times_activated)) {
785
-                    $times_activated = array($times_activated);
786
-                }
787
-                foreach ($times_activated as $an_activation) {
788
-                    if ($an_activation !== 'unknown-date'
789
-                        && $an_activation
790
-                           > $most_recently_active_version_activation) {
791
-                        $most_recently_active_version = $version;
792
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
793
-                            ? '1970-01-01 00:00:00'
794
-                            : $an_activation;
795
-                    }
796
-                }
797
-            }
798
-        }
799
-        return $most_recently_active_version;
800
-    }
801
-
802
-
803
-    /**
804
-     * This redirects to the about EE page after activation
805
-     *
806
-     * @return void
807
-     */
808
-    public function redirect_to_about_ee()
809
-    {
810
-        $notices = EE_Error::get_notices(false);
811
-        // if current user is an admin and it's not an ajax or rest request
812
-        if (! isset($notices['errors'])
813
-            && $this->request->isAdmin()
814
-            && apply_filters(
815
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
816
-                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
817
-            )
818
-        ) {
819
-            $query_params = array('page' => 'espresso_about');
820
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
821
-                $query_params['new_activation'] = true;
822
-            }
823
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
824
-                $query_params['reactivation'] = true;
825
-            }
826
-            $url = add_query_arg($query_params, admin_url('admin.php'));
827
-            wp_safe_redirect($url);
828
-            exit();
829
-        }
830
-    }
831
-
832
-
833
-    /**
834
-     * load_core_configuration
835
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
836
-     * which runs during the WP 'plugins_loaded' action at priority 5
837
-     *
838
-     * @return void
839
-     * @throws ReflectionException
840
-     */
841
-    public function load_core_configuration()
842
-    {
843
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
844
-        $this->loader->getShared('EE_Load_Textdomain');
845
-        // load textdomain
846
-        EE_Load_Textdomain::load_textdomain();
847
-        // load and setup EE_Config and EE_Network_Config
848
-        $config = $this->loader->getShared('EE_Config');
849
-        $this->loader->getShared('EE_Network_Config');
850
-        // setup autoloaders
851
-        // enable logging?
852
-        if ($config->admin->use_full_logging) {
853
-            $this->loader->getShared('EE_Log');
854
-        }
855
-        // check for activation errors
856
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
857
-        if ($activation_errors) {
858
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
859
-            update_option('ee_plugin_activation_errors', false);
860
-        }
861
-        // get model names
862
-        $this->_parse_model_names();
863
-        // load caf stuff a chance to play during the activation process too.
864
-        $this->_maybe_brew_regular();
865
-        // configure custom post type definitions
866
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
867
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
868
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
869
-    }
870
-
871
-
872
-    /**
873
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
874
-     *
875
-     * @return void
876
-     * @throws ReflectionException
877
-     */
878
-    private function _parse_model_names()
879
-    {
880
-        // get all the files in the EE_MODELS folder that end in .model.php
881
-        $models = glob(EE_MODELS . '*.model.php');
882
-        $model_names = array();
883
-        $non_abstract_db_models = array();
884
-        foreach ($models as $model) {
885
-            // get model classname
886
-            $classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
887
-            $short_name = str_replace('EEM_', '', $classname);
888
-            $reflectionClass = new ReflectionClass($classname);
889
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
890
-                $non_abstract_db_models[ $short_name ] = $classname;
891
-            }
892
-            $model_names[ $short_name ] = $classname;
893
-        }
894
-        $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
895
-        $this->registry->non_abstract_db_models = apply_filters(
896
-            'FHEE__EE_System__parse_implemented_model_names',
897
-            $non_abstract_db_models
898
-        );
899
-    }
900
-
901
-
902
-    /**
903
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
904
-     * that need to be setup before our EE_System launches.
905
-     *
906
-     * @return void
907
-     * @throws DomainException
908
-     * @throws InvalidArgumentException
909
-     * @throws InvalidDataTypeException
910
-     * @throws InvalidInterfaceException
911
-     * @throws InvalidClassException
912
-     * @throws InvalidFilePathException
913
-     */
914
-    private function _maybe_brew_regular()
915
-    {
916
-        /** @var Domain $domain */
917
-        $domain = DomainFactory::getShared(
918
-            new FullyQualifiedName(
919
-                'EventEspresso\core\domain\Domain'
920
-            ),
921
-            array(
922
-                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
923
-                Version::fromString(espresso_version()),
924
-            )
925
-        );
926
-        if ($domain->isCaffeinated()) {
927
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
928
-        }
929
-    }
930
-
931
-
932
-    /**
933
-     * register_shortcodes_modules_and_widgets
934
-     * generate lists of shortcodes and modules, then verify paths and classes
935
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
936
-     * which runs during the WP 'plugins_loaded' action at priority 7
937
-     *
938
-     * @access public
939
-     * @return void
940
-     * @throws Exception
941
-     */
942
-    public function register_shortcodes_modules_and_widgets()
943
-    {
944
-        try {
945
-            // load, register, and add shortcodes the new way
946
-            if ($this->request->isFrontend() || $this->request->isIframe()) {
947
-                $this->loader->getShared(
948
-                    'EventEspresso\core\services\shortcodes\ShortcodesManager',
949
-                    array(
950
-                        // and the old way, but we'll put it under control of the new system
951
-                        EE_Config::getLegacyShortcodesManager(),
952
-                    )
953
-                );
954
-            }
955
-        } catch (Exception $exception) {
956
-            new ExceptionStackTraceDisplay($exception);
957
-        }
958
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
959
-        // check for addons using old hook point
960
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
961
-            $this->_incompatible_addon_error();
962
-        }
963
-    }
964
-
965
-
966
-    /**
967
-     * _incompatible_addon_error
968
-     *
969
-     * @access public
970
-     * @return void
971
-     */
972
-    private function _incompatible_addon_error()
973
-    {
974
-        // get array of classes hooking into here
975
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
976
-            'AHEE__EE_System__register_shortcodes_modules_and_addons'
977
-        );
978
-        if (! empty($class_names)) {
979
-            $msg = __(
980
-                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
981
-                'event_espresso'
982
-            );
983
-            $msg .= '<ul>';
984
-            foreach ($class_names as $class_name) {
985
-                $msg .= '<li><b>Event Espresso - '
986
-                        . str_replace(
987
-                            array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
988
-                            '',
989
-                            $class_name
990
-                        ) . '</b></li>';
991
-            }
992
-            $msg .= '</ul>';
993
-            $msg .= __(
994
-                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
995
-                'event_espresso'
996
-            );
997
-            // save list of incompatible addons to wp-options for later use
998
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
999
-            if (is_admin()) {
1000
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1001
-            }
1002
-        }
1003
-    }
1004
-
1005
-
1006
-    /**
1007
-     * brew_espresso
1008
-     * begins the process of setting hooks for initializing EE in the correct order
1009
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1010
-     * which runs during the WP 'plugins_loaded' action at priority 9
1011
-     *
1012
-     * @return void
1013
-     */
1014
-    public function brew_espresso()
1015
-    {
1016
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1017
-        // load some final core systems
1018
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
1019
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1020
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1021
-        add_action('init', array($this, 'load_controllers'), 7);
1022
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1023
-        add_action('init', array($this, 'initialize'), 10);
1024
-        add_action('init', array($this, 'initialize_last'), 100);
1025
-        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1026
-            // pew pew pew
1027
-            $this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1028
-            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1029
-        }
1030
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1031
-    }
1032
-
1033
-
1034
-    /**
1035
-     *    set_hooks_for_core
1036
-     *
1037
-     * @access public
1038
-     * @return    void
1039
-     * @throws EE_Error
1040
-     */
1041
-    public function set_hooks_for_core()
1042
-    {
1043
-        $this->_deactivate_incompatible_addons();
1044
-        do_action('AHEE__EE_System__set_hooks_for_core');
1045
-        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1046
-        // caps need to be initialized on every request so that capability maps are set.
1047
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1048
-        $this->registry->CAP->init_caps();
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * Using the information gathered in EE_System::_incompatible_addon_error,
1054
-     * deactivates any addons considered incompatible with the current version of EE
1055
-     */
1056
-    private function _deactivate_incompatible_addons()
1057
-    {
1058
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
1059
-        if (! empty($incompatible_addons)) {
1060
-            $active_plugins = get_option('active_plugins', array());
1061
-            foreach ($active_plugins as $active_plugin) {
1062
-                foreach ($incompatible_addons as $incompatible_addon) {
1063
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1064
-                        unset($_GET['activate']);
1065
-                        espresso_deactivate_plugin($active_plugin);
1066
-                    }
1067
-                }
1068
-            }
1069
-        }
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     *    perform_activations_upgrades_and_migrations
1075
-     *
1076
-     * @access public
1077
-     * @return    void
1078
-     */
1079
-    public function perform_activations_upgrades_and_migrations()
1080
-    {
1081
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1082
-    }
1083
-
1084
-
1085
-    /**
1086
-     * @return void
1087
-     * @throws DomainException
1088
-     */
1089
-    public function load_CPTs_and_session()
1090
-    {
1091
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1092
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1093
-        $register_custom_taxonomies = $this->loader->getShared(
1094
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1095
-        );
1096
-        $register_custom_taxonomies->registerCustomTaxonomies();
1097
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1098
-        $register_custom_post_types = $this->loader->getShared(
1099
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1100
-        );
1101
-        $register_custom_post_types->registerCustomPostTypes();
1102
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1103
-        $register_custom_taxonomy_terms = $this->loader->getShared(
1104
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1105
-        );
1106
-        $register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1107
-        // load legacy Custom Post Types and Taxonomies
1108
-        $this->loader->getShared('EE_Register_CPTs');
1109
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1110
-    }
1111
-
1112
-
1113
-    /**
1114
-     * load_controllers
1115
-     * this is the best place to load any additional controllers that needs access to EE core.
1116
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1117
-     * time
1118
-     *
1119
-     * @access public
1120
-     * @return void
1121
-     */
1122
-    public function load_controllers()
1123
-    {
1124
-        do_action('AHEE__EE_System__load_controllers__start');
1125
-        // let's get it started
1126
-        if (! $this->maintenance_mode->level()
1127
-            && ($this->request->isFrontend() || $this->request->isFrontAjax())
1128
-        ) {
1129
-            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1130
-            $this->loader->getShared('EE_Front_Controller');
1131
-        } elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1132
-            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1133
-            $this->loader->getShared('EE_Admin');
1134
-        }
1135
-        do_action('AHEE__EE_System__load_controllers__complete');
1136
-    }
1137
-
1138
-
1139
-    /**
1140
-     * core_loaded_and_ready
1141
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1142
-     *
1143
-     * @access public
1144
-     * @return void
1145
-     */
1146
-    public function core_loaded_and_ready()
1147
-    {
1148
-        if ($this->request->isAdmin()
1149
-            || $this->request->isEeAjax()
1150
-            || $this->request->isFrontend()
1151
-        ) {
1152
-            $this->loader->getShared('EE_Session');
1153
-        }
1154
-        do_action('AHEE__EE_System__core_loaded_and_ready');
1155
-        // load_espresso_template_tags
1156
-        if (is_readable(EE_PUBLIC . 'template_tags.php')
1157
-            && (
1158
-                $this->request->isFrontend()
1159
-                || $this->request->isAdmin()
1160
-                || $this->request->isIframe()
1161
-                || $this->request->isFeed()
1162
-            )
1163
-        ) {
1164
-            require_once EE_PUBLIC . 'template_tags.php';
1165
-        }
1166
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1167
-        if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1168
-            $this->loader->getShared('EventEspresso\core\services\assets\Registry');
1169
-        }
1170
-    }
1171
-
1172
-
1173
-    /**
1174
-     * initialize
1175
-     * this is the best place to begin initializing client code
1176
-     *
1177
-     * @access public
1178
-     * @return void
1179
-     */
1180
-    public function initialize()
1181
-    {
1182
-        do_action('AHEE__EE_System__initialize');
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * initialize_last
1188
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1189
-     * initialize has done so
1190
-     *
1191
-     * @access public
1192
-     * @return void
1193
-     */
1194
-    public function initialize_last()
1195
-    {
1196
-        do_action('AHEE__EE_System__initialize_last');
1197
-        /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1198
-        $rewrite_rules = $this->loader->getShared(
1199
-            'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1200
-        );
1201
-        $rewrite_rules->flushRewriteRules();
1202
-        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * @return void
1208
-     * @throws EE_Error
1209
-     */
1210
-    public function addEspressoToolbar()
1211
-    {
1212
-        $this->loader->getShared(
1213
-            'EventEspresso\core\domain\services\admin\AdminToolBar',
1214
-            array($this->registry->CAP)
1215
-        );
1216
-    }
1217
-
1218
-
1219
-    /**
1220
-     * do_not_cache
1221
-     * sets no cache headers and defines no cache constants for WP plugins
1222
-     *
1223
-     * @access public
1224
-     * @return void
1225
-     */
1226
-    public static function do_not_cache()
1227
-    {
1228
-        // set no cache constants
1229
-        if (! defined('DONOTCACHEPAGE')) {
1230
-            define('DONOTCACHEPAGE', true);
1231
-        }
1232
-        if (! defined('DONOTCACHCEOBJECT')) {
1233
-            define('DONOTCACHCEOBJECT', true);
1234
-        }
1235
-        if (! defined('DONOTCACHEDB')) {
1236
-            define('DONOTCACHEDB', true);
1237
-        }
1238
-        // add no cache headers
1239
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1240
-        // plus a little extra for nginx and Google Chrome
1241
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1242
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1243
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     *    extra_nocache_headers
1249
-     *
1250
-     * @access    public
1251
-     * @param $headers
1252
-     * @return    array
1253
-     */
1254
-    public static function extra_nocache_headers($headers)
1255
-    {
1256
-        // for NGINX
1257
-        $headers['X-Accel-Expires'] = 0;
1258
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1259
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1260
-        return $headers;
1261
-    }
1262
-
1263
-
1264
-    /**
1265
-     *    nocache_headers
1266
-     *
1267
-     * @access    public
1268
-     * @return    void
1269
-     */
1270
-    public static function nocache_headers()
1271
-    {
1272
-        nocache_headers();
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1278
-     * never returned with the function.
1279
-     *
1280
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1281
-     * @return array
1282
-     */
1283
-    public function remove_pages_from_wp_list_pages($exclude_array)
1284
-    {
1285
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1286
-    }
31
+	/**
32
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
33
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
34
+	 */
35
+	const req_type_normal = 0;
36
+
37
+	/**
38
+	 * Indicates this is a brand new installation of EE so we should install
39
+	 * tables and default data etc
40
+	 */
41
+	const req_type_new_activation = 1;
42
+
43
+	/**
44
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
45
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
46
+	 * and that default data is setup too
47
+	 */
48
+	const req_type_reactivation = 2;
49
+
50
+	/**
51
+	 * indicates that EE has been upgraded since its previous request.
52
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
53
+	 */
54
+	const req_type_upgrade = 3;
55
+
56
+	/**
57
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
58
+	 */
59
+	const req_type_downgrade = 4;
60
+
61
+	/**
62
+	 * @deprecated since version 4.6.0.dev.006
63
+	 * Now whenever a new_activation is detected the request type is still just
64
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
65
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
66
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
67
+	 * (Specifically, when the migration manager indicates migrations are finished
68
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
69
+	 */
70
+	const req_type_activation_but_not_installed = 5;
71
+
72
+	/**
73
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
74
+	 */
75
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
76
+
77
+
78
+	/**
79
+	 * @var EE_System $_instance
80
+	 */
81
+	private static $_instance;
82
+
83
+	/**
84
+	 * @var EE_Registry $registry
85
+	 */
86
+	private $registry;
87
+
88
+	/**
89
+	 * @var LoaderInterface $loader
90
+	 */
91
+	private $loader;
92
+
93
+	/**
94
+	 * @var EE_Capabilities $capabilities
95
+	 */
96
+	private $capabilities;
97
+
98
+	/**
99
+	 * @var RequestInterface $request
100
+	 */
101
+	private $request;
102
+
103
+	/**
104
+	 * @var EE_Maintenance_Mode $maintenance_mode
105
+	 */
106
+	private $maintenance_mode;
107
+
108
+	/**
109
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
110
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
111
+	 *
112
+	 * @var int $_req_type
113
+	 */
114
+	private $_req_type;
115
+
116
+	/**
117
+	 * Whether or not there was a non-micro version change in EE core version during this request
118
+	 *
119
+	 * @var boolean $_major_version_change
120
+	 */
121
+	private $_major_version_change = false;
122
+
123
+	/**
124
+	 * A Context DTO dedicated solely to identifying the current request type.
125
+	 *
126
+	 * @var RequestTypeContextCheckerInterface $request_type
127
+	 */
128
+	private $request_type;
129
+
130
+
131
+	/**
132
+	 * @singleton method used to instantiate class object
133
+	 * @param EE_Registry|null         $registry
134
+	 * @param LoaderInterface|null     $loader
135
+	 * @param RequestInterface|null    $request
136
+	 * @param EE_Maintenance_Mode|null $maintenance_mode
137
+	 * @return EE_System
138
+	 */
139
+	public static function instance(
140
+		EE_Registry $registry = null,
141
+		LoaderInterface $loader = null,
142
+		RequestInterface $request = null,
143
+		EE_Maintenance_Mode $maintenance_mode = null
144
+	) {
145
+		// check if class object is instantiated
146
+		if (! self::$_instance instanceof EE_System) {
147
+			self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
148
+		}
149
+		return self::$_instance;
150
+	}
151
+
152
+
153
+	/**
154
+	 * resets the instance and returns it
155
+	 *
156
+	 * @return EE_System
157
+	 */
158
+	public static function reset()
159
+	{
160
+		self::$_instance->_req_type = null;
161
+		// make sure none of the old hooks are left hanging around
162
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
163
+		// we need to reset the migration manager in order for it to detect DMSs properly
164
+		EE_Data_Migration_Manager::reset();
165
+		self::instance()->detect_activations_or_upgrades();
166
+		self::instance()->perform_activations_upgrades_and_migrations();
167
+		return self::instance();
168
+	}
169
+
170
+
171
+	/**
172
+	 * sets hooks for running rest of system
173
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
174
+	 * starting EE Addons from any other point may lead to problems
175
+	 *
176
+	 * @param EE_Registry         $registry
177
+	 * @param LoaderInterface     $loader
178
+	 * @param RequestInterface    $request
179
+	 * @param EE_Maintenance_Mode $maintenance_mode
180
+	 */
181
+	private function __construct(
182
+		EE_Registry $registry,
183
+		LoaderInterface $loader,
184
+		RequestInterface $request,
185
+		EE_Maintenance_Mode $maintenance_mode
186
+	) {
187
+		$this->registry = $registry;
188
+		$this->loader = $loader;
189
+		$this->request = $request;
190
+		$this->maintenance_mode = $maintenance_mode;
191
+		do_action('AHEE__EE_System__construct__begin', $this);
192
+		add_action(
193
+			'AHEE__EE_Bootstrap__load_espresso_addons',
194
+			array($this, 'loadCapabilities'),
195
+			5
196
+		);
197
+		add_action(
198
+			'AHEE__EE_Bootstrap__load_espresso_addons',
199
+			array($this, 'loadCommandBus'),
200
+			7
201
+		);
202
+		add_action(
203
+			'AHEE__EE_Bootstrap__load_espresso_addons',
204
+			array($this, 'loadPluginApi'),
205
+			9
206
+		);
207
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
208
+		add_action(
209
+			'AHEE__EE_Bootstrap__load_espresso_addons',
210
+			array($this, 'load_espresso_addons')
211
+		);
212
+		// when an ee addon is activated, we want to call the core hook(s) again
213
+		// because the newly-activated addon didn't get a chance to run at all
214
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
215
+		// detect whether install or upgrade
216
+		add_action(
217
+			'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
218
+			array($this, 'detect_activations_or_upgrades'),
219
+			3
220
+		);
221
+		// load EE_Config, EE_Textdomain, etc
222
+		add_action(
223
+			'AHEE__EE_Bootstrap__load_core_configuration',
224
+			array($this, 'load_core_configuration'),
225
+			5
226
+		);
227
+		// load EE_Config, EE_Textdomain, etc
228
+		add_action(
229
+			'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
230
+			array($this, 'register_shortcodes_modules_and_widgets'),
231
+			7
232
+		);
233
+		// you wanna get going? I wanna get going... let's get going!
234
+		add_action(
235
+			'AHEE__EE_Bootstrap__brew_espresso',
236
+			array($this, 'brew_espresso'),
237
+			9
238
+		);
239
+		// other housekeeping
240
+		// exclude EE critical pages from wp_list_pages
241
+		add_filter(
242
+			'wp_list_pages_excludes',
243
+			array($this, 'remove_pages_from_wp_list_pages'),
244
+			10
245
+		);
246
+		// ALL EE Addons should use the following hook point to attach their initial setup too
247
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
248
+		do_action('AHEE__EE_System__construct__complete', $this);
249
+	}
250
+
251
+
252
+	/**
253
+	 * load and setup EE_Capabilities
254
+	 *
255
+	 * @return void
256
+	 * @throws EE_Error
257
+	 */
258
+	public function loadCapabilities()
259
+	{
260
+		$this->capabilities = $this->loader->getShared('EE_Capabilities');
261
+		add_action(
262
+			'AHEE__EE_Capabilities__init_caps__before_initialization',
263
+			function () {
264
+				LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
265
+			}
266
+		);
267
+	}
268
+
269
+
270
+	/**
271
+	 * create and cache the CommandBus, and also add middleware
272
+	 * The CapChecker middleware requires the use of EE_Capabilities
273
+	 * which is why we need to load the CommandBus after Caps are set up
274
+	 *
275
+	 * @return void
276
+	 * @throws EE_Error
277
+	 */
278
+	public function loadCommandBus()
279
+	{
280
+		$this->loader->getShared(
281
+			'CommandBusInterface',
282
+			array(
283
+				null,
284
+				apply_filters(
285
+					'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
286
+					array(
287
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
288
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
289
+					)
290
+				),
291
+			)
292
+		);
293
+	}
294
+
295
+
296
+	/**
297
+	 * @return void
298
+	 * @throws EE_Error
299
+	 */
300
+	public function loadPluginApi()
301
+	{
302
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
303
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
304
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
305
+		$this->loader->getShared('EE_Request_Handler');
306
+	}
307
+
308
+
309
+	/**
310
+	 * @param string $addon_name
311
+	 * @param string $version_constant
312
+	 * @param string $min_version_required
313
+	 * @param string $load_callback
314
+	 * @param string $plugin_file_constant
315
+	 * @return void
316
+	 */
317
+	private function deactivateIncompatibleAddon(
318
+		$addon_name,
319
+		$version_constant,
320
+		$min_version_required,
321
+		$load_callback,
322
+		$plugin_file_constant
323
+	) {
324
+		if (! defined($version_constant)) {
325
+			return;
326
+		}
327
+		$addon_version = constant($version_constant);
328
+		if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
329
+			remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
330
+			if (! function_exists('deactivate_plugins')) {
331
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
332
+			}
333
+			deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
334
+			unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
335
+			EE_Error::add_error(
336
+				sprintf(
337
+					esc_html__(
338
+						'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
339
+						'event_espresso'
340
+					),
341
+					$addon_name,
342
+					$min_version_required
343
+				),
344
+				__FILE__,
345
+				__FUNCTION__ . "({$addon_name})",
346
+				__LINE__
347
+			);
348
+			EE_Error::get_notices(false, true);
349
+		}
350
+	}
351
+
352
+
353
+	/**
354
+	 * load_espresso_addons
355
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
356
+	 * this is hooked into both:
357
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
358
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
359
+	 *    and the WP 'activate_plugin' hook point
360
+	 *
361
+	 * @access public
362
+	 * @return void
363
+	 */
364
+	public function load_espresso_addons()
365
+	{
366
+		$this->deactivateIncompatibleAddon(
367
+			'Wait Lists',
368
+			'EE_WAIT_LISTS_VERSION',
369
+			'1.0.0.beta.074',
370
+			'load_espresso_wait_lists',
371
+			'EE_WAIT_LISTS_PLUGIN_FILE'
372
+		);
373
+		$this->deactivateIncompatibleAddon(
374
+			'Automated Upcoming Event Notifications',
375
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
376
+			'1.0.0.beta.091',
377
+			'load_espresso_automated_upcoming_event_notification',
378
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
379
+		);
380
+		do_action('AHEE__EE_System__load_espresso_addons');
381
+		// if the WP API basic auth plugin isn't already loaded, load it now.
382
+		// We want it for mobile apps. Just include the entire plugin
383
+		// also, don't load the basic auth when a plugin is getting activated, because
384
+		// it could be the basic auth plugin, and it doesn't check if its methods are already defined
385
+		// and causes a fatal error
386
+		if ($this->request->getRequestParam('activate') !== 'true'
387
+			&& ! function_exists('json_basic_auth_handler')
388
+			&& ! function_exists('json_basic_auth_error')
389
+			&& ! in_array(
390
+				$this->request->getRequestParam('action'),
391
+				array('activate', 'activate-selected'),
392
+				true
393
+			)
394
+		) {
395
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
396
+		}
397
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
398
+	}
399
+
400
+
401
+	/**
402
+	 * detect_activations_or_upgrades
403
+	 * Checks for activation or upgrade of core first;
404
+	 * then also checks if any registered addons have been activated or upgraded
405
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
406
+	 * which runs during the WP 'plugins_loaded' action at priority 3
407
+	 *
408
+	 * @access public
409
+	 * @return void
410
+	 */
411
+	public function detect_activations_or_upgrades()
412
+	{
413
+		// first off: let's make sure to handle core
414
+		$this->detect_if_activation_or_upgrade();
415
+		foreach ($this->registry->addons as $addon) {
416
+			if ($addon instanceof EE_Addon) {
417
+				// detect teh request type for that addon
418
+				$addon->detect_activation_or_upgrade();
419
+			}
420
+		}
421
+	}
422
+
423
+
424
+	/**
425
+	 * detect_if_activation_or_upgrade
426
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
427
+	 * and either setting up the DB or setting up maintenance mode etc.
428
+	 *
429
+	 * @access public
430
+	 * @return void
431
+	 */
432
+	public function detect_if_activation_or_upgrade()
433
+	{
434
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
435
+		// check if db has been updated, or if its a brand-new installation
436
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
437
+		$request_type = $this->detect_req_type($espresso_db_update);
438
+		// EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
439
+		switch ($request_type) {
440
+			case EE_System::req_type_new_activation:
441
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
442
+				$this->_handle_core_version_change($espresso_db_update);
443
+				break;
444
+			case EE_System::req_type_reactivation:
445
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
446
+				$this->_handle_core_version_change($espresso_db_update);
447
+				break;
448
+			case EE_System::req_type_upgrade:
449
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
450
+				// migrations may be required now that we've upgraded
451
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
452
+				$this->_handle_core_version_change($espresso_db_update);
453
+				break;
454
+			case EE_System::req_type_downgrade:
455
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
456
+				// its possible migrations are no longer required
457
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
458
+				$this->_handle_core_version_change($espresso_db_update);
459
+				break;
460
+			case EE_System::req_type_normal:
461
+			default:
462
+				break;
463
+		}
464
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
465
+	}
466
+
467
+
468
+	/**
469
+	 * Updates the list of installed versions and sets hooks for
470
+	 * initializing the database later during the request
471
+	 *
472
+	 * @param array $espresso_db_update
473
+	 */
474
+	private function _handle_core_version_change($espresso_db_update)
475
+	{
476
+		$this->update_list_of_installed_versions($espresso_db_update);
477
+		// get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
478
+		add_action(
479
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
480
+			array($this, 'initialize_db_if_no_migrations_required')
481
+		);
482
+	}
483
+
484
+
485
+	/**
486
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
487
+	 * information about what versions of EE have been installed and activated,
488
+	 * NOT necessarily the state of the database
489
+	 *
490
+	 * @param mixed $espresso_db_update           the value of the WordPress option.
491
+	 *                                            If not supplied, fetches it from the options table
492
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
493
+	 */
494
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
495
+	{
496
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
497
+		if (! $espresso_db_update) {
498
+			$espresso_db_update = get_option('espresso_db_update');
499
+		}
500
+		// check that option is an array
501
+		if (! is_array($espresso_db_update)) {
502
+			// if option is FALSE, then it never existed
503
+			if ($espresso_db_update === false) {
504
+				// make $espresso_db_update an array and save option with autoload OFF
505
+				$espresso_db_update = array();
506
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
507
+			} else {
508
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
509
+				$espresso_db_update = array($espresso_db_update => array());
510
+				update_option('espresso_db_update', $espresso_db_update);
511
+			}
512
+		} else {
513
+			$corrected_db_update = array();
514
+			// if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
515
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
516
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
517
+					// the key is an int, and the value IS NOT an array
518
+					// so it must be numerically-indexed, where values are versions installed...
519
+					// fix it!
520
+					$version_string = $should_be_array;
521
+					$corrected_db_update[ $version_string ] = array('unknown-date');
522
+				} else {
523
+					// ok it checks out
524
+					$corrected_db_update[ $should_be_version_string ] = $should_be_array;
525
+				}
526
+			}
527
+			$espresso_db_update = $corrected_db_update;
528
+			update_option('espresso_db_update', $espresso_db_update);
529
+		}
530
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
531
+		return $espresso_db_update;
532
+	}
533
+
534
+
535
+	/**
536
+	 * Does the traditional work of setting up the plugin's database and adding default data.
537
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
538
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
539
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
540
+	 * so that it will be done when migrations are finished
541
+	 *
542
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
543
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
544
+	 *                                       This is a resource-intensive job
545
+	 *                                       so we prefer to only do it when necessary
546
+	 * @return void
547
+	 * @throws EE_Error
548
+	 */
549
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
550
+	{
551
+		$request_type = $this->detect_req_type();
552
+		// only initialize system if we're not in maintenance mode.
553
+		if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
554
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
555
+			$rewrite_rules = $this->loader->getShared(
556
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
557
+			);
558
+			$rewrite_rules->flush();
559
+			if ($verify_schema) {
560
+				EEH_Activation::initialize_db_and_folders();
561
+			}
562
+			EEH_Activation::initialize_db_content();
563
+			EEH_Activation::system_initialization();
564
+			if ($initialize_addons_too) {
565
+				$this->initialize_addons();
566
+			}
567
+		} else {
568
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
569
+		}
570
+		if ($request_type === EE_System::req_type_new_activation
571
+			|| $request_type === EE_System::req_type_reactivation
572
+			|| (
573
+				$request_type === EE_System::req_type_upgrade
574
+				&& $this->is_major_version_change()
575
+			)
576
+		) {
577
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
578
+		}
579
+	}
580
+
581
+
582
+	/**
583
+	 * Initializes the db for all registered addons
584
+	 *
585
+	 * @throws EE_Error
586
+	 */
587
+	public function initialize_addons()
588
+	{
589
+		// foreach registered addon, make sure its db is up-to-date too
590
+		foreach ($this->registry->addons as $addon) {
591
+			if ($addon instanceof EE_Addon) {
592
+				$addon->initialize_db_if_no_migrations_required();
593
+			}
594
+		}
595
+	}
596
+
597
+
598
+	/**
599
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
600
+	 *
601
+	 * @param    array  $version_history
602
+	 * @param    string $current_version_to_add version to be added to the version history
603
+	 * @return    boolean success as to whether or not this option was changed
604
+	 */
605
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
606
+	{
607
+		if (! $version_history) {
608
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
609
+		}
610
+		if ($current_version_to_add === null) {
611
+			$current_version_to_add = espresso_version();
612
+		}
613
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
614
+		// re-save
615
+		return update_option('espresso_db_update', $version_history);
616
+	}
617
+
618
+
619
+	/**
620
+	 * Detects if the current version indicated in the has existed in the list of
621
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
622
+	 *
623
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
624
+	 *                                  If not supplied, fetches it from the options table.
625
+	 *                                  Also, caches its result so later parts of the code can also know whether
626
+	 *                                  there's been an update or not. This way we can add the current version to
627
+	 *                                  espresso_db_update, but still know if this is a new install or not
628
+	 * @return int one of the constants on EE_System::req_type_
629
+	 */
630
+	public function detect_req_type($espresso_db_update = null)
631
+	{
632
+		if ($this->_req_type === null) {
633
+			$espresso_db_update = ! empty($espresso_db_update)
634
+				? $espresso_db_update
635
+				: $this->fix_espresso_db_upgrade_option();
636
+			$this->_req_type = EE_System::detect_req_type_given_activation_history(
637
+				$espresso_db_update,
638
+				'ee_espresso_activation',
639
+				espresso_version()
640
+			);
641
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
642
+			$this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
643
+		}
644
+		return $this->_req_type;
645
+	}
646
+
647
+
648
+	/**
649
+	 * Returns whether or not there was a non-micro version change (ie, change in either
650
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
651
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
652
+	 *
653
+	 * @param $activation_history
654
+	 * @return bool
655
+	 */
656
+	private function _detect_major_version_change($activation_history)
657
+	{
658
+		$previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
659
+		$previous_version_parts = explode('.', $previous_version);
660
+		$current_version_parts = explode('.', espresso_version());
661
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
662
+			   && ($previous_version_parts[0] !== $current_version_parts[0]
663
+				   || $previous_version_parts[1] !== $current_version_parts[1]
664
+			   );
665
+	}
666
+
667
+
668
+	/**
669
+	 * Returns true if either the major or minor version of EE changed during this request.
670
+	 * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
671
+	 *
672
+	 * @return bool
673
+	 */
674
+	public function is_major_version_change()
675
+	{
676
+		return $this->_major_version_change;
677
+	}
678
+
679
+
680
+	/**
681
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
682
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
683
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
684
+	 * just activated to (for core that will always be espresso_version())
685
+	 *
686
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
687
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
688
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
689
+	 *                                                 indicate that this plugin was just activated
690
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
691
+	 *                                                 espresso_version())
692
+	 * @return int one of the constants on EE_System::req_type_*
693
+	 */
694
+	public static function detect_req_type_given_activation_history(
695
+		$activation_history_for_addon,
696
+		$activation_indicator_option_name,
697
+		$version_to_upgrade_to
698
+	) {
699
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
700
+		if ($activation_history_for_addon) {
701
+			// it exists, so this isn't a completely new install
702
+			// check if this version already in that list of previously installed versions
703
+			if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
704
+				// it a version we haven't seen before
705
+				if ($version_is_higher === 1) {
706
+					$req_type = EE_System::req_type_upgrade;
707
+				} else {
708
+					$req_type = EE_System::req_type_downgrade;
709
+				}
710
+				delete_option($activation_indicator_option_name);
711
+			} else {
712
+				// its not an update. maybe a reactivation?
713
+				if (get_option($activation_indicator_option_name, false)) {
714
+					if ($version_is_higher === -1) {
715
+						$req_type = EE_System::req_type_downgrade;
716
+					} elseif ($version_is_higher === 0) {
717
+						// we've seen this version before, but it's an activation. must be a reactivation
718
+						$req_type = EE_System::req_type_reactivation;
719
+					} else {// $version_is_higher === 1
720
+						$req_type = EE_System::req_type_upgrade;
721
+					}
722
+					delete_option($activation_indicator_option_name);
723
+				} else {
724
+					// we've seen this version before and the activation indicate doesn't show it was just activated
725
+					if ($version_is_higher === -1) {
726
+						$req_type = EE_System::req_type_downgrade;
727
+					} elseif ($version_is_higher === 0) {
728
+						// we've seen this version before and it's not an activation. its normal request
729
+						$req_type = EE_System::req_type_normal;
730
+					} else {// $version_is_higher === 1
731
+						$req_type = EE_System::req_type_upgrade;
732
+					}
733
+				}
734
+			}
735
+		} else {
736
+			// brand new install
737
+			$req_type = EE_System::req_type_new_activation;
738
+			delete_option($activation_indicator_option_name);
739
+		}
740
+		return $req_type;
741
+	}
742
+
743
+
744
+	/**
745
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
746
+	 * the $activation_history_for_addon
747
+	 *
748
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
749
+	 *                                             sometimes containing 'unknown-date'
750
+	 * @param string $version_to_upgrade_to        (current version)
751
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
752
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
753
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
754
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
755
+	 */
756
+	private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
757
+	{
758
+		// find the most recently-activated version
759
+		$most_recently_active_version =
760
+			EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
761
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
762
+	}
763
+
764
+
765
+	/**
766
+	 * Gets the most recently active version listed in the activation history,
767
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
768
+	 *
769
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
770
+	 *                                   sometimes containing 'unknown-date'
771
+	 * @return string
772
+	 */
773
+	private static function _get_most_recently_active_version_from_activation_history($activation_history)
774
+	{
775
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
776
+		$most_recently_active_version = '0.0.0.dev.000';
777
+		if (is_array($activation_history)) {
778
+			foreach ($activation_history as $version => $times_activated) {
779
+				// check there is a record of when this version was activated. Otherwise,
780
+				// mark it as unknown
781
+				if (! $times_activated) {
782
+					$times_activated = array('unknown-date');
783
+				}
784
+				if (is_string($times_activated)) {
785
+					$times_activated = array($times_activated);
786
+				}
787
+				foreach ($times_activated as $an_activation) {
788
+					if ($an_activation !== 'unknown-date'
789
+						&& $an_activation
790
+						   > $most_recently_active_version_activation) {
791
+						$most_recently_active_version = $version;
792
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
793
+							? '1970-01-01 00:00:00'
794
+							: $an_activation;
795
+					}
796
+				}
797
+			}
798
+		}
799
+		return $most_recently_active_version;
800
+	}
801
+
802
+
803
+	/**
804
+	 * This redirects to the about EE page after activation
805
+	 *
806
+	 * @return void
807
+	 */
808
+	public function redirect_to_about_ee()
809
+	{
810
+		$notices = EE_Error::get_notices(false);
811
+		// if current user is an admin and it's not an ajax or rest request
812
+		if (! isset($notices['errors'])
813
+			&& $this->request->isAdmin()
814
+			&& apply_filters(
815
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
816
+				$this->capabilities->current_user_can('manage_options', 'espresso_about_default')
817
+			)
818
+		) {
819
+			$query_params = array('page' => 'espresso_about');
820
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
821
+				$query_params['new_activation'] = true;
822
+			}
823
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
824
+				$query_params['reactivation'] = true;
825
+			}
826
+			$url = add_query_arg($query_params, admin_url('admin.php'));
827
+			wp_safe_redirect($url);
828
+			exit();
829
+		}
830
+	}
831
+
832
+
833
+	/**
834
+	 * load_core_configuration
835
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
836
+	 * which runs during the WP 'plugins_loaded' action at priority 5
837
+	 *
838
+	 * @return void
839
+	 * @throws ReflectionException
840
+	 */
841
+	public function load_core_configuration()
842
+	{
843
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
844
+		$this->loader->getShared('EE_Load_Textdomain');
845
+		// load textdomain
846
+		EE_Load_Textdomain::load_textdomain();
847
+		// load and setup EE_Config and EE_Network_Config
848
+		$config = $this->loader->getShared('EE_Config');
849
+		$this->loader->getShared('EE_Network_Config');
850
+		// setup autoloaders
851
+		// enable logging?
852
+		if ($config->admin->use_full_logging) {
853
+			$this->loader->getShared('EE_Log');
854
+		}
855
+		// check for activation errors
856
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
857
+		if ($activation_errors) {
858
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
859
+			update_option('ee_plugin_activation_errors', false);
860
+		}
861
+		// get model names
862
+		$this->_parse_model_names();
863
+		// load caf stuff a chance to play during the activation process too.
864
+		$this->_maybe_brew_regular();
865
+		// configure custom post type definitions
866
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
867
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
868
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
869
+	}
870
+
871
+
872
+	/**
873
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
874
+	 *
875
+	 * @return void
876
+	 * @throws ReflectionException
877
+	 */
878
+	private function _parse_model_names()
879
+	{
880
+		// get all the files in the EE_MODELS folder that end in .model.php
881
+		$models = glob(EE_MODELS . '*.model.php');
882
+		$model_names = array();
883
+		$non_abstract_db_models = array();
884
+		foreach ($models as $model) {
885
+			// get model classname
886
+			$classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
887
+			$short_name = str_replace('EEM_', '', $classname);
888
+			$reflectionClass = new ReflectionClass($classname);
889
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
890
+				$non_abstract_db_models[ $short_name ] = $classname;
891
+			}
892
+			$model_names[ $short_name ] = $classname;
893
+		}
894
+		$this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
895
+		$this->registry->non_abstract_db_models = apply_filters(
896
+			'FHEE__EE_System__parse_implemented_model_names',
897
+			$non_abstract_db_models
898
+		);
899
+	}
900
+
901
+
902
+	/**
903
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
904
+	 * that need to be setup before our EE_System launches.
905
+	 *
906
+	 * @return void
907
+	 * @throws DomainException
908
+	 * @throws InvalidArgumentException
909
+	 * @throws InvalidDataTypeException
910
+	 * @throws InvalidInterfaceException
911
+	 * @throws InvalidClassException
912
+	 * @throws InvalidFilePathException
913
+	 */
914
+	private function _maybe_brew_regular()
915
+	{
916
+		/** @var Domain $domain */
917
+		$domain = DomainFactory::getShared(
918
+			new FullyQualifiedName(
919
+				'EventEspresso\core\domain\Domain'
920
+			),
921
+			array(
922
+				new FilePath(EVENT_ESPRESSO_MAIN_FILE),
923
+				Version::fromString(espresso_version()),
924
+			)
925
+		);
926
+		if ($domain->isCaffeinated()) {
927
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
928
+		}
929
+	}
930
+
931
+
932
+	/**
933
+	 * register_shortcodes_modules_and_widgets
934
+	 * generate lists of shortcodes and modules, then verify paths and classes
935
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
936
+	 * which runs during the WP 'plugins_loaded' action at priority 7
937
+	 *
938
+	 * @access public
939
+	 * @return void
940
+	 * @throws Exception
941
+	 */
942
+	public function register_shortcodes_modules_and_widgets()
943
+	{
944
+		try {
945
+			// load, register, and add shortcodes the new way
946
+			if ($this->request->isFrontend() || $this->request->isIframe()) {
947
+				$this->loader->getShared(
948
+					'EventEspresso\core\services\shortcodes\ShortcodesManager',
949
+					array(
950
+						// and the old way, but we'll put it under control of the new system
951
+						EE_Config::getLegacyShortcodesManager(),
952
+					)
953
+				);
954
+			}
955
+		} catch (Exception $exception) {
956
+			new ExceptionStackTraceDisplay($exception);
957
+		}
958
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
959
+		// check for addons using old hook point
960
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
961
+			$this->_incompatible_addon_error();
962
+		}
963
+	}
964
+
965
+
966
+	/**
967
+	 * _incompatible_addon_error
968
+	 *
969
+	 * @access public
970
+	 * @return void
971
+	 */
972
+	private function _incompatible_addon_error()
973
+	{
974
+		// get array of classes hooking into here
975
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
976
+			'AHEE__EE_System__register_shortcodes_modules_and_addons'
977
+		);
978
+		if (! empty($class_names)) {
979
+			$msg = __(
980
+				'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
981
+				'event_espresso'
982
+			);
983
+			$msg .= '<ul>';
984
+			foreach ($class_names as $class_name) {
985
+				$msg .= '<li><b>Event Espresso - '
986
+						. str_replace(
987
+							array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
988
+							'',
989
+							$class_name
990
+						) . '</b></li>';
991
+			}
992
+			$msg .= '</ul>';
993
+			$msg .= __(
994
+				'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
995
+				'event_espresso'
996
+			);
997
+			// save list of incompatible addons to wp-options for later use
998
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
999
+			if (is_admin()) {
1000
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1001
+			}
1002
+		}
1003
+	}
1004
+
1005
+
1006
+	/**
1007
+	 * brew_espresso
1008
+	 * begins the process of setting hooks for initializing EE in the correct order
1009
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1010
+	 * which runs during the WP 'plugins_loaded' action at priority 9
1011
+	 *
1012
+	 * @return void
1013
+	 */
1014
+	public function brew_espresso()
1015
+	{
1016
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
1017
+		// load some final core systems
1018
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
1019
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1020
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
1021
+		add_action('init', array($this, 'load_controllers'), 7);
1022
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
1023
+		add_action('init', array($this, 'initialize'), 10);
1024
+		add_action('init', array($this, 'initialize_last'), 100);
1025
+		if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1026
+			// pew pew pew
1027
+			$this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1028
+			do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1029
+		}
1030
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
1031
+	}
1032
+
1033
+
1034
+	/**
1035
+	 *    set_hooks_for_core
1036
+	 *
1037
+	 * @access public
1038
+	 * @return    void
1039
+	 * @throws EE_Error
1040
+	 */
1041
+	public function set_hooks_for_core()
1042
+	{
1043
+		$this->_deactivate_incompatible_addons();
1044
+		do_action('AHEE__EE_System__set_hooks_for_core');
1045
+		$this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1046
+		// caps need to be initialized on every request so that capability maps are set.
1047
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1048
+		$this->registry->CAP->init_caps();
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
1054
+	 * deactivates any addons considered incompatible with the current version of EE
1055
+	 */
1056
+	private function _deactivate_incompatible_addons()
1057
+	{
1058
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
1059
+		if (! empty($incompatible_addons)) {
1060
+			$active_plugins = get_option('active_plugins', array());
1061
+			foreach ($active_plugins as $active_plugin) {
1062
+				foreach ($incompatible_addons as $incompatible_addon) {
1063
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
1064
+						unset($_GET['activate']);
1065
+						espresso_deactivate_plugin($active_plugin);
1066
+					}
1067
+				}
1068
+			}
1069
+		}
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 *    perform_activations_upgrades_and_migrations
1075
+	 *
1076
+	 * @access public
1077
+	 * @return    void
1078
+	 */
1079
+	public function perform_activations_upgrades_and_migrations()
1080
+	{
1081
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1082
+	}
1083
+
1084
+
1085
+	/**
1086
+	 * @return void
1087
+	 * @throws DomainException
1088
+	 */
1089
+	public function load_CPTs_and_session()
1090
+	{
1091
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
1092
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1093
+		$register_custom_taxonomies = $this->loader->getShared(
1094
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1095
+		);
1096
+		$register_custom_taxonomies->registerCustomTaxonomies();
1097
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1098
+		$register_custom_post_types = $this->loader->getShared(
1099
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1100
+		);
1101
+		$register_custom_post_types->registerCustomPostTypes();
1102
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1103
+		$register_custom_taxonomy_terms = $this->loader->getShared(
1104
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1105
+		);
1106
+		$register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1107
+		// load legacy Custom Post Types and Taxonomies
1108
+		$this->loader->getShared('EE_Register_CPTs');
1109
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1110
+	}
1111
+
1112
+
1113
+	/**
1114
+	 * load_controllers
1115
+	 * this is the best place to load any additional controllers that needs access to EE core.
1116
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1117
+	 * time
1118
+	 *
1119
+	 * @access public
1120
+	 * @return void
1121
+	 */
1122
+	public function load_controllers()
1123
+	{
1124
+		do_action('AHEE__EE_System__load_controllers__start');
1125
+		// let's get it started
1126
+		if (! $this->maintenance_mode->level()
1127
+			&& ($this->request->isFrontend() || $this->request->isFrontAjax())
1128
+		) {
1129
+			do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1130
+			$this->loader->getShared('EE_Front_Controller');
1131
+		} elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1132
+			do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1133
+			$this->loader->getShared('EE_Admin');
1134
+		}
1135
+		do_action('AHEE__EE_System__load_controllers__complete');
1136
+	}
1137
+
1138
+
1139
+	/**
1140
+	 * core_loaded_and_ready
1141
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1142
+	 *
1143
+	 * @access public
1144
+	 * @return void
1145
+	 */
1146
+	public function core_loaded_and_ready()
1147
+	{
1148
+		if ($this->request->isAdmin()
1149
+			|| $this->request->isEeAjax()
1150
+			|| $this->request->isFrontend()
1151
+		) {
1152
+			$this->loader->getShared('EE_Session');
1153
+		}
1154
+		do_action('AHEE__EE_System__core_loaded_and_ready');
1155
+		// load_espresso_template_tags
1156
+		if (is_readable(EE_PUBLIC . 'template_tags.php')
1157
+			&& (
1158
+				$this->request->isFrontend()
1159
+				|| $this->request->isAdmin()
1160
+				|| $this->request->isIframe()
1161
+				|| $this->request->isFeed()
1162
+			)
1163
+		) {
1164
+			require_once EE_PUBLIC . 'template_tags.php';
1165
+		}
1166
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1167
+		if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1168
+			$this->loader->getShared('EventEspresso\core\services\assets\Registry');
1169
+		}
1170
+	}
1171
+
1172
+
1173
+	/**
1174
+	 * initialize
1175
+	 * this is the best place to begin initializing client code
1176
+	 *
1177
+	 * @access public
1178
+	 * @return void
1179
+	 */
1180
+	public function initialize()
1181
+	{
1182
+		do_action('AHEE__EE_System__initialize');
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * initialize_last
1188
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1189
+	 * initialize has done so
1190
+	 *
1191
+	 * @access public
1192
+	 * @return void
1193
+	 */
1194
+	public function initialize_last()
1195
+	{
1196
+		do_action('AHEE__EE_System__initialize_last');
1197
+		/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1198
+		$rewrite_rules = $this->loader->getShared(
1199
+			'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1200
+		);
1201
+		$rewrite_rules->flushRewriteRules();
1202
+		add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * @return void
1208
+	 * @throws EE_Error
1209
+	 */
1210
+	public function addEspressoToolbar()
1211
+	{
1212
+		$this->loader->getShared(
1213
+			'EventEspresso\core\domain\services\admin\AdminToolBar',
1214
+			array($this->registry->CAP)
1215
+		);
1216
+	}
1217
+
1218
+
1219
+	/**
1220
+	 * do_not_cache
1221
+	 * sets no cache headers and defines no cache constants for WP plugins
1222
+	 *
1223
+	 * @access public
1224
+	 * @return void
1225
+	 */
1226
+	public static function do_not_cache()
1227
+	{
1228
+		// set no cache constants
1229
+		if (! defined('DONOTCACHEPAGE')) {
1230
+			define('DONOTCACHEPAGE', true);
1231
+		}
1232
+		if (! defined('DONOTCACHCEOBJECT')) {
1233
+			define('DONOTCACHCEOBJECT', true);
1234
+		}
1235
+		if (! defined('DONOTCACHEDB')) {
1236
+			define('DONOTCACHEDB', true);
1237
+		}
1238
+		// add no cache headers
1239
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1240
+		// plus a little extra for nginx and Google Chrome
1241
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1242
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1243
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 *    extra_nocache_headers
1249
+	 *
1250
+	 * @access    public
1251
+	 * @param $headers
1252
+	 * @return    array
1253
+	 */
1254
+	public static function extra_nocache_headers($headers)
1255
+	{
1256
+		// for NGINX
1257
+		$headers['X-Accel-Expires'] = 0;
1258
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1259
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1260
+		return $headers;
1261
+	}
1262
+
1263
+
1264
+	/**
1265
+	 *    nocache_headers
1266
+	 *
1267
+	 * @access    public
1268
+	 * @return    void
1269
+	 */
1270
+	public static function nocache_headers()
1271
+	{
1272
+		nocache_headers();
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1278
+	 * never returned with the function.
1279
+	 *
1280
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1281
+	 * @return array
1282
+	 */
1283
+	public function remove_pages_from_wp_list_pages($exclude_array)
1284
+	{
1285
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1286
+	}
1287 1287
 }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since           4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.4.0');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.4.0');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.62.rc.053');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.62.rc.053');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
Please login to merge, or discard this patch.