Completed
Branch FET-8385-datetime-ticket-selec... (cac7e5)
by
unknown
67:23 queued 43:13
created

EED_Single_Page_Checkout::run()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 8
nc 2
nop 1
dl 0
loc 11
rs 8.8571
c 0
b 0
f 0
1
<?php use EventEspresso\core\domain\services\capabilities\PublicCapabilities;
2
use EventEspresso\core\exceptions\InvalidEntityException;
3
4
if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
5
	exit( 'No direct script access allowed' );
6
}
7
8
9
10
/**
11
 * Single Page Checkout (SPCO)
12
 *
13
 * @package			Event Espresso
14
 * @subpackage		/modules/single_page_checkout/
15
 * @author				Brent Christensen
16
 *
17
 */
18
class EED_Single_Page_Checkout  extends EED_Module {
19
20
	/**
21
	 * $_initialized - has the SPCO controller already been initialized ?
22
	 * @access private
23
	 * @var bool $_initialized
24
	 */
25
	private static $_initialized = false;
26
27
28
	/**
29
	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
30
	 *
31
	 * @access private
32
	 * @var bool $_valid_checkout
33
	 */
34
	private static $_checkout_verified = true;
35
36
	/**
37
	 * 	$_reg_steps_array - holds initial array of reg steps
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
	 * 	@access public
46
	 *	@var EE_Checkout $checkout
47
	 */
48
	public $checkout;
49
50
51
52
53
	/**
54
	 * @return EED_Single_Page_Checkout
55
	 */
56
	public static function instance() {
57
		add_filter( 'EED_Single_Page_Checkout__SPCO_active', '__return_true' );
58
		return parent::get_instance( __CLASS__ );
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (get_instance() instead of instance()). Are you sure this is correct? If so, you might want to change this to $this->get_instance().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
59
	}
60
61
62
63
	/**
64
	 * @return EE_CART
65
	 */
66
	public function cart() {
67
		return $this->checkout->cart;
68
	}
69
70
71
72
	/**
73
	 * @return EE_Transaction
74
	 */
75
	public function transaction() {
76
		return $this->checkout->transaction;
77
	}
78
79
80
81
	/**
82
	 *    set_hooks - for hooking into EE Core, other modules, etc
83
	 *
84
	 * @access    public
85
	 * @return    void
86
	 * @throws \EE_Error
87
	 */
88
	public static function set_hooks() {
89
		EED_Single_Page_Checkout::set_definitions();
90
	}
91
92
93
94
	/**
95
	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
96
	 *
97
	 * @access    public
98
	 * @return    void
99
	 * @throws \EE_Error
100
	 */
101
	public static function set_hooks_admin() {
102
		EED_Single_Page_Checkout::set_definitions();
103
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
104
			// going to start an output buffer in case anything gets accidentally output that might disrupt our JSON response
105
			ob_start();
106
			EED_Single_Page_Checkout::load_request_handler();
107
			EED_Single_Page_Checkout::load_reg_steps();
108
		} else {
109
			// hook into the top of pre_get_posts to set the reg step routing, which gives other modules or plugins a chance to modify the reg steps, but just before the routes get called
110
			add_action( 'pre_get_posts', array( 'EED_Single_Page_Checkout', 'load_reg_steps' ), 1 );
111
		}
112
		// set ajax hooks
113
		add_action( 'wp_ajax_process_reg_step', array( 'EED_Single_Page_Checkout', 'process_reg_step' ));
114
		add_action( 'wp_ajax_nopriv_process_reg_step', array( 'EED_Single_Page_Checkout', 'process_reg_step' ));
115
		add_action( 'wp_ajax_display_spco_reg_step', array( 'EED_Single_Page_Checkout', 'display_reg_step' ));
116
		add_action( 'wp_ajax_nopriv_display_spco_reg_step', array( 'EED_Single_Page_Checkout', 'display_reg_step' ));
117
		add_action( 'wp_ajax_update_reg_step', array( 'EED_Single_Page_Checkout', 'update_reg_step' ));
118
		add_action( 'wp_ajax_nopriv_update_reg_step', array( 'EED_Single_Page_Checkout', 'update_reg_step' ));
119
	}
120
121
122
123
	/**
124
	 *    process ajax request
125
	 *
126
	 * @param string $ajax_action
127
	 * @throws \EE_Error
128
	 */
129
	public static function process_ajax_request( $ajax_action ) {
130
		EE_Registry::instance()->REQ->set( 'action', $ajax_action );
131
		EED_Single_Page_Checkout::instance()->_initialize();
132
	}
133
134
135
136
	/**
137
	 *    ajax display registration step
138
	 *
139
	 * @throws \EE_Error
140
	 */
141
	public static function display_reg_step() {
142
		EED_Single_Page_Checkout::process_ajax_request( 'display_spco_reg_step' );
143
	}
144
145
146
147
	/**
148
	 *    ajax process registration step
149
	 *
150
	 * @throws \EE_Error
151
	 */
152
	public static function process_reg_step() {
153
		EED_Single_Page_Checkout::process_ajax_request( 'process_reg_step' );
154
	}
155
156
157
158
	/**
159
	 *    ajax process registration step
160
	 *
161
	 * @throws \EE_Error
162
	 */
163
	public static function update_reg_step() {
164
		EED_Single_Page_Checkout::process_ajax_request( 'update_reg_step' );
165
	}
166
167
168
169
	/**
170
	 *   update_checkout
171
	 *
172
	 * @access public
173
	 * @return void
174
	 * @throws \EE_Error
175
	 */
176
	public static function update_checkout() {
177
		EED_Single_Page_Checkout::process_ajax_request( 'update_checkout' );
178
	}
179
180
181
182
	/**
183
	 *    load_request_handler
184
	 *
185
	 * @access    public
186
	 * @return    void
187
	 */
188
	public static function load_request_handler() {
189
		// load core Request_Handler class
190
		if ( ! isset( EE_Registry::instance()->REQ )) {
191
			EE_Registry::instance()->load_core( 'Request_Handler' );
192
		}
193
	}
194
195
196
197
	/**
198
	 *    set_definitions
199
	 *
200
	 * @access    public
201
	 * @return    void
202
	 * @throws \EE_Error
203
	 */
204
	public static function set_definitions() {
205
		define( 'SPCO_BASE_PATH', rtrim( str_replace( array( '\\', '/' ), DS, plugin_dir_path( __FILE__ )), DS ) . DS );
206
		define( 'SPCO_CSS_URL', plugin_dir_url( __FILE__ ) . 'css' . DS );
207
		define( 'SPCO_IMG_URL', plugin_dir_url( __FILE__ ) . 'img' . DS );
208
		define( 'SPCO_JS_URL', plugin_dir_url( __FILE__ ) . 'js' . DS );
209
		define( 'SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS );
210
		define( 'SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS );
211
		define( 'SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS );
212
		EEH_Autoloader::register_autoloaders_for_each_file_in_folder( SPCO_BASE_PATH, TRUE );
213
	}
214
215
216
217
	/**
218
	 * load_reg_steps
219
	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
220
	 *
221
	 * @access    private
222
	 * @throws EE_Error
223
	 * @return void
224
	 */
225
	public static function load_reg_steps() {
226
		static $reg_steps_loaded = FALSE;
227
		if ( $reg_steps_loaded ) {
228
			return;
229
		}
230
		// filter list of reg_steps
231
		$reg_steps_to_load = apply_filters(
232
			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
233
			EED_Single_Page_Checkout::get_reg_steps()
234
		);
235
		// sort by key (order)
236
		ksort( $reg_steps_to_load );
237
		// loop through folders
238
		foreach ( $reg_steps_to_load as $order => $reg_step ) {
239
			// we need a
240
			if ( isset( $reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'] )) {
241
				// copy over to the reg_steps_array
242
				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
243
				// register custom key route for each reg step
244
				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
245
				EE_Config::register_route( $reg_step['slug'], 'EED_Single_Page_Checkout', 'run', 'step' );
246
				// add AJAX or other hooks
247
				if ( isset( $reg_step['has_hooks'] ) && $reg_step['has_hooks'] ) {
248
					// setup autoloaders if necessary
249
					if ( ! class_exists( $reg_step['class_name'] )) {
250
						EEH_Autoloader::register_autoloaders_for_each_file_in_folder( $reg_step['file_path'], TRUE );
251
					}
252
					if ( is_callable( $reg_step['class_name'], 'set_hooks' )) {
253
						call_user_func( array( $reg_step['class_name'], 'set_hooks' ));
254
					}
255
				}
256
			}
257
		}
258
259
		$reg_steps_loaded = TRUE;
260
	}
261
262
263
264
	/**
265
	 *    get_reg_steps
266
	 *
267
	 * @access 	public
268
	 * @return 	array
269
	 */
270
	public static function get_reg_steps() {
271
		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
272
		if ( empty( $reg_steps )) {
273
			$reg_steps = array(
274
				10 => array(
275
					'file_path' => SPCO_REG_STEPS_PATH . 'attendee_information',
276
					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
277
					'slug' => 'attendee_information',
278
					'has_hooks' => FALSE
279
				),
280
				20 => array(
281
					'file_path' => SPCO_REG_STEPS_PATH . 'registration_confirmation',
282
					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
283
					'slug' => 'registration_confirmation',
284
					'has_hooks' => FALSE
285
				),
286
				30 => array(
287
					'file_path' => SPCO_REG_STEPS_PATH . 'payment_options',
288
					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
289
					'slug' => 'payment_options',
290
					'has_hooks' => TRUE
291
				),
292
				999 => array(
293
					'file_path' => SPCO_REG_STEPS_PATH . 'finalize_registration',
294
					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
295
					'slug' => 'finalize_registration',
296
					'has_hooks' => FALSE
297
				)
298
			);
299
		}
300
		return $reg_steps;
301
	}
302
303
304
305
	/**
306
	 *    registration_checkout_for_admin
307
	 *
308
	 * @access    public
309
	 * @return    string
310
	 * @throws \EE_Error
311
	 */
312
	public static function registration_checkout_for_admin() {
313
		EED_Single_Page_Checkout::load_reg_steps();
314
		EE_Registry::instance()->REQ->set( 'step', 'attendee_information' );
315
		EE_Registry::instance()->REQ->set( 'action', 'display_spco_reg_step' );
316
		EE_Registry::instance()->REQ->set( 'process_form_submission', false );
317
		EED_Single_Page_Checkout::instance()->_initialize();
318
		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
319
		return EE_Registry::instance()->REQ->get_output();
320
	}
321
322
323
324
	/**
325
     * process_registration_from_admin
326
     *
327
     * @access public
328
	 * @return \EE_Transaction
329
	 * @throws \EE_Error
330
	 */
331
	public static function process_registration_from_admin() {
332
		EED_Single_Page_Checkout::load_reg_steps();
333
		EE_Registry::instance()->REQ->set( 'step', 'attendee_information' );
334
		EE_Registry::instance()->REQ->set( 'action', 'process_reg_step' );
335
		EE_Registry::instance()->REQ->set( 'process_form_submission', true );
336
		EED_Single_Page_Checkout::instance()->_initialize();
337
		if ( EED_Single_Page_Checkout::instance()->checkout->current_step->completed() ) {
338
			$final_reg_step = end( EED_Single_Page_Checkout::instance()->checkout->reg_steps );
339
			if ( $final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration ) {
340
				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated( $final_reg_step );
341
				if ( $final_reg_step->process_reg_step() ) {
342
					$final_reg_step->set_completed();
343
					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
344
					return EED_Single_Page_Checkout::instance()->checkout->transaction;
345
				}
346
			}
347
		}
348
		return null;
349
	}
350
351
352
353
	/**
354
	 *    run
355
	 *
356
	 * @access    public
357
	 * @param WP_Query $WP_Query
358
	 * @return    void
359
	 * @throws \EE_Error
360
	 */
361
	public function run( $WP_Query ) {
362
		if (
363
			$WP_Query instanceof WP_Query
0 ignored issues
show
Bug introduced by
The class WP_Query does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
364
			&& $WP_Query->is_main_query()
365
			&& apply_filters( 'FHEE__EED_Single_Page_Checkout__run', true )
366
			&& isset( $WP_Query->query['pagename'] )
367
			&& strpos( EE_Config::instance()->core->reg_page_url(), $WP_Query->query['pagename'] ) !== false
368
		) {
369
			$this->_initialize();
370
		}
371
	}
372
373
374
375
	/**
376
	 *    run
377
	 *
378
	 * @access    public
379
	 * @param WP_Query $WP_Query
380
	 * @return    void
381
	 * @throws \EE_Error
382
	 */
383
	public static function init( $WP_Query ) {
384
		EED_Single_Page_Checkout::instance()->run( $WP_Query );
385
	}
386
387
388
389
	/**
390
	 *    _initialize - initial module setup
391
	 *
392
	 * @access    private
393
	 * @throws EE_Error
394
	 * @return    void
395
	 */
396
	private function _initialize() {
397
		// ensure SPCO doesn't run twice
398
		if ( EED_Single_Page_Checkout::$_initialized ) {
399
			return;
400
		}
401
		try {
402
			// setup the EE_Checkout object
403
			$this->checkout = $this->_initialize_checkout();
404
			// filter checkout
405
			$this->checkout = apply_filters( 'FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout );
406
			// get the $_GET
407
			$this->_get_request_vars();
408
			$this->_block_bots();
409
			// filter continue_reg
410
			$this->checkout->continue_reg = apply_filters( 'FHEE__EED_Single_Page_Checkout__init___continue_reg', TRUE, $this->checkout );
411
			// load the reg steps array
412
			if ( ! $this->_load_and_instantiate_reg_steps() ) {
413
				EED_Single_Page_Checkout::$_initialized = true;
414
				return;
415
			}
416
			// set the current step
417
			$this->checkout->set_current_step( $this->checkout->step );
418
			// and the next step
419
			$this->checkout->set_next_step();
420
			// was there already a valid transaction in the checkout from the session ?
421
			if ( ! $this->checkout->transaction instanceof EE_Transaction ) {
422
				// get transaction from db or session
423
				$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
424
					? $this->_get_transaction_and_cart_for_previous_visit()
425
					: $this->_get_cart_for_current_session_and_setup_new_transaction();
426
				if ( ! $this->checkout->transaction instanceof EE_Transaction ) {
427
					// add some style and make it dance
428
					$this->checkout->transaction = EE_Transaction::new_instance();
429
					$this->add_styles_and_scripts();
430
					EED_Single_Page_Checkout::$_initialized = true;
431
					return;
432
				}
433
				// and the registrations for the transaction
434
				$this->_get_registrations( $this->checkout->transaction );
435
			}
436
			// verify that everything has been setup correctly
437
			if ( ! $this->_final_verifications() ) {
438
				EED_Single_Page_Checkout::$_initialized = true;
439
				return;
440
			}
441
			// lock the transaction
442
			$this->checkout->transaction->lock();
443
			// make sure all of our cached objects are added to their respective model entity mappers
444
			$this->checkout->refresh_all_entities();
445
			// set amount owing
446
			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
447
			// initialize each reg step, which gives them the chance to potentially alter the process
448
			$this->_initialize_reg_steps();
449
			// DEBUG LOG
450
			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
451
			// get reg form
452
			$this->_check_form_submission();
453
			// checkout the action!!!
454
			$this->_process_form_action();
455
			// add some style and make it dance
456
			$this->add_styles_and_scripts();
457
			// kk... SPCO has successfully run
458
			EED_Single_Page_Checkout::$_initialized = TRUE;
459
			// set no cache headers and constants
460
			EE_System::do_not_cache();
461
			// add anchor
462
			add_action( 'loop_start', array( $this, 'set_checkout_anchor' ), 1 );
463
		} catch ( Exception $e ) {
464
			EE_Error::add_error( $e->getMessage(), __FILE__, __FUNCTION__, __LINE__ );
465
		}
466
	}
467
468
469
470
	/**
471
	 *    _initialize_checkout
472
	 * loads and instantiates EE_Checkout
473
	 *
474
	 * @access    private
475
	 * @throws EE_Error
476
	 * @return EE_Checkout
477
	 */
478
	private function _initialize_checkout() {
479
		// look in session for existing checkout
480
		$checkout = EE_Registry::instance()->SSN->checkout();
481
		// verify
482
		if ( ! $checkout instanceof EE_Checkout ) {
483
			// instantiate EE_Checkout object for handling the properties of the current checkout process
484
			$checkout = EE_Registry::instance()->load_file( SPCO_INC_PATH, 'EE_Checkout', 'class', array(), FALSE  );
485
		} else {
486
			if ( $checkout->current_step->is_final_step() && $checkout->exit_spco() === true )  {
487
				$this->unlock_transaction();
488
				wp_safe_redirect( $checkout->redirect_url );
489
				exit();
490
			}
491
		}
492
		$checkout = apply_filters( 'FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout );
493
		// verify again
494
		if ( ! $checkout instanceof EE_Checkout ) {
495
			throw new EE_Error( __( 'The EE_Checkout class could not be loaded.', 'event_espresso' ) );
496
		}
497
		// reset anything that needs a clean slate for each request
498
		$checkout->reset_for_current_request();
499
		return $checkout;
500
	}
501
502
503
504
	/**
505
	 *    _get_request_vars
506
	 *
507
	 * @access    private
508
	 * @return    void
509
	 * @throws \EE_Error
510
	 */
511
	private function _get_request_vars() {
512
		// load classes
513
		EED_Single_Page_Checkout::load_request_handler();
514
		//make sure this request is marked as belonging to EE
515
		EE_Registry::instance()->REQ->set_espresso_page( TRUE );
516
		// which step is being requested ?
517
		$this->checkout->step = EE_Registry::instance()->REQ->get( 'step', $this->_get_first_step() );
518
		// which step is being edited ?
519
		$this->checkout->edit_step = EE_Registry::instance()->REQ->get( 'edit_step', '' );
520
		// and what we're doing on the current step
521
		$this->checkout->action = EE_Registry::instance()->REQ->get( 'action', 'display_spco_reg_step' );
522
		// timestamp
523
		$this->checkout->uts = EE_Registry::instance()->REQ->get( 'uts', 0 );
524
		// returning to edit ?
525
		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get( 'e_reg_url_link', '' );
526
		// or some other kind of revisit ?
527
		$this->checkout->revisit = EE_Registry::instance()->REQ->get( 'revisit', FALSE );
528
		// and whether or not to generate a reg form for this request
529
		$this->checkout->generate_reg_form = EE_Registry::instance()->REQ->get( 'generate_reg_form', TRUE ); 		// TRUE 	FALSE
530
		// and whether or not to process a reg form submission for this request
531
		$this->checkout->process_form_submission = EE_Registry::instance()->REQ->get( 'process_form_submission', FALSE ); 		// TRUE 	FALSE
532
		$this->checkout->process_form_submission = $this->checkout->action !== 'display_spco_reg_step'
533
			? $this->checkout->process_form_submission
534
			: FALSE; 		// TRUE 	FALSE
535
		// $this->_display_request_vars();
536
	}
537
538
539
540
	/**
541
	 *  _display_request_vars
542
	 *
543
	 * @access    protected
544
	 * @return    void
545
	 */
546
	protected function _display_request_vars() {
547
		if ( ! WP_DEBUG ) {
548
			return;
549
		}
550
		EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
551
		EEH_Debug_Tools::printr( $this->checkout->step, '$this->checkout->step', __FILE__, __LINE__ );
552
		EEH_Debug_Tools::printr( $this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__ );
553
		EEH_Debug_Tools::printr( $this->checkout->action, '$this->checkout->action', __FILE__, __LINE__ );
554
		EEH_Debug_Tools::printr( $this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__ );
555
		EEH_Debug_Tools::printr( $this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__ );
556
		EEH_Debug_Tools::printr( $this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__ );
557
		EEH_Debug_Tools::printr( $this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__ );
558
	}
559
560
561
562
	/**
563
	 * _block_bots
564
	 * checks that the incoming request has either of the following set:
565
	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
566
	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
567
	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
568
	 * then where you coming from man?
569
	 */
570
	private function _block_bots() {
571
		$invalid_checkout_access = \EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
572
		if ( $invalid_checkout_access->checkoutAccessIsInvalid( $this->checkout ) ) {
573
			$this->_handle_html_redirects();
574
		}
575
	}
576
577
578
579
	/**
580
	 *    _get_first_step
581
	 *  gets slug for first step in $_reg_steps_array
582
	 *
583
	 * @access    private
584
	 * @throws EE_Error
585
	 * @return    array
586
	 */
587
	private function _get_first_step() {
588
		$first_step = reset( EED_Single_Page_Checkout::$_reg_steps_array );
589
		return isset( $first_step['slug'] ) ? $first_step['slug'] : 'attendee_information';
590
	}
591
592
593
594
	/**
595
	 *    _load_and_instantiate_reg_steps
596
	 *  instantiates each reg step based on the loaded reg_steps array
597
	 *
598
	 * @access    private
599
	 * @throws EE_Error
600
	 * @return    bool
601
	 */
602
	private function _load_and_instantiate_reg_steps() {
603
		// have reg_steps already been instantiated ?
604
		if (
605
			empty( $this->checkout->reg_steps ) ||
606
			apply_filters( 'FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout )
607
		) {
608
			// if not, then loop through raw reg steps array
609
			foreach ( EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step ) {
610
				if ( ! $this->_load_and_instantiate_reg_step( $reg_step, $order )) {
611
					return false;
612
				}
613
			}
614
			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = TRUE;
615
			EE_Registry::instance()->CFG->registration->reg_confirmation_last = TRUE;
616
			// skip the registration_confirmation page ?
617
			if ( EE_Registry::instance()->CFG->registration->skip_reg_confirmation ) {
618
				// just remove it from the reg steps array
619
				$this->checkout->remove_reg_step( 'registration_confirmation', false );
620
			} else if (
621
				isset( $this->checkout->reg_steps['registration_confirmation'] )
622
				&& EE_Registry::instance()->CFG->registration->reg_confirmation_last
623
			) {
624
				// set the order to something big like 100
625
				$this->checkout->set_reg_step_order( 'registration_confirmation', 100 );
626
			}
627
			// filter the array for good luck
628
			$this->checkout->reg_steps = apply_filters(
629
				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
630
				$this->checkout->reg_steps
631
			);
632
			// finally re-sort based on the reg step class order properties
633
			$this->checkout->sort_reg_steps();
634
		} else {
635
			foreach ( $this->checkout->reg_steps as $reg_step ) {
636
				// set all current step stati to FALSE
637
				$reg_step->set_is_current_step( FALSE );
638
			}
639
		}
640
		if ( empty( $this->checkout->reg_steps )) {
641
			EE_Error::add_error( __( 'No Reg Steps were loaded..', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__);
642
			return false;
643
		}
644
			// make reg step details available to JS
645
		$this->checkout->set_reg_step_JSON_info();
646
		return true;
647
	}
648
649
650
651
	/**
652
	 *     _load_and_instantiate_reg_step
653
	 *
654
	 * @access    private
655
	 * @param array $reg_step
656
	 * @param int   $order
657
	 * @return bool
658
	 */
659
	private function _load_and_instantiate_reg_step( $reg_step = array(), $order = 0 ) {
660
661
		// we need a file_path, class_name, and slug to add a reg step
662
		if ( isset( $reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'] )) {
663
			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
664
			if (
665
				$this->checkout->reg_url_link
666
				&& $this->checkout->step !== $reg_step['slug']
667
				&& $reg_step['slug'] !== 'finalize_registration'
668
			) {
669
				return true;
670
			}
671
			// instantiate step class using file path and class name
672
			$reg_step_obj = EE_Registry::instance()->load_file(
673
				$reg_step['file_path'],
674
				$reg_step['class_name'],
675
				'class',
676
				$this->checkout,
677
				FALSE
678
			);
679
			// did we gets the goods ?
680 View Code Duplication
			if ( $reg_step_obj instanceof EE_SPCO_Reg_Step ) {
681
				// set reg step order based on config
682
				$reg_step_obj->set_order( $order );
683
				// add instantiated reg step object to the master reg steps array
684
				$this->checkout->add_reg_step( $reg_step_obj );
685
			} else {
686
				EE_Error::add_error(
687
					__( 'The current step could not be set.', 'event_espresso' ),
688
					__FILE__, __FUNCTION__, __LINE__
689
				);
690
				return false;
691
			}
692
		} else {
693
			if ( WP_DEBUG ) {
694
				EE_Error::add_error(
695
					sprintf(
696
						__( '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', 'event_espresso' ),
697
						isset( $reg_step['file_path'] ) ? $reg_step['file_path'] : '',
698
						isset( $reg_step['class_name'] ) ? $reg_step['class_name'] : '',
699
						isset( $reg_step['slug'] ) ? $reg_step['slug'] : '',
700
						'<ul>',
701
						'<li>',
702
						'</li>',
703
						'</ul>'
704
					),
705
					__FILE__, __FUNCTION__, __LINE__
706
				);
707
			}
708
			return false;
709
		}
710
		return true;
711
	}
712
713
714
715
	/**
716
	 * _get_transaction_and_cart_for_previous_visit
717
	 *
718
	 * @access private
719
	 * 	@return mixed EE_Transaction|NULL
720
	 */
721
	private function _get_transaction_and_cart_for_previous_visit() {
722
		/** @var $TXN_model EEM_Transaction */
723
		$TXN_model = EE_Registry::instance()->load_model( 'Transaction' );
724
		// because the reg_url_link is present in the request, this is a return visit to SPCO, so we'll get the transaction data from the db
725
		$transaction = $TXN_model->get_transaction_from_reg_url_link( $this->checkout->reg_url_link );
726
		// verify transaction
727 View Code Duplication
		if ( $transaction instanceof EE_Transaction ) {
728
			// and get the cart that was used for that transaction
729
			$this->checkout->cart = $this->_get_cart_for_transaction( $transaction );
730
			return $transaction;
731
		} else {
732
			EE_Error::add_error( __( 'Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__);
733
			return NULL;
734
		}
735
	}
736
737
738
739
	/**
740
	 * _get_cart_for_transaction
741
	 *
742
	 * @access private
743
	 * @param EE_Transaction $transaction
744
	 * @return EE_Cart
745
	 */
746
	private function _get_cart_for_transaction( $transaction ) {
747
		return $this->checkout->get_cart_for_transaction( $transaction );
748
	}
749
750
751
752
	/**
753
	 * get_cart_for_transaction
754
	 *
755
	 * @access public
756
	 * @param EE_Transaction $transaction
757
	 * @return EE_Cart
758
	 */
759
	public function get_cart_for_transaction( EE_Transaction $transaction ) {
760
		return $this->checkout->get_cart_for_transaction( $transaction );
761
	}
762
763
764
765
	/**
766
	 * _get_transaction_and_cart_for_current_session
767
	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
768
	 *
769
	 * @access private
770
	 * @return EE_Transaction
771
	 * @throws \EE_Error
772
	 */
773
	private function _get_cart_for_current_session_and_setup_new_transaction() {
774
		//  if there's no transaction, then this is the FIRST visit to SPCO
775
		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
776
		$this->checkout->cart = $this->_get_cart_for_transaction( NULL );
0 ignored issues
show
Documentation introduced by
NULL is of type null, but the function expects a object<EE_Transaction>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
777
		// and then create a new transaction
778
		$transaction = $this->_initialize_transaction();
779
		// verify transaction
780
		if ( $transaction instanceof EE_Transaction ) {
781
			// save it so that we have an ID for other objects to use
782
			$transaction->save();
783
			// and save TXN data to the cart
784
			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn( $transaction->ID() );
785
		} else {
786
			EE_Error::add_error( __( 'A Valid Transaction could not be initialized.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
787
		}
788
		return $transaction;
789
	}
790
791
792
793
	/**
794
	 * 	generates a new EE_Transaction object and adds it to the $_transaction property.
795
	 *
796
	 * 	@access private
797
	 * 	@return mixed EE_Transaction|NULL
798
	 */
799
	private function _initialize_transaction() {
800
		try {
801
			// ensure cart totals have been calculated
802
			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
803
			// grab the cart grand total
804
			$cart_total = $this->checkout->cart->get_cart_grand_total();
805
			// create new TXN
806
			return EE_Transaction::new_instance(
807
				array(
808
					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
809
					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
810
					'TXN_paid'      => 0,
811
					'STS_ID'        => EEM_Transaction::failed_status_code,
812
				)
813
			);
814
		} catch( Exception $e ) {
815
			EE_Error::add_error( $e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
816
		}
817
		return NULL;
818
	}
819
820
821
822
    /**
823
     * _get_registrations
824
     *
825
     * @access private
826
     * @param EE_Transaction $transaction
827
     * @return void
828
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
829
     * @throws \EE_Error
830
     */
831
	private function _get_registrations( EE_Transaction $transaction ) {
832
		// first step: grab the registrants  { : o
833
		$registrations = $transaction->registrations( $this->checkout->reg_cache_where_params, true );
834
		// verify registrations have been set
835
		if ( empty( $registrations )) {
836
			// if no cached registrations, then check the db
837
			$registrations = $transaction->registrations( $this->checkout->reg_cache_where_params, false );
838
			// still nothing ? well as long as this isn't a revisit
839
			if ( empty( $registrations ) && ! $this->checkout->revisit ) {
840
				// generate new registrations from scratch
841
				$registrations = $this->_initialize_registrations( $transaction );
842
			}
843
		}
844
		// sort by their original registration order
845
		usort( $registrations, array( 'EED_Single_Page_Checkout', 'sort_registrations_by_REG_count' ));
846
		// then loop thru the array
847
		foreach ( $registrations as $registration ) {
848
			// verify each registration
849
			if ( $registration instanceof EE_Registration ) {
850
				// we display all attendee info for the primary registrant
851
				if ( $this->checkout->reg_url_link === $registration->reg_url_link()
852
				     && $registration->is_primary_registrant()
853
				) {
854
					$this->checkout->primary_revisit = true;
855
					break;
856
				} else if ( $this->checkout->revisit
857
				            && $this->checkout->reg_url_link !== $registration->reg_url_link()
858
				) {
859
					// but hide info if it doesn't belong to you
860
					$transaction->clear_cache( 'Registration', $registration->ID() );
861
				}
862
				$this->checkout->set_reg_status_updated( $registration->ID(), false );
863
			}
864
		}
865
	}
866
867
868
869
    /**
870
     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
871
     *
872
     * @access private
873
     * @param EE_Transaction $transaction
874
     * @return    array
875
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
876
     * @throws \EE_Error
877
     */
878
	private function _initialize_registrations( EE_Transaction $transaction ) {
879
		$att_nmbr = 0;
880
		$registrations = array();
881
		if ( $transaction instanceof EE_Transaction ) {
882
			/** @type EE_Registration_Processor $registration_processor */
883
			$registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' );
884
			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
885
			// now let's add the cart items to the $transaction
886
			foreach ( $this->checkout->cart->get_tickets() as $line_item ) {
887
				//do the following for each ticket of this type they selected
888
				for ( $x = 1; $x <= $line_item->quantity(); $x++ ) {
889
					$att_nmbr++;
890
                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
891
                    $CreateRegistrationCommand = EE_Registry::instance()
892
                        ->create(
893
                           'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
894
                           array(
895
	                           $transaction,
896
	                           $line_item,
897
	                           $att_nmbr,
898
	                           $this->checkout->total_ticket_count
899
                           )
900
                        );
901
                    // override capabilities for frontend registrations
902
                    if ( ! is_admin()) {
903
                        $CreateRegistrationCommand->setCapCheck(
904
	                        new PublicCapabilities( '', 'create_new_registration' )
905
                        );
906
                    }
907
					$registration = EE_Registry::instance()->BUS->execute( $CreateRegistrationCommand );
908
					if ( ! $registration instanceof EE_Registration ) {
909
						throw new InvalidEntityException( $registration, 'EE_Registration' );
910
					}
911
					$registrations[ $registration->ID() ] = $registration;
912
				}
913
			}
914
			$registration_processor->fix_reg_final_price_rounding_issue( $transaction );
915
		}
916
		return $registrations;
917
	}
918
919
920
921
	/**
922
	 * sorts registrations by REG_count
923
	 *
924
	 * @access public
925
	 * @param EE_Registration $reg_A
926
	 * @param EE_Registration $reg_B
927
	 * @return int
928
	 */
929
	public static function sort_registrations_by_REG_count( EE_Registration $reg_A, EE_Registration $reg_B ) {
930
		// this shouldn't ever happen within the same TXN, but oh well
931
		if ( $reg_A->count() === $reg_B->count() ) {
932
			return 0;
933
		}
934
		return ( $reg_A->count() > $reg_B->count() ) ? 1 : -1;
935
	}
936
937
938
939
	/**
940
	 *    _final_verifications
941
	 * just makes sure that everything is set up correctly before proceeding
942
	 *
943
	 * @access    private
944
	 * @return    bool
945
	 * @throws \EE_Error
946
	 */
947
	private function _final_verifications() {
948
		// filter checkout
949
		$this->checkout = apply_filters( 'FHEE__EED_Single_Page_Checkout___final_verifications__checkout', $this->checkout );
950
		//verify that current step is still set correctly
951
		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step ) {
952
			EE_Error::add_error( __( '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.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
953
			return false;
954
		}
955
		// if returning to SPCO, then verify that primary registrant is set
956
		if ( ! empty( $this->checkout->reg_url_link )) {
957
			$valid_registrant = $this->checkout->transaction->primary_registration();
958
			if ( ! $valid_registrant instanceof EE_Registration ) {
959
				EE_Error::add_error( __( '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.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
960
				return false;
961
			}
962
			$valid_registrant = null;
963
			foreach ( $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params ) as $registration ) {
964
				if (
965
					$registration instanceof EE_Registration
966
					&& $registration->reg_url_link() === $this->checkout->reg_url_link
967
				) {
968
					$valid_registrant = $registration;
969
				}
970
			}
971
			if ( ! $valid_registrant instanceof EE_Registration ) {
972
				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
973
				if ( EED_Single_Page_Checkout::$_checkout_verified ) {
974
					// clear the session, mark the checkout as unverified, and try again
975
					EE_Registry::instance()->SSN->clear_session();
976
					EED_Single_Page_Checkout::$_initialized = false;
977
					EED_Single_Page_Checkout::$_checkout_verified = false;
978
					$this->_initialize();
979
					EE_Error::reset_notices();
980
					return false;
981
				}
982
				EE_Error::add_error( __( '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.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
983
				return false;
984
			}
985
		}
986
		// now that things have been kinda sufficiently verified,
987
		// let's add the checkout to the session so that's available other systems
988
		EE_Registry::instance()->SSN->set_checkout( $this->checkout );
989
		return true;
990
	}
991
992
993
994
	/**
995
	 *    _initialize_reg_steps
996
	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
997
	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
998
	 *
999
	 * @access    private
1000
	 * @param bool $reinitializing
1001
	 * @throws \EE_Error
1002
	 */
1003
	private function _initialize_reg_steps( $reinitializing = false ) {
1004
		$this->checkout->set_reg_step_initiated( $this->checkout->current_step );
1005
		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1006
		foreach ( $this->checkout->reg_steps as $reg_step ) {
1007
			if ( ! $reg_step->initialize_reg_step() ) {
1008
				// if not initialized then maybe this step is being removed...
1009
				if ( ! $reinitializing && $reg_step->is_current_step() ) {
1010
					// if it was the current step, then we need to start over here
1011
					$this->_initialize_reg_steps( true );
1012
					return;
1013
				}
1014
				continue;
1015
			}
1016
			// add css and JS for current step
1017
			$reg_step->enqueue_styles_and_scripts();
1018
			// i18n
1019
			$reg_step->translate_js_strings();
1020
			if ( $reg_step->is_current_step() ) {
1021
				// the text that appears on the reg step form submit button
1022
				$reg_step->set_submit_button_text();
1023
			}
1024
		}
1025
		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1026
		do_action( "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}", $this->checkout->current_step );
1027
	}
1028
1029
1030
1031
	/**
1032
	 * _check_form_submission
1033
	 *
1034
	 * @access private
1035
	 * 	@return void
1036
	 */
1037
	private function _check_form_submission() {
1038
		//does this request require the reg form to be generated ?
1039
		if ( $this->checkout->generate_reg_form ) {
1040
			// ever heard that song by Blue Rodeo ?
1041
			try {
1042
				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->checkout->current...ep->generate_reg_form() of type string is incompatible with the declared type object<EE_Form_Section_Proper> of property $reg_form.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1043
				// if not displaying a form, then check for form submission
1044
				if ( $this->checkout->process_form_submission && $this->checkout->current_step->reg_form->was_submitted() ) {
0 ignored issues
show
Bug introduced by
The method was_submitted cannot be called on $this->checkout->current_step->reg_form (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1045
					// clear out any old data in case this step is being run again
1046
					$this->checkout->current_step->set_valid_data( array() );
1047
					// capture submitted form data
1048
					$this->checkout->current_step->reg_form->receive_form_submission(
0 ignored issues
show
Bug introduced by
The method receive_form_submission cannot be called on $this->checkout->current_step->reg_form (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1049
						apply_filters( 'FHEE__Single_Page_Checkout___check_form_submission__request_params', EE_Registry::instance()->REQ->params(), $this->checkout )
1050
					);
1051
					// validate submitted form data
1052
					if ( ! $this->checkout->continue_reg && ! $this->checkout->current_step->reg_form->is_valid() ) {
0 ignored issues
show
Bug introduced by
The method is_valid cannot be called on $this->checkout->current_step->reg_form (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1053
						// thou shall not pass !!!
1054
						$this->checkout->continue_reg = FALSE;
1055
						// any form validation errors?
1056
						if ( $this->checkout->current_step->reg_form->submission_error_message() !== '' ) {
0 ignored issues
show
Bug introduced by
The method submission_error_message cannot be called on $this->checkout->current_step->reg_form (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1057
							$submission_error_messages = array();
1058
							// bad, bad, bad registrant
1059
							foreach( $this->checkout->current_step->reg_form->get_validation_errors_accumulated() as $validation_error ){
0 ignored issues
show
Bug introduced by
The method get_validation_errors_accumulated cannot be called on $this->checkout->current_step->reg_form (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1060 View Code Duplication
								if ( $validation_error instanceof EE_Validation_Error ) {
1061
									$submission_error_messages[] = sprintf(
1062
										__( '%s : %s', 'event_espresso' ),
1063
										$validation_error->get_form_section()->html_label_text(),
1064
										$validation_error->getMessage()
1065
									);
1066
								}
1067
							}
1068
							EE_Error::add_error( implode( '<br />', $submission_error_messages ), __FILE__, __FUNCTION__, __LINE__ );
1069
						}
1070
						// well not really... what will happen is we'll just get redirected back to redo the current step
1071
						$this->go_to_next_step();
1072
						return;
1073
					}
1074
				}
1075
			} catch( EE_Error $e ) {
1076
				$e->get_error();
1077
			}
1078
		}
1079
	}
1080
1081
1082
1083
	/**
1084
	 * _process_action
1085
	 *
1086
	 * @access private
1087
	 * @return void
1088
	 * @throws \EE_Error
1089
	 */
1090
	private function _process_form_action() {
1091
		// what cha wanna do?
1092
		switch( $this->checkout->action ) {
1093
			// AJAX next step reg form
1094
			case 'display_spco_reg_step' :
1095
				$this->checkout->redirect = FALSE;
1096
				if ( EE_Registry::instance()->REQ->ajax ) {
1097
					$this->checkout->json_response->set_reg_step_html( $this->checkout->current_step->display_reg_form() );
1098
				}
1099
				break;
1100
1101
			default :
1102
				// meh... do one of those other steps first
1103
				if ( ! empty( $this->checkout->action ) && is_callable( array( $this->checkout->current_step, $this->checkout->action ))) {
1104
					// dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1105
					do_action( "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step );
1106
					// call action on current step
1107
					if ( call_user_func( array( $this->checkout->current_step, $this->checkout->action )) ) {
1108
						// good registrant, you get to proceed
1109
						if (
1110
							$this->checkout->current_step->success_message() !== ''
1111
							&& apply_filters(
1112
								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1113
								false
1114
							)
1115
						) {
1116
								EE_Error::add_success(
1117
									$this->checkout->current_step->success_message()
1118
									. '<br />' . $this->checkout->next_step->_instructions()
1119
								);
1120
1121
						}
1122
						// pack it up, pack it in...
1123
						$this->_setup_redirect();
1124
					}
1125
					// dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1126
					do_action( "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step );
1127
1128
				} else {
1129
					EE_Error::add_error(
1130
						sprintf(
1131
							__( 'The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso' ),
1132
							$this->checkout->action,
1133
							$this->checkout->current_step->name()
1134
						),
1135
						__FILE__, __FUNCTION__, __LINE__
1136
					);
1137
				}
1138
			// end default
1139
		}
1140
		// store our progress so far
1141
		$this->checkout->stash_transaction_and_checkout();
1142
		// advance to the next step! If you pass GO, collect $200
1143
		$this->go_to_next_step();
1144
	}
1145
1146
1147
1148
	/**
1149
	 * 		add_styles_and_scripts
1150
	 *
1151
	 * 		@access 		public
1152
	 * 		@return 		void
1153
	 */
1154
	public function add_styles_and_scripts() {
1155
		// i18n
1156
		$this->translate_js_strings();
1157
		if ( $this->checkout->admin_request ) {
1158
			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10 );
1159
		} else {
1160
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles_and_scripts' ), 10 );
1161
		}
1162
	}
1163
1164
1165
1166
	/**
1167
	 * 		translate_js_strings
1168
	 *
1169
	 * 		@access 		public
1170
	 * 		@return 		void
1171
	 */
1172
	public function translate_js_strings() {
1173
		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1174
		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1175
		EE_Registry::$i18n_js_strings['server_error'] = __('An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1176
		EE_Registry::$i18n_js_strings['invalid_json_response'] = __( 'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso' );
1177
		EE_Registry::$i18n_js_strings['validation_error'] = __( 'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.', 'event_espresso' );
1178
		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __( 'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.', 'event_espresso' );
1179
		EE_Registry::$i18n_js_strings['reg_step_error'] = __('This registration step could not be completed. Please refresh the page and try again.', 'event_espresso');
1180
		EE_Registry::$i18n_js_strings['invalid_coupon'] = __('We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.', 'event_espresso');
1181
		EE_Registry::$i18n_js_strings['process_registration'] = sprintf( __( 'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.', 'event_espresso' ), '<br/>', '<br/>' );
1182
		EE_Registry::$i18n_js_strings['language'] = get_bloginfo( 'language' );
1183
		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1184
		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1185
		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1186
		EE_Registry::$i18n_js_strings['timer_years'] = __( 'years', 'event_espresso' );
1187
		EE_Registry::$i18n_js_strings['timer_months'] = __( 'months', 'event_espresso' );
1188
		EE_Registry::$i18n_js_strings['timer_weeks'] = __( 'weeks', 'event_espresso' );
1189
		EE_Registry::$i18n_js_strings['timer_days'] = __( 'days', 'event_espresso' );
1190
		EE_Registry::$i18n_js_strings['timer_hours'] = __( 'hours', 'event_espresso' );
1191
		EE_Registry::$i18n_js_strings['timer_minutes'] = __( 'minutes', 'event_espresso' );
1192
		EE_Registry::$i18n_js_strings['timer_seconds'] = __( 'seconds', 'event_espresso' );
1193
		EE_Registry::$i18n_js_strings['timer_year'] = __( 'year', 'event_espresso' );
1194
		EE_Registry::$i18n_js_strings['timer_month'] = __( 'month', 'event_espresso' );
1195
		EE_Registry::$i18n_js_strings['timer_week'] = __( 'week', 'event_espresso' );
1196
		EE_Registry::$i18n_js_strings['timer_day'] = __( 'day', 'event_espresso' );
1197
		EE_Registry::$i18n_js_strings['timer_hour'] = __( 'hour', 'event_espresso' );
1198
		EE_Registry::$i18n_js_strings['timer_minute'] = __( 'minute', 'event_espresso' );
1199
		EE_Registry::$i18n_js_strings['timer_second'] = __( 'second', 'event_espresso' );
1200
		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1201
			__( '%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 except our apologies for any inconvenience this may have caused.%8$s', 'event_espresso' ),
1202
			'<h4 class="important-notice">',
1203
			'</h4>',
1204
			'<br />',
1205
			'<p>',
1206
			'<a href="'. get_post_type_archive_link( 'espresso_events' ) . '" title="',
1207
			'">',
1208
			'</a>',
1209
			'</p>'
1210
		);
1211
		EE_Registry::$i18n_js_strings[ 'ajax_submit' ] = apply_filters( 'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', true );
1212
	}
1213
1214
1215
1216
	/**
1217
	 *    enqueue_styles_and_scripts
1218
	 *
1219
	 * @access        public
1220
	 * @return        void
1221
	 * @throws \EE_Error
1222
	 */
1223
	public function enqueue_styles_and_scripts() {
1224
		// load css
1225
		wp_register_style( 'single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION );
1226
		wp_enqueue_style( 'single_page_checkout' );
1227
		// load JS
1228
		wp_register_script( 'jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array( 'jquery' ), '1.0.1', TRUE );
1229
		wp_register_script( 'jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array( 'jquery_plugin' ), '2.0.2', TRUE );
1230
		wp_register_script( 'single_page_checkout', SPCO_JS_URL . 'single_page_checkout.js', array( 'espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown' ), EVENT_ESPRESSO_VERSION, TRUE );
1231
		$this->checkout->registration_form->enqueue_js();
1232
		wp_enqueue_script( 'single_page_checkout' );
1233
1234
		/**
1235
		 * global action hook for enqueueing styles and scripts with
1236
		 * spco calls.
1237
		 */
1238
		do_action( 'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this );
1239
1240
		/**
1241
		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1242
		 * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1243
		 */
1244
		do_action( 'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this );
1245
1246
	}
1247
1248
1249
1250
	/**
1251
	 *    display the Registration Single Page Checkout Form
1252
	 *
1253
	 * @access    private
1254
	 * @return    void
1255
	 * @throws \EE_Error
1256
	 */
1257
	private function _display_spco_reg_form() {
1258
		// if registering via the admin, just display the reg form for the current step
1259
		if ( $this->checkout->admin_request ) {
1260
			EE_Registry::instance()->REQ->add_output( $this->checkout->current_step->display_reg_form() );
1261
		} else {
1262
			// add powered by EE msg
1263
			add_action( 'AHEE__SPCO__reg_form_footer', array( 'EED_Single_Page_Checkout', 'display_registration_footer' ));
1264
1265
			$empty_cart = count( $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params ) ) < 1 ? true : false;
1266
			$cookies_not_set_msg = '';
1267
			if ( $empty_cart && ! isset( $_COOKIE[ 'ee_cookie_test' ] ) ) {
1268
				$cookies_not_set_msg = apply_filters(
1269
					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1270
					sprintf(
1271
						__( '%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', 'event_espresso' ),
1272
						'<div class="ee-attention">',
1273
						'</div>',
1274
						'<h6 class="important-notice">',
1275
						'</h6>',
1276
						'<p>',
1277
						'</p>',
1278
						'<br />',
1279
						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1280
						'</a>'
1281
					)
1282
				);
1283
			}
1284
			$this->checkout->registration_form = new EE_Form_Section_Proper(
1285
				array(
1286
					'name' 	=> 'single-page-checkout',
1287
					'html_id' 	=> 'ee-single-page-checkout-dv',
1288
					'layout_strategy' =>
1289
						new EE_Template_Layout(
1290
							array(
1291
								'layout_template_file' 			=> SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1292
								'template_args' => array(
1293
									'empty_cart' 		=> $empty_cart,
1294
									'revisit' 				=> $this->checkout->revisit,
1295
									'reg_steps' 			=> $this->checkout->reg_steps,
1296
									'next_step' 			=>  $this->checkout->next_step instanceof EE_SPCO_Reg_Step ? $this->checkout->next_step->slug() : '',
1297
									'empty_msg' 		=> apply_filters(
1298
										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1299
										sprintf(
1300
											__( 'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.', 'event_espresso' ),
1301
											'<a href="' . get_post_type_archive_link( 'espresso_events' ) . '" title="',
1302
											'">',
1303
											'</a>'
1304
										)
1305
									),
1306
									'cookies_not_set_msg' 		=> $cookies_not_set_msg,
1307
									'registration_time_limit' 	=> $this->checkout->get_registration_time_limit(),
1308
									'session_expiration' 			=>
1309
										date( 'M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) )
1310
							)
1311
						)
1312
					)
1313
				)
1314
			);
1315
			// load template and add to output sent that gets filtered into the_content()
1316
			EE_Registry::instance()->REQ->add_output( $this->checkout->registration_form->get_html() );
1317
		}
1318
	}
1319
1320
1321
1322
	/**
1323
	 *    add_extra_finalize_registration_inputs
1324
	 *
1325
	 * @access    public
1326
	 * @param $next_step
1327
	 * @internal  param string $label
1328
	 * @return void
1329
	 */
1330
	public function add_extra_finalize_registration_inputs( $next_step ) {
1331
		if ( $next_step === 'finalize_registration' ) {
1332
			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1333
		}
1334
	}
1335
1336
1337
1338
	/**
1339
	 * 	display_registration_footer
1340
	 *
1341
	 *  @access 	public
1342
	 *  @return 	string
1343
	 */
1344
	public static function display_registration_footer() {
1345
		if (
1346
			apply_filters(
1347
				'FHEE__EE_Front__Controller__show_reg_footer',
1348
				EE_Registry::instance()->CFG->admin->show_reg_footer
1349
			)
1350
		) {
1351
			add_filter(
1352
				'FHEE__EEH_Template__powered_by_event_espresso__url',
1353
				function( $url) {
1354
					return apply_filters( 'FHEE__EE_Front_Controller__registration_footer__url', $url );
1355
				}
1356
			);
1357
			echo apply_filters(
1358
				'FHEE__EE_Front_Controller__display_registration_footer',
1359
				\EEH_Template::powered_by_event_espresso(
1360
					'',
1361
					'espresso-registration-footer-dv',
1362
					array( 'utm_content' => 'registration_checkout' )
1363
				)
1364
			);
1365
		}
1366
		return '';
1367
	}
1368
1369
1370
1371
	/**
1372
	 *    unlock_transaction
1373
	 *
1374
	 * @access    public
1375
	 * @return    void
1376
	 * @throws \EE_Error
1377
	 */
1378
	public function unlock_transaction() {
1379
		if ( $this->checkout->transaction instanceof EE_Transaction ) {
1380
			$this->checkout->transaction->unlock();
1381
		}
1382
	}
1383
1384
1385
1386
1387
	/**
1388
	 *        _setup_redirect
1389
	 *
1390
	 * @access 	private
1391
	 * @return void
1392
	 */
1393
	private function _setup_redirect() {
1394
		if ( $this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step ) {
1395
			$this->checkout->redirect = TRUE;
1396
			if ( empty( $this->checkout->redirect_url )) {
1397
				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1398
			}
1399
			$this->checkout->redirect_url = apply_filters(
1400
			    'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1401
                $this->checkout->redirect_url,
1402
                $this->checkout
1403
            );
1404
		}
1405
	}
1406
1407
1408
1409
	/**
1410
	 *   handle ajax message responses and redirects
1411
	 *
1412
	 * @access public
1413
	 * @return void
1414
	 * @throws \EE_Error
1415
	 */
1416
	public function go_to_next_step() {
1417
		if ( EE_Registry::instance()->REQ->ajax ) {
1418
			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1419
			$this->checkout->json_response->set_unexpected_errors( ob_get_clean() );
1420
		}
1421
		$this->unlock_transaction();
1422
		// just return for these conditions
1423
		if (
1424
			$this->checkout->admin_request
1425
			|| $this->checkout->action === 'redirect_form'
1426
			|| $this->checkout->action === 'update_checkout'
1427
		) {
1428
			return;
1429
		}
1430
		// AJAX response
1431
		$this->_handle_json_response();
1432
		// redirect to next step or the Thank You page
1433
		$this->_handle_html_redirects();
1434
		// hmmm... must be something wrong, so let's just display the form again !
1435
		$this->_display_spco_reg_form();
1436
	}
1437
1438
1439
1440
	/**
1441
	 *   _handle_json_response
1442
	 *
1443
	 * @access protected
1444
	 * @return void
1445
	 */
1446
	protected function _handle_json_response() {
1447
		// if this is an ajax request
1448
		if ( EE_Registry::instance()->REQ->ajax ) {
1449
			// DEBUG LOG
1450
			//$this->checkout->log(
1451
			//	__CLASS__, __FUNCTION__, __LINE__,
1452
			//	array(
1453
			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1454
			//		'redirect'                   => $this->checkout->redirect,
1455
			//		'continue_reg'               => $this->checkout->continue_reg,
1456
			//	)
1457
			//);
1458
			$this->checkout->json_response->set_registration_time_limit(
1459
				$this->checkout->get_registration_time_limit()
1460
			);
1461
			$this->checkout->json_response->set_payment_amount( $this->checkout->amount_owing );
1462
			// just send the ajax (
1463
			$json_response = apply_filters(
1464
				'FHEE__EE_Single_Page_Checkout__JSON_response',
1465
				$this->checkout->json_response
1466
			);
1467
			echo $json_response;
1468
			exit();
1469
		}
1470
	}
1471
1472
1473
1474
	/**
1475
	 *   _handle_redirects
1476
	 *
1477
	 * @access protected
1478
	 * @return void
1479
	 */
1480
	protected function _handle_html_redirects() {
1481
		// going somewhere ?
1482
		if ( $this->checkout->redirect && ! empty( $this->checkout->redirect_url ) ) {
1483
			// store notices in a transient
1484
			EE_Error::get_notices( false, true, true );
1485
			// DEBUG LOG
1486
			//$this->checkout->log(
1487
			//	__CLASS__, __FUNCTION__, __LINE__,
1488
			//	array(
1489
			//		'headers_sent' => headers_sent(),
1490
			//		'redirect_url'     => $this->checkout->redirect_url,
1491
			//		'headers_list'    => headers_list(),
1492
			//	)
1493
			//);
1494
			wp_safe_redirect( $this->checkout->redirect_url );
1495
			exit();
1496
		}
1497
	}
1498
1499
1500
1501
	/**
1502
	 *   set_checkout_anchor
1503
	 *
1504
	 * @access public
1505
	 * @return void
1506
	 */
1507
	public function set_checkout_anchor() {
1508
		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1509
	}
1510
1511
1512
1513
}
1514
// End of file EED_Single_Page_Checkout.module.php
1515
// Location: /modules/single_page_checkout/EED_Single_Page_Checkout.module.php
1516