Completed
Branch BUG-9623-config-log (1352ef)
by
unknown
225:37 queued 211:25
created

EED_Single_Page_Checkout   F

Complexity

Total Complexity 165

Size/Duplication

Total Lines 1392
Duplicated Lines 2.01 %

Coupling/Cohesion

Components 1
Dependencies 24
Metric Value
wmc 165
lcom 1
cbo 24
dl 28
loc 1392
rs 0.5665

49 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 4 1
A cart() 0 3 1
A transaction() 0 3 1
A set_hooks() 0 3 1
A process_ajax_request() 0 4 1
A display_reg_step() 0 3 1
A process_reg_step() 0 3 1
A update_reg_step() 0 3 1
A update_checkout() 0 3 1
A set_hooks_admin() 0 19 2
A load_request_handler() 0 6 2
A set_definitions() 0 10 1
B get_reg_steps() 0 32 2
A registration_checkout_for_admin() 0 9 1
A process_registration_from_admin() 0 19 4
A init() 0 3 1
B _initialize_checkout() 0 22 5
A _display_request_vars() 0 13 2
A _get_first_step() 0 4 2
A _get_transaction_and_cart_for_previous_visit() 8 15 2
A _get_cart_for_transaction() 0 8 3
A get_cart_for_transaction() 0 3 1
A _get_cart_for_current_session_and_setup_new_transaction() 0 17 2
A _initialize_transaction() 0 19 3
D _get_registrations() 0 31 10
B _initialize_registrations() 0 27 5
A sort_registrations_by_REG_count() 0 7 3
C _final_verifications() 8 33 8
B _initialize_reg_steps() 0 23 6
D _check_form_submission() 3 39 10
C _process_form_action() 0 47 8
A add_styles_and_scripts() 0 9 2
B translate_js_strings() 0 41 1
B enqueue_styles_and_scripts() 0 25 1
B _display_spco_reg_form() 0 64 6
A add_extra_finalize_registration_inputs() 0 5 2
A display_registration_footer() 0 19 3
A unlock_transaction() 0 3 1
A _setup_redirect() 0 9 4
B go_to_next_step() 0 16 5
A _handle_json_response() 0 21 2
A _handle_html_redirects() 0 19 3
A set_checkout_anchor() 0 3 1
C load_reg_steps() 0 36 8
A run() 0 9 4
C _initialize() 0 72 8
B _get_request_vars() 0 24 2
D _load_and_instantiate_reg_steps() 0 46 10
C _load_and_instantiate_reg_step() 9 53 10

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EED_Single_Page_Checkout often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EED_Single_Page_Checkout, and based on these observations, apply Extract Interface, too.

1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 * Single Page Checkout (SPCO)
4
 *
5
 * @package			Event Espresso
6
 * @subpackage		/modules/single_page_checkout/
7
 * @author				Brent Christensen
8
 *
9
 */
10
class EED_Single_Page_Checkout  extends EED_Module {
11
12
13
	/**
14
	 * 	$_initialized - has the SPCO controller already been initialized ?
15
	 * 	@access private
16
	 *	@var bool $_initialized
17
	 */
18
	private static $_initialized = FALSE;
19
20
	/**
21
	 * 	$_reg_steps_array - holds initial array of reg steps
22
	 * 	@access private
23
	 *	@var array $_reg_steps_array
24
	 */
25
	private static $_reg_steps_array = array();
26
27
	/**
28
	 * 	$checkout - EE_Checkout object for handling the properties of the current checkout process
29
	 * 	@access public
30
	 *	@var EE_Checkout $checkout
31
	 */
32
	public $checkout = NULL;
33
34
35
36
37
	/**
38
	 * @return EED_Single_Page_Checkout
39
	 */
40
	public static function instance() {
41
		add_filter( 'EED_Single_Page_Checkout__SPCO_active', '__return_true' );
42
		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...
43
	}
44
45
46
47
	/**
48
	 * @return EE_CART
49
	 */
50
	public function cart() {
51
		return $this->checkout->cart;
52
	}
53
54
55
56
	/**
57
	 * @return EE_Transaction
58
	 */
59
	public function transaction() {
60
		return $this->checkout->transaction;
61
	}
62
63
64
65
66
67
	/**
68
	 * 	set_hooks - for hooking into EE Core, other modules, etc
69
	 *
70
	 *  @access 	public
71
	 *  @return 	void
72
	 */
73
	public static function set_hooks() {
74
		EED_Single_Page_Checkout::set_definitions();
75
	}
76
77
78
79
	/**
80
	 * 	set_hooks_admin - for hooking into EE Admin Core, other modules, etc
81
	 *
82
	 *  @access 	public
83
	 *  @return 	void
84
	 */
85
	public static function set_hooks_admin() {
86
		EED_Single_Page_Checkout::set_definitions();
87
		if ( defined( 'DOING_AJAX' )) {
88
			// going to start an output buffer in case anything gets accidentally output that might disrupt our JSON response
89
			ob_start();
90
			EED_Single_Page_Checkout::load_request_handler();
91
			EED_Single_Page_Checkout::load_reg_steps();
92
		} else {
93
			// 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
94
			add_action( 'pre_get_posts', array( 'EED_Single_Page_Checkout', 'load_reg_steps' ), 1 );
95
		}
96
		// set ajax hooks
97
		add_action( 'wp_ajax_process_reg_step', array( 'EED_Single_Page_Checkout', 'process_reg_step' ));
98
		add_action( 'wp_ajax_nopriv_process_reg_step', array( 'EED_Single_Page_Checkout', 'process_reg_step' ));
99
		add_action( 'wp_ajax_display_spco_reg_step', array( 'EED_Single_Page_Checkout', 'display_reg_step' ));
100
		add_action( 'wp_ajax_nopriv_display_spco_reg_step', array( 'EED_Single_Page_Checkout', 'display_reg_step' ));
101
		add_action( 'wp_ajax_update_reg_step', array( 'EED_Single_Page_Checkout', 'update_reg_step' ));
102
		add_action( 'wp_ajax_nopriv_update_reg_step', array( 'EED_Single_Page_Checkout', 'update_reg_step' ));
103
	}
104
105
106
107
	/**
108
	 * 	process ajax request
109
	 * @param string $ajax_action
110
	 */
111
	public static function process_ajax_request( $ajax_action ) {
112
		EE_Registry::instance()->REQ->set( 'action', $ajax_action );
113
		EED_Single_Page_Checkout::instance()->_initialize();
114
	}
115
116
117
118
	/**
119
	 * 	ajax display registration step
120
	 */
121
	public static function display_reg_step() {
122
		EED_Single_Page_Checkout::process_ajax_request( 'display_spco_reg_step' );
123
	}
124
125
126
127
	/**
128
	 * 	ajax process registration step
129
	 */
130
	public static function process_reg_step() {
131
		EED_Single_Page_Checkout::process_ajax_request( 'process_reg_step' );
132
	}
133
134
135
136
	/**
137
	 * 	ajax process registration step
138
	 */
139
	public static function update_reg_step() {
140
		EED_Single_Page_Checkout::process_ajax_request( 'update_reg_step' );
141
	}
142
143
144
145
	/**
146
	 *   update_checkout
147
	 *
148
	 * @access public
149
	 * @return void
150
	 */
151
	public static function update_checkout() {
152
		EED_Single_Page_Checkout::process_ajax_request( 'update_checkout' );
153
	}
154
155
156
157
	/**
158
	 *    load_request_handler
159
	 *
160
	 * @access    public
161
	 * @return    void
162
	 */
163
	public static function load_request_handler() {
164
		// load core Request_Handler class
165
		if ( ! isset( EE_Registry::instance()->REQ )) {
166
			EE_Registry::instance()->load_core( 'Request_Handler' );
167
		}
168
	}
169
170
171
172
	/**
173
	 * 	set_definitions
174
	 *
175
	 *  @access 	public
176
	 *  @return 	void
177
	 */
178
	public static function set_definitions() {
179
		define( 'SPCO_BASE_PATH', rtrim( str_replace( array( '\\', '/' ), DS, plugin_dir_path( __FILE__ )), DS ) . DS );
180
		define( 'SPCO_CSS_URL', plugin_dir_url( __FILE__ ) . 'css' . DS );
181
		define( 'SPCO_IMG_URL', plugin_dir_url( __FILE__ ) . 'img' . DS );
182
		define( 'SPCO_JS_URL', plugin_dir_url( __FILE__ ) . 'js' . DS );
183
		define( 'SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS );
184
		define( 'SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS );
185
		define( 'SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS );
186
		EEH_Autoloader::register_autoloaders_for_each_file_in_folder( SPCO_BASE_PATH, TRUE );
187
	}
188
189
190
191
	/**
192
	 * load_reg_steps
193
	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
194
	 *
195
	 * @access    private
196
	 * @throws EE_Error
197
	 * @return    array
198
	 */
199
	public static function load_reg_steps() {
200
		static $reg_steps_loaded = FALSE;
201
		if ( $reg_steps_loaded ) {
202
			return;
203
		}
204
		// filter list of reg_steps
205
		$reg_steps_to_load = apply_filters(
206
			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
207
			EED_Single_Page_Checkout::get_reg_steps()
208
		);
209
		// sort by key (order)
210
		ksort( $reg_steps_to_load );
211
		// loop through folders
212
		foreach ( $reg_steps_to_load as $order => $reg_step ) {
213
			// we need a
214
			if ( isset( $reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'] )) {
215
				// copy over to the reg_steps_array
216
				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
217
				// register custom key route for each reg step
218
				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
219
				EE_Config::register_route( $reg_step['slug'], 'EED_Single_Page_Checkout', 'run', 'step' );
220
				// add AJAX or other hooks
221
				if ( isset( $reg_step['has_hooks'] ) && $reg_step['has_hooks'] ) {
222
					// setup autoloaders if necessary
223
					if ( ! class_exists( $reg_step['class_name'] )) {
224
						EEH_Autoloader::register_autoloaders_for_each_file_in_folder( $reg_step['file_path'], TRUE );
225
					}
226
					if ( is_callable( $reg_step['class_name'], 'set_hooks' )) {
227
						call_user_func( array( $reg_step['class_name'], 'set_hooks' ));
228
					}
229
				}
230
			}
231
		}
232
233
		$reg_steps_loaded = TRUE;
234
	}
235
236
237
238
	/**
239
	 *    get_reg_steps
240
	 *
241
	 * @access 	public
242
	 * @return 	array
243
	 */
244
	public static function get_reg_steps() {
245
		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
246
		if ( empty( $reg_steps )) {
247
			$reg_steps = array(
248
				10 => array(
249
					'file_path' => SPCO_REG_STEPS_PATH . 'attendee_information',
250
					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
251
					'slug' => 'attendee_information',
252
					'has_hooks' => FALSE
253
				),
254
				20 => array(
255
					'file_path' => SPCO_REG_STEPS_PATH . 'registration_confirmation',
256
					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
257
					'slug' => 'registration_confirmation',
258
					'has_hooks' => FALSE
259
				),
260
				30 => array(
261
					'file_path' => SPCO_REG_STEPS_PATH . 'payment_options',
262
					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
263
					'slug' => 'payment_options',
264
					'has_hooks' => TRUE
265
				),
266
				999 => array(
267
					'file_path' => SPCO_REG_STEPS_PATH . 'finalize_registration',
268
					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
269
					'slug' => 'finalize_registration',
270
					'has_hooks' => FALSE
271
				)
272
			);
273
		}
274
		return $reg_steps;
275
	}
276
277
278
279
	/**
280
	 *    registration_checkout_for_admin
281
	 *
282
	 * @access    public
283
	 * @return    string
284
	 */
285
	public static function registration_checkout_for_admin() {
286
		EED_Single_Page_Checkout::load_reg_steps();
287
		EE_Registry::instance()->REQ->set( 'step', 'attendee_information' );
288
		EE_Registry::instance()->REQ->set( 'action', 'display_spco_reg_step' );
289
		EE_Registry::instance()->REQ->set( 'process_form_submission', false );
290
		EED_Single_Page_Checkout::instance()->_initialize();
291
		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
292
		return EE_Registry::instance()->REQ->get_output();
293
	}
294
295
296
297
	/**
298
	 *    process_registration_from_admin
299
	 *
300
	 * @access    public
301
	 * @return    int
302
	 */
303
	public static function process_registration_from_admin() {
304
		EED_Single_Page_Checkout::load_reg_steps();
305
		EE_Registry::instance()->REQ->set( 'step', 'attendee_information' );
306
		EE_Registry::instance()->REQ->set( 'action', 'process_reg_step' );
307
		EE_Registry::instance()->REQ->set( 'process_form_submission', true );
308
		EED_Single_Page_Checkout::instance()->_initialize();
309
		if ( EED_Single_Page_Checkout::instance()->checkout->current_step->completed() ) {
310
			$final_reg_step = end( EED_Single_Page_Checkout::instance()->checkout->reg_steps );
311
			if ( $final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration ) {
312
				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated( $final_reg_step );
313
				if ( $final_reg_step->process_reg_step() ) {
314
					$final_reg_step->set_completed();
315
					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
316
					return EED_Single_Page_Checkout::instance()->checkout->transaction;
317
				}
318
			}
319
		}
320
		return FALSE;
321
	}
322
323
324
325
	/**
326
	 *    run
327
	 *
328
	 * @access    public
329
	 * @param WP_Query $WP_Query
330
	 * @return    void
331
	 */
332
	public function run( $WP_Query ) {
333
		if (
334
			$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...
335
			&& $WP_Query->is_main_query()
336
			&& apply_filters( 'FHEE__EED_Single_Page_Checkout__run', true )
337
		) {
338
			$this->_initialize();
339
		}
340
	}
341
342
343
344
345
	/**
346
	 *    run
347
	 *
348
	 * @access    public
349
	 * @param WP_Query $WP_Query
350
	 * @return    void
351
	 */
352
	public static function init( $WP_Query ) {
353
		EED_Single_Page_Checkout::instance()->run( $WP_Query );
354
	}
355
356
357
358
	/**
359
	 *    _initialize - initial module setup
360
	 *
361
	 * @access    private
362
	 * @throws EE_Error
363
	 * @return    void
364
	 */
365
	private function _initialize() {
366
		// ensure SPCO doesn't run twice
367
		if ( EED_Single_Page_Checkout::$_initialized ) {
368
			return;
369
		}
370
		// setup the EE_Checkout object
371
		$this->checkout = $this->_initialize_checkout();
372
		// filter checkout
373
		$this->checkout = apply_filters( 'FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout );
374
		// get the $_GET
375
		$this->_get_request_vars();
376
		// filter continue_reg
377
		$this->checkout->continue_reg = apply_filters( 'FHEE__EED_Single_Page_Checkout__init___continue_reg', TRUE, $this->checkout );
378
		// load the reg steps array
379
		if ( ! $this->_load_and_instantiate_reg_steps() ) {
380
			EED_Single_Page_Checkout::$_initialized = true;
381
			return;
382
		}
383
		// set the current step
384
		$this->checkout->set_current_step( $this->checkout->step );
385
		// and the next step
386
		$this->checkout->set_next_step();
387
		// was there already a valid transaction in the checkout from the session ?
388
		if ( ! $this->checkout->transaction instanceof EE_Transaction ) {
389
			// get transaction from db or session
390
			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
391
				? $this->_get_transaction_and_cart_for_previous_visit()
392
				: $this->_get_cart_for_current_session_and_setup_new_transaction();
393
			if ( ! $this->checkout->transaction instanceof EE_Transaction ) {
394
				EE_Error::add_error(
395
					__( 'Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso' ),
396
					__FILE__, __FUNCTION__, __LINE__
397
				);
398
				// add some style and make it dance
399
				$this->checkout->transaction = EE_Transaction::new_instance();
400
				$this->add_styles_and_scripts();
401
				EED_Single_Page_Checkout::$_initialized = true;
402
				return;
403
			}
404
			// and the registrations for the transaction
405
			$this->_get_registrations( $this->checkout->transaction );
406
		}
407
		// verify that everything has been setup correctly
408
		if ( ! $this->_final_verifications() ) {
409
			EED_Single_Page_Checkout::$_initialized = true;
410
			return;
411
		}
412
		// lock the transaction
413
		$this->checkout->transaction->lock();
414
		// make sure all of our cached objects are added to their respective model entity mappers
415
		$this->checkout->refresh_all_entities();
416
		// set amount owing
417
		$this->checkout->amount_owing = $this->checkout->transaction->remaining();
418
		// initialize each reg step, which gives them the chance to potentially alter the process
419
		$this->_initialize_reg_steps();
420
		// DEBUG LOG
421
		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
422
		// get reg form
423
		$this->_check_form_submission();
424
		// checkout the action!!!
425
		$this->_process_form_action();
426
		// add some style and make it dance
427
		$this->add_styles_and_scripts();
428
		// kk... SPCO has successfully run
429
		EED_Single_Page_Checkout::$_initialized = TRUE;
430
		// set no cache headers and constants
431
		EE_System::do_not_cache();
432
		// add anchor
433
		add_action( 'loop_start', array( $this, 'set_checkout_anchor' ), 1 );
434
		// remove transaction lock
435
		add_action( 'shutdown', array( $this, 'unlock_transaction' ), 1 );
436
	}
437
438
439
440
	/**
441
	 *    _initialize_checkout
442
	 * loads and instantiates EE_Checkout
443
	 *
444
	 * @access    private
445
	 * @throws EE_Error
446
	 * @return EE_Checkout
447
	 */
448
	private function _initialize_checkout() {
449
		// look in session for existing checkout
450
		$checkout = EE_Registry::instance()->SSN->checkout();
451
		// verify
452
		if ( ! $checkout instanceof EE_Checkout ) {
453
			// instantiate EE_Checkout object for handling the properties of the current checkout process
454
			$checkout = EE_Registry::instance()->load_file( SPCO_INC_PATH, 'EE_Checkout', 'class', array(), FALSE  );
455
			// verify again
456
			if ( ! $checkout instanceof EE_Checkout ) {
457
				throw new EE_Error( __( 'The EE_Checkout class could not be loaded.', 'event_espresso' ) );
458
			}
459
		} else {
460
			if ( $checkout->current_step->is_final_step() && $checkout->exit_spco() === true )  {
461
				wp_safe_redirect( $checkout->redirect_url );
462
				exit();
463
			}
464
		}
465
		$checkout = apply_filters( 'FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout );
466
		// reset anything that needs a clean slate for each request
467
		$checkout->reset_for_current_request();
468
		return $checkout;
469
	}
470
471
472
473
	/**
474
	 *    _get_request_vars
475
	 *
476
	 * @access 	private
477
	 * @return 	void
478
	 */
479
	private function _get_request_vars() {
480
		// load classes
481
		EED_Single_Page_Checkout::load_request_handler();
482
		//make sure this request is marked as belonging to EE
483
		EE_Registry::instance()->REQ->set_espresso_page( TRUE );
484
		// which step is being requested ?
485
		$this->checkout->step = EE_Registry::instance()->REQ->get( 'step', $this->_get_first_step() );
486
		// which step is being edited ?
487
		$this->checkout->edit_step = EE_Registry::instance()->REQ->get( 'edit_step', '' );
488
		// and what we're doing on the current step
489
		$this->checkout->action = EE_Registry::instance()->REQ->get( 'action', 'display_spco_reg_step' );
490
		// returning to edit ?
491
		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get( 'e_reg_url_link', '' );
492
		// or some other kind of revisit ?
493
		$this->checkout->revisit = EE_Registry::instance()->REQ->get( 'revisit', FALSE );
494
		// and whether or not to generate a reg form for this request
495
		$this->checkout->generate_reg_form = EE_Registry::instance()->REQ->get( 'generate_reg_form', TRUE ); 		// TRUE 	FALSE
496
		// and whether or not to process a reg form submission for this request
497
		$this->checkout->process_form_submission = EE_Registry::instance()->REQ->get( 'process_form_submission', FALSE ); 		// TRUE 	FALSE
498
		$this->checkout->process_form_submission = $this->checkout->action !== 'display_spco_reg_step'
499
			? $this->checkout->process_form_submission
500
			: FALSE; 		// TRUE 	FALSE
501
		//$this->_display_request_vars();
502
	}
503
504
505
506
	/**
507
	 *  _display_request_vars
508
	 *
509
	 * @access    protected
510
	 * @return    void
511
	 */
512
	protected function _display_request_vars() {
513
		if ( ! WP_DEBUG ) {
514
			return;
515
		}
516
		EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$_REQUEST' is of type string, but the function expects a boolean.

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...
517
		EEH_Debug_Tools::printr( $this->checkout->step, '$this->checkout->step', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->step' is of type string, but the function expects a boolean.

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...
518
		EEH_Debug_Tools::printr( $this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->edit_step' is of type string, but the function expects a boolean.

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...
519
		EEH_Debug_Tools::printr( $this->checkout->action, '$this->checkout->action', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->action' is of type string, but the function expects a boolean.

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...
520
		EEH_Debug_Tools::printr( $this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->reg_url_link' is of type string, but the function expects a boolean.

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...
521
		EEH_Debug_Tools::printr( $this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->revisit' is of type string, but the function expects a boolean.

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...
522
		EEH_Debug_Tools::printr( $this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->generate_reg_form' is of type string, but the function expects a boolean.

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...
523
		EEH_Debug_Tools::printr( $this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__ );
0 ignored issues
show
Documentation introduced by
'$this->checkout->process_form_submission' is of type string, but the function expects a boolean.

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...
524
	}
525
526
527
528
	/**
529
	 *    _get_first_step
530
	 *  gets slug for first step in $_reg_steps_array
531
	 *
532
	 * @access    private
533
	 * @throws EE_Error
534
	 * @return    array
535
	 */
536
	private function _get_first_step() {
537
		$first_step = reset( EED_Single_Page_Checkout::$_reg_steps_array );
538
		return isset( $first_step['slug'] ) ? $first_step['slug'] : 'attendee_information';
539
	}
540
541
542
543
	/**
544
	 *    _load_and_instantiate_reg_steps
545
	 *  instantiates each reg step based on the loaded reg_steps array
546
	 *
547
	 * @access    private
548
	 * @throws EE_Error
549
	 * @return    bool
550
	 */
551
	private function _load_and_instantiate_reg_steps() {
552
		// have reg_steps already been instantiated ?
553
		if (
554
			empty( $this->checkout->reg_steps ) ||
555
			apply_filters( 'FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout )
556
		) {
557
			// if not, then loop through raw reg steps array
558
			foreach ( EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step ) {
559
				if ( ! $this->_load_and_instantiate_reg_step( $reg_step, $order )) {
560
					return false;
561
				}
562
			}
563
			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = TRUE;
564
			EE_Registry::instance()->CFG->registration->reg_confirmation_last = TRUE;
565
			// skip the registration_confirmation page ?
566
			if ( EE_Registry::instance()->CFG->registration->skip_reg_confirmation ) {
567
				// just remove it from the reg steps array
568
				$this->checkout->remove_reg_step( 'registration_confirmation', false );
569
			} else if (
570
				EE_Registry::instance()->CFG->registration->reg_confirmation_last
571
				&& isset( $this->checkout->reg_steps['registration_confirmation'] )
572
			) {
573
				// set the order to something big like 100
574
				$this->checkout->set_reg_step_order( 'registration_confirmation', 100 );
575
			}
576
			// filter the array for good luck
577
			$this->checkout->reg_steps = apply_filters(
578
				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
579
				$this->checkout->reg_steps
580
			);
581
			// finally re-sort based on the reg step class order properties
582
			$this->checkout->sort_reg_steps();
583
		} else {
584
			foreach ( $this->checkout->reg_steps as $reg_step ) {
585
				// set all current step stati to FALSE
586
				$reg_step->set_is_current_step( FALSE );
587
			}
588
		}
589
		if ( empty( $this->checkout->reg_steps )) {
590
			EE_Error::add_error( __( 'No Reg Steps were loaded..', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__);
591
			return false;
592
		}
593
			// make reg step details available to JS
594
		$this->checkout->set_reg_step_JSON_info();
595
		return true;
596
	}
597
598
599
600
	/**
601
	 *     _load_and_instantiate_reg_step
602
	 *
603
	 * @access    private
604
	 * @param array $reg_step
605
	 * @param int   $order
606
	 * @return bool
607
	 */
608
	private function _load_and_instantiate_reg_step( $reg_step = array(), $order = 0 ) {
609
610
		// we need a file_path, class_name, and slug to add a reg step
611
		if ( isset( $reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'] )) {
612
			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
613
			if (
614
				$this->checkout->reg_url_link
615
				&& $this->checkout->step !== $reg_step['slug']
616
				&& $reg_step['slug'] !== 'finalize_registration'
617
			) {
618
				return true;
619
			}
620
			// instantiate step class using file path and class name
621
			$reg_step_obj = EE_Registry::instance()->load_file(
622
				$reg_step['file_path'],
623
				$reg_step['class_name'],
624
				'class',
625
				$this->checkout,
626
				FALSE
627
			);
628
			// did we gets the goods ?
629 View Code Duplication
			if ( $reg_step_obj instanceof EE_SPCO_Reg_Step ) {
630
				// set reg step order based on config
631
				$reg_step_obj->set_order( $order );
632
				// add instantiated reg step object to the master reg steps array
633
				$this->checkout->add_reg_step( $reg_step_obj );
634
			} else {
635
				EE_Error::add_error(
636
					__( 'The current step could not be set.', 'event_espresso' ),
637
					__FILE__, __FUNCTION__, __LINE__
638
				);
639
				return false;
640
			}
641
		} else {
642
			if ( WP_DEBUG ) {
643
				EE_Error::add_error(
644
					sprintf(
645
						__( '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' ),
646
						isset( $reg_step['file_path'] ) ? $reg_step['file_path'] : '',
647
						isset( $reg_step['class_name'] ) ? $reg_step['class_name'] : '',
648
						isset( $reg_step['slug'] ) ? $reg_step['slug'] : '',
649
						'<ul>',
650
						'<li>',
651
						'</li>',
652
						'</ul>'
653
					),
654
					__FILE__, __FUNCTION__, __LINE__
655
				);
656
			}
657
			return false;
658
		}
659
		return true;
660
	}
661
662
663
664
	/**
665
	 * _get_transaction_and_cart_for_previous_visit
666
	 *
667
	 * @access private
668
	 * 	@return mixed EE_Transaction|NULL
669
	 */
670
	private function _get_transaction_and_cart_for_previous_visit() {
671
		/** @var $TXN_model EEM_Transaction */
672
		$TXN_model = EE_Registry::instance()->load_model( 'Transaction' );
673
		// 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
674
		$transaction = $TXN_model->get_transaction_from_reg_url_link( $this->checkout->reg_url_link );
675
		// verify transaction
676 View Code Duplication
		if ( $transaction instanceof EE_Transaction ) {
677
			// and get the cart that was used for that transaction
678
			$this->checkout->cart = $this->_get_cart_for_transaction( $transaction );
679
			return $transaction;
680
		} else {
681
			EE_Error::add_error( __( 'Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__);
682
			return NULL;
683
		}
684
	}
685
686
687
688
	/**
689
	 * _get_cart_for_transaction
690
	 *
691
	 * @access private
692
	 * @param EE_Transaction $transaction
693
	 * @return EE_Cart
694
	 */
695
	private function _get_cart_for_transaction( $transaction ) {
696
		$cart = $transaction instanceof EE_Transaction ? EE_Cart::get_cart_from_txn( $transaction ) : NULL;
697
		// verify cart
698
		if ( ! $cart instanceof EE_Cart ) {
699
			$cart = EE_Registry::instance()->load_core( 'Cart' );
0 ignored issues
show
Bug Compatibility introduced by
The expression \EE_Registry::instance()->load_core('Cart'); of type boolean adds the type boolean to the return on line 701 which is incompatible with the return type documented by EED_Single_Page_Checkout...et_cart_for_transaction of type EE_Cart.
Loading history...
700
		}
701
		return $cart;
702
	}
703
704
705
706
	/**
707
	 * _get_cart_for_current_session_and_setup_new_transaction
708
	 * 	generates a new EE_Transaction object and adds it to the $_transaction property.
709
	 *
710
	 * 	@access public
711
	 * @param EE_Transaction $transaction
712
	 * 	@return EE_Cart
713
	 */
714
	public function get_cart_for_transaction( EE_Transaction $transaction ) {
715
		return EE_Cart::get_cart_from_txn( $transaction );
716
	}
717
718
719
720
	/**
721
	 * _get_transaction_and_cart_for_current_session
722
	 * 	generates a new EE_Transaction object and adds it to the $_transaction property.
723
	 *
724
	 * 	@access private
725
	 * 	@return EE_Transaction
726
	 */
727
	private function _get_cart_for_current_session_and_setup_new_transaction() {
728
		//  if there's no transaction, then this is the FIRST visit to SPCO
729
		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
730
		$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...
731
		// and then create a new transaction
732
		$transaction = $this->_initialize_transaction();
733
		// verify transaction
734
		if ( $transaction instanceof EE_Transaction ) {
735
			// save it so that we have an ID for other objects to use
736
			$transaction->save();
737
			// and save TXN data to the cart
738
			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn( $transaction->ID() );
739
		} else {
740
			EE_Error::add_error( __( 'A Valid Transaction could not be initialized.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
741
		}
742
		return $transaction;
743
	}
744
745
746
747
	/**
748
	 * 	generates a new EE_Transaction object and adds it to the $_transaction property.
749
	 *
750
	 * 	@access private
751
	 * 	@return mixed EE_Transaction|NULL
752
	 */
753
	private function _initialize_transaction() {
754
		try {
755
			// ensure cart totals have been calculated
756
			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
757
			// grab the cart grand total
758
			$cart_total = $this->checkout->cart->get_cart_grand_total();
759
			// create new TXN
760
			return EE_Transaction::new_instance( array(
761
				'TXN_timestamp' 	=> time(),
762
				'TXN_reg_steps' 		=> $this->checkout->initialize_txn_reg_steps_array(),
763
				'TXN_total' 				=> $cart_total > 0 ? $cart_total : 0,
764
				'TXN_paid' 				=> 0,
765
				'STS_ID' 					=> EEM_Transaction::failed_status_code,
766
			));
767
		} catch( Exception $e ) {
768
			EE_Error::add_error( $e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
769
		}
770
		return NULL;
771
	}
772
773
774
775
	/**
776
	 * _get_registrations
777
	 *
778
	 * @access private
779
	 * @param EE_Transaction $transaction
780
	 * @return EE_Cart
781
	 */
782
	private function _get_registrations( EE_Transaction $transaction ) {
783
		// first step: grab the registrants  { : o
784
		$registrations = $transaction->registrations( $this->checkout->reg_cache_where_params, true );
785
		// verify registrations have been set
786
		if ( empty( $registrations )) {
787
			// if no cached registrations, then check the db
788
			$registrations = $transaction->registrations( $this->checkout->reg_cache_where_params, false );
789
			// still nothing ? well as long as this isn't a revisit
790
			if ( empty( $registrations ) && ! $this->checkout->revisit ) {
791
				// generate new registrations from scratch
792
				$registrations = $this->_initialize_registrations( $transaction );
793
			}
794
		}
795
		// sort by their original registration order
796
		usort( $registrations, array( 'EED_Single_Page_Checkout', 'sort_registrations_by_REG_count' ));
797
		// then loop thru the array
798
		foreach ( $registrations as $registration ) {
799
			// verify each registration
800
			if ( $registration instanceof EE_Registration ) {
801
				// we display all attendee info for the primary registrant
802
				if ( $this->checkout->reg_url_link == $registration->reg_url_link() && $registration->is_primary_registrant() ) {
803
					$this->checkout->primary_revisit = TRUE;
804
					break;
805
				} else if ( $this->checkout->revisit && $this->checkout->reg_url_link != $registration->reg_url_link() ) {
806
					// but hide info if it doesn't belong to you
807
					$transaction->clear_cache( 'Registration', $registration->ID() );
808
				}
809
				$this->checkout->set_reg_status_updated( $registration->ID(), false );
810
			}
811
		}
812
	}
813
814
815
816
	/**
817
	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
818
	 *
819
	 * @access private
820
	 * @param EE_Transaction $transaction
821
	 * @return    array
822
	 */
823
	private function _initialize_registrations( EE_Transaction $transaction ) {
824
		$att_nmbr = 0;
825
		$registrations = array();
826
		if ( $transaction instanceof EE_Transaction ) {
827
			/** @type EE_Registration_Processor $registration_processor */
828
			$registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' );
829
			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->checkout->cart->a...ticket_quantity_count() can also be of type double. However, the property $total_ticket_count is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
830
			// now let's add the cart items to the $transaction
831
			foreach ( $this->checkout->cart->get_tickets() as $line_item ) {
832
				//do the following for each ticket of this type they selected
833
				for ( $x = 1; $x <= $line_item->quantity(); $x++ ) {
834
					$att_nmbr++;
835
					$registration = $registration_processor->generate_ONE_registration_from_line_item(
836
						$line_item,
837
						$transaction,
838
						$att_nmbr,
839
						$this->checkout->total_ticket_count
840
					);
841
					if ( $registration instanceof EE_Registration ) {
842
						$registrations[ $registration->ID() ] = $registration;
843
					}
844
				}
845
			}
846
			$registration_processor->fix_reg_final_price_rounding_issue( $transaction );
847
		}
848
		return $registrations;
849
	}
850
851
852
853
	/**
854
	 * sorts registrations by REG_count
855
	 *
856
	 * @access public
857
	 * @param EE_Registration $reg_A
858
	 * @param EE_Registration $reg_B
859
	 * @return array()
0 ignored issues
show
Documentation introduced by
The doc-type array() could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
860
	 */
861
	public static function sort_registrations_by_REG_count( EE_Registration $reg_A, EE_Registration $reg_B ) {
862
		// this shouldn't ever happen within the same TXN, but oh well
863
		if ( $reg_A->count() == $reg_B->count() ) {
864
			return 0;
865
		}
866
		return ( $reg_A->count() > $reg_B->count() ) ? 1 : -1;
867
	}
868
869
870
871
	/**
872
	 * 	_final_verifications
873
	 *
874
	 * just makes sure that everything is set up correctly before proceeding
875
	 *
876
	 *  @access 	private
877
	 *  @return 	bool
878
	 */
879
	private function _final_verifications() {
880
		// filter checkout
881
		$this->checkout = apply_filters( 'FHEE__EED_Single_Page_Checkout___final_verifications__checkout', $this->checkout );
882
		//verify that current step is still set correctly
883
		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step ) {
884
			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__ );
885
			return false;
886
		}
887
		// if returning to SPCO, then verify that primary registrant is set
888
		if ( ! empty( $this->checkout->reg_url_link )) {
889
			$valid_registrant = $this->checkout->transaction->primary_registration();
890 View Code Duplication
			if ( ! $valid_registrant instanceof EE_Registration ) {
891
				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__ );
892
				return false;
893
			}
894
			$valid_registrant = null;
895
			foreach ( $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params ) as $registration ) {
896
				if ( $registration instanceof EE_Registration ) {
897
					if ( $registration->reg_url_link() == $this->checkout->reg_url_link ) {
898
						$valid_registrant = $registration;
899
					}
900
				}
901
			}
902 View Code Duplication
			if ( ! $valid_registrant instanceof EE_Registration ) {
903
				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__ );
904
				return false;
905
			}
906
		}
907
		// now that things have been kinda sufficiently verified,
908
		// let's add the checkout to the session so that's available other systems
909
		EE_Registry::instance()->SSN->set_checkout( $this->checkout );
910
		return true;
911
	}
912
913
914
915
916
	/**
917
	 *    _initialize_reg_steps
918
	 *
919
	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
920
	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
921
	 *
922
	 * @access    private
923
	 * @param bool $reinitializing
924
	 */
925
	private function _initialize_reg_steps( $reinitializing = false ) {
926
		$this->checkout->set_reg_step_initiated( $this->checkout->current_step );
927
		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
928
		foreach ( $this->checkout->reg_steps as $reg_step ) {
929
			if ( ! $reg_step->initialize_reg_step() ) {
930
				// if not initialized then maybe this step is being removed...
931
				if ( $reg_step->is_current_step() && ! $reinitializing ) {
932
					// if it was the current step, then we need to start over here
933
					$this->_initialize_reg_steps( true );
934
					return;
935
				}
936
				continue;
937
			}
938
			// i18n
939
			$reg_step->translate_js_strings();
940
			if ( $reg_step->is_current_step() ) {
941
				// the text that appears on the reg step form submit button
942
				$reg_step->set_submit_button_text();
943
			}
944
		}
945
		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
946
		do_action( "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}", $this->checkout->current_step );
947
	}
948
949
950
951
	/**
952
	 * _check_form_submission
953
	 *
954
	 * @access private
955
	 * 	@return void
956
	 */
957
	private function _check_form_submission() {
958
		//does this request require the reg form to be generated ?
959
		if ( $this->checkout->generate_reg_form ) {
960
			// ever heard that song by Blue Rodeo ?
961
			try {
962
				$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...
963
				// if not displaying a form, then check for form submission
964
				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...
965
					// clear out any old data in case this step is being run again
966
					$this->checkout->current_step->set_valid_data( array() );
967
					// capture submitted form data
968
					$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...
969
						apply_filters( 'FHEE__Single_Page_Checkout___check_form_submission__request_params', EE_Registry::instance()->REQ->params(), $this->checkout )
970
					);
971
					// validate submitted form data
972
					if ( ! $this->checkout->current_step->reg_form->is_valid() || ! $this->checkout->continue_reg ) {
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...
973
						// thou shall not pass !!!
974
						$this->checkout->continue_reg = FALSE;
975
						// any form validation errors?
976
						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...
977
							$submission_error_messages = array();
978
							// bad, bad, bad registrant
979
							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...
980 View Code Duplication
								if ( $validation_error instanceof EE_Validation_Error ) {
981
									$submission_error_messages[] = sprintf( __( '%s : %s', 'event_espresso' ), $validation_error->get_form_section()->html_label_text(), $validation_error->getMessage() );
982
								}
983
							}
984
							EE_Error::add_error( join( '<br />', $submission_error_messages ), __FILE__, __FUNCTION__, __LINE__ );
985
						}
986
						// well not really... what will happen is we'll just get redirected back to redo the current step
987
						$this->go_to_next_step();
988
						return;
989
					}
990
				}
991
			} catch( EE_Error $e ) {
992
				$e->get_error();
993
			}
994
		}
995
	}
996
997
998
999
	/**
1000
	 * _process_action
1001
	 *
1002
	 * @access private
1003
	 * 	@return void
1004
	 */
1005
	private function _process_form_action() {
1006
		// what cha wanna do?
1007
		switch( $this->checkout->action ) {
1008
			// AJAX next step reg form
1009
			case 'display_spco_reg_step' :
1010
				$this->checkout->redirect = FALSE;
1011
				if ( EE_Registry::instance()->REQ->ajax ) {
1012
					$this->checkout->json_response->set_reg_step_html( $this->checkout->current_step->display_reg_form() );
1013
				}
1014
				break;
1015
1016
			default :
1017
				// meh... do one of those other steps first
1018
				if ( ! empty( $this->checkout->action ) && is_callable( array( $this->checkout->current_step, $this->checkout->action ))) {
1019
					// dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1020
					do_action( "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step );
1021
					// call action on current step
1022
					if ( call_user_func( array( $this->checkout->current_step, $this->checkout->action )) ) {
1023
						// good registrant, you get to proceed
1024
						if ( $this->checkout->current_step->success_message() != '' ) {
1025
							if ( apply_filters( 'FHEE__Single_Page_Checkout___process_form_action__display_success', false ) ) {
1026
								EE_Error::add_success( $this->checkout->current_step->success_message() . '<br />' . $this->checkout->next_step->_instructions() );
1027
							}
1028
						}
1029
						// pack it up, pack it in...
1030
						$this->_setup_redirect();
1031
					}
1032
					// dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1033
					do_action( "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step );
1034
1035
				} else {
1036
					EE_Error::add_error(
1037
						sprintf(
1038
							__( 'The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso' ),
1039
							$this->checkout->action,
1040
							$this->checkout->current_step->name()
1041
						),
1042
						__FILE__, __FUNCTION__, __LINE__
1043
					);
1044
				}
1045
			// end default
1046
		}
1047
		// store our progress so far
1048
		$this->checkout->stash_transaction_and_checkout();
1049
		// advance to the next step! If you pass GO, collect $200
1050
		$this->go_to_next_step();
1051
	}
1052
1053
1054
1055
	/**
1056
	 * 		add_styles_and_scripts
1057
	 *
1058
	 * 		@access 		public
1059
	 * 		@return 		void
1060
	 */
1061
	public function add_styles_and_scripts() {
1062
		// i18n
1063
		$this->translate_js_strings();
1064
		if ( $this->checkout->admin_request ) {
1065
			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10 );
1066
		} else {
1067
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles_and_scripts' ), 10 );
1068
		}
1069
	}
1070
1071
1072
1073
	/**
1074
	 * 		translate_js_strings
1075
	 *
1076
	 * 		@access 		public
1077
	 * 		@return 		void
1078
	 */
1079
	public function translate_js_strings() {
1080
		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1081
		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1082
		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');
1083
		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' );
1084
		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' );
1085
		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' );
1086
		EE_Registry::$i18n_js_strings['reg_step_error'] = __('This registration step could not be completed. Please refresh the page and try again.', 'event_espresso');
1087
		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');
1088
		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/>' );
1089
		EE_Registry::$i18n_js_strings['language'] = get_bloginfo( 'language' );
1090
		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1091
		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1092
		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1093
		EE_Registry::$i18n_js_strings['timer_years'] = __( 'years', 'event_espresso' );
1094
		EE_Registry::$i18n_js_strings['timer_months'] = __( 'months', 'event_espresso' );
1095
		EE_Registry::$i18n_js_strings['timer_weeks'] = __( 'weeks', 'event_espresso' );
1096
		EE_Registry::$i18n_js_strings['timer_days'] = __( 'days', 'event_espresso' );
1097
		EE_Registry::$i18n_js_strings['timer_hours'] = __( 'hours', 'event_espresso' );
1098
		EE_Registry::$i18n_js_strings['timer_minutes'] = __( 'minutes', 'event_espresso' );
1099
		EE_Registry::$i18n_js_strings['timer_seconds'] = __( 'seconds', 'event_espresso' );
1100
		EE_Registry::$i18n_js_strings['timer_year'] = __( 'year', 'event_espresso' );
1101
		EE_Registry::$i18n_js_strings['timer_month'] = __( 'month', 'event_espresso' );
1102
		EE_Registry::$i18n_js_strings['timer_week'] = __( 'week', 'event_espresso' );
1103
		EE_Registry::$i18n_js_strings['timer_day'] = __( 'day', 'event_espresso' );
1104
		EE_Registry::$i18n_js_strings['timer_hour'] = __( 'hour', 'event_espresso' );
1105
		EE_Registry::$i18n_js_strings['timer_minute'] = __( 'minute', 'event_espresso' );
1106
		EE_Registry::$i18n_js_strings['timer_second'] = __( 'second', 'event_espresso' );
1107
		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1108
			__( '%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' ),
1109
			'<h4 class="important-notice">',
1110
			'</h4>',
1111
			'<br />',
1112
			'<p>',
1113
			'<a href="'. get_post_type_archive_link( 'espresso_events' ) . '" title="',
1114
			'">',
1115
			'</a>',
1116
			'</p>'
1117
		);
1118
		EE_Registry::$i18n_js_strings[ 'ajax_submit' ] = apply_filters( 'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', true );
1119
	}
1120
1121
1122
1123
	/**
1124
	 * 	enqueue_styles_and_scripts
1125
	 *
1126
	 * 	@access 		public
1127
	 * 	@return 		void
1128
	 */
1129
	public function enqueue_styles_and_scripts() {
1130
		// load css
1131
		wp_register_style( 'single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION );
1132
		wp_enqueue_style( 'single_page_checkout' );
1133
		// load JS
1134
		wp_register_script( 'jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array( 'jquery' ), '1.0.1', TRUE );
1135
		wp_register_script( 'jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array( 'jquery_plugin' ), '2.0.2', TRUE );
1136
		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 );
1137
		wp_enqueue_script( 'single_page_checkout' );
1138
1139
		/**
1140
		 * global action hook for enqueueing styles and scripts with
1141
		 * spco calls.
1142
		 */
1143
		do_action( 'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this );
1144
1145
		/**
1146
		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1147
		 * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1148
		 */
1149
		do_action( 'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this );
1150
1151
		// add css and JS for current step
1152
		$this->checkout->current_step->enqueue_styles_and_scripts();
1153
	}
1154
1155
1156
1157
	/**
1158
	 * 	display the Registration Single Page Checkout Form
1159
	 *
1160
	 * @access 	private
1161
	 * @return 	void
1162
	 */
1163
	private function _display_spco_reg_form() {
1164
		// if registering via the admin, just display the reg form for the current step
1165
		if ( $this->checkout->admin_request ) {
1166
			EE_Registry::instance()->REQ->add_output( $this->checkout->current_step->display_reg_form() );
1167
		} else {
1168
			// add powered by EE msg
1169
			add_action( 'AHEE__SPCO__reg_form_footer', array( 'EED_Single_Page_Checkout', 'display_registration_footer' ));
1170
1171
			$empty_cart = count( $this->checkout->transaction->registrations( $this->checkout->reg_cache_where_params ) ) < 1 ? true : false;
1172
			$cookies_not_set_msg = '';
1173
			if ( $empty_cart ) {
1174
				if ( ! isset( $_COOKIE[ 'ee_cookie_test' ] ) ) {
1175
					$cookies_not_set_msg = apply_filters(
1176
						'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1177
						sprintf(
1178
							__( '%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' ),
1179
							'<div class="ee-attention">',
1180
							'</div>',
1181
							'<h6 class="important-notice">',
1182
							'</h6>',
1183
							'<p>',
1184
							'</p>',
1185
							'<br />',
1186
							'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1187
							'</a>'
1188
						)
1189
					);
1190
				}
1191
			}
1192
			$this->checkout->registration_form = new EE_Form_Section_Proper(
1193
				array(
1194
					'name' 	=> 'single-page-checkout',
1195
					'html_id' 	=> 'ee-single-page-checkout-dv',
1196
					'layout_strategy' =>
1197
						new EE_Template_Layout(
1198
							array(
1199
								'layout_template_file' 			=> SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1200
								'template_args' => array(
1201
									'empty_cart' 		=> $empty_cart,
1202
									'revisit' 				=> $this->checkout->revisit,
1203
									'reg_steps' 			=> $this->checkout->reg_steps,
1204
									'next_step' 			=>  $this->checkout->next_step instanceof EE_SPCO_Reg_Step ? $this->checkout->next_step->slug() : '',
1205
									'empty_msg' 		=> apply_filters(
1206
										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1207
										sprintf(
1208
											__( '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' ),
1209
											'<a href="' . get_post_type_archive_link( 'espresso_events' ) . '" title="',
1210
											'">',
1211
											'</a>'
1212
										)
1213
									),
1214
									'cookies_not_set_msg' 		=> $cookies_not_set_msg,
1215
									'registration_time_limit' 	=> $this->checkout->get_registration_time_limit(),
1216
									'session_expiration' 			=>
1217
										gmdate( 'M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) )
1218
							)
1219
						)
1220
					)
1221
				)
1222
			);
1223
			// load template and add to output sent that gets filtered into the_content()
1224
			EE_Registry::instance()->REQ->add_output( $this->checkout->registration_form->get_html_and_js() );
1225
		}
1226
	}
1227
1228
1229
1230
	/**
1231
	 *    add_extra_finalize_registration_inputs
1232
	 *
1233
	 * @access    public
1234
	 * @param $next_step
1235
	 * @internal  param string $label
1236
	 * @return        string
1237
	 */
1238
	public function add_extra_finalize_registration_inputs( $next_step ) {
1239
		if ( $next_step == 'finalize_registration' ) {
1240
			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1241
		}
1242
	}
1243
1244
1245
1246
	/**
1247
	 * 	display_registration_footer
1248
	 *
1249
	 *  @access 	public
1250
	 *  @return 	string
1251
	 */
1252
	public static function display_registration_footer() {
1253
		if ( apply_filters( 'FHEE__EE_Front__Controller__show_reg_footer', EE_Registry::instance()->CFG->admin->show_reg_footer ) ) {
1254
			EE_Registry::instance()->CFG->admin->affiliate_id = ! empty( EE_Registry::instance()->CFG->admin->affiliate_id ) ? EE_Registry::instance()->CFG->admin->affiliate_id : 'default';
1255
			$url = add_query_arg( array( 'ap_id' => EE_Registry::instance()->CFG->admin->affiliate_id ), 'https://eventespresso.com/' );
1256
			$url = apply_filters( 'FHEE__EE_Front_Controller__registration_footer__url', $url );
1257
			echo apply_filters(
1258
				'FHEE__EE_Front_Controller__display_registration_footer',
1259
				sprintf(
1260
					__( '%1$sEvent Registration Powered by Event Espresso%2$sEvent Registration and Ticketing%3$s Powered by %4$sEvent Espresso - Event Registration and Management System for WordPress%5$sEvent Espresso%6$s', 'event_espresso' ),
1261
					'<div id="espresso-registration-footer-dv"><a href="' . $url . '" title="',
1262
					'" target="_blank">',
1263
					'</a>',
1264
					'<a href="' . $url . '" title="',
1265
					'" target="_blank">',
1266
					'</a></div>'
1267
				)
1268
			);
1269
		}
1270
	}
1271
1272
1273
1274
1275
	/**
1276
	 * 	unlock_transaction
1277
	 *
1278
	 * @access 	public
1279
	 * @return 	void
1280
	 */
1281
	public function unlock_transaction() {
1282
		$this->checkout->transaction->unlock();
1283
	}
1284
1285
1286
1287
1288
	/**
1289
	 *        _setup_redirect
1290
	 *
1291
	 * @access 	private
1292
	 * @return 	array
1293
	 */
1294
	private function _setup_redirect() {
1295
		if ( $this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step ) {
1296
			$this->checkout->redirect = TRUE;
1297
			if ( empty( $this->checkout->redirect_url )) {
1298
				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1299
			}
1300
			$this->checkout->redirect_url = apply_filters( 'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url', $this->checkout->redirect_url, $this->checkout );
1301
		}
1302
	}
1303
1304
1305
1306
	/**
1307
	 *   handle ajax message responses and redirects
1308
	 *
1309
	 * @access public
1310
	 * @return void
1311
	 */
1312
	public function go_to_next_step() {
1313
		if ( EE_Registry::instance()->REQ->ajax ) {
1314
			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1315
			$this->checkout->json_response->set_unexpected_errors( ob_get_clean() );
1316
		}
1317
		// just return for these conditions
1318
		if ( $this->checkout->admin_request || $this->checkout->action == 'redirect_form' || $this->checkout->action == 'update_checkout' ) {
1319
			return;
1320
		}
1321
		// AJAX response
1322
		$this->_handle_json_response();
1323
		// redirect to next step or the Thank You page
1324
		$this->_handle_html_redirects();
1325
		// hmmm... must be something wrong, so let's just display the form again !
1326
		$this->_display_spco_reg_form();
1327
	}
1328
1329
1330
1331
	/**
1332
	 *   _handle_json_response
1333
	 *
1334
	 * @access protected
1335
	 * @return void
1336
	 */
1337
	protected function _handle_json_response() {
1338
		// if this is an ajax request
1339
		if ( EE_Registry::instance()->REQ->ajax ) {
1340
			// DEBUG LOG
1341
			//$this->checkout->log(
1342
			//	__CLASS__, __FUNCTION__, __LINE__,
1343
			//	array(
1344
			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1345
			//		'redirect'                   => $this->checkout->redirect,
1346
			//		'continue_reg'               => $this->checkout->continue_reg,
1347
			//	)
1348
			//);
1349
			$this->checkout->json_response->set_registration_time_limit( $this->checkout->get_registration_time_limit() );
1350
			$this->checkout->json_response->set_payment_amount( $this->checkout->amount_owing );
1351
			// just send the ajax (
1352
			$json_response = apply_filters( 'FHEE__EE_Single_Page_Checkout__JSON_response', $this->checkout->json_response );
1353
			$this->unlock_transaction();
1354
			echo $json_response;
1355
			exit();
1356
		}
1357
	}
1358
1359
1360
1361
	/**
1362
	 *   _handle_redirects
1363
	 *
1364
	 * @access protected
1365
	 * @return void
1366
	 */
1367
	protected function _handle_html_redirects() {
1368
		// going somewhere ?
1369
		if ( $this->checkout->redirect && ! empty( $this->checkout->redirect_url ) ) {
1370
			// store notices in a transient
1371
			EE_Error::get_notices( false, true, true );
1372
			$this->unlock_transaction();
1373
			// DEBUG LOG
1374
			//$this->checkout->log(
1375
			//	__CLASS__, __FUNCTION__, __LINE__,
1376
			//	array(
1377
			//		'headers_sent' => headers_sent(),
1378
			//		'redirect_url'     => $this->checkout->redirect_url,
1379
			//		'headers_list'    => headers_list(),
1380
			//	)
1381
			//);
1382
			wp_safe_redirect( $this->checkout->redirect_url );
1383
			exit();
1384
		}
1385
	}
1386
1387
1388
1389
	/**
1390
	 *   set_checkout_anchor
1391
	 *
1392
	 * @access public
1393
	 * @return string
1394
	 */
1395
	public function set_checkout_anchor() {
1396
		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1397
	}
1398
1399
1400
1401
}
1402
// End of file EED_Single_Page_Checkout.module.php
1403
// Location: /modules/single_page_checkout/EED_Single_Page_Checkout.module.php
1404