Completed
Branch BUG/brents-suggested-tweaks-fo... (808055)
by
unknown
10:17 queued 45s
created
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 1 patch
Indentation   +1792 added lines, -1792 removed lines patch added patch discarded remove patch
@@ -15,1796 +15,1796 @@
 block discarded – undo
15 15
 class EED_Single_Page_Checkout extends EED_Module
16 16
 {
17 17
 
18
-    /**
19
-     * $_initialized - has the SPCO controller already been initialized ?
20
-     *
21
-     * @access private
22
-     * @var bool $_initialized
23
-     */
24
-    private static $_initialized = false;
25
-
26
-
27
-    /**
28
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
29
-     *
30
-     * @access private
31
-     * @var bool $_valid_checkout
32
-     */
33
-    private static $_checkout_verified = true;
34
-
35
-    /**
36
-     *    $_reg_steps_array - holds initial array of reg steps
37
-     *
38
-     * @access private
39
-     * @var array $_reg_steps_array
40
-     */
41
-    private static $_reg_steps_array = array();
42
-
43
-    /**
44
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
45
-     *
46
-     * @access public
47
-     * @var EE_Checkout $checkout
48
-     */
49
-    public $checkout;
50
-
51
-
52
-    /**
53
-     * @return EED_Module|EED_Single_Page_Checkout
54
-     */
55
-    public static function instance()
56
-    {
57
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
58
-        return parent::get_instance(__CLASS__);
59
-    }
60
-
61
-
62
-    /**
63
-     * @return EE_CART
64
-     */
65
-    public function cart()
66
-    {
67
-        return $this->checkout->cart;
68
-    }
69
-
70
-
71
-    /**
72
-     * @return EE_Transaction
73
-     */
74
-    public function transaction()
75
-    {
76
-        return $this->checkout->transaction;
77
-    }
78
-
79
-
80
-    /**
81
-     *    set_hooks - for hooking into EE Core, other modules, etc
82
-     *
83
-     * @access    public
84
-     * @return    void
85
-     * @throws EE_Error
86
-     */
87
-    public static function set_hooks()
88
-    {
89
-        EED_Single_Page_Checkout::set_definitions();
90
-    }
91
-
92
-
93
-    /**
94
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
95
-     *
96
-     * @access    public
97
-     * @return    void
98
-     * @throws EE_Error
99
-     */
100
-    public static function set_hooks_admin()
101
-    {
102
-        EED_Single_Page_Checkout::set_definitions();
103
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
104
-            return;
105
-        }
106
-        // going to start an output buffer in case anything gets accidentally output
107
-        // that might disrupt our JSON response
108
-        ob_start();
109
-        EED_Single_Page_Checkout::load_request_handler();
110
-        EED_Single_Page_Checkout::load_reg_steps();
111
-        // set ajax hooks
112
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
113
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
114
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
115
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
116
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
117
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
118
-    }
119
-
120
-
121
-    /**
122
-     *    process ajax request
123
-     *
124
-     * @param string $ajax_action
125
-     * @throws EE_Error
126
-     */
127
-    public static function process_ajax_request($ajax_action)
128
-    {
129
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
130
-        EED_Single_Page_Checkout::instance()->_initialize();
131
-    }
132
-
133
-
134
-    /**
135
-     *    ajax display registration step
136
-     *
137
-     * @throws EE_Error
138
-     */
139
-    public static function display_reg_step()
140
-    {
141
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
142
-    }
143
-
144
-
145
-    /**
146
-     *    ajax process registration step
147
-     *
148
-     * @throws EE_Error
149
-     */
150
-    public static function process_reg_step()
151
-    {
152
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
153
-    }
154
-
155
-
156
-    /**
157
-     *    ajax process registration step
158
-     *
159
-     * @throws EE_Error
160
-     */
161
-    public static function update_reg_step()
162
-    {
163
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
164
-    }
165
-
166
-
167
-    /**
168
-     *   update_checkout
169
-     *
170
-     * @access public
171
-     * @return void
172
-     * @throws EE_Error
173
-     */
174
-    public static function update_checkout()
175
-    {
176
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
177
-    }
178
-
179
-
180
-    /**
181
-     *    load_request_handler
182
-     *
183
-     * @access    public
184
-     * @return    void
185
-     */
186
-    public static function load_request_handler()
187
-    {
188
-        // load core Request_Handler class
189
-        if (EE_Registry::instance()->REQ !== null) {
190
-            EE_Registry::instance()->load_core('Request_Handler');
191
-        }
192
-    }
193
-
194
-
195
-    /**
196
-     *    set_definitions
197
-     *
198
-     * @access    public
199
-     * @return    void
200
-     * @throws EE_Error
201
-     */
202
-    public static function set_definitions()
203
-    {
204
-        if (defined('SPCO_BASE_PATH')) {
205
-            return;
206
-        }
207
-        define(
208
-            'SPCO_BASE_PATH',
209
-            rtrim(str_replace(array('\\', '/'), '/', plugin_dir_path(__FILE__)), '/') . '/'
210
-        );
211
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
212
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
213
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
214
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
215
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
216
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
217
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
218
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
219
-        );
220
-    }
221
-
222
-
223
-    /**
224
-     * load_reg_steps
225
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
226
-     *
227
-     * @access    private
228
-     * @throws EE_Error
229
-     */
230
-    public static function load_reg_steps()
231
-    {
232
-        static $reg_steps_loaded = false;
233
-        if ($reg_steps_loaded) {
234
-            return;
235
-        }
236
-        // filter list of reg_steps
237
-        $reg_steps_to_load = (array) apply_filters(
238
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
239
-            EED_Single_Page_Checkout::get_reg_steps()
240
-        );
241
-        // sort by key (order)
242
-        ksort($reg_steps_to_load);
243
-        // loop through folders
244
-        foreach ($reg_steps_to_load as $order => $reg_step) {
245
-            // we need a
246
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
247
-                // copy over to the reg_steps_array
248
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
249
-                // register custom key route for each reg step
250
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
251
-                EE_Config::register_route(
252
-                    $reg_step['slug'],
253
-                    'EED_Single_Page_Checkout',
254
-                    'run',
255
-                    'step'
256
-                );
257
-                // add AJAX or other hooks
258
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
259
-                    // setup autoloaders if necessary
260
-                    if (! class_exists($reg_step['class_name'])) {
261
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
262
-                            $reg_step['file_path'],
263
-                            true
264
-                        );
265
-                    }
266
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
267
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
268
-                    }
269
-                }
270
-            }
271
-        }
272
-        $reg_steps_loaded = true;
273
-    }
274
-
275
-
276
-    /**
277
-     *    get_reg_steps
278
-     *
279
-     * @access    public
280
-     * @return    array
281
-     */
282
-    public static function get_reg_steps()
283
-    {
284
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
285
-        if (empty($reg_steps)) {
286
-            $reg_steps = array(
287
-                10  => array(
288
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
289
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
290
-                    'slug'       => 'attendee_information',
291
-                    'has_hooks'  => false,
292
-                ),
293
-                30  => array(
294
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
295
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
296
-                    'slug'       => 'payment_options',
297
-                    'has_hooks'  => true,
298
-                ),
299
-                999 => array(
300
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
301
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
302
-                    'slug'       => 'finalize_registration',
303
-                    'has_hooks'  => false,
304
-                ),
305
-            );
306
-        }
307
-        return $reg_steps;
308
-    }
309
-
310
-
311
-    /**
312
-     *    registration_checkout_for_admin
313
-     *
314
-     * @access    public
315
-     * @return    string
316
-     * @throws EE_Error
317
-     */
318
-    public static function registration_checkout_for_admin()
319
-    {
320
-        EED_Single_Page_Checkout::load_request_handler();
321
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
322
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
323
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
324
-        EED_Single_Page_Checkout::instance()->_initialize();
325
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
326
-        return EE_Registry::instance()->REQ->get_output();
327
-    }
328
-
329
-
330
-    /**
331
-     * process_registration_from_admin
332
-     *
333
-     * @access public
334
-     * @return \EE_Transaction
335
-     * @throws EE_Error
336
-     */
337
-    public static function process_registration_from_admin()
338
-    {
339
-        EED_Single_Page_Checkout::load_request_handler();
340
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
341
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
342
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
343
-        EED_Single_Page_Checkout::instance()->_initialize();
344
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
345
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
346
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
347
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
348
-                if ($final_reg_step->process_reg_step()) {
349
-                    $final_reg_step->set_completed();
350
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
351
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
352
-                }
353
-            }
354
-        }
355
-        return null;
356
-    }
357
-
358
-
359
-    /**
360
-     *    run
361
-     *
362
-     * @access    public
363
-     * @param WP_Query $WP_Query
364
-     * @return    void
365
-     * @throws EE_Error
366
-     */
367
-    public function run($WP_Query)
368
-    {
369
-        if ($WP_Query instanceof WP_Query
370
-            && $WP_Query->is_main_query()
371
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
372
-            && $this->_is_reg_checkout()
373
-        ) {
374
-            $this->_initialize();
375
-        }
376
-    }
377
-
378
-
379
-    /**
380
-     * determines whether current url matches reg page url
381
-     *
382
-     * @return bool
383
-     */
384
-    protected function _is_reg_checkout()
385
-    {
386
-        // get current permalink for reg page without any extra query args
387
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
388
-        // get request URI for current request, but without the scheme or host
389
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
390
-        $current_request_uri = html_entity_decode($current_request_uri);
391
-        // get array of query args from the current request URI
392
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
393
-        // grab page id if it is set
394
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
395
-        // and remove the page id from the query args (we will re-add it later)
396
-        unset($query_args['page_id']);
397
-        // now strip all query args from current request URI
398
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
399
-        // and re-add the page id if it was set
400
-        if ($page_id) {
401
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
402
-        }
403
-        // remove slashes and ?
404
-        $current_request_uri = trim($current_request_uri, '?/');
405
-        // is current request URI part of the known full reg page URL ?
406
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
407
-    }
408
-
409
-
410
-    /**
411
-     * @param WP_Query $wp_query
412
-     * @return    void
413
-     * @throws EE_Error
414
-     */
415
-    public static function init($wp_query)
416
-    {
417
-        EED_Single_Page_Checkout::instance()->run($wp_query);
418
-    }
419
-
420
-
421
-    /**
422
-     *    _initialize - initial module setup
423
-     *
424
-     * @access    private
425
-     * @throws EE_Error
426
-     * @return    void
427
-     */
428
-    private function _initialize()
429
-    {
430
-        // ensure SPCO doesn't run twice
431
-        if (EED_Single_Page_Checkout::$_initialized) {
432
-            return;
433
-        }
434
-        try {
435
-            EED_Single_Page_Checkout::load_reg_steps();
436
-            $this->_verify_session();
437
-            // setup the EE_Checkout object
438
-            $this->checkout = $this->_initialize_checkout();
439
-            // filter checkout
440
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
441
-            // get the $_GET
442
-            $this->_get_request_vars();
443
-            if ($this->_block_bots()) {
444
-                return;
445
-            }
446
-            // filter continue_reg
447
-            $this->checkout->continue_reg = apply_filters(
448
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
449
-                true,
450
-                $this->checkout
451
-            );
452
-            // load the reg steps array
453
-            if (! $this->_load_and_instantiate_reg_steps()) {
454
-                EED_Single_Page_Checkout::$_initialized = true;
455
-                return;
456
-            }
457
-            // set the current step
458
-            $this->checkout->set_current_step($this->checkout->step);
459
-            // and the next step
460
-            $this->checkout->set_next_step();
461
-            // verify that everything has been setup correctly
462
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
463
-                EED_Single_Page_Checkout::$_initialized = true;
464
-                return;
465
-            }
466
-            // lock the transaction
467
-            $this->checkout->transaction->lock();
468
-            // make sure all of our cached objects are added to their respective model entity mappers
469
-            $this->checkout->refresh_all_entities();
470
-            // set amount owing
471
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
472
-            // initialize each reg step, which gives them the chance to potentially alter the process
473
-            $this->_initialize_reg_steps();
474
-            // DEBUG LOG
475
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
476
-            // get reg form
477
-            if (! $this->_check_form_submission()) {
478
-                EED_Single_Page_Checkout::$_initialized = true;
479
-                return;
480
-            }
481
-            // checkout the action!!!
482
-            $this->_process_form_action();
483
-            // add some style and make it dance
484
-            $this->add_styles_and_scripts($this);
485
-            // kk... SPCO has successfully run
486
-            EED_Single_Page_Checkout::$_initialized = true;
487
-            // set no cache headers and constants
488
-            EE_System::do_not_cache();
489
-            // add anchor
490
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
491
-            // remove transaction lock
492
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
493
-        } catch (Exception $e) {
494
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
495
-        }
496
-    }
497
-
498
-
499
-    /**
500
-     *    _verify_session
501
-     * checks that the session is valid and not expired
502
-     *
503
-     * @access    private
504
-     * @throws EE_Error
505
-     */
506
-    private function _verify_session()
507
-    {
508
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
509
-            throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
510
-        }
511
-        $clear_session_requested = filter_var(
512
-            EE_Registry::instance()->REQ->get('clear_session', false),
513
-            FILTER_VALIDATE_BOOLEAN
514
-        );
515
-        // is session still valid ?
516
-        if ($clear_session_requested
517
-            || (EE_Registry::instance()->SSN->expired()
518
-                && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
519
-            )
520
-        ) {
521
-            $this->checkout = new EE_Checkout();
522
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
523
-            // EE_Registry::instance()->SSN->reset_cart();
524
-            // EE_Registry::instance()->SSN->reset_checkout();
525
-            // EE_Registry::instance()->SSN->reset_transaction();
526
-            if (! $clear_session_requested) {
527
-                EE_Error::add_attention(
528
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
529
-                    __FILE__,
530
-                    __FUNCTION__,
531
-                    __LINE__
532
-                );
533
-            }
534
-            // EE_Registry::instance()->SSN->reset_expired();
535
-        }
536
-    }
537
-
538
-
539
-    /**
540
-     *    _initialize_checkout
541
-     * loads and instantiates EE_Checkout
542
-     *
543
-     * @access    private
544
-     * @throws EE_Error
545
-     * @return EE_Checkout
546
-     */
547
-    private function _initialize_checkout()
548
-    {
549
-        // look in session for existing checkout
550
-        /** @type EE_Checkout $checkout */
551
-        $checkout = EE_Registry::instance()->SSN->checkout();
552
-        // verify
553
-        if (! $checkout instanceof EE_Checkout) {
554
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
555
-            $checkout = EE_Registry::instance()->load_file(
556
-                SPCO_INC_PATH,
557
-                'EE_Checkout',
558
-                'class',
559
-                array(),
560
-                false
561
-            );
562
-        } else {
563
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
564
-                $this->unlock_transaction();
565
-                wp_safe_redirect($checkout->redirect_url);
566
-                exit();
567
-            }
568
-        }
569
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
570
-        // verify again
571
-        if (! $checkout instanceof EE_Checkout) {
572
-            throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
573
-        }
574
-        // reset anything that needs a clean slate for each request
575
-        $checkout->reset_for_current_request();
576
-        return $checkout;
577
-    }
578
-
579
-
580
-    /**
581
-     *    _get_request_vars
582
-     *
583
-     * @access    private
584
-     * @return    void
585
-     * @throws EE_Error
586
-     */
587
-    private function _get_request_vars()
588
-    {
589
-        // load classes
590
-        EED_Single_Page_Checkout::load_request_handler();
591
-        // make sure this request is marked as belonging to EE
592
-        EE_Registry::instance()->REQ->set_espresso_page(true);
593
-        // which step is being requested ?
594
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
595
-        // which step is being edited ?
596
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
597
-        // and what we're doing on the current step
598
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
599
-        // timestamp
600
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
601
-        // returning to edit ?
602
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
603
-        // add reg url link to registration query params
604
-        if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
605
-            $this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
606
-        }
607
-        // or some other kind of revisit ?
608
-        $this->checkout->revisit = filter_var(
609
-            EE_Registry::instance()->REQ->get('revisit', false),
610
-            FILTER_VALIDATE_BOOLEAN
611
-        );
612
-        // and whether or not to generate a reg form for this request
613
-        $this->checkout->generate_reg_form = filter_var(
614
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
615
-            FILTER_VALIDATE_BOOLEAN
616
-        );
617
-        // and whether or not to process a reg form submission for this request
618
-        $this->checkout->process_form_submission = filter_var(
619
-            EE_Registry::instance()->REQ->get(
620
-                'process_form_submission',
621
-                $this->checkout->action === 'process_reg_step'
622
-            ),
623
-            FILTER_VALIDATE_BOOLEAN
624
-        );
625
-        $this->checkout->process_form_submission = filter_var(
626
-            $this->checkout->action !== 'display_spco_reg_step'
627
-                ? $this->checkout->process_form_submission
628
-                : false,
629
-            FILTER_VALIDATE_BOOLEAN
630
-        );
631
-        // $this->_display_request_vars();
632
-    }
633
-
634
-
635
-    /**
636
-     *  _display_request_vars
637
-     *
638
-     * @access    protected
639
-     * @return    void
640
-     */
641
-    protected function _display_request_vars()
642
-    {
643
-        if (! WP_DEBUG) {
644
-            return;
645
-        }
646
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
647
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
648
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
649
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
650
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
651
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
652
-        EEH_Debug_Tools::printr(
653
-            $this->checkout->generate_reg_form,
654
-            '$this->checkout->generate_reg_form',
655
-            __FILE__,
656
-            __LINE__
657
-        );
658
-        EEH_Debug_Tools::printr(
659
-            $this->checkout->process_form_submission,
660
-            '$this->checkout->process_form_submission',
661
-            __FILE__,
662
-            __LINE__
663
-        );
664
-    }
665
-
666
-
667
-    /**
668
-     * _block_bots
669
-     * checks that the incoming request has either of the following set:
670
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
671
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
672
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
673
-     * then where you coming from man?
674
-     *
675
-     * @return boolean
676
-     */
677
-    private function _block_bots()
678
-    {
679
-        $invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
680
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
681
-            return true;
682
-        }
683
-        return false;
684
-    }
685
-
686
-
687
-    /**
688
-     *    _get_first_step
689
-     *  gets slug for first step in $_reg_steps_array
690
-     *
691
-     * @access    private
692
-     * @throws EE_Error
693
-     * @return    string
694
-     */
695
-    private function _get_first_step()
696
-    {
697
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
698
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
699
-    }
700
-
701
-
702
-    /**
703
-     * instantiates each reg step based on the loaded reg_steps array
704
-     *
705
-     * @return    bool
706
-     * @throws EE_Error
707
-     * @throws InvalidArgumentException
708
-     * @throws InvalidDataTypeException
709
-     * @throws InvalidInterfaceException
710
-     */
711
-    private function _load_and_instantiate_reg_steps()
712
-    {
713
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
714
-        // have reg_steps already been instantiated ?
715
-        if (empty($this->checkout->reg_steps)
716
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
717
-        ) {
718
-            // if not, then loop through raw reg steps array
719
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
720
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
721
-                    return false;
722
-                }
723
-            }
724
-            if (isset($this->checkout->reg_steps['registration_confirmation'])) {
725
-                // skip the registration_confirmation page ?
726
-                if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
727
-                    // just remove it from the reg steps array
728
-                    $this->checkout->remove_reg_step('registration_confirmation', false);
729
-                } elseif (EE_Registry::instance()->CFG->registration->reg_confirmation_last
730
-                ) {
731
-                    // set the order to something big like 100
732
-                    $this->checkout->set_reg_step_order('registration_confirmation', 100);
733
-                }
734
-            }
735
-            // filter the array for good luck
736
-            $this->checkout->reg_steps = apply_filters(
737
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
738
-                $this->checkout->reg_steps
739
-            );
740
-            // finally re-sort based on the reg step class order properties
741
-            $this->checkout->sort_reg_steps();
742
-        } else {
743
-            foreach ($this->checkout->reg_steps as $reg_step) {
744
-                // set all current step stati to FALSE
745
-                $reg_step->set_is_current_step(false);
746
-            }
747
-        }
748
-        if (empty($this->checkout->reg_steps)) {
749
-            EE_Error::add_error(
750
-                esc_html__('No Reg Steps were loaded..', 'event_espresso'),
751
-                __FILE__,
752
-                __FUNCTION__,
753
-                __LINE__
754
-            );
755
-            return false;
756
-        }
757
-        // make reg step details available to JS
758
-        $this->checkout->set_reg_step_JSON_info();
759
-        return true;
760
-    }
761
-
762
-
763
-    /**
764
-     *     _load_and_instantiate_reg_step
765
-     *
766
-     * @access    private
767
-     * @param array $reg_step
768
-     * @param int   $order
769
-     * @return bool
770
-     */
771
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
772
-    {
773
-        // we need a file_path, class_name, and slug to add a reg step
774
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
775
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
776
-            if ($this->checkout->reg_url_link
777
-                && $this->checkout->step !== $reg_step['slug']
778
-                && $reg_step['slug'] !== 'finalize_registration'
779
-                // normally at this point we would NOT load the reg step, but this filter can change that
780
-                && apply_filters(
781
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
782
-                    true,
783
-                    $reg_step,
784
-                    $this->checkout
785
-                )
786
-            ) {
787
-                return true;
788
-            }
789
-            // instantiate step class using file path and class name
790
-            $reg_step_obj = EE_Registry::instance()->load_file(
791
-                $reg_step['file_path'],
792
-                $reg_step['class_name'],
793
-                'class',
794
-                $this->checkout,
795
-                false
796
-            );
797
-            // did we gets the goods ?
798
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
799
-                // set reg step order based on config
800
-                $reg_step_obj->set_order($order);
801
-                // add instantiated reg step object to the master reg steps array
802
-                $this->checkout->add_reg_step($reg_step_obj);
803
-            } else {
804
-                EE_Error::add_error(
805
-                    esc_html__('The current step could not be set.', 'event_espresso'),
806
-                    __FILE__,
807
-                    __FUNCTION__,
808
-                    __LINE__
809
-                );
810
-                return false;
811
-            }
812
-        } else {
813
-            if (WP_DEBUG) {
814
-                EE_Error::add_error(
815
-                    sprintf(
816
-                        esc_html__(
817
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
818
-                            'event_espresso'
819
-                        ),
820
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
821
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
822
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
823
-                        '<ul>',
824
-                        '<li>',
825
-                        '</li>',
826
-                        '</ul>'
827
-                    ),
828
-                    __FILE__,
829
-                    __FUNCTION__,
830
-                    __LINE__
831
-                );
832
-            }
833
-            return false;
834
-        }
835
-        return true;
836
-    }
837
-
838
-
839
-    /**
840
-     * _verify_transaction_and_get_registrations
841
-     *
842
-     * @access private
843
-     * @return bool
844
-     * @throws InvalidDataTypeException
845
-     * @throws InvalidEntityException
846
-     * @throws EE_Error
847
-     */
848
-    private function _verify_transaction_and_get_registrations()
849
-    {
850
-        // was there already a valid transaction in the checkout from the session ?
851
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
852
-            // get transaction from db or session
853
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
854
-                ? $this->_get_transaction_and_cart_for_previous_visit()
855
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
856
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
857
-                EE_Error::add_error(
858
-                    esc_html__(
859
-                        'Your Registration and Transaction information could not be retrieved from the db.',
860
-                        'event_espresso'
861
-                    ),
862
-                    __FILE__,
863
-                    __FUNCTION__,
864
-                    __LINE__
865
-                );
866
-                $this->checkout->transaction = EE_Transaction::new_instance();
867
-                // add some style and make it dance
868
-                $this->add_styles_and_scripts($this);
869
-                EED_Single_Page_Checkout::$_initialized = true;
870
-                return false;
871
-            }
872
-            // and the registrations for the transaction
873
-            $this->_get_registrations($this->checkout->transaction);
874
-        }
875
-        return true;
876
-    }
877
-
878
-
879
-    /**
880
-     * _get_transaction_and_cart_for_previous_visit
881
-     *
882
-     * @access private
883
-     * @return mixed EE_Transaction|NULL
884
-     */
885
-    private function _get_transaction_and_cart_for_previous_visit()
886
-    {
887
-        /** @var $TXN_model EEM_Transaction */
888
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
889
-        // because the reg_url_link is present in the request,
890
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
891
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
892
-        // verify transaction
893
-        if ($transaction instanceof EE_Transaction) {
894
-            // and get the cart that was used for that transaction
895
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
896
-            return $transaction;
897
-        }
898
-        EE_Error::add_error(
899
-            esc_html__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
900
-            __FILE__,
901
-            __FUNCTION__,
902
-            __LINE__
903
-        );
904
-        return null;
905
-    }
906
-
907
-
908
-    /**
909
-     * _get_cart_for_transaction
910
-     *
911
-     * @access private
912
-     * @param EE_Transaction $transaction
913
-     * @return EE_Cart
914
-     */
915
-    private function _get_cart_for_transaction($transaction)
916
-    {
917
-        return $this->checkout->get_cart_for_transaction($transaction);
918
-    }
919
-
920
-
921
-    /**
922
-     * get_cart_for_transaction
923
-     *
924
-     * @access public
925
-     * @param EE_Transaction $transaction
926
-     * @return EE_Cart
927
-     */
928
-    public function get_cart_for_transaction(EE_Transaction $transaction)
929
-    {
930
-        return $this->checkout->get_cart_for_transaction($transaction);
931
-    }
932
-
933
-
934
-    /**
935
-     * _get_transaction_and_cart_for_current_session
936
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
937
-     *
938
-     * @access private
939
-     * @return EE_Transaction
940
-     * @throws EE_Error
941
-     */
942
-    private function _get_cart_for_current_session_and_setup_new_transaction()
943
-    {
944
-        //  if there's no transaction, then this is the FIRST visit to SPCO
945
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
946
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
947
-        // and then create a new transaction
948
-        $transaction = $this->_initialize_transaction();
949
-        // verify transaction
950
-        if ($transaction instanceof EE_Transaction) {
951
-            // save it so that we have an ID for other objects to use
952
-            $transaction->save();
953
-            // and save TXN data to the cart
954
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
955
-        } else {
956
-            EE_Error::add_error(
957
-                esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
958
-                __FILE__,
959
-                __FUNCTION__,
960
-                __LINE__
961
-            );
962
-        }
963
-        return $transaction;
964
-    }
965
-
966
-
967
-    /**
968
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
969
-     *
970
-     * @access private
971
-     * @return mixed EE_Transaction|NULL
972
-     */
973
-    private function _initialize_transaction()
974
-    {
975
-        try {
976
-            // ensure cart totals have been calculated
977
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
978
-            // grab the cart grand total
979
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
980
-            // create new TXN
981
-            $transaction = EE_Transaction::new_instance(
982
-                array(
983
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
984
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
985
-                    'TXN_paid'      => 0,
986
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
987
-                )
988
-            );
989
-            // save it so that we have an ID for other objects to use
990
-            $transaction->save();
991
-            // set cron job for following up on TXNs after their session has expired
992
-            EE_Cron_Tasks::schedule_expired_transaction_check(
993
-                EE_Registry::instance()->SSN->expiration() + 1,
994
-                $transaction->ID()
995
-            );
996
-            return $transaction;
997
-        } catch (Exception $e) {
998
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
999
-        }
1000
-        return null;
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * _get_registrations
1006
-     *
1007
-     * @access private
1008
-     * @param EE_Transaction $transaction
1009
-     * @return void
1010
-     * @throws InvalidDataTypeException
1011
-     * @throws InvalidEntityException
1012
-     * @throws EE_Error
1013
-     */
1014
-    private function _get_registrations(EE_Transaction $transaction)
1015
-    {
1016
-        // first step: grab the registrants  { : o
1017
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1018
-        $this->checkout->total_ticket_count = count($registrations);
1019
-        // verify registrations have been set
1020
-        if (empty($registrations)) {
1021
-            // if no cached registrations, then check the db
1022
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1023
-            // still nothing ? well as long as this isn't a revisit
1024
-            if (empty($registrations) && ! $this->checkout->revisit) {
1025
-                // generate new registrations from scratch
1026
-                $registrations = $this->_initialize_registrations($transaction);
1027
-            }
1028
-        }
1029
-        // sort by their original registration order
1030
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1031
-        // then loop thru the array
1032
-        foreach ($registrations as $registration) {
1033
-            // verify each registration
1034
-            if ($registration instanceof EE_Registration) {
1035
-                // we display all attendee info for the primary registrant
1036
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1037
-                    && $registration->is_primary_registrant()
1038
-                ) {
1039
-                    $this->checkout->primary_revisit = true;
1040
-                    break;
1041
-                }
1042
-                if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1043
-                    // but hide info if it doesn't belong to you
1044
-                    $transaction->clear_cache('Registration', $registration->ID());
1045
-                    $this->checkout->total_ticket_count--;
1046
-                }
1047
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1048
-            }
1049
-        }
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1055
-     *
1056
-     * @access private
1057
-     * @param EE_Transaction $transaction
1058
-     * @return    array
1059
-     * @throws InvalidDataTypeException
1060
-     * @throws InvalidEntityException
1061
-     * @throws EE_Error
1062
-     */
1063
-    private function _initialize_registrations(EE_Transaction $transaction)
1064
-    {
1065
-        $att_nmbr = 0;
1066
-        $registrations = array();
1067
-        if ($transaction instanceof EE_Transaction) {
1068
-            /** @type EE_Registration_Processor $registration_processor */
1069
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1070
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1071
-            // now let's add the cart items to the $transaction
1072
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1073
-                // do the following for each ticket of this type they selected
1074
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1075
-                    $att_nmbr++;
1076
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1077
-                    $CreateRegistrationCommand = EE_Registry::instance()->create(
1078
-                        'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1079
-                        array(
1080
-                            $transaction,
1081
-                            $line_item,
1082
-                            $att_nmbr,
1083
-                            $this->checkout->total_ticket_count,
1084
-                        )
1085
-                    );
1086
-                    // override capabilities for frontend registrations
1087
-                    if (! is_admin()) {
1088
-                        $CreateRegistrationCommand->setCapCheck(
1089
-                            new PublicCapabilities('', 'create_new_registration')
1090
-                        );
1091
-                    }
1092
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1093
-                    if (! $registration instanceof EE_Registration) {
1094
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1095
-                    }
1096
-                    $registrations[ $registration->ID() ] = $registration;
1097
-                }
1098
-            }
1099
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1100
-        }
1101
-        return $registrations;
1102
-    }
1103
-
1104
-
1105
-    /**
1106
-     * sorts registrations by REG_count
1107
-     *
1108
-     * @access public
1109
-     * @param EE_Registration $reg_A
1110
-     * @param EE_Registration $reg_B
1111
-     * @return int
1112
-     */
1113
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1114
-    {
1115
-        // this shouldn't ever happen within the same TXN, but oh well
1116
-        if ($reg_A->count() === $reg_B->count()) {
1117
-            return 0;
1118
-        }
1119
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1120
-    }
1121
-
1122
-
1123
-    /**
1124
-     *    _final_verifications
1125
-     * just makes sure that everything is set up correctly before proceeding
1126
-     *
1127
-     * @access    private
1128
-     * @return    bool
1129
-     * @throws EE_Error
1130
-     */
1131
-    private function _final_verifications()
1132
-    {
1133
-        // filter checkout
1134
-        $this->checkout = apply_filters(
1135
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1136
-            $this->checkout
1137
-        );
1138
-        // verify that current step is still set correctly
1139
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1140
-            EE_Error::add_error(
1141
-                esc_html__(
1142
-                    'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1143
-                    'event_espresso'
1144
-                ),
1145
-                __FILE__,
1146
-                __FUNCTION__,
1147
-                __LINE__
1148
-            );
1149
-            return false;
1150
-        }
1151
-        // if returning to SPCO, then verify that primary registrant is set
1152
-        if (! empty($this->checkout->reg_url_link)) {
1153
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1154
-            if (! $valid_registrant instanceof EE_Registration) {
1155
-                EE_Error::add_error(
1156
-                    esc_html__(
1157
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1158
-                        'event_espresso'
1159
-                    ),
1160
-                    __FILE__,
1161
-                    __FUNCTION__,
1162
-                    __LINE__
1163
-                );
1164
-                return false;
1165
-            }
1166
-            $valid_registrant = null;
1167
-            foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1168
-                if ($registration instanceof EE_Registration
1169
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1170
-                ) {
1171
-                    $valid_registrant = $registration;
1172
-                }
1173
-            }
1174
-            if (! $valid_registrant instanceof EE_Registration) {
1175
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1176
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1177
-                    // clear the session, mark the checkout as unverified, and try again
1178
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1179
-                    EED_Single_Page_Checkout::$_initialized = false;
1180
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1181
-                    $this->_initialize();
1182
-                    EE_Error::reset_notices();
1183
-                    return false;
1184
-                }
1185
-                EE_Error::add_error(
1186
-                    esc_html__(
1187
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1188
-                        'event_espresso'
1189
-                    ),
1190
-                    __FILE__,
1191
-                    __FUNCTION__,
1192
-                    __LINE__
1193
-                );
1194
-                return false;
1195
-            }
1196
-        }
1197
-        // now that things have been kinda sufficiently verified,
1198
-        // let's add the checkout to the session so that it's available to other systems
1199
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1200
-        return true;
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     *    _initialize_reg_steps
1206
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1207
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1208
-     *
1209
-     * @access    private
1210
-     * @param bool $reinitializing
1211
-     * @throws EE_Error
1212
-     */
1213
-    private function _initialize_reg_steps($reinitializing = false)
1214
-    {
1215
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1216
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1217
-        foreach ($this->checkout->reg_steps as $reg_step) {
1218
-            if (! $reg_step->initialize_reg_step()) {
1219
-                // if not initialized then maybe this step is being removed...
1220
-                if (! $reinitializing && $reg_step->is_current_step()) {
1221
-                    // if it was the current step, then we need to start over here
1222
-                    $this->_initialize_reg_steps(true);
1223
-                    return;
1224
-                }
1225
-                continue;
1226
-            }
1227
-            // add css and JS for current step
1228
-            $this->add_styles_and_scripts($reg_step);
1229
-            if ($reg_step->is_current_step()) {
1230
-                // the text that appears on the reg step form submit button
1231
-                $reg_step->set_submit_button_text();
1232
-            }
1233
-        }
1234
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1235
-        do_action(
1236
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1237
-            $this->checkout->current_step
1238
-        );
1239
-    }
1240
-
1241
-
1242
-    /**
1243
-     * _check_form_submission
1244
-     *
1245
-     * @access private
1246
-     * @return boolean
1247
-     */
1248
-    private function _check_form_submission()
1249
-    {
1250
-        // does this request require the reg form to be generated ?
1251
-        if ($this->checkout->generate_reg_form) {
1252
-            // ever heard that song by Blue Rodeo ?
1253
-            try {
1254
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1255
-                // if not displaying a form, then check for form submission
1256
-                if ($this->checkout->process_form_submission
1257
-                    && $this->checkout->current_step->reg_form->was_submitted()
1258
-                ) {
1259
-                    // clear out any old data in case this step is being run again
1260
-                    $this->checkout->current_step->set_valid_data(array());
1261
-                    // capture submitted form data
1262
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1263
-                        apply_filters(
1264
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1265
-                            EE_Registry::instance()->REQ->params(),
1266
-                            $this->checkout
1267
-                        )
1268
-                    );
1269
-                    // validate submitted form data
1270
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1271
-                        // thou shall not pass !!!
1272
-                        $this->checkout->continue_reg = false;
1273
-                        // any form validation errors?
1274
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1275
-                            EE_Error::add_error(
1276
-                                $this->checkout->current_step->reg_form->submission_error_message(),
1277
-                                __FILE__,
1278
-                                __FUNCTION__,
1279
-                                __LINE__
1280
-                            );
1281
-                        }
1282
-                        // well not really... what will happen is
1283
-                        // we'll just get redirected back to redo the current step
1284
-                        $this->go_to_next_step();
1285
-                        return false;
1286
-                    }
1287
-                }
1288
-            } catch (EE_Error $e) {
1289
-                $e->get_error();
1290
-            }
1291
-        }
1292
-        return true;
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * _process_action
1298
-     *
1299
-     * @access private
1300
-     * @return void
1301
-     * @throws EE_Error
1302
-     */
1303
-    private function _process_form_action()
1304
-    {
1305
-        // what cha wanna do?
1306
-        switch ($this->checkout->action) {
1307
-            // AJAX next step reg form
1308
-            case 'display_spco_reg_step':
1309
-                $this->checkout->redirect = false;
1310
-                if (EE_Registry::instance()->REQ->ajax) {
1311
-                    $this->checkout->json_response->set_reg_step_html(
1312
-                        $this->checkout->current_step->display_reg_form()
1313
-                    );
1314
-                }
1315
-                break;
1316
-            default:
1317
-                // meh... do one of those other steps first
1318
-                if (! empty($this->checkout->action)
1319
-                    && is_callable(array($this->checkout->current_step, $this->checkout->action))
1320
-                ) {
1321
-                    // dynamically creates hook point like:
1322
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1323
-                    do_action(
1324
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1325
-                        $this->checkout->current_step
1326
-                    );
1327
-                    // call action on current step
1328
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1329
-                        // good registrant, you get to proceed
1330
-                        if ($this->checkout->current_step->success_message() !== ''
1331
-                            && apply_filters(
1332
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1333
-                                false
1334
-                            )
1335
-                        ) {
1336
-                            EE_Error::add_success(
1337
-                                $this->checkout->current_step->success_message()
1338
-                                . '<br />' . $this->checkout->next_step->_instructions()
1339
-                            );
1340
-                        }
1341
-                        // pack it up, pack it in...
1342
-                        $this->_setup_redirect();
1343
-                    }
1344
-                    // dynamically creates hook point like:
1345
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1346
-                    do_action(
1347
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1348
-                        $this->checkout->current_step
1349
-                    );
1350
-                } else {
1351
-                    EE_Error::add_error(
1352
-                        sprintf(
1353
-                            esc_html__(
1354
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1355
-                                'event_espresso'
1356
-                            ),
1357
-                            $this->checkout->action,
1358
-                            $this->checkout->current_step->name()
1359
-                        ),
1360
-                        __FILE__,
1361
-                        __FUNCTION__,
1362
-                        __LINE__
1363
-                    );
1364
-                }
1365
-            // end default
1366
-        }
1367
-        // store our progress so far
1368
-        $this->checkout->stash_transaction_and_checkout();
1369
-        // advance to the next step! If you pass GO, collect $200
1370
-        $this->go_to_next_step();
1371
-    }
1372
-
1373
-
1374
-    /**
1375
-     * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target
1376
-     * @param object $target an object with the method `translate_js_strings` and `enqueue_styles_and_scripts`.
1377
-     * @return        void
1378
-     */
1379
-    public function add_styles_and_scripts($target)
1380
-    {
1381
-        // i18n
1382
-        $target->translate_js_strings();
1383
-        if ($this->checkout->admin_request) {
1384
-            add_action('admin_enqueue_scripts', array($target, 'enqueue_styles_and_scripts'), 10);
1385
-        } else {
1386
-            add_action('wp_enqueue_scripts', array($target, 'enqueue_styles_and_scripts'), 10);
1387
-        }
1388
-    }
1389
-
1390
-    /**
1391
-     *        translate_js_strings
1392
-     *
1393
-     * @access        public
1394
-     * @return        void
1395
-     */
1396
-    public function translate_js_strings()
1397
-    {
1398
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1399
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1400
-        EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
1401
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1402
-            'event_espresso'
1403
-        );
1404
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = esc_html__(
1405
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1406
-            'event_espresso'
1407
-        );
1408
-        EE_Registry::$i18n_js_strings['validation_error'] = esc_html__(
1409
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1410
-            'event_espresso'
1411
-        );
1412
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
1413
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1414
-            'event_espresso'
1415
-        );
1416
-        EE_Registry::$i18n_js_strings['reg_step_error'] = esc_html__(
1417
-            'This registration step could not be completed. Please refresh the page and try again.',
1418
-            'event_espresso'
1419
-        );
1420
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = esc_html__(
1421
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1422
-            'event_espresso'
1423
-        );
1424
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1425
-            esc_html__(
1426
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1427
-                'event_espresso'
1428
-            ),
1429
-            '<br/>',
1430
-            '<br/>'
1431
-        );
1432
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1433
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1434
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1435
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1436
-        EE_Registry::$i18n_js_strings['timer_years'] = esc_html__('years', 'event_espresso');
1437
-        EE_Registry::$i18n_js_strings['timer_months'] = esc_html__('months', 'event_espresso');
1438
-        EE_Registry::$i18n_js_strings['timer_weeks'] = esc_html__('weeks', 'event_espresso');
1439
-        EE_Registry::$i18n_js_strings['timer_days'] = esc_html__('days', 'event_espresso');
1440
-        EE_Registry::$i18n_js_strings['timer_hours'] = esc_html__('hours', 'event_espresso');
1441
-        EE_Registry::$i18n_js_strings['timer_minutes'] = esc_html__('minutes', 'event_espresso');
1442
-        EE_Registry::$i18n_js_strings['timer_seconds'] = esc_html__('seconds', 'event_espresso');
1443
-        EE_Registry::$i18n_js_strings['timer_year'] = esc_html__('year', 'event_espresso');
1444
-        EE_Registry::$i18n_js_strings['timer_month'] = esc_html__('month', 'event_espresso');
1445
-        EE_Registry::$i18n_js_strings['timer_week'] = esc_html__('week', 'event_espresso');
1446
-        EE_Registry::$i18n_js_strings['timer_day'] = esc_html__('day', 'event_espresso');
1447
-        EE_Registry::$i18n_js_strings['timer_hour'] = esc_html__('hour', 'event_espresso');
1448
-        EE_Registry::$i18n_js_strings['timer_minute'] = esc_html__('minute', 'event_espresso');
1449
-        EE_Registry::$i18n_js_strings['timer_second'] = esc_html__('second', 'event_espresso');
1450
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
1451
-        );
1452
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1453
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1454
-            true
1455
-        );
1456
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1457
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1458
-        );
1459
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1460
-            'M d, Y H:i:s',
1461
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1462
-        );
1463
-    }
1464
-
1465
-
1466
-    /**
1467
-     *    enqueue_styles_and_scripts
1468
-     *
1469
-     * @access        public
1470
-     * @return        void
1471
-     * @throws EE_Error
1472
-     */
1473
-    public function enqueue_styles_and_scripts()
1474
-    {
1475
-        // load css
1476
-        wp_register_style(
1477
-            'single_page_checkout',
1478
-            SPCO_CSS_URL . 'single_page_checkout.css',
1479
-            array('espresso_default'),
1480
-            EVENT_ESPRESSO_VERSION
1481
-        );
1482
-        wp_enqueue_style('single_page_checkout');
1483
-        // load JS
1484
-        wp_register_script(
1485
-            'jquery_plugin',
1486
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1487
-            array('jquery'),
1488
-            '1.0.1',
1489
-            true
1490
-        );
1491
-        wp_register_script(
1492
-            'jquery_countdown',
1493
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1494
-            array('jquery_plugin'),
1495
-            '2.1.0',
1496
-            true
1497
-        );
1498
-        wp_register_script(
1499
-            'single_page_checkout',
1500
-            SPCO_JS_URL . 'single_page_checkout.js',
1501
-            array('espresso_core', 'underscore', 'ee_form_section_validation'),
1502
-            EVENT_ESPRESSO_VERSION,
1503
-            true
1504
-        );
1505
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1506
-            $this->checkout->registration_form->enqueue_js();
1507
-        }
1508
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1509
-            $this->checkout->current_step->reg_form->enqueue_js();
1510
-        }
1511
-        wp_enqueue_script('single_page_checkout');
1512
-        if (apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)) {
1513
-            wp_enqueue_script('jquery_countdown');
1514
-        }
1515
-        /**
1516
-         * global action hook for enqueueing styles and scripts with
1517
-         * spco calls.
1518
-         */
1519
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1520
-        /**
1521
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1522
-         * The hook will end up being something like:
1523
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1524
-         */
1525
-        do_action(
1526
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1527
-            $this
1528
-        );
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     *    display the Registration Single Page Checkout Form
1534
-     *
1535
-     * @access    private
1536
-     * @return    void
1537
-     * @throws EE_Error
1538
-     */
1539
-    private function _display_spco_reg_form()
1540
-    {
1541
-        // if registering via the admin, just display the reg form for the current step
1542
-        if ($this->checkout->admin_request) {
1543
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1544
-        } else {
1545
-            // add powered by EE msg
1546
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1547
-            $empty_cart = count($this->checkout->transaction
1548
-                                    ->registrations($this->checkout->reg_cache_where_params)) < 1;
1549
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1550
-            $cookies_not_set_msg = '';
1551
-            if ($empty_cart) {
1552
-                $cookies_not_set_msg = apply_filters(
1553
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1554
-                    sprintf(
1555
-                        esc_html__(
1556
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1557
-                            'event_espresso'
1558
-                        ),
1559
-                        '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1560
-                        '</div>',
1561
-                        '<h6 class="important-notice">',
1562
-                        '</h6>',
1563
-                        '<p>',
1564
-                        '</p>',
1565
-                        '<br />',
1566
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank" rel="noopener noreferrer">',
1567
-                        '</a>'
1568
-                    )
1569
-                );
1570
-            }
1571
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1572
-                array(
1573
-                    'name'            => 'single-page-checkout',
1574
-                    'html_id'         => 'ee-single-page-checkout-dv',
1575
-                    'layout_strategy' =>
1576
-                        new EE_Template_Layout(
1577
-                            array(
1578
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1579
-                                'template_args'        => array(
1580
-                                    'empty_cart'              => $empty_cart,
1581
-                                    'revisit'                 => $this->checkout->revisit,
1582
-                                    'reg_steps'               => $this->checkout->reg_steps,
1583
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1584
-                                        ? $this->checkout->next_step->slug()
1585
-                                        : '',
1586
-                                    'empty_msg'               => apply_filters(
1587
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1588
-                                        sprintf(
1589
-                                            esc_html__(
1590
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1591
-                                                'event_espresso'
1592
-                                            ),
1593
-                                            '<a href="'
1594
-                                            . get_post_type_archive_link('espresso_events')
1595
-                                            . '" title="',
1596
-                                            '">',
1597
-                                            '</a>'
1598
-                                        )
1599
-                                    ),
1600
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1601
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1602
-                                    'session_expiration'      => gmdate(
1603
-                                        'M d, Y H:i:s',
1604
-                                        EE_Registry::instance()->SSN->expiration()
1605
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1606
-                                    ),
1607
-                                ),
1608
-                            )
1609
-                        ),
1610
-                )
1611
-            );
1612
-            // load template and add to output sent that gets filtered into the_content()
1613
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1614
-        }
1615
-    }
1616
-
1617
-
1618
-    /**
1619
-     *    add_extra_finalize_registration_inputs
1620
-     *
1621
-     * @access    public
1622
-     * @param $next_step
1623
-     * @internal  param string $label
1624
-     * @return void
1625
-     */
1626
-    public function add_extra_finalize_registration_inputs($next_step)
1627
-    {
1628
-        if ($next_step === 'finalize_registration') {
1629
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1630
-        }
1631
-    }
1632
-
1633
-
1634
-    /**
1635
-     *    display_registration_footer
1636
-     *
1637
-     * @access    public
1638
-     * @return    string
1639
-     */
1640
-    public static function display_registration_footer()
1641
-    {
1642
-        if (apply_filters(
1643
-            'FHEE__EE_Front__Controller__show_reg_footer',
1644
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1645
-        )) {
1646
-            add_filter(
1647
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1648
-                function ($url) {
1649
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1650
-                }
1651
-            );
1652
-            echo apply_filters(
1653
-                'FHEE__EE_Front_Controller__display_registration_footer',
1654
-                \EEH_Template::powered_by_event_espresso(
1655
-                    '',
1656
-                    'espresso-registration-footer-dv',
1657
-                    array('utm_content' => 'registration_checkout')
1658
-                )
1659
-            );
1660
-        }
1661
-        return '';
1662
-    }
1663
-
1664
-
1665
-    /**
1666
-     *    unlock_transaction
1667
-     *
1668
-     * @access    public
1669
-     * @return    void
1670
-     * @throws EE_Error
1671
-     */
1672
-    public function unlock_transaction()
1673
-    {
1674
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1675
-            $this->checkout->transaction->unlock();
1676
-        }
1677
-    }
1678
-
1679
-
1680
-    /**
1681
-     *        _setup_redirect
1682
-     *
1683
-     * @access    private
1684
-     * @return void
1685
-     */
1686
-    private function _setup_redirect()
1687
-    {
1688
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1689
-            $this->checkout->redirect = true;
1690
-            if (empty($this->checkout->redirect_url)) {
1691
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1692
-            }
1693
-            $this->checkout->redirect_url = apply_filters(
1694
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1695
-                $this->checkout->redirect_url,
1696
-                $this->checkout
1697
-            );
1698
-        }
1699
-    }
1700
-
1701
-
1702
-    /**
1703
-     *   handle ajax message responses and redirects
1704
-     *
1705
-     * @access public
1706
-     * @return void
1707
-     * @throws EE_Error
1708
-     */
1709
-    public function go_to_next_step()
1710
-    {
1711
-        if (EE_Registry::instance()->REQ->ajax) {
1712
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1713
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1714
-        }
1715
-        $this->unlock_transaction();
1716
-        // just return for these conditions
1717
-        if ($this->checkout->admin_request
1718
-            || $this->checkout->action === 'redirect_form'
1719
-            || $this->checkout->action === 'update_checkout'
1720
-        ) {
1721
-            return;
1722
-        }
1723
-        // AJAX response
1724
-        $this->_handle_json_response();
1725
-        // redirect to next step or the Thank You page
1726
-        $this->_handle_html_redirects();
1727
-        // hmmm... must be something wrong, so let's just display the form again !
1728
-        $this->_display_spco_reg_form();
1729
-    }
1730
-
1731
-
1732
-    /**
1733
-     *   _handle_json_response
1734
-     *
1735
-     * @access protected
1736
-     * @return void
1737
-     */
1738
-    protected function _handle_json_response()
1739
-    {
1740
-        // if this is an ajax request
1741
-        if (EE_Registry::instance()->REQ->ajax) {
1742
-            $this->checkout->json_response->set_registration_time_limit(
1743
-                $this->checkout->get_registration_time_limit()
1744
-            );
1745
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1746
-            // just send the ajax (
1747
-            $json_response = apply_filters(
1748
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1749
-                $this->checkout->json_response
1750
-            );
1751
-            echo $json_response;
1752
-            exit();
1753
-        }
1754
-    }
1755
-
1756
-
1757
-    /**
1758
-     *   _handle_redirects
1759
-     *
1760
-     * @access protected
1761
-     * @return void
1762
-     */
1763
-    protected function _handle_html_redirects()
1764
-    {
1765
-        // going somewhere ?
1766
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1767
-            // store notices in a transient
1768
-            EE_Error::get_notices(false, true, true);
1769
-            wp_safe_redirect($this->checkout->redirect_url);
1770
-            exit();
1771
-        }
1772
-    }
1773
-
1774
-
1775
-    /**
1776
-     *   set_checkout_anchor
1777
-     *
1778
-     * @access public
1779
-     * @return void
1780
-     */
1781
-    public function set_checkout_anchor()
1782
-    {
1783
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1784
-    }
1785
-
1786
-    /**
1787
-     *    getRegistrationExpirationNotice
1788
-     *
1789
-     * @since     4.9.59.p
1790
-     * @access    public
1791
-     * @return    string
1792
-     */
1793
-    public static function getRegistrationExpirationNotice()
1794
-    {
1795
-        return sprintf(
1796
-            esc_html__(
1797
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1798
-                'event_espresso'
1799
-            ),
1800
-            '<h4 class="important-notice">',
1801
-            '</h4>',
1802
-            '<br />',
1803
-            '<p>',
1804
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1805
-            '">',
1806
-            '</a>',
1807
-            '</p>'
1808
-        );
1809
-    }
18
+	/**
19
+	 * $_initialized - has the SPCO controller already been initialized ?
20
+	 *
21
+	 * @access private
22
+	 * @var bool $_initialized
23
+	 */
24
+	private static $_initialized = false;
25
+
26
+
27
+	/**
28
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
29
+	 *
30
+	 * @access private
31
+	 * @var bool $_valid_checkout
32
+	 */
33
+	private static $_checkout_verified = true;
34
+
35
+	/**
36
+	 *    $_reg_steps_array - holds initial array of reg steps
37
+	 *
38
+	 * @access private
39
+	 * @var array $_reg_steps_array
40
+	 */
41
+	private static $_reg_steps_array = array();
42
+
43
+	/**
44
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
45
+	 *
46
+	 * @access public
47
+	 * @var EE_Checkout $checkout
48
+	 */
49
+	public $checkout;
50
+
51
+
52
+	/**
53
+	 * @return EED_Module|EED_Single_Page_Checkout
54
+	 */
55
+	public static function instance()
56
+	{
57
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
58
+		return parent::get_instance(__CLASS__);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @return EE_CART
64
+	 */
65
+	public function cart()
66
+	{
67
+		return $this->checkout->cart;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @return EE_Transaction
73
+	 */
74
+	public function transaction()
75
+	{
76
+		return $this->checkout->transaction;
77
+	}
78
+
79
+
80
+	/**
81
+	 *    set_hooks - for hooking into EE Core, other modules, etc
82
+	 *
83
+	 * @access    public
84
+	 * @return    void
85
+	 * @throws EE_Error
86
+	 */
87
+	public static function set_hooks()
88
+	{
89
+		EED_Single_Page_Checkout::set_definitions();
90
+	}
91
+
92
+
93
+	/**
94
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
95
+	 *
96
+	 * @access    public
97
+	 * @return    void
98
+	 * @throws EE_Error
99
+	 */
100
+	public static function set_hooks_admin()
101
+	{
102
+		EED_Single_Page_Checkout::set_definitions();
103
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
104
+			return;
105
+		}
106
+		// going to start an output buffer in case anything gets accidentally output
107
+		// that might disrupt our JSON response
108
+		ob_start();
109
+		EED_Single_Page_Checkout::load_request_handler();
110
+		EED_Single_Page_Checkout::load_reg_steps();
111
+		// set ajax hooks
112
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
113
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
114
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
115
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
116
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
117
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
118
+	}
119
+
120
+
121
+	/**
122
+	 *    process ajax request
123
+	 *
124
+	 * @param string $ajax_action
125
+	 * @throws EE_Error
126
+	 */
127
+	public static function process_ajax_request($ajax_action)
128
+	{
129
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
130
+		EED_Single_Page_Checkout::instance()->_initialize();
131
+	}
132
+
133
+
134
+	/**
135
+	 *    ajax display registration step
136
+	 *
137
+	 * @throws EE_Error
138
+	 */
139
+	public static function display_reg_step()
140
+	{
141
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
142
+	}
143
+
144
+
145
+	/**
146
+	 *    ajax process registration step
147
+	 *
148
+	 * @throws EE_Error
149
+	 */
150
+	public static function process_reg_step()
151
+	{
152
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
153
+	}
154
+
155
+
156
+	/**
157
+	 *    ajax process registration step
158
+	 *
159
+	 * @throws EE_Error
160
+	 */
161
+	public static function update_reg_step()
162
+	{
163
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
164
+	}
165
+
166
+
167
+	/**
168
+	 *   update_checkout
169
+	 *
170
+	 * @access public
171
+	 * @return void
172
+	 * @throws EE_Error
173
+	 */
174
+	public static function update_checkout()
175
+	{
176
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
177
+	}
178
+
179
+
180
+	/**
181
+	 *    load_request_handler
182
+	 *
183
+	 * @access    public
184
+	 * @return    void
185
+	 */
186
+	public static function load_request_handler()
187
+	{
188
+		// load core Request_Handler class
189
+		if (EE_Registry::instance()->REQ !== null) {
190
+			EE_Registry::instance()->load_core('Request_Handler');
191
+		}
192
+	}
193
+
194
+
195
+	/**
196
+	 *    set_definitions
197
+	 *
198
+	 * @access    public
199
+	 * @return    void
200
+	 * @throws EE_Error
201
+	 */
202
+	public static function set_definitions()
203
+	{
204
+		if (defined('SPCO_BASE_PATH')) {
205
+			return;
206
+		}
207
+		define(
208
+			'SPCO_BASE_PATH',
209
+			rtrim(str_replace(array('\\', '/'), '/', plugin_dir_path(__FILE__)), '/') . '/'
210
+		);
211
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
212
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
213
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
214
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
215
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
216
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
217
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
218
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
219
+		);
220
+	}
221
+
222
+
223
+	/**
224
+	 * load_reg_steps
225
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
226
+	 *
227
+	 * @access    private
228
+	 * @throws EE_Error
229
+	 */
230
+	public static function load_reg_steps()
231
+	{
232
+		static $reg_steps_loaded = false;
233
+		if ($reg_steps_loaded) {
234
+			return;
235
+		}
236
+		// filter list of reg_steps
237
+		$reg_steps_to_load = (array) apply_filters(
238
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
239
+			EED_Single_Page_Checkout::get_reg_steps()
240
+		);
241
+		// sort by key (order)
242
+		ksort($reg_steps_to_load);
243
+		// loop through folders
244
+		foreach ($reg_steps_to_load as $order => $reg_step) {
245
+			// we need a
246
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
247
+				// copy over to the reg_steps_array
248
+				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
249
+				// register custom key route for each reg step
250
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
251
+				EE_Config::register_route(
252
+					$reg_step['slug'],
253
+					'EED_Single_Page_Checkout',
254
+					'run',
255
+					'step'
256
+				);
257
+				// add AJAX or other hooks
258
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
259
+					// setup autoloaders if necessary
260
+					if (! class_exists($reg_step['class_name'])) {
261
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
262
+							$reg_step['file_path'],
263
+							true
264
+						);
265
+					}
266
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
267
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
268
+					}
269
+				}
270
+			}
271
+		}
272
+		$reg_steps_loaded = true;
273
+	}
274
+
275
+
276
+	/**
277
+	 *    get_reg_steps
278
+	 *
279
+	 * @access    public
280
+	 * @return    array
281
+	 */
282
+	public static function get_reg_steps()
283
+	{
284
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
285
+		if (empty($reg_steps)) {
286
+			$reg_steps = array(
287
+				10  => array(
288
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
289
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
290
+					'slug'       => 'attendee_information',
291
+					'has_hooks'  => false,
292
+				),
293
+				30  => array(
294
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
295
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
296
+					'slug'       => 'payment_options',
297
+					'has_hooks'  => true,
298
+				),
299
+				999 => array(
300
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
301
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
302
+					'slug'       => 'finalize_registration',
303
+					'has_hooks'  => false,
304
+				),
305
+			);
306
+		}
307
+		return $reg_steps;
308
+	}
309
+
310
+
311
+	/**
312
+	 *    registration_checkout_for_admin
313
+	 *
314
+	 * @access    public
315
+	 * @return    string
316
+	 * @throws EE_Error
317
+	 */
318
+	public static function registration_checkout_for_admin()
319
+	{
320
+		EED_Single_Page_Checkout::load_request_handler();
321
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
322
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
323
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
324
+		EED_Single_Page_Checkout::instance()->_initialize();
325
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
326
+		return EE_Registry::instance()->REQ->get_output();
327
+	}
328
+
329
+
330
+	/**
331
+	 * process_registration_from_admin
332
+	 *
333
+	 * @access public
334
+	 * @return \EE_Transaction
335
+	 * @throws EE_Error
336
+	 */
337
+	public static function process_registration_from_admin()
338
+	{
339
+		EED_Single_Page_Checkout::load_request_handler();
340
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
341
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
342
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
343
+		EED_Single_Page_Checkout::instance()->_initialize();
344
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
345
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
346
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
347
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
348
+				if ($final_reg_step->process_reg_step()) {
349
+					$final_reg_step->set_completed();
350
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
351
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
352
+				}
353
+			}
354
+		}
355
+		return null;
356
+	}
357
+
358
+
359
+	/**
360
+	 *    run
361
+	 *
362
+	 * @access    public
363
+	 * @param WP_Query $WP_Query
364
+	 * @return    void
365
+	 * @throws EE_Error
366
+	 */
367
+	public function run($WP_Query)
368
+	{
369
+		if ($WP_Query instanceof WP_Query
370
+			&& $WP_Query->is_main_query()
371
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
372
+			&& $this->_is_reg_checkout()
373
+		) {
374
+			$this->_initialize();
375
+		}
376
+	}
377
+
378
+
379
+	/**
380
+	 * determines whether current url matches reg page url
381
+	 *
382
+	 * @return bool
383
+	 */
384
+	protected function _is_reg_checkout()
385
+	{
386
+		// get current permalink for reg page without any extra query args
387
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
388
+		// get request URI for current request, but without the scheme or host
389
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
390
+		$current_request_uri = html_entity_decode($current_request_uri);
391
+		// get array of query args from the current request URI
392
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
393
+		// grab page id if it is set
394
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
395
+		// and remove the page id from the query args (we will re-add it later)
396
+		unset($query_args['page_id']);
397
+		// now strip all query args from current request URI
398
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
399
+		// and re-add the page id if it was set
400
+		if ($page_id) {
401
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
402
+		}
403
+		// remove slashes and ?
404
+		$current_request_uri = trim($current_request_uri, '?/');
405
+		// is current request URI part of the known full reg page URL ?
406
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
407
+	}
408
+
409
+
410
+	/**
411
+	 * @param WP_Query $wp_query
412
+	 * @return    void
413
+	 * @throws EE_Error
414
+	 */
415
+	public static function init($wp_query)
416
+	{
417
+		EED_Single_Page_Checkout::instance()->run($wp_query);
418
+	}
419
+
420
+
421
+	/**
422
+	 *    _initialize - initial module setup
423
+	 *
424
+	 * @access    private
425
+	 * @throws EE_Error
426
+	 * @return    void
427
+	 */
428
+	private function _initialize()
429
+	{
430
+		// ensure SPCO doesn't run twice
431
+		if (EED_Single_Page_Checkout::$_initialized) {
432
+			return;
433
+		}
434
+		try {
435
+			EED_Single_Page_Checkout::load_reg_steps();
436
+			$this->_verify_session();
437
+			// setup the EE_Checkout object
438
+			$this->checkout = $this->_initialize_checkout();
439
+			// filter checkout
440
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
441
+			// get the $_GET
442
+			$this->_get_request_vars();
443
+			if ($this->_block_bots()) {
444
+				return;
445
+			}
446
+			// filter continue_reg
447
+			$this->checkout->continue_reg = apply_filters(
448
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
449
+				true,
450
+				$this->checkout
451
+			);
452
+			// load the reg steps array
453
+			if (! $this->_load_and_instantiate_reg_steps()) {
454
+				EED_Single_Page_Checkout::$_initialized = true;
455
+				return;
456
+			}
457
+			// set the current step
458
+			$this->checkout->set_current_step($this->checkout->step);
459
+			// and the next step
460
+			$this->checkout->set_next_step();
461
+			// verify that everything has been setup correctly
462
+			if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
463
+				EED_Single_Page_Checkout::$_initialized = true;
464
+				return;
465
+			}
466
+			// lock the transaction
467
+			$this->checkout->transaction->lock();
468
+			// make sure all of our cached objects are added to their respective model entity mappers
469
+			$this->checkout->refresh_all_entities();
470
+			// set amount owing
471
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
472
+			// initialize each reg step, which gives them the chance to potentially alter the process
473
+			$this->_initialize_reg_steps();
474
+			// DEBUG LOG
475
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
476
+			// get reg form
477
+			if (! $this->_check_form_submission()) {
478
+				EED_Single_Page_Checkout::$_initialized = true;
479
+				return;
480
+			}
481
+			// checkout the action!!!
482
+			$this->_process_form_action();
483
+			// add some style and make it dance
484
+			$this->add_styles_and_scripts($this);
485
+			// kk... SPCO has successfully run
486
+			EED_Single_Page_Checkout::$_initialized = true;
487
+			// set no cache headers and constants
488
+			EE_System::do_not_cache();
489
+			// add anchor
490
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
491
+			// remove transaction lock
492
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
493
+		} catch (Exception $e) {
494
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
495
+		}
496
+	}
497
+
498
+
499
+	/**
500
+	 *    _verify_session
501
+	 * checks that the session is valid and not expired
502
+	 *
503
+	 * @access    private
504
+	 * @throws EE_Error
505
+	 */
506
+	private function _verify_session()
507
+	{
508
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
509
+			throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
510
+		}
511
+		$clear_session_requested = filter_var(
512
+			EE_Registry::instance()->REQ->get('clear_session', false),
513
+			FILTER_VALIDATE_BOOLEAN
514
+		);
515
+		// is session still valid ?
516
+		if ($clear_session_requested
517
+			|| (EE_Registry::instance()->SSN->expired()
518
+				&& EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
519
+			)
520
+		) {
521
+			$this->checkout = new EE_Checkout();
522
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
523
+			// EE_Registry::instance()->SSN->reset_cart();
524
+			// EE_Registry::instance()->SSN->reset_checkout();
525
+			// EE_Registry::instance()->SSN->reset_transaction();
526
+			if (! $clear_session_requested) {
527
+				EE_Error::add_attention(
528
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
529
+					__FILE__,
530
+					__FUNCTION__,
531
+					__LINE__
532
+				);
533
+			}
534
+			// EE_Registry::instance()->SSN->reset_expired();
535
+		}
536
+	}
537
+
538
+
539
+	/**
540
+	 *    _initialize_checkout
541
+	 * loads and instantiates EE_Checkout
542
+	 *
543
+	 * @access    private
544
+	 * @throws EE_Error
545
+	 * @return EE_Checkout
546
+	 */
547
+	private function _initialize_checkout()
548
+	{
549
+		// look in session for existing checkout
550
+		/** @type EE_Checkout $checkout */
551
+		$checkout = EE_Registry::instance()->SSN->checkout();
552
+		// verify
553
+		if (! $checkout instanceof EE_Checkout) {
554
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
555
+			$checkout = EE_Registry::instance()->load_file(
556
+				SPCO_INC_PATH,
557
+				'EE_Checkout',
558
+				'class',
559
+				array(),
560
+				false
561
+			);
562
+		} else {
563
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
564
+				$this->unlock_transaction();
565
+				wp_safe_redirect($checkout->redirect_url);
566
+				exit();
567
+			}
568
+		}
569
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
570
+		// verify again
571
+		if (! $checkout instanceof EE_Checkout) {
572
+			throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
573
+		}
574
+		// reset anything that needs a clean slate for each request
575
+		$checkout->reset_for_current_request();
576
+		return $checkout;
577
+	}
578
+
579
+
580
+	/**
581
+	 *    _get_request_vars
582
+	 *
583
+	 * @access    private
584
+	 * @return    void
585
+	 * @throws EE_Error
586
+	 */
587
+	private function _get_request_vars()
588
+	{
589
+		// load classes
590
+		EED_Single_Page_Checkout::load_request_handler();
591
+		// make sure this request is marked as belonging to EE
592
+		EE_Registry::instance()->REQ->set_espresso_page(true);
593
+		// which step is being requested ?
594
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
595
+		// which step is being edited ?
596
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
597
+		// and what we're doing on the current step
598
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
599
+		// timestamp
600
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
601
+		// returning to edit ?
602
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
603
+		// add reg url link to registration query params
604
+		if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
605
+			$this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
606
+		}
607
+		// or some other kind of revisit ?
608
+		$this->checkout->revisit = filter_var(
609
+			EE_Registry::instance()->REQ->get('revisit', false),
610
+			FILTER_VALIDATE_BOOLEAN
611
+		);
612
+		// and whether or not to generate a reg form for this request
613
+		$this->checkout->generate_reg_form = filter_var(
614
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
615
+			FILTER_VALIDATE_BOOLEAN
616
+		);
617
+		// and whether or not to process a reg form submission for this request
618
+		$this->checkout->process_form_submission = filter_var(
619
+			EE_Registry::instance()->REQ->get(
620
+				'process_form_submission',
621
+				$this->checkout->action === 'process_reg_step'
622
+			),
623
+			FILTER_VALIDATE_BOOLEAN
624
+		);
625
+		$this->checkout->process_form_submission = filter_var(
626
+			$this->checkout->action !== 'display_spco_reg_step'
627
+				? $this->checkout->process_form_submission
628
+				: false,
629
+			FILTER_VALIDATE_BOOLEAN
630
+		);
631
+		// $this->_display_request_vars();
632
+	}
633
+
634
+
635
+	/**
636
+	 *  _display_request_vars
637
+	 *
638
+	 * @access    protected
639
+	 * @return    void
640
+	 */
641
+	protected function _display_request_vars()
642
+	{
643
+		if (! WP_DEBUG) {
644
+			return;
645
+		}
646
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
647
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
648
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
649
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
650
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
651
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
652
+		EEH_Debug_Tools::printr(
653
+			$this->checkout->generate_reg_form,
654
+			'$this->checkout->generate_reg_form',
655
+			__FILE__,
656
+			__LINE__
657
+		);
658
+		EEH_Debug_Tools::printr(
659
+			$this->checkout->process_form_submission,
660
+			'$this->checkout->process_form_submission',
661
+			__FILE__,
662
+			__LINE__
663
+		);
664
+	}
665
+
666
+
667
+	/**
668
+	 * _block_bots
669
+	 * checks that the incoming request has either of the following set:
670
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
671
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
672
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
673
+	 * then where you coming from man?
674
+	 *
675
+	 * @return boolean
676
+	 */
677
+	private function _block_bots()
678
+	{
679
+		$invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
680
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
681
+			return true;
682
+		}
683
+		return false;
684
+	}
685
+
686
+
687
+	/**
688
+	 *    _get_first_step
689
+	 *  gets slug for first step in $_reg_steps_array
690
+	 *
691
+	 * @access    private
692
+	 * @throws EE_Error
693
+	 * @return    string
694
+	 */
695
+	private function _get_first_step()
696
+	{
697
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
698
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
699
+	}
700
+
701
+
702
+	/**
703
+	 * instantiates each reg step based on the loaded reg_steps array
704
+	 *
705
+	 * @return    bool
706
+	 * @throws EE_Error
707
+	 * @throws InvalidArgumentException
708
+	 * @throws InvalidDataTypeException
709
+	 * @throws InvalidInterfaceException
710
+	 */
711
+	private function _load_and_instantiate_reg_steps()
712
+	{
713
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
714
+		// have reg_steps already been instantiated ?
715
+		if (empty($this->checkout->reg_steps)
716
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
717
+		) {
718
+			// if not, then loop through raw reg steps array
719
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
720
+				if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
721
+					return false;
722
+				}
723
+			}
724
+			if (isset($this->checkout->reg_steps['registration_confirmation'])) {
725
+				// skip the registration_confirmation page ?
726
+				if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
727
+					// just remove it from the reg steps array
728
+					$this->checkout->remove_reg_step('registration_confirmation', false);
729
+				} elseif (EE_Registry::instance()->CFG->registration->reg_confirmation_last
730
+				) {
731
+					// set the order to something big like 100
732
+					$this->checkout->set_reg_step_order('registration_confirmation', 100);
733
+				}
734
+			}
735
+			// filter the array for good luck
736
+			$this->checkout->reg_steps = apply_filters(
737
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
738
+				$this->checkout->reg_steps
739
+			);
740
+			// finally re-sort based on the reg step class order properties
741
+			$this->checkout->sort_reg_steps();
742
+		} else {
743
+			foreach ($this->checkout->reg_steps as $reg_step) {
744
+				// set all current step stati to FALSE
745
+				$reg_step->set_is_current_step(false);
746
+			}
747
+		}
748
+		if (empty($this->checkout->reg_steps)) {
749
+			EE_Error::add_error(
750
+				esc_html__('No Reg Steps were loaded..', 'event_espresso'),
751
+				__FILE__,
752
+				__FUNCTION__,
753
+				__LINE__
754
+			);
755
+			return false;
756
+		}
757
+		// make reg step details available to JS
758
+		$this->checkout->set_reg_step_JSON_info();
759
+		return true;
760
+	}
761
+
762
+
763
+	/**
764
+	 *     _load_and_instantiate_reg_step
765
+	 *
766
+	 * @access    private
767
+	 * @param array $reg_step
768
+	 * @param int   $order
769
+	 * @return bool
770
+	 */
771
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
772
+	{
773
+		// we need a file_path, class_name, and slug to add a reg step
774
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
775
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
776
+			if ($this->checkout->reg_url_link
777
+				&& $this->checkout->step !== $reg_step['slug']
778
+				&& $reg_step['slug'] !== 'finalize_registration'
779
+				// normally at this point we would NOT load the reg step, but this filter can change that
780
+				&& apply_filters(
781
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
782
+					true,
783
+					$reg_step,
784
+					$this->checkout
785
+				)
786
+			) {
787
+				return true;
788
+			}
789
+			// instantiate step class using file path and class name
790
+			$reg_step_obj = EE_Registry::instance()->load_file(
791
+				$reg_step['file_path'],
792
+				$reg_step['class_name'],
793
+				'class',
794
+				$this->checkout,
795
+				false
796
+			);
797
+			// did we gets the goods ?
798
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
799
+				// set reg step order based on config
800
+				$reg_step_obj->set_order($order);
801
+				// add instantiated reg step object to the master reg steps array
802
+				$this->checkout->add_reg_step($reg_step_obj);
803
+			} else {
804
+				EE_Error::add_error(
805
+					esc_html__('The current step could not be set.', 'event_espresso'),
806
+					__FILE__,
807
+					__FUNCTION__,
808
+					__LINE__
809
+				);
810
+				return false;
811
+			}
812
+		} else {
813
+			if (WP_DEBUG) {
814
+				EE_Error::add_error(
815
+					sprintf(
816
+						esc_html__(
817
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
818
+							'event_espresso'
819
+						),
820
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
821
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
822
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
823
+						'<ul>',
824
+						'<li>',
825
+						'</li>',
826
+						'</ul>'
827
+					),
828
+					__FILE__,
829
+					__FUNCTION__,
830
+					__LINE__
831
+				);
832
+			}
833
+			return false;
834
+		}
835
+		return true;
836
+	}
837
+
838
+
839
+	/**
840
+	 * _verify_transaction_and_get_registrations
841
+	 *
842
+	 * @access private
843
+	 * @return bool
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws InvalidEntityException
846
+	 * @throws EE_Error
847
+	 */
848
+	private function _verify_transaction_and_get_registrations()
849
+	{
850
+		// was there already a valid transaction in the checkout from the session ?
851
+		if (! $this->checkout->transaction instanceof EE_Transaction) {
852
+			// get transaction from db or session
853
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
854
+				? $this->_get_transaction_and_cart_for_previous_visit()
855
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
856
+			if (! $this->checkout->transaction instanceof EE_Transaction) {
857
+				EE_Error::add_error(
858
+					esc_html__(
859
+						'Your Registration and Transaction information could not be retrieved from the db.',
860
+						'event_espresso'
861
+					),
862
+					__FILE__,
863
+					__FUNCTION__,
864
+					__LINE__
865
+				);
866
+				$this->checkout->transaction = EE_Transaction::new_instance();
867
+				// add some style and make it dance
868
+				$this->add_styles_and_scripts($this);
869
+				EED_Single_Page_Checkout::$_initialized = true;
870
+				return false;
871
+			}
872
+			// and the registrations for the transaction
873
+			$this->_get_registrations($this->checkout->transaction);
874
+		}
875
+		return true;
876
+	}
877
+
878
+
879
+	/**
880
+	 * _get_transaction_and_cart_for_previous_visit
881
+	 *
882
+	 * @access private
883
+	 * @return mixed EE_Transaction|NULL
884
+	 */
885
+	private function _get_transaction_and_cart_for_previous_visit()
886
+	{
887
+		/** @var $TXN_model EEM_Transaction */
888
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
889
+		// because the reg_url_link is present in the request,
890
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
891
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
892
+		// verify transaction
893
+		if ($transaction instanceof EE_Transaction) {
894
+			// and get the cart that was used for that transaction
895
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
896
+			return $transaction;
897
+		}
898
+		EE_Error::add_error(
899
+			esc_html__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
900
+			__FILE__,
901
+			__FUNCTION__,
902
+			__LINE__
903
+		);
904
+		return null;
905
+	}
906
+
907
+
908
+	/**
909
+	 * _get_cart_for_transaction
910
+	 *
911
+	 * @access private
912
+	 * @param EE_Transaction $transaction
913
+	 * @return EE_Cart
914
+	 */
915
+	private function _get_cart_for_transaction($transaction)
916
+	{
917
+		return $this->checkout->get_cart_for_transaction($transaction);
918
+	}
919
+
920
+
921
+	/**
922
+	 * get_cart_for_transaction
923
+	 *
924
+	 * @access public
925
+	 * @param EE_Transaction $transaction
926
+	 * @return EE_Cart
927
+	 */
928
+	public function get_cart_for_transaction(EE_Transaction $transaction)
929
+	{
930
+		return $this->checkout->get_cart_for_transaction($transaction);
931
+	}
932
+
933
+
934
+	/**
935
+	 * _get_transaction_and_cart_for_current_session
936
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
937
+	 *
938
+	 * @access private
939
+	 * @return EE_Transaction
940
+	 * @throws EE_Error
941
+	 */
942
+	private function _get_cart_for_current_session_and_setup_new_transaction()
943
+	{
944
+		//  if there's no transaction, then this is the FIRST visit to SPCO
945
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
946
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
947
+		// and then create a new transaction
948
+		$transaction = $this->_initialize_transaction();
949
+		// verify transaction
950
+		if ($transaction instanceof EE_Transaction) {
951
+			// save it so that we have an ID for other objects to use
952
+			$transaction->save();
953
+			// and save TXN data to the cart
954
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
955
+		} else {
956
+			EE_Error::add_error(
957
+				esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
958
+				__FILE__,
959
+				__FUNCTION__,
960
+				__LINE__
961
+			);
962
+		}
963
+		return $transaction;
964
+	}
965
+
966
+
967
+	/**
968
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
969
+	 *
970
+	 * @access private
971
+	 * @return mixed EE_Transaction|NULL
972
+	 */
973
+	private function _initialize_transaction()
974
+	{
975
+		try {
976
+			// ensure cart totals have been calculated
977
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
978
+			// grab the cart grand total
979
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
980
+			// create new TXN
981
+			$transaction = EE_Transaction::new_instance(
982
+				array(
983
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
984
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
985
+					'TXN_paid'      => 0,
986
+					'STS_ID'        => EEM_Transaction::failed_status_code,
987
+				)
988
+			);
989
+			// save it so that we have an ID for other objects to use
990
+			$transaction->save();
991
+			// set cron job for following up on TXNs after their session has expired
992
+			EE_Cron_Tasks::schedule_expired_transaction_check(
993
+				EE_Registry::instance()->SSN->expiration() + 1,
994
+				$transaction->ID()
995
+			);
996
+			return $transaction;
997
+		} catch (Exception $e) {
998
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
999
+		}
1000
+		return null;
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * _get_registrations
1006
+	 *
1007
+	 * @access private
1008
+	 * @param EE_Transaction $transaction
1009
+	 * @return void
1010
+	 * @throws InvalidDataTypeException
1011
+	 * @throws InvalidEntityException
1012
+	 * @throws EE_Error
1013
+	 */
1014
+	private function _get_registrations(EE_Transaction $transaction)
1015
+	{
1016
+		// first step: grab the registrants  { : o
1017
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1018
+		$this->checkout->total_ticket_count = count($registrations);
1019
+		// verify registrations have been set
1020
+		if (empty($registrations)) {
1021
+			// if no cached registrations, then check the db
1022
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1023
+			// still nothing ? well as long as this isn't a revisit
1024
+			if (empty($registrations) && ! $this->checkout->revisit) {
1025
+				// generate new registrations from scratch
1026
+				$registrations = $this->_initialize_registrations($transaction);
1027
+			}
1028
+		}
1029
+		// sort by their original registration order
1030
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1031
+		// then loop thru the array
1032
+		foreach ($registrations as $registration) {
1033
+			// verify each registration
1034
+			if ($registration instanceof EE_Registration) {
1035
+				// we display all attendee info for the primary registrant
1036
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1037
+					&& $registration->is_primary_registrant()
1038
+				) {
1039
+					$this->checkout->primary_revisit = true;
1040
+					break;
1041
+				}
1042
+				if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1043
+					// but hide info if it doesn't belong to you
1044
+					$transaction->clear_cache('Registration', $registration->ID());
1045
+					$this->checkout->total_ticket_count--;
1046
+				}
1047
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1048
+			}
1049
+		}
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1055
+	 *
1056
+	 * @access private
1057
+	 * @param EE_Transaction $transaction
1058
+	 * @return    array
1059
+	 * @throws InvalidDataTypeException
1060
+	 * @throws InvalidEntityException
1061
+	 * @throws EE_Error
1062
+	 */
1063
+	private function _initialize_registrations(EE_Transaction $transaction)
1064
+	{
1065
+		$att_nmbr = 0;
1066
+		$registrations = array();
1067
+		if ($transaction instanceof EE_Transaction) {
1068
+			/** @type EE_Registration_Processor $registration_processor */
1069
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1070
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1071
+			// now let's add the cart items to the $transaction
1072
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1073
+				// do the following for each ticket of this type they selected
1074
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1075
+					$att_nmbr++;
1076
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1077
+					$CreateRegistrationCommand = EE_Registry::instance()->create(
1078
+						'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1079
+						array(
1080
+							$transaction,
1081
+							$line_item,
1082
+							$att_nmbr,
1083
+							$this->checkout->total_ticket_count,
1084
+						)
1085
+					);
1086
+					// override capabilities for frontend registrations
1087
+					if (! is_admin()) {
1088
+						$CreateRegistrationCommand->setCapCheck(
1089
+							new PublicCapabilities('', 'create_new_registration')
1090
+						);
1091
+					}
1092
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1093
+					if (! $registration instanceof EE_Registration) {
1094
+						throw new InvalidEntityException($registration, 'EE_Registration');
1095
+					}
1096
+					$registrations[ $registration->ID() ] = $registration;
1097
+				}
1098
+			}
1099
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1100
+		}
1101
+		return $registrations;
1102
+	}
1103
+
1104
+
1105
+	/**
1106
+	 * sorts registrations by REG_count
1107
+	 *
1108
+	 * @access public
1109
+	 * @param EE_Registration $reg_A
1110
+	 * @param EE_Registration $reg_B
1111
+	 * @return int
1112
+	 */
1113
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1114
+	{
1115
+		// this shouldn't ever happen within the same TXN, but oh well
1116
+		if ($reg_A->count() === $reg_B->count()) {
1117
+			return 0;
1118
+		}
1119
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1120
+	}
1121
+
1122
+
1123
+	/**
1124
+	 *    _final_verifications
1125
+	 * just makes sure that everything is set up correctly before proceeding
1126
+	 *
1127
+	 * @access    private
1128
+	 * @return    bool
1129
+	 * @throws EE_Error
1130
+	 */
1131
+	private function _final_verifications()
1132
+	{
1133
+		// filter checkout
1134
+		$this->checkout = apply_filters(
1135
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1136
+			$this->checkout
1137
+		);
1138
+		// verify that current step is still set correctly
1139
+		if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1140
+			EE_Error::add_error(
1141
+				esc_html__(
1142
+					'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1143
+					'event_espresso'
1144
+				),
1145
+				__FILE__,
1146
+				__FUNCTION__,
1147
+				__LINE__
1148
+			);
1149
+			return false;
1150
+		}
1151
+		// if returning to SPCO, then verify that primary registrant is set
1152
+		if (! empty($this->checkout->reg_url_link)) {
1153
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1154
+			if (! $valid_registrant instanceof EE_Registration) {
1155
+				EE_Error::add_error(
1156
+					esc_html__(
1157
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1158
+						'event_espresso'
1159
+					),
1160
+					__FILE__,
1161
+					__FUNCTION__,
1162
+					__LINE__
1163
+				);
1164
+				return false;
1165
+			}
1166
+			$valid_registrant = null;
1167
+			foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1168
+				if ($registration instanceof EE_Registration
1169
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1170
+				) {
1171
+					$valid_registrant = $registration;
1172
+				}
1173
+			}
1174
+			if (! $valid_registrant instanceof EE_Registration) {
1175
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1176
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1177
+					// clear the session, mark the checkout as unverified, and try again
1178
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1179
+					EED_Single_Page_Checkout::$_initialized = false;
1180
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1181
+					$this->_initialize();
1182
+					EE_Error::reset_notices();
1183
+					return false;
1184
+				}
1185
+				EE_Error::add_error(
1186
+					esc_html__(
1187
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1188
+						'event_espresso'
1189
+					),
1190
+					__FILE__,
1191
+					__FUNCTION__,
1192
+					__LINE__
1193
+				);
1194
+				return false;
1195
+			}
1196
+		}
1197
+		// now that things have been kinda sufficiently verified,
1198
+		// let's add the checkout to the session so that it's available to other systems
1199
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1200
+		return true;
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 *    _initialize_reg_steps
1206
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1207
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1208
+	 *
1209
+	 * @access    private
1210
+	 * @param bool $reinitializing
1211
+	 * @throws EE_Error
1212
+	 */
1213
+	private function _initialize_reg_steps($reinitializing = false)
1214
+	{
1215
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1216
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1217
+		foreach ($this->checkout->reg_steps as $reg_step) {
1218
+			if (! $reg_step->initialize_reg_step()) {
1219
+				// if not initialized then maybe this step is being removed...
1220
+				if (! $reinitializing && $reg_step->is_current_step()) {
1221
+					// if it was the current step, then we need to start over here
1222
+					$this->_initialize_reg_steps(true);
1223
+					return;
1224
+				}
1225
+				continue;
1226
+			}
1227
+			// add css and JS for current step
1228
+			$this->add_styles_and_scripts($reg_step);
1229
+			if ($reg_step->is_current_step()) {
1230
+				// the text that appears on the reg step form submit button
1231
+				$reg_step->set_submit_button_text();
1232
+			}
1233
+		}
1234
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1235
+		do_action(
1236
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1237
+			$this->checkout->current_step
1238
+		);
1239
+	}
1240
+
1241
+
1242
+	/**
1243
+	 * _check_form_submission
1244
+	 *
1245
+	 * @access private
1246
+	 * @return boolean
1247
+	 */
1248
+	private function _check_form_submission()
1249
+	{
1250
+		// does this request require the reg form to be generated ?
1251
+		if ($this->checkout->generate_reg_form) {
1252
+			// ever heard that song by Blue Rodeo ?
1253
+			try {
1254
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1255
+				// if not displaying a form, then check for form submission
1256
+				if ($this->checkout->process_form_submission
1257
+					&& $this->checkout->current_step->reg_form->was_submitted()
1258
+				) {
1259
+					// clear out any old data in case this step is being run again
1260
+					$this->checkout->current_step->set_valid_data(array());
1261
+					// capture submitted form data
1262
+					$this->checkout->current_step->reg_form->receive_form_submission(
1263
+						apply_filters(
1264
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1265
+							EE_Registry::instance()->REQ->params(),
1266
+							$this->checkout
1267
+						)
1268
+					);
1269
+					// validate submitted form data
1270
+					if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1271
+						// thou shall not pass !!!
1272
+						$this->checkout->continue_reg = false;
1273
+						// any form validation errors?
1274
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1275
+							EE_Error::add_error(
1276
+								$this->checkout->current_step->reg_form->submission_error_message(),
1277
+								__FILE__,
1278
+								__FUNCTION__,
1279
+								__LINE__
1280
+							);
1281
+						}
1282
+						// well not really... what will happen is
1283
+						// we'll just get redirected back to redo the current step
1284
+						$this->go_to_next_step();
1285
+						return false;
1286
+					}
1287
+				}
1288
+			} catch (EE_Error $e) {
1289
+				$e->get_error();
1290
+			}
1291
+		}
1292
+		return true;
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * _process_action
1298
+	 *
1299
+	 * @access private
1300
+	 * @return void
1301
+	 * @throws EE_Error
1302
+	 */
1303
+	private function _process_form_action()
1304
+	{
1305
+		// what cha wanna do?
1306
+		switch ($this->checkout->action) {
1307
+			// AJAX next step reg form
1308
+			case 'display_spco_reg_step':
1309
+				$this->checkout->redirect = false;
1310
+				if (EE_Registry::instance()->REQ->ajax) {
1311
+					$this->checkout->json_response->set_reg_step_html(
1312
+						$this->checkout->current_step->display_reg_form()
1313
+					);
1314
+				}
1315
+				break;
1316
+			default:
1317
+				// meh... do one of those other steps first
1318
+				if (! empty($this->checkout->action)
1319
+					&& is_callable(array($this->checkout->current_step, $this->checkout->action))
1320
+				) {
1321
+					// dynamically creates hook point like:
1322
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1323
+					do_action(
1324
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1325
+						$this->checkout->current_step
1326
+					);
1327
+					// call action on current step
1328
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1329
+						// good registrant, you get to proceed
1330
+						if ($this->checkout->current_step->success_message() !== ''
1331
+							&& apply_filters(
1332
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1333
+								false
1334
+							)
1335
+						) {
1336
+							EE_Error::add_success(
1337
+								$this->checkout->current_step->success_message()
1338
+								. '<br />' . $this->checkout->next_step->_instructions()
1339
+							);
1340
+						}
1341
+						// pack it up, pack it in...
1342
+						$this->_setup_redirect();
1343
+					}
1344
+					// dynamically creates hook point like:
1345
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1346
+					do_action(
1347
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1348
+						$this->checkout->current_step
1349
+					);
1350
+				} else {
1351
+					EE_Error::add_error(
1352
+						sprintf(
1353
+							esc_html__(
1354
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1355
+								'event_espresso'
1356
+							),
1357
+							$this->checkout->action,
1358
+							$this->checkout->current_step->name()
1359
+						),
1360
+						__FILE__,
1361
+						__FUNCTION__,
1362
+						__LINE__
1363
+					);
1364
+				}
1365
+			// end default
1366
+		}
1367
+		// store our progress so far
1368
+		$this->checkout->stash_transaction_and_checkout();
1369
+		// advance to the next step! If you pass GO, collect $200
1370
+		$this->go_to_next_step();
1371
+	}
1372
+
1373
+
1374
+	/**
1375
+	 * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target
1376
+	 * @param object $target an object with the method `translate_js_strings` and `enqueue_styles_and_scripts`.
1377
+	 * @return        void
1378
+	 */
1379
+	public function add_styles_and_scripts($target)
1380
+	{
1381
+		// i18n
1382
+		$target->translate_js_strings();
1383
+		if ($this->checkout->admin_request) {
1384
+			add_action('admin_enqueue_scripts', array($target, 'enqueue_styles_and_scripts'), 10);
1385
+		} else {
1386
+			add_action('wp_enqueue_scripts', array($target, 'enqueue_styles_and_scripts'), 10);
1387
+		}
1388
+	}
1389
+
1390
+	/**
1391
+	 *        translate_js_strings
1392
+	 *
1393
+	 * @access        public
1394
+	 * @return        void
1395
+	 */
1396
+	public function translate_js_strings()
1397
+	{
1398
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1399
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1400
+		EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
1401
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1402
+			'event_espresso'
1403
+		);
1404
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = esc_html__(
1405
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1406
+			'event_espresso'
1407
+		);
1408
+		EE_Registry::$i18n_js_strings['validation_error'] = esc_html__(
1409
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1410
+			'event_espresso'
1411
+		);
1412
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
1413
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1414
+			'event_espresso'
1415
+		);
1416
+		EE_Registry::$i18n_js_strings['reg_step_error'] = esc_html__(
1417
+			'This registration step could not be completed. Please refresh the page and try again.',
1418
+			'event_espresso'
1419
+		);
1420
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = esc_html__(
1421
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1422
+			'event_espresso'
1423
+		);
1424
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1425
+			esc_html__(
1426
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1427
+				'event_espresso'
1428
+			),
1429
+			'<br/>',
1430
+			'<br/>'
1431
+		);
1432
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1433
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1434
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1435
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1436
+		EE_Registry::$i18n_js_strings['timer_years'] = esc_html__('years', 'event_espresso');
1437
+		EE_Registry::$i18n_js_strings['timer_months'] = esc_html__('months', 'event_espresso');
1438
+		EE_Registry::$i18n_js_strings['timer_weeks'] = esc_html__('weeks', 'event_espresso');
1439
+		EE_Registry::$i18n_js_strings['timer_days'] = esc_html__('days', 'event_espresso');
1440
+		EE_Registry::$i18n_js_strings['timer_hours'] = esc_html__('hours', 'event_espresso');
1441
+		EE_Registry::$i18n_js_strings['timer_minutes'] = esc_html__('minutes', 'event_espresso');
1442
+		EE_Registry::$i18n_js_strings['timer_seconds'] = esc_html__('seconds', 'event_espresso');
1443
+		EE_Registry::$i18n_js_strings['timer_year'] = esc_html__('year', 'event_espresso');
1444
+		EE_Registry::$i18n_js_strings['timer_month'] = esc_html__('month', 'event_espresso');
1445
+		EE_Registry::$i18n_js_strings['timer_week'] = esc_html__('week', 'event_espresso');
1446
+		EE_Registry::$i18n_js_strings['timer_day'] = esc_html__('day', 'event_espresso');
1447
+		EE_Registry::$i18n_js_strings['timer_hour'] = esc_html__('hour', 'event_espresso');
1448
+		EE_Registry::$i18n_js_strings['timer_minute'] = esc_html__('minute', 'event_espresso');
1449
+		EE_Registry::$i18n_js_strings['timer_second'] = esc_html__('second', 'event_espresso');
1450
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice(
1451
+		);
1452
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1453
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1454
+			true
1455
+		);
1456
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1457
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1458
+		);
1459
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1460
+			'M d, Y H:i:s',
1461
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1462
+		);
1463
+	}
1464
+
1465
+
1466
+	/**
1467
+	 *    enqueue_styles_and_scripts
1468
+	 *
1469
+	 * @access        public
1470
+	 * @return        void
1471
+	 * @throws EE_Error
1472
+	 */
1473
+	public function enqueue_styles_and_scripts()
1474
+	{
1475
+		// load css
1476
+		wp_register_style(
1477
+			'single_page_checkout',
1478
+			SPCO_CSS_URL . 'single_page_checkout.css',
1479
+			array('espresso_default'),
1480
+			EVENT_ESPRESSO_VERSION
1481
+		);
1482
+		wp_enqueue_style('single_page_checkout');
1483
+		// load JS
1484
+		wp_register_script(
1485
+			'jquery_plugin',
1486
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1487
+			array('jquery'),
1488
+			'1.0.1',
1489
+			true
1490
+		);
1491
+		wp_register_script(
1492
+			'jquery_countdown',
1493
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1494
+			array('jquery_plugin'),
1495
+			'2.1.0',
1496
+			true
1497
+		);
1498
+		wp_register_script(
1499
+			'single_page_checkout',
1500
+			SPCO_JS_URL . 'single_page_checkout.js',
1501
+			array('espresso_core', 'underscore', 'ee_form_section_validation'),
1502
+			EVENT_ESPRESSO_VERSION,
1503
+			true
1504
+		);
1505
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1506
+			$this->checkout->registration_form->enqueue_js();
1507
+		}
1508
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1509
+			$this->checkout->current_step->reg_form->enqueue_js();
1510
+		}
1511
+		wp_enqueue_script('single_page_checkout');
1512
+		if (apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)) {
1513
+			wp_enqueue_script('jquery_countdown');
1514
+		}
1515
+		/**
1516
+		 * global action hook for enqueueing styles and scripts with
1517
+		 * spco calls.
1518
+		 */
1519
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1520
+		/**
1521
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1522
+		 * The hook will end up being something like:
1523
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1524
+		 */
1525
+		do_action(
1526
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1527
+			$this
1528
+		);
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 *    display the Registration Single Page Checkout Form
1534
+	 *
1535
+	 * @access    private
1536
+	 * @return    void
1537
+	 * @throws EE_Error
1538
+	 */
1539
+	private function _display_spco_reg_form()
1540
+	{
1541
+		// if registering via the admin, just display the reg form for the current step
1542
+		if ($this->checkout->admin_request) {
1543
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1544
+		} else {
1545
+			// add powered by EE msg
1546
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1547
+			$empty_cart = count($this->checkout->transaction
1548
+									->registrations($this->checkout->reg_cache_where_params)) < 1;
1549
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1550
+			$cookies_not_set_msg = '';
1551
+			if ($empty_cart) {
1552
+				$cookies_not_set_msg = apply_filters(
1553
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1554
+					sprintf(
1555
+						esc_html__(
1556
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1557
+							'event_espresso'
1558
+						),
1559
+						'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1560
+						'</div>',
1561
+						'<h6 class="important-notice">',
1562
+						'</h6>',
1563
+						'<p>',
1564
+						'</p>',
1565
+						'<br />',
1566
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank" rel="noopener noreferrer">',
1567
+						'</a>'
1568
+					)
1569
+				);
1570
+			}
1571
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1572
+				array(
1573
+					'name'            => 'single-page-checkout',
1574
+					'html_id'         => 'ee-single-page-checkout-dv',
1575
+					'layout_strategy' =>
1576
+						new EE_Template_Layout(
1577
+							array(
1578
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1579
+								'template_args'        => array(
1580
+									'empty_cart'              => $empty_cart,
1581
+									'revisit'                 => $this->checkout->revisit,
1582
+									'reg_steps'               => $this->checkout->reg_steps,
1583
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1584
+										? $this->checkout->next_step->slug()
1585
+										: '',
1586
+									'empty_msg'               => apply_filters(
1587
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1588
+										sprintf(
1589
+											esc_html__(
1590
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1591
+												'event_espresso'
1592
+											),
1593
+											'<a href="'
1594
+											. get_post_type_archive_link('espresso_events')
1595
+											. '" title="',
1596
+											'">',
1597
+											'</a>'
1598
+										)
1599
+									),
1600
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1601
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1602
+									'session_expiration'      => gmdate(
1603
+										'M d, Y H:i:s',
1604
+										EE_Registry::instance()->SSN->expiration()
1605
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1606
+									),
1607
+								),
1608
+							)
1609
+						),
1610
+				)
1611
+			);
1612
+			// load template and add to output sent that gets filtered into the_content()
1613
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1614
+		}
1615
+	}
1616
+
1617
+
1618
+	/**
1619
+	 *    add_extra_finalize_registration_inputs
1620
+	 *
1621
+	 * @access    public
1622
+	 * @param $next_step
1623
+	 * @internal  param string $label
1624
+	 * @return void
1625
+	 */
1626
+	public function add_extra_finalize_registration_inputs($next_step)
1627
+	{
1628
+		if ($next_step === 'finalize_registration') {
1629
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1630
+		}
1631
+	}
1632
+
1633
+
1634
+	/**
1635
+	 *    display_registration_footer
1636
+	 *
1637
+	 * @access    public
1638
+	 * @return    string
1639
+	 */
1640
+	public static function display_registration_footer()
1641
+	{
1642
+		if (apply_filters(
1643
+			'FHEE__EE_Front__Controller__show_reg_footer',
1644
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1645
+		)) {
1646
+			add_filter(
1647
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1648
+				function ($url) {
1649
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1650
+				}
1651
+			);
1652
+			echo apply_filters(
1653
+				'FHEE__EE_Front_Controller__display_registration_footer',
1654
+				\EEH_Template::powered_by_event_espresso(
1655
+					'',
1656
+					'espresso-registration-footer-dv',
1657
+					array('utm_content' => 'registration_checkout')
1658
+				)
1659
+			);
1660
+		}
1661
+		return '';
1662
+	}
1663
+
1664
+
1665
+	/**
1666
+	 *    unlock_transaction
1667
+	 *
1668
+	 * @access    public
1669
+	 * @return    void
1670
+	 * @throws EE_Error
1671
+	 */
1672
+	public function unlock_transaction()
1673
+	{
1674
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1675
+			$this->checkout->transaction->unlock();
1676
+		}
1677
+	}
1678
+
1679
+
1680
+	/**
1681
+	 *        _setup_redirect
1682
+	 *
1683
+	 * @access    private
1684
+	 * @return void
1685
+	 */
1686
+	private function _setup_redirect()
1687
+	{
1688
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1689
+			$this->checkout->redirect = true;
1690
+			if (empty($this->checkout->redirect_url)) {
1691
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1692
+			}
1693
+			$this->checkout->redirect_url = apply_filters(
1694
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1695
+				$this->checkout->redirect_url,
1696
+				$this->checkout
1697
+			);
1698
+		}
1699
+	}
1700
+
1701
+
1702
+	/**
1703
+	 *   handle ajax message responses and redirects
1704
+	 *
1705
+	 * @access public
1706
+	 * @return void
1707
+	 * @throws EE_Error
1708
+	 */
1709
+	public function go_to_next_step()
1710
+	{
1711
+		if (EE_Registry::instance()->REQ->ajax) {
1712
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1713
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1714
+		}
1715
+		$this->unlock_transaction();
1716
+		// just return for these conditions
1717
+		if ($this->checkout->admin_request
1718
+			|| $this->checkout->action === 'redirect_form'
1719
+			|| $this->checkout->action === 'update_checkout'
1720
+		) {
1721
+			return;
1722
+		}
1723
+		// AJAX response
1724
+		$this->_handle_json_response();
1725
+		// redirect to next step or the Thank You page
1726
+		$this->_handle_html_redirects();
1727
+		// hmmm... must be something wrong, so let's just display the form again !
1728
+		$this->_display_spco_reg_form();
1729
+	}
1730
+
1731
+
1732
+	/**
1733
+	 *   _handle_json_response
1734
+	 *
1735
+	 * @access protected
1736
+	 * @return void
1737
+	 */
1738
+	protected function _handle_json_response()
1739
+	{
1740
+		// if this is an ajax request
1741
+		if (EE_Registry::instance()->REQ->ajax) {
1742
+			$this->checkout->json_response->set_registration_time_limit(
1743
+				$this->checkout->get_registration_time_limit()
1744
+			);
1745
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1746
+			// just send the ajax (
1747
+			$json_response = apply_filters(
1748
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1749
+				$this->checkout->json_response
1750
+			);
1751
+			echo $json_response;
1752
+			exit();
1753
+		}
1754
+	}
1755
+
1756
+
1757
+	/**
1758
+	 *   _handle_redirects
1759
+	 *
1760
+	 * @access protected
1761
+	 * @return void
1762
+	 */
1763
+	protected function _handle_html_redirects()
1764
+	{
1765
+		// going somewhere ?
1766
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1767
+			// store notices in a transient
1768
+			EE_Error::get_notices(false, true, true);
1769
+			wp_safe_redirect($this->checkout->redirect_url);
1770
+			exit();
1771
+		}
1772
+	}
1773
+
1774
+
1775
+	/**
1776
+	 *   set_checkout_anchor
1777
+	 *
1778
+	 * @access public
1779
+	 * @return void
1780
+	 */
1781
+	public function set_checkout_anchor()
1782
+	{
1783
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1784
+	}
1785
+
1786
+	/**
1787
+	 *    getRegistrationExpirationNotice
1788
+	 *
1789
+	 * @since     4.9.59.p
1790
+	 * @access    public
1791
+	 * @return    string
1792
+	 */
1793
+	public static function getRegistrationExpirationNotice()
1794
+	{
1795
+		return sprintf(
1796
+			esc_html__(
1797
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1798
+				'event_espresso'
1799
+			),
1800
+			'<h4 class="important-notice">',
1801
+			'</h4>',
1802
+			'<br />',
1803
+			'<p>',
1804
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1805
+			'">',
1806
+			'</a>',
1807
+			'</p>'
1808
+		);
1809
+	}
1810 1810
 }
Please login to merge, or discard this patch.