Completed
Branch BUG-10911-php-7.2 (ef442d)
by
unknown
104:08 queued 92:42
created
core/EE_Front_Controller.core.php 1 patch
Indentation   +499 added lines, -499 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\widgets\EspressoWidget;
9 9
 
10 10
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
11
-    exit('No direct script access allowed');
11
+	exit('No direct script access allowed');
12 12
 }
13 13
 
14 14
 /**
@@ -31,405 +31,405 @@  discard block
 block discarded – undo
31 31
 final class EE_Front_Controller
32 32
 {
33 33
 
34
-    /**
35
-     * @var string $_template_path
36
-     */
37
-    private $_template_path;
38
-
39
-    /**
40
-     * @var string $_template
41
-     */
42
-    private $_template;
43
-
44
-    /**
45
-     * @type EE_Registry $Registry
46
-     */
47
-    protected $Registry;
48
-
49
-    /**
50
-     * @type EE_Request_Handler $Request_Handler
51
-     */
52
-    protected $Request_Handler;
53
-
54
-    /**
55
-     * @type EE_Module_Request_Router $Module_Request_Router
56
-     */
57
-    protected $Module_Request_Router;
58
-
59
-    /**
60
-     * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
61
-     */
62
-    private $persistent_admin_notice_manager;
63
-
64
-
65
-    /**
66
-     *    class constructor
67
-     *    should fire after shortcode, module, addon, or other plugin's default priority init phases have run
68
-     *
69
-     * @access    public
70
-     * @param \EE_Registry              $Registry
71
-     * @param \EE_Request_Handler       $Request_Handler
72
-     * @param \EE_Module_Request_Router $Module_Request_Router
73
-     */
74
-    public function __construct(
75
-        EE_Registry $Registry,
76
-        EE_Request_Handler $Request_Handler,
77
-        EE_Module_Request_Router $Module_Request_Router
78
-    ) {
79
-        $this->Registry              = $Registry;
80
-        $this->Request_Handler       = $Request_Handler;
81
-        $this->Module_Request_Router = $Module_Request_Router;
82
-        // determine how to integrate WP_Query with the EE models
83
-        add_action('AHEE__EE_System__initialize', array($this, 'employ_CPT_Strategy'));
84
-        // just in case any nag notices are created during the request
85
-        add_action('AHEE__EE_System__initialize_last', array($this, 'loadPersistentAdminNoticeManager'));
86
-        // load other resources and begin to actually run shortcodes and modules
87
-        add_action('wp_loaded', array($this, 'wp_loaded'), 5);
88
-        // analyse the incoming WP request
89
-        add_action('parse_request', array($this, 'get_request'), 1, 1);
90
-        // process request with module factory
91
-        add_action('pre_get_posts', array($this, 'pre_get_posts'), 10, 1);
92
-        // before headers sent
93
-        add_action('wp', array($this, 'wp'), 5);
94
-        // primarily used to process any content shortcodes
95
-        add_action('template_redirect', array($this, 'templateRedirect'), 999);
96
-        // header
97
-        add_action('wp_head', array($this, 'header_meta_tag'), 5);
98
-        add_action('wp_print_scripts', array($this, 'wp_print_scripts'), 10);
99
-        add_filter('template_include', array($this, 'template_include'), 1);
100
-        // display errors
101
-        add_action('loop_start', array($this, 'display_errors'), 2);
102
-        // the content
103
-        // add_filter( 'the_content', array( $this, 'the_content' ), 5, 1 );
104
-        //exclude our private cpt comments
105
-        add_filter('comments_clauses', array($this, 'filter_wp_comments'), 10, 1);
106
-        //make sure any ajax requests will respect the url schema when requests are made against admin-ajax.php (http:// or https://)
107
-        add_filter('admin_url', array($this, 'maybe_force_admin_ajax_ssl'), 200, 1);
108
-        // action hook EE
109
-        do_action('AHEE__EE_Front_Controller__construct__done', $this);
110
-        // for checking that browser cookies are enabled
111
-        if (apply_filters('FHEE__EE_Front_Controller____construct__set_test_cookie', true)) {
112
-            setcookie('ee_cookie_test', uniqid('ect',true), time() + DAY_IN_SECONDS, '/');
113
-        }
114
-    }
115
-
116
-
117
-    /**
118
-     * @return EE_Request_Handler
119
-     */
120
-    public function Request_Handler()
121
-    {
122
-        return $this->Request_Handler;
123
-    }
124
-
125
-
126
-    /**
127
-     * @return EE_Module_Request_Router
128
-     */
129
-    public function Module_Request_Router()
130
-    {
131
-        return $this->Module_Request_Router;
132
-    }
133
-
134
-
135
-
136
-    /**
137
-     * @return LegacyShortcodesManager
138
-     */
139
-    public function getLegacyShortcodesManager()
140
-    {
141
-        return EE_Config::getLegacyShortcodesManager();
142
-    }
143
-
144
-
145
-
146
-
147
-
148
-    /***********************************************        INIT ACTION HOOK         ***********************************************/
149
-
150
-
151
-
152
-    /**
153
-     * filter_wp_comments
154
-     * This simply makes sure that any "private" EE CPTs do not have their comments show up in any wp comment
155
-     * widgets/queries done on frontend
156
-     *
157
-     * @param  array $clauses array of comment clauses setup by WP_Comment_Query
158
-     * @return array array of comment clauses with modifications.
159
-     */
160
-    public function filter_wp_comments($clauses)
161
-    {
162
-        global $wpdb;
163
-        if (strpos($clauses['join'], $wpdb->posts) !== false) {
164
-            $cpts = EE_Register_CPTs::get_private_CPTs();
165
-            foreach ($cpts as $cpt => $details) {
166
-                $clauses['where'] .= $wpdb->prepare(" AND $wpdb->posts.post_type != %s", $cpt);
167
-            }
168
-        }
169
-        return $clauses;
170
-    }
171
-
172
-
173
-    /**
174
-     * @return void
175
-     * @throws EE_Error
176
-     * @throws ReflectionException
177
-     */
178
-    public function employ_CPT_Strategy()
179
-    {
180
-        if (apply_filters('FHEE__EE_Front_Controller__employ_CPT_Strategy', true)) {
181
-            $this->Registry->load_core('CPT_Strategy');
182
-        }
183
-    }
184
-
185
-
186
-    /**
187
-     * @return void
188
-     * @throws InvalidArgumentException
189
-     * @throws InvalidDataTypeException
190
-     * @throws InvalidInterfaceException
191
-     */
192
-    public function loadPersistentAdminNoticeManager()
193
-    {
194
-        $this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
195
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
196
-        );
197
-    }
198
-
199
-
200
-    /**
201
-     * this just makes sure that if the site is using ssl that we force that for any admin ajax calls from frontend
202
-     *
203
-     * @param  string $url incoming url
204
-     * @return string         final assembled url
205
-     */
206
-    public function maybe_force_admin_ajax_ssl($url)
207
-    {
208
-        if (is_ssl() && preg_match('/admin-ajax.php/', $url)) {
209
-            $url = str_replace('http://', 'https://', $url);
210
-        }
211
-        return $url;
212
-    }
34
+	/**
35
+	 * @var string $_template_path
36
+	 */
37
+	private $_template_path;
38
+
39
+	/**
40
+	 * @var string $_template
41
+	 */
42
+	private $_template;
43
+
44
+	/**
45
+	 * @type EE_Registry $Registry
46
+	 */
47
+	protected $Registry;
48
+
49
+	/**
50
+	 * @type EE_Request_Handler $Request_Handler
51
+	 */
52
+	protected $Request_Handler;
53
+
54
+	/**
55
+	 * @type EE_Module_Request_Router $Module_Request_Router
56
+	 */
57
+	protected $Module_Request_Router;
58
+
59
+	/**
60
+	 * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
61
+	 */
62
+	private $persistent_admin_notice_manager;
63
+
64
+
65
+	/**
66
+	 *    class constructor
67
+	 *    should fire after shortcode, module, addon, or other plugin's default priority init phases have run
68
+	 *
69
+	 * @access    public
70
+	 * @param \EE_Registry              $Registry
71
+	 * @param \EE_Request_Handler       $Request_Handler
72
+	 * @param \EE_Module_Request_Router $Module_Request_Router
73
+	 */
74
+	public function __construct(
75
+		EE_Registry $Registry,
76
+		EE_Request_Handler $Request_Handler,
77
+		EE_Module_Request_Router $Module_Request_Router
78
+	) {
79
+		$this->Registry              = $Registry;
80
+		$this->Request_Handler       = $Request_Handler;
81
+		$this->Module_Request_Router = $Module_Request_Router;
82
+		// determine how to integrate WP_Query with the EE models
83
+		add_action('AHEE__EE_System__initialize', array($this, 'employ_CPT_Strategy'));
84
+		// just in case any nag notices are created during the request
85
+		add_action('AHEE__EE_System__initialize_last', array($this, 'loadPersistentAdminNoticeManager'));
86
+		// load other resources and begin to actually run shortcodes and modules
87
+		add_action('wp_loaded', array($this, 'wp_loaded'), 5);
88
+		// analyse the incoming WP request
89
+		add_action('parse_request', array($this, 'get_request'), 1, 1);
90
+		// process request with module factory
91
+		add_action('pre_get_posts', array($this, 'pre_get_posts'), 10, 1);
92
+		// before headers sent
93
+		add_action('wp', array($this, 'wp'), 5);
94
+		// primarily used to process any content shortcodes
95
+		add_action('template_redirect', array($this, 'templateRedirect'), 999);
96
+		// header
97
+		add_action('wp_head', array($this, 'header_meta_tag'), 5);
98
+		add_action('wp_print_scripts', array($this, 'wp_print_scripts'), 10);
99
+		add_filter('template_include', array($this, 'template_include'), 1);
100
+		// display errors
101
+		add_action('loop_start', array($this, 'display_errors'), 2);
102
+		// the content
103
+		// add_filter( 'the_content', array( $this, 'the_content' ), 5, 1 );
104
+		//exclude our private cpt comments
105
+		add_filter('comments_clauses', array($this, 'filter_wp_comments'), 10, 1);
106
+		//make sure any ajax requests will respect the url schema when requests are made against admin-ajax.php (http:// or https://)
107
+		add_filter('admin_url', array($this, 'maybe_force_admin_ajax_ssl'), 200, 1);
108
+		// action hook EE
109
+		do_action('AHEE__EE_Front_Controller__construct__done', $this);
110
+		// for checking that browser cookies are enabled
111
+		if (apply_filters('FHEE__EE_Front_Controller____construct__set_test_cookie', true)) {
112
+			setcookie('ee_cookie_test', uniqid('ect',true), time() + DAY_IN_SECONDS, '/');
113
+		}
114
+	}
115
+
116
+
117
+	/**
118
+	 * @return EE_Request_Handler
119
+	 */
120
+	public function Request_Handler()
121
+	{
122
+		return $this->Request_Handler;
123
+	}
124
+
125
+
126
+	/**
127
+	 * @return EE_Module_Request_Router
128
+	 */
129
+	public function Module_Request_Router()
130
+	{
131
+		return $this->Module_Request_Router;
132
+	}
133
+
134
+
135
+
136
+	/**
137
+	 * @return LegacyShortcodesManager
138
+	 */
139
+	public function getLegacyShortcodesManager()
140
+	{
141
+		return EE_Config::getLegacyShortcodesManager();
142
+	}
143
+
144
+
145
+
146
+
147
+
148
+	/***********************************************        INIT ACTION HOOK         ***********************************************/
149
+
150
+
151
+
152
+	/**
153
+	 * filter_wp_comments
154
+	 * This simply makes sure that any "private" EE CPTs do not have their comments show up in any wp comment
155
+	 * widgets/queries done on frontend
156
+	 *
157
+	 * @param  array $clauses array of comment clauses setup by WP_Comment_Query
158
+	 * @return array array of comment clauses with modifications.
159
+	 */
160
+	public function filter_wp_comments($clauses)
161
+	{
162
+		global $wpdb;
163
+		if (strpos($clauses['join'], $wpdb->posts) !== false) {
164
+			$cpts = EE_Register_CPTs::get_private_CPTs();
165
+			foreach ($cpts as $cpt => $details) {
166
+				$clauses['where'] .= $wpdb->prepare(" AND $wpdb->posts.post_type != %s", $cpt);
167
+			}
168
+		}
169
+		return $clauses;
170
+	}
171
+
172
+
173
+	/**
174
+	 * @return void
175
+	 * @throws EE_Error
176
+	 * @throws ReflectionException
177
+	 */
178
+	public function employ_CPT_Strategy()
179
+	{
180
+		if (apply_filters('FHEE__EE_Front_Controller__employ_CPT_Strategy', true)) {
181
+			$this->Registry->load_core('CPT_Strategy');
182
+		}
183
+	}
184
+
185
+
186
+	/**
187
+	 * @return void
188
+	 * @throws InvalidArgumentException
189
+	 * @throws InvalidDataTypeException
190
+	 * @throws InvalidInterfaceException
191
+	 */
192
+	public function loadPersistentAdminNoticeManager()
193
+	{
194
+		$this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
195
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
196
+		);
197
+	}
198
+
199
+
200
+	/**
201
+	 * this just makes sure that if the site is using ssl that we force that for any admin ajax calls from frontend
202
+	 *
203
+	 * @param  string $url incoming url
204
+	 * @return string         final assembled url
205
+	 */
206
+	public function maybe_force_admin_ajax_ssl($url)
207
+	{
208
+		if (is_ssl() && preg_match('/admin-ajax.php/', $url)) {
209
+			$url = str_replace('http://', 'https://', $url);
210
+		}
211
+		return $url;
212
+	}
213 213
 
214 214
 
215 215
 
216
-
217
-
218
-
219
-    /***********************************************        WP_LOADED ACTION HOOK         ***********************************************/
220
-
221
-
222
-    /**
223
-     *    wp_loaded - should fire after shortcode, module, addon, or other plugin's have been registered and their
224
-     *    default priority init phases have run
225
-     *
226
-     * @access    public
227
-     * @return    void
228
-     */
229
-    public function wp_loaded()
230
-    {
231
-    }
232
-
233
-
234
-
235
-
236
-
237
-    /***********************************************        PARSE_REQUEST HOOK         ***********************************************/
238
-    /**
239
-     *    _get_request
240
-     *
241
-     * @access public
242
-     * @param WP $WP
243
-     * @return void
244
-     */
245
-    public function get_request(WP $WP)
246
-    {
247
-        do_action('AHEE__EE_Front_Controller__get_request__start');
248
-        $this->Request_Handler->parse_request($WP);
249
-        do_action('AHEE__EE_Front_Controller__get_request__complete');
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     *    pre_get_posts - basically a module factory for instantiating modules and selecting the final view template
256
-     *
257
-     * @access    public
258
-     * @param   WP_Query $WP_Query
259
-     * @return    void
260
-     */
261
-    public function pre_get_posts($WP_Query)
262
-    {
263
-        // only load Module_Request_Router if this is the main query
264
-        if (
265
-            $this->Module_Request_Router instanceof EE_Module_Request_Router
266
-            && $WP_Query->is_main_query()
267
-        ) {
268
-            // cycle thru module routes
269
-            while ($route = $this->Module_Request_Router->get_route($WP_Query)) {
270
-                // determine module and method for route
271
-                $module = $this->Module_Request_Router->resolve_route($route[0], $route[1]);
272
-                if ($module instanceof EED_Module) {
273
-                    // get registered view for route
274
-                    $this->_template_path = $this->Module_Request_Router->get_view($route);
275
-                    // grab module name
276
-                    $module_name = $module->module_name();
277
-                    // map the module to the module objects
278
-                    $this->Registry->modules->{$module_name} = $module;
279
-                }
280
-            }
281
-        }
282
-    }
283
-
284
-
285
-
286
-
287
-
288
-    /***********************************************        WP HOOK         ***********************************************/
289
-
290
-
291
-    /**
292
-     *    wp - basically last chance to do stuff before headers sent
293
-     *
294
-     * @access    public
295
-     * @return    void
296
-     */
297
-    public function wp()
298
-    {
299
-    }
300
-
301
-
302
-
303
-    /***********************     GET_HEADER && WP_HEAD HOOK     ***********************/
304
-
305
-
306
-
307
-    /**
308
-     * callback for the "template_redirect" hook point
309
-     * checks sidebars for EE widgets
310
-     * loads resources and assets accordingly
311
-     *
312
-     * @return void
313
-     */
314
-    public function templateRedirect()
315
-    {
316
-        global $wp_query;
317
-        if (empty($wp_query->posts)){
318
-            return;
319
-        }
320
-        // if we already know this is an espresso page, then load assets
321
-        $load_assets = $this->Request_Handler->is_espresso_page();
322
-        // if we are already loading assets then just move along, otherwise check for widgets
323
-        $load_assets = $load_assets ? $load_assets : $this->espresso_widgets_in_active_sidebars();
324
-        if ( $load_assets){
325
-            add_action('wp_enqueue_scripts', array($this, 'enqueueStyle'), 10);
326
-            add_action('wp_print_footer_scripts', array($this, 'enqueueScripts'), 10);
327
-        }
328
-    }
329
-
330
-
331
-
332
-    /**
333
-     * builds list of active widgets then scans active sidebars looking for them
334
-     * returns true is an EE widget is found in an active sidebar
335
-     * Please Note: this does NOT mean that the sidebar or widget
336
-     * is actually in use in a given template, as that is unfortunately not known
337
-     * until a sidebar and it's widgets are actually loaded
338
-     *
339
-     * @return boolean
340
-     */
341
-    private function espresso_widgets_in_active_sidebars()
342
-    {
343
-        $espresso_widgets = array();
344
-        foreach ($this->Registry->widgets as $widget_class => $widget) {
345
-            $id_base = EspressoWidget::getIdBase($widget_class);
346
-            if (is_active_widget(false, false, $id_base)) {
347
-                $espresso_widgets[] = $id_base;
348
-            }
349
-        }
350
-        $all_sidebar_widgets = wp_get_sidebars_widgets();
351
-        foreach ($all_sidebar_widgets as $sidebar_name => $sidebar_widgets) {
352
-            if (is_array($sidebar_widgets) && ! empty($sidebar_widgets)) {
353
-                foreach ($sidebar_widgets as $sidebar_widget) {
354
-                    foreach ($espresso_widgets as $espresso_widget) {
355
-                        if (strpos($sidebar_widget, $espresso_widget) !== false) {
356
-                            return true;
357
-                        }
358
-                    }
359
-                }
360
-            }
361
-        }
362
-        return false;
363
-    }
364
-
365
-
366
-
367
-
368
-    /**
369
-     *    header_meta_tag
370
-     *
371
-     * @access    public
372
-     * @return    void
373
-     */
374
-    public function header_meta_tag()
375
-    {
376
-        print(
377
-            apply_filters(
378
-                'FHEE__EE_Front_Controller__header_meta_tag',
379
-                '<meta name="generator" content="Event Espresso Version ' . EVENT_ESPRESSO_VERSION . "\" />\n")
380
-        );
381
-
382
-        //let's exclude all event type taxonomy term archive pages from search engine indexing
383
-        //@see https://events.codebasehq.com/projects/event-espresso/tickets/10249
384
-        //also exclude all critical pages from indexing
385
-        if (
386
-            (
387
-                is_tax('espresso_event_type')
388
-                && get_option( 'blog_public' ) !== '0'
389
-            )
390
-            || is_page(EE_Registry::instance()->CFG->core->get_critical_pages_array())
391
-        ) {
392
-            print(
393
-                apply_filters(
394
-                    'FHEE__EE_Front_Controller__header_meta_tag__noindex_for_event_type',
395
-                    '<meta name="robots" content="noindex,follow" />' . "\n"
396
-                )
397
-            );
398
-        }
399
-    }
400
-
401
-
402
-
403
-    /**
404
-     * wp_print_scripts
405
-     *
406
-     * @return void
407
-     */
408
-    public function wp_print_scripts()
409
-    {
410
-        global $post;
411
-        if (
412
-            isset($post->EE_Event)
413
-            && $post->EE_Event instanceof EE_Event
414
-            && get_post_type() === 'espresso_events'
415
-            && is_singular()
416
-        ) {
417
-            \EEH_Schema::add_json_linked_data_for_event($post->EE_Event);
418
-        }
419
-    }
420
-
421
-
422
-
423
-    public function enqueueStyle()
424
-    {
425
-        wp_enqueue_style('espresso_default');
426
-        wp_enqueue_style('espresso_custom_css');
427
-    }
428
-
429
-
430
-
431
-
432
-    /***********************************************        THE_CONTENT FILTER HOOK         **********************************************
216
+
217
+
218
+
219
+	/***********************************************        WP_LOADED ACTION HOOK         ***********************************************/
220
+
221
+
222
+	/**
223
+	 *    wp_loaded - should fire after shortcode, module, addon, or other plugin's have been registered and their
224
+	 *    default priority init phases have run
225
+	 *
226
+	 * @access    public
227
+	 * @return    void
228
+	 */
229
+	public function wp_loaded()
230
+	{
231
+	}
232
+
233
+
234
+
235
+
236
+
237
+	/***********************************************        PARSE_REQUEST HOOK         ***********************************************/
238
+	/**
239
+	 *    _get_request
240
+	 *
241
+	 * @access public
242
+	 * @param WP $WP
243
+	 * @return void
244
+	 */
245
+	public function get_request(WP $WP)
246
+	{
247
+		do_action('AHEE__EE_Front_Controller__get_request__start');
248
+		$this->Request_Handler->parse_request($WP);
249
+		do_action('AHEE__EE_Front_Controller__get_request__complete');
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 *    pre_get_posts - basically a module factory for instantiating modules and selecting the final view template
256
+	 *
257
+	 * @access    public
258
+	 * @param   WP_Query $WP_Query
259
+	 * @return    void
260
+	 */
261
+	public function pre_get_posts($WP_Query)
262
+	{
263
+		// only load Module_Request_Router if this is the main query
264
+		if (
265
+			$this->Module_Request_Router instanceof EE_Module_Request_Router
266
+			&& $WP_Query->is_main_query()
267
+		) {
268
+			// cycle thru module routes
269
+			while ($route = $this->Module_Request_Router->get_route($WP_Query)) {
270
+				// determine module and method for route
271
+				$module = $this->Module_Request_Router->resolve_route($route[0], $route[1]);
272
+				if ($module instanceof EED_Module) {
273
+					// get registered view for route
274
+					$this->_template_path = $this->Module_Request_Router->get_view($route);
275
+					// grab module name
276
+					$module_name = $module->module_name();
277
+					// map the module to the module objects
278
+					$this->Registry->modules->{$module_name} = $module;
279
+				}
280
+			}
281
+		}
282
+	}
283
+
284
+
285
+
286
+
287
+
288
+	/***********************************************        WP HOOK         ***********************************************/
289
+
290
+
291
+	/**
292
+	 *    wp - basically last chance to do stuff before headers sent
293
+	 *
294
+	 * @access    public
295
+	 * @return    void
296
+	 */
297
+	public function wp()
298
+	{
299
+	}
300
+
301
+
302
+
303
+	/***********************     GET_HEADER && WP_HEAD HOOK     ***********************/
304
+
305
+
306
+
307
+	/**
308
+	 * callback for the "template_redirect" hook point
309
+	 * checks sidebars for EE widgets
310
+	 * loads resources and assets accordingly
311
+	 *
312
+	 * @return void
313
+	 */
314
+	public function templateRedirect()
315
+	{
316
+		global $wp_query;
317
+		if (empty($wp_query->posts)){
318
+			return;
319
+		}
320
+		// if we already know this is an espresso page, then load assets
321
+		$load_assets = $this->Request_Handler->is_espresso_page();
322
+		// if we are already loading assets then just move along, otherwise check for widgets
323
+		$load_assets = $load_assets ? $load_assets : $this->espresso_widgets_in_active_sidebars();
324
+		if ( $load_assets){
325
+			add_action('wp_enqueue_scripts', array($this, 'enqueueStyle'), 10);
326
+			add_action('wp_print_footer_scripts', array($this, 'enqueueScripts'), 10);
327
+		}
328
+	}
329
+
330
+
331
+
332
+	/**
333
+	 * builds list of active widgets then scans active sidebars looking for them
334
+	 * returns true is an EE widget is found in an active sidebar
335
+	 * Please Note: this does NOT mean that the sidebar or widget
336
+	 * is actually in use in a given template, as that is unfortunately not known
337
+	 * until a sidebar and it's widgets are actually loaded
338
+	 *
339
+	 * @return boolean
340
+	 */
341
+	private function espresso_widgets_in_active_sidebars()
342
+	{
343
+		$espresso_widgets = array();
344
+		foreach ($this->Registry->widgets as $widget_class => $widget) {
345
+			$id_base = EspressoWidget::getIdBase($widget_class);
346
+			if (is_active_widget(false, false, $id_base)) {
347
+				$espresso_widgets[] = $id_base;
348
+			}
349
+		}
350
+		$all_sidebar_widgets = wp_get_sidebars_widgets();
351
+		foreach ($all_sidebar_widgets as $sidebar_name => $sidebar_widgets) {
352
+			if (is_array($sidebar_widgets) && ! empty($sidebar_widgets)) {
353
+				foreach ($sidebar_widgets as $sidebar_widget) {
354
+					foreach ($espresso_widgets as $espresso_widget) {
355
+						if (strpos($sidebar_widget, $espresso_widget) !== false) {
356
+							return true;
357
+						}
358
+					}
359
+				}
360
+			}
361
+		}
362
+		return false;
363
+	}
364
+
365
+
366
+
367
+
368
+	/**
369
+	 *    header_meta_tag
370
+	 *
371
+	 * @access    public
372
+	 * @return    void
373
+	 */
374
+	public function header_meta_tag()
375
+	{
376
+		print(
377
+			apply_filters(
378
+				'FHEE__EE_Front_Controller__header_meta_tag',
379
+				'<meta name="generator" content="Event Espresso Version ' . EVENT_ESPRESSO_VERSION . "\" />\n")
380
+		);
381
+
382
+		//let's exclude all event type taxonomy term archive pages from search engine indexing
383
+		//@see https://events.codebasehq.com/projects/event-espresso/tickets/10249
384
+		//also exclude all critical pages from indexing
385
+		if (
386
+			(
387
+				is_tax('espresso_event_type')
388
+				&& get_option( 'blog_public' ) !== '0'
389
+			)
390
+			|| is_page(EE_Registry::instance()->CFG->core->get_critical_pages_array())
391
+		) {
392
+			print(
393
+				apply_filters(
394
+					'FHEE__EE_Front_Controller__header_meta_tag__noindex_for_event_type',
395
+					'<meta name="robots" content="noindex,follow" />' . "\n"
396
+				)
397
+			);
398
+		}
399
+	}
400
+
401
+
402
+
403
+	/**
404
+	 * wp_print_scripts
405
+	 *
406
+	 * @return void
407
+	 */
408
+	public function wp_print_scripts()
409
+	{
410
+		global $post;
411
+		if (
412
+			isset($post->EE_Event)
413
+			&& $post->EE_Event instanceof EE_Event
414
+			&& get_post_type() === 'espresso_events'
415
+			&& is_singular()
416
+		) {
417
+			\EEH_Schema::add_json_linked_data_for_event($post->EE_Event);
418
+		}
419
+	}
420
+
421
+
422
+
423
+	public function enqueueStyle()
424
+	{
425
+		wp_enqueue_style('espresso_default');
426
+		wp_enqueue_style('espresso_custom_css');
427
+	}
428
+
429
+
430
+
431
+
432
+	/***********************************************        THE_CONTENT FILTER HOOK         **********************************************
433 433
 
434 434
 
435 435
 
@@ -440,108 +440,108 @@  discard block
 block discarded – undo
440 440
     //  * @param   $the_content
441 441
     //  * @return    string
442 442
     //  */
443
-    // public function the_content( $the_content ) {
444
-    // 	// nothing gets loaded at this point unless other systems turn this hookpoint on by using:  add_filter( 'FHEE_run_EE_the_content', '__return_true' );
445
-    // 	if ( apply_filters( 'FHEE_run_EE_the_content', FALSE ) ) {
446
-    // 	}
447
-    // 	return $the_content;
448
-    // }
449
-
450
-
451
-
452
-    /***********************************************        WP_FOOTER         ***********************************************/
453
-
454
-
455
-
456
-    public function enqueueScripts()
457
-    {
458
-        wp_enqueue_script('espresso_core');
459
-    }
460
-
461
-
462
-
463
-    /**
464
-     * display_errors
465
-     *
466
-     * @access public
467
-     * @return void
468
-     * @throws DomainException
469
-     */
470
-    public function display_errors()
471
-    {
472
-        static $shown_already = false;
473
-        do_action('AHEE__EE_Front_Controller__display_errors__begin');
474
-        if (
475
-            ! $shown_already
476
-            && apply_filters('FHEE__EE_Front_Controller__display_errors', true)
477
-            && is_main_query()
478
-            && ! is_feed()
479
-            && in_the_loop()
480
-            && $this->Request_Handler->is_espresso_page()
481
-        ) {
482
-            echo EE_Error::get_notices();
483
-            $shown_already = true;
484
-            EEH_Template::display_template(EE_TEMPLATES . 'espresso-ajax-notices.template.php');
485
-        }
486
-        do_action('AHEE__EE_Front_Controller__display_errors__end');
487
-    }
488
-
489
-
490
-
491
-
492
-
493
-    /***********************************************        UTILITIES         ***********************************************/
494
-    /**
495
-     *    template_include
496
-     *
497
-     * @access    public
498
-     * @param   string $template_include_path
499
-     * @return    string
500
-     */
501
-    public function template_include($template_include_path = null)
502
-    {
503
-        if ($this->Request_Handler->is_espresso_page()) {
504
-            $this->_template_path = ! empty($this->_template_path) ? basename($this->_template_path) : basename($template_include_path);
505
-            $template_path        = EEH_Template::locate_template($this->_template_path, array(), false);
506
-            $this->_template_path = ! empty($template_path) ? $template_path : $template_include_path;
507
-            $this->_template      = basename($this->_template_path);
508
-            return $this->_template_path;
509
-        }
510
-        return $template_include_path;
511
-    }
512
-
513
-
514
-    /**
515
-     *    get_selected_template
516
-     *
517
-     * @access    public
518
-     * @param bool $with_path
519
-     * @return    string
520
-     */
521
-    public function get_selected_template($with_path = false)
522
-    {
523
-        return $with_path ? $this->_template_path : $this->_template;
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * @deprecated 4.9.26
530
-     * @param string $shortcode_class
531
-     * @param \WP    $wp
532
-     */
533
-    public function initialize_shortcode($shortcode_class = '', WP $wp = null)
534
-    {
535
-        \EE_Error::doing_it_wrong(
536
-            __METHOD__,
537
-            __(
538
-                'Usage is deprecated. Please use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::initializeShortcode() instead.',
539
-                'event_espresso'
540
-            ),
541
-            '4.9.26'
542
-        );
543
-        $this->getLegacyShortcodesManager()->initializeShortcode($shortcode_class, $wp);
544
-    }
443
+	// public function the_content( $the_content ) {
444
+	// 	// nothing gets loaded at this point unless other systems turn this hookpoint on by using:  add_filter( 'FHEE_run_EE_the_content', '__return_true' );
445
+	// 	if ( apply_filters( 'FHEE_run_EE_the_content', FALSE ) ) {
446
+	// 	}
447
+	// 	return $the_content;
448
+	// }
449
+
450
+
451
+
452
+	/***********************************************        WP_FOOTER         ***********************************************/
453
+
454
+
455
+
456
+	public function enqueueScripts()
457
+	{
458
+		wp_enqueue_script('espresso_core');
459
+	}
460
+
461
+
462
+
463
+	/**
464
+	 * display_errors
465
+	 *
466
+	 * @access public
467
+	 * @return void
468
+	 * @throws DomainException
469
+	 */
470
+	public function display_errors()
471
+	{
472
+		static $shown_already = false;
473
+		do_action('AHEE__EE_Front_Controller__display_errors__begin');
474
+		if (
475
+			! $shown_already
476
+			&& apply_filters('FHEE__EE_Front_Controller__display_errors', true)
477
+			&& is_main_query()
478
+			&& ! is_feed()
479
+			&& in_the_loop()
480
+			&& $this->Request_Handler->is_espresso_page()
481
+		) {
482
+			echo EE_Error::get_notices();
483
+			$shown_already = true;
484
+			EEH_Template::display_template(EE_TEMPLATES . 'espresso-ajax-notices.template.php');
485
+		}
486
+		do_action('AHEE__EE_Front_Controller__display_errors__end');
487
+	}
488
+
489
+
490
+
491
+
492
+
493
+	/***********************************************        UTILITIES         ***********************************************/
494
+	/**
495
+	 *    template_include
496
+	 *
497
+	 * @access    public
498
+	 * @param   string $template_include_path
499
+	 * @return    string
500
+	 */
501
+	public function template_include($template_include_path = null)
502
+	{
503
+		if ($this->Request_Handler->is_espresso_page()) {
504
+			$this->_template_path = ! empty($this->_template_path) ? basename($this->_template_path) : basename($template_include_path);
505
+			$template_path        = EEH_Template::locate_template($this->_template_path, array(), false);
506
+			$this->_template_path = ! empty($template_path) ? $template_path : $template_include_path;
507
+			$this->_template      = basename($this->_template_path);
508
+			return $this->_template_path;
509
+		}
510
+		return $template_include_path;
511
+	}
512
+
513
+
514
+	/**
515
+	 *    get_selected_template
516
+	 *
517
+	 * @access    public
518
+	 * @param bool $with_path
519
+	 * @return    string
520
+	 */
521
+	public function get_selected_template($with_path = false)
522
+	{
523
+		return $with_path ? $this->_template_path : $this->_template;
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * @deprecated 4.9.26
530
+	 * @param string $shortcode_class
531
+	 * @param \WP    $wp
532
+	 */
533
+	public function initialize_shortcode($shortcode_class = '', WP $wp = null)
534
+	{
535
+		\EE_Error::doing_it_wrong(
536
+			__METHOD__,
537
+			__(
538
+				'Usage is deprecated. Please use \EventEspresso\core\services\shortcodes\LegacyShortcodesManager::initializeShortcode() instead.',
539
+				'event_espresso'
540
+			),
541
+			'4.9.26'
542
+		);
543
+		$this->getLegacyShortcodesManager()->initializeShortcode($shortcode_class, $wp);
544
+	}
545 545
 
546 546
 }
547 547
 // End of file EE_Front_Controller.core.php
Please login to merge, or discard this patch.
core/db_classes/EE_Datetime.class.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -435,7 +435,7 @@  discard block
 block discarded – undo
435 435
 	 * @param string $dt_frmt     - string representation of date format defaults to WP settings
436 436
 	 * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
437 437
 	 *                            the end date ie: Jan 01 "to" Dec 31
438
-	 * @return mixed        string on success, FALSE on fail
438
+	 * @return string        string on success, FALSE on fail
439 439
 	 * @throws \EE_Error
440 440
 	 */
441 441
 	public function date_range( $dt_frmt = '', $conjunction = ' - ' ) {
@@ -507,7 +507,7 @@  discard block
 block discarded – undo
507 507
 	 * @param string $tm_format   string representation of time format defaults to 'g:i a'
508 508
 	 * @param string $conjunction conjunction junction what's your function ?
509 509
 	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
510
-	 * @return mixed              string on success, FALSE on fail
510
+	 * @return string              string on success, FALSE on fail
511 511
 	 * @throws \EE_Error
512 512
 	 */
513 513
 	public function time_range( $tm_format = '', $conjunction = ' - ' ) {
Please login to merge, or discard this patch.
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -210,13 +210,13 @@  discard block
 block discarded – undo
210 210
 		// remove ticket reservation
211 211
 		$this->decrease_reserved( $qty );
212 212
 		$this->set_sold( $sold );
213
-        do_action(
214
-            'AHEE__EE_Datetime__increase_sold',
215
-            $this,
216
-            $qty,
217
-            $sold
218
-        );
219
-    }
213
+		do_action(
214
+			'AHEE__EE_Datetime__increase_sold',
215
+			$this,
216
+			$qty,
217
+			$sold
218
+		);
219
+	}
220 220
 
221 221
 
222 222
 
@@ -227,13 +227,13 @@  discard block
 block discarded – undo
227 227
 	public function decrease_sold( $qty = 1 ) {
228 228
 		$sold = $this->sold() - $qty;
229 229
 		$this->set_sold( $sold );
230
-        do_action(
231
-            'AHEE__EE_Datetime__decrease_sold',
232
-            $this,
233
-            $qty,
234
-            $sold
235
-        );
236
-    }
230
+		do_action(
231
+			'AHEE__EE_Datetime__decrease_sold',
232
+			$this,
233
+			$qty,
234
+			$sold
235
+		);
236
+	}
237 237
 
238 238
 
239 239
 
@@ -269,13 +269,13 @@  discard block
 block discarded – undo
269 269
 	 */
270 270
 	public function increase_reserved( $qty = 1 ) {
271 271
 		$reserved = $this->reserved() + absint( $qty );
272
-        do_action(
273
-            'AHEE__EE_Datetime__increase_reserved',
274
-            $this,
275
-            $qty,
276
-            $reserved
277
-        );
278
-        $this->set_reserved( $reserved );
272
+		do_action(
273
+			'AHEE__EE_Datetime__increase_reserved',
274
+			$this,
275
+			$qty,
276
+			$reserved
277
+		);
278
+		$this->set_reserved( $reserved );
279 279
 	}
280 280
 
281 281
 
@@ -288,13 +288,13 @@  discard block
 block discarded – undo
288 288
 	 */
289 289
 	public function decrease_reserved( $qty = 1 ) {
290 290
 		$reserved = $this->reserved() - absint( $qty );
291
-        do_action(
292
-            'AHEE__EE_Datetime__decrease_reserved',
293
-            $this,
294
-            $qty,
295
-            $reserved
296
-        );
297
-        $this->set_reserved( $reserved );
291
+		do_action(
292
+			'AHEE__EE_Datetime__decrease_reserved',
293
+			$this,
294
+			$qty,
295
+			$reserved
296
+		);
297
+		$this->set_reserved( $reserved );
298 298
 	}
299 299
 
300 300
 
@@ -382,13 +382,13 @@  discard block
 block discarded – undo
382 382
 
383 383
 
384 384
 
385
-    /**
386
-     * get event start date.  Provide either the date format, or NULL to re-use the
387
-     * last-used format, or '' to use the default date format
388
-     *
389
-     * @param string $dt_frmt - string representation of date format defaults to 'F j, Y'
390
-     * @return        mixed        string on success, FALSE on fail
391
-     */
385
+	/**
386
+	 * get event start date.  Provide either the date format, or NULL to re-use the
387
+	 * last-used format, or '' to use the default date format
388
+	 *
389
+	 * @param string $dt_frmt - string representation of date format defaults to 'F j, Y'
390
+	 * @return        mixed        string on success, FALSE on fail
391
+	 */
392 392
 	public function start_date( $dt_frmt = '' ) {
393 393
 		return $this->_show_datetime( 'D', 'start', $dt_frmt );
394 394
 	}
@@ -405,13 +405,13 @@  discard block
 block discarded – undo
405 405
 
406 406
 
407 407
 
408
-    /**
409
-     * get end date. Provide either the date format, or NULL to re-use the
410
-     * last-used format, or '' to use the default date format
411
-     *
412
-     * @param string $dt_frmt - string representation of date format defaults to 'F j, Y'
413
-     * @return        mixed        string on success, FALSE on fail
414
-     */
408
+	/**
409
+	 * get end date. Provide either the date format, or NULL to re-use the
410
+	 * last-used format, or '' to use the default date format
411
+	 *
412
+	 * @param string $dt_frmt - string representation of date format defaults to 'F j, Y'
413
+	 * @return        mixed        string on success, FALSE on fail
414
+	 */
415 415
 	public function end_date( $dt_frmt = '' ) {
416 416
 		return $this->_show_datetime( 'D', 'end', $dt_frmt );
417 417
 	}
@@ -533,23 +533,23 @@  discard block
 block discarded – undo
533 533
 	/**
534 534
 	 * This returns a range representation of the date and times.
535 535
 	 * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
536
-     * Also, the return value is localized.
537
-     *
538
-     * @param string $dt_format
536
+	 * Also, the return value is localized.
537
+	 *
538
+	 * @param string $dt_format
539 539
 	 * @param string $tm_format
540 540
 	 * @param string $conjunction used between two different dates or times.
541
-     *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
542
-     * @param string $separator   used between the date and time formats.
543
-     *                            ex: Dec 1, 2016{$separator}2pm
541
+	 *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
542
+	 * @param string $separator   used between the date and time formats.
543
+	 *                            ex: Dec 1, 2016{$separator}2pm
544 544
 	 * @return string
545 545
 	 * @throws \EE_Error
546 546
 	 */
547 547
 	public function date_and_time_range(
548
-	    $dt_format = '',
549
-        $tm_format = '',
550
-        $conjunction = ' - ' ,
551
-        $separator = ' '
552
-    ) {
548
+		$dt_format = '',
549
+		$tm_format = '',
550
+		$conjunction = ' - ' ,
551
+		$separator = ' '
552
+	) {
553 553
 		$dt_format = ! empty( $dt_format ) ? $dt_format : $this->_dt_frmt;
554 554
 		$tm_format = ! empty( $tm_format ) ? $tm_format : $this->_tm_frmt;
555 555
 		$full_format = $dt_format . $separator . $tm_format;
@@ -563,14 +563,14 @@  discard block
 block discarded – undo
563 563
 			//start and end date are the same but times are different
564 564
 			case ( $this->start_date() === $this->end_date() ) :
565 565
 				$output = $this->get_i18n_datetime( 'DTT_EVT_start', $full_format )
566
-				          . $conjunction
567
-				          . $this->get_i18n_datetime( 'DTT_EVT_end', $tm_format );
566
+						  . $conjunction
567
+						  . $this->get_i18n_datetime( 'DTT_EVT_end', $tm_format );
568 568
 				break;
569 569
 			//all other conditions
570 570
 			default :
571 571
 				$output = $this->get_i18n_datetime( 'DTT_EVT_start', $full_format )
572
-				          . $conjunction
573
-				          . $this->get_i18n_datetime( 'DTT_EVT_end', $full_format );
572
+						  . $conjunction
573
+						  . $this->get_i18n_datetime( 'DTT_EVT_end', $full_format );
574 574
 				break;
575 575
 		}
576 576
 		return $output;
@@ -654,13 +654,13 @@  discard block
 block discarded – undo
654 654
 
655 655
 
656 656
 	/**
657
-     *        get end date and time
658
-     *
659
-     * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
660
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
661
-     * @return    mixed                string on success, FALSE on fail
662
-     */
663
-    public function end_date_and_time($dt_frmt = '', $tm_format = '') {
657
+	 *        get end date and time
658
+	 *
659
+	 * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
660
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
661
+	 * @return    mixed                string on success, FALSE on fail
662
+	 */
663
+	public function end_date_and_time($dt_frmt = '', $tm_format = '') {
664 664
 		return $this->_show_datetime( '', 'end', $dt_frmt, $tm_format );
665 665
 	}
666 666
 
@@ -929,13 +929,13 @@  discard block
 block discarded – undo
929 929
 
930 930
 
931 931
 
932
-    /**
933
-     * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime (via the tickets).
934
-     * into account
935
-     *
936
-     * @return int
937
-     * @throws \EE_Error
938
-     */
932
+	/**
933
+	 * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime (via the tickets).
934
+	 * into account
935
+	 *
936
+	 * @return int
937
+	 * @throws \EE_Error
938
+	 */
939 939
 	public function update_sold() {
940 940
 		$count_regs_for_this_datetime = EEM_Registration::instance()->count(
941 941
 			array( array(
@@ -944,14 +944,14 @@  discard block
 block discarded – undo
944 944
 				'Ticket.Datetime.DTT_ID' 	=> $this->ID(),
945 945
 			) )
946 946
 		);
947
-        $sold = $this->sold();
948
-        if ($count_regs_for_this_datetime > $sold) {
949
-            $this->increase_sold($count_regs_for_this_datetime - $sold);
950
-            $this->save();
951
-        } else if ($count_regs_for_this_datetime < $sold) {
952
-            $this->decrease_sold($count_regs_for_this_datetime - $sold);
953
-            $this->save();
954
-        }
947
+		$sold = $this->sold();
948
+		if ($count_regs_for_this_datetime > $sold) {
949
+			$this->increase_sold($count_regs_for_this_datetime - $sold);
950
+			$this->save();
951
+		} else if ($count_regs_for_this_datetime < $sold) {
952
+			$this->decrease_sold($count_regs_for_this_datetime - $sold);
953
+			$this->save();
954
+		}
955 955
 		return $count_regs_for_this_datetime;
956 956
 	}
957 957
 }
Please login to merge, or discard this patch.
Spacing   +149 added lines, -149 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1
-<?php if ( !defined( 'EVENT_ESPRESSO_VERSION' ) ) {
2
-	exit( 'No direct script access allowed' );
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /**
5 5
  * Event Espresso
@@ -74,9 +74,9 @@  discard block
 block discarded – undo
74 74
 	 *                             		    date_format and the second value is the time format
75 75
 	 * @return EE_Datetime
76 76
 	 */
77
-	public static function new_instance( $props_n_values = array(), $timezone = null, $date_formats = array() ) {
78
-		$has_object = parent::_check_for_object( $props_n_values, __CLASS__, $timezone, $date_formats );
79
-		return $has_object ? $has_object : new self( $props_n_values, false, $timezone, $date_formats );
77
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) {
78
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
79
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
80 80
 	}
81 81
 
82 82
 
@@ -87,8 +87,8 @@  discard block
 block discarded – undo
87 87
 	 *                          		the website will be used.
88 88
 	 * @return EE_Datetime
89 89
 	 */
90
-	public static function new_instance_from_db( $props_n_values = array(), $timezone = null ) {
91
-		return new self( $props_n_values, TRUE, $timezone );
90
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null) {
91
+		return new self($props_n_values, TRUE, $timezone);
92 92
 	}
93 93
 
94 94
 
@@ -96,8 +96,8 @@  discard block
 block discarded – undo
96 96
 	/**
97 97
 	 * @param $name
98 98
 	 */
99
-	public function set_name( $name ) {
100
-		$this->set( 'DTT_name', $name );
99
+	public function set_name($name) {
100
+		$this->set('DTT_name', $name);
101 101
 	}
102 102
 
103 103
 
@@ -105,8 +105,8 @@  discard block
 block discarded – undo
105 105
 	/**
106 106
 	 * @param $description
107 107
 	 */
108
-	public function set_description( $description ) {
109
-		$this->set( 'DTT_description', $description );
108
+	public function set_description($description) {
109
+		$this->set('DTT_description', $description);
110 110
 	}
111 111
 
112 112
 
@@ -118,8 +118,8 @@  discard block
 block discarded – undo
118 118
 	 *
119 119
 	 * @param        string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
120 120
 	 */
121
-	public function set_start_date( $date ) {
122
-		$this->_set_date_for( $date, 'DTT_EVT_start' );
121
+	public function set_start_date($date) {
122
+		$this->_set_date_for($date, 'DTT_EVT_start');
123 123
 	}
124 124
 
125 125
 
@@ -131,8 +131,8 @@  discard block
 block discarded – undo
131 131
 	 *
132 132
 	 * @param        string $time a string representation of the event time ex:  9am  or  7:30 PM
133 133
 	 */
134
-	public function set_start_time( $time ) {
135
-		$this->_set_time_for( $time, 'DTT_EVT_start' );
134
+	public function set_start_time($time) {
135
+		$this->_set_time_for($time, 'DTT_EVT_start');
136 136
 	}
137 137
 
138 138
 
@@ -144,8 +144,8 @@  discard block
 block discarded – undo
144 144
 	 *
145 145
 	 * @param        string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
146 146
 	 */
147
-	public function set_end_date( $date ) {
148
-		$this->_set_date_for( $date, 'DTT_EVT_end' );
147
+	public function set_end_date($date) {
148
+		$this->_set_date_for($date, 'DTT_EVT_end');
149 149
 	}
150 150
 
151 151
 
@@ -157,8 +157,8 @@  discard block
 block discarded – undo
157 157
 	 *
158 158
 	 * @param        string $time a string representation of the event time ex:  9am  or  7:30 PM
159 159
 	 */
160
-	public function set_end_time( $time ) {
161
-		$this->_set_time_for( $time, 'DTT_EVT_end' );
160
+	public function set_end_time($time) {
161
+		$this->_set_time_for($time, 'DTT_EVT_end');
162 162
 	}
163 163
 
164 164
 
@@ -170,8 +170,8 @@  discard block
 block discarded – undo
170 170
 	 *
171 171
 	 * @param        int $reg_limit
172 172
 	 */
173
-	public function set_reg_limit( $reg_limit ) {
174
-		$this->set( 'DTT_reg_limit', $reg_limit );
173
+	public function set_reg_limit($reg_limit) {
174
+		$this->set('DTT_reg_limit', $reg_limit);
175 175
 	}
176 176
 
177 177
 
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 	 * @return        mixed        int on success, FALSE on fail
184 184
 	 */
185 185
 	public function sold() {
186
-		return $this->get_raw( 'DTT_sold' );
186
+		return $this->get_raw('DTT_sold');
187 187
 	}
188 188
 
189 189
 
@@ -193,10 +193,10 @@  discard block
 block discarded – undo
193 193
 	 *
194 194
 	 * @param        int $sold
195 195
 	 */
196
-	public function set_sold( $sold ) {
196
+	public function set_sold($sold) {
197 197
 		// sold can not go below zero
198
-		$sold = max( 0, $sold );
199
-		$this->set( 'DTT_sold', $sold );
198
+		$sold = max(0, $sold);
199
+		$this->set('DTT_sold', $sold);
200 200
 	}
201 201
 
202 202
 
@@ -205,11 +205,11 @@  discard block
 block discarded – undo
205 205
 	 * increments sold by amount passed by $qty
206 206
 	 * @param int $qty
207 207
 	 */
208
-	public function increase_sold( $qty = 1 ) {
208
+	public function increase_sold($qty = 1) {
209 209
 		$sold = $this->sold() + $qty;
210 210
 		// remove ticket reservation
211
-		$this->decrease_reserved( $qty );
212
-		$this->set_sold( $sold );
211
+		$this->decrease_reserved($qty);
212
+		$this->set_sold($sold);
213 213
         do_action(
214 214
             'AHEE__EE_Datetime__increase_sold',
215 215
             $this,
@@ -224,9 +224,9 @@  discard block
 block discarded – undo
224 224
 	 * decrements (subtracts) sold amount passed by $qty
225 225
 	 * @param int $qty
226 226
 	 */
227
-	public function decrease_sold( $qty = 1 ) {
227
+	public function decrease_sold($qty = 1) {
228 228
 		$sold = $this->sold() - $qty;
229
-		$this->set_sold( $sold );
229
+		$this->set_sold($sold);
230 230
         do_action(
231 231
             'AHEE__EE_Datetime__decrease_sold',
232 232
             $this,
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
 	 * @return int
244 244
 	 */
245 245
 	public function reserved() {
246
-		return $this->get_raw( 'DTT_reserved' );
246
+		return $this->get_raw('DTT_reserved');
247 247
 	}
248 248
 
249 249
 
@@ -253,10 +253,10 @@  discard block
 block discarded – undo
253 253
 	 *
254 254
 	 * @param int $reserved
255 255
 	 */
256
-	public function set_reserved( $reserved ) {
256
+	public function set_reserved($reserved) {
257 257
 		// reserved can not go below zero
258
-		$reserved = max( 0, (int) $reserved );
259
-		$this->set( 'DTT_reserved', $reserved );
258
+		$reserved = max(0, (int) $reserved);
259
+		$this->set('DTT_reserved', $reserved);
260 260
 	}
261 261
 
262 262
 
@@ -267,15 +267,15 @@  discard block
 block discarded – undo
267 267
 	 * @param int $qty
268 268
 	 * @return void
269 269
 	 */
270
-	public function increase_reserved( $qty = 1 ) {
271
-		$reserved = $this->reserved() + absint( $qty );
270
+	public function increase_reserved($qty = 1) {
271
+		$reserved = $this->reserved() + absint($qty);
272 272
         do_action(
273 273
             'AHEE__EE_Datetime__increase_reserved',
274 274
             $this,
275 275
             $qty,
276 276
             $reserved
277 277
         );
278
-        $this->set_reserved( $reserved );
278
+        $this->set_reserved($reserved);
279 279
 	}
280 280
 
281 281
 
@@ -286,15 +286,15 @@  discard block
 block discarded – undo
286 286
 	 * @param int $qty
287 287
 	 * @return void
288 288
 	 */
289
-	public function decrease_reserved( $qty = 1 ) {
290
-		$reserved = $this->reserved() - absint( $qty );
289
+	public function decrease_reserved($qty = 1) {
290
+		$reserved = $this->reserved() - absint($qty);
291 291
         do_action(
292 292
             'AHEE__EE_Datetime__decrease_reserved',
293 293
             $this,
294 294
             $qty,
295 295
             $reserved
296 296
         );
297
-        $this->set_reserved( $reserved );
297
+        $this->set_reserved($reserved);
298 298
 	}
299 299
 
300 300
 
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
 	 * @return string
316 316
 	 */
317 317
 	public function name() {
318
-		return $this->get( 'DTT_name' );
318
+		return $this->get('DTT_name');
319 319
 	}
320 320
 
321 321
 
@@ -325,7 +325,7 @@  discard block
 block discarded – undo
325 325
 	 * @return string
326 326
 	 */
327 327
 	public function description() {
328
-		return $this->get( 'DTT_description' );
328
+		return $this->get('DTT_description');
329 329
 	}
330 330
 
331 331
 
@@ -335,7 +335,7 @@  discard block
 block discarded – undo
335 335
 	 * @return boolean          TRUE if is primary, FALSE if not.
336 336
 	 */
337 337
 	public function is_primary() {
338
-		return $this->get( 'DTT_is_primary' );
338
+		return $this->get('DTT_is_primary');
339 339
 	}
340 340
 
341 341
 
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
 	 * @return int         The order of the datetime for this event.
346 346
 	 */
347 347
 	public function order() {
348
-		return $this->get( 'DTT_order' );
348
+		return $this->get('DTT_order');
349 349
 	}
350 350
 
351 351
 
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
 	 * @return int
356 356
 	 */
357 357
 	public function parent() {
358
-		return $this->get( 'DTT_parent' );
358
+		return $this->get('DTT_parent');
359 359
 	}
360 360
 
361 361
 
@@ -371,10 +371,10 @@  discard block
 block discarded – undo
371 371
 	 * @param    bool   $echo         - whether we echo or return (note echoing uses "pretty" formats, otherwise we use the standard formats)
372 372
 	 * @return    string|bool  string on success, FALSE on fail
373 373
 	 */
374
-	private function _show_datetime( $date_or_time = NULL, $start_or_end = 'start', $dt_frmt = '', $tm_frmt = '', $echo = FALSE ) {
374
+	private function _show_datetime($date_or_time = NULL, $start_or_end = 'start', $dt_frmt = '', $tm_frmt = '', $echo = FALSE) {
375 375
 		$field_name = "DTT_EVT_{$start_or_end}";
376
-		$dtt = $this->_get_datetime( $field_name, $dt_frmt, $tm_frmt, $date_or_time, $echo );
377
-		if ( ! $echo ) {
376
+		$dtt = $this->_get_datetime($field_name, $dt_frmt, $tm_frmt, $date_or_time, $echo);
377
+		if ( ! $echo) {
378 378
 			return $dtt;
379 379
 		}
380 380
 		return '';
@@ -389,8 +389,8 @@  discard block
 block discarded – undo
389 389
      * @param string $dt_frmt - string representation of date format defaults to 'F j, Y'
390 390
      * @return        mixed        string on success, FALSE on fail
391 391
      */
392
-	public function start_date( $dt_frmt = '' ) {
393
-		return $this->_show_datetime( 'D', 'start', $dt_frmt );
392
+	public function start_date($dt_frmt = '') {
393
+		return $this->_show_datetime('D', 'start', $dt_frmt);
394 394
 	}
395 395
 
396 396
 
@@ -399,8 +399,8 @@  discard block
 block discarded – undo
399 399
 	 * Echoes start_date()
400 400
 	 * @param string $dt_frmt
401 401
 	 */
402
-	public function e_start_date( $dt_frmt = '' ) {
403
-		$this->_show_datetime( 'D', 'start', $dt_frmt, NULL, TRUE );
402
+	public function e_start_date($dt_frmt = '') {
403
+		$this->_show_datetime('D', 'start', $dt_frmt, NULL, TRUE);
404 404
 	}
405 405
 
406 406
 
@@ -412,8 +412,8 @@  discard block
 block discarded – undo
412 412
      * @param string $dt_frmt - string representation of date format defaults to 'F j, Y'
413 413
      * @return        mixed        string on success, FALSE on fail
414 414
      */
415
-	public function end_date( $dt_frmt = '' ) {
416
-		return $this->_show_datetime( 'D', 'end', $dt_frmt );
415
+	public function end_date($dt_frmt = '') {
416
+		return $this->_show_datetime('D', 'end', $dt_frmt);
417 417
 	}
418 418
 
419 419
 
@@ -422,8 +422,8 @@  discard block
 block discarded – undo
422 422
 	 * Echoes the end date. See end_date()
423 423
 	 * @param string $dt_frmt
424 424
 	 */
425
-	public function e_end_date( $dt_frmt = '' ) {
426
-		$this->_show_datetime( 'D', 'end', $dt_frmt, NULL, TRUE );
425
+	public function e_end_date($dt_frmt = '') {
426
+		$this->_show_datetime('D', 'end', $dt_frmt, NULL, TRUE);
427 427
 	}
428 428
 
429 429
 
@@ -438,11 +438,11 @@  discard block
 block discarded – undo
438 438
 	 * @return mixed        string on success, FALSE on fail
439 439
 	 * @throws \EE_Error
440 440
 	 */
441
-	public function date_range( $dt_frmt = '', $conjunction = ' - ' ) {
442
-		$dt_frmt = ! empty( $dt_frmt ) ? $dt_frmt : $this->_dt_frmt;
443
-		$start = str_replace( ' ', '&nbsp;', $this->get_i18n_datetime( 'DTT_EVT_start', $dt_frmt ) );
444
-		$end = str_replace( ' ', '&nbsp;', $this->get_i18n_datetime( 'DTT_EVT_end', $dt_frmt ) );
445
-		return $start !== $end ? $start . $conjunction . $end : $start;
441
+	public function date_range($dt_frmt = '', $conjunction = ' - ') {
442
+		$dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
443
+		$start = str_replace(' ', '&nbsp;', $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt));
444
+		$end = str_replace(' ', '&nbsp;', $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt));
445
+		return $start !== $end ? $start.$conjunction.$end : $start;
446 446
 	}
447 447
 
448 448
 
@@ -452,8 +452,8 @@  discard block
 block discarded – undo
452 452
 	 * @param string $conjunction
453 453
 	 * @throws \EE_Error
454 454
 	 */
455
-	public function e_date_range( $dt_frmt = '', $conjunction = ' - ' ) {
456
-		echo $this->date_range( $dt_frmt, $conjunction );
455
+	public function e_date_range($dt_frmt = '', $conjunction = ' - ') {
456
+		echo $this->date_range($dt_frmt, $conjunction);
457 457
 	}
458 458
 
459 459
 
@@ -464,8 +464,8 @@  discard block
 block discarded – undo
464 464
 	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
465 465
 	 * @return mixed        string on success, FALSE on fail
466 466
 	 */
467
-	public function start_time( $tm_format = '' ) {
468
-		return $this->_show_datetime( 'T', 'start', NULL, $tm_format );
467
+	public function start_time($tm_format = '') {
468
+		return $this->_show_datetime('T', 'start', NULL, $tm_format);
469 469
 	}
470 470
 
471 471
 
@@ -473,8 +473,8 @@  discard block
 block discarded – undo
473 473
 	/**
474 474
 	 * @param string $tm_format
475 475
 	 */
476
-	public function e_start_time( $tm_format = '' ) {
477
-		$this->_show_datetime( 'T', 'start', NULL, $tm_format, TRUE );
476
+	public function e_start_time($tm_format = '') {
477
+		$this->_show_datetime('T', 'start', NULL, $tm_format, TRUE);
478 478
 	}
479 479
 
480 480
 
@@ -485,8 +485,8 @@  discard block
 block discarded – undo
485 485
 	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
486 486
 	 * @return mixed        string on success, FALSE on fail
487 487
 	 */
488
-	public function end_time( $tm_format = '' ) {
489
-		return $this->_show_datetime( 'T', 'end', NULL, $tm_format );
488
+	public function end_time($tm_format = '') {
489
+		return $this->_show_datetime('T', 'end', NULL, $tm_format);
490 490
 	}
491 491
 
492 492
 
@@ -494,8 +494,8 @@  discard block
 block discarded – undo
494 494
 	/**
495 495
 	 * @param string $tm_format
496 496
 	 */
497
-	public function e_end_time( $tm_format = '' ) {
498
-		$this->_show_datetime( 'T', 'end', NULL, $tm_format, TRUE );
497
+	public function e_end_time($tm_format = '') {
498
+		$this->_show_datetime('T', 'end', NULL, $tm_format, TRUE);
499 499
 	}
500 500
 
501 501
 
@@ -510,11 +510,11 @@  discard block
 block discarded – undo
510 510
 	 * @return mixed              string on success, FALSE on fail
511 511
 	 * @throws \EE_Error
512 512
 	 */
513
-	public function time_range( $tm_format = '', $conjunction = ' - ' ) {
514
-		$tm_format = ! empty( $tm_format ) ? $tm_format : $this->_tm_frmt;
515
-		$start = str_replace( ' ', '&nbsp;', $this->get_i18n_datetime( 'DTT_EVT_start', $tm_format ) );
516
-		$end = str_replace( ' ', '&nbsp;', $this->get_i18n_datetime( 'DTT_EVT_end',  $tm_format ) );
517
-		return $start !== $end ? $start . $conjunction . $end : $start;
513
+	public function time_range($tm_format = '', $conjunction = ' - ') {
514
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
515
+		$start = str_replace(' ', '&nbsp;', $this->get_i18n_datetime('DTT_EVT_start', $tm_format));
516
+		$end = str_replace(' ', '&nbsp;', $this->get_i18n_datetime('DTT_EVT_end', $tm_format));
517
+		return $start !== $end ? $start.$conjunction.$end : $start;
518 518
 	}
519 519
 
520 520
 
@@ -524,8 +524,8 @@  discard block
 block discarded – undo
524 524
 	 * @param string $conjunction
525 525
 	 * @throws \EE_Error
526 526
 	 */
527
-	public function e_time_range( $tm_format = '', $conjunction = ' - ' ) {
528
-		echo $this->time_range( $tm_format, $conjunction );
527
+	public function e_time_range($tm_format = '', $conjunction = ' - ') {
528
+		echo $this->time_range($tm_format, $conjunction);
529 529
 	}
530 530
 
531 531
 
@@ -547,30 +547,30 @@  discard block
 block discarded – undo
547 547
 	public function date_and_time_range(
548 548
 	    $dt_format = '',
549 549
         $tm_format = '',
550
-        $conjunction = ' - ' ,
550
+        $conjunction = ' - ',
551 551
         $separator = ' '
552 552
     ) {
553
-		$dt_format = ! empty( $dt_format ) ? $dt_format : $this->_dt_frmt;
554
-		$tm_format = ! empty( $tm_format ) ? $tm_format : $this->_tm_frmt;
555
-		$full_format = $dt_format . $separator . $tm_format;
553
+		$dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
554
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
555
+		$full_format = $dt_format.$separator.$tm_format;
556 556
 
557 557
 		//the range output depends on various conditions
558
-		switch ( true ) {
558
+		switch (true) {
559 559
 			//start date timestamp and end date timestamp are the same.
560
-			case ( $this->get_raw( 'DTT_EVT_start' ) === $this->get_raw( 'DTT_EVT_end' ) ) :
561
-				$output = $this->get_i18n_datetime( 'DTT_EVT_start', $full_format );
560
+			case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')) :
561
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
562 562
 				break;
563 563
 			//start and end date are the same but times are different
564
-			case ( $this->start_date() === $this->end_date() ) :
565
-				$output = $this->get_i18n_datetime( 'DTT_EVT_start', $full_format )
564
+			case ($this->start_date() === $this->end_date()) :
565
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
566 566
 				          . $conjunction
567
-				          . $this->get_i18n_datetime( 'DTT_EVT_end', $tm_format );
567
+				          . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
568 568
 				break;
569 569
 			//all other conditions
570 570
 			default :
571
-				$output = $this->get_i18n_datetime( 'DTT_EVT_start', $full_format )
571
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
572 572
 				          . $conjunction
573
-				          . $this->get_i18n_datetime( 'DTT_EVT_end', $full_format );
573
+				          . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
574 574
 				break;
575 575
 		}
576 576
 		return $output;
@@ -588,8 +588,8 @@  discard block
 block discarded – undo
588 588
 	 * @return void
589 589
 	 * @throws \EE_Error
590 590
 	 */
591
-	public function e_date_and_time_range( $dt_format = '', $tm_format = '', $conjunction = ' - ' ) {
592
-		echo $this->date_and_time_range( $dt_format, $tm_format, $conjunction );
591
+	public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ') {
592
+		echo $this->date_and_time_range($dt_format, $tm_format, $conjunction);
593 593
 	}
594 594
 
595 595
 
@@ -601,8 +601,8 @@  discard block
 block discarded – undo
601 601
 	 * @param 	string 	$tm_format - string representation of time format defaults to 'g:i a'
602 602
 	 * @return 	mixed 	string on success, FALSE on fail
603 603
 	 */
604
-	public function start_date_and_time( $dt_format = '', $tm_format = '' ) {
605
-		return $this->_show_datetime( '', 'start', $dt_format, $tm_format );
604
+	public function start_date_and_time($dt_format = '', $tm_format = '') {
605
+		return $this->_show_datetime('', 'start', $dt_format, $tm_format);
606 606
 	}
607 607
 
608 608
 
@@ -611,8 +611,8 @@  discard block
 block discarded – undo
611 611
 	 * @param string $dt_frmt
612 612
 	 * @param string $tm_format
613 613
 	 */
614
-	public function e_start_date_and_time( $dt_frmt = '', $tm_format = '' ) {
615
-		$this->_show_datetime( '', 'start', $dt_frmt, $tm_format, TRUE );
614
+	public function e_start_date_and_time($dt_frmt = '', $tm_format = '') {
615
+		$this->_show_datetime('', 'start', $dt_frmt, $tm_format, TRUE);
616 616
 	}
617 617
 
618 618
 
@@ -626,11 +626,11 @@  discard block
 block discarded – undo
626 626
 	 * @param bool   $round_up
627 627
 	 * @return float|int|mixed
628 628
 	 */
629
-	public function length( $units = 'seconds', $round_up = FALSE ) {
630
-		$start = $this->get_raw( 'DTT_EVT_start' );
631
-		$end = $this->get_raw( 'DTT_EVT_end' );
629
+	public function length($units = 'seconds', $round_up = FALSE) {
630
+		$start = $this->get_raw('DTT_EVT_start');
631
+		$end = $this->get_raw('DTT_EVT_end');
632 632
 		$length_in_units = $end - $start;
633
-		switch ( $units ) {
633
+		switch ($units) {
634 634
 			//NOTE: We purposefully don't use "break;" in order to chain the divisions
635 635
 			/** @noinspection PhpMissingBreakStatementInspection */
636 636
 			case 'days':
@@ -643,10 +643,10 @@  discard block
 block discarded – undo
643 643
 				$length_in_units /= 60;
644 644
 			case 'seconds':
645 645
 			default:
646
-				$length_in_units = ceil( $length_in_units );
646
+				$length_in_units = ceil($length_in_units);
647 647
 		}
648
-		if ( $round_up ) {
649
-			$length_in_units = max( $length_in_units, 1 );
648
+		if ($round_up) {
649
+			$length_in_units = max($length_in_units, 1);
650 650
 		}
651 651
 		return $length_in_units;
652 652
 	}
@@ -661,7 +661,7 @@  discard block
 block discarded – undo
661 661
      * @return    mixed                string on success, FALSE on fail
662 662
      */
663 663
     public function end_date_and_time($dt_frmt = '', $tm_format = '') {
664
-		return $this->_show_datetime( '', 'end', $dt_frmt, $tm_format );
664
+		return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
665 665
 	}
666 666
 
667 667
 
@@ -670,8 +670,8 @@  discard block
 block discarded – undo
670 670
 	 * @param string $dt_frmt
671 671
 	 * @param string $tm_format
672 672
 	 */
673
-	public function e_end_date_and_time( $dt_frmt = '', $tm_format = '' ) {
674
-		$this->_show_datetime( '', 'end', $dt_frmt, $tm_format, TRUE );
673
+	public function e_end_date_and_time($dt_frmt = '', $tm_format = '') {
674
+		$this->_show_datetime('', 'end', $dt_frmt, $tm_format, TRUE);
675 675
 	}
676 676
 
677 677
 
@@ -682,7 +682,7 @@  discard block
 block discarded – undo
682 682
 	 * @return        int
683 683
 	 */
684 684
 	public function start() {
685
-		return $this->get_raw( 'DTT_EVT_start' );
685
+		return $this->get_raw('DTT_EVT_start');
686 686
 	}
687 687
 
688 688
 
@@ -693,7 +693,7 @@  discard block
 block discarded – undo
693 693
 	 * @return        int
694 694
 	 */
695 695
 	public function end() {
696
-		return $this->get_raw( 'DTT_EVT_end' );
696
+		return $this->get_raw('DTT_EVT_end');
697 697
 	}
698 698
 
699 699
 
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
 	 * @return        mixed        int on success, FALSE on fail
705 705
 	 */
706 706
 	public function reg_limit() {
707
-		return $this->get_raw( 'DTT_reg_limit' );
707
+		return $this->get_raw('DTT_reg_limit');
708 708
 	}
709 709
 
710 710
 
@@ -732,15 +732,15 @@  discard block
 block discarded – undo
732 732
 	 * 																	the spaces remaining for this particular datetime, hence the flag.
733 733
 	 * @return 	int
734 734
 	 */
735
-	public function spaces_remaining( $consider_tickets = FALSE ) {
735
+	public function spaces_remaining($consider_tickets = FALSE) {
736 736
 		// tickets remaining available for purchase
737 737
 		//no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
738 738
 		$dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
739
-		if ( ! $consider_tickets ) {
739
+		if ( ! $consider_tickets) {
740 740
 			return $dtt_remaining;
741 741
 		}
742 742
 		$tickets_remaining = $this->tickets_remaining();
743
-		return min( $dtt_remaining, $tickets_remaining );
743
+		return min($dtt_remaining, $tickets_remaining);
744 744
 	}
745 745
 
746 746
 
@@ -751,19 +751,19 @@  discard block
 block discarded – undo
751 751
 	 * @param array $query_params like EEM_Base::get_all's
752 752
 	 * @return int
753 753
 	 */
754
-	public function tickets_remaining( $query_params = array() ) {
754
+	public function tickets_remaining($query_params = array()) {
755 755
 		$sum = 0;
756
-		$tickets = $this->tickets( $query_params );
757
-		if ( ! empty( $tickets ) ) {
758
-			foreach ( $tickets as $ticket ) {
759
-				if ( $ticket instanceof EE_Ticket ) {
756
+		$tickets = $this->tickets($query_params);
757
+		if ( ! empty($tickets)) {
758
+			foreach ($tickets as $ticket) {
759
+				if ($ticket instanceof EE_Ticket) {
760 760
 					// get the actual amount of tickets that can be sold
761
-					$qty = $ticket->qty( 'saleable' );
762
-					if ( $qty === EE_INF ) {
761
+					$qty = $ticket->qty('saleable');
762
+					if ($qty === EE_INF) {
763 763
 						return EE_INF;
764 764
 					}
765 765
 					// no negative ticket quantities plz
766
-					if ( $qty > 0 ) {
766
+					if ($qty > 0) {
767 767
 						$sum += $qty;
768 768
 					}
769 769
 				}
@@ -780,8 +780,8 @@  discard block
 block discarded – undo
780 780
 	 * @param array $query_params like EEM_Base::get_all's
781 781
 	 * @return int
782 782
 	 */
783
-	public function sum_tickets_initially_available( $query_params = array() ) {
784
-		return $this->sum_related( 'Ticket', $query_params, 'TKT_qty' );
783
+	public function sum_tickets_initially_available($query_params = array()) {
784
+		return $this->sum_related('Ticket', $query_params, 'TKT_qty');
785 785
 	}
786 786
 
787 787
 
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
 	 * @return int
794 794
 	 */
795 795
 	public function total_tickets_available_at_this_datetime() {
796
-		return $this->spaces_remaining( true );
796
+		return $this->spaces_remaining(true);
797 797
 	}
798 798
 
799 799
 
@@ -804,7 +804,7 @@  discard block
 block discarded – undo
804 804
 	 * @return boolean
805 805
 	 */
806 806
 	public function is_upcoming() {
807
-		return ( $this->get_raw( 'DTT_EVT_start' ) > time() );
807
+		return ($this->get_raw('DTT_EVT_start') > time());
808 808
 	}
809 809
 
810 810
 
@@ -814,7 +814,7 @@  discard block
 block discarded – undo
814 814
 	 * @return boolean
815 815
 	 */
816 816
 	public function is_active() {
817
-		return ( $this->get_raw( 'DTT_EVT_start' ) < time() && $this->get_raw( 'DTT_EVT_end' ) > time() );
817
+		return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
818 818
 	}
819 819
 
820 820
 
@@ -824,7 +824,7 @@  discard block
 block discarded – undo
824 824
 	 * @return boolean
825 825
 	 */
826 826
 	public function is_expired() {
827
-		return ( $this->get_raw( 'DTT_EVT_end' ) < time() );
827
+		return ($this->get_raw('DTT_EVT_end') < time());
828 828
 	}
829 829
 
830 830
 
@@ -835,16 +835,16 @@  discard block
 block discarded – undo
835 835
 	 */
836 836
 	public function get_active_status() {
837 837
 		$total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
838
-		if ( $total_tickets_for_this_dtt !== FALSE && $total_tickets_for_this_dtt < 1 ) {
838
+		if ($total_tickets_for_this_dtt !== FALSE && $total_tickets_for_this_dtt < 1) {
839 839
 			return EE_Datetime::sold_out;
840 840
 		}
841
-		if ( $this->is_expired() ) {
841
+		if ($this->is_expired()) {
842 842
 			return EE_Datetime::expired;
843 843
 		}
844
-		if ( $this->is_upcoming() ) {
844
+		if ($this->is_upcoming()) {
845 845
 			return EE_Datetime::upcoming;
846 846
 		}
847
-		if ( $this->is_active() ) {
847
+		if ($this->is_active()) {
848 848
 			return EE_Datetime::active;
849 849
 		}
850 850
 		return NULL;
@@ -858,24 +858,24 @@  discard block
 block discarded – undo
858 858
 	 * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
859 859
 	 * @return string
860 860
 	 */
861
-	public function get_dtt_display_name( $use_dtt_name = FALSE ) {
862
-		if ( $use_dtt_name ) {
861
+	public function get_dtt_display_name($use_dtt_name = FALSE) {
862
+		if ($use_dtt_name) {
863 863
 			$dtt_name = $this->name();
864
-			if ( !empty( $dtt_name ) ) {
864
+			if ( ! empty($dtt_name)) {
865 865
 				return $dtt_name;
866 866
 			}
867 867
 		}
868 868
 		//first condition is to see if the months are different
869
-		if ( date( 'm', $this->get_raw( 'DTT_EVT_start' ) ) != date( 'm', $this->get_raw( 'DTT_EVT_end' ) ) ) {
870
-			$display_date = $this->start_date( 'M j\, Y g:i a' ) . ' - ' . $this->end_date( 'M j\, Y g:i a' );
869
+		if (date('m', $this->get_raw('DTT_EVT_start')) != date('m', $this->get_raw('DTT_EVT_end'))) {
870
+			$display_date = $this->start_date('M j\, Y g:i a').' - '.$this->end_date('M j\, Y g:i a');
871 871
 			//next condition is if its the same month but different day
872 872
 		}
873 873
 		else {
874
-			if ( date( 'm', $this->get_raw( 'DTT_EVT_start' ) ) == date( 'm', $this->get_raw( 'DTT_EVT_end' ) ) && date( 'd', $this->get_raw( 'DTT_EVT_start' ) ) != date( 'd', $this->get_raw( 'DTT_EVT_end' ) ) ) {
875
-				$display_date = $this->start_date( 'M j\, g:i a' ) . ' - ' . $this->end_date( 'M j\, g:i a Y' );
874
+			if (date('m', $this->get_raw('DTT_EVT_start')) == date('m', $this->get_raw('DTT_EVT_end')) && date('d', $this->get_raw('DTT_EVT_start')) != date('d', $this->get_raw('DTT_EVT_end'))) {
875
+				$display_date = $this->start_date('M j\, g:i a').' - '.$this->end_date('M j\, g:i a Y');
876 876
 			}
877 877
 			else {
878
-				$display_date = $this->start_date( 'F j\, Y' ) . ' @ ' . $this->start_date( 'g:i a' ) . ' - ' . $this->end_date( 'g:i a' );
878
+				$display_date = $this->start_date('F j\, Y').' @ '.$this->start_date('g:i a').' - '.$this->end_date('g:i a');
879 879
 			}
880 880
 		}
881 881
 		return $display_date;
@@ -889,8 +889,8 @@  discard block
 block discarded – undo
889 889
 *@param array $query_params see EEM_Base::get_all()
890 890
 	 * @return EE_Ticket[]
891 891
 	 */
892
-	public function tickets( $query_params = array() ) {
893
-		return $this->get_many_related( 'Ticket', $query_params );
892
+	public function tickets($query_params = array()) {
893
+		return $this->get_many_related('Ticket', $query_params);
894 894
 	}
895 895
 
896 896
 
@@ -900,21 +900,21 @@  discard block
 block discarded – undo
900 900
 	 * @param array $query_params like EEM_Base::get_all's
901 901
 	 * @return EE_Ticket[]
902 902
 	 */
903
-	public function ticket_types_available_for_purchase( $query_params = array() ) {
903
+	public function ticket_types_available_for_purchase($query_params = array()) {
904 904
 		// first check if datetime is valid
905
-		if ( ! ( $this->is_upcoming() || $this->is_active() ) || $this->sold_out() ) {
905
+		if ( ! ($this->is_upcoming() || $this->is_active()) || $this->sold_out()) {
906 906
 			return array();
907 907
 		}
908
-		if ( empty( $query_params ) ) {
908
+		if (empty($query_params)) {
909 909
 			$query_params = array(
910 910
 				array(
911
-					'TKT_start_date' => array( '<=', EEM_Ticket::instance()->current_time_for_query( 'TKT_start_date' ) ),
912
-					'TKT_end_date'   => array( '>=', EEM_Ticket::instance()->current_time_for_query( 'TKT_end_date' ) ),
911
+					'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
912
+					'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
913 913
 					'TKT_deleted'    => false
914 914
 				)
915 915
 			);
916 916
 		}
917
-		return $this->tickets( $query_params );
917
+		return $this->tickets($query_params);
918 918
 	}
919 919
 
920 920
 
@@ -924,7 +924,7 @@  discard block
 block discarded – undo
924 924
 	 * @return EE_Event
925 925
 	 */
926 926
 	public function event() {
927
-		return $this->get_first_related( 'Event' );
927
+		return $this->get_first_related('Event');
928 928
 	}
929 929
 
930 930
 
@@ -938,11 +938,11 @@  discard block
 block discarded – undo
938 938
      */
939 939
 	public function update_sold() {
940 940
 		$count_regs_for_this_datetime = EEM_Registration::instance()->count(
941
-			array( array(
941
+			array(array(
942 942
 				'STS_ID' 					=> EEM_Registration::status_id_approved,
943 943
 				'REG_deleted' 				=> 0,
944 944
 				'Ticket.Datetime.DTT_ID' 	=> $this->ID(),
945
-			) )
945
+			))
946 946
 		);
947 947
         $sold = $this->sold();
948 948
         if ($count_regs_for_this_datetime > $sold) {
Please login to merge, or discard this patch.
reg_steps/payment_options/EE_SPCO_Reg_Step_Payment_Options.class.php 2 patches
Indentation   +2870 added lines, -2870 removed lines patch added patch discarded remove patch
@@ -15,2874 +15,2874 @@
 block discarded – undo
15 15
 class EE_SPCO_Reg_Step_Payment_Options extends EE_SPCO_Reg_Step
16 16
 {
17 17
 
18
-    /**
19
-     * @access protected
20
-     * @var EE_Line_Item_Display $Line_Item_Display
21
-     */
22
-    protected $line_item_display;
23
-
24
-    /**
25
-     * @access protected
26
-     * @var boolean $handle_IPN_in_this_request
27
-     */
28
-    protected $handle_IPN_in_this_request = false;
29
-
30
-
31
-    /**
32
-     *    set_hooks - for hooking into EE Core, other modules, etc
33
-     *
34
-     * @access    public
35
-     * @return    void
36
-     */
37
-    public static function set_hooks()
38
-    {
39
-        add_filter(
40
-            'FHEE__SPCO__EE_Line_Item_Filter_Collection',
41
-            array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
42
-        );
43
-        add_action(
44
-            'wp_ajax_switch_spco_billing_form',
45
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
46
-        );
47
-        add_action(
48
-            'wp_ajax_nopriv_switch_spco_billing_form',
49
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
50
-        );
51
-        add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
52
-        add_action(
53
-            'wp_ajax_nopriv_save_payer_details',
54
-            array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
55
-        );
56
-        add_action(
57
-            'wp_ajax_get_transaction_details_for_gateways',
58
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
59
-        );
60
-        add_action(
61
-            'wp_ajax_nopriv_get_transaction_details_for_gateways',
62
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
63
-        );
64
-        add_filter(
65
-            'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
66
-            array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
67
-            10,
68
-            1
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     *    ajax switch_spco_billing_form
75
-     *
76
-     * @throws \EE_Error
77
-     */
78
-    public static function switch_spco_billing_form()
79
-    {
80
-        EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
81
-    }
82
-
83
-
84
-    /**
85
-     *    ajax save_payer_details
86
-     *
87
-     * @throws \EE_Error
88
-     */
89
-    public static function save_payer_details()
90
-    {
91
-        EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
-    }
93
-
94
-
95
-    /**
96
-     *    ajax get_transaction_details
97
-     *
98
-     * @throws \EE_Error
99
-     */
100
-    public static function get_transaction_details()
101
-    {
102
-        EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
103
-    }
104
-
105
-
106
-    /**
107
-     * bypass_recaptcha_for_load_payment_method
108
-     *
109
-     * @access public
110
-     * @return array
111
-     * @throws InvalidArgumentException
112
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
113
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
114
-     */
115
-    public static function bypass_recaptcha_for_load_payment_method()
116
-    {
117
-        return array(
118
-            'EESID'  => EE_Registry::instance()->SSN->id(),
119
-            'step'   => 'payment_options',
120
-            'action' => 'spco_billing_form',
121
-        );
122
-    }
123
-
124
-
125
-    /**
126
-     *    class constructor
127
-     *
128
-     * @access    public
129
-     * @param    EE_Checkout $checkout
130
-     */
131
-    public function __construct(EE_Checkout $checkout)
132
-    {
133
-        $this->_slug     = 'payment_options';
134
-        $this->_name     = esc_html__('Payment Options', 'event_espresso');
135
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
136
-        $this->checkout  = $checkout;
137
-        $this->_reset_success_message();
138
-        $this->set_instructions(
139
-            esc_html__(
140
-                'Please select a method of payment and provide any necessary billing information before proceeding.',
141
-                'event_espresso'
142
-            )
143
-        );
144
-    }
145
-
146
-
147
-    /**
148
-     * @return null
149
-     */
150
-    public function line_item_display()
151
-    {
152
-        return $this->line_item_display;
153
-    }
154
-
155
-
156
-    /**
157
-     * @param null $line_item_display
158
-     */
159
-    public function set_line_item_display($line_item_display)
160
-    {
161
-        $this->line_item_display = $line_item_display;
162
-    }
163
-
164
-
165
-    /**
166
-     * @return boolean
167
-     */
168
-    public function handle_IPN_in_this_request()
169
-    {
170
-        return $this->handle_IPN_in_this_request;
171
-    }
172
-
173
-
174
-    /**
175
-     * @param boolean $handle_IPN_in_this_request
176
-     */
177
-    public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
-    {
179
-        $this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
-    }
181
-
182
-
183
-    /**
184
-     * translate_js_strings
185
-     *
186
-     * @return void
187
-     */
188
-    public function translate_js_strings()
189
-    {
190
-        EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
-            'Please select a method of payment in order to continue.',
192
-            'event_espresso'
193
-        );
194
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
-            'A valid method of payment could not be determined. Please refresh the page and try again.',
196
-            'event_espresso'
197
-        );
198
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
-            'Forwarding to Secure Payment Provider.',
200
-            'event_espresso'
201
-        );
202
-    }
203
-
204
-
205
-    /**
206
-     * enqueue_styles_and_scripts
207
-     *
208
-     * @return void
209
-     * @throws EE_Error
210
-     * @throws InvalidArgumentException
211
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
212
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
213
-     */
214
-    public function enqueue_styles_and_scripts()
215
-    {
216
-        $transaction = $this->checkout->transaction;
217
-        //if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219
-            return;
220
-        }
221
-        foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
222
-            $type_obj = $payment_method->type_obj();
223
-            if ($type_obj instanceof EE_PMT_Base) {
224
-                $billing_form = $type_obj->generate_new_billing_form($transaction);
225
-                if ($billing_form instanceof EE_Form_Section_Proper) {
226
-                    $billing_form->enqueue_js();
227
-                }
228
-            }
229
-        }
230
-    }
231
-
232
-
233
-    /**
234
-     * initialize_reg_step
235
-     *
236
-     * @return bool
237
-     * @throws EE_Error
238
-     * @throws InvalidArgumentException
239
-     * @throws ReflectionException
240
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
241
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
242
-     */
243
-    public function initialize_reg_step()
244
-    {
245
-        // TODO: if /when we implement donations, then this will need overriding
246
-        if (// don't need payment options for:
247
-            // 	registrations made via the admin
248
-            // 	completed transactions
249
-            // 	overpaid transactions
250
-            // 	$ 0.00 transactions (no payment required)
251
-            ! $this->checkout->payment_required()
252
-            // but do NOT remove if current action being called belongs to this reg step
253
-            && ! is_callable(array($this, $this->checkout->action))
254
-            && ! $this->completed()
255
-        ) {
256
-            // and if so, then we no longer need the Payment Options step
257
-            if ($this->is_current_step()) {
258
-                $this->checkout->generate_reg_form = false;
259
-            }
260
-            $this->checkout->remove_reg_step($this->_slug);
261
-            // DEBUG LOG
262
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
263
-            return false;
264
-        }
265
-        // load EEM_Payment_Method
266
-        EE_Registry::instance()->load_model('Payment_Method');
267
-        // get all active payment methods
268
-        $this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
269
-            $this->checkout->transaction,
270
-            EEM_Payment_Method::scope_cart
271
-        );
272
-        return true;
273
-    }
274
-
275
-
276
-    /**
277
-     * @return EE_Form_Section_Proper
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws ReflectionException
281
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
282
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
283
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
284
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
285
-     */
286
-    public function generate_reg_form()
287
-    {
288
-        // reset in case someone changes their mind
289
-        $this->_reset_selected_method_of_payment();
290
-        // set some defaults
291
-        $this->checkout->selected_method_of_payment = 'payments_closed';
292
-        $registrations_requiring_payment            = array();
293
-        $registrations_for_free_events              = array();
294
-        $registrations_requiring_pre_approval       = array();
295
-        $sold_out_events                            = array();
296
-        $insufficient_spaces_available              = array();
297
-        $no_payment_required                        = true;
298
-        // loop thru registrations to gather info
299
-        $registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
300
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
301
-            $registrations,
302
-            $this->checkout->revisit
303
-        );
304
-        foreach ($registrations as $REG_ID => $registration) {
305
-            /** @var $registration EE_Registration */
306
-            // has this registration lost it's space ?
307
-            if (isset($ejected_registrations[ $REG_ID ])) {
308
-                if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
310
-                } else {
311
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
312
-                }
313
-                continue;
314
-            }
315
-            // event requires admin approval
316
-            if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
317
-                // add event to list of events with pre-approval reg status
318
-                $registrations_requiring_pre_approval[$REG_ID] = $registration;
319
-                do_action(
320
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
321
-                    $registration->event(),
322
-                    $this
323
-                );
324
-                continue;
325
-            }
326
-            if ($this->checkout->revisit
327
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
328
-                && (
329
-                    $registration->event()->is_sold_out()
330
-                    || $registration->event()->is_sold_out(true)
331
-                )
332
-            ) {
333
-                // add event to list of events that are sold out
334
-                $sold_out_events[$registration->event()->ID()] = $registration->event();
335
-                do_action(
336
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
337
-                    $registration->event(),
338
-                    $this
339
-                );
340
-                continue;
341
-            }
342
-            // are they allowed to pay now and is there monies owing?
343
-            if ($registration->owes_monies_and_can_pay()) {
344
-                $registrations_requiring_payment[$REG_ID] = $registration;
345
-                do_action(
346
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
347
-                    $registration->event(),
348
-                    $this
349
-                );
350
-            } elseif (! $this->checkout->revisit
351
-                && $registration->status_ID() !== EEM_Registration::status_id_not_approved
352
-                && $registration->ticket()->is_free()
353
-            ) {
354
-                $registrations_for_free_events[$registration->event()->ID()] = $registration;
355
-            }
356
-        }
357
-        $subsections = array();
358
-        // now decide which template to load
359
-        if (! empty($sold_out_events)) {
360
-            $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361
-        }
362
-        if (! empty($insufficient_spaces_available)) {
363
-            $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364
-                $insufficient_spaces_available
365
-            );
366
-        }
367
-        if (! empty($registrations_requiring_pre_approval)) {
368
-            $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369
-                $registrations_requiring_pre_approval
370
-            );
371
-        }
372
-        if (! empty($registrations_for_free_events)) {
373
-            $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374
-        }
375
-        if (! empty($registrations_requiring_payment)) {
376
-            if ($this->checkout->amount_owing > 0) {
377
-                // autoload Line_Item_Display classes
378
-                EEH_Autoloader::register_line_item_filter_autoloaders();
379
-                $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
380
-                    apply_filters(
381
-                        'FHEE__SPCO__EE_Line_Item_Filter_Collection',
382
-                        new EE_Line_Item_Filter_Collection()
383
-                    ),
384
-                    $this->checkout->cart->get_grand_total()
385
-                );
386
-                /** @var EE_Line_Item $filtered_line_item_tree */
387
-                $filtered_line_item_tree = $line_item_filter_processor->process();
388
-                EEH_Autoloader::register_line_item_display_autoloaders();
389
-                $this->set_line_item_display(new EE_Line_Item_Display('spco'));
390
-                $subsections['payment_options'] = $this->_display_payment_options(
391
-                    $this->line_item_display->display_line_item(
392
-                        $filtered_line_item_tree,
393
-                        array('registrations' => $registrations)
394
-                    )
395
-                );
396
-                $this->checkout->amount_owing   = $filtered_line_item_tree->total();
397
-                $this->_apply_registration_payments_to_amount_owing($registrations);
398
-            }
399
-            $no_payment_required = false;
400
-        } else {
401
-            $this->_hide_reg_step_submit_button_if_revisit();
402
-        }
403
-        $this->_save_selected_method_of_payment();
404
-
405
-        $subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
406
-        $subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
407
-
408
-        return new EE_Form_Section_Proper(
409
-            array(
410
-                'name'            => $this->reg_form_name(),
411
-                'html_id'         => $this->reg_form_name(),
412
-                'subsections'     => $subsections,
413
-                'layout_strategy' => new EE_No_Layout(),
414
-            )
415
-        );
416
-    }
417
-
418
-
419
-    /**
420
-     * add line item filters required for this reg step
421
-     * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
422
-     *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
423
-     *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
424
-     *        payment options reg step, can apply these filters via the following: apply_filters(
425
-     *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
426
-     *        filter collection by passing that instead of instantiating a new collection
427
-     *
428
-     * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
429
-     * @return EE_Line_Item_Filter_Collection
430
-     * @throws EE_Error
431
-     * @throws InvalidArgumentException
432
-     * @throws ReflectionException
433
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
434
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
435
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
436
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
437
-     */
438
-    public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439
-    {
440
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
441
-            return $line_item_filter_collection;
442
-        }
443
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444
-            return $line_item_filter_collection;
445
-        }
446
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447
-            return $line_item_filter_collection;
448
-        }
449
-        $line_item_filter_collection->add(
450
-            new EE_Billable_Line_Item_Filter(
451
-                EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
452
-                    EE_Registry::instance()->SSN->checkout()->transaction->registrations(
453
-                        EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
454
-                    )
455
-                )
456
-            )
457
-        );
458
-        $line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
459
-        return $line_item_filter_collection;
460
-    }
461
-
462
-
463
-    /**
464
-     * remove_ejected_registrations
465
-     * if a registrant has lost their potential space at an event due to lack of payment,
466
-     * then this method removes them from the list of registrations being paid for during this request
467
-     *
468
-     * @param \EE_Registration[] $registrations
469
-     * @return EE_Registration[]
470
-     * @throws EE_Error
471
-     * @throws InvalidArgumentException
472
-     * @throws ReflectionException
473
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
474
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
475
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
476
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
477
-     */
478
-    public static function remove_ejected_registrations(array $registrations)
479
-    {
480
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
481
-            $registrations,
482
-            EE_Registry::instance()->SSN->checkout()->revisit
483
-        );
484
-        foreach ($registrations as $REG_ID => $registration) {
485
-            // has this registration lost it's space ?
486
-            if (isset($ejected_registrations[$REG_ID])) {
487
-                unset($registrations[$REG_ID]);
488
-                continue;
489
-            }
490
-        }
491
-        return $registrations;
492
-    }
493
-
494
-
495
-    /**
496
-     * find_registrations_that_lost_their_space
497
-     * If a registrant chooses an offline payment method like Invoice,
498
-     * then no space is reserved for them at the event until they fully pay fo that site
499
-     * (unless the event's default reg status is set to APPROVED)
500
-     * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
501
-     * then this method will determine which registrations have lost the ability to complete the reg process.
502
-     *
503
-     * @param \EE_Registration[] $registrations
504
-     * @param bool               $revisit
505
-     * @return array
506
-     * @throws EE_Error
507
-     * @throws InvalidArgumentException
508
-     * @throws ReflectionException
509
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
510
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
511
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
512
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
513
-     */
514
-    public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
515
-    {
516
-        // registrations per event
517
-        $event_reg_count = array();
518
-        // spaces left per event
519
-        $event_spaces_remaining = array();
520
-        // tickets left sorted by ID
521
-        $tickets_remaining = array();
522
-        // registrations that have lost their space
523
-        $ejected_registrations = array();
524
-        foreach ($registrations as $REG_ID => $registration) {
525
-            if ($registration->status_ID() === EEM_Registration::status_id_approved
526
-                || apply_filters(
527
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
528
-                    false,
529
-                    $registration,
530
-                    $revisit
531
-                )
532
-            ) {
533
-                continue;
534
-            }
535
-            $EVT_ID = $registration->event_ID();
536
-            $ticket = $registration->ticket();
537
-            if (! isset($tickets_remaining[$ticket->ID()])) {
538
-                $tickets_remaining[$ticket->ID()] = $ticket->remaining();
539
-            }
540
-            if ($tickets_remaining[$ticket->ID()] > 0) {
541
-                if (! isset($event_reg_count[$EVT_ID])) {
542
-                    $event_reg_count[$EVT_ID] = 0;
543
-                }
544
-                $event_reg_count[$EVT_ID]++;
545
-                if (! isset($event_spaces_remaining[$EVT_ID])) {
546
-                    $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547
-                }
548
-            }
549
-            if ($revisit
550
-                && ($tickets_remaining[$ticket->ID()] === 0
551
-                    || $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
552
-                )
553
-            ) {
554
-                $ejected_registrations[$REG_ID] = $registration->event();
555
-                if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
556
-                    /** @type EE_Registration_Processor $registration_processor */
557
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
558
-                    // at this point, we should have enough details about the registrant to consider the registration
559
-                    // NOT incomplete
560
-                    $registration_processor->manually_update_registration_status(
561
-                        $registration,
562
-                        EEM_Registration::status_id_wait_list
563
-                    );
564
-                }
565
-            }
566
-        }
567
-        return $ejected_registrations;
568
-    }
569
-
570
-
571
-    /**
572
-     * _hide_reg_step_submit_button
573
-     * removes the html for the reg step submit button
574
-     * by replacing it with an empty string via filter callback
575
-     *
576
-     * @return void
577
-     */
578
-    protected function _adjust_registration_status_if_event_old_sold()
579
-    {
580
-    }
581
-
582
-
583
-    /**
584
-     * _hide_reg_step_submit_button
585
-     * removes the html for the reg step submit button
586
-     * by replacing it with an empty string via filter callback
587
-     *
588
-     * @return void
589
-     */
590
-    protected function _hide_reg_step_submit_button_if_revisit()
591
-    {
592
-        if ($this->checkout->revisit) {
593
-            add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
594
-        }
595
-    }
596
-
597
-
598
-    /**
599
-     * sold_out_events
600
-     * displays notices regarding events that have sold out since hte registrant first signed up
601
-     *
602
-     * @param \EE_Event[] $sold_out_events_array
603
-     * @return \EE_Form_Section_Proper
604
-     * @throws \EE_Error
605
-     */
606
-    private function _sold_out_events($sold_out_events_array = array())
607
-    {
608
-        // set some defaults
609
-        $this->checkout->selected_method_of_payment = 'events_sold_out';
610
-        $sold_out_events                            = '';
611
-        foreach ($sold_out_events_array as $sold_out_event) {
612
-            $sold_out_events .= EEH_HTML::li(
613
-                EEH_HTML::span(
614
-                    '  ' . $sold_out_event->name(),
615
-                    '',
616
-                    'dashicons dashicons-marker ee-icon-size-16 pink-text'
617
-                )
618
-            );
619
-        }
620
-        return new EE_Form_Section_Proper(
621
-            array(
622
-                'layout_strategy' => new EE_Template_Layout(
623
-                    array(
624
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
625
-                                                  . $this->_slug
626
-                                                  . DS
627
-                                                  . 'sold_out_events.template.php',
628
-                        'template_args'        => apply_filters(
629
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
630
-                            array(
631
-                                'sold_out_events'     => $sold_out_events,
632
-                                'sold_out_events_msg' => apply_filters(
633
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
634
-                                    sprintf(
635
-                                        esc_html__(
636
-                                            'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
637
-                                            'event_espresso'
638
-                                        ),
639
-                                        '<strong>',
640
-                                        '</strong>',
641
-                                        '<br />'
642
-                                    )
643
-                                ),
644
-                            )
645
-                        ),
646
-                    )
647
-                ),
648
-            )
649
-        );
650
-    }
651
-
652
-
653
-    /**
654
-     * _insufficient_spaces_available
655
-     * displays notices regarding events that do not have enough remaining spaces
656
-     * to satisfy the current number of registrations looking to pay
657
-     *
658
-     * @param \EE_Event[] $insufficient_spaces_events_array
659
-     * @return \EE_Form_Section_Proper
660
-     * @throws \EE_Error
661
-     */
662
-    private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
663
-    {
664
-        // set some defaults
665
-        $this->checkout->selected_method_of_payment = 'invoice';
666
-        $insufficient_space_events                  = '';
667
-        foreach ($insufficient_spaces_events_array as $event) {
668
-            if ($event instanceof EE_Event) {
669
-                $insufficient_space_events .= EEH_HTML::li(
670
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671
-                );
672
-            }
673
-        }
674
-        return new EE_Form_Section_Proper(
675
-            array(
676
-                'subsections'     => array(
677
-                    'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
678
-                    'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
679
-                ),
680
-                'layout_strategy' => new EE_Template_Layout(
681
-                    array(
682
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
683
-                                                  . $this->_slug
684
-                                                  . DS
685
-                                                  . 'sold_out_events.template.php',
686
-                        'template_args'        => apply_filters(
687
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
688
-                            array(
689
-                                'sold_out_events'     => $insufficient_space_events,
690
-                                'sold_out_events_msg' => apply_filters(
691
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
692
-                                    esc_html__(
693
-                                        'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
694
-                                        'event_espresso'
695
-                                    )
696
-                                ),
697
-                            )
698
-                        ),
699
-                    )
700
-                ),
701
-            )
702
-        );
703
-    }
704
-
705
-
706
-    /**
707
-     * registrations_requiring_pre_approval
708
-     *
709
-     * @param array $registrations_requiring_pre_approval
710
-     * @return EE_Form_Section_Proper
711
-     * @throws EE_Error
712
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
713
-     */
714
-    private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
715
-    {
716
-        $events_requiring_pre_approval = '';
717
-        foreach ($registrations_requiring_pre_approval as $registration) {
718
-            if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
719
-                $events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
720
-                    EEH_HTML::span(
721
-                        '',
722
-                        '',
723
-                        'dashicons dashicons-marker ee-icon-size-16 orange-text'
724
-                    )
725
-                    . EEH_HTML::span($registration->event()->name(), '', 'orange-text')
726
-                );
727
-            }
728
-        }
729
-        return new EE_Form_Section_Proper(
730
-            array(
731
-                'layout_strategy' => new EE_Template_Layout(
732
-                    array(
733
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
734
-                                                  . $this->_slug
735
-                                                  . DS
736
-                                                  . 'events_requiring_pre_approval.template.php', // layout_template
737
-                        'template_args'        => apply_filters(
738
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
739
-                            array(
740
-                                'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
741
-                                'events_requiring_pre_approval_msg' => apply_filters(
742
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
743
-                                    esc_html__(
744
-                                        'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
745
-                                        'event_espresso'
746
-                                    )
747
-                                ),
748
-                            )
749
-                        ),
750
-                    )
751
-                ),
752
-            )
753
-        );
754
-    }
755
-
756
-
757
-    /**
758
-     * _no_payment_required
759
-     *
760
-     * @param \EE_Event[] $registrations_for_free_events
761
-     * @return \EE_Form_Section_Proper
762
-     * @throws \EE_Error
763
-     */
764
-    private function _no_payment_required($registrations_for_free_events = array())
765
-    {
766
-        // set some defaults
767
-        $this->checkout->selected_method_of_payment = 'no_payment_required';
768
-        // generate no_payment_required form
769
-        return new EE_Form_Section_Proper(
770
-            array(
771
-                'layout_strategy' => new EE_Template_Layout(
772
-                    array(
773
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
774
-                                                  . $this->_slug
775
-                                                  . DS
776
-                                                  . 'no_payment_required.template.php', // layout_template
777
-                        'template_args'        => apply_filters(
778
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
779
-                            array(
780
-                                'revisit'                       => $this->checkout->revisit,
781
-                                'registrations'                 => array(),
782
-                                'ticket_count'                  => array(),
783
-                                'registrations_for_free_events' => $registrations_for_free_events,
784
-                                'no_payment_required_msg'       => EEH_HTML::p(
785
-                                    esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
786
-                                ),
787
-                            )
788
-                        ),
789
-                    )
790
-                ),
791
-            )
792
-        );
793
-    }
794
-
795
-
796
-    /**
797
-     * _display_payment_options
798
-     *
799
-     * @param string $transaction_details
800
-     * @return EE_Form_Section_Proper
801
-     * @throws EE_Error
802
-     * @throws InvalidArgumentException
803
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
804
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
805
-     */
806
-    private function _display_payment_options($transaction_details = '')
807
-    {
808
-        // has method_of_payment been set by no-js user?
809
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
810
-        // build payment options form
811
-        return apply_filters(
812
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
813
-            new EE_Form_Section_Proper(
814
-                array(
815
-                    'subsections'     => array(
816
-                        'before_payment_options' => apply_filters(
817
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
818
-                            new EE_Form_Section_Proper(
819
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
820
-                            )
821
-                        ),
822
-                        'payment_options'        => $this->_setup_payment_options(),
823
-                        'after_payment_options'  => apply_filters(
824
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
825
-                            new EE_Form_Section_Proper(
826
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
827
-                            )
828
-                        ),
829
-                    ),
830
-                    'layout_strategy' => new EE_Template_Layout(
831
-                        array(
832
-                            'layout_template_file' => $this->_template,
833
-                            'template_args'        => apply_filters(
834
-                                'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
835
-                                array(
836
-                                    'reg_count'                 => $this->line_item_display->total_items(),
837
-                                    'transaction_details'       => $transaction_details,
838
-                                    'available_payment_methods' => array(),
839
-                                )
840
-                            ),
841
-                        )
842
-                    ),
843
-                )
844
-            )
845
-        );
846
-    }
847
-
848
-
849
-    /**
850
-     * _extra_hidden_inputs
851
-     *
852
-     * @param bool $no_payment_required
853
-     * @return \EE_Form_Section_Proper
854
-     * @throws \EE_Error
855
-     */
856
-    private function _extra_hidden_inputs($no_payment_required = true)
857
-    {
858
-        return new EE_Form_Section_Proper(
859
-            array(
860
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
861
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
862
-                'subsections'     => array(
863
-                    'spco_no_payment_required' => new EE_Hidden_Input(
864
-                        array(
865
-                            'normalization_strategy' => new EE_Boolean_Normalization(),
866
-                            'html_name'              => 'spco_no_payment_required',
867
-                            'html_id'                => 'spco-no-payment-required-payment_options',
868
-                            'default'                => $no_payment_required,
869
-                        )
870
-                    ),
871
-                    'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
872
-                        array(
873
-                            'normalization_strategy' => new EE_Int_Normalization(),
874
-                            'html_name'              => 'spco_transaction_id',
875
-                            'html_id'                => 'spco-transaction-id',
876
-                            'default'                => $this->checkout->transaction->ID(),
877
-                        )
878
-                    ),
879
-                ),
880
-            )
881
-        );
882
-    }
883
-
884
-
885
-    /**
886
-     *    _apply_registration_payments_to_amount_owing
887
-     *
888
-     * @access protected
889
-     * @param array $registrations
890
-     * @throws EE_Error
891
-     */
892
-    protected function _apply_registration_payments_to_amount_owing(array $registrations)
893
-    {
894
-        $payments = array();
895
-        foreach ($registrations as $registration) {
896
-            if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
897
-                $payments += $registration->registration_payments();
898
-            }
899
-        }
900
-        if (! empty($payments)) {
901
-            foreach ($payments as $payment) {
902
-                if ($payment instanceof EE_Registration_Payment) {
903
-                    $this->checkout->amount_owing -= $payment->amount();
904
-                }
905
-            }
906
-        }
907
-    }
908
-
909
-
910
-    /**
911
-     *    _reset_selected_method_of_payment
912
-     *
913
-     * @access    private
914
-     * @param    bool $force_reset
915
-     * @return void
916
-     * @throws InvalidArgumentException
917
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919
-     */
920
-    private function _reset_selected_method_of_payment($force_reset = false)
921
-    {
922
-        $reset_payment_method = $force_reset
923
-            ? true
924
-            : sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
925
-        if ($reset_payment_method) {
926
-            $this->checkout->selected_method_of_payment = null;
927
-            $this->checkout->payment_method             = null;
928
-            $this->checkout->billing_form               = null;
929
-            $this->_save_selected_method_of_payment();
930
-        }
931
-    }
932
-
933
-
934
-    /**
935
-     * _save_selected_method_of_payment
936
-     * stores the selected_method_of_payment in the session
937
-     * so that it's available for all subsequent requests including AJAX
938
-     *
939
-     * @access        private
940
-     * @param string $selected_method_of_payment
941
-     * @return void
942
-     * @throws InvalidArgumentException
943
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
944
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
945
-     */
946
-    private function _save_selected_method_of_payment($selected_method_of_payment = '')
947
-    {
948
-        $selected_method_of_payment = ! empty($selected_method_of_payment)
949
-            ? $selected_method_of_payment
950
-            : $this->checkout->selected_method_of_payment;
951
-        EE_Registry::instance()->SSN->set_session_data(
952
-            array('selected_method_of_payment' => $selected_method_of_payment)
953
-        );
954
-    }
955
-
956
-
957
-    /**
958
-     * _setup_payment_options
959
-     *
960
-     * @return EE_Form_Section_Proper
961
-     * @throws EE_Error
962
-     * @throws InvalidArgumentException
963
-     * @throws ReflectionException
964
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
965
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
966
-     */
967
-    public function _setup_payment_options()
968
-    {
969
-        // load payment method classes
970
-        $this->checkout->available_payment_methods = $this->_get_available_payment_methods();
971
-        if (empty($this->checkout->available_payment_methods)) {
972
-            EE_Error::add_error(
973
-                apply_filters(
974
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
975
-                    sprintf(
976
-                        esc_html__(
977
-                            'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
978
-                            'event_espresso'
979
-                        ),
980
-                        '<br>',
981
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
982
-                    )
983
-                ),
984
-                __FILE__,
985
-                __FUNCTION__,
986
-                __LINE__
987
-            );
988
-        }
989
-        // switch up header depending on number of available payment methods
990
-        $payment_method_header     = count($this->checkout->available_payment_methods) > 1
991
-            ? apply_filters(
992
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
993
-                esc_html__('Please Select Your Method of Payment', 'event_espresso')
994
-            )
995
-            : apply_filters(
996
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
997
-                esc_html__('Method of Payment', 'event_espresso')
998
-            );
999
-        $available_payment_methods = array(
1000
-            // display the "Payment Method" header
1001
-            'payment_method_header' => new EE_Form_Section_HTML(
1002
-                EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr')
1003
-            ),
1004
-        );
1005
-        // the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1006
-        $available_payment_method_options = array();
1007
-        $default_payment_method_option    = array();
1008
-        // additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1009
-        $payment_methods_billing_info = array(
1010
-            new EE_Form_Section_HTML(
1011
-                EEH_HTML::div('<br />', '', '', 'clear:both;')
1012
-            ),
1013
-        );
1014
-        // loop through payment methods
1015
-        foreach ($this->checkout->available_payment_methods as $payment_method) {
1016
-            if ($payment_method instanceof EE_Payment_Method) {
1017
-                $payment_method_button = EEH_HTML::img(
1018
-                    $payment_method->button_url(),
1019
-                    $payment_method->name(),
1020
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1021
-                    'spco-payment-method-btn-img'
1022
-                );
1023
-                // check if any payment methods are set as default
1024
-                // if payment method is already selected OR nothing is selected and this payment method should be
1025
-                // open_by_default
1026
-                if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028
-                ) {
1029
-                    $this->checkout->selected_method_of_payment = $payment_method->slug();
1030
-                    $this->_save_selected_method_of_payment();
1031
-                    $default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1032
-                } else {
1033
-                    $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034
-                }
1035
-                $payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1036
-                    $payment_method
1037
-                );
1038
-            }
1039
-        }
1040
-        // prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1041
-        // of PMs
1042
-        $available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1043
-        // now generate the actual form  inputs
1044
-        $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045
-            $available_payment_method_options
1046
-        );
1047
-        $available_payment_methods                              += $payment_methods_billing_info;
1048
-        // build the available payment methods form
1049
-        return new EE_Form_Section_Proper(
1050
-            array(
1051
-                'html_id'         => 'spco-available-methods-of-payment-dv',
1052
-                'subsections'     => $available_payment_methods,
1053
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1054
-            )
1055
-        );
1056
-    }
1057
-
1058
-
1059
-    /**
1060
-     * _get_available_payment_methods
1061
-     *
1062
-     * @return EE_Payment_Method[]
1063
-     * @throws EE_Error
1064
-     * @throws InvalidArgumentException
1065
-     * @throws ReflectionException
1066
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1067
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1068
-     */
1069
-    protected function _get_available_payment_methods()
1070
-    {
1071
-        if (! empty($this->checkout->available_payment_methods)) {
1072
-            return $this->checkout->available_payment_methods;
1073
-        }
1074
-        $available_payment_methods = array();
1075
-        // load EEM_Payment_Method
1076
-        EE_Registry::instance()->load_model('Payment_Method');
1077
-        /** @type EEM_Payment_Method $EEM_Payment_Method */
1078
-        $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1079
-        // get all active payment methods
1080
-        $payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1081
-            $this->checkout->transaction,
1082
-            EEM_Payment_Method::scope_cart
1083
-        );
1084
-        foreach ($payment_methods as $payment_method) {
1085
-            if ($payment_method instanceof EE_Payment_Method) {
1086
-                $available_payment_methods[$payment_method->slug()] = $payment_method;
1087
-            }
1088
-        }
1089
-        return $available_payment_methods;
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     *    _available_payment_method_inputs
1095
-     *
1096
-     * @access    private
1097
-     * @param    array $available_payment_method_options
1098
-     * @return    \EE_Form_Section_Proper
1099
-     */
1100
-    private function _available_payment_method_inputs($available_payment_method_options = array())
1101
-    {
1102
-        // generate inputs
1103
-        return new EE_Form_Section_Proper(
1104
-            array(
1105
-                'html_id'         => 'ee-available-payment-method-inputs',
1106
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1107
-                'subsections'     => array(
1108
-                    '' => new EE_Radio_Button_Input(
1109
-                        $available_payment_method_options,
1110
-                        array(
1111
-                            'html_name'          => 'selected_method_of_payment',
1112
-                            'html_class'         => 'spco-payment-method',
1113
-                            'default'            => $this->checkout->selected_method_of_payment,
1114
-                            'label_size'         => 11,
1115
-                            'enforce_label_size' => true,
1116
-                        )
1117
-                    ),
1118
-                ),
1119
-            )
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    /**
1125
-     *    _payment_method_billing_info
1126
-     *
1127
-     * @access    private
1128
-     * @param    EE_Payment_Method $payment_method
1129
-     * @return EE_Form_Section_Proper
1130
-     * @throws EE_Error
1131
-     * @throws InvalidArgumentException
1132
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1133
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1134
-     */
1135
-    private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1136
-    {
1137
-        $currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1138
-            ? true
1139
-            : false;
1140
-        // generate the billing form for payment method
1141
-        $billing_form                 = $currently_selected
1142
-            ? $this->_get_billing_form_for_payment_method($payment_method)
1143
-            : new EE_Form_Section_HTML();
1144
-        $this->checkout->billing_form = $currently_selected
1145
-            ? $billing_form
1146
-            : $this->checkout->billing_form;
1147
-        // it's all in the details
1148
-        $info_html = EEH_HTML::h3(
1149
-            esc_html__('Important information regarding your payment', 'event_espresso'),
1150
-            '',
1151
-            'spco-payment-method-hdr'
1152
-        );
1153
-        // add some info regarding the step, either from what's saved in the admin,
1154
-        // or a default string depending on whether the PM has a billing form or not
1155
-        if ($payment_method->description()) {
1156
-            $payment_method_info = $payment_method->description();
1157
-        } elseif ($billing_form instanceof EE_Billing_Info_Form) {
1158
-            $payment_method_info = sprintf(
1159
-                esc_html__(
1160
-                    'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1161
-                    'event_espresso'
1162
-                ),
1163
-                $this->submit_button_text()
1164
-            );
1165
-        } else {
1166
-            $payment_method_info = sprintf(
1167
-                esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1168
-                $this->submit_button_text()
1169
-            );
1170
-        }
1171
-        $info_html .= EEH_HTML::p(
1172
-            apply_filters(
1173
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1174
-                $payment_method_info
1175
-            ),
1176
-            '',
1177
-            'spco-payment-method-desc ee-attention'
1178
-        );
1179
-        return new EE_Form_Section_Proper(
1180
-            array(
1181
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1182
-                'html_class'      => 'spco-payment-method-info-dv',
1183
-                // only display the selected or default PM
1184
-                'html_style'      => $currently_selected ? '' : 'display:none;',
1185
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1186
-                'subsections'     => array(
1187
-                    'info'         => new EE_Form_Section_HTML($info_html),
1188
-                    'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1189
-                ),
1190
-            )
1191
-        );
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * get_billing_form_html_for_payment_method
1197
-     *
1198
-     * @access public
1199
-     * @return string
1200
-     * @throws EE_Error
1201
-     * @throws InvalidArgumentException
1202
-     * @throws ReflectionException
1203
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1204
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1205
-     */
1206
-    public function get_billing_form_html_for_payment_method()
1207
-    {
1208
-        // how have they chosen to pay?
1209
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210
-        $this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212
-            return false;
1213
-        }
1214
-        if (apply_filters(
1215
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1216
-            false
1217
-        )) {
1218
-            EE_Error::add_success(
1219
-                apply_filters(
1220
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1221
-                    sprintf(
1222
-                        esc_html__(
1223
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1224
-                            'event_espresso'
1225
-                        ),
1226
-                        $this->checkout->payment_method->name()
1227
-                    )
1228
-                )
1229
-            );
1230
-        }
1231
-        // now generate billing form for selected method of payment
1232
-        $payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1233
-        // fill form with attendee info if applicable
1234
-        if ($payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1235
-            && $this->checkout->transaction_has_primary_registrant()
1236
-        ) {
1237
-            $payment_method_billing_form->populate_from_attendee(
1238
-                $this->checkout->transaction->primary_registration()->attendee()
1239
-            );
1240
-        }
1241
-        // and debug content
1242
-        if ($payment_method_billing_form instanceof EE_Billing_Info_Form
1243
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1244
-        ) {
1245
-            $payment_method_billing_form =
1246
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1247
-                    $payment_method_billing_form
1248
-                );
1249
-        }
1250
-        $billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1251
-            ? $payment_method_billing_form->get_html()
1252
-            : '';
1253
-        $this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1254
-        // localize validation rules for main form
1255
-        $this->checkout->current_step->reg_form->localize_validation_rules();
1256
-        $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1257
-        return true;
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * _get_billing_form_for_payment_method
1263
-     *
1264
-     * @access private
1265
-     * @param EE_Payment_Method $payment_method
1266
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1267
-     * @throws EE_Error
1268
-     * @throws InvalidArgumentException
1269
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1270
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1271
-     */
1272
-    private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1273
-    {
1274
-        $billing_form = $payment_method->type_obj()->billing_form(
1275
-            $this->checkout->transaction,
1276
-            array('amount_owing' => $this->checkout->amount_owing)
1277
-        );
1278
-        if ($billing_form instanceof EE_Billing_Info_Form) {
1279
-            if (apply_filters(
1280
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1281
-                false
1282
-            )
1283
-                && EE_Registry::instance()->REQ->is_set('payment_method')
1284
-            ) {
1285
-                EE_Error::add_success(
1286
-                    apply_filters(
1287
-                        'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1288
-                        sprintf(
1289
-                            esc_html__(
1290
-                                'You have selected "%s" as your method of payment. Please note the important payment information below.',
1291
-                                'event_espresso'
1292
-                            ),
1293
-                            $payment_method->name()
1294
-                        )
1295
-                    )
1296
-                );
1297
-            }
1298
-            return apply_filters(
1299
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1300
-                $billing_form,
1301
-                $payment_method
1302
-            );
1303
-        }
1304
-        // no actual billing form, so return empty HTML form section
1305
-        return new EE_Form_Section_HTML();
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * _get_selected_method_of_payment
1311
-     *
1312
-     * @access private
1313
-     * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1314
-     *                          is not found in the incoming request
1315
-     * @param string  $request_param
1316
-     * @return NULL|string
1317
-     * @throws EE_Error
1318
-     * @throws InvalidArgumentException
1319
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1320
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1321
-     */
1322
-    private function _get_selected_method_of_payment(
1323
-        $required = false,
1324
-        $request_param = 'selected_method_of_payment'
1325
-    ) {
1326
-        // is selected_method_of_payment set in the request ?
1327
-        $selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1328
-        if ($selected_method_of_payment) {
1329
-            // sanitize it
1330
-            $selected_method_of_payment = is_array($selected_method_of_payment)
1331
-                ? array_shift($selected_method_of_payment)
1332
-                : $selected_method_of_payment;
1333
-            $selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1334
-            // store it in the session so that it's available for all subsequent requests including AJAX
1335
-            $this->_save_selected_method_of_payment($selected_method_of_payment);
1336
-        } else {
1337
-            // or is is set in the session ?
1338
-            $selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1339
-                'selected_method_of_payment'
1340
-            );
1341
-        }
1342
-        // do ya really really gotta have it?
1343
-        if (empty($selected_method_of_payment) && $required) {
1344
-            EE_Error::add_error(
1345
-                sprintf(
1346
-                    esc_html__(
1347
-                        'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1348
-                        'event_espresso'
1349
-                    ),
1350
-                    '<br/>',
1351
-                    '<br/>',
1352
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
1353
-                ),
1354
-                __FILE__,
1355
-                __FUNCTION__,
1356
-                __LINE__
1357
-            );
1358
-            return null;
1359
-        }
1360
-        return $selected_method_of_payment;
1361
-    }
1362
-
1363
-
1364
-
1365
-
1366
-
1367
-
1368
-    /********************************************************************************************************/
1369
-    /***********************************  SWITCH PAYMENT METHOD  ************************************/
1370
-    /********************************************************************************************************/
1371
-    /**
1372
-     * switch_payment_method
1373
-     *
1374
-     * @access public
1375
-     * @return string
1376
-     * @throws EE_Error
1377
-     * @throws InvalidArgumentException
1378
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1379
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1380
-     */
1381
-    public function switch_payment_method()
1382
-    {
1383
-        if (! $this->_verify_payment_method_is_set()) {
1384
-            return false;
1385
-        }
1386
-        if (apply_filters(
1387
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1388
-            false
1389
-        )) {
1390
-            EE_Error::add_success(
1391
-                apply_filters(
1392
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1393
-                    sprintf(
1394
-                        esc_html__(
1395
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1396
-                            'event_espresso'
1397
-                        ),
1398
-                        $this->checkout->payment_method->name()
1399
-                    )
1400
-                )
1401
-            );
1402
-        }
1403
-        // generate billing form for selected method of payment if it hasn't been done already
1404
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1405
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1406
-                $this->checkout->payment_method
1407
-            );
1408
-        }
1409
-        // fill form with attendee info if applicable
1410
-        if (apply_filters(
1411
-            'FHEE__populate_billing_form_fields_from_attendee',
1412
-            (
1413
-                $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1414
-                && $this->checkout->transaction_has_primary_registrant()
1415
-            ),
1416
-            $this->checkout->billing_form,
1417
-            $this->checkout->transaction
1418
-        )
1419
-        ) {
1420
-            $this->checkout->billing_form->populate_from_attendee(
1421
-                $this->checkout->transaction->primary_registration()->attendee()
1422
-            );
1423
-        }
1424
-        // and debug content
1425
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form
1426
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1427
-        ) {
1428
-            $this->checkout->billing_form =
1429
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1430
-                    $this->checkout->billing_form
1431
-                );
1432
-        }
1433
-        // get html and validation rules for form
1434
-        if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1435
-            $this->checkout->json_response->set_return_data(
1436
-                array('payment_method_info' => $this->checkout->billing_form->get_html())
1437
-            );
1438
-            // localize validation rules for main form
1439
-            $this->checkout->billing_form->localize_validation_rules(true);
1440
-            $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1441
-        } else {
1442
-            $this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1443
-        }
1444
-        //prevents advancement to next step
1445
-        $this->checkout->continue_reg = false;
1446
-        return true;
1447
-    }
1448
-
1449
-
1450
-    /**
1451
-     * _verify_payment_method_is_set
1452
-     *
1453
-     * @return bool
1454
-     * @throws EE_Error
1455
-     * @throws InvalidArgumentException
1456
-     * @throws ReflectionException
1457
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1458
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1459
-     */
1460
-    protected function _verify_payment_method_is_set()
1461
-    {
1462
-        // generate billing form for selected method of payment if it hasn't been done already
1463
-        if (empty($this->checkout->selected_method_of_payment)) {
1464
-            // how have they chosen to pay?
1465
-            $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1466
-        } else {
1467
-            // choose your own adventure based on method_of_payment
1468
-            switch ($this->checkout->selected_method_of_payment) {
1469
-                case 'events_sold_out' :
1470
-                    EE_Error::add_attention(
1471
-                        apply_filters(
1472
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1473
-                            esc_html__(
1474
-                                'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1475
-                                'event_espresso'
1476
-                            )
1477
-                        ),
1478
-                        __FILE__, __FUNCTION__, __LINE__
1479
-                    );
1480
-                    return false;
1481
-                    break;
1482
-                case 'payments_closed' :
1483
-                    EE_Error::add_attention(
1484
-                        apply_filters(
1485
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1486
-                            esc_html__(
1487
-                                'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1488
-                                'event_espresso'
1489
-                            )
1490
-                        ),
1491
-                        __FILE__, __FUNCTION__, __LINE__
1492
-                    );
1493
-                    return false;
1494
-                    break;
1495
-                case 'no_payment_required' :
1496
-                    EE_Error::add_attention(
1497
-                        apply_filters(
1498
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1499
-                            esc_html__(
1500
-                                'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1501
-                                'event_espresso'
1502
-                            )
1503
-                        ),
1504
-                        __FILE__, __FUNCTION__, __LINE__
1505
-                    );
1506
-                    return false;
1507
-                    break;
1508
-                default:
1509
-            }
1510
-        }
1511
-        // verify payment method
1512
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513
-            // get payment method for selected method of payment
1514
-            $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515
-        }
1516
-        return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1517
-    }
1518
-
1519
-
1520
-
1521
-    /********************************************************************************************************/
1522
-    /***************************************  SAVE PAYER DETAILS  ****************************************/
1523
-    /********************************************************************************************************/
1524
-    /**
1525
-     * save_payer_details_via_ajax
1526
-     *
1527
-     * @return void
1528
-     * @throws EE_Error
1529
-     * @throws InvalidArgumentException
1530
-     * @throws ReflectionException
1531
-     * @throws RuntimeException
1532
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1533
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1534
-     */
1535
-    public function save_payer_details_via_ajax()
1536
-    {
1537
-        if (! $this->_verify_payment_method_is_set()) {
1538
-            return;
1539
-        }
1540
-        // generate billing form for selected method of payment if it hasn't been done already
1541
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1542
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1543
-                $this->checkout->payment_method
1544
-            );
1545
-        }
1546
-        // generate primary attendee from payer info if applicable
1547
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1548
-            $attendee = $this->_create_attendee_from_request_data();
1549
-            if ($attendee instanceof EE_Attendee) {
1550
-                foreach ($this->checkout->transaction->registrations() as $registration) {
1551
-                    if ($registration->is_primary_registrant()) {
1552
-                        $this->checkout->primary_attendee_obj = $attendee;
1553
-                        $registration->_add_relation_to($attendee, 'Attendee');
1554
-                        $registration->set_attendee_id($attendee->ID());
1555
-                        $registration->update_cache_after_object_save('Attendee', $attendee);
1556
-                    }
1557
-                }
1558
-            }
1559
-        }
1560
-    }
1561
-
1562
-
1563
-    /**
1564
-     * create_attendee_from_request_data
1565
-     * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1566
-     *
1567
-     * @return EE_Attendee
1568
-     * @throws EE_Error
1569
-     * @throws InvalidArgumentException
1570
-     * @throws ReflectionException
1571
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1572
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1573
-     */
1574
-    protected function _create_attendee_from_request_data()
1575
-    {
1576
-        // get State ID
1577
-        $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
-        if (! empty($STA_ID)) {
1579
-            // can we get state object from name ?
1580
-            EE_Registry::instance()->load_model('State');
1581
-            $state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1582
-            $STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1583
-        }
1584
-        // get Country ISO
1585
-        $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
-        if (! empty($CNT_ISO)) {
1587
-            // can we get country object from name ?
1588
-            EE_Registry::instance()->load_model('Country');
1589
-            $country = EEM_Country::instance()->get_col(
1590
-                array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1591
-                'CNT_ISO'
1592
-            );
1593
-            $CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1594
-        }
1595
-        // grab attendee data
1596
-        $attendee_data = array(
1597
-            'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1598
-            'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1599
-            'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1600
-            'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1601
-            'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1602
-            'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1603
-            'STA_ID'       => $STA_ID,
1604
-            'CNT_ISO'      => $CNT_ISO,
1605
-            'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1606
-            'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1607
-        );
1608
-        // validate the email address since it is the most important piece of info
1609
-        if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1610
-            EE_Error::add_error(
1611
-                esc_html__('An invalid email address was submitted.', 'event_espresso'),
1612
-                __FILE__,
1613
-                __FUNCTION__,
1614
-                __LINE__
1615
-            );
1616
-        }
1617
-        // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618
-        // AND email address
1619
-        if (! empty($attendee_data['ATT_fname'])
1620
-            && ! empty($attendee_data['ATT_lname'])
1621
-            && ! empty($attendee_data['ATT_email'])
1622
-        ) {
1623
-            $existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1624
-                array(
1625
-                    'ATT_fname' => $attendee_data['ATT_fname'],
1626
-                    'ATT_lname' => $attendee_data['ATT_lname'],
1627
-                    'ATT_email' => $attendee_data['ATT_email'],
1628
-                )
1629
-            );
1630
-            if ($existing_attendee instanceof EE_Attendee) {
1631
-                return $existing_attendee;
1632
-            }
1633
-        }
1634
-        // no existing attendee? kk let's create a new one
1635
-        // kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1636
-        // don't exist
1637
-        $attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1638
-            ? $attendee_data['ATT_fname']
1639
-            : $attendee_data['ATT_email'];
1640
-        $attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1641
-            ? $attendee_data['ATT_lname']
1642
-            : $attendee_data['ATT_email'];
1643
-        return EE_Attendee::new_instance($attendee_data);
1644
-    }
1645
-
1646
-
1647
-
1648
-    /********************************************************************************************************/
1649
-    /****************************************  PROCESS REG STEP  *****************************************/
1650
-    /********************************************************************************************************/
1651
-    /**
1652
-     * process_reg_step
1653
-     *
1654
-     * @return bool
1655
-     * @throws EE_Error
1656
-     * @throws InvalidArgumentException
1657
-     * @throws ReflectionException
1658
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1659
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1660
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1661
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1662
-     */
1663
-    public function process_reg_step()
1664
-    {
1665
-        // how have they chosen to pay?
1666
-        $this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1667
-            ? 'no_payment_required'
1668
-            : $this->_get_selected_method_of_payment(true);
1669
-        // choose your own adventure based on method_of_payment
1670
-        switch ($this->checkout->selected_method_of_payment) {
1671
-
1672
-            case 'events_sold_out' :
1673
-                $this->checkout->redirect     = true;
1674
-                $this->checkout->redirect_url = $this->checkout->cancel_page_url;
1675
-                $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1676
-                // mark this reg step as completed
1677
-                $this->set_completed();
1678
-                return false;
1679
-                break;
1680
-
1681
-            case 'payments_closed' :
1682
-                if (apply_filters(
1683
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1684
-                    false
1685
-                )) {
1686
-                    EE_Error::add_success(
1687
-                        esc_html__('no payment required at this time.', 'event_espresso'),
1688
-                        __FILE__,
1689
-                        __FUNCTION__,
1690
-                        __LINE__
1691
-                    );
1692
-                }
1693
-                // mark this reg step as completed
1694
-                $this->set_completed();
1695
-                return true;
1696
-                break;
1697
-
1698
-            case 'no_payment_required' :
1699
-                if (apply_filters(
1700
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1701
-                    false
1702
-                )) {
1703
-                    EE_Error::add_success(
1704
-                        esc_html__('no payment required.', 'event_espresso'),
1705
-                        __FILE__,
1706
-                        __FUNCTION__,
1707
-                        __LINE__
1708
-                    );
1709
-                }
1710
-                // mark this reg step as completed
1711
-                $this->set_completed();
1712
-                return true;
1713
-                break;
1714
-
1715
-            default:
1716
-                $registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1717
-                    EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1718
-                );
1719
-                $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1720
-                    $registrations,
1721
-                    EE_Registry::instance()->SSN->checkout()->revisit
1722
-                );
1723
-                // calculate difference between the two arrays
1724
-                $registrations = array_diff($registrations, $ejected_registrations);
1725
-                if (empty($registrations)) {
1726
-                    $this->_redirect_because_event_sold_out();
1727
-                    return false;
1728
-                }
1729
-                $payment_successful = $this->_process_payment();
1730
-                if ($payment_successful) {
1731
-                    $this->checkout->continue_reg = true;
1732
-                    $this->_maybe_set_completed($this->checkout->payment_method);
1733
-                } else {
1734
-                    $this->checkout->continue_reg = false;
1735
-                }
1736
-                return $payment_successful;
1737
-        }
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * _redirect_because_event_sold_out
1743
-     *
1744
-     * @access protected
1745
-     * @return void
1746
-     */
1747
-    protected function _redirect_because_event_sold_out()
1748
-    {
1749
-        $this->checkout->continue_reg = false;
1750
-        // set redirect URL
1751
-        $this->checkout->redirect_url = add_query_arg(
1752
-            array('e_reg_url_link' => $this->checkout->reg_url_link),
1753
-            $this->checkout->current_step->reg_step_url()
1754
-        );
1755
-        $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1756
-    }
1757
-
1758
-
1759
-    /**
1760
-     * _maybe_set_completed
1761
-     *
1762
-     * @access protected
1763
-     * @param \EE_Payment_Method $payment_method
1764
-     * @return void
1765
-     * @throws \EE_Error
1766
-     */
1767
-    protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1768
-    {
1769
-        switch ($payment_method->type_obj()->payment_occurs()) {
1770
-            case EE_PMT_Base::offsite :
1771
-                break;
1772
-            case EE_PMT_Base::onsite :
1773
-            case EE_PMT_Base::offline :
1774
-                // mark this reg step as completed
1775
-                $this->set_completed();
1776
-                break;
1777
-        }
1778
-    }
1779
-
1780
-
1781
-    /**
1782
-     *    update_reg_step
1783
-     *    this is the final step after a user  revisits the site to retry a payment
1784
-     *
1785
-     * @return bool
1786
-     * @throws EE_Error
1787
-     * @throws InvalidArgumentException
1788
-     * @throws ReflectionException
1789
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1790
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1791
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1792
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1793
-     */
1794
-    public function update_reg_step()
1795
-    {
1796
-        $success = true;
1797
-        // if payment required
1798
-        if ($this->checkout->transaction->total() > 0) {
1799
-            do_action(
1800
-                'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1801
-                $this->checkout->transaction
1802
-            );
1803
-            // attempt payment via payment method
1804
-            $success = $this->process_reg_step();
1805
-        }
1806
-        if ($success && ! $this->checkout->redirect) {
1807
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1808
-                $this->checkout->transaction->ID()
1809
-            );
1810
-            // set return URL
1811
-            $this->checkout->redirect_url = add_query_arg(
1812
-                array('e_reg_url_link' => $this->checkout->reg_url_link),
1813
-                $this->checkout->thank_you_page_url
1814
-            );
1815
-        }
1816
-        return $success;
1817
-    }
1818
-
1819
-
1820
-    /**
1821
-     *    _process_payment
1822
-     *
1823
-     * @access private
1824
-     * @return bool
1825
-     * @throws EE_Error
1826
-     * @throws InvalidArgumentException
1827
-     * @throws ReflectionException
1828
-     * @throws RuntimeException
1829
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1830
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1831
-     */
1832
-    private function _process_payment()
1833
-    {
1834
-        // basically confirm that the event hasn't sold out since they hit the page
1835
-        if (! $this->_last_second_ticket_verifications()) {
1836
-            return false;
1837
-        }
1838
-        // ya gotta make a choice man
1839
-        if (empty($this->checkout->selected_method_of_payment)) {
1840
-            $this->checkout->json_response->set_plz_select_method_of_payment(
1841
-                esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1842
-            );
1843
-            return false;
1844
-        }
1845
-        // get EE_Payment_Method object
1846
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847
-            return false;
1848
-        }
1849
-        // setup billing form
1850
-        if ($this->checkout->payment_method->is_on_site()) {
1851
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1852
-                $this->checkout->payment_method
1853
-            );
1854
-            // bad billing form ?
1855
-            if (! $this->_billing_form_is_valid()) {
1856
-                return false;
1857
-            }
1858
-        }
1859
-        // ensure primary registrant has been fully processed
1860
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1861
-            return false;
1862
-        }
1863
-        // if session is close to expiring (under 10 minutes by default)
1864
-        if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1865
-            // add some time to session expiration so that payment can be completed
1866
-            EE_Registry::instance()->SSN->extend_expiration();
1867
-        }
1868
-        /** @type EE_Transaction_Processor $transaction_processor */
1869
-        //$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1870
-        // in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1871
-        // for events with a default reg status of Approved
1872
-        // $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1873
-        //      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1874
-        // );
1875
-        // attempt payment
1876
-        $payment = $this->_attempt_payment($this->checkout->payment_method);
1877
-        // process results
1878
-        $payment = $this->_validate_payment($payment);
1879
-        $payment = $this->_post_payment_processing($payment);
1880
-        // verify payment
1881
-        if ($payment instanceof EE_Payment) {
1882
-            // store that for later
1883
-            $this->checkout->payment = $payment;
1884
-            // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1885
-            $this->checkout->transaction->toggle_failed_transaction_status();
1886
-            $payment_status = $payment->status();
1887
-            if (
1888
-                $payment_status === EEM_Payment::status_id_approved
1889
-                || $payment_status === EEM_Payment::status_id_pending
1890
-            ) {
1891
-                return true;
1892
-            } else {
1893
-                return false;
1894
-            }
1895
-        } else if ($payment === true) {
1896
-            // please note that offline payment methods will NOT make a payment,
1897
-            // but instead just mark themselves as the PMD_ID on the transaction, and return true
1898
-            $this->checkout->payment = $payment;
1899
-            return true;
1900
-        }
1901
-        // where's my money?
1902
-        return false;
1903
-    }
1904
-
1905
-
1906
-    /**
1907
-     * _last_second_ticket_verifications
1908
-     *
1909
-     * @access public
1910
-     * @return bool
1911
-     * @throws EE_Error
1912
-     */
1913
-    protected function _last_second_ticket_verifications()
1914
-    {
1915
-        // don't bother re-validating if not a return visit
1916
-        if (! $this->checkout->revisit) {
1917
-            return true;
1918
-        }
1919
-        $registrations = $this->checkout->transaction->registrations();
1920
-        if (empty($registrations)) {
1921
-            return false;
1922
-        }
1923
-        foreach ($registrations as $registration) {
1924
-            if ($registration instanceof EE_Registration) {
1925
-                $event = $registration->event_obj();
1926
-                if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1927
-                    EE_Error::add_error(
1928
-                        apply_filters(
1929
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1930
-                            sprintf(
1931
-                                esc_html__(
1932
-                                    'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1933
-                                    'event_espresso'
1934
-                                ),
1935
-                                $event->name()
1936
-                            )
1937
-                        ),
1938
-                        __FILE__,
1939
-                        __FUNCTION__,
1940
-                        __LINE__
1941
-                    );
1942
-                    return false;
1943
-                }
1944
-            }
1945
-        }
1946
-        return true;
1947
-    }
1948
-
1949
-
1950
-    /**
1951
-     * redirect_form
1952
-     *
1953
-     * @access public
1954
-     * @return bool
1955
-     * @throws EE_Error
1956
-     * @throws InvalidArgumentException
1957
-     * @throws ReflectionException
1958
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1959
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1960
-     */
1961
-    public function redirect_form()
1962
-    {
1963
-        $payment_method_billing_info = $this->_payment_method_billing_info(
1964
-            $this->_get_payment_method_for_selected_method_of_payment()
1965
-        );
1966
-        $html                        = $payment_method_billing_info->get_html();
1967
-        $html                        .= $this->checkout->redirect_form;
1968
-        EE_Registry::instance()->REQ->add_output($html);
1969
-        return true;
1970
-    }
1971
-
1972
-
1973
-    /**
1974
-     * _billing_form_is_valid
1975
-     *
1976
-     * @access private
1977
-     * @return bool
1978
-     * @throws \EE_Error
1979
-     */
1980
-    private function _billing_form_is_valid()
1981
-    {
1982
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983
-            return true;
1984
-        }
1985
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1986
-            if ($this->checkout->billing_form->was_submitted()) {
1987
-                $this->checkout->billing_form->receive_form_submission();
1988
-                if ($this->checkout->billing_form->is_valid()) {
1989
-                    return true;
1990
-                }
1991
-                $validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
1992
-                $error_strings     = array();
1993
-                foreach ($validation_errors as $validation_error) {
1994
-                    if ($validation_error instanceof EE_Validation_Error) {
1995
-                        $form_section = $validation_error->get_form_section();
1996
-                        if ($form_section instanceof EE_Form_Input_Base) {
1997
-                            $label = $form_section->html_label_text();
1998
-                        } elseif ($form_section instanceof EE_Form_Section_Base) {
1999
-                            $label = $form_section->name();
2000
-                        } else {
2001
-                            $label = esc_html__('Validation Error', 'event_espresso');
2002
-                        }
2003
-                        $error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2004
-                    }
2005
-                }
2006
-                EE_Error::add_error(
2007
-                    sprintf(
2008
-                        esc_html__(
2009
-                            'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2010
-                            'event_espresso'
2011
-                        ),
2012
-                        '<br/>',
2013
-                        implode('<br/>', $error_strings)
2014
-                    ),
2015
-                    __FILE__,
2016
-                    __FUNCTION__,
2017
-                    __LINE__
2018
-                );
2019
-            } else {
2020
-                EE_Error::add_error(
2021
-                    esc_html__(
2022
-                        'The billing form was not submitted or something prevented it\'s submission.',
2023
-                        'event_espresso'
2024
-                    ),
2025
-                    __FILE__,
2026
-                    __FUNCTION__,
2027
-                    __LINE__
2028
-                );
2029
-            }
2030
-        } else {
2031
-            EE_Error::add_error(
2032
-                esc_html__('The submitted billing form is invalid possibly due to a technical reason.', 'event_espresso'),
2033
-                __FILE__,
2034
-                __FUNCTION__,
2035
-                __LINE__
2036
-            );
2037
-        }
2038
-        return false;
2039
-    }
2040
-
2041
-
2042
-    /**
2043
-     * _setup_primary_registrant_prior_to_payment
2044
-     * ensures that the primary registrant has a valid attendee object created with the critical details populated
2045
-     * (first & last name & email) and that both the transaction object and primary registration object have been saved
2046
-     * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2047
-     * yet)
2048
-     *
2049
-     * @access private
2050
-     * @return bool
2051
-     * @throws EE_Error
2052
-     * @throws InvalidArgumentException
2053
-     * @throws ReflectionException
2054
-     * @throws RuntimeException
2055
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2056
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2057
-     */
2058
-    private function _setup_primary_registrant_prior_to_payment()
2059
-    {
2060
-        // check if transaction has a primary registrant and that it has a related Attendee object
2061
-        // if not, then we need to at least gather some primary registrant data before attempting payment
2062
-        if (
2063
-            $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2064
-            && ! $this->checkout->transaction_has_primary_registrant()
2065
-            && ! $this->_capture_primary_registration_data_from_billing_form()
2066
-        ) {
2067
-            return false;
2068
-        }
2069
-        // because saving an object clears it's cache, we need to do the chevy shuffle
2070
-        // grab the primary_registration object
2071
-        $primary_registration = $this->checkout->transaction->primary_registration();
2072
-        // at this point we'll consider a TXN to not have been failed
2073
-        $this->checkout->transaction->toggle_failed_transaction_status();
2074
-        // save the TXN ( which clears cached copy of primary_registration)
2075
-        $this->checkout->transaction->save();
2076
-        // grab TXN ID and save it to the primary_registration
2077
-        $primary_registration->set_transaction_id($this->checkout->transaction->ID());
2078
-        // save what we have so far
2079
-        $primary_registration->save();
2080
-        return true;
2081
-    }
2082
-
2083
-
2084
-    /**
2085
-     * _capture_primary_registration_data_from_billing_form
2086
-     *
2087
-     * @access private
2088
-     * @return bool
2089
-     * @throws EE_Error
2090
-     * @throws InvalidArgumentException
2091
-     * @throws ReflectionException
2092
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2093
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2094
-     */
2095
-    private function _capture_primary_registration_data_from_billing_form()
2096
-    {
2097
-        // convert billing form data into an attendee
2098
-        $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100
-            EE_Error::add_error(
2101
-                sprintf(
2102
-                    esc_html__(
2103
-                        'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2104
-                        'event_espresso'
2105
-                    ),
2106
-                    '<br/>',
2107
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2108
-                ),
2109
-                __FILE__,
2110
-                __FUNCTION__,
2111
-                __LINE__
2112
-            );
2113
-            return false;
2114
-        }
2115
-        $primary_registration = $this->checkout->transaction->primary_registration();
2116
-        if (! $primary_registration instanceof EE_Registration) {
2117
-            EE_Error::add_error(
2118
-                sprintf(
2119
-                    esc_html__(
2120
-                        'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2121
-                        'event_espresso'
2122
-                    ),
2123
-                    '<br/>',
2124
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2125
-                ),
2126
-                __FILE__,
2127
-                __FUNCTION__,
2128
-                __LINE__
2129
-            );
2130
-            return false;
2131
-        }
2132
-        if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133
-              instanceof
2134
-              EE_Attendee
2135
-        ) {
2136
-            EE_Error::add_error(
2137
-                sprintf(
2138
-                    esc_html__(
2139
-                        'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2140
-                        'event_espresso'
2141
-                    ),
2142
-                    '<br/>',
2143
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2144
-                ),
2145
-                __FILE__,
2146
-                __FUNCTION__,
2147
-                __LINE__
2148
-            );
2149
-            return false;
2150
-        }
2151
-        /** @type EE_Registration_Processor $registration_processor */
2152
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2153
-        // at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2154
-        $registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2155
-        return true;
2156
-    }
2157
-
2158
-
2159
-    /**
2160
-     * _get_payment_method_for_selected_method_of_payment
2161
-     * retrieves a valid payment method
2162
-     *
2163
-     * @access public
2164
-     * @return EE_Payment_Method
2165
-     * @throws EE_Error
2166
-     * @throws InvalidArgumentException
2167
-     * @throws ReflectionException
2168
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2169
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2170
-     */
2171
-    private function _get_payment_method_for_selected_method_of_payment()
2172
-    {
2173
-        if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2174
-            $this->_redirect_because_event_sold_out();
2175
-            return null;
2176
-        }
2177
-        // get EE_Payment_Method object
2178
-        if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2179
-            $payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2180
-        } else {
2181
-            // load EEM_Payment_Method
2182
-            EE_Registry::instance()->load_model('Payment_Method');
2183
-            /** @type EEM_Payment_Method $EEM_Payment_Method */
2184
-            $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2185
-            $payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186
-        }
2187
-        // verify $payment_method
2188
-        if (! $payment_method instanceof EE_Payment_Method) {
2189
-            // not a payment
2190
-            EE_Error::add_error(
2191
-                sprintf(
2192
-                    esc_html__(
2193
-                        'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2194
-                        'event_espresso'
2195
-                    ),
2196
-                    '<br/>',
2197
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2198
-                ),
2199
-                __FILE__,
2200
-                __FUNCTION__,
2201
-                __LINE__
2202
-            );
2203
-            return null;
2204
-        }
2205
-        // and verify it has a valid Payment_Method Type object
2206
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207
-            // not a payment
2208
-            EE_Error::add_error(
2209
-                sprintf(
2210
-                    esc_html__(
2211
-                        'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2212
-                        'event_espresso'
2213
-                    ),
2214
-                    '<br/>',
2215
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2216
-                ),
2217
-                __FILE__,
2218
-                __FUNCTION__,
2219
-                __LINE__
2220
-            );
2221
-            return null;
2222
-        }
2223
-        return $payment_method;
2224
-    }
2225
-
2226
-
2227
-    /**
2228
-     *    _attempt_payment
2229
-     *
2230
-     * @access    private
2231
-     * @type    EE_Payment_Method $payment_method
2232
-     * @return mixed EE_Payment | boolean
2233
-     * @throws EE_Error
2234
-     * @throws InvalidArgumentException
2235
-     * @throws ReflectionException
2236
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2237
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2238
-     */
2239
-    private function _attempt_payment(EE_Payment_Method $payment_method)
2240
-    {
2241
-        $payment = null;
2242
-        $this->checkout->transaction->save();
2243
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2245
-            return false;
2246
-        }
2247
-        try {
2248
-            $payment_processor->set_revisit($this->checkout->revisit);
2249
-            // generate payment object
2250
-            $payment = $payment_processor->process_payment(
2251
-                $payment_method,
2252
-                $this->checkout->transaction,
2253
-                $this->checkout->amount_owing,
2254
-                $this->checkout->billing_form,
2255
-                $this->_get_return_url($payment_method),
2256
-                'CART',
2257
-                $this->checkout->admin_request,
2258
-                true,
2259
-                $this->reg_step_url()
2260
-            );
2261
-        } catch (Exception $e) {
2262
-            $this->_handle_payment_processor_exception($e);
2263
-        }
2264
-        return $payment;
2265
-    }
2266
-
2267
-
2268
-    /**
2269
-     * _handle_payment_processor_exception
2270
-     *
2271
-     * @access protected
2272
-     * @param \Exception $e
2273
-     * @return void
2274
-     * @throws EE_Error
2275
-     * @throws InvalidArgumentException
2276
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2277
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2278
-     */
2279
-    protected function _handle_payment_processor_exception(Exception $e)
2280
-    {
2281
-        EE_Error::add_error(
2282
-            sprintf(
2283
-                esc_html__(
2284
-                    'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2285
-                    'event_espresso'
2286
-                ),
2287
-                '<br/>',
2288
-                EE_Registry::instance()->CFG->organization->get_pretty('email'),
2289
-                $e->getMessage(),
2290
-                $e->getFile(),
2291
-                $e->getLine()
2292
-            ),
2293
-            __FILE__,
2294
-            __FUNCTION__,
2295
-            __LINE__
2296
-        );
2297
-    }
2298
-
2299
-
2300
-    /**
2301
-     * _get_return_url
2302
-     *
2303
-     * @access protected
2304
-     * @param \EE_Payment_Method $payment_method
2305
-     * @return string
2306
-     * @throws \EE_Error
2307
-     */
2308
-    protected function _get_return_url(EE_Payment_Method $payment_method)
2309
-    {
2310
-        $return_url = '';
2311
-        switch ($payment_method->type_obj()->payment_occurs()) {
2312
-            case EE_PMT_Base::offsite :
2313
-                $return_url = add_query_arg(
2314
-                    array(
2315
-                        'action'                     => 'process_gateway_response',
2316
-                        'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2317
-                        'spco_txn'                   => $this->checkout->transaction->ID(),
2318
-                    ),
2319
-                    $this->reg_step_url()
2320
-                );
2321
-                break;
2322
-            case EE_PMT_Base::onsite :
2323
-            case EE_PMT_Base::offline :
2324
-                $return_url = $this->checkout->next_step->reg_step_url();
2325
-                break;
2326
-        }
2327
-        return $return_url;
2328
-    }
2329
-
2330
-
2331
-    /**
2332
-     * _validate_payment
2333
-     *
2334
-     * @access private
2335
-     * @param EE_Payment $payment
2336
-     * @return EE_Payment|FALSE
2337
-     * @throws EE_Error
2338
-     * @throws InvalidArgumentException
2339
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2340
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2341
-     */
2342
-    private function _validate_payment($payment = null)
2343
-    {
2344
-        if ($this->checkout->payment_method->is_off_line()) {
2345
-            return true;
2346
-        }
2347
-        // verify payment object
2348
-        if (! $payment instanceof EE_Payment) {
2349
-            // not a payment
2350
-            EE_Error::add_error(
2351
-                sprintf(
2352
-                    esc_html__(
2353
-                        'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2354
-                        'event_espresso'
2355
-                    ),
2356
-                    '<br/>',
2357
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2358
-                ),
2359
-                __FILE__,
2360
-                __FUNCTION__,
2361
-                __LINE__
2362
-            );
2363
-            return false;
2364
-        }
2365
-        return $payment;
2366
-    }
2367
-
2368
-
2369
-    /**
2370
-     * _post_payment_processing
2371
-     *
2372
-     * @access private
2373
-     * @param EE_Payment|bool $payment
2374
-     * @return bool
2375
-     * @throws EE_Error
2376
-     * @throws InvalidArgumentException
2377
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2378
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2379
-     */
2380
-    private function _post_payment_processing($payment = null)
2381
-    {
2382
-        // Off-Line payment?
2383
-        if ($payment === true) {
2384
-            //$this->_setup_redirect_for_next_step();
2385
-            return true;
2386
-            // On-Site payment?
2387
-        } else if ($this->checkout->payment_method->is_on_site()) {
2388
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389
-                //$this->_setup_redirect_for_next_step();
2390
-                $this->checkout->continue_reg = false;
2391
-            }
2392
-            // Off-Site payment?
2393
-        } else if ($this->checkout->payment_method->is_off_site()) {
2394
-            // if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2395
-            if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2396
-                do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2397
-                $this->checkout->redirect      = true;
2398
-                $this->checkout->redirect_form = $payment->redirect_form();
2399
-                $this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2400
-                // set JSON response
2401
-                $this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2402
-                // and lastly, let's bump the payment status to pending
2403
-                $payment->set_status(EEM_Payment::status_id_pending);
2404
-                $payment->save();
2405
-            } else {
2406
-                // not a payment
2407
-                $this->checkout->continue_reg = false;
2408
-                EE_Error::add_error(
2409
-                    sprintf(
2410
-                        esc_html__(
2411
-                            'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2412
-                            'event_espresso'
2413
-                        ),
2414
-                        '<br/>',
2415
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
2416
-                    ),
2417
-                    __FILE__,
2418
-                    __FUNCTION__,
2419
-                    __LINE__
2420
-                );
2421
-            }
2422
-        } else {
2423
-            // ummm ya... not Off-Line, not On-Site, not off-Site ????
2424
-            $this->checkout->continue_reg = false;
2425
-            return false;
2426
-        }
2427
-        return $payment;
2428
-    }
2429
-
2430
-
2431
-    /**
2432
-     *    _process_payment_status
2433
-     *
2434
-     * @access private
2435
-     * @type    EE_Payment $payment
2436
-     * @param string       $payment_occurs
2437
-     * @return bool
2438
-     * @throws EE_Error
2439
-     * @throws InvalidArgumentException
2440
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2441
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2442
-     */
2443
-    private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2444
-    {
2445
-        // off-line payment? carry on
2446
-        if ($payment_occurs === EE_PMT_Base::offline) {
2447
-            return true;
2448
-        }
2449
-        // verify payment validity
2450
-        if ($payment instanceof EE_Payment) {
2451
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2452
-            $msg = $payment->gateway_response();
2453
-            // check results
2454
-            switch ($payment->status()) {
2455
-                // good payment
2456
-                case EEM_Payment::status_id_approved :
2457
-                    EE_Error::add_success(
2458
-                        esc_html__('Your payment was processed successfully.', 'event_espresso'),
2459
-                        __FILE__,
2460
-                        __FUNCTION__,
2461
-                        __LINE__
2462
-                    );
2463
-                    return true;
2464
-                    break;
2465
-                // slow payment
2466
-                case EEM_Payment::status_id_pending :
2467
-                    if (empty($msg)) {
2468
-                        $msg = esc_html__(
2469
-                            'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2470
-                            'event_espresso'
2471
-                        );
2472
-                    }
2473
-                    EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2474
-                    return true;
2475
-                    break;
2476
-                // don't wanna payment
2477
-                case EEM_Payment::status_id_cancelled :
2478
-                    if (empty($msg)) {
2479
-                        $msg = _n(
2480
-                            'Payment cancelled. Please try again.',
2481
-                            'Payment cancelled. Please try again or select another method of payment.',
2482
-                            count($this->checkout->available_payment_methods),
2483
-                            'event_espresso'
2484
-                        );
2485
-                    }
2486
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2487
-                    return false;
2488
-                    break;
2489
-                // not enough payment
2490
-                case EEM_Payment::status_id_declined :
2491
-                    if (empty($msg)) {
2492
-                        $msg = _n(
2493
-                            'We\'re sorry but your payment was declined. Please try again.',
2494
-                            'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2495
-                            count($this->checkout->available_payment_methods),
2496
-                            'event_espresso'
2497
-                        );
2498
-                    }
2499
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2500
-                    return false;
2501
-                    break;
2502
-                // bad payment
2503
-                case EEM_Payment::status_id_failed :
2504
-                    if (! empty($msg)) {
2505
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506
-                        return false;
2507
-                    }
2508
-                    // default to error below
2509
-                    break;
2510
-            }
2511
-        }
2512
-        // off-site payment gateway responses are too unreliable, so let's just assume that
2513
-        // the payment processing is just running slower than the registrant's request
2514
-        if ($payment_occurs === EE_PMT_Base::offsite) {
2515
-            return true;
2516
-        }
2517
-        EE_Error::add_error(
2518
-            sprintf(
2519
-                esc_html__(
2520
-                    'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2521
-                    'event_espresso'
2522
-                ),
2523
-                '<br/>',
2524
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
2525
-            ),
2526
-            __FILE__,
2527
-            __FUNCTION__,
2528
-            __LINE__
2529
-        );
2530
-        return false;
2531
-    }
2532
-
2533
-
2534
-
2535
-
2536
-
2537
-
2538
-    /********************************************************************************************************/
2539
-    /**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2540
-    /********************************************************************************************************/
2541
-    /**
2542
-     * process_gateway_response
2543
-     * this is the return point for Off-Site Payment Methods
2544
-     * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2545
-     * otherwise, it will load up the last payment made for the TXN.
2546
-     * If the payment retrieved looks good, it will then either:
2547
-     *    complete the current step and allow advancement to the next reg step
2548
-     *        or present the payment options again
2549
-     *
2550
-     * @access private
2551
-     * @return EE_Payment|FALSE
2552
-     * @throws EE_Error
2553
-     * @throws InvalidArgumentException
2554
-     * @throws ReflectionException
2555
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2556
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2557
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2558
-     */
2559
-    public function process_gateway_response()
2560
-    {
2561
-        $payment = null;
2562
-        // how have they chosen to pay?
2563
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564
-        // get EE_Payment_Method object
2565
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566
-            $this->checkout->continue_reg = false;
2567
-            return false;
2568
-        }
2569
-        if (! $this->checkout->payment_method->is_off_site()) {
2570
-            return false;
2571
-        }
2572
-        $this->_validate_offsite_return();
2573
-        // DEBUG LOG
2574
-        //$this->checkout->log(
2575
-        //	__CLASS__, __FUNCTION__, __LINE__,
2576
-        //	array(
2577
-        //		'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2578
-        //		'payment_method' => $this->checkout->payment_method,
2579
-        //	),
2580
-        //	true
2581
-        //);
2582
-        // verify TXN
2583
-        if ($this->checkout->transaction instanceof EE_Transaction) {
2584
-            $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2586
-                $this->checkout->continue_reg = false;
2587
-                return false;
2588
-            }
2589
-            $payment = $this->_process_off_site_payment($gateway);
2590
-            $payment = $this->_process_cancelled_payments($payment);
2591
-            $payment = $this->_validate_payment($payment);
2592
-            // if payment was not declined by the payment gateway or cancelled by the registrant
2593
-            if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2594
-                //$this->_setup_redirect_for_next_step();
2595
-                // store that for later
2596
-                $this->checkout->payment = $payment;
2597
-                // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2598
-                // because we will complete this step during the IPN processing then
2599
-                if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2600
-                    $this->set_completed();
2601
-                }
2602
-                return true;
2603
-            }
2604
-        }
2605
-        // DEBUG LOG
2606
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2607
-        //	array( 'payment' => $payment )
2608
-        //);
2609
-        $this->checkout->continue_reg = false;
2610
-        return false;
2611
-    }
2612
-
2613
-
2614
-    /**
2615
-     * _validate_return
2616
-     *
2617
-     * @access private
2618
-     * @return void
2619
-     * @throws EE_Error
2620
-     * @throws InvalidArgumentException
2621
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2622
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2623
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2624
-     */
2625
-    private function _validate_offsite_return()
2626
-    {
2627
-        $TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2628
-        if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
-            // Houston... we might have a problem
2630
-            $invalid_TXN = false;
2631
-            // first gather some info
2632
-            $valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
-            $primary_registrant = $valid_TXN instanceof EE_Transaction
2634
-                ? $valid_TXN->primary_registration()
2635
-                : null;
2636
-            // let's start by retrieving the cart for this TXN
2637
-            $cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
-            if ($cart instanceof EE_Cart) {
2639
-                // verify that the current cart has tickets
2640
-                $tickets = $cart->get_tickets();
2641
-                if (empty($tickets)) {
2642
-                    $invalid_TXN = true;
2643
-                }
2644
-            } else {
2645
-                $invalid_TXN = true;
2646
-            }
2647
-            $valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
-                ? $primary_registrant->session_ID()
2649
-                : null;
2650
-            // validate current Session ID and compare against valid TXN session ID
2651
-            if (
2652
-                $invalid_TXN // if this is already true, then skip other checks
2653
-                || EE_Session::instance()->id() === null
2654
-                || (
2655
-                    // WARNING !!!
2656
-                    // this could be PayPal sending back duplicate requests (ya they do that)
2657
-                    // or it **could** mean someone is simply registering AGAIN after having just done so
2658
-                    // so now we need to determine if this current TXN looks valid or not
2659
-                    // and whether this reg step has even been started ?
2660
-                    EE_Session::instance()->id() === $valid_TXN_SID
2661
-                    // really? you're half way through this reg step, but you never started it ?
2662
-                    && $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
-                )
2664
-            ) {
2665
-                $invalid_TXN = true;
2666
-            }
2667
-            if ($invalid_TXN) {
2668
-                // is the valid TXN completed ?
2669
-                if ($valid_TXN instanceof EE_Transaction) {
2670
-                    // has this step even been started ?
2671
-                    $reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
-                    if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
-                        // so it **looks** like this is a double request from PayPal
2674
-                        // so let's try to pick up where we left off
2675
-                        $this->checkout->transaction = $valid_TXN;
2676
-                        $this->checkout->refresh_all_entities(true);
2677
-                        return;
2678
-                    }
2679
-                }
2680
-                // you appear to be lost?
2681
-                $this->_redirect_wayward_request($primary_registrant);
2682
-            }
2683
-        }
2684
-    }
2685
-
2686
-
2687
-    /**
2688
-     * _redirect_wayward_request
2689
-     *
2690
-     * @access private
2691
-     * @param \EE_Registration|null $primary_registrant
2692
-     * @return bool
2693
-     * @throws EE_Error
2694
-     * @throws InvalidArgumentException
2695
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2696
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2697
-     */
2698
-    private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
-    {
2700
-        if (! $primary_registrant instanceof EE_Registration) {
2701
-            // try redirecting based on the current TXN
2702
-            $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
-                ? $this->checkout->transaction->primary_registration()
2704
-                : null;
2705
-        }
2706
-        if (! $primary_registrant instanceof EE_Registration) {
2707
-            EE_Error::add_error(
2708
-                sprintf(
2709
-                    esc_html__(
2710
-                        'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
-                        'event_espresso'
2712
-                    ),
2713
-                    '<br/>',
2714
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
-                ),
2716
-                __FILE__,
2717
-                __FUNCTION__,
2718
-                __LINE__
2719
-            );
2720
-            return false;
2721
-        }
2722
-        // make sure transaction is not locked
2723
-        $this->checkout->transaction->unlock();
2724
-        wp_safe_redirect(
2725
-            add_query_arg(
2726
-                array(
2727
-                    'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
-                ),
2729
-                $this->checkout->thank_you_page_url
2730
-            )
2731
-        );
2732
-        exit();
2733
-    }
2734
-
2735
-
2736
-    /**
2737
-     * _process_off_site_payment
2738
-     *
2739
-     * @access private
2740
-     * @param \EE_Offsite_Gateway $gateway
2741
-     * @return EE_Payment
2742
-     * @throws EE_Error
2743
-     * @throws InvalidArgumentException
2744
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2745
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2746
-     */
2747
-    private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
-    {
2749
-        try {
2750
-            $request_data = \EE_Registry::instance()->REQ->params();
2751
-            // if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2752
-            $this->set_handle_IPN_in_this_request(
2753
-                $gateway->handle_IPN_in_this_request($request_data, false)
2754
-            );
2755
-            if ($this->handle_IPN_in_this_request()) {
2756
-                // get payment details and process results
2757
-                /** @type EE_Payment_Processor $payment_processor */
2758
-                $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2759
-                $payment           = $payment_processor->process_ipn(
2760
-                    $request_data,
2761
-                    $this->checkout->transaction,
2762
-                    $this->checkout->payment_method,
2763
-                    true,
2764
-                    false
2765
-                );
2766
-                //$payment_source = 'process_ipn';
2767
-            } else {
2768
-                $payment = $this->checkout->transaction->last_payment();
2769
-                //$payment_source = 'last_payment';
2770
-            }
2771
-        } catch (Exception $e) {
2772
-            // let's just eat the exception and try to move on using any previously set payment info
2773
-            $payment = $this->checkout->transaction->last_payment();
2774
-            //$payment_source = 'last_payment after Exception';
2775
-            // but if we STILL don't have a payment object
2776
-            if (! $payment instanceof EE_Payment) {
2777
-                // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778
-                $this->_handle_payment_processor_exception($e);
2779
-            }
2780
-        }
2781
-        // DEBUG LOG
2782
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2783
-        //	array(
2784
-        //		'process_ipn_payment' => $payment,
2785
-        //		'payment_source'      => $payment_source,
2786
-        //	)
2787
-        //);
2788
-        return $payment;
2789
-    }
2790
-
2791
-
2792
-    /**
2793
-     * _process_cancelled_payments
2794
-     * just makes sure that the payment status gets updated correctly
2795
-     * so tha tan error isn't generated during payment validation
2796
-     *
2797
-     * @access private
2798
-     * @param EE_Payment $payment
2799
-     * @return EE_Payment | FALSE
2800
-     * @throws \EE_Error
2801
-     */
2802
-    private function _process_cancelled_payments($payment = null)
2803
-    {
2804
-        if (
2805
-            $payment instanceof EE_Payment
2806
-            && isset($_REQUEST['ee_cancel_payment'])
2807
-            && $payment->status() === EEM_Payment::status_id_failed
2808
-        ) {
2809
-            $payment->set_status(EEM_Payment::status_id_cancelled);
2810
-        }
2811
-        return $payment;
2812
-    }
2813
-
2814
-
2815
-    /**
2816
-     *    get_transaction_details_for_gateways
2817
-     *
2818
-     * @access    public
2819
-     * @return int
2820
-     * @throws EE_Error
2821
-     * @throws InvalidArgumentException
2822
-     * @throws ReflectionException
2823
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2824
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2825
-     */
2826
-    public function get_transaction_details_for_gateways()
2827
-    {
2828
-        $txn_details = array();
2829
-        // ya gotta make a choice man
2830
-        if (empty($this->checkout->selected_method_of_payment)) {
2831
-            $txn_details = array(
2832
-                'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2833
-            );
2834
-        }
2835
-        // get EE_Payment_Method object
2836
-        if (
2837
-            empty($txn_details)
2838
-            &&
2839
-            ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2840
-        ) {
2841
-            $txn_details = array(
2842
-                'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2843
-                'error'                      => esc_html__(
2844
-                    'A valid Payment Method could not be determined.',
2845
-                    'event_espresso'
2846
-                ),
2847
-            );
2848
-        }
2849
-        if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2850
-            $return_url  = $this->_get_return_url($this->checkout->payment_method);
2851
-            $txn_details = array(
2852
-                'TXN_ID'         => $this->checkout->transaction->ID(),
2853
-                'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2854
-                'TXN_total'      => $this->checkout->transaction->total(),
2855
-                'TXN_paid'       => $this->checkout->transaction->paid(),
2856
-                'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2857
-                'STS_ID'         => $this->checkout->transaction->status_ID(),
2858
-                'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2859
-                'payment_amount' => $this->checkout->amount_owing,
2860
-                'return_url'     => $return_url,
2861
-                'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2862
-                'notify_url'     => EE_Config::instance()->core->txn_page_url(
2863
-                    array(
2864
-                        'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2865
-                        'ee_payment_method' => $this->checkout->payment_method->slug(),
2866
-                    )
2867
-                ),
2868
-            );
2869
-        }
2870
-        echo wp_json_encode($txn_details);
2871
-        exit();
2872
-    }
2873
-
2874
-
2875
-    /**
2876
-     *    __sleep
2877
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2878
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2879
-     * reg form, because if needed, it will be regenerated anyways
2880
-     *
2881
-     * @return array
2882
-     */
2883
-    public function __sleep()
2884
-    {
2885
-        // remove the reg form and the checkout
2886
-        return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2887
-    }
18
+	/**
19
+	 * @access protected
20
+	 * @var EE_Line_Item_Display $Line_Item_Display
21
+	 */
22
+	protected $line_item_display;
23
+
24
+	/**
25
+	 * @access protected
26
+	 * @var boolean $handle_IPN_in_this_request
27
+	 */
28
+	protected $handle_IPN_in_this_request = false;
29
+
30
+
31
+	/**
32
+	 *    set_hooks - for hooking into EE Core, other modules, etc
33
+	 *
34
+	 * @access    public
35
+	 * @return    void
36
+	 */
37
+	public static function set_hooks()
38
+	{
39
+		add_filter(
40
+			'FHEE__SPCO__EE_Line_Item_Filter_Collection',
41
+			array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
42
+		);
43
+		add_action(
44
+			'wp_ajax_switch_spco_billing_form',
45
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
46
+		);
47
+		add_action(
48
+			'wp_ajax_nopriv_switch_spco_billing_form',
49
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
50
+		);
51
+		add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
52
+		add_action(
53
+			'wp_ajax_nopriv_save_payer_details',
54
+			array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
55
+		);
56
+		add_action(
57
+			'wp_ajax_get_transaction_details_for_gateways',
58
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
59
+		);
60
+		add_action(
61
+			'wp_ajax_nopriv_get_transaction_details_for_gateways',
62
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
63
+		);
64
+		add_filter(
65
+			'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
66
+			array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
67
+			10,
68
+			1
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 *    ajax switch_spco_billing_form
75
+	 *
76
+	 * @throws \EE_Error
77
+	 */
78
+	public static function switch_spco_billing_form()
79
+	{
80
+		EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
81
+	}
82
+
83
+
84
+	/**
85
+	 *    ajax save_payer_details
86
+	 *
87
+	 * @throws \EE_Error
88
+	 */
89
+	public static function save_payer_details()
90
+	{
91
+		EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
+	}
93
+
94
+
95
+	/**
96
+	 *    ajax get_transaction_details
97
+	 *
98
+	 * @throws \EE_Error
99
+	 */
100
+	public static function get_transaction_details()
101
+	{
102
+		EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
103
+	}
104
+
105
+
106
+	/**
107
+	 * bypass_recaptcha_for_load_payment_method
108
+	 *
109
+	 * @access public
110
+	 * @return array
111
+	 * @throws InvalidArgumentException
112
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
113
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
114
+	 */
115
+	public static function bypass_recaptcha_for_load_payment_method()
116
+	{
117
+		return array(
118
+			'EESID'  => EE_Registry::instance()->SSN->id(),
119
+			'step'   => 'payment_options',
120
+			'action' => 'spco_billing_form',
121
+		);
122
+	}
123
+
124
+
125
+	/**
126
+	 *    class constructor
127
+	 *
128
+	 * @access    public
129
+	 * @param    EE_Checkout $checkout
130
+	 */
131
+	public function __construct(EE_Checkout $checkout)
132
+	{
133
+		$this->_slug     = 'payment_options';
134
+		$this->_name     = esc_html__('Payment Options', 'event_espresso');
135
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
136
+		$this->checkout  = $checkout;
137
+		$this->_reset_success_message();
138
+		$this->set_instructions(
139
+			esc_html__(
140
+				'Please select a method of payment and provide any necessary billing information before proceeding.',
141
+				'event_espresso'
142
+			)
143
+		);
144
+	}
145
+
146
+
147
+	/**
148
+	 * @return null
149
+	 */
150
+	public function line_item_display()
151
+	{
152
+		return $this->line_item_display;
153
+	}
154
+
155
+
156
+	/**
157
+	 * @param null $line_item_display
158
+	 */
159
+	public function set_line_item_display($line_item_display)
160
+	{
161
+		$this->line_item_display = $line_item_display;
162
+	}
163
+
164
+
165
+	/**
166
+	 * @return boolean
167
+	 */
168
+	public function handle_IPN_in_this_request()
169
+	{
170
+		return $this->handle_IPN_in_this_request;
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param boolean $handle_IPN_in_this_request
176
+	 */
177
+	public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
+	{
179
+		$this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
+	}
181
+
182
+
183
+	/**
184
+	 * translate_js_strings
185
+	 *
186
+	 * @return void
187
+	 */
188
+	public function translate_js_strings()
189
+	{
190
+		EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
+			'Please select a method of payment in order to continue.',
192
+			'event_espresso'
193
+		);
194
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
+			'A valid method of payment could not be determined. Please refresh the page and try again.',
196
+			'event_espresso'
197
+		);
198
+		EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
+			'Forwarding to Secure Payment Provider.',
200
+			'event_espresso'
201
+		);
202
+	}
203
+
204
+
205
+	/**
206
+	 * enqueue_styles_and_scripts
207
+	 *
208
+	 * @return void
209
+	 * @throws EE_Error
210
+	 * @throws InvalidArgumentException
211
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
212
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
213
+	 */
214
+	public function enqueue_styles_and_scripts()
215
+	{
216
+		$transaction = $this->checkout->transaction;
217
+		//if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
+		if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219
+			return;
220
+		}
221
+		foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
222
+			$type_obj = $payment_method->type_obj();
223
+			if ($type_obj instanceof EE_PMT_Base) {
224
+				$billing_form = $type_obj->generate_new_billing_form($transaction);
225
+				if ($billing_form instanceof EE_Form_Section_Proper) {
226
+					$billing_form->enqueue_js();
227
+				}
228
+			}
229
+		}
230
+	}
231
+
232
+
233
+	/**
234
+	 * initialize_reg_step
235
+	 *
236
+	 * @return bool
237
+	 * @throws EE_Error
238
+	 * @throws InvalidArgumentException
239
+	 * @throws ReflectionException
240
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
241
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
242
+	 */
243
+	public function initialize_reg_step()
244
+	{
245
+		// TODO: if /when we implement donations, then this will need overriding
246
+		if (// don't need payment options for:
247
+			// 	registrations made via the admin
248
+			// 	completed transactions
249
+			// 	overpaid transactions
250
+			// 	$ 0.00 transactions (no payment required)
251
+			! $this->checkout->payment_required()
252
+			// but do NOT remove if current action being called belongs to this reg step
253
+			&& ! is_callable(array($this, $this->checkout->action))
254
+			&& ! $this->completed()
255
+		) {
256
+			// and if so, then we no longer need the Payment Options step
257
+			if ($this->is_current_step()) {
258
+				$this->checkout->generate_reg_form = false;
259
+			}
260
+			$this->checkout->remove_reg_step($this->_slug);
261
+			// DEBUG LOG
262
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
263
+			return false;
264
+		}
265
+		// load EEM_Payment_Method
266
+		EE_Registry::instance()->load_model('Payment_Method');
267
+		// get all active payment methods
268
+		$this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
269
+			$this->checkout->transaction,
270
+			EEM_Payment_Method::scope_cart
271
+		);
272
+		return true;
273
+	}
274
+
275
+
276
+	/**
277
+	 * @return EE_Form_Section_Proper
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws ReflectionException
281
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
282
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
283
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
284
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
285
+	 */
286
+	public function generate_reg_form()
287
+	{
288
+		// reset in case someone changes their mind
289
+		$this->_reset_selected_method_of_payment();
290
+		// set some defaults
291
+		$this->checkout->selected_method_of_payment = 'payments_closed';
292
+		$registrations_requiring_payment            = array();
293
+		$registrations_for_free_events              = array();
294
+		$registrations_requiring_pre_approval       = array();
295
+		$sold_out_events                            = array();
296
+		$insufficient_spaces_available              = array();
297
+		$no_payment_required                        = true;
298
+		// loop thru registrations to gather info
299
+		$registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
300
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
301
+			$registrations,
302
+			$this->checkout->revisit
303
+		);
304
+		foreach ($registrations as $REG_ID => $registration) {
305
+			/** @var $registration EE_Registration */
306
+			// has this registration lost it's space ?
307
+			if (isset($ejected_registrations[ $REG_ID ])) {
308
+				if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
+					$sold_out_events[ $registration->event()->ID() ] = $registration->event();
310
+				} else {
311
+					$insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
312
+				}
313
+				continue;
314
+			}
315
+			// event requires admin approval
316
+			if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
317
+				// add event to list of events with pre-approval reg status
318
+				$registrations_requiring_pre_approval[$REG_ID] = $registration;
319
+				do_action(
320
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
321
+					$registration->event(),
322
+					$this
323
+				);
324
+				continue;
325
+			}
326
+			if ($this->checkout->revisit
327
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
328
+				&& (
329
+					$registration->event()->is_sold_out()
330
+					|| $registration->event()->is_sold_out(true)
331
+				)
332
+			) {
333
+				// add event to list of events that are sold out
334
+				$sold_out_events[$registration->event()->ID()] = $registration->event();
335
+				do_action(
336
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
337
+					$registration->event(),
338
+					$this
339
+				);
340
+				continue;
341
+			}
342
+			// are they allowed to pay now and is there monies owing?
343
+			if ($registration->owes_monies_and_can_pay()) {
344
+				$registrations_requiring_payment[$REG_ID] = $registration;
345
+				do_action(
346
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
347
+					$registration->event(),
348
+					$this
349
+				);
350
+			} elseif (! $this->checkout->revisit
351
+				&& $registration->status_ID() !== EEM_Registration::status_id_not_approved
352
+				&& $registration->ticket()->is_free()
353
+			) {
354
+				$registrations_for_free_events[$registration->event()->ID()] = $registration;
355
+			}
356
+		}
357
+		$subsections = array();
358
+		// now decide which template to load
359
+		if (! empty($sold_out_events)) {
360
+			$subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361
+		}
362
+		if (! empty($insufficient_spaces_available)) {
363
+			$subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364
+				$insufficient_spaces_available
365
+			);
366
+		}
367
+		if (! empty($registrations_requiring_pre_approval)) {
368
+			$subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369
+				$registrations_requiring_pre_approval
370
+			);
371
+		}
372
+		if (! empty($registrations_for_free_events)) {
373
+			$subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374
+		}
375
+		if (! empty($registrations_requiring_payment)) {
376
+			if ($this->checkout->amount_owing > 0) {
377
+				// autoload Line_Item_Display classes
378
+				EEH_Autoloader::register_line_item_filter_autoloaders();
379
+				$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
380
+					apply_filters(
381
+						'FHEE__SPCO__EE_Line_Item_Filter_Collection',
382
+						new EE_Line_Item_Filter_Collection()
383
+					),
384
+					$this->checkout->cart->get_grand_total()
385
+				);
386
+				/** @var EE_Line_Item $filtered_line_item_tree */
387
+				$filtered_line_item_tree = $line_item_filter_processor->process();
388
+				EEH_Autoloader::register_line_item_display_autoloaders();
389
+				$this->set_line_item_display(new EE_Line_Item_Display('spco'));
390
+				$subsections['payment_options'] = $this->_display_payment_options(
391
+					$this->line_item_display->display_line_item(
392
+						$filtered_line_item_tree,
393
+						array('registrations' => $registrations)
394
+					)
395
+				);
396
+				$this->checkout->amount_owing   = $filtered_line_item_tree->total();
397
+				$this->_apply_registration_payments_to_amount_owing($registrations);
398
+			}
399
+			$no_payment_required = false;
400
+		} else {
401
+			$this->_hide_reg_step_submit_button_if_revisit();
402
+		}
403
+		$this->_save_selected_method_of_payment();
404
+
405
+		$subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
406
+		$subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
407
+
408
+		return new EE_Form_Section_Proper(
409
+			array(
410
+				'name'            => $this->reg_form_name(),
411
+				'html_id'         => $this->reg_form_name(),
412
+				'subsections'     => $subsections,
413
+				'layout_strategy' => new EE_No_Layout(),
414
+			)
415
+		);
416
+	}
417
+
418
+
419
+	/**
420
+	 * add line item filters required for this reg step
421
+	 * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
422
+	 *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
423
+	 *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
424
+	 *        payment options reg step, can apply these filters via the following: apply_filters(
425
+	 *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
426
+	 *        filter collection by passing that instead of instantiating a new collection
427
+	 *
428
+	 * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
429
+	 * @return EE_Line_Item_Filter_Collection
430
+	 * @throws EE_Error
431
+	 * @throws InvalidArgumentException
432
+	 * @throws ReflectionException
433
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
434
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
435
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
436
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
437
+	 */
438
+	public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439
+	{
440
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
441
+			return $line_item_filter_collection;
442
+		}
443
+		if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444
+			return $line_item_filter_collection;
445
+		}
446
+		if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447
+			return $line_item_filter_collection;
448
+		}
449
+		$line_item_filter_collection->add(
450
+			new EE_Billable_Line_Item_Filter(
451
+				EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
452
+					EE_Registry::instance()->SSN->checkout()->transaction->registrations(
453
+						EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
454
+					)
455
+				)
456
+			)
457
+		);
458
+		$line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
459
+		return $line_item_filter_collection;
460
+	}
461
+
462
+
463
+	/**
464
+	 * remove_ejected_registrations
465
+	 * if a registrant has lost their potential space at an event due to lack of payment,
466
+	 * then this method removes them from the list of registrations being paid for during this request
467
+	 *
468
+	 * @param \EE_Registration[] $registrations
469
+	 * @return EE_Registration[]
470
+	 * @throws EE_Error
471
+	 * @throws InvalidArgumentException
472
+	 * @throws ReflectionException
473
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
474
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
475
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
476
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
477
+	 */
478
+	public static function remove_ejected_registrations(array $registrations)
479
+	{
480
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
481
+			$registrations,
482
+			EE_Registry::instance()->SSN->checkout()->revisit
483
+		);
484
+		foreach ($registrations as $REG_ID => $registration) {
485
+			// has this registration lost it's space ?
486
+			if (isset($ejected_registrations[$REG_ID])) {
487
+				unset($registrations[$REG_ID]);
488
+				continue;
489
+			}
490
+		}
491
+		return $registrations;
492
+	}
493
+
494
+
495
+	/**
496
+	 * find_registrations_that_lost_their_space
497
+	 * If a registrant chooses an offline payment method like Invoice,
498
+	 * then no space is reserved for them at the event until they fully pay fo that site
499
+	 * (unless the event's default reg status is set to APPROVED)
500
+	 * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
501
+	 * then this method will determine which registrations have lost the ability to complete the reg process.
502
+	 *
503
+	 * @param \EE_Registration[] $registrations
504
+	 * @param bool               $revisit
505
+	 * @return array
506
+	 * @throws EE_Error
507
+	 * @throws InvalidArgumentException
508
+	 * @throws ReflectionException
509
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
510
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
511
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
512
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
513
+	 */
514
+	public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
515
+	{
516
+		// registrations per event
517
+		$event_reg_count = array();
518
+		// spaces left per event
519
+		$event_spaces_remaining = array();
520
+		// tickets left sorted by ID
521
+		$tickets_remaining = array();
522
+		// registrations that have lost their space
523
+		$ejected_registrations = array();
524
+		foreach ($registrations as $REG_ID => $registration) {
525
+			if ($registration->status_ID() === EEM_Registration::status_id_approved
526
+				|| apply_filters(
527
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
528
+					false,
529
+					$registration,
530
+					$revisit
531
+				)
532
+			) {
533
+				continue;
534
+			}
535
+			$EVT_ID = $registration->event_ID();
536
+			$ticket = $registration->ticket();
537
+			if (! isset($tickets_remaining[$ticket->ID()])) {
538
+				$tickets_remaining[$ticket->ID()] = $ticket->remaining();
539
+			}
540
+			if ($tickets_remaining[$ticket->ID()] > 0) {
541
+				if (! isset($event_reg_count[$EVT_ID])) {
542
+					$event_reg_count[$EVT_ID] = 0;
543
+				}
544
+				$event_reg_count[$EVT_ID]++;
545
+				if (! isset($event_spaces_remaining[$EVT_ID])) {
546
+					$event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547
+				}
548
+			}
549
+			if ($revisit
550
+				&& ($tickets_remaining[$ticket->ID()] === 0
551
+					|| $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
552
+				)
553
+			) {
554
+				$ejected_registrations[$REG_ID] = $registration->event();
555
+				if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
556
+					/** @type EE_Registration_Processor $registration_processor */
557
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
558
+					// at this point, we should have enough details about the registrant to consider the registration
559
+					// NOT incomplete
560
+					$registration_processor->manually_update_registration_status(
561
+						$registration,
562
+						EEM_Registration::status_id_wait_list
563
+					);
564
+				}
565
+			}
566
+		}
567
+		return $ejected_registrations;
568
+	}
569
+
570
+
571
+	/**
572
+	 * _hide_reg_step_submit_button
573
+	 * removes the html for the reg step submit button
574
+	 * by replacing it with an empty string via filter callback
575
+	 *
576
+	 * @return void
577
+	 */
578
+	protected function _adjust_registration_status_if_event_old_sold()
579
+	{
580
+	}
581
+
582
+
583
+	/**
584
+	 * _hide_reg_step_submit_button
585
+	 * removes the html for the reg step submit button
586
+	 * by replacing it with an empty string via filter callback
587
+	 *
588
+	 * @return void
589
+	 */
590
+	protected function _hide_reg_step_submit_button_if_revisit()
591
+	{
592
+		if ($this->checkout->revisit) {
593
+			add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
594
+		}
595
+	}
596
+
597
+
598
+	/**
599
+	 * sold_out_events
600
+	 * displays notices regarding events that have sold out since hte registrant first signed up
601
+	 *
602
+	 * @param \EE_Event[] $sold_out_events_array
603
+	 * @return \EE_Form_Section_Proper
604
+	 * @throws \EE_Error
605
+	 */
606
+	private function _sold_out_events($sold_out_events_array = array())
607
+	{
608
+		// set some defaults
609
+		$this->checkout->selected_method_of_payment = 'events_sold_out';
610
+		$sold_out_events                            = '';
611
+		foreach ($sold_out_events_array as $sold_out_event) {
612
+			$sold_out_events .= EEH_HTML::li(
613
+				EEH_HTML::span(
614
+					'  ' . $sold_out_event->name(),
615
+					'',
616
+					'dashicons dashicons-marker ee-icon-size-16 pink-text'
617
+				)
618
+			);
619
+		}
620
+		return new EE_Form_Section_Proper(
621
+			array(
622
+				'layout_strategy' => new EE_Template_Layout(
623
+					array(
624
+						'layout_template_file' => SPCO_REG_STEPS_PATH
625
+												  . $this->_slug
626
+												  . DS
627
+												  . 'sold_out_events.template.php',
628
+						'template_args'        => apply_filters(
629
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
630
+							array(
631
+								'sold_out_events'     => $sold_out_events,
632
+								'sold_out_events_msg' => apply_filters(
633
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
634
+									sprintf(
635
+										esc_html__(
636
+											'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
637
+											'event_espresso'
638
+										),
639
+										'<strong>',
640
+										'</strong>',
641
+										'<br />'
642
+									)
643
+								),
644
+							)
645
+						),
646
+					)
647
+				),
648
+			)
649
+		);
650
+	}
651
+
652
+
653
+	/**
654
+	 * _insufficient_spaces_available
655
+	 * displays notices regarding events that do not have enough remaining spaces
656
+	 * to satisfy the current number of registrations looking to pay
657
+	 *
658
+	 * @param \EE_Event[] $insufficient_spaces_events_array
659
+	 * @return \EE_Form_Section_Proper
660
+	 * @throws \EE_Error
661
+	 */
662
+	private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
663
+	{
664
+		// set some defaults
665
+		$this->checkout->selected_method_of_payment = 'invoice';
666
+		$insufficient_space_events                  = '';
667
+		foreach ($insufficient_spaces_events_array as $event) {
668
+			if ($event instanceof EE_Event) {
669
+				$insufficient_space_events .= EEH_HTML::li(
670
+					EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671
+				);
672
+			}
673
+		}
674
+		return new EE_Form_Section_Proper(
675
+			array(
676
+				'subsections'     => array(
677
+					'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
678
+					'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
679
+				),
680
+				'layout_strategy' => new EE_Template_Layout(
681
+					array(
682
+						'layout_template_file' => SPCO_REG_STEPS_PATH
683
+												  . $this->_slug
684
+												  . DS
685
+												  . 'sold_out_events.template.php',
686
+						'template_args'        => apply_filters(
687
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
688
+							array(
689
+								'sold_out_events'     => $insufficient_space_events,
690
+								'sold_out_events_msg' => apply_filters(
691
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
692
+									esc_html__(
693
+										'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
694
+										'event_espresso'
695
+									)
696
+								),
697
+							)
698
+						),
699
+					)
700
+				),
701
+			)
702
+		);
703
+	}
704
+
705
+
706
+	/**
707
+	 * registrations_requiring_pre_approval
708
+	 *
709
+	 * @param array $registrations_requiring_pre_approval
710
+	 * @return EE_Form_Section_Proper
711
+	 * @throws EE_Error
712
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
713
+	 */
714
+	private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
715
+	{
716
+		$events_requiring_pre_approval = '';
717
+		foreach ($registrations_requiring_pre_approval as $registration) {
718
+			if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
719
+				$events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
720
+					EEH_HTML::span(
721
+						'',
722
+						'',
723
+						'dashicons dashicons-marker ee-icon-size-16 orange-text'
724
+					)
725
+					. EEH_HTML::span($registration->event()->name(), '', 'orange-text')
726
+				);
727
+			}
728
+		}
729
+		return new EE_Form_Section_Proper(
730
+			array(
731
+				'layout_strategy' => new EE_Template_Layout(
732
+					array(
733
+						'layout_template_file' => SPCO_REG_STEPS_PATH
734
+												  . $this->_slug
735
+												  . DS
736
+												  . 'events_requiring_pre_approval.template.php', // layout_template
737
+						'template_args'        => apply_filters(
738
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
739
+							array(
740
+								'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
741
+								'events_requiring_pre_approval_msg' => apply_filters(
742
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
743
+									esc_html__(
744
+										'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
745
+										'event_espresso'
746
+									)
747
+								),
748
+							)
749
+						),
750
+					)
751
+				),
752
+			)
753
+		);
754
+	}
755
+
756
+
757
+	/**
758
+	 * _no_payment_required
759
+	 *
760
+	 * @param \EE_Event[] $registrations_for_free_events
761
+	 * @return \EE_Form_Section_Proper
762
+	 * @throws \EE_Error
763
+	 */
764
+	private function _no_payment_required($registrations_for_free_events = array())
765
+	{
766
+		// set some defaults
767
+		$this->checkout->selected_method_of_payment = 'no_payment_required';
768
+		// generate no_payment_required form
769
+		return new EE_Form_Section_Proper(
770
+			array(
771
+				'layout_strategy' => new EE_Template_Layout(
772
+					array(
773
+						'layout_template_file' => SPCO_REG_STEPS_PATH
774
+												  . $this->_slug
775
+												  . DS
776
+												  . 'no_payment_required.template.php', // layout_template
777
+						'template_args'        => apply_filters(
778
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
779
+							array(
780
+								'revisit'                       => $this->checkout->revisit,
781
+								'registrations'                 => array(),
782
+								'ticket_count'                  => array(),
783
+								'registrations_for_free_events' => $registrations_for_free_events,
784
+								'no_payment_required_msg'       => EEH_HTML::p(
785
+									esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
786
+								),
787
+							)
788
+						),
789
+					)
790
+				),
791
+			)
792
+		);
793
+	}
794
+
795
+
796
+	/**
797
+	 * _display_payment_options
798
+	 *
799
+	 * @param string $transaction_details
800
+	 * @return EE_Form_Section_Proper
801
+	 * @throws EE_Error
802
+	 * @throws InvalidArgumentException
803
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
804
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
805
+	 */
806
+	private function _display_payment_options($transaction_details = '')
807
+	{
808
+		// has method_of_payment been set by no-js user?
809
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
810
+		// build payment options form
811
+		return apply_filters(
812
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
813
+			new EE_Form_Section_Proper(
814
+				array(
815
+					'subsections'     => array(
816
+						'before_payment_options' => apply_filters(
817
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
818
+							new EE_Form_Section_Proper(
819
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
820
+							)
821
+						),
822
+						'payment_options'        => $this->_setup_payment_options(),
823
+						'after_payment_options'  => apply_filters(
824
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
825
+							new EE_Form_Section_Proper(
826
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
827
+							)
828
+						),
829
+					),
830
+					'layout_strategy' => new EE_Template_Layout(
831
+						array(
832
+							'layout_template_file' => $this->_template,
833
+							'template_args'        => apply_filters(
834
+								'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
835
+								array(
836
+									'reg_count'                 => $this->line_item_display->total_items(),
837
+									'transaction_details'       => $transaction_details,
838
+									'available_payment_methods' => array(),
839
+								)
840
+							),
841
+						)
842
+					),
843
+				)
844
+			)
845
+		);
846
+	}
847
+
848
+
849
+	/**
850
+	 * _extra_hidden_inputs
851
+	 *
852
+	 * @param bool $no_payment_required
853
+	 * @return \EE_Form_Section_Proper
854
+	 * @throws \EE_Error
855
+	 */
856
+	private function _extra_hidden_inputs($no_payment_required = true)
857
+	{
858
+		return new EE_Form_Section_Proper(
859
+			array(
860
+				'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
861
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
862
+				'subsections'     => array(
863
+					'spco_no_payment_required' => new EE_Hidden_Input(
864
+						array(
865
+							'normalization_strategy' => new EE_Boolean_Normalization(),
866
+							'html_name'              => 'spco_no_payment_required',
867
+							'html_id'                => 'spco-no-payment-required-payment_options',
868
+							'default'                => $no_payment_required,
869
+						)
870
+					),
871
+					'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
872
+						array(
873
+							'normalization_strategy' => new EE_Int_Normalization(),
874
+							'html_name'              => 'spco_transaction_id',
875
+							'html_id'                => 'spco-transaction-id',
876
+							'default'                => $this->checkout->transaction->ID(),
877
+						)
878
+					),
879
+				),
880
+			)
881
+		);
882
+	}
883
+
884
+
885
+	/**
886
+	 *    _apply_registration_payments_to_amount_owing
887
+	 *
888
+	 * @access protected
889
+	 * @param array $registrations
890
+	 * @throws EE_Error
891
+	 */
892
+	protected function _apply_registration_payments_to_amount_owing(array $registrations)
893
+	{
894
+		$payments = array();
895
+		foreach ($registrations as $registration) {
896
+			if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
897
+				$payments += $registration->registration_payments();
898
+			}
899
+		}
900
+		if (! empty($payments)) {
901
+			foreach ($payments as $payment) {
902
+				if ($payment instanceof EE_Registration_Payment) {
903
+					$this->checkout->amount_owing -= $payment->amount();
904
+				}
905
+			}
906
+		}
907
+	}
908
+
909
+
910
+	/**
911
+	 *    _reset_selected_method_of_payment
912
+	 *
913
+	 * @access    private
914
+	 * @param    bool $force_reset
915
+	 * @return void
916
+	 * @throws InvalidArgumentException
917
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
918
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
919
+	 */
920
+	private function _reset_selected_method_of_payment($force_reset = false)
921
+	{
922
+		$reset_payment_method = $force_reset
923
+			? true
924
+			: sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
925
+		if ($reset_payment_method) {
926
+			$this->checkout->selected_method_of_payment = null;
927
+			$this->checkout->payment_method             = null;
928
+			$this->checkout->billing_form               = null;
929
+			$this->_save_selected_method_of_payment();
930
+		}
931
+	}
932
+
933
+
934
+	/**
935
+	 * _save_selected_method_of_payment
936
+	 * stores the selected_method_of_payment in the session
937
+	 * so that it's available for all subsequent requests including AJAX
938
+	 *
939
+	 * @access        private
940
+	 * @param string $selected_method_of_payment
941
+	 * @return void
942
+	 * @throws InvalidArgumentException
943
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
944
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
945
+	 */
946
+	private function _save_selected_method_of_payment($selected_method_of_payment = '')
947
+	{
948
+		$selected_method_of_payment = ! empty($selected_method_of_payment)
949
+			? $selected_method_of_payment
950
+			: $this->checkout->selected_method_of_payment;
951
+		EE_Registry::instance()->SSN->set_session_data(
952
+			array('selected_method_of_payment' => $selected_method_of_payment)
953
+		);
954
+	}
955
+
956
+
957
+	/**
958
+	 * _setup_payment_options
959
+	 *
960
+	 * @return EE_Form_Section_Proper
961
+	 * @throws EE_Error
962
+	 * @throws InvalidArgumentException
963
+	 * @throws ReflectionException
964
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
965
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
966
+	 */
967
+	public function _setup_payment_options()
968
+	{
969
+		// load payment method classes
970
+		$this->checkout->available_payment_methods = $this->_get_available_payment_methods();
971
+		if (empty($this->checkout->available_payment_methods)) {
972
+			EE_Error::add_error(
973
+				apply_filters(
974
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
975
+					sprintf(
976
+						esc_html__(
977
+							'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
978
+							'event_espresso'
979
+						),
980
+						'<br>',
981
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
982
+					)
983
+				),
984
+				__FILE__,
985
+				__FUNCTION__,
986
+				__LINE__
987
+			);
988
+		}
989
+		// switch up header depending on number of available payment methods
990
+		$payment_method_header     = count($this->checkout->available_payment_methods) > 1
991
+			? apply_filters(
992
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
993
+				esc_html__('Please Select Your Method of Payment', 'event_espresso')
994
+			)
995
+			: apply_filters(
996
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
997
+				esc_html__('Method of Payment', 'event_espresso')
998
+			);
999
+		$available_payment_methods = array(
1000
+			// display the "Payment Method" header
1001
+			'payment_method_header' => new EE_Form_Section_HTML(
1002
+				EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr')
1003
+			),
1004
+		);
1005
+		// the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1006
+		$available_payment_method_options = array();
1007
+		$default_payment_method_option    = array();
1008
+		// additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1009
+		$payment_methods_billing_info = array(
1010
+			new EE_Form_Section_HTML(
1011
+				EEH_HTML::div('<br />', '', '', 'clear:both;')
1012
+			),
1013
+		);
1014
+		// loop through payment methods
1015
+		foreach ($this->checkout->available_payment_methods as $payment_method) {
1016
+			if ($payment_method instanceof EE_Payment_Method) {
1017
+				$payment_method_button = EEH_HTML::img(
1018
+					$payment_method->button_url(),
1019
+					$payment_method->name(),
1020
+					'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1021
+					'spco-payment-method-btn-img'
1022
+				);
1023
+				// check if any payment methods are set as default
1024
+				// if payment method is already selected OR nothing is selected and this payment method should be
1025
+				// open_by_default
1026
+				if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
+					|| (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028
+				) {
1029
+					$this->checkout->selected_method_of_payment = $payment_method->slug();
1030
+					$this->_save_selected_method_of_payment();
1031
+					$default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1032
+				} else {
1033
+					$available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034
+				}
1035
+				$payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1036
+					$payment_method
1037
+				);
1038
+			}
1039
+		}
1040
+		// prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1041
+		// of PMs
1042
+		$available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1043
+		// now generate the actual form  inputs
1044
+		$available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045
+			$available_payment_method_options
1046
+		);
1047
+		$available_payment_methods                              += $payment_methods_billing_info;
1048
+		// build the available payment methods form
1049
+		return new EE_Form_Section_Proper(
1050
+			array(
1051
+				'html_id'         => 'spco-available-methods-of-payment-dv',
1052
+				'subsections'     => $available_payment_methods,
1053
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1054
+			)
1055
+		);
1056
+	}
1057
+
1058
+
1059
+	/**
1060
+	 * _get_available_payment_methods
1061
+	 *
1062
+	 * @return EE_Payment_Method[]
1063
+	 * @throws EE_Error
1064
+	 * @throws InvalidArgumentException
1065
+	 * @throws ReflectionException
1066
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1067
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1068
+	 */
1069
+	protected function _get_available_payment_methods()
1070
+	{
1071
+		if (! empty($this->checkout->available_payment_methods)) {
1072
+			return $this->checkout->available_payment_methods;
1073
+		}
1074
+		$available_payment_methods = array();
1075
+		// load EEM_Payment_Method
1076
+		EE_Registry::instance()->load_model('Payment_Method');
1077
+		/** @type EEM_Payment_Method $EEM_Payment_Method */
1078
+		$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1079
+		// get all active payment methods
1080
+		$payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1081
+			$this->checkout->transaction,
1082
+			EEM_Payment_Method::scope_cart
1083
+		);
1084
+		foreach ($payment_methods as $payment_method) {
1085
+			if ($payment_method instanceof EE_Payment_Method) {
1086
+				$available_payment_methods[$payment_method->slug()] = $payment_method;
1087
+			}
1088
+		}
1089
+		return $available_payment_methods;
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 *    _available_payment_method_inputs
1095
+	 *
1096
+	 * @access    private
1097
+	 * @param    array $available_payment_method_options
1098
+	 * @return    \EE_Form_Section_Proper
1099
+	 */
1100
+	private function _available_payment_method_inputs($available_payment_method_options = array())
1101
+	{
1102
+		// generate inputs
1103
+		return new EE_Form_Section_Proper(
1104
+			array(
1105
+				'html_id'         => 'ee-available-payment-method-inputs',
1106
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1107
+				'subsections'     => array(
1108
+					'' => new EE_Radio_Button_Input(
1109
+						$available_payment_method_options,
1110
+						array(
1111
+							'html_name'          => 'selected_method_of_payment',
1112
+							'html_class'         => 'spco-payment-method',
1113
+							'default'            => $this->checkout->selected_method_of_payment,
1114
+							'label_size'         => 11,
1115
+							'enforce_label_size' => true,
1116
+						)
1117
+					),
1118
+				),
1119
+			)
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	/**
1125
+	 *    _payment_method_billing_info
1126
+	 *
1127
+	 * @access    private
1128
+	 * @param    EE_Payment_Method $payment_method
1129
+	 * @return EE_Form_Section_Proper
1130
+	 * @throws EE_Error
1131
+	 * @throws InvalidArgumentException
1132
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1133
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1134
+	 */
1135
+	private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1136
+	{
1137
+		$currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1138
+			? true
1139
+			: false;
1140
+		// generate the billing form for payment method
1141
+		$billing_form                 = $currently_selected
1142
+			? $this->_get_billing_form_for_payment_method($payment_method)
1143
+			: new EE_Form_Section_HTML();
1144
+		$this->checkout->billing_form = $currently_selected
1145
+			? $billing_form
1146
+			: $this->checkout->billing_form;
1147
+		// it's all in the details
1148
+		$info_html = EEH_HTML::h3(
1149
+			esc_html__('Important information regarding your payment', 'event_espresso'),
1150
+			'',
1151
+			'spco-payment-method-hdr'
1152
+		);
1153
+		// add some info regarding the step, either from what's saved in the admin,
1154
+		// or a default string depending on whether the PM has a billing form or not
1155
+		if ($payment_method->description()) {
1156
+			$payment_method_info = $payment_method->description();
1157
+		} elseif ($billing_form instanceof EE_Billing_Info_Form) {
1158
+			$payment_method_info = sprintf(
1159
+				esc_html__(
1160
+					'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1161
+					'event_espresso'
1162
+				),
1163
+				$this->submit_button_text()
1164
+			);
1165
+		} else {
1166
+			$payment_method_info = sprintf(
1167
+				esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1168
+				$this->submit_button_text()
1169
+			);
1170
+		}
1171
+		$info_html .= EEH_HTML::p(
1172
+			apply_filters(
1173
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1174
+				$payment_method_info
1175
+			),
1176
+			'',
1177
+			'spco-payment-method-desc ee-attention'
1178
+		);
1179
+		return new EE_Form_Section_Proper(
1180
+			array(
1181
+				'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1182
+				'html_class'      => 'spco-payment-method-info-dv',
1183
+				// only display the selected or default PM
1184
+				'html_style'      => $currently_selected ? '' : 'display:none;',
1185
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1186
+				'subsections'     => array(
1187
+					'info'         => new EE_Form_Section_HTML($info_html),
1188
+					'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1189
+				),
1190
+			)
1191
+		);
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * get_billing_form_html_for_payment_method
1197
+	 *
1198
+	 * @access public
1199
+	 * @return string
1200
+	 * @throws EE_Error
1201
+	 * @throws InvalidArgumentException
1202
+	 * @throws ReflectionException
1203
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1204
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1205
+	 */
1206
+	public function get_billing_form_html_for_payment_method()
1207
+	{
1208
+		// how have they chosen to pay?
1209
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210
+		$this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212
+			return false;
1213
+		}
1214
+		if (apply_filters(
1215
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1216
+			false
1217
+		)) {
1218
+			EE_Error::add_success(
1219
+				apply_filters(
1220
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1221
+					sprintf(
1222
+						esc_html__(
1223
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1224
+							'event_espresso'
1225
+						),
1226
+						$this->checkout->payment_method->name()
1227
+					)
1228
+				)
1229
+			);
1230
+		}
1231
+		// now generate billing form for selected method of payment
1232
+		$payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1233
+		// fill form with attendee info if applicable
1234
+		if ($payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1235
+			&& $this->checkout->transaction_has_primary_registrant()
1236
+		) {
1237
+			$payment_method_billing_form->populate_from_attendee(
1238
+				$this->checkout->transaction->primary_registration()->attendee()
1239
+			);
1240
+		}
1241
+		// and debug content
1242
+		if ($payment_method_billing_form instanceof EE_Billing_Info_Form
1243
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1244
+		) {
1245
+			$payment_method_billing_form =
1246
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1247
+					$payment_method_billing_form
1248
+				);
1249
+		}
1250
+		$billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1251
+			? $payment_method_billing_form->get_html()
1252
+			: '';
1253
+		$this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1254
+		// localize validation rules for main form
1255
+		$this->checkout->current_step->reg_form->localize_validation_rules();
1256
+		$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1257
+		return true;
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * _get_billing_form_for_payment_method
1263
+	 *
1264
+	 * @access private
1265
+	 * @param EE_Payment_Method $payment_method
1266
+	 * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1267
+	 * @throws EE_Error
1268
+	 * @throws InvalidArgumentException
1269
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1270
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1271
+	 */
1272
+	private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1273
+	{
1274
+		$billing_form = $payment_method->type_obj()->billing_form(
1275
+			$this->checkout->transaction,
1276
+			array('amount_owing' => $this->checkout->amount_owing)
1277
+		);
1278
+		if ($billing_form instanceof EE_Billing_Info_Form) {
1279
+			if (apply_filters(
1280
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1281
+				false
1282
+			)
1283
+				&& EE_Registry::instance()->REQ->is_set('payment_method')
1284
+			) {
1285
+				EE_Error::add_success(
1286
+					apply_filters(
1287
+						'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1288
+						sprintf(
1289
+							esc_html__(
1290
+								'You have selected "%s" as your method of payment. Please note the important payment information below.',
1291
+								'event_espresso'
1292
+							),
1293
+							$payment_method->name()
1294
+						)
1295
+					)
1296
+				);
1297
+			}
1298
+			return apply_filters(
1299
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1300
+				$billing_form,
1301
+				$payment_method
1302
+			);
1303
+		}
1304
+		// no actual billing form, so return empty HTML form section
1305
+		return new EE_Form_Section_HTML();
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * _get_selected_method_of_payment
1311
+	 *
1312
+	 * @access private
1313
+	 * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1314
+	 *                          is not found in the incoming request
1315
+	 * @param string  $request_param
1316
+	 * @return NULL|string
1317
+	 * @throws EE_Error
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1320
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1321
+	 */
1322
+	private function _get_selected_method_of_payment(
1323
+		$required = false,
1324
+		$request_param = 'selected_method_of_payment'
1325
+	) {
1326
+		// is selected_method_of_payment set in the request ?
1327
+		$selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1328
+		if ($selected_method_of_payment) {
1329
+			// sanitize it
1330
+			$selected_method_of_payment = is_array($selected_method_of_payment)
1331
+				? array_shift($selected_method_of_payment)
1332
+				: $selected_method_of_payment;
1333
+			$selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1334
+			// store it in the session so that it's available for all subsequent requests including AJAX
1335
+			$this->_save_selected_method_of_payment($selected_method_of_payment);
1336
+		} else {
1337
+			// or is is set in the session ?
1338
+			$selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1339
+				'selected_method_of_payment'
1340
+			);
1341
+		}
1342
+		// do ya really really gotta have it?
1343
+		if (empty($selected_method_of_payment) && $required) {
1344
+			EE_Error::add_error(
1345
+				sprintf(
1346
+					esc_html__(
1347
+						'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1348
+						'event_espresso'
1349
+					),
1350
+					'<br/>',
1351
+					'<br/>',
1352
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
1353
+				),
1354
+				__FILE__,
1355
+				__FUNCTION__,
1356
+				__LINE__
1357
+			);
1358
+			return null;
1359
+		}
1360
+		return $selected_method_of_payment;
1361
+	}
1362
+
1363
+
1364
+
1365
+
1366
+
1367
+
1368
+	/********************************************************************************************************/
1369
+	/***********************************  SWITCH PAYMENT METHOD  ************************************/
1370
+	/********************************************************************************************************/
1371
+	/**
1372
+	 * switch_payment_method
1373
+	 *
1374
+	 * @access public
1375
+	 * @return string
1376
+	 * @throws EE_Error
1377
+	 * @throws InvalidArgumentException
1378
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1379
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1380
+	 */
1381
+	public function switch_payment_method()
1382
+	{
1383
+		if (! $this->_verify_payment_method_is_set()) {
1384
+			return false;
1385
+		}
1386
+		if (apply_filters(
1387
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1388
+			false
1389
+		)) {
1390
+			EE_Error::add_success(
1391
+				apply_filters(
1392
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1393
+					sprintf(
1394
+						esc_html__(
1395
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1396
+							'event_espresso'
1397
+						),
1398
+						$this->checkout->payment_method->name()
1399
+					)
1400
+				)
1401
+			);
1402
+		}
1403
+		// generate billing form for selected method of payment if it hasn't been done already
1404
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1405
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1406
+				$this->checkout->payment_method
1407
+			);
1408
+		}
1409
+		// fill form with attendee info if applicable
1410
+		if (apply_filters(
1411
+			'FHEE__populate_billing_form_fields_from_attendee',
1412
+			(
1413
+				$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1414
+				&& $this->checkout->transaction_has_primary_registrant()
1415
+			),
1416
+			$this->checkout->billing_form,
1417
+			$this->checkout->transaction
1418
+		)
1419
+		) {
1420
+			$this->checkout->billing_form->populate_from_attendee(
1421
+				$this->checkout->transaction->primary_registration()->attendee()
1422
+			);
1423
+		}
1424
+		// and debug content
1425
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form
1426
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1427
+		) {
1428
+			$this->checkout->billing_form =
1429
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1430
+					$this->checkout->billing_form
1431
+				);
1432
+		}
1433
+		// get html and validation rules for form
1434
+		if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1435
+			$this->checkout->json_response->set_return_data(
1436
+				array('payment_method_info' => $this->checkout->billing_form->get_html())
1437
+			);
1438
+			// localize validation rules for main form
1439
+			$this->checkout->billing_form->localize_validation_rules(true);
1440
+			$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1441
+		} else {
1442
+			$this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1443
+		}
1444
+		//prevents advancement to next step
1445
+		$this->checkout->continue_reg = false;
1446
+		return true;
1447
+	}
1448
+
1449
+
1450
+	/**
1451
+	 * _verify_payment_method_is_set
1452
+	 *
1453
+	 * @return bool
1454
+	 * @throws EE_Error
1455
+	 * @throws InvalidArgumentException
1456
+	 * @throws ReflectionException
1457
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1458
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1459
+	 */
1460
+	protected function _verify_payment_method_is_set()
1461
+	{
1462
+		// generate billing form for selected method of payment if it hasn't been done already
1463
+		if (empty($this->checkout->selected_method_of_payment)) {
1464
+			// how have they chosen to pay?
1465
+			$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1466
+		} else {
1467
+			// choose your own adventure based on method_of_payment
1468
+			switch ($this->checkout->selected_method_of_payment) {
1469
+				case 'events_sold_out' :
1470
+					EE_Error::add_attention(
1471
+						apply_filters(
1472
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1473
+							esc_html__(
1474
+								'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1475
+								'event_espresso'
1476
+							)
1477
+						),
1478
+						__FILE__, __FUNCTION__, __LINE__
1479
+					);
1480
+					return false;
1481
+					break;
1482
+				case 'payments_closed' :
1483
+					EE_Error::add_attention(
1484
+						apply_filters(
1485
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1486
+							esc_html__(
1487
+								'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1488
+								'event_espresso'
1489
+							)
1490
+						),
1491
+						__FILE__, __FUNCTION__, __LINE__
1492
+					);
1493
+					return false;
1494
+					break;
1495
+				case 'no_payment_required' :
1496
+					EE_Error::add_attention(
1497
+						apply_filters(
1498
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1499
+							esc_html__(
1500
+								'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1501
+								'event_espresso'
1502
+							)
1503
+						),
1504
+						__FILE__, __FUNCTION__, __LINE__
1505
+					);
1506
+					return false;
1507
+					break;
1508
+				default:
1509
+			}
1510
+		}
1511
+		// verify payment method
1512
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513
+			// get payment method for selected method of payment
1514
+			$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515
+		}
1516
+		return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1517
+	}
1518
+
1519
+
1520
+
1521
+	/********************************************************************************************************/
1522
+	/***************************************  SAVE PAYER DETAILS  ****************************************/
1523
+	/********************************************************************************************************/
1524
+	/**
1525
+	 * save_payer_details_via_ajax
1526
+	 *
1527
+	 * @return void
1528
+	 * @throws EE_Error
1529
+	 * @throws InvalidArgumentException
1530
+	 * @throws ReflectionException
1531
+	 * @throws RuntimeException
1532
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1533
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1534
+	 */
1535
+	public function save_payer_details_via_ajax()
1536
+	{
1537
+		if (! $this->_verify_payment_method_is_set()) {
1538
+			return;
1539
+		}
1540
+		// generate billing form for selected method of payment if it hasn't been done already
1541
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1542
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1543
+				$this->checkout->payment_method
1544
+			);
1545
+		}
1546
+		// generate primary attendee from payer info if applicable
1547
+		if (! $this->checkout->transaction_has_primary_registrant()) {
1548
+			$attendee = $this->_create_attendee_from_request_data();
1549
+			if ($attendee instanceof EE_Attendee) {
1550
+				foreach ($this->checkout->transaction->registrations() as $registration) {
1551
+					if ($registration->is_primary_registrant()) {
1552
+						$this->checkout->primary_attendee_obj = $attendee;
1553
+						$registration->_add_relation_to($attendee, 'Attendee');
1554
+						$registration->set_attendee_id($attendee->ID());
1555
+						$registration->update_cache_after_object_save('Attendee', $attendee);
1556
+					}
1557
+				}
1558
+			}
1559
+		}
1560
+	}
1561
+
1562
+
1563
+	/**
1564
+	 * create_attendee_from_request_data
1565
+	 * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1566
+	 *
1567
+	 * @return EE_Attendee
1568
+	 * @throws EE_Error
1569
+	 * @throws InvalidArgumentException
1570
+	 * @throws ReflectionException
1571
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1572
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1573
+	 */
1574
+	protected function _create_attendee_from_request_data()
1575
+	{
1576
+		// get State ID
1577
+		$STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
+		if (! empty($STA_ID)) {
1579
+			// can we get state object from name ?
1580
+			EE_Registry::instance()->load_model('State');
1581
+			$state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1582
+			$STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1583
+		}
1584
+		// get Country ISO
1585
+		$CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
+		if (! empty($CNT_ISO)) {
1587
+			// can we get country object from name ?
1588
+			EE_Registry::instance()->load_model('Country');
1589
+			$country = EEM_Country::instance()->get_col(
1590
+				array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1591
+				'CNT_ISO'
1592
+			);
1593
+			$CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1594
+		}
1595
+		// grab attendee data
1596
+		$attendee_data = array(
1597
+			'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1598
+			'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1599
+			'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1600
+			'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1601
+			'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1602
+			'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1603
+			'STA_ID'       => $STA_ID,
1604
+			'CNT_ISO'      => $CNT_ISO,
1605
+			'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1606
+			'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1607
+		);
1608
+		// validate the email address since it is the most important piece of info
1609
+		if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1610
+			EE_Error::add_error(
1611
+				esc_html__('An invalid email address was submitted.', 'event_espresso'),
1612
+				__FILE__,
1613
+				__FUNCTION__,
1614
+				__LINE__
1615
+			);
1616
+		}
1617
+		// does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618
+		// AND email address
1619
+		if (! empty($attendee_data['ATT_fname'])
1620
+			&& ! empty($attendee_data['ATT_lname'])
1621
+			&& ! empty($attendee_data['ATT_email'])
1622
+		) {
1623
+			$existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1624
+				array(
1625
+					'ATT_fname' => $attendee_data['ATT_fname'],
1626
+					'ATT_lname' => $attendee_data['ATT_lname'],
1627
+					'ATT_email' => $attendee_data['ATT_email'],
1628
+				)
1629
+			);
1630
+			if ($existing_attendee instanceof EE_Attendee) {
1631
+				return $existing_attendee;
1632
+			}
1633
+		}
1634
+		// no existing attendee? kk let's create a new one
1635
+		// kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1636
+		// don't exist
1637
+		$attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1638
+			? $attendee_data['ATT_fname']
1639
+			: $attendee_data['ATT_email'];
1640
+		$attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1641
+			? $attendee_data['ATT_lname']
1642
+			: $attendee_data['ATT_email'];
1643
+		return EE_Attendee::new_instance($attendee_data);
1644
+	}
1645
+
1646
+
1647
+
1648
+	/********************************************************************************************************/
1649
+	/****************************************  PROCESS REG STEP  *****************************************/
1650
+	/********************************************************************************************************/
1651
+	/**
1652
+	 * process_reg_step
1653
+	 *
1654
+	 * @return bool
1655
+	 * @throws EE_Error
1656
+	 * @throws InvalidArgumentException
1657
+	 * @throws ReflectionException
1658
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1659
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1660
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1661
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1662
+	 */
1663
+	public function process_reg_step()
1664
+	{
1665
+		// how have they chosen to pay?
1666
+		$this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1667
+			? 'no_payment_required'
1668
+			: $this->_get_selected_method_of_payment(true);
1669
+		// choose your own adventure based on method_of_payment
1670
+		switch ($this->checkout->selected_method_of_payment) {
1671
+
1672
+			case 'events_sold_out' :
1673
+				$this->checkout->redirect     = true;
1674
+				$this->checkout->redirect_url = $this->checkout->cancel_page_url;
1675
+				$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1676
+				// mark this reg step as completed
1677
+				$this->set_completed();
1678
+				return false;
1679
+				break;
1680
+
1681
+			case 'payments_closed' :
1682
+				if (apply_filters(
1683
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1684
+					false
1685
+				)) {
1686
+					EE_Error::add_success(
1687
+						esc_html__('no payment required at this time.', 'event_espresso'),
1688
+						__FILE__,
1689
+						__FUNCTION__,
1690
+						__LINE__
1691
+					);
1692
+				}
1693
+				// mark this reg step as completed
1694
+				$this->set_completed();
1695
+				return true;
1696
+				break;
1697
+
1698
+			case 'no_payment_required' :
1699
+				if (apply_filters(
1700
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1701
+					false
1702
+				)) {
1703
+					EE_Error::add_success(
1704
+						esc_html__('no payment required.', 'event_espresso'),
1705
+						__FILE__,
1706
+						__FUNCTION__,
1707
+						__LINE__
1708
+					);
1709
+				}
1710
+				// mark this reg step as completed
1711
+				$this->set_completed();
1712
+				return true;
1713
+				break;
1714
+
1715
+			default:
1716
+				$registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1717
+					EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1718
+				);
1719
+				$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1720
+					$registrations,
1721
+					EE_Registry::instance()->SSN->checkout()->revisit
1722
+				);
1723
+				// calculate difference between the two arrays
1724
+				$registrations = array_diff($registrations, $ejected_registrations);
1725
+				if (empty($registrations)) {
1726
+					$this->_redirect_because_event_sold_out();
1727
+					return false;
1728
+				}
1729
+				$payment_successful = $this->_process_payment();
1730
+				if ($payment_successful) {
1731
+					$this->checkout->continue_reg = true;
1732
+					$this->_maybe_set_completed($this->checkout->payment_method);
1733
+				} else {
1734
+					$this->checkout->continue_reg = false;
1735
+				}
1736
+				return $payment_successful;
1737
+		}
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * _redirect_because_event_sold_out
1743
+	 *
1744
+	 * @access protected
1745
+	 * @return void
1746
+	 */
1747
+	protected function _redirect_because_event_sold_out()
1748
+	{
1749
+		$this->checkout->continue_reg = false;
1750
+		// set redirect URL
1751
+		$this->checkout->redirect_url = add_query_arg(
1752
+			array('e_reg_url_link' => $this->checkout->reg_url_link),
1753
+			$this->checkout->current_step->reg_step_url()
1754
+		);
1755
+		$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1756
+	}
1757
+
1758
+
1759
+	/**
1760
+	 * _maybe_set_completed
1761
+	 *
1762
+	 * @access protected
1763
+	 * @param \EE_Payment_Method $payment_method
1764
+	 * @return void
1765
+	 * @throws \EE_Error
1766
+	 */
1767
+	protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1768
+	{
1769
+		switch ($payment_method->type_obj()->payment_occurs()) {
1770
+			case EE_PMT_Base::offsite :
1771
+				break;
1772
+			case EE_PMT_Base::onsite :
1773
+			case EE_PMT_Base::offline :
1774
+				// mark this reg step as completed
1775
+				$this->set_completed();
1776
+				break;
1777
+		}
1778
+	}
1779
+
1780
+
1781
+	/**
1782
+	 *    update_reg_step
1783
+	 *    this is the final step after a user  revisits the site to retry a payment
1784
+	 *
1785
+	 * @return bool
1786
+	 * @throws EE_Error
1787
+	 * @throws InvalidArgumentException
1788
+	 * @throws ReflectionException
1789
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1790
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1791
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1792
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1793
+	 */
1794
+	public function update_reg_step()
1795
+	{
1796
+		$success = true;
1797
+		// if payment required
1798
+		if ($this->checkout->transaction->total() > 0) {
1799
+			do_action(
1800
+				'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1801
+				$this->checkout->transaction
1802
+			);
1803
+			// attempt payment via payment method
1804
+			$success = $this->process_reg_step();
1805
+		}
1806
+		if ($success && ! $this->checkout->redirect) {
1807
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1808
+				$this->checkout->transaction->ID()
1809
+			);
1810
+			// set return URL
1811
+			$this->checkout->redirect_url = add_query_arg(
1812
+				array('e_reg_url_link' => $this->checkout->reg_url_link),
1813
+				$this->checkout->thank_you_page_url
1814
+			);
1815
+		}
1816
+		return $success;
1817
+	}
1818
+
1819
+
1820
+	/**
1821
+	 *    _process_payment
1822
+	 *
1823
+	 * @access private
1824
+	 * @return bool
1825
+	 * @throws EE_Error
1826
+	 * @throws InvalidArgumentException
1827
+	 * @throws ReflectionException
1828
+	 * @throws RuntimeException
1829
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1830
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1831
+	 */
1832
+	private function _process_payment()
1833
+	{
1834
+		// basically confirm that the event hasn't sold out since they hit the page
1835
+		if (! $this->_last_second_ticket_verifications()) {
1836
+			return false;
1837
+		}
1838
+		// ya gotta make a choice man
1839
+		if (empty($this->checkout->selected_method_of_payment)) {
1840
+			$this->checkout->json_response->set_plz_select_method_of_payment(
1841
+				esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1842
+			);
1843
+			return false;
1844
+		}
1845
+		// get EE_Payment_Method object
1846
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847
+			return false;
1848
+		}
1849
+		// setup billing form
1850
+		if ($this->checkout->payment_method->is_on_site()) {
1851
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1852
+				$this->checkout->payment_method
1853
+			);
1854
+			// bad billing form ?
1855
+			if (! $this->_billing_form_is_valid()) {
1856
+				return false;
1857
+			}
1858
+		}
1859
+		// ensure primary registrant has been fully processed
1860
+		if (! $this->_setup_primary_registrant_prior_to_payment()) {
1861
+			return false;
1862
+		}
1863
+		// if session is close to expiring (under 10 minutes by default)
1864
+		if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1865
+			// add some time to session expiration so that payment can be completed
1866
+			EE_Registry::instance()->SSN->extend_expiration();
1867
+		}
1868
+		/** @type EE_Transaction_Processor $transaction_processor */
1869
+		//$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1870
+		// in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1871
+		// for events with a default reg status of Approved
1872
+		// $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1873
+		//      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1874
+		// );
1875
+		// attempt payment
1876
+		$payment = $this->_attempt_payment($this->checkout->payment_method);
1877
+		// process results
1878
+		$payment = $this->_validate_payment($payment);
1879
+		$payment = $this->_post_payment_processing($payment);
1880
+		// verify payment
1881
+		if ($payment instanceof EE_Payment) {
1882
+			// store that for later
1883
+			$this->checkout->payment = $payment;
1884
+			// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1885
+			$this->checkout->transaction->toggle_failed_transaction_status();
1886
+			$payment_status = $payment->status();
1887
+			if (
1888
+				$payment_status === EEM_Payment::status_id_approved
1889
+				|| $payment_status === EEM_Payment::status_id_pending
1890
+			) {
1891
+				return true;
1892
+			} else {
1893
+				return false;
1894
+			}
1895
+		} else if ($payment === true) {
1896
+			// please note that offline payment methods will NOT make a payment,
1897
+			// but instead just mark themselves as the PMD_ID on the transaction, and return true
1898
+			$this->checkout->payment = $payment;
1899
+			return true;
1900
+		}
1901
+		// where's my money?
1902
+		return false;
1903
+	}
1904
+
1905
+
1906
+	/**
1907
+	 * _last_second_ticket_verifications
1908
+	 *
1909
+	 * @access public
1910
+	 * @return bool
1911
+	 * @throws EE_Error
1912
+	 */
1913
+	protected function _last_second_ticket_verifications()
1914
+	{
1915
+		// don't bother re-validating if not a return visit
1916
+		if (! $this->checkout->revisit) {
1917
+			return true;
1918
+		}
1919
+		$registrations = $this->checkout->transaction->registrations();
1920
+		if (empty($registrations)) {
1921
+			return false;
1922
+		}
1923
+		foreach ($registrations as $registration) {
1924
+			if ($registration instanceof EE_Registration) {
1925
+				$event = $registration->event_obj();
1926
+				if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1927
+					EE_Error::add_error(
1928
+						apply_filters(
1929
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1930
+							sprintf(
1931
+								esc_html__(
1932
+									'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1933
+									'event_espresso'
1934
+								),
1935
+								$event->name()
1936
+							)
1937
+						),
1938
+						__FILE__,
1939
+						__FUNCTION__,
1940
+						__LINE__
1941
+					);
1942
+					return false;
1943
+				}
1944
+			}
1945
+		}
1946
+		return true;
1947
+	}
1948
+
1949
+
1950
+	/**
1951
+	 * redirect_form
1952
+	 *
1953
+	 * @access public
1954
+	 * @return bool
1955
+	 * @throws EE_Error
1956
+	 * @throws InvalidArgumentException
1957
+	 * @throws ReflectionException
1958
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1959
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1960
+	 */
1961
+	public function redirect_form()
1962
+	{
1963
+		$payment_method_billing_info = $this->_payment_method_billing_info(
1964
+			$this->_get_payment_method_for_selected_method_of_payment()
1965
+		);
1966
+		$html                        = $payment_method_billing_info->get_html();
1967
+		$html                        .= $this->checkout->redirect_form;
1968
+		EE_Registry::instance()->REQ->add_output($html);
1969
+		return true;
1970
+	}
1971
+
1972
+
1973
+	/**
1974
+	 * _billing_form_is_valid
1975
+	 *
1976
+	 * @access private
1977
+	 * @return bool
1978
+	 * @throws \EE_Error
1979
+	 */
1980
+	private function _billing_form_is_valid()
1981
+	{
1982
+		if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983
+			return true;
1984
+		}
1985
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1986
+			if ($this->checkout->billing_form->was_submitted()) {
1987
+				$this->checkout->billing_form->receive_form_submission();
1988
+				if ($this->checkout->billing_form->is_valid()) {
1989
+					return true;
1990
+				}
1991
+				$validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
1992
+				$error_strings     = array();
1993
+				foreach ($validation_errors as $validation_error) {
1994
+					if ($validation_error instanceof EE_Validation_Error) {
1995
+						$form_section = $validation_error->get_form_section();
1996
+						if ($form_section instanceof EE_Form_Input_Base) {
1997
+							$label = $form_section->html_label_text();
1998
+						} elseif ($form_section instanceof EE_Form_Section_Base) {
1999
+							$label = $form_section->name();
2000
+						} else {
2001
+							$label = esc_html__('Validation Error', 'event_espresso');
2002
+						}
2003
+						$error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2004
+					}
2005
+				}
2006
+				EE_Error::add_error(
2007
+					sprintf(
2008
+						esc_html__(
2009
+							'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2010
+							'event_espresso'
2011
+						),
2012
+						'<br/>',
2013
+						implode('<br/>', $error_strings)
2014
+					),
2015
+					__FILE__,
2016
+					__FUNCTION__,
2017
+					__LINE__
2018
+				);
2019
+			} else {
2020
+				EE_Error::add_error(
2021
+					esc_html__(
2022
+						'The billing form was not submitted or something prevented it\'s submission.',
2023
+						'event_espresso'
2024
+					),
2025
+					__FILE__,
2026
+					__FUNCTION__,
2027
+					__LINE__
2028
+				);
2029
+			}
2030
+		} else {
2031
+			EE_Error::add_error(
2032
+				esc_html__('The submitted billing form is invalid possibly due to a technical reason.', 'event_espresso'),
2033
+				__FILE__,
2034
+				__FUNCTION__,
2035
+				__LINE__
2036
+			);
2037
+		}
2038
+		return false;
2039
+	}
2040
+
2041
+
2042
+	/**
2043
+	 * _setup_primary_registrant_prior_to_payment
2044
+	 * ensures that the primary registrant has a valid attendee object created with the critical details populated
2045
+	 * (first & last name & email) and that both the transaction object and primary registration object have been saved
2046
+	 * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2047
+	 * yet)
2048
+	 *
2049
+	 * @access private
2050
+	 * @return bool
2051
+	 * @throws EE_Error
2052
+	 * @throws InvalidArgumentException
2053
+	 * @throws ReflectionException
2054
+	 * @throws RuntimeException
2055
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2056
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2057
+	 */
2058
+	private function _setup_primary_registrant_prior_to_payment()
2059
+	{
2060
+		// check if transaction has a primary registrant and that it has a related Attendee object
2061
+		// if not, then we need to at least gather some primary registrant data before attempting payment
2062
+		if (
2063
+			$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2064
+			&& ! $this->checkout->transaction_has_primary_registrant()
2065
+			&& ! $this->_capture_primary_registration_data_from_billing_form()
2066
+		) {
2067
+			return false;
2068
+		}
2069
+		// because saving an object clears it's cache, we need to do the chevy shuffle
2070
+		// grab the primary_registration object
2071
+		$primary_registration = $this->checkout->transaction->primary_registration();
2072
+		// at this point we'll consider a TXN to not have been failed
2073
+		$this->checkout->transaction->toggle_failed_transaction_status();
2074
+		// save the TXN ( which clears cached copy of primary_registration)
2075
+		$this->checkout->transaction->save();
2076
+		// grab TXN ID and save it to the primary_registration
2077
+		$primary_registration->set_transaction_id($this->checkout->transaction->ID());
2078
+		// save what we have so far
2079
+		$primary_registration->save();
2080
+		return true;
2081
+	}
2082
+
2083
+
2084
+	/**
2085
+	 * _capture_primary_registration_data_from_billing_form
2086
+	 *
2087
+	 * @access private
2088
+	 * @return bool
2089
+	 * @throws EE_Error
2090
+	 * @throws InvalidArgumentException
2091
+	 * @throws ReflectionException
2092
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2093
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2094
+	 */
2095
+	private function _capture_primary_registration_data_from_billing_form()
2096
+	{
2097
+		// convert billing form data into an attendee
2098
+		$this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
+		if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100
+			EE_Error::add_error(
2101
+				sprintf(
2102
+					esc_html__(
2103
+						'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2104
+						'event_espresso'
2105
+					),
2106
+					'<br/>',
2107
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2108
+				),
2109
+				__FILE__,
2110
+				__FUNCTION__,
2111
+				__LINE__
2112
+			);
2113
+			return false;
2114
+		}
2115
+		$primary_registration = $this->checkout->transaction->primary_registration();
2116
+		if (! $primary_registration instanceof EE_Registration) {
2117
+			EE_Error::add_error(
2118
+				sprintf(
2119
+					esc_html__(
2120
+						'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2121
+						'event_espresso'
2122
+					),
2123
+					'<br/>',
2124
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2125
+				),
2126
+				__FILE__,
2127
+				__FUNCTION__,
2128
+				__LINE__
2129
+			);
2130
+			return false;
2131
+		}
2132
+		if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133
+			  instanceof
2134
+			  EE_Attendee
2135
+		) {
2136
+			EE_Error::add_error(
2137
+				sprintf(
2138
+					esc_html__(
2139
+						'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2140
+						'event_espresso'
2141
+					),
2142
+					'<br/>',
2143
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2144
+				),
2145
+				__FILE__,
2146
+				__FUNCTION__,
2147
+				__LINE__
2148
+			);
2149
+			return false;
2150
+		}
2151
+		/** @type EE_Registration_Processor $registration_processor */
2152
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2153
+		// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2154
+		$registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2155
+		return true;
2156
+	}
2157
+
2158
+
2159
+	/**
2160
+	 * _get_payment_method_for_selected_method_of_payment
2161
+	 * retrieves a valid payment method
2162
+	 *
2163
+	 * @access public
2164
+	 * @return EE_Payment_Method
2165
+	 * @throws EE_Error
2166
+	 * @throws InvalidArgumentException
2167
+	 * @throws ReflectionException
2168
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2169
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2170
+	 */
2171
+	private function _get_payment_method_for_selected_method_of_payment()
2172
+	{
2173
+		if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2174
+			$this->_redirect_because_event_sold_out();
2175
+			return null;
2176
+		}
2177
+		// get EE_Payment_Method object
2178
+		if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2179
+			$payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2180
+		} else {
2181
+			// load EEM_Payment_Method
2182
+			EE_Registry::instance()->load_model('Payment_Method');
2183
+			/** @type EEM_Payment_Method $EEM_Payment_Method */
2184
+			$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2185
+			$payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186
+		}
2187
+		// verify $payment_method
2188
+		if (! $payment_method instanceof EE_Payment_Method) {
2189
+			// not a payment
2190
+			EE_Error::add_error(
2191
+				sprintf(
2192
+					esc_html__(
2193
+						'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2194
+						'event_espresso'
2195
+					),
2196
+					'<br/>',
2197
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2198
+				),
2199
+				__FILE__,
2200
+				__FUNCTION__,
2201
+				__LINE__
2202
+			);
2203
+			return null;
2204
+		}
2205
+		// and verify it has a valid Payment_Method Type object
2206
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207
+			// not a payment
2208
+			EE_Error::add_error(
2209
+				sprintf(
2210
+					esc_html__(
2211
+						'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2212
+						'event_espresso'
2213
+					),
2214
+					'<br/>',
2215
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2216
+				),
2217
+				__FILE__,
2218
+				__FUNCTION__,
2219
+				__LINE__
2220
+			);
2221
+			return null;
2222
+		}
2223
+		return $payment_method;
2224
+	}
2225
+
2226
+
2227
+	/**
2228
+	 *    _attempt_payment
2229
+	 *
2230
+	 * @access    private
2231
+	 * @type    EE_Payment_Method $payment_method
2232
+	 * @return mixed EE_Payment | boolean
2233
+	 * @throws EE_Error
2234
+	 * @throws InvalidArgumentException
2235
+	 * @throws ReflectionException
2236
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2237
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2238
+	 */
2239
+	private function _attempt_payment(EE_Payment_Method $payment_method)
2240
+	{
2241
+		$payment = null;
2242
+		$this->checkout->transaction->save();
2243
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
+		if (! $payment_processor instanceof EE_Payment_Processor) {
2245
+			return false;
2246
+		}
2247
+		try {
2248
+			$payment_processor->set_revisit($this->checkout->revisit);
2249
+			// generate payment object
2250
+			$payment = $payment_processor->process_payment(
2251
+				$payment_method,
2252
+				$this->checkout->transaction,
2253
+				$this->checkout->amount_owing,
2254
+				$this->checkout->billing_form,
2255
+				$this->_get_return_url($payment_method),
2256
+				'CART',
2257
+				$this->checkout->admin_request,
2258
+				true,
2259
+				$this->reg_step_url()
2260
+			);
2261
+		} catch (Exception $e) {
2262
+			$this->_handle_payment_processor_exception($e);
2263
+		}
2264
+		return $payment;
2265
+	}
2266
+
2267
+
2268
+	/**
2269
+	 * _handle_payment_processor_exception
2270
+	 *
2271
+	 * @access protected
2272
+	 * @param \Exception $e
2273
+	 * @return void
2274
+	 * @throws EE_Error
2275
+	 * @throws InvalidArgumentException
2276
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2277
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2278
+	 */
2279
+	protected function _handle_payment_processor_exception(Exception $e)
2280
+	{
2281
+		EE_Error::add_error(
2282
+			sprintf(
2283
+				esc_html__(
2284
+					'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2285
+					'event_espresso'
2286
+				),
2287
+				'<br/>',
2288
+				EE_Registry::instance()->CFG->organization->get_pretty('email'),
2289
+				$e->getMessage(),
2290
+				$e->getFile(),
2291
+				$e->getLine()
2292
+			),
2293
+			__FILE__,
2294
+			__FUNCTION__,
2295
+			__LINE__
2296
+		);
2297
+	}
2298
+
2299
+
2300
+	/**
2301
+	 * _get_return_url
2302
+	 *
2303
+	 * @access protected
2304
+	 * @param \EE_Payment_Method $payment_method
2305
+	 * @return string
2306
+	 * @throws \EE_Error
2307
+	 */
2308
+	protected function _get_return_url(EE_Payment_Method $payment_method)
2309
+	{
2310
+		$return_url = '';
2311
+		switch ($payment_method->type_obj()->payment_occurs()) {
2312
+			case EE_PMT_Base::offsite :
2313
+				$return_url = add_query_arg(
2314
+					array(
2315
+						'action'                     => 'process_gateway_response',
2316
+						'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2317
+						'spco_txn'                   => $this->checkout->transaction->ID(),
2318
+					),
2319
+					$this->reg_step_url()
2320
+				);
2321
+				break;
2322
+			case EE_PMT_Base::onsite :
2323
+			case EE_PMT_Base::offline :
2324
+				$return_url = $this->checkout->next_step->reg_step_url();
2325
+				break;
2326
+		}
2327
+		return $return_url;
2328
+	}
2329
+
2330
+
2331
+	/**
2332
+	 * _validate_payment
2333
+	 *
2334
+	 * @access private
2335
+	 * @param EE_Payment $payment
2336
+	 * @return EE_Payment|FALSE
2337
+	 * @throws EE_Error
2338
+	 * @throws InvalidArgumentException
2339
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2340
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2341
+	 */
2342
+	private function _validate_payment($payment = null)
2343
+	{
2344
+		if ($this->checkout->payment_method->is_off_line()) {
2345
+			return true;
2346
+		}
2347
+		// verify payment object
2348
+		if (! $payment instanceof EE_Payment) {
2349
+			// not a payment
2350
+			EE_Error::add_error(
2351
+				sprintf(
2352
+					esc_html__(
2353
+						'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2354
+						'event_espresso'
2355
+					),
2356
+					'<br/>',
2357
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2358
+				),
2359
+				__FILE__,
2360
+				__FUNCTION__,
2361
+				__LINE__
2362
+			);
2363
+			return false;
2364
+		}
2365
+		return $payment;
2366
+	}
2367
+
2368
+
2369
+	/**
2370
+	 * _post_payment_processing
2371
+	 *
2372
+	 * @access private
2373
+	 * @param EE_Payment|bool $payment
2374
+	 * @return bool
2375
+	 * @throws EE_Error
2376
+	 * @throws InvalidArgumentException
2377
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2378
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2379
+	 */
2380
+	private function _post_payment_processing($payment = null)
2381
+	{
2382
+		// Off-Line payment?
2383
+		if ($payment === true) {
2384
+			//$this->_setup_redirect_for_next_step();
2385
+			return true;
2386
+			// On-Site payment?
2387
+		} else if ($this->checkout->payment_method->is_on_site()) {
2388
+			if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389
+				//$this->_setup_redirect_for_next_step();
2390
+				$this->checkout->continue_reg = false;
2391
+			}
2392
+			// Off-Site payment?
2393
+		} else if ($this->checkout->payment_method->is_off_site()) {
2394
+			// if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2395
+			if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2396
+				do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2397
+				$this->checkout->redirect      = true;
2398
+				$this->checkout->redirect_form = $payment->redirect_form();
2399
+				$this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2400
+				// set JSON response
2401
+				$this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2402
+				// and lastly, let's bump the payment status to pending
2403
+				$payment->set_status(EEM_Payment::status_id_pending);
2404
+				$payment->save();
2405
+			} else {
2406
+				// not a payment
2407
+				$this->checkout->continue_reg = false;
2408
+				EE_Error::add_error(
2409
+					sprintf(
2410
+						esc_html__(
2411
+							'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2412
+							'event_espresso'
2413
+						),
2414
+						'<br/>',
2415
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
2416
+					),
2417
+					__FILE__,
2418
+					__FUNCTION__,
2419
+					__LINE__
2420
+				);
2421
+			}
2422
+		} else {
2423
+			// ummm ya... not Off-Line, not On-Site, not off-Site ????
2424
+			$this->checkout->continue_reg = false;
2425
+			return false;
2426
+		}
2427
+		return $payment;
2428
+	}
2429
+
2430
+
2431
+	/**
2432
+	 *    _process_payment_status
2433
+	 *
2434
+	 * @access private
2435
+	 * @type    EE_Payment $payment
2436
+	 * @param string       $payment_occurs
2437
+	 * @return bool
2438
+	 * @throws EE_Error
2439
+	 * @throws InvalidArgumentException
2440
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2441
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2442
+	 */
2443
+	private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2444
+	{
2445
+		// off-line payment? carry on
2446
+		if ($payment_occurs === EE_PMT_Base::offline) {
2447
+			return true;
2448
+		}
2449
+		// verify payment validity
2450
+		if ($payment instanceof EE_Payment) {
2451
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2452
+			$msg = $payment->gateway_response();
2453
+			// check results
2454
+			switch ($payment->status()) {
2455
+				// good payment
2456
+				case EEM_Payment::status_id_approved :
2457
+					EE_Error::add_success(
2458
+						esc_html__('Your payment was processed successfully.', 'event_espresso'),
2459
+						__FILE__,
2460
+						__FUNCTION__,
2461
+						__LINE__
2462
+					);
2463
+					return true;
2464
+					break;
2465
+				// slow payment
2466
+				case EEM_Payment::status_id_pending :
2467
+					if (empty($msg)) {
2468
+						$msg = esc_html__(
2469
+							'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2470
+							'event_espresso'
2471
+						);
2472
+					}
2473
+					EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2474
+					return true;
2475
+					break;
2476
+				// don't wanna payment
2477
+				case EEM_Payment::status_id_cancelled :
2478
+					if (empty($msg)) {
2479
+						$msg = _n(
2480
+							'Payment cancelled. Please try again.',
2481
+							'Payment cancelled. Please try again or select another method of payment.',
2482
+							count($this->checkout->available_payment_methods),
2483
+							'event_espresso'
2484
+						);
2485
+					}
2486
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2487
+					return false;
2488
+					break;
2489
+				// not enough payment
2490
+				case EEM_Payment::status_id_declined :
2491
+					if (empty($msg)) {
2492
+						$msg = _n(
2493
+							'We\'re sorry but your payment was declined. Please try again.',
2494
+							'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2495
+							count($this->checkout->available_payment_methods),
2496
+							'event_espresso'
2497
+						);
2498
+					}
2499
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2500
+					return false;
2501
+					break;
2502
+				// bad payment
2503
+				case EEM_Payment::status_id_failed :
2504
+					if (! empty($msg)) {
2505
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506
+						return false;
2507
+					}
2508
+					// default to error below
2509
+					break;
2510
+			}
2511
+		}
2512
+		// off-site payment gateway responses are too unreliable, so let's just assume that
2513
+		// the payment processing is just running slower than the registrant's request
2514
+		if ($payment_occurs === EE_PMT_Base::offsite) {
2515
+			return true;
2516
+		}
2517
+		EE_Error::add_error(
2518
+			sprintf(
2519
+				esc_html__(
2520
+					'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2521
+					'event_espresso'
2522
+				),
2523
+				'<br/>',
2524
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
2525
+			),
2526
+			__FILE__,
2527
+			__FUNCTION__,
2528
+			__LINE__
2529
+		);
2530
+		return false;
2531
+	}
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+	/********************************************************************************************************/
2539
+	/**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2540
+	/********************************************************************************************************/
2541
+	/**
2542
+	 * process_gateway_response
2543
+	 * this is the return point for Off-Site Payment Methods
2544
+	 * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2545
+	 * otherwise, it will load up the last payment made for the TXN.
2546
+	 * If the payment retrieved looks good, it will then either:
2547
+	 *    complete the current step and allow advancement to the next reg step
2548
+	 *        or present the payment options again
2549
+	 *
2550
+	 * @access private
2551
+	 * @return EE_Payment|FALSE
2552
+	 * @throws EE_Error
2553
+	 * @throws InvalidArgumentException
2554
+	 * @throws ReflectionException
2555
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2556
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2557
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2558
+	 */
2559
+	public function process_gateway_response()
2560
+	{
2561
+		$payment = null;
2562
+		// how have they chosen to pay?
2563
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564
+		// get EE_Payment_Method object
2565
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566
+			$this->checkout->continue_reg = false;
2567
+			return false;
2568
+		}
2569
+		if (! $this->checkout->payment_method->is_off_site()) {
2570
+			return false;
2571
+		}
2572
+		$this->_validate_offsite_return();
2573
+		// DEBUG LOG
2574
+		//$this->checkout->log(
2575
+		//	__CLASS__, __FUNCTION__, __LINE__,
2576
+		//	array(
2577
+		//		'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2578
+		//		'payment_method' => $this->checkout->payment_method,
2579
+		//	),
2580
+		//	true
2581
+		//);
2582
+		// verify TXN
2583
+		if ($this->checkout->transaction instanceof EE_Transaction) {
2584
+			$gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
+			if (! $gateway instanceof EE_Offsite_Gateway) {
2586
+				$this->checkout->continue_reg = false;
2587
+				return false;
2588
+			}
2589
+			$payment = $this->_process_off_site_payment($gateway);
2590
+			$payment = $this->_process_cancelled_payments($payment);
2591
+			$payment = $this->_validate_payment($payment);
2592
+			// if payment was not declined by the payment gateway or cancelled by the registrant
2593
+			if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2594
+				//$this->_setup_redirect_for_next_step();
2595
+				// store that for later
2596
+				$this->checkout->payment = $payment;
2597
+				// mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2598
+				// because we will complete this step during the IPN processing then
2599
+				if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2600
+					$this->set_completed();
2601
+				}
2602
+				return true;
2603
+			}
2604
+		}
2605
+		// DEBUG LOG
2606
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2607
+		//	array( 'payment' => $payment )
2608
+		//);
2609
+		$this->checkout->continue_reg = false;
2610
+		return false;
2611
+	}
2612
+
2613
+
2614
+	/**
2615
+	 * _validate_return
2616
+	 *
2617
+	 * @access private
2618
+	 * @return void
2619
+	 * @throws EE_Error
2620
+	 * @throws InvalidArgumentException
2621
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2622
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2623
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2624
+	 */
2625
+	private function _validate_offsite_return()
2626
+	{
2627
+		$TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2628
+		if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
+			// Houston... we might have a problem
2630
+			$invalid_TXN = false;
2631
+			// first gather some info
2632
+			$valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
+			$primary_registrant = $valid_TXN instanceof EE_Transaction
2634
+				? $valid_TXN->primary_registration()
2635
+				: null;
2636
+			// let's start by retrieving the cart for this TXN
2637
+			$cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
+			if ($cart instanceof EE_Cart) {
2639
+				// verify that the current cart has tickets
2640
+				$tickets = $cart->get_tickets();
2641
+				if (empty($tickets)) {
2642
+					$invalid_TXN = true;
2643
+				}
2644
+			} else {
2645
+				$invalid_TXN = true;
2646
+			}
2647
+			$valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
+				? $primary_registrant->session_ID()
2649
+				: null;
2650
+			// validate current Session ID and compare against valid TXN session ID
2651
+			if (
2652
+				$invalid_TXN // if this is already true, then skip other checks
2653
+				|| EE_Session::instance()->id() === null
2654
+				|| (
2655
+					// WARNING !!!
2656
+					// this could be PayPal sending back duplicate requests (ya they do that)
2657
+					// or it **could** mean someone is simply registering AGAIN after having just done so
2658
+					// so now we need to determine if this current TXN looks valid or not
2659
+					// and whether this reg step has even been started ?
2660
+					EE_Session::instance()->id() === $valid_TXN_SID
2661
+					// really? you're half way through this reg step, but you never started it ?
2662
+					&& $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
+				)
2664
+			) {
2665
+				$invalid_TXN = true;
2666
+			}
2667
+			if ($invalid_TXN) {
2668
+				// is the valid TXN completed ?
2669
+				if ($valid_TXN instanceof EE_Transaction) {
2670
+					// has this step even been started ?
2671
+					$reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
+					if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
+						// so it **looks** like this is a double request from PayPal
2674
+						// so let's try to pick up where we left off
2675
+						$this->checkout->transaction = $valid_TXN;
2676
+						$this->checkout->refresh_all_entities(true);
2677
+						return;
2678
+					}
2679
+				}
2680
+				// you appear to be lost?
2681
+				$this->_redirect_wayward_request($primary_registrant);
2682
+			}
2683
+		}
2684
+	}
2685
+
2686
+
2687
+	/**
2688
+	 * _redirect_wayward_request
2689
+	 *
2690
+	 * @access private
2691
+	 * @param \EE_Registration|null $primary_registrant
2692
+	 * @return bool
2693
+	 * @throws EE_Error
2694
+	 * @throws InvalidArgumentException
2695
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2696
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2697
+	 */
2698
+	private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
+	{
2700
+		if (! $primary_registrant instanceof EE_Registration) {
2701
+			// try redirecting based on the current TXN
2702
+			$primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
+				? $this->checkout->transaction->primary_registration()
2704
+				: null;
2705
+		}
2706
+		if (! $primary_registrant instanceof EE_Registration) {
2707
+			EE_Error::add_error(
2708
+				sprintf(
2709
+					esc_html__(
2710
+						'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
+						'event_espresso'
2712
+					),
2713
+					'<br/>',
2714
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
+				),
2716
+				__FILE__,
2717
+				__FUNCTION__,
2718
+				__LINE__
2719
+			);
2720
+			return false;
2721
+		}
2722
+		// make sure transaction is not locked
2723
+		$this->checkout->transaction->unlock();
2724
+		wp_safe_redirect(
2725
+			add_query_arg(
2726
+				array(
2727
+					'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
+				),
2729
+				$this->checkout->thank_you_page_url
2730
+			)
2731
+		);
2732
+		exit();
2733
+	}
2734
+
2735
+
2736
+	/**
2737
+	 * _process_off_site_payment
2738
+	 *
2739
+	 * @access private
2740
+	 * @param \EE_Offsite_Gateway $gateway
2741
+	 * @return EE_Payment
2742
+	 * @throws EE_Error
2743
+	 * @throws InvalidArgumentException
2744
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2745
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2746
+	 */
2747
+	private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
+	{
2749
+		try {
2750
+			$request_data = \EE_Registry::instance()->REQ->params();
2751
+			// if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2752
+			$this->set_handle_IPN_in_this_request(
2753
+				$gateway->handle_IPN_in_this_request($request_data, false)
2754
+			);
2755
+			if ($this->handle_IPN_in_this_request()) {
2756
+				// get payment details and process results
2757
+				/** @type EE_Payment_Processor $payment_processor */
2758
+				$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2759
+				$payment           = $payment_processor->process_ipn(
2760
+					$request_data,
2761
+					$this->checkout->transaction,
2762
+					$this->checkout->payment_method,
2763
+					true,
2764
+					false
2765
+				);
2766
+				//$payment_source = 'process_ipn';
2767
+			} else {
2768
+				$payment = $this->checkout->transaction->last_payment();
2769
+				//$payment_source = 'last_payment';
2770
+			}
2771
+		} catch (Exception $e) {
2772
+			// let's just eat the exception and try to move on using any previously set payment info
2773
+			$payment = $this->checkout->transaction->last_payment();
2774
+			//$payment_source = 'last_payment after Exception';
2775
+			// but if we STILL don't have a payment object
2776
+			if (! $payment instanceof EE_Payment) {
2777
+				// then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778
+				$this->_handle_payment_processor_exception($e);
2779
+			}
2780
+		}
2781
+		// DEBUG LOG
2782
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__,
2783
+		//	array(
2784
+		//		'process_ipn_payment' => $payment,
2785
+		//		'payment_source'      => $payment_source,
2786
+		//	)
2787
+		//);
2788
+		return $payment;
2789
+	}
2790
+
2791
+
2792
+	/**
2793
+	 * _process_cancelled_payments
2794
+	 * just makes sure that the payment status gets updated correctly
2795
+	 * so tha tan error isn't generated during payment validation
2796
+	 *
2797
+	 * @access private
2798
+	 * @param EE_Payment $payment
2799
+	 * @return EE_Payment | FALSE
2800
+	 * @throws \EE_Error
2801
+	 */
2802
+	private function _process_cancelled_payments($payment = null)
2803
+	{
2804
+		if (
2805
+			$payment instanceof EE_Payment
2806
+			&& isset($_REQUEST['ee_cancel_payment'])
2807
+			&& $payment->status() === EEM_Payment::status_id_failed
2808
+		) {
2809
+			$payment->set_status(EEM_Payment::status_id_cancelled);
2810
+		}
2811
+		return $payment;
2812
+	}
2813
+
2814
+
2815
+	/**
2816
+	 *    get_transaction_details_for_gateways
2817
+	 *
2818
+	 * @access    public
2819
+	 * @return int
2820
+	 * @throws EE_Error
2821
+	 * @throws InvalidArgumentException
2822
+	 * @throws ReflectionException
2823
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2824
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2825
+	 */
2826
+	public function get_transaction_details_for_gateways()
2827
+	{
2828
+		$txn_details = array();
2829
+		// ya gotta make a choice man
2830
+		if (empty($this->checkout->selected_method_of_payment)) {
2831
+			$txn_details = array(
2832
+				'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2833
+			);
2834
+		}
2835
+		// get EE_Payment_Method object
2836
+		if (
2837
+			empty($txn_details)
2838
+			&&
2839
+			! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2840
+		) {
2841
+			$txn_details = array(
2842
+				'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2843
+				'error'                      => esc_html__(
2844
+					'A valid Payment Method could not be determined.',
2845
+					'event_espresso'
2846
+				),
2847
+			);
2848
+		}
2849
+		if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2850
+			$return_url  = $this->_get_return_url($this->checkout->payment_method);
2851
+			$txn_details = array(
2852
+				'TXN_ID'         => $this->checkout->transaction->ID(),
2853
+				'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2854
+				'TXN_total'      => $this->checkout->transaction->total(),
2855
+				'TXN_paid'       => $this->checkout->transaction->paid(),
2856
+				'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2857
+				'STS_ID'         => $this->checkout->transaction->status_ID(),
2858
+				'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2859
+				'payment_amount' => $this->checkout->amount_owing,
2860
+				'return_url'     => $return_url,
2861
+				'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2862
+				'notify_url'     => EE_Config::instance()->core->txn_page_url(
2863
+					array(
2864
+						'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2865
+						'ee_payment_method' => $this->checkout->payment_method->slug(),
2866
+					)
2867
+				),
2868
+			);
2869
+		}
2870
+		echo wp_json_encode($txn_details);
2871
+		exit();
2872
+	}
2873
+
2874
+
2875
+	/**
2876
+	 *    __sleep
2877
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2878
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2879
+	 * reg form, because if needed, it will be regenerated anyways
2880
+	 *
2881
+	 * @return array
2882
+	 */
2883
+	public function __sleep()
2884
+	{
2885
+		// remove the reg form and the checkout
2886
+		return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2887
+	}
2888 2888
 }
Please login to merge, or discard this patch.
Spacing   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
     {
133 133
         $this->_slug     = 'payment_options';
134 134
         $this->_name     = esc_html__('Payment Options', 'event_espresso');
135
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'payment_options_main.template.php';
135
+        $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.DS.'payment_options_main.template.php';
136 136
         $this->checkout  = $checkout;
137 137
         $this->_reset_success_message();
138 138
         $this->set_instructions(
@@ -187,7 +187,7 @@  discard block
 block discarded – undo
187 187
      */
188 188
     public function translate_js_strings()
189 189
     {
190
-        EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
190
+        EE_Registry::$i18n_js_strings['no_payment_method'] = esc_html__(
191 191
             'Please select a method of payment in order to continue.',
192 192
             'event_espresso'
193 193
         );
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
             'A valid method of payment could not be determined. Please refresh the page and try again.',
196 196
             'event_espresso'
197 197
         );
198
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
198
+        EE_Registry::$i18n_js_strings['forwarding_to_offsite'] = esc_html__(
199 199
             'Forwarding to Secure Payment Provider.',
200 200
             'event_espresso'
201 201
         );
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
     {
216 216
         $transaction = $this->checkout->transaction;
217 217
         //if the transaction isn't set or nothing is owed on it, don't enqueue any JS
218
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
218
+        if ( ! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
219 219
             return;
220 220
         }
221 221
         foreach (EEM_Payment_Method::instance()->get_all_for_transaction($transaction, EEM_Payment_Method::scope_cart) as $payment_method) {
@@ -304,11 +304,11 @@  discard block
 block discarded – undo
304 304
         foreach ($registrations as $REG_ID => $registration) {
305 305
             /** @var $registration EE_Registration */
306 306
             // has this registration lost it's space ?
307
-            if (isset($ejected_registrations[ $REG_ID ])) {
307
+            if (isset($ejected_registrations[$REG_ID])) {
308 308
                 if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
309
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
309
+                    $sold_out_events[$registration->event()->ID()] = $registration->event();
310 310
                 } else {
311
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
311
+                    $insufficient_spaces_available[$registration->event()->ID()] = $registration->event();
312 312
                 }
313 313
                 continue;
314 314
             }
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
                     $registration->event(),
348 348
                     $this
349 349
                 );
350
-            } elseif (! $this->checkout->revisit
350
+            } elseif ( ! $this->checkout->revisit
351 351
                 && $registration->status_ID() !== EEM_Registration::status_id_not_approved
352 352
                 && $registration->ticket()->is_free()
353 353
             ) {
@@ -356,23 +356,23 @@  discard block
 block discarded – undo
356 356
         }
357 357
         $subsections = array();
358 358
         // now decide which template to load
359
-        if (! empty($sold_out_events)) {
359
+        if ( ! empty($sold_out_events)) {
360 360
             $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
361 361
         }
362
-        if (! empty($insufficient_spaces_available)) {
362
+        if ( ! empty($insufficient_spaces_available)) {
363 363
             $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
364 364
                 $insufficient_spaces_available
365 365
             );
366 366
         }
367
-        if (! empty($registrations_requiring_pre_approval)) {
367
+        if ( ! empty($registrations_requiring_pre_approval)) {
368 368
             $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
369 369
                 $registrations_requiring_pre_approval
370 370
             );
371 371
         }
372
-        if (! empty($registrations_for_free_events)) {
372
+        if ( ! empty($registrations_for_free_events)) {
373 373
             $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
374 374
         }
375
-        if (! empty($registrations_requiring_payment)) {
375
+        if ( ! empty($registrations_requiring_payment)) {
376 376
             if ($this->checkout->amount_owing > 0) {
377 377
                 // autoload Line_Item_Display classes
378 378
                 EEH_Autoloader::register_line_item_filter_autoloaders();
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
                         array('registrations' => $registrations)
394 394
                     )
395 395
                 );
396
-                $this->checkout->amount_owing   = $filtered_line_item_tree->total();
396
+                $this->checkout->amount_owing = $filtered_line_item_tree->total();
397 397
                 $this->_apply_registration_payments_to_amount_owing($registrations);
398 398
             }
399 399
             $no_payment_required = false;
@@ -437,13 +437,13 @@  discard block
 block discarded – undo
437 437
      */
438 438
     public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
439 439
     {
440
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
440
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
441 441
             return $line_item_filter_collection;
442 442
         }
443
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
443
+        if ( ! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
444 444
             return $line_item_filter_collection;
445 445
         }
446
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
446
+        if ( ! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
447 447
             return $line_item_filter_collection;
448 448
         }
449 449
         $line_item_filter_collection->add(
@@ -534,15 +534,15 @@  discard block
 block discarded – undo
534 534
             }
535 535
             $EVT_ID = $registration->event_ID();
536 536
             $ticket = $registration->ticket();
537
-            if (! isset($tickets_remaining[$ticket->ID()])) {
537
+            if ( ! isset($tickets_remaining[$ticket->ID()])) {
538 538
                 $tickets_remaining[$ticket->ID()] = $ticket->remaining();
539 539
             }
540 540
             if ($tickets_remaining[$ticket->ID()] > 0) {
541
-                if (! isset($event_reg_count[$EVT_ID])) {
541
+                if ( ! isset($event_reg_count[$EVT_ID])) {
542 542
                     $event_reg_count[$EVT_ID] = 0;
543 543
                 }
544 544
                 $event_reg_count[$EVT_ID]++;
545
-                if (! isset($event_spaces_remaining[$EVT_ID])) {
545
+                if ( ! isset($event_spaces_remaining[$EVT_ID])) {
546 546
                     $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
547 547
                 }
548 548
             }
@@ -611,7 +611,7 @@  discard block
 block discarded – undo
611 611
         foreach ($sold_out_events_array as $sold_out_event) {
612 612
             $sold_out_events .= EEH_HTML::li(
613 613
                 EEH_HTML::span(
614
-                    '  ' . $sold_out_event->name(),
614
+                    '  '.$sold_out_event->name(),
615 615
                     '',
616 616
                     'dashicons dashicons-marker ee-icon-size-16 pink-text'
617 617
                 )
@@ -667,7 +667,7 @@  discard block
 block discarded – undo
667 667
         foreach ($insufficient_spaces_events_array as $event) {
668 668
             if ($event instanceof EE_Event) {
669 669
                 $insufficient_space_events .= EEH_HTML::li(
670
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
670
+                    EEH_HTML::span(' '.$event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
671 671
                 );
672 672
             }
673 673
         }
@@ -857,7 +857,7 @@  discard block
 block discarded – undo
857 857
     {
858 858
         return new EE_Form_Section_Proper(
859 859
             array(
860
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
860
+                'html_id'         => 'ee-'.$this->slug().'-extra-hidden-inputs',
861 861
                 'layout_strategy' => new EE_Div_Per_Section_Layout(),
862 862
                 'subsections'     => array(
863 863
                     'spco_no_payment_required' => new EE_Hidden_Input(
@@ -897,7 +897,7 @@  discard block
 block discarded – undo
897 897
                 $payments += $registration->registration_payments();
898 898
             }
899 899
         }
900
-        if (! empty($payments)) {
900
+        if ( ! empty($payments)) {
901 901
             foreach ($payments as $payment) {
902 902
                 if ($payment instanceof EE_Registration_Payment) {
903 903
                     $this->checkout->amount_owing -= $payment->amount();
@@ -987,7 +987,7 @@  discard block
 block discarded – undo
987 987
             );
988 988
         }
989 989
         // switch up header depending on number of available payment methods
990
-        $payment_method_header     = count($this->checkout->available_payment_methods) > 1
990
+        $payment_method_header = count($this->checkout->available_payment_methods) > 1
991 991
             ? apply_filters(
992 992
                 'FHEE__registration_page_payment_options__method_of_payment_hdr',
993 993
                 esc_html__('Please Select Your Method of Payment', 'event_espresso')
@@ -1017,14 +1017,14 @@  discard block
 block discarded – undo
1017 1017
                 $payment_method_button = EEH_HTML::img(
1018 1018
                     $payment_method->button_url(),
1019 1019
                     $payment_method->name(),
1020
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1020
+                    'spco-payment-method-'.$payment_method->slug().'-btn-img',
1021 1021
                     'spco-payment-method-btn-img'
1022 1022
                 );
1023 1023
                 // check if any payment methods are set as default
1024 1024
                 // if payment method is already selected OR nothing is selected and this payment method should be
1025 1025
                 // open_by_default
1026 1026
                 if (($this->checkout->selected_method_of_payment === $payment_method->slug())
1027
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1027
+                    || ( ! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1028 1028
                 ) {
1029 1029
                     $this->checkout->selected_method_of_payment = $payment_method->slug();
1030 1030
                     $this->_save_selected_method_of_payment();
@@ -1032,7 +1032,7 @@  discard block
 block discarded – undo
1032 1032
                 } else {
1033 1033
                     $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1034 1034
                 }
1035
-                $payment_methods_billing_info[$payment_method->slug() . '-info'] = $this->_payment_method_billing_info(
1035
+                $payment_methods_billing_info[$payment_method->slug().'-info'] = $this->_payment_method_billing_info(
1036 1036
                     $payment_method
1037 1037
                 );
1038 1038
             }
@@ -1044,7 +1044,7 @@  discard block
 block discarded – undo
1044 1044
         $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1045 1045
             $available_payment_method_options
1046 1046
         );
1047
-        $available_payment_methods                              += $payment_methods_billing_info;
1047
+        $available_payment_methods += $payment_methods_billing_info;
1048 1048
         // build the available payment methods form
1049 1049
         return new EE_Form_Section_Proper(
1050 1050
             array(
@@ -1068,7 +1068,7 @@  discard block
 block discarded – undo
1068 1068
      */
1069 1069
     protected function _get_available_payment_methods()
1070 1070
     {
1071
-        if (! empty($this->checkout->available_payment_methods)) {
1071
+        if ( ! empty($this->checkout->available_payment_methods)) {
1072 1072
             return $this->checkout->available_payment_methods;
1073 1073
         }
1074 1074
         $available_payment_methods = array();
@@ -1178,7 +1178,7 @@  discard block
 block discarded – undo
1178 1178
         );
1179 1179
         return new EE_Form_Section_Proper(
1180 1180
             array(
1181
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1181
+                'html_id'         => 'spco-payment-method-info-'.$payment_method->slug(),
1182 1182
                 'html_class'      => 'spco-payment-method-info-dv',
1183 1183
                 // only display the selected or default PM
1184 1184
                 'html_style'      => $currently_selected ? '' : 'display:none;',
@@ -1208,7 +1208,7 @@  discard block
 block discarded – undo
1208 1208
         // how have they chosen to pay?
1209 1209
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1210 1210
         $this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1211
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1211
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1212 1212
             return false;
1213 1213
         }
1214 1214
         if (apply_filters(
@@ -1380,7 +1380,7 @@  discard block
 block discarded – undo
1380 1380
      */
1381 1381
     public function switch_payment_method()
1382 1382
     {
1383
-        if (! $this->_verify_payment_method_is_set()) {
1383
+        if ( ! $this->_verify_payment_method_is_set()) {
1384 1384
             return false;
1385 1385
         }
1386 1386
         if (apply_filters(
@@ -1509,7 +1509,7 @@  discard block
 block discarded – undo
1509 1509
             }
1510 1510
         }
1511 1511
         // verify payment method
1512
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1512
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1513 1513
             // get payment method for selected method of payment
1514 1514
             $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1515 1515
         }
@@ -1534,7 +1534,7 @@  discard block
 block discarded – undo
1534 1534
      */
1535 1535
     public function save_payer_details_via_ajax()
1536 1536
     {
1537
-        if (! $this->_verify_payment_method_is_set()) {
1537
+        if ( ! $this->_verify_payment_method_is_set()) {
1538 1538
             return;
1539 1539
         }
1540 1540
         // generate billing form for selected method of payment if it hasn't been done already
@@ -1544,7 +1544,7 @@  discard block
 block discarded – undo
1544 1544
             );
1545 1545
         }
1546 1546
         // generate primary attendee from payer info if applicable
1547
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1547
+        if ( ! $this->checkout->transaction_has_primary_registrant()) {
1548 1548
             $attendee = $this->_create_attendee_from_request_data();
1549 1549
             if ($attendee instanceof EE_Attendee) {
1550 1550
                 foreach ($this->checkout->transaction->registrations() as $registration) {
@@ -1575,7 +1575,7 @@  discard block
 block discarded – undo
1575 1575
     {
1576 1576
         // get State ID
1577 1577
         $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1578
-        if (! empty($STA_ID)) {
1578
+        if ( ! empty($STA_ID)) {
1579 1579
             // can we get state object from name ?
1580 1580
             EE_Registry::instance()->load_model('State');
1581 1581
             $state  = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
@@ -1583,7 +1583,7 @@  discard block
 block discarded – undo
1583 1583
         }
1584 1584
         // get Country ISO
1585 1585
         $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1586
-        if (! empty($CNT_ISO)) {
1586
+        if ( ! empty($CNT_ISO)) {
1587 1587
             // can we get country object from name ?
1588 1588
             EE_Registry::instance()->load_model('Country');
1589 1589
             $country = EEM_Country::instance()->get_col(
@@ -1616,7 +1616,7 @@  discard block
 block discarded – undo
1616 1616
         }
1617 1617
         // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1618 1618
         // AND email address
1619
-        if (! empty($attendee_data['ATT_fname'])
1619
+        if ( ! empty($attendee_data['ATT_fname'])
1620 1620
             && ! empty($attendee_data['ATT_lname'])
1621 1621
             && ! empty($attendee_data['ATT_email'])
1622 1622
         ) {
@@ -1832,7 +1832,7 @@  discard block
 block discarded – undo
1832 1832
     private function _process_payment()
1833 1833
     {
1834 1834
         // basically confirm that the event hasn't sold out since they hit the page
1835
-        if (! $this->_last_second_ticket_verifications()) {
1835
+        if ( ! $this->_last_second_ticket_verifications()) {
1836 1836
             return false;
1837 1837
         }
1838 1838
         // ya gotta make a choice man
@@ -1843,7 +1843,7 @@  discard block
 block discarded – undo
1843 1843
             return false;
1844 1844
         }
1845 1845
         // get EE_Payment_Method object
1846
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1846
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1847 1847
             return false;
1848 1848
         }
1849 1849
         // setup billing form
@@ -1852,12 +1852,12 @@  discard block
 block discarded – undo
1852 1852
                 $this->checkout->payment_method
1853 1853
             );
1854 1854
             // bad billing form ?
1855
-            if (! $this->_billing_form_is_valid()) {
1855
+            if ( ! $this->_billing_form_is_valid()) {
1856 1856
                 return false;
1857 1857
             }
1858 1858
         }
1859 1859
         // ensure primary registrant has been fully processed
1860
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1860
+        if ( ! $this->_setup_primary_registrant_prior_to_payment()) {
1861 1861
             return false;
1862 1862
         }
1863 1863
         // if session is close to expiring (under 10 minutes by default)
@@ -1913,7 +1913,7 @@  discard block
 block discarded – undo
1913 1913
     protected function _last_second_ticket_verifications()
1914 1914
     {
1915 1915
         // don't bother re-validating if not a return visit
1916
-        if (! $this->checkout->revisit) {
1916
+        if ( ! $this->checkout->revisit) {
1917 1917
             return true;
1918 1918
         }
1919 1919
         $registrations = $this->checkout->transaction->registrations();
@@ -1964,7 +1964,7 @@  discard block
 block discarded – undo
1964 1964
             $this->_get_payment_method_for_selected_method_of_payment()
1965 1965
         );
1966 1966
         $html                        = $payment_method_billing_info->get_html();
1967
-        $html                        .= $this->checkout->redirect_form;
1967
+        $html .= $this->checkout->redirect_form;
1968 1968
         EE_Registry::instance()->REQ->add_output($html);
1969 1969
         return true;
1970 1970
     }
@@ -1979,7 +1979,7 @@  discard block
 block discarded – undo
1979 1979
      */
1980 1980
     private function _billing_form_is_valid()
1981 1981
     {
1982
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1982
+        if ( ! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1983 1983
             return true;
1984 1984
         }
1985 1985
         if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
@@ -2096,7 +2096,7 @@  discard block
 block discarded – undo
2096 2096
     {
2097 2097
         // convert billing form data into an attendee
2098 2098
         $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2099
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2099
+        if ( ! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2100 2100
             EE_Error::add_error(
2101 2101
                 sprintf(
2102 2102
                     esc_html__(
@@ -2113,7 +2113,7 @@  discard block
 block discarded – undo
2113 2113
             return false;
2114 2114
         }
2115 2115
         $primary_registration = $this->checkout->transaction->primary_registration();
2116
-        if (! $primary_registration instanceof EE_Registration) {
2116
+        if ( ! $primary_registration instanceof EE_Registration) {
2117 2117
             EE_Error::add_error(
2118 2118
                 sprintf(
2119 2119
                     esc_html__(
@@ -2129,7 +2129,7 @@  discard block
 block discarded – undo
2129 2129
             );
2130 2130
             return false;
2131 2131
         }
2132
-        if (! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2132
+        if ( ! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2133 2133
               instanceof
2134 2134
               EE_Attendee
2135 2135
         ) {
@@ -2185,7 +2185,7 @@  discard block
 block discarded – undo
2185 2185
             $payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2186 2186
         }
2187 2187
         // verify $payment_method
2188
-        if (! $payment_method instanceof EE_Payment_Method) {
2188
+        if ( ! $payment_method instanceof EE_Payment_Method) {
2189 2189
             // not a payment
2190 2190
             EE_Error::add_error(
2191 2191
                 sprintf(
@@ -2203,7 +2203,7 @@  discard block
 block discarded – undo
2203 2203
             return null;
2204 2204
         }
2205 2205
         // and verify it has a valid Payment_Method Type object
2206
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2206
+        if ( ! $payment_method->type_obj() instanceof EE_PMT_Base) {
2207 2207
             // not a payment
2208 2208
             EE_Error::add_error(
2209 2209
                 sprintf(
@@ -2241,7 +2241,7 @@  discard block
 block discarded – undo
2241 2241
         $payment = null;
2242 2242
         $this->checkout->transaction->save();
2243 2243
         $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2244
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2244
+        if ( ! $payment_processor instanceof EE_Payment_Processor) {
2245 2245
             return false;
2246 2246
         }
2247 2247
         try {
@@ -2345,7 +2345,7 @@  discard block
 block discarded – undo
2345 2345
             return true;
2346 2346
         }
2347 2347
         // verify payment object
2348
-        if (! $payment instanceof EE_Payment) {
2348
+        if ( ! $payment instanceof EE_Payment) {
2349 2349
             // not a payment
2350 2350
             EE_Error::add_error(
2351 2351
                 sprintf(
@@ -2385,7 +2385,7 @@  discard block
 block discarded – undo
2385 2385
             return true;
2386 2386
             // On-Site payment?
2387 2387
         } else if ($this->checkout->payment_method->is_on_site()) {
2388
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2388
+            if ( ! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2389 2389
                 //$this->_setup_redirect_for_next_step();
2390 2390
                 $this->checkout->continue_reg = false;
2391 2391
             }
@@ -2501,7 +2501,7 @@  discard block
 block discarded – undo
2501 2501
                     break;
2502 2502
                 // bad payment
2503 2503
                 case EEM_Payment::status_id_failed :
2504
-                    if (! empty($msg)) {
2504
+                    if ( ! empty($msg)) {
2505 2505
                         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2506 2506
                         return false;
2507 2507
                     }
@@ -2562,11 +2562,11 @@  discard block
 block discarded – undo
2562 2562
         // how have they chosen to pay?
2563 2563
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2564 2564
         // get EE_Payment_Method object
2565
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2565
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2566 2566
             $this->checkout->continue_reg = false;
2567 2567
             return false;
2568 2568
         }
2569
-        if (! $this->checkout->payment_method->is_off_site()) {
2569
+        if ( ! $this->checkout->payment_method->is_off_site()) {
2570 2570
             return false;
2571 2571
         }
2572 2572
         $this->_validate_offsite_return();
@@ -2582,7 +2582,7 @@  discard block
 block discarded – undo
2582 2582
         // verify TXN
2583 2583
         if ($this->checkout->transaction instanceof EE_Transaction) {
2584 2584
             $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2585
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2585
+            if ( ! $gateway instanceof EE_Offsite_Gateway) {
2586 2586
                 $this->checkout->continue_reg = false;
2587 2587
                 return false;
2588 2588
             }
@@ -2624,7 +2624,7 @@  discard block
 block discarded – undo
2624 2624
      */
2625 2625
     private function _validate_offsite_return()
2626 2626
     {
2627
-        $TXN_ID = (int)EE_Registry::instance()->REQ->get('spco_txn', 0);
2627
+        $TXN_ID = (int) EE_Registry::instance()->REQ->get('spco_txn', 0);
2628 2628
         if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629 2629
             // Houston... we might have a problem
2630 2630
             $invalid_TXN = false;
@@ -2697,13 +2697,13 @@  discard block
 block discarded – undo
2697 2697
      */
2698 2698
     private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699 2699
     {
2700
-        if (! $primary_registrant instanceof EE_Registration) {
2700
+        if ( ! $primary_registrant instanceof EE_Registration) {
2701 2701
             // try redirecting based on the current TXN
2702 2702
             $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703 2703
                 ? $this->checkout->transaction->primary_registration()
2704 2704
                 : null;
2705 2705
         }
2706
-        if (! $primary_registrant instanceof EE_Registration) {
2706
+        if ( ! $primary_registrant instanceof EE_Registration) {
2707 2707
             EE_Error::add_error(
2708 2708
                 sprintf(
2709 2709
                     esc_html__(
@@ -2773,7 +2773,7 @@  discard block
 block discarded – undo
2773 2773
             $payment = $this->checkout->transaction->last_payment();
2774 2774
             //$payment_source = 'last_payment after Exception';
2775 2775
             // but if we STILL don't have a payment object
2776
-            if (! $payment instanceof EE_Payment) {
2776
+            if ( ! $payment instanceof EE_Payment) {
2777 2777
                 // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778 2778
                 $this->_handle_payment_processor_exception($e);
2779 2779
             }
Please login to merge, or discard this patch.
core/helpers/EEH_Event_Query.helper.php 2 patches
Indentation   +670 added lines, -670 removed lines patch added patch discarded remove patch
@@ -18,676 +18,676 @@
 block discarded – undo
18 18
 class EEH_Event_Query
19 19
 {
20 20
 
21
-    /**
22
-     * Start Date
23
-     *
24
-     * @var $_event_query_month
25
-     */
26
-    protected static $_event_query_month;
27
-
28
-    /**
29
-     * Category
30
-     *
31
-     * @var $_event_query_category
32
-     */
33
-    protected static $_event_query_category;
34
-
35
-    /**
36
-     * whether to display expired events in the event list
37
-     *
38
-     * @var bool $_show_expired
39
-     */
40
-    protected static $_event_query_show_expired = false;
41
-
42
-    /**
43
-     * list of params for controlling how the query results are ordered
44
-     *
45
-     * @var array $_event_query_orderby
46
-     */
47
-    protected static $_event_query_orderby = array();
48
-
49
-    /**
50
-     * direction list is sorted
51
-     *
52
-     * @var string $_event_query_sort
53
-     */
54
-    protected static $_event_query_sort;
55
-
56
-    /**
57
-     * list of params used to build the query's various clauses
58
-     *
59
-     * @var $_query_params
60
-     */
61
-    protected static $_query_params = array();
62
-
63
-
64
-
65
-    /**
66
-     * @return void
67
-     */
68
-    public static function add_query_filters()
69
-    {
70
-        //add query filters
71
-        add_action('pre_get_posts', array('EEH_Event_Query', 'filter_query_parts'), 10, 1);
72
-    }
73
-
74
-
75
-
76
-    /**
77
-     * @param WP_Query $WP_Query
78
-     * @return bool
79
-     */
80
-    public static function apply_query_filters(WP_Query $WP_Query)
81
-    {
82
-        return (
83
-                   isset($WP_Query->query['post_type'])
84
-                   && $WP_Query->query['post_type'] === 'espresso_events'
85
-               )
86
-               || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false);
87
-    }
88
-
89
-
90
-    /**
91
-     * @param WP_Query $WP_Query
92
-     */
93
-    public static function filter_query_parts(WP_Query $WP_Query)
94
-    {
95
-        // ONLY add our filters if this isn't the main wp_query,
96
-        // because if this is the main wp_query we already have
97
-        // our cpt strategies take care of adding things in.
98
-        if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) {
99
-            // build event list query
100
-            add_filter('posts_fields', array('EEH_Event_Query', 'posts_fields'), 10, 2);
101
-            add_filter('posts_join', array('EEH_Event_Query', 'posts_join'), 10, 2);
102
-            add_filter('posts_where', array('EEH_Event_Query', 'posts_where'), 10, 2);
103
-            add_filter('posts_orderby', array('EEH_Event_Query', 'posts_orderby'), 10, 2);
104
-            add_filter('posts_clauses_request', array('EEH_Event_Query', 'posts_clauses'), 10, 2);
105
-        }
106
-    }
107
-
108
-
109
-
110
-    /**
111
-     * @param string $month
112
-     * @param string $category
113
-     * @param bool   $show_expired
114
-     * @param string $orderby
115
-     * @param string $sort
116
-     * @throws InvalidArgumentException
117
-     * @throws InvalidDataTypeException
118
-     * @throws InvalidInterfaceException
119
-     */
120
-    public static function set_query_params(
121
-        $month = '',
122
-        $category = '',
123
-        $show_expired = false,
124
-        $orderby = 'start_date',
125
-        $sort = 'ASC'
126
-    ) {
127
-        self::$_query_params                        = array();
128
-        EEH_Event_Query::$_event_query_month        = EEH_Event_Query::_display_month($month);
129
-        EEH_Event_Query::$_event_query_category     = EEH_Event_Query::_event_category_slug($category);
130
-        EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired);
131
-        EEH_Event_Query::$_event_query_orderby      = EEH_Event_Query::_orderby($orderby);
132
-        EEH_Event_Query::$_event_query_sort         = EEH_Event_Query::_sort($sort);
133
-    }
134
-
135
-
136
-
137
-    /**
138
-     * what month should the event list display events for?
139
-     *
140
-     * @param string $month
141
-     * @return string
142
-     * @throws InvalidArgumentException
143
-     * @throws InvalidDataTypeException
144
-     * @throws InvalidInterfaceException
145
-     */
146
-    private static function _display_month($month = '')
147
-    {
148
-        return sanitize_text_field(EE_Registry::instance()->REQ->get('event_query_month', $month));
149
-    }
150
-
151
-
152
-
153
-    /**
154
-     * @param string $category
155
-     * @return string
156
-     * @throws InvalidArgumentException
157
-     * @throws InvalidDataTypeException
158
-     * @throws InvalidInterfaceException
159
-     */
160
-    private static function _event_category_slug($category = '')
161
-    {
162
-        return sanitize_title_with_dashes(EE_Registry::instance()->REQ->get('event_query_category', $category));
163
-    }
164
-
165
-
166
-
167
-    /**
168
-     * @param bool $show_expired
169
-     * @return bool
170
-     * @throws InvalidArgumentException
171
-     * @throws InvalidDataTypeException
172
-     * @throws InvalidInterfaceException
173
-     */
174
-    private static function _show_expired($show_expired = false)
175
-    {
176
-        // override default expired option if set via filter
177
-        return filter_var(
178
-            EE_Registry::instance()->REQ->get('event_query_show_expired', $show_expired),
179
-            FILTER_VALIDATE_BOOLEAN
180
-        );
181
-    }
182
-
183
-
184
-
185
-    /**
186
-     * @param    string $orderby
187
-     * @return array
188
-     * @throws InvalidArgumentException
189
-     * @throws InvalidDataTypeException
190
-     * @throws InvalidInterfaceException
191
-     */
192
-    private static function _orderby($orderby = 'start_date')
193
-    {
194
-        $event_query_orderby = EE_Registry::instance()->REQ->get('event_query_orderby', $orderby);
195
-        $event_query_orderby = is_array($event_query_orderby)
196
-            ? $event_query_orderby
197
-            : explode(',', $event_query_orderby);
198
-        $event_query_orderby = array_map('trim', $event_query_orderby);
199
-        $event_query_orderby = array_map('sanitize_text_field', $event_query_orderby);
200
-        return $event_query_orderby;
201
-    }
202
-
203
-
204
-
205
-    /**
206
-     * @param string $sort
207
-     * @return string
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     */
212
-    private static function _sort($sort = 'ASC')
213
-    {
214
-        $sort = EE_Registry::instance()->REQ->get('event_query_sort', $sort);
215
-        return in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
216
-            ? strtoupper($sort)
217
-            : 'ASC';
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * Filters the clauses for the WP_Query object
224
-     *
225
-     * @param array    $clauses array of clauses
226
-     * @param WP_Query $wp_query
227
-     * @return array   array of clauses
228
-     */
229
-    public static function posts_clauses($clauses, WP_Query $wp_query)
230
-    {
231
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
232
-            global $wpdb;
233
-            $clauses['groupby'] = $wpdb->posts . '.ID ';
234
-        }
235
-        return $clauses;
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     * @param string   $SQL
242
-     * @param WP_Query $wp_query
243
-     * @return string
244
-     * @throws EE_Error
245
-     * @throws InvalidArgumentException
246
-     * @throws InvalidDataTypeException
247
-     * @throws InvalidInterfaceException
248
-     */
249
-    public static function posts_fields($SQL, WP_Query $wp_query)
250
-    {
251
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
252
-            // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
253
-            $SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby);
254
-        }
255
-        return $SQL;
256
-    }
257
-
258
-
259
-
260
-    /**
261
-     * @param array $orderby_params
262
-     * @return string
263
-     * @throws EE_Error
264
-     * @throws InvalidArgumentException
265
-     * @throws InvalidDataTypeException
266
-     * @throws InvalidInterfaceException
267
-     */
268
-    public static function posts_fields_sql_for_orderby(array $orderby_params = array())
269
-    {
270
-        $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
271
-        foreach ($orderby_params as $orderby) {
272
-            switch ($orderby) {
273
-
274
-                case 'ticket_start' :
275
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
276
-                    break;
277
-                case 'ticket_end' :
278
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
279
-                    break;
280
-                case 'venue_title' :
281
-                    $SQL .= ', Venue.post_title AS venue_title';
282
-                    break;
283
-                case 'city' :
284
-                    $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
285
-                    break;
286
-                case 'state' :
287
-                    $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
288
-                    break;
289
-            }
290
-        }
291
-        return $SQL;
292
-    }
293
-
294
-
295
-
296
-    /**
297
-     * @param string   $SQL
298
-     * @param WP_Query $wp_query
299
-     * @return string
300
-     * @throws EE_Error
301
-     * @throws InvalidArgumentException
302
-     * @throws InvalidDataTypeException
303
-     * @throws InvalidInterfaceException
304
-     */
305
-    public static function posts_join($SQL = '', WP_Query $wp_query)
306
-    {
307
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
308
-            // Category
309
-            $SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired);
310
-            $SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category);
311
-            $SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby);
312
-        }
313
-        return $SQL;
314
-    }
315
-
316
-
317
-
318
-    /**
319
-     * @param string  $SQL
320
-     * @param boolean $show_expired if TRUE, then displayed past events
321
-     * @return string
322
-     * @throws EE_Error
323
-     * @throws InvalidArgumentException
324
-     * @throws InvalidDataTypeException
325
-     * @throws InvalidInterfaceException
326
-     */
327
-    public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
328
-    {
329
-        if (! $show_expired) {
330
-            $join = EEM_Event::instance()->table() . '.ID = ';
331
-            $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
332
-            // don't add if this is already in the SQL
333
-            if (strpos($SQL, $join) === false) {
334
-                $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
335
-            }
336
-        }
337
-        return $SQL;
338
-    }
339
-
340
-
341
-
342
-    /**
343
-     * @param string $SQL
344
-     * @param string $join_terms    pass TRUE or term string, doesn't really matter since this value doesn't really get
345
-     *                              used for anything yet
346
-     * @return string
347
-     */
348
-    public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
349
-    {
350
-        if (! empty($join_terms)) {
351
-            global $wpdb;
352
-            $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
353
-            $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
354
-            $SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) ";
355
-        }
356
-        return $SQL;
357
-    }
358
-
359
-
360
-
361
-    /**
362
-     * usage:  $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params );
363
-     *
364
-     * @param    string $SQL
365
-     * @param    array  $orderby_params
366
-     * @return string
367
-     * @throws EE_Error
368
-     * @throws InvalidArgumentException
369
-     * @throws InvalidDataTypeException
370
-     * @throws InvalidInterfaceException
371
-     */
372
-    public static function posts_join_for_orderby($SQL = '', array $orderby_params = array())
373
-    {
374
-        foreach ($orderby_params as $orderby) {
375
-            switch ($orderby) {
376
-                case 'ticket_start' :
377
-                case 'ticket_end' :
378
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime(
379
-                        $SQL,
380
-                        EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
381
-                    );
382
-                    $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
383
-                    $SQL .= ' ON (';
384
-                    $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
385
-                    $SQL .= ' = ';
386
-                    $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
387
-                    $SQL .= ' )';
388
-                    break;
389
-                case 'venue_title' :
390
-                case 'city' :
391
-                    $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
392
-                    break;
393
-                case 'state' :
394
-                    $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
395
-                    $SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL);
396
-                    break;
397
-                case 'start_date' :
398
-                default :
399
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
400
-                    break;
401
-            }
402
-        }
403
-        return $SQL;
404
-    }
405
-
406
-
407
-
408
-    /**
409
-     * @param string $SQL
410
-     * @param string $join
411
-     * @return string
412
-     * @throws EE_Error
413
-     * @throws InvalidArgumentException
414
-     * @throws InvalidDataTypeException
415
-     * @throws InvalidInterfaceException
416
-     */
417
-    protected static function _posts_join_for_datetime($SQL = '', $join = '')
418
-    {
419
-        if (! empty($join)) {
420
-            $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
421
-            if (strpos($SQL, $join) === false) {
422
-                return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
423
-            }
424
-        }
425
-        return '';
426
-    }
427
-
428
-
429
-
430
-    /**
431
-     * @param string $SQL
432
-     * @return string
433
-     * @throws EE_Error
434
-     * @throws InvalidArgumentException
435
-     * @throws InvalidDataTypeException
436
-     * @throws InvalidInterfaceException
437
-     */
438
-    protected static function _posts_join_for_event_venue($SQL = '')
439
-    {
440
-        // Event Venue table name
441
-        $event_venue_table = EEM_Event_Venue::instance()->table();
442
-        // generate conditions for:  Event <=> Event Venue  JOIN clause
443
-        $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = ';
444
-        $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name();
445
-        // don't add joins if they have already been added
446
-        if (strpos($SQL, $event_to_event_venue_join) === false) {
447
-            // Venue table name
448
-            $venue_table = EEM_Venue::instance()->table();
449
-            // Venue table pk
450
-            $venue_table_pk = EEM_Venue::instance()->primary_key_name();
451
-            // Venue Meta table name
452
-            $venue_meta_table = EEM_Venue::instance()->second_table();
453
-            // generate JOIN clause for: Event <=> Event Venue
454
-            $venue_SQL = " LEFT JOIN $event_venue_table ON ( $event_to_event_venue_join )";
455
-            // generate JOIN clause for: Event Venue <=> Venue
456
-            $venue_SQL .= " LEFT JOIN $venue_table as Venue ON ( $event_venue_table.$venue_table_pk = Venue.ID )";
457
-            // generate JOIN clause for: Venue <=> Venue Meta
458
-            $venue_SQL .= " LEFT JOIN $venue_meta_table ON ( Venue.ID = $venue_meta_table.$venue_table_pk )";
459
-            unset($event_venue_table, $event_to_event_venue_join, $venue_table, $venue_table_pk, $venue_meta_table);
460
-            return $venue_SQL;
461
-        }
462
-        unset($event_venue_table, $event_to_event_venue_join);
463
-        return '';
464
-    }
465
-
466
-
467
-
468
-    /**
469
-     * @param string $SQL
470
-     * @return string
471
-     * @throws EE_Error
472
-     * @throws InvalidArgumentException
473
-     * @throws InvalidDataTypeException
474
-     * @throws InvalidInterfaceException
475
-     */
476
-    protected static function _posts_join_for_venue_state($SQL = '')
477
-    {
478
-        // Venue Meta table name
479
-        $venue_meta_table = EEM_Venue::instance()->second_table();
480
-        // State table name
481
-        $state_table = EEM_State::instance()->table();
482
-        // State table pk
483
-        $state_table_pk = EEM_State::instance()->primary_key_name();
484
-        // verify vars
485
-        if ($venue_meta_table && $state_table && $state_table_pk) {
486
-            // like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID
487
-            $join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk";
488
-            // don't add join if it has already been added
489
-            if (strpos($SQL, $join) === false) {
490
-                unset($state_table_pk, $venue_meta_table, $venue_table_pk);
491
-                return " LEFT JOIN $state_table ON ( $join )";
492
-            }
493
-        }
494
-        unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk);
495
-        return '';
496
-    }
497
-
498
-
499
-
500
-    /**
501
-     * @param string   $SQL
502
-     * @param WP_Query $wp_query
503
-     * @return string
504
-     * @throws EE_Error
505
-     * @throws InvalidArgumentException
506
-     * @throws InvalidDataTypeException
507
-     * @throws InvalidInterfaceException
508
-     */
509
-    public static function posts_where($SQL = '', WP_Query $wp_query)
510
-    {
511
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
512
-            // Show Expired ?
513
-            $SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired);
514
-            // Category
515
-            $SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category);
516
-            // Start Date
517
-            $SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month);
518
-        }
519
-        return $SQL;
520
-    }
521
-
522
-
523
-
524
-    /**
525
-     * @param    boolean $show_expired if TRUE, then displayed past events
526
-     * @return string
527
-     * @throws EE_Error
528
-     * @throws InvalidArgumentException
529
-     * @throws InvalidDataTypeException
530
-     * @throws InvalidInterfaceException
531
-     */
532
-    public static function posts_where_sql_for_show_expired($show_expired = false)
533
-    {
534
-        return ! $show_expired
535
-            ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
536
-            : '';
537
-    }
538
-
539
-
540
-
541
-    /**
542
-     * @param boolean $event_category_slug
543
-     * @return string
544
-     */
545
-    public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
546
-    {
547
-        global $wpdb;
548
-        return ! empty($event_category_slug)
549
-            ? $wpdb->prepare(" AND {$wpdb->terms}.slug = %s ", $event_category_slug)
550
-            : '';
551
-    }
552
-
553
-
554
-
555
-    /**
556
-     * @param boolean $month
557
-     * @return string
558
-     * @throws EE_Error
559
-     * @throws InvalidArgumentException
560
-     * @throws InvalidDataTypeException
561
-     * @throws InvalidInterfaceException
562
-     */
563
-    public static function posts_where_sql_for_event_list_month($month = null)
564
-    {
565
-        $SQL = '';
566
-        if (! empty($month)) {
567
-            $datetime_table = EEM_Datetime::instance()->table();
568
-            // event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
569
-            $SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
570
-            $SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
571
-            // event end date is GREATER than the start of the month ( so nothing that ended before this month )
572
-            $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
573
-            $SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
574
-        }
575
-        return $SQL;
576
-    }
577
-
578
-
579
-
580
-    /**
581
-     * @param string $SQL
582
-     * @param WP_Query $wp_query
583
-     * @return string
584
-     * @throws EE_Error
585
-     * @throws InvalidArgumentException
586
-     * @throws InvalidDataTypeException
587
-     * @throws InvalidInterfaceException
588
-     */
589
-    public static function posts_orderby($SQL = '', WP_Query $wp_query)
590
-    {
591
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
592
-            $SQL = EEH_Event_Query::posts_orderby_sql(
593
-                EEH_Event_Query::$_event_query_orderby,
594
-                EEH_Event_Query::$_event_query_sort
595
-            );
596
-        }
597
-        return $SQL;
598
-    }
599
-
600
-
601
-
602
-    /**
603
-     *    posts_orderby_sql
604
-     *    possible parameters:
605
-     *    ID
606
-     *    start_date
607
-     *    end_date
608
-     *    event_name
609
-     *    category_slug
610
-     *    ticket_start
611
-     *    ticket_end
612
-     *    venue_title
613
-     *    city
614
-     *    state
615
-     *    **IMPORTANT**
616
-     *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
617
-     *    or else some of the table references below will result in MySQL errors
618
-     *
619
-     * @param array  $orderby_params
620
-     * @param string $sort
621
-     * @return string
622
-     * @throws EE_Error
623
-     * @throws InvalidArgumentException
624
-     * @throws InvalidDataTypeException
625
-     * @throws InvalidInterfaceException
626
-     */
627
-    public static function posts_orderby_sql(array $orderby_params = array(), $sort = 'ASC')
628
-    {
629
-        global $wpdb;
630
-        $SQL     = '';
631
-        $counter = 0;
632
-        $sort    = in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
633
-            ? strtoupper($sort)
634
-            : 'ASC';
635
-        //make sure 'orderby' is set in query params
636
-        if (! isset(self::$_query_params['orderby'])) {
637
-            self::$_query_params['orderby'] = array();
638
-        }
639
-        // loop thru $orderby_params (type cast as array)
640
-        foreach ($orderby_params as $orderby) {
641
-            // check if we have already added this param
642
-            if (isset(self::$_query_params['orderby'][ $orderby ])) {
643
-                // if so then remove from the $orderby_params so that the count() method below is accurate
644
-                unset($orderby_params[ $orderby ]);
645
-                // then bump ahead to the next param
646
-                continue;
647
-            }
648
-            // this will ad a comma depending on whether this is the first or last param
649
-            $glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', ';
650
-            // ok what's we dealing with?
651
-            switch ($orderby) {
652
-                case 'id' :
653
-                case 'ID' :
654
-                    $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
655
-                    break;
656
-                case 'end_date' :
657
-                    $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
658
-                    break;
659
-                case 'event_name' :
660
-                    $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
661
-                    break;
662
-                case 'category_slug' :
663
-                    $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
664
-                    break;
665
-                case 'ticket_start' :
666
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
667
-                    break;
668
-                case 'ticket_end' :
669
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
670
-                    break;
671
-                case 'venue_title' :
672
-                    $SQL .= $glue . 'venue_title ' . $sort;
673
-                    break;
674
-                case 'city' :
675
-                    $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
676
-                    break;
677
-                case 'state' :
678
-                    $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
679
-                    break;
680
-                case 'start_date' :
681
-                default :
682
-                    $SQL .= $glue . ' event_start_date ' . $sort;
683
-                    break;
684
-            }
685
-            // add to array of orderby params that have been added
686
-            self::$_query_params['orderby'][ $orderby ] = true;
687
-            $counter++;
688
-        }
689
-        return $SQL;
690
-    }
21
+	/**
22
+	 * Start Date
23
+	 *
24
+	 * @var $_event_query_month
25
+	 */
26
+	protected static $_event_query_month;
27
+
28
+	/**
29
+	 * Category
30
+	 *
31
+	 * @var $_event_query_category
32
+	 */
33
+	protected static $_event_query_category;
34
+
35
+	/**
36
+	 * whether to display expired events in the event list
37
+	 *
38
+	 * @var bool $_show_expired
39
+	 */
40
+	protected static $_event_query_show_expired = false;
41
+
42
+	/**
43
+	 * list of params for controlling how the query results are ordered
44
+	 *
45
+	 * @var array $_event_query_orderby
46
+	 */
47
+	protected static $_event_query_orderby = array();
48
+
49
+	/**
50
+	 * direction list is sorted
51
+	 *
52
+	 * @var string $_event_query_sort
53
+	 */
54
+	protected static $_event_query_sort;
55
+
56
+	/**
57
+	 * list of params used to build the query's various clauses
58
+	 *
59
+	 * @var $_query_params
60
+	 */
61
+	protected static $_query_params = array();
62
+
63
+
64
+
65
+	/**
66
+	 * @return void
67
+	 */
68
+	public static function add_query_filters()
69
+	{
70
+		//add query filters
71
+		add_action('pre_get_posts', array('EEH_Event_Query', 'filter_query_parts'), 10, 1);
72
+	}
73
+
74
+
75
+
76
+	/**
77
+	 * @param WP_Query $WP_Query
78
+	 * @return bool
79
+	 */
80
+	public static function apply_query_filters(WP_Query $WP_Query)
81
+	{
82
+		return (
83
+				   isset($WP_Query->query['post_type'])
84
+				   && $WP_Query->query['post_type'] === 'espresso_events'
85
+			   )
86
+			   || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false);
87
+	}
88
+
89
+
90
+	/**
91
+	 * @param WP_Query $WP_Query
92
+	 */
93
+	public static function filter_query_parts(WP_Query $WP_Query)
94
+	{
95
+		// ONLY add our filters if this isn't the main wp_query,
96
+		// because if this is the main wp_query we already have
97
+		// our cpt strategies take care of adding things in.
98
+		if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) {
99
+			// build event list query
100
+			add_filter('posts_fields', array('EEH_Event_Query', 'posts_fields'), 10, 2);
101
+			add_filter('posts_join', array('EEH_Event_Query', 'posts_join'), 10, 2);
102
+			add_filter('posts_where', array('EEH_Event_Query', 'posts_where'), 10, 2);
103
+			add_filter('posts_orderby', array('EEH_Event_Query', 'posts_orderby'), 10, 2);
104
+			add_filter('posts_clauses_request', array('EEH_Event_Query', 'posts_clauses'), 10, 2);
105
+		}
106
+	}
107
+
108
+
109
+
110
+	/**
111
+	 * @param string $month
112
+	 * @param string $category
113
+	 * @param bool   $show_expired
114
+	 * @param string $orderby
115
+	 * @param string $sort
116
+	 * @throws InvalidArgumentException
117
+	 * @throws InvalidDataTypeException
118
+	 * @throws InvalidInterfaceException
119
+	 */
120
+	public static function set_query_params(
121
+		$month = '',
122
+		$category = '',
123
+		$show_expired = false,
124
+		$orderby = 'start_date',
125
+		$sort = 'ASC'
126
+	) {
127
+		self::$_query_params                        = array();
128
+		EEH_Event_Query::$_event_query_month        = EEH_Event_Query::_display_month($month);
129
+		EEH_Event_Query::$_event_query_category     = EEH_Event_Query::_event_category_slug($category);
130
+		EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired);
131
+		EEH_Event_Query::$_event_query_orderby      = EEH_Event_Query::_orderby($orderby);
132
+		EEH_Event_Query::$_event_query_sort         = EEH_Event_Query::_sort($sort);
133
+	}
134
+
135
+
136
+
137
+	/**
138
+	 * what month should the event list display events for?
139
+	 *
140
+	 * @param string $month
141
+	 * @return string
142
+	 * @throws InvalidArgumentException
143
+	 * @throws InvalidDataTypeException
144
+	 * @throws InvalidInterfaceException
145
+	 */
146
+	private static function _display_month($month = '')
147
+	{
148
+		return sanitize_text_field(EE_Registry::instance()->REQ->get('event_query_month', $month));
149
+	}
150
+
151
+
152
+
153
+	/**
154
+	 * @param string $category
155
+	 * @return string
156
+	 * @throws InvalidArgumentException
157
+	 * @throws InvalidDataTypeException
158
+	 * @throws InvalidInterfaceException
159
+	 */
160
+	private static function _event_category_slug($category = '')
161
+	{
162
+		return sanitize_title_with_dashes(EE_Registry::instance()->REQ->get('event_query_category', $category));
163
+	}
164
+
165
+
166
+
167
+	/**
168
+	 * @param bool $show_expired
169
+	 * @return bool
170
+	 * @throws InvalidArgumentException
171
+	 * @throws InvalidDataTypeException
172
+	 * @throws InvalidInterfaceException
173
+	 */
174
+	private static function _show_expired($show_expired = false)
175
+	{
176
+		// override default expired option if set via filter
177
+		return filter_var(
178
+			EE_Registry::instance()->REQ->get('event_query_show_expired', $show_expired),
179
+			FILTER_VALIDATE_BOOLEAN
180
+		);
181
+	}
182
+
183
+
184
+
185
+	/**
186
+	 * @param    string $orderby
187
+	 * @return array
188
+	 * @throws InvalidArgumentException
189
+	 * @throws InvalidDataTypeException
190
+	 * @throws InvalidInterfaceException
191
+	 */
192
+	private static function _orderby($orderby = 'start_date')
193
+	{
194
+		$event_query_orderby = EE_Registry::instance()->REQ->get('event_query_orderby', $orderby);
195
+		$event_query_orderby = is_array($event_query_orderby)
196
+			? $event_query_orderby
197
+			: explode(',', $event_query_orderby);
198
+		$event_query_orderby = array_map('trim', $event_query_orderby);
199
+		$event_query_orderby = array_map('sanitize_text_field', $event_query_orderby);
200
+		return $event_query_orderby;
201
+	}
202
+
203
+
204
+
205
+	/**
206
+	 * @param string $sort
207
+	 * @return string
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 */
212
+	private static function _sort($sort = 'ASC')
213
+	{
214
+		$sort = EE_Registry::instance()->REQ->get('event_query_sort', $sort);
215
+		return in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
216
+			? strtoupper($sort)
217
+			: 'ASC';
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * Filters the clauses for the WP_Query object
224
+	 *
225
+	 * @param array    $clauses array of clauses
226
+	 * @param WP_Query $wp_query
227
+	 * @return array   array of clauses
228
+	 */
229
+	public static function posts_clauses($clauses, WP_Query $wp_query)
230
+	{
231
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
232
+			global $wpdb;
233
+			$clauses['groupby'] = $wpdb->posts . '.ID ';
234
+		}
235
+		return $clauses;
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 * @param string   $SQL
242
+	 * @param WP_Query $wp_query
243
+	 * @return string
244
+	 * @throws EE_Error
245
+	 * @throws InvalidArgumentException
246
+	 * @throws InvalidDataTypeException
247
+	 * @throws InvalidInterfaceException
248
+	 */
249
+	public static function posts_fields($SQL, WP_Query $wp_query)
250
+	{
251
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
252
+			// adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
253
+			$SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby);
254
+		}
255
+		return $SQL;
256
+	}
257
+
258
+
259
+
260
+	/**
261
+	 * @param array $orderby_params
262
+	 * @return string
263
+	 * @throws EE_Error
264
+	 * @throws InvalidArgumentException
265
+	 * @throws InvalidDataTypeException
266
+	 * @throws InvalidInterfaceException
267
+	 */
268
+	public static function posts_fields_sql_for_orderby(array $orderby_params = array())
269
+	{
270
+		$SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
271
+		foreach ($orderby_params as $orderby) {
272
+			switch ($orderby) {
273
+
274
+				case 'ticket_start' :
275
+					$SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
276
+					break;
277
+				case 'ticket_end' :
278
+					$SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
279
+					break;
280
+				case 'venue_title' :
281
+					$SQL .= ', Venue.post_title AS venue_title';
282
+					break;
283
+				case 'city' :
284
+					$SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
285
+					break;
286
+				case 'state' :
287
+					$SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
288
+					break;
289
+			}
290
+		}
291
+		return $SQL;
292
+	}
293
+
294
+
295
+
296
+	/**
297
+	 * @param string   $SQL
298
+	 * @param WP_Query $wp_query
299
+	 * @return string
300
+	 * @throws EE_Error
301
+	 * @throws InvalidArgumentException
302
+	 * @throws InvalidDataTypeException
303
+	 * @throws InvalidInterfaceException
304
+	 */
305
+	public static function posts_join($SQL = '', WP_Query $wp_query)
306
+	{
307
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
308
+			// Category
309
+			$SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired);
310
+			$SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category);
311
+			$SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby);
312
+		}
313
+		return $SQL;
314
+	}
315
+
316
+
317
+
318
+	/**
319
+	 * @param string  $SQL
320
+	 * @param boolean $show_expired if TRUE, then displayed past events
321
+	 * @return string
322
+	 * @throws EE_Error
323
+	 * @throws InvalidArgumentException
324
+	 * @throws InvalidDataTypeException
325
+	 * @throws InvalidInterfaceException
326
+	 */
327
+	public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
328
+	{
329
+		if (! $show_expired) {
330
+			$join = EEM_Event::instance()->table() . '.ID = ';
331
+			$join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
332
+			// don't add if this is already in the SQL
333
+			if (strpos($SQL, $join) === false) {
334
+				$SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
335
+			}
336
+		}
337
+		return $SQL;
338
+	}
339
+
340
+
341
+
342
+	/**
343
+	 * @param string $SQL
344
+	 * @param string $join_terms    pass TRUE or term string, doesn't really matter since this value doesn't really get
345
+	 *                              used for anything yet
346
+	 * @return string
347
+	 */
348
+	public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
349
+	{
350
+		if (! empty($join_terms)) {
351
+			global $wpdb;
352
+			$SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
353
+			$SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
354
+			$SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) ";
355
+		}
356
+		return $SQL;
357
+	}
358
+
359
+
360
+
361
+	/**
362
+	 * usage:  $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params );
363
+	 *
364
+	 * @param    string $SQL
365
+	 * @param    array  $orderby_params
366
+	 * @return string
367
+	 * @throws EE_Error
368
+	 * @throws InvalidArgumentException
369
+	 * @throws InvalidDataTypeException
370
+	 * @throws InvalidInterfaceException
371
+	 */
372
+	public static function posts_join_for_orderby($SQL = '', array $orderby_params = array())
373
+	{
374
+		foreach ($orderby_params as $orderby) {
375
+			switch ($orderby) {
376
+				case 'ticket_start' :
377
+				case 'ticket_end' :
378
+					$SQL .= EEH_Event_Query::_posts_join_for_datetime(
379
+						$SQL,
380
+						EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
381
+					);
382
+					$SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
383
+					$SQL .= ' ON (';
384
+					$SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
385
+					$SQL .= ' = ';
386
+					$SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
387
+					$SQL .= ' )';
388
+					break;
389
+				case 'venue_title' :
390
+				case 'city' :
391
+					$SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
392
+					break;
393
+				case 'state' :
394
+					$SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
395
+					$SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL);
396
+					break;
397
+				case 'start_date' :
398
+				default :
399
+					$SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
400
+					break;
401
+			}
402
+		}
403
+		return $SQL;
404
+	}
405
+
406
+
407
+
408
+	/**
409
+	 * @param string $SQL
410
+	 * @param string $join
411
+	 * @return string
412
+	 * @throws EE_Error
413
+	 * @throws InvalidArgumentException
414
+	 * @throws InvalidDataTypeException
415
+	 * @throws InvalidInterfaceException
416
+	 */
417
+	protected static function _posts_join_for_datetime($SQL = '', $join = '')
418
+	{
419
+		if (! empty($join)) {
420
+			$join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
421
+			if (strpos($SQL, $join) === false) {
422
+				return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
423
+			}
424
+		}
425
+		return '';
426
+	}
427
+
428
+
429
+
430
+	/**
431
+	 * @param string $SQL
432
+	 * @return string
433
+	 * @throws EE_Error
434
+	 * @throws InvalidArgumentException
435
+	 * @throws InvalidDataTypeException
436
+	 * @throws InvalidInterfaceException
437
+	 */
438
+	protected static function _posts_join_for_event_venue($SQL = '')
439
+	{
440
+		// Event Venue table name
441
+		$event_venue_table = EEM_Event_Venue::instance()->table();
442
+		// generate conditions for:  Event <=> Event Venue  JOIN clause
443
+		$event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = ';
444
+		$event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name();
445
+		// don't add joins if they have already been added
446
+		if (strpos($SQL, $event_to_event_venue_join) === false) {
447
+			// Venue table name
448
+			$venue_table = EEM_Venue::instance()->table();
449
+			// Venue table pk
450
+			$venue_table_pk = EEM_Venue::instance()->primary_key_name();
451
+			// Venue Meta table name
452
+			$venue_meta_table = EEM_Venue::instance()->second_table();
453
+			// generate JOIN clause for: Event <=> Event Venue
454
+			$venue_SQL = " LEFT JOIN $event_venue_table ON ( $event_to_event_venue_join )";
455
+			// generate JOIN clause for: Event Venue <=> Venue
456
+			$venue_SQL .= " LEFT JOIN $venue_table as Venue ON ( $event_venue_table.$venue_table_pk = Venue.ID )";
457
+			// generate JOIN clause for: Venue <=> Venue Meta
458
+			$venue_SQL .= " LEFT JOIN $venue_meta_table ON ( Venue.ID = $venue_meta_table.$venue_table_pk )";
459
+			unset($event_venue_table, $event_to_event_venue_join, $venue_table, $venue_table_pk, $venue_meta_table);
460
+			return $venue_SQL;
461
+		}
462
+		unset($event_venue_table, $event_to_event_venue_join);
463
+		return '';
464
+	}
465
+
466
+
467
+
468
+	/**
469
+	 * @param string $SQL
470
+	 * @return string
471
+	 * @throws EE_Error
472
+	 * @throws InvalidArgumentException
473
+	 * @throws InvalidDataTypeException
474
+	 * @throws InvalidInterfaceException
475
+	 */
476
+	protected static function _posts_join_for_venue_state($SQL = '')
477
+	{
478
+		// Venue Meta table name
479
+		$venue_meta_table = EEM_Venue::instance()->second_table();
480
+		// State table name
481
+		$state_table = EEM_State::instance()->table();
482
+		// State table pk
483
+		$state_table_pk = EEM_State::instance()->primary_key_name();
484
+		// verify vars
485
+		if ($venue_meta_table && $state_table && $state_table_pk) {
486
+			// like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID
487
+			$join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk";
488
+			// don't add join if it has already been added
489
+			if (strpos($SQL, $join) === false) {
490
+				unset($state_table_pk, $venue_meta_table, $venue_table_pk);
491
+				return " LEFT JOIN $state_table ON ( $join )";
492
+			}
493
+		}
494
+		unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk);
495
+		return '';
496
+	}
497
+
498
+
499
+
500
+	/**
501
+	 * @param string   $SQL
502
+	 * @param WP_Query $wp_query
503
+	 * @return string
504
+	 * @throws EE_Error
505
+	 * @throws InvalidArgumentException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws InvalidInterfaceException
508
+	 */
509
+	public static function posts_where($SQL = '', WP_Query $wp_query)
510
+	{
511
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
512
+			// Show Expired ?
513
+			$SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired);
514
+			// Category
515
+			$SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category);
516
+			// Start Date
517
+			$SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month);
518
+		}
519
+		return $SQL;
520
+	}
521
+
522
+
523
+
524
+	/**
525
+	 * @param    boolean $show_expired if TRUE, then displayed past events
526
+	 * @return string
527
+	 * @throws EE_Error
528
+	 * @throws InvalidArgumentException
529
+	 * @throws InvalidDataTypeException
530
+	 * @throws InvalidInterfaceException
531
+	 */
532
+	public static function posts_where_sql_for_show_expired($show_expired = false)
533
+	{
534
+		return ! $show_expired
535
+			? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
536
+			: '';
537
+	}
538
+
539
+
540
+
541
+	/**
542
+	 * @param boolean $event_category_slug
543
+	 * @return string
544
+	 */
545
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
546
+	{
547
+		global $wpdb;
548
+		return ! empty($event_category_slug)
549
+			? $wpdb->prepare(" AND {$wpdb->terms}.slug = %s ", $event_category_slug)
550
+			: '';
551
+	}
552
+
553
+
554
+
555
+	/**
556
+	 * @param boolean $month
557
+	 * @return string
558
+	 * @throws EE_Error
559
+	 * @throws InvalidArgumentException
560
+	 * @throws InvalidDataTypeException
561
+	 * @throws InvalidInterfaceException
562
+	 */
563
+	public static function posts_where_sql_for_event_list_month($month = null)
564
+	{
565
+		$SQL = '';
566
+		if (! empty($month)) {
567
+			$datetime_table = EEM_Datetime::instance()->table();
568
+			// event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
569
+			$SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
570
+			$SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
571
+			// event end date is GREATER than the start of the month ( so nothing that ended before this month )
572
+			$SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
573
+			$SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
574
+		}
575
+		return $SQL;
576
+	}
577
+
578
+
579
+
580
+	/**
581
+	 * @param string $SQL
582
+	 * @param WP_Query $wp_query
583
+	 * @return string
584
+	 * @throws EE_Error
585
+	 * @throws InvalidArgumentException
586
+	 * @throws InvalidDataTypeException
587
+	 * @throws InvalidInterfaceException
588
+	 */
589
+	public static function posts_orderby($SQL = '', WP_Query $wp_query)
590
+	{
591
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
592
+			$SQL = EEH_Event_Query::posts_orderby_sql(
593
+				EEH_Event_Query::$_event_query_orderby,
594
+				EEH_Event_Query::$_event_query_sort
595
+			);
596
+		}
597
+		return $SQL;
598
+	}
599
+
600
+
601
+
602
+	/**
603
+	 *    posts_orderby_sql
604
+	 *    possible parameters:
605
+	 *    ID
606
+	 *    start_date
607
+	 *    end_date
608
+	 *    event_name
609
+	 *    category_slug
610
+	 *    ticket_start
611
+	 *    ticket_end
612
+	 *    venue_title
613
+	 *    city
614
+	 *    state
615
+	 *    **IMPORTANT**
616
+	 *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
617
+	 *    or else some of the table references below will result in MySQL errors
618
+	 *
619
+	 * @param array  $orderby_params
620
+	 * @param string $sort
621
+	 * @return string
622
+	 * @throws EE_Error
623
+	 * @throws InvalidArgumentException
624
+	 * @throws InvalidDataTypeException
625
+	 * @throws InvalidInterfaceException
626
+	 */
627
+	public static function posts_orderby_sql(array $orderby_params = array(), $sort = 'ASC')
628
+	{
629
+		global $wpdb;
630
+		$SQL     = '';
631
+		$counter = 0;
632
+		$sort    = in_array($sort, array('ASC', 'asc', 'DESC', 'desc'), true)
633
+			? strtoupper($sort)
634
+			: 'ASC';
635
+		//make sure 'orderby' is set in query params
636
+		if (! isset(self::$_query_params['orderby'])) {
637
+			self::$_query_params['orderby'] = array();
638
+		}
639
+		// loop thru $orderby_params (type cast as array)
640
+		foreach ($orderby_params as $orderby) {
641
+			// check if we have already added this param
642
+			if (isset(self::$_query_params['orderby'][ $orderby ])) {
643
+				// if so then remove from the $orderby_params so that the count() method below is accurate
644
+				unset($orderby_params[ $orderby ]);
645
+				// then bump ahead to the next param
646
+				continue;
647
+			}
648
+			// this will ad a comma depending on whether this is the first or last param
649
+			$glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', ';
650
+			// ok what's we dealing with?
651
+			switch ($orderby) {
652
+				case 'id' :
653
+				case 'ID' :
654
+					$SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
655
+					break;
656
+				case 'end_date' :
657
+					$SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
658
+					break;
659
+				case 'event_name' :
660
+					$SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
661
+					break;
662
+				case 'category_slug' :
663
+					$SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
664
+					break;
665
+				case 'ticket_start' :
666
+					$SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
667
+					break;
668
+				case 'ticket_end' :
669
+					$SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
670
+					break;
671
+				case 'venue_title' :
672
+					$SQL .= $glue . 'venue_title ' . $sort;
673
+					break;
674
+				case 'city' :
675
+					$SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
676
+					break;
677
+				case 'state' :
678
+					$SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
679
+					break;
680
+				case 'start_date' :
681
+				default :
682
+					$SQL .= $glue . ' event_start_date ' . $sort;
683
+					break;
684
+			}
685
+			// add to array of orderby params that have been added
686
+			self::$_query_params['orderby'][ $orderby ] = true;
687
+			$counter++;
688
+		}
689
+		return $SQL;
690
+	}
691 691
 
692 692
 
693 693
 }
Please login to merge, or discard this patch.
Spacing   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -230,7 +230,7 @@  discard block
 block discarded – undo
230 230
     {
231 231
         if (EEH_Event_Query::apply_query_filters($wp_query)) {
232 232
             global $wpdb;
233
-            $clauses['groupby'] = $wpdb->posts . '.ID ';
233
+            $clauses['groupby'] = $wpdb->posts.'.ID ';
234 234
         }
235 235
         return $clauses;
236 236
     }
@@ -267,24 +267,24 @@  discard block
 block discarded – undo
267 267
      */
268 268
     public static function posts_fields_sql_for_orderby(array $orderby_params = array())
269 269
     {
270
-        $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
270
+        $SQL = ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date ';
271 271
         foreach ($orderby_params as $orderby) {
272 272
             switch ($orderby) {
273 273
 
274 274
                 case 'ticket_start' :
275
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
275
+                    $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_start_date';
276 276
                     break;
277 277
                 case 'ticket_end' :
278
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
278
+                    $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_end_date';
279 279
                     break;
280 280
                 case 'venue_title' :
281 281
                     $SQL .= ', Venue.post_title AS venue_title';
282 282
                     break;
283 283
                 case 'city' :
284
-                    $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
284
+                    $SQL .= ', '.EEM_Venue::instance()->second_table().'.VNU_city';
285 285
                     break;
286 286
                 case 'state' :
287
-                    $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
287
+                    $SQL .= ', '.EEM_State::instance()->table().'.STA_name';
288 288
                     break;
289 289
             }
290 290
         }
@@ -326,12 +326,12 @@  discard block
 block discarded – undo
326 326
      */
327 327
     public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
328 328
     {
329
-        if (! $show_expired) {
330
-            $join = EEM_Event::instance()->table() . '.ID = ';
331
-            $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
329
+        if ( ! $show_expired) {
330
+            $join = EEM_Event::instance()->table().'.ID = ';
331
+            $join .= EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name();
332 332
             // don't add if this is already in the SQL
333 333
             if (strpos($SQL, $join) === false) {
334
-                $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
334
+                $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' ) ';
335 335
             }
336 336
         }
337 337
         return $SQL;
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
      */
348 348
     public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
349 349
     {
350
-        if (! empty($join_terms)) {
350
+        if ( ! empty($join_terms)) {
351 351
             global $wpdb;
352 352
             $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
353 353
             $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
@@ -377,13 +377,13 @@  discard block
 block discarded – undo
377 377
                 case 'ticket_end' :
378 378
                     $SQL .= EEH_Event_Query::_posts_join_for_datetime(
379 379
                         $SQL,
380
-                        EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
380
+                        EEM_Datetime_Ticket::instance()->table().'.'.EEM_Datetime::instance()->primary_key_name()
381 381
                     );
382
-                    $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
382
+                    $SQL .= ' LEFT JOIN '.EEM_Ticket::instance()->table();
383 383
                     $SQL .= ' ON (';
384
-                    $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
384
+                    $SQL .= EEM_Datetime_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name();
385 385
                     $SQL .= ' = ';
386
-                    $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
386
+                    $SQL .= EEM_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name();
387 387
                     $SQL .= ' )';
388 388
                     break;
389 389
                 case 'venue_title' :
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
                     break;
397 397
                 case 'start_date' :
398 398
                 default :
399
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
399
+                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table().'.ID');
400 400
                     break;
401 401
             }
402 402
         }
@@ -416,10 +416,10 @@  discard block
 block discarded – undo
416 416
      */
417 417
     protected static function _posts_join_for_datetime($SQL = '', $join = '')
418 418
     {
419
-        if (! empty($join)) {
420
-            $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
419
+        if ( ! empty($join)) {
420
+            $join .= ' = '.EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name();
421 421
             if (strpos($SQL, $join) === false) {
422
-                return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
422
+                return ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' )';
423 423
             }
424 424
         }
425 425
         return '';
@@ -440,8 +440,8 @@  discard block
 block discarded – undo
440 440
         // Event Venue table name
441 441
         $event_venue_table = EEM_Event_Venue::instance()->table();
442 442
         // generate conditions for:  Event <=> Event Venue  JOIN clause
443
-        $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = ';
444
-        $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name();
443
+        $event_to_event_venue_join = EEM_Event::instance()->table().'.ID = ';
444
+        $event_to_event_venue_join .= $event_venue_table.'.'.EEM_Event::instance()->primary_key_name();
445 445
         // don't add joins if they have already been added
446 446
         if (strpos($SQL, $event_to_event_venue_join) === false) {
447 447
             // Venue table name
@@ -532,7 +532,7 @@  discard block
 block discarded – undo
532 532
     public static function posts_where_sql_for_show_expired($show_expired = false)
533 533
     {
534 534
         return ! $show_expired
535
-            ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
535
+            ? ' AND '.EEM_Datetime::instance()->table().'.DTT_EVT_end > \''.current_time('mysql', true).'\' '
536 536
             : '';
537 537
     }
538 538
 
@@ -563,14 +563,14 @@  discard block
 block discarded – undo
563 563
     public static function posts_where_sql_for_event_list_month($month = null)
564 564
     {
565 565
         $SQL = '';
566
-        if (! empty($month)) {
566
+        if ( ! empty($month)) {
567 567
             $datetime_table = EEM_Datetime::instance()->table();
568 568
             // event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
569 569
             $SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
570
-            $SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
570
+            $SQL .= date('Y-m-t 23:59:59', \EEH_DTT_Helper::first_of_month_timestamp($month))."'";
571 571
             // event end date is GREATER than the start of the month ( so nothing that ended before this month )
572 572
             $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
573
-            $SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
573
+            $SQL .= date('Y-m-01 0:0:00', \EEH_DTT_Helper::first_of_month_timestamp($month))."' ";
574 574
         }
575 575
         return $SQL;
576 576
     }
@@ -633,15 +633,15 @@  discard block
 block discarded – undo
633 633
             ? strtoupper($sort)
634 634
             : 'ASC';
635 635
         //make sure 'orderby' is set in query params
636
-        if (! isset(self::$_query_params['orderby'])) {
636
+        if ( ! isset(self::$_query_params['orderby'])) {
637 637
             self::$_query_params['orderby'] = array();
638 638
         }
639 639
         // loop thru $orderby_params (type cast as array)
640 640
         foreach ($orderby_params as $orderby) {
641 641
             // check if we have already added this param
642
-            if (isset(self::$_query_params['orderby'][ $orderby ])) {
642
+            if (isset(self::$_query_params['orderby'][$orderby])) {
643 643
                 // if so then remove from the $orderby_params so that the count() method below is accurate
644
-                unset($orderby_params[ $orderby ]);
644
+                unset($orderby_params[$orderby]);
645 645
                 // then bump ahead to the next param
646 646
                 continue;
647 647
             }
@@ -651,39 +651,39 @@  discard block
 block discarded – undo
651 651
             switch ($orderby) {
652 652
                 case 'id' :
653 653
                 case 'ID' :
654
-                    $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
654
+                    $SQL .= $glue.$wpdb->posts.'.ID '.$sort;
655 655
                     break;
656 656
                 case 'end_date' :
657
-                    $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
657
+                    $SQL .= $glue.EEM_Datetime::instance()->table().'.DTT_EVT_end '.$sort;
658 658
                     break;
659 659
                 case 'event_name' :
660
-                    $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
660
+                    $SQL .= $glue.$wpdb->posts.'.post_title '.$sort;
661 661
                     break;
662 662
                 case 'category_slug' :
663
-                    $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
663
+                    $SQL .= $glue.$wpdb->terms.'.slug '.$sort;
664 664
                     break;
665 665
                 case 'ticket_start' :
666
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
666
+                    $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_start_date '.$sort;
667 667
                     break;
668 668
                 case 'ticket_end' :
669
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
669
+                    $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_end_date '.$sort;
670 670
                     break;
671 671
                 case 'venue_title' :
672
-                    $SQL .= $glue . 'venue_title ' . $sort;
672
+                    $SQL .= $glue.'venue_title '.$sort;
673 673
                     break;
674 674
                 case 'city' :
675
-                    $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
675
+                    $SQL .= $glue.EEM_Venue::instance()->second_table().'.VNU_city '.$sort;
676 676
                     break;
677 677
                 case 'state' :
678
-                    $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
678
+                    $SQL .= $glue.EEM_State::instance()->table().'.STA_name '.$sort;
679 679
                     break;
680 680
                 case 'start_date' :
681 681
                 default :
682
-                    $SQL .= $glue . ' event_start_date ' . $sort;
682
+                    $SQL .= $glue.' event_start_date '.$sort;
683 683
                     break;
684 684
             }
685 685
             // add to array of orderby params that have been added
686
-            self::$_query_params['orderby'][ $orderby ] = true;
686
+            self::$_query_params['orderby'][$orderby] = true;
687 687
             $counter++;
688 688
         }
689 689
         return $SQL;
Please login to merge, or discard this patch.
core/domain/entities/notifications/PersistentAdminNotice.php 2 patches
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
      */
131 131
     private function setName($name)
132 132
     {
133
-        if (! is_string($name)) {
133
+        if ( ! is_string($name)) {
134 134
             throw new InvalidDataTypeException('$name', $name, 'string');
135 135
         }
136 136
         $this->name = sanitize_key($name);
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
      */
155 155
     private function setMessage($message)
156 156
     {
157
-        if (! is_string($message)) {
157
+        if ( ! is_string($message)) {
158 158
             throw new InvalidDataTypeException('$message', $message, 'string');
159 159
         }
160 160
         global $allowedtags;
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
      */
201 201
     private function setCapability($capability)
202 202
     {
203
-        if (! is_string($capability)) {
203
+        if ( ! is_string($capability)) {
204 204
             throw new InvalidDataTypeException('$capability', $capability, 'string');
205 205
         }
206 206
         $this->capability = ! empty($capability) ? $capability : 'manage_options';
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
      */
225 225
     private function setCapContext($cap_context)
226 226
     {
227
-        if (! is_string($cap_context)) {
227
+        if ( ! is_string($cap_context)) {
228 228
             throw new InvalidDataTypeException('$cap_context', $cap_context, 'string');
229 229
         }
230 230
         $this->cap_context = ! empty($cap_context) ? $cap_context : 'view persistent admin notice';
@@ -258,7 +258,7 @@  discard block
 block discarded – undo
258 258
      */
259 259
     public function getCapCheck()
260 260
     {
261
-        if (! $this->cap_check instanceof CapCheckInterface) {
261
+        if ( ! $this->cap_check instanceof CapCheckInterface) {
262 262
             $this->setCapCheck(
263 263
                 new CapCheck(
264 264
                     $this->capability,
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
      */
341 341
     public function confirmRegistered()
342 342
     {
343
-        if (! $this->registered && WP_DEBUG) {
343
+        if ( ! $this->registered && WP_DEBUG) {
344 344
             new ExceptionStackTraceDisplay(
345 345
                 new DomainException(
346 346
                     sprintf(
Please login to merge, or discard this patch.
Indentation   +325 added lines, -325 removed lines patch added patch discarded remove patch
@@ -28,334 +28,334 @@
 block discarded – undo
28 28
 class PersistentAdminNotice implements RequiresCapCheckInterface
29 29
 {
30 30
 
31
-    /**
32
-     * @var string $name
33
-     */
34
-    protected $name = '';
35
-
36
-    /**
37
-     * @var string $message
38
-     */
39
-    protected $message = '';
40
-
41
-    /**
42
-     * @var boolean $force_update
43
-     */
44
-    protected $force_update = false;
45
-
46
-    /**
47
-     * @var string $capability
48
-     */
49
-    protected $capability = 'manage_options';
50
-
51
-    /**
52
-     * @var string $cap_context
53
-     */
54
-    protected $cap_context = 'view persistent admin notice';
55
-
56
-    /**
57
-     * @var boolean $dismissed
58
-     */
59
-    protected $dismissed = false;
60
-
61
-    /**
62
-     * @var CapCheckInterface $cap_check
63
-     */
64
-    protected $cap_check;
65
-
66
-    /**
67
-     * if true, then this notice will be deleted from the database
68
-     *
69
-     * @var boolean $purge
70
-     */
71
-    protected $purge = false;
72
-
73
-    /**
74
-     * gets set to true if notice is successfully registered with the PersistentAdminNoticeManager
75
-     * if false, and WP_DEBUG is on, then an exception will be thrown in the admin footer
76
-     *
77
-     * @var boolean $registered
78
-     */
79
-    private $registered = false;
80
-
81
-
82
-
83
-    /**
84
-     * PersistentAdminNotice constructor
85
-     *
86
-     * @param string $name         [required] the name, or key of the Persistent Admin Notice to be stored
87
-     * @param string $message      [required] the message to be stored persistently until dismissed
88
-     * @param bool   $force_update enforce the reappearance of a persistent message
89
-     * @param string $capability   user capability required to view this notice
90
-     * @param string $cap_context  description for why the cap check is being performed
91
-     * @param bool   $dismissed    whether or not the user has already dismissed/viewed this notice
92
-     * @throws InvalidDataTypeException
93
-     */
94
-    public function __construct(
95
-        $name,
96
-        $message,
97
-        $force_update = false,
98
-        $capability = 'manage_options',
99
-        $cap_context = 'view persistent admin notice',
100
-        $dismissed = false
101
-    ) {
102
-        $this->setName($name);
103
-        $this->setMessage($message);
104
-        $this->setForceUpdate($force_update);
105
-        $this->setCapability($capability);
106
-        $this->setCapContext($cap_context);
107
-        $this->setDismissed($dismissed);
108
-        add_action(
109
-            'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices',
110
-            array($this, 'registerPersistentAdminNotice')
111
-        );
112
-        add_action('shutdown', array($this, 'confirmRegistered'), 999);
113
-    }
114
-
115
-
116
-
117
-    /**
118
-     * @return string
119
-     */
120
-    public function getName()
121
-    {
122
-        return $this->name;
123
-    }
124
-
125
-
126
-
127
-    /**
128
-     * @param string $name
129
-     * @throws InvalidDataTypeException
130
-     */
131
-    private function setName($name)
132
-    {
133
-        if (! is_string($name)) {
134
-            throw new InvalidDataTypeException('$name', $name, 'string');
135
-        }
136
-        $this->name = sanitize_key($name);
137
-    }
138
-
139
-
140
-
141
-    /**
142
-     * @return string
143
-     */
144
-    public function getMessage()
145
-    {
146
-        return $this->message;
147
-    }
148
-
149
-
150
-
151
-    /**
152
-     * @param string $message
153
-     * @throws InvalidDataTypeException
154
-     */
155
-    private function setMessage($message)
156
-    {
157
-        if (! is_string($message)) {
158
-            throw new InvalidDataTypeException('$message', $message, 'string');
159
-        }
160
-        global $allowedtags;
161
-        $allowedtags['br'] = array();
162
-        $this->message     = wp_kses($message, $allowedtags);
163
-    }
164
-
165
-
166
-
167
-    /**
168
-     * @return bool
169
-     */
170
-    public function getForceUpdate()
171
-    {
172
-        return $this->force_update;
173
-    }
174
-
175
-
176
-
177
-    /**
178
-     * @param bool $force_update
179
-     */
180
-    private function setForceUpdate($force_update)
181
-    {
182
-        $this->force_update = filter_var($force_update, FILTER_VALIDATE_BOOLEAN);
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * @return string
189
-     */
190
-    public function getCapability()
191
-    {
192
-        return $this->capability;
193
-    }
194
-
195
-
196
-
197
-    /**
198
-     * @param string $capability
199
-     * @throws InvalidDataTypeException
200
-     */
201
-    private function setCapability($capability)
202
-    {
203
-        if (! is_string($capability)) {
204
-            throw new InvalidDataTypeException('$capability', $capability, 'string');
205
-        }
206
-        $this->capability = ! empty($capability) ? $capability : 'manage_options';
207
-    }
31
+	/**
32
+	 * @var string $name
33
+	 */
34
+	protected $name = '';
35
+
36
+	/**
37
+	 * @var string $message
38
+	 */
39
+	protected $message = '';
40
+
41
+	/**
42
+	 * @var boolean $force_update
43
+	 */
44
+	protected $force_update = false;
45
+
46
+	/**
47
+	 * @var string $capability
48
+	 */
49
+	protected $capability = 'manage_options';
50
+
51
+	/**
52
+	 * @var string $cap_context
53
+	 */
54
+	protected $cap_context = 'view persistent admin notice';
55
+
56
+	/**
57
+	 * @var boolean $dismissed
58
+	 */
59
+	protected $dismissed = false;
60
+
61
+	/**
62
+	 * @var CapCheckInterface $cap_check
63
+	 */
64
+	protected $cap_check;
65
+
66
+	/**
67
+	 * if true, then this notice will be deleted from the database
68
+	 *
69
+	 * @var boolean $purge
70
+	 */
71
+	protected $purge = false;
72
+
73
+	/**
74
+	 * gets set to true if notice is successfully registered with the PersistentAdminNoticeManager
75
+	 * if false, and WP_DEBUG is on, then an exception will be thrown in the admin footer
76
+	 *
77
+	 * @var boolean $registered
78
+	 */
79
+	private $registered = false;
80
+
81
+
82
+
83
+	/**
84
+	 * PersistentAdminNotice constructor
85
+	 *
86
+	 * @param string $name         [required] the name, or key of the Persistent Admin Notice to be stored
87
+	 * @param string $message      [required] the message to be stored persistently until dismissed
88
+	 * @param bool   $force_update enforce the reappearance of a persistent message
89
+	 * @param string $capability   user capability required to view this notice
90
+	 * @param string $cap_context  description for why the cap check is being performed
91
+	 * @param bool   $dismissed    whether or not the user has already dismissed/viewed this notice
92
+	 * @throws InvalidDataTypeException
93
+	 */
94
+	public function __construct(
95
+		$name,
96
+		$message,
97
+		$force_update = false,
98
+		$capability = 'manage_options',
99
+		$cap_context = 'view persistent admin notice',
100
+		$dismissed = false
101
+	) {
102
+		$this->setName($name);
103
+		$this->setMessage($message);
104
+		$this->setForceUpdate($force_update);
105
+		$this->setCapability($capability);
106
+		$this->setCapContext($cap_context);
107
+		$this->setDismissed($dismissed);
108
+		add_action(
109
+			'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices',
110
+			array($this, 'registerPersistentAdminNotice')
111
+		);
112
+		add_action('shutdown', array($this, 'confirmRegistered'), 999);
113
+	}
114
+
115
+
116
+
117
+	/**
118
+	 * @return string
119
+	 */
120
+	public function getName()
121
+	{
122
+		return $this->name;
123
+	}
124
+
125
+
126
+
127
+	/**
128
+	 * @param string $name
129
+	 * @throws InvalidDataTypeException
130
+	 */
131
+	private function setName($name)
132
+	{
133
+		if (! is_string($name)) {
134
+			throw new InvalidDataTypeException('$name', $name, 'string');
135
+		}
136
+		$this->name = sanitize_key($name);
137
+	}
138
+
139
+
140
+
141
+	/**
142
+	 * @return string
143
+	 */
144
+	public function getMessage()
145
+	{
146
+		return $this->message;
147
+	}
148
+
149
+
150
+
151
+	/**
152
+	 * @param string $message
153
+	 * @throws InvalidDataTypeException
154
+	 */
155
+	private function setMessage($message)
156
+	{
157
+		if (! is_string($message)) {
158
+			throw new InvalidDataTypeException('$message', $message, 'string');
159
+		}
160
+		global $allowedtags;
161
+		$allowedtags['br'] = array();
162
+		$this->message     = wp_kses($message, $allowedtags);
163
+	}
164
+
165
+
166
+
167
+	/**
168
+	 * @return bool
169
+	 */
170
+	public function getForceUpdate()
171
+	{
172
+		return $this->force_update;
173
+	}
174
+
175
+
176
+
177
+	/**
178
+	 * @param bool $force_update
179
+	 */
180
+	private function setForceUpdate($force_update)
181
+	{
182
+		$this->force_update = filter_var($force_update, FILTER_VALIDATE_BOOLEAN);
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * @return string
189
+	 */
190
+	public function getCapability()
191
+	{
192
+		return $this->capability;
193
+	}
194
+
195
+
196
+
197
+	/**
198
+	 * @param string $capability
199
+	 * @throws InvalidDataTypeException
200
+	 */
201
+	private function setCapability($capability)
202
+	{
203
+		if (! is_string($capability)) {
204
+			throw new InvalidDataTypeException('$capability', $capability, 'string');
205
+		}
206
+		$this->capability = ! empty($capability) ? $capability : 'manage_options';
207
+	}
208 208
 
209 209
 
210 210
 
211
-    /**
212
-     * @return string
213
-     */
214
-    public function getCapContext()
215
-    {
216
-        return $this->cap_context;
217
-    }
218
-
219
-
220
-
221
-    /**
222
-     * @param string $cap_context
223
-     * @throws InvalidDataTypeException
224
-     */
225
-    private function setCapContext($cap_context)
226
-    {
227
-        if (! is_string($cap_context)) {
228
-            throw new InvalidDataTypeException('$cap_context', $cap_context, 'string');
229
-        }
230
-        $this->cap_context = ! empty($cap_context) ? $cap_context : 'view persistent admin notice';
231
-    }
232
-
233
-
234
-
235
-    /**
236
-     * @return bool
237
-     */
238
-    public function getDismissed()
239
-    {
240
-        return $this->dismissed;
241
-    }
242
-
243
-
244
-
245
-    /**
246
-     * @param bool $dismissed
247
-     */
248
-    public function setDismissed($dismissed)
249
-    {
250
-        $this->dismissed = filter_var($dismissed, FILTER_VALIDATE_BOOLEAN);
251
-    }
252
-
253
-
254
-
255
-    /**
256
-     * @return CapCheckInterface
257
-     * @throws InvalidDataTypeException
258
-     */
259
-    public function getCapCheck()
260
-    {
261
-        if (! $this->cap_check instanceof CapCheckInterface) {
262
-            $this->setCapCheck(
263
-                new CapCheck(
264
-                    $this->capability,
265
-                    $this->cap_context
266
-                )
267
-            );
268
-        }
269
-        return $this->cap_check;
270
-    }
271
-
272
-
273
-
274
-    /**
275
-     * @param CapCheckInterface $cap_check
276
-     */
277
-    private function setCapCheck(CapCheckInterface $cap_check)
278
-    {
279
-        $this->cap_check = $cap_check;
280
-    }
281
-
282
-
283
-
284
-    /**
285
-     * @return bool
286
-     */
287
-    public function getPurge()
288
-    {
289
-        return $this->purge;
290
-    }
291
-
292
-
293
-
294
-    /**
295
-     * @param bool $purge
296
-     */
297
-    public function setPurge($purge)
298
-    {
299
-        $this->purge = filter_var($purge, FILTER_VALIDATE_BOOLEAN);
300
-    }
301
-
302
-
303
-
304
-    /**
305
-     * given a valid PersistentAdminNotice Collection,
306
-     * this notice will be added if it is not already found in the collection (using its name as the identifier)
307
-     * if an existing notice is found that has already been dismissed,
308
-     * but we are overriding with a forced update, then we will toggle its dismissed state,
309
-     * so that the notice is displayed again
310
-     *
311
-     * @param Collection $persistent_admin_notice_collection
312
-     * @throws InvalidEntityException
313
-     */
314
-    public function registerPersistentAdminNotice(Collection $persistent_admin_notice_collection)
315
-    {
316
-        if ($this->registered) {
317
-            return;
318
-        }
319
-        // first check if this notice has already been added to the collection
320
-        if ($persistent_admin_notice_collection->has($this->name)) {
321
-            /** @var PersistentAdminNotice $existing */
322
-            $existing = $persistent_admin_notice_collection->get($this->name);
323
-            // we don't need to add it again (we can't actually)
324
-            // but if it has already been dismissed, and we are overriding with a forced update
325
-            if ($existing->getDismissed() && $this->getForceUpdate()) {
326
-                // then toggle the notice's dismissed state to true
327
-                // so that it gets displayed again
328
-                $existing->setDismissed(false);
329
-                // and make sure the message is set
330
-                $existing->setMessage($this->message);
331
-            }
332
-        } else {
333
-            $persistent_admin_notice_collection->add($this, $this->name);
334
-        }
335
-        $this->registered = true;
336
-    }
337
-
338
-
339
-
340
-    /**
341
-     * @throws Exception
342
-     */
343
-    public function confirmRegistered()
344
-    {
345
-        if (! $this->registered && WP_DEBUG) {
346
-            new ExceptionStackTraceDisplay(
347
-                new DomainException(
348
-                    sprintf(
349
-                        esc_html__(
350
-                            'The "%1$s" PersistentAdminNotice was not successfully registered. Please ensure that it is being created prior to either the "admin_notices" or "network_admin_notices" hooks being triggered.',
351
-                            'event_espresso'
352
-                        ),
353
-                        $this->name
354
-                    )
355
-                )
356
-            );
357
-        }
358
-    }
211
+	/**
212
+	 * @return string
213
+	 */
214
+	public function getCapContext()
215
+	{
216
+		return $this->cap_context;
217
+	}
218
+
219
+
220
+
221
+	/**
222
+	 * @param string $cap_context
223
+	 * @throws InvalidDataTypeException
224
+	 */
225
+	private function setCapContext($cap_context)
226
+	{
227
+		if (! is_string($cap_context)) {
228
+			throw new InvalidDataTypeException('$cap_context', $cap_context, 'string');
229
+		}
230
+		$this->cap_context = ! empty($cap_context) ? $cap_context : 'view persistent admin notice';
231
+	}
232
+
233
+
234
+
235
+	/**
236
+	 * @return bool
237
+	 */
238
+	public function getDismissed()
239
+	{
240
+		return $this->dismissed;
241
+	}
242
+
243
+
244
+
245
+	/**
246
+	 * @param bool $dismissed
247
+	 */
248
+	public function setDismissed($dismissed)
249
+	{
250
+		$this->dismissed = filter_var($dismissed, FILTER_VALIDATE_BOOLEAN);
251
+	}
252
+
253
+
254
+
255
+	/**
256
+	 * @return CapCheckInterface
257
+	 * @throws InvalidDataTypeException
258
+	 */
259
+	public function getCapCheck()
260
+	{
261
+		if (! $this->cap_check instanceof CapCheckInterface) {
262
+			$this->setCapCheck(
263
+				new CapCheck(
264
+					$this->capability,
265
+					$this->cap_context
266
+				)
267
+			);
268
+		}
269
+		return $this->cap_check;
270
+	}
271
+
272
+
273
+
274
+	/**
275
+	 * @param CapCheckInterface $cap_check
276
+	 */
277
+	private function setCapCheck(CapCheckInterface $cap_check)
278
+	{
279
+		$this->cap_check = $cap_check;
280
+	}
281
+
282
+
283
+
284
+	/**
285
+	 * @return bool
286
+	 */
287
+	public function getPurge()
288
+	{
289
+		return $this->purge;
290
+	}
291
+
292
+
293
+
294
+	/**
295
+	 * @param bool $purge
296
+	 */
297
+	public function setPurge($purge)
298
+	{
299
+		$this->purge = filter_var($purge, FILTER_VALIDATE_BOOLEAN);
300
+	}
301
+
302
+
303
+
304
+	/**
305
+	 * given a valid PersistentAdminNotice Collection,
306
+	 * this notice will be added if it is not already found in the collection (using its name as the identifier)
307
+	 * if an existing notice is found that has already been dismissed,
308
+	 * but we are overriding with a forced update, then we will toggle its dismissed state,
309
+	 * so that the notice is displayed again
310
+	 *
311
+	 * @param Collection $persistent_admin_notice_collection
312
+	 * @throws InvalidEntityException
313
+	 */
314
+	public function registerPersistentAdminNotice(Collection $persistent_admin_notice_collection)
315
+	{
316
+		if ($this->registered) {
317
+			return;
318
+		}
319
+		// first check if this notice has already been added to the collection
320
+		if ($persistent_admin_notice_collection->has($this->name)) {
321
+			/** @var PersistentAdminNotice $existing */
322
+			$existing = $persistent_admin_notice_collection->get($this->name);
323
+			// we don't need to add it again (we can't actually)
324
+			// but if it has already been dismissed, and we are overriding with a forced update
325
+			if ($existing->getDismissed() && $this->getForceUpdate()) {
326
+				// then toggle the notice's dismissed state to true
327
+				// so that it gets displayed again
328
+				$existing->setDismissed(false);
329
+				// and make sure the message is set
330
+				$existing->setMessage($this->message);
331
+			}
332
+		} else {
333
+			$persistent_admin_notice_collection->add($this, $this->name);
334
+		}
335
+		$this->registered = true;
336
+	}
337
+
338
+
339
+
340
+	/**
341
+	 * @throws Exception
342
+	 */
343
+	public function confirmRegistered()
344
+	{
345
+		if (! $this->registered && WP_DEBUG) {
346
+			new ExceptionStackTraceDisplay(
347
+				new DomainException(
348
+					sprintf(
349
+						esc_html__(
350
+							'The "%1$s" PersistentAdminNotice was not successfully registered. Please ensure that it is being created prior to either the "admin_notices" or "network_admin_notices" hooks being triggered.',
351
+							'event_espresso'
352
+						),
353
+						$this->name
354
+					)
355
+				)
356
+			);
357
+		}
358
+	}
359 359
 
360 360
 
361 361
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Payment_Method.model.php 2 patches
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -294,15 +294,15 @@  discard block
 block discarded – undo
294 294
 
295 295
 
296 296
 
297
-    /**
298
-     * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
299
-     * but also verifies the payment method type of each is a usable object. If not,
300
-     * deactivate it, sets a notification, and deactivates it
301
-     *
302
-     * @param array $rows
303
-     * @return EE_Payment_Method[]
304
-     * @throws InvalidDataTypeException
305
-     */
297
+	/**
298
+	 * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
299
+	 * but also verifies the payment method type of each is a usable object. If not,
300
+	 * deactivate it, sets a notification, and deactivates it
301
+	 *
302
+	 * @param array $rows
303
+	 * @return EE_Payment_Method[]
304
+	 * @throws InvalidDataTypeException
305
+	 */
306 306
 	protected function _create_objects( $rows = array() ) {
307 307
 		EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
308 308
 		$payment_methods = parent::_create_objects( $rows );
@@ -319,18 +319,18 @@  discard block
 block discarded – undo
319 319
 				//only deactivate and notify the admin if the payment is active somewhere
320 320
 				$payment_method->deactivate();
321 321
 				$payment_method->save();
322
-                new PersistentAdminNotice(
323
-                    'auto-deactivated-' . $payment_method->type(),
324
-                    sprintf(
325
-                        __('The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
326
-                            'event_espresso'),
327
-                        $payment_method->admin_name(),
328
-                        '<br />',
329
-                        '<a href="' . admin_url('plugins.php') . '">',
330
-                        '</a>'
331
-                    ),
332
-                    true
333
-                );
322
+				new PersistentAdminNotice(
323
+					'auto-deactivated-' . $payment_method->type(),
324
+					sprintf(
325
+						__('The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
326
+							'event_espresso'),
327
+						$payment_method->admin_name(),
328
+						'<br />',
329
+						'<a href="' . admin_url('plugins.php') . '">',
330
+						'</a>'
331
+					),
332
+					true
333
+				);
334 334
 			}
335 335
 		}
336 336
 		return $usable_payment_methods;
Please login to merge, or discard this patch.
Spacing   +90 added lines, -90 removed lines patch added patch discarded remove patch
@@ -1,8 +1,8 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\domain\entities\notifications\PersistentAdminNotice;
2 2
 use EventEspresso\core\exceptions\InvalidDataTypeException;
3 3
 
4
-if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
5
-	exit( 'No direct script access allowed' );
4
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 /**
8 8
  *
@@ -40,33 +40,33 @@  discard block
 block discarded – undo
40 40
 	 * @access   protected
41 41
 	 * @return EEM_Payment_Method
42 42
 	 */
43
-	protected function __construct( $timezone = NULL ) {
44
-		$this->singlular_item = __( 'Payment Method', 'event_espresso' );
45
-		$this->plural_item = __( 'Payment Methods', 'event_espresso' );
46
-		$this->_tables = array( 'Payment_Method' => new EE_Primary_Table( 'esp_payment_method', 'PMD_ID' ) );
43
+	protected function __construct($timezone = NULL) {
44
+		$this->singlular_item = __('Payment Method', 'event_espresso');
45
+		$this->plural_item = __('Payment Methods', 'event_espresso');
46
+		$this->_tables = array('Payment_Method' => new EE_Primary_Table('esp_payment_method', 'PMD_ID'));
47 47
 		$this->_fields = array(
48 48
 			'Payment_Method' => array(
49
-				'PMD_ID' => new EE_Primary_Key_Int_Field( 'PMD_ID', __( "ID", 'event_espresso' ) ),
50
-				'PMD_type' => new EE_Plain_Text_Field( 'PMD_type', __( "Payment Method Type", 'event_espresso' ), FALSE, 'Admin_Only' ),
51
-				'PMD_name' => new EE_Plain_Text_Field( 'PMD_name', __( "Name", 'event_espresso' ), FALSE ),
52
-				'PMD_desc' => new EE_Post_Content_Field( 'PMD_desc', __( "Description", 'event_espresso' ), FALSE, '' ),
53
-				'PMD_admin_name' => new EE_Plain_Text_Field( 'PMD_admin_name', __( "Admin-Only Name", 'event_espresso' ), TRUE ),
54
-				'PMD_admin_desc' => new EE_Post_Content_Field( 'PMD_admin_desc', __( "Admin-Only Description", 'event_espresso' ), TRUE ),
55
-				'PMD_slug' => new EE_Slug_Field( 'PMD_slug', __( "Slug", 'event_espresso' ), FALSE ),
56
-				'PMD_order' => new EE_Integer_Field( 'PMD_order', __( "Order", 'event_espresso' ), FALSE, 0 ),
57
-				'PMD_debug_mode' => new EE_Boolean_Field( 'PMD_debug_mode', __( "Debug Mode On?", 'event_espresso' ), FALSE, FALSE ),
58
-				'PMD_wp_user' => new EE_WP_User_Field( 'PMD_wp_user', __( "Payment Method Creator ID", 'event_espresso' ), FALSE ),
59
-				'PMD_open_by_default' => new EE_Boolean_Field( 'PMD_open_by_default', __( "Open by Default?", 'event_espresso' ), FALSE, FALSE ), 'PMD_button_url' => new EE_Plain_Text_Field( 'PMD_button_url', __( "Button URL", 'event_espresso' ), TRUE, '' ),
60
-				'PMD_scope' => new EE_Serialized_Text_Field( 'PMD_scope', __( "Usable From?", 'event_espresso' ), FALSE, array() ), //possible values currently are 'CART','ADMIN','API'
49
+				'PMD_ID' => new EE_Primary_Key_Int_Field('PMD_ID', __("ID", 'event_espresso')),
50
+				'PMD_type' => new EE_Plain_Text_Field('PMD_type', __("Payment Method Type", 'event_espresso'), FALSE, 'Admin_Only'),
51
+				'PMD_name' => new EE_Plain_Text_Field('PMD_name', __("Name", 'event_espresso'), FALSE),
52
+				'PMD_desc' => new EE_Post_Content_Field('PMD_desc', __("Description", 'event_espresso'), FALSE, ''),
53
+				'PMD_admin_name' => new EE_Plain_Text_Field('PMD_admin_name', __("Admin-Only Name", 'event_espresso'), TRUE),
54
+				'PMD_admin_desc' => new EE_Post_Content_Field('PMD_admin_desc', __("Admin-Only Description", 'event_espresso'), TRUE),
55
+				'PMD_slug' => new EE_Slug_Field('PMD_slug', __("Slug", 'event_espresso'), FALSE),
56
+				'PMD_order' => new EE_Integer_Field('PMD_order', __("Order", 'event_espresso'), FALSE, 0),
57
+				'PMD_debug_mode' => new EE_Boolean_Field('PMD_debug_mode', __("Debug Mode On?", 'event_espresso'), FALSE, FALSE),
58
+				'PMD_wp_user' => new EE_WP_User_Field('PMD_wp_user', __("Payment Method Creator ID", 'event_espresso'), FALSE),
59
+				'PMD_open_by_default' => new EE_Boolean_Field('PMD_open_by_default', __("Open by Default?", 'event_espresso'), FALSE, FALSE), 'PMD_button_url' => new EE_Plain_Text_Field('PMD_button_url', __("Button URL", 'event_espresso'), TRUE, ''),
60
+				'PMD_scope' => new EE_Serialized_Text_Field('PMD_scope', __("Usable From?", 'event_espresso'), FALSE, array()), //possible values currently are 'CART','ADMIN','API'
61 61
 		) );
62 62
 		$this->_model_relations = array(
63 63
  //			'Event'=>new EE_HABTM_Relation('Event_Payment_Method'),
64 64
 			'Payment' => new EE_Has_Many_Relation(),
65
-			'Currency' => new EE_HABTM_Relation( 'Currency_Payment_Method' ),
65
+			'Currency' => new EE_HABTM_Relation('Currency_Payment_Method'),
66 66
 			'Transaction' => new EE_Has_Many_Relation(),
67 67
 			'WP_User' => new EE_Belongs_To_Relation(),
68 68
 		);
69
-		parent::__construct( $timezone );
69
+		parent::__construct($timezone);
70 70
 	}
71 71
 
72 72
 
@@ -76,8 +76,8 @@  discard block
 block discarded – undo
76 76
 	 * @param string $slug
77 77
 	 * @return EE_Payment_Method
78 78
 	 */
79
-	public function get_one_by_slug( $slug ) {
80
-		return $this->get_one( array( array( 'PMD_slug' => $slug ) ) );
79
+	public function get_one_by_slug($slug) {
80
+		return $this->get_one(array(array('PMD_slug' => $slug)));
81 81
 	}
82 82
 
83 83
 
@@ -91,8 +91,8 @@  discard block
 block discarded – undo
91 91
 		return apply_filters(
92 92
 			'FHEE__EEM_Payment_Method__scopes',
93 93
 			array(
94
-				self::scope_cart 		=> __( "Front-end Registration Page", 'event_espresso' ),
95
-				self::scope_admin 	=> __( "Admin Registration Page (no online processing)", 'event_espresso' )
94
+				self::scope_cart 		=> __("Front-end Registration Page", 'event_espresso'),
95
+				self::scope_admin 	=> __("Admin Registration Page (no online processing)", 'event_espresso')
96 96
 			)
97 97
 		);
98 98
 	}
@@ -104,9 +104,9 @@  discard block
 block discarded – undo
104 104
 	 * @param string $scope like one of EEM_Payment_Method::instance()->scopes()
105 105
 	 * @return boolean
106 106
 	 */
107
-	public function is_valid_scope( $scope ) {
107
+	public function is_valid_scope($scope) {
108 108
 		$scopes = $this->scopes();
109
-		if ( isset( $scopes[ $scope ] ) ) {
109
+		if (isset($scopes[$scope])) {
110 110
 			return TRUE;
111 111
 		} else {
112 112
 			return FALSE;
@@ -122,11 +122,11 @@  discard block
 block discarded – undo
122 122
 	 * @throws EE_Error
123 123
 	 * @return EE_Payment_Method[]
124 124
 	 */
125
-	public function get_all_active( $scope = NULL, $query_params = array() ) {
126
-		if( ! isset( $query_params[ 'order_by' ] ) && ! isset( $query_params[ 'order' ] ) ) {
127
-			$query_params['order_by'] = array( 'PMD_order' => 'ASC', 'PMD_ID' => 'ASC' );
125
+	public function get_all_active($scope = NULL, $query_params = array()) {
126
+		if ( ! isset($query_params['order_by']) && ! isset($query_params['order'])) {
127
+			$query_params['order_by'] = array('PMD_order' => 'ASC', 'PMD_ID' => 'ASC');
128 128
 		}
129
-		return $this->get_all( $this->_get_query_params_for_all_active( $scope, $query_params ) );
129
+		return $this->get_all($this->_get_query_params_for_all_active($scope, $query_params));
130 130
 	}
131 131
 
132 132
 	/**
@@ -135,8 +135,8 @@  discard block
 block discarded – undo
135 135
 	 * @param array $query_params
136 136
 	 * @return int
137 137
 	 */
138
-	public function count_active( $scope = NULL, $query_params = array() ){
139
-		return $this->count( $this->_get_query_params_for_all_active( $scope, $query_params ) );
138
+	public function count_active($scope = NULL, $query_params = array()) {
139
+		return $this->count($this->_get_query_params_for_all_active($scope, $query_params));
140 140
 	}
141 141
 
142 142
 	/**
@@ -147,21 +147,21 @@  discard block
 block discarded – undo
147 147
 	 * @return array like param of EEM_Base::get_all()
148 148
 	 * @throws EE_Error
149 149
 	 */
150
-	protected function _get_query_params_for_all_active( $scope = NULL, $query_params = array() ){
151
-		if ( $scope ) {
152
-			if ( $this->is_valid_scope( $scope ) ) {
153
-				return array_replace_recursive( array( array( 'PMD_scope' => array( 'LIKE', "%$scope%" ) ) ), $query_params );
150
+	protected function _get_query_params_for_all_active($scope = NULL, $query_params = array()) {
151
+		if ($scope) {
152
+			if ($this->is_valid_scope($scope)) {
153
+				return array_replace_recursive(array(array('PMD_scope' => array('LIKE', "%$scope%"))), $query_params);
154 154
 			} else {
155
-				throw new EE_Error( sprintf( __( "'%s' is not a valid scope for a payment method", "event_espresso" ), $scope ) );
155
+				throw new EE_Error(sprintf(__("'%s' is not a valid scope for a payment method", "event_espresso"), $scope));
156 156
 			}
157 157
 		} else {
158 158
 			$acceptable_scopes = array();
159 159
 			$count = 0;
160
-			foreach ( $this->scopes() as $scope_name => $desc ) {
160
+			foreach ($this->scopes() as $scope_name => $desc) {
161 161
 				$count++;
162
-				$acceptable_scopes[ 'PMD_scope*' . $count ] = array( 'LIKE', '%' . $scope_name . '%' );
162
+				$acceptable_scopes['PMD_scope*'.$count] = array('LIKE', '%'.$scope_name.'%');
163 163
 			}
164
-			return array_replace_recursive( array( array( 'OR*active_scope' => $acceptable_scopes ) ), $query_params );
164
+			return array_replace_recursive(array(array('OR*active_scope' => $acceptable_scopes)), $query_params);
165 165
 		}
166 166
 	}
167 167
 
@@ -173,8 +173,8 @@  discard block
 block discarded – undo
173 173
 	 * @return array like param of EEM_Base::get_all()
174 174
 	 * @throws EE_Error
175 175
 	 */
176
-	public function get_query_params_for_all_active( $scope = NULL, $query_params = array() ) {
177
-		return $this->_get_query_params_for_all_active( $scope, $query_params );
176
+	public function get_query_params_for_all_active($scope = NULL, $query_params = array()) {
177
+		return $this->_get_query_params_for_all_active($scope, $query_params);
178 178
 	}
179 179
 
180 180
 
@@ -184,8 +184,8 @@  discard block
 block discarded – undo
184 184
 	 * @param array  $query_params
185 185
 	 * @return EE_Payment_Method
186 186
 	 */
187
-	public function get_one_active( $scope = NULL, $query_params = array() ) {
188
-		return $this->get_one( $this->_get_query_params_for_all_active( $scope, $query_params ) );
187
+	public function get_one_active($scope = NULL, $query_params = array()) {
188
+		return $this->get_one($this->_get_query_params_for_all_active($scope, $query_params));
189 189
 	}
190 190
 
191 191
 
@@ -195,8 +195,8 @@  discard block
 block discarded – undo
195 195
 	 * @param string $type
196 196
 	 * @return EE_Payment_Method
197 197
 	 */
198
-	public function get_one_of_type( $type ) {
199
-		return $this->get_one( array( array( 'PMD_type' => $type ) ) );
198
+	public function get_one_of_type($type) {
199
+		return $this->get_one(array(array('PMD_type' => $type)));
200 200
 	}
201 201
 
202 202
 
@@ -209,22 +209,22 @@  discard block
 block discarded – undo
209 209
 	 * @return EE_Payment_Method
210 210
 	 * @throws EE_Error
211 211
 	 */
212
-	public function ensure_is_obj( $base_class_obj_or_id, $ensure_is_in_db = FALSE ) {
212
+	public function ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db = FALSE) {
213 213
 		//first: check if it's a slug
214
-		if( is_string( $base_class_obj_or_id ) ) {
215
-			$obj = $this->get_one_by_slug( $base_class_obj_or_id );
216
-			if( $obj ) {
214
+		if (is_string($base_class_obj_or_id)) {
215
+			$obj = $this->get_one_by_slug($base_class_obj_or_id);
216
+			if ($obj) {
217 217
 				return $obj;
218 218
 			}
219 219
 		}
220 220
 		//ok so it wasn't a slug we were passed. try the usual then (ie, it's an object or an ID)
221 221
 		try {
222
-			return parent::ensure_is_obj( $base_class_obj_or_id, $ensure_is_in_db );
222
+			return parent::ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db);
223 223
 		}
224
-		catch ( EE_Error $e ) {
224
+		catch (EE_Error $e) {
225 225
 			//handle it outside the catch
226 226
 		}
227
-		throw new EE_Error( sprintf( __( "'%s' is neither a Payment Method ID, slug, nor object.", "event_espresso" ), $base_class_obj_or_id ) );
227
+		throw new EE_Error(sprintf(__("'%s' is neither a Payment Method ID, slug, nor object.", "event_espresso"), $base_class_obj_or_id));
228 228
 	}
229 229
 
230 230
 
@@ -235,12 +235,12 @@  discard block
 block discarded – undo
235 235
 	 * @param mixed $base_obj_or_id_or_slug
236 236
 	 * @return int
237 237
 	 */
238
-	function ensure_is_ID( $base_obj_or_id_or_slug ) {
239
-		if ( is_string( $base_obj_or_id_or_slug ) ) {
238
+	function ensure_is_ID($base_obj_or_id_or_slug) {
239
+		if (is_string($base_obj_or_id_or_slug)) {
240 240
 			//assume it's a slug
241
-			$base_obj_or_id_or_slug = $this->get_one_by_slug( $base_obj_or_id_or_slug );
241
+			$base_obj_or_id_or_slug = $this->get_one_by_slug($base_obj_or_id_or_slug);
242 242
 		}
243
-		return parent::ensure_is_ID( $base_obj_or_id_or_slug );
243
+		return parent::ensure_is_ID($base_obj_or_id_or_slug);
244 244
 	}
245 245
 
246 246
 
@@ -249,36 +249,36 @@  discard block
 block discarded – undo
249 249
 	 * Verifies the button urls on all the passed payment methods have a valid button url. If not, resets them to their default.
250 250
 	 * @param EE_Payment_Method[] $payment_methods. If NULL is provided defaults to all payment methods active in the cart
251 251
 	 */
252
-	function verify_button_urls( $payment_methods = NULL ) {
253
-		$payment_methods = is_array( $payment_methods ) ? $payment_methods : $this->get_all_active(EEM_Payment_Method::scope_cart);
254
-		foreach ( $payment_methods as $payment_method ) {
252
+	function verify_button_urls($payment_methods = NULL) {
253
+		$payment_methods = is_array($payment_methods) ? $payment_methods : $this->get_all_active(EEM_Payment_Method::scope_cart);
254
+		foreach ($payment_methods as $payment_method) {
255 255
 			try {
256 256
 				$current_button_url = $payment_method->button_url();
257
-				$buttons_urls_to_try = apply_filters( 'FHEE__EEM_Payment_Method__verify_button_urls__button_urls_to_try', array(
258
-					'current_ssl' => str_replace( "http://", "https://", $current_button_url ),
259
-					'current' => str_replace( "https://", "http://", $current_button_url ),
260
-					'default_ssl' => str_replace( "http://", "https://", $payment_method->type_obj()->default_button_url() ),
261
-					'default' => str_replace( "https://", "http://", $payment_method->type_obj()->default_button_url() ),
262
-				) );
263
-				foreach( $buttons_urls_to_try as $button_url_to_try ) {
264
-					if(
257
+				$buttons_urls_to_try = apply_filters('FHEE__EEM_Payment_Method__verify_button_urls__button_urls_to_try', array(
258
+					'current_ssl' => str_replace("http://", "https://", $current_button_url),
259
+					'current' => str_replace("https://", "http://", $current_button_url),
260
+					'default_ssl' => str_replace("http://", "https://", $payment_method->type_obj()->default_button_url()),
261
+					'default' => str_replace("https://", "http://", $payment_method->type_obj()->default_button_url()),
262
+				));
263
+				foreach ($buttons_urls_to_try as $button_url_to_try) {
264
+					if (
265 265
 							(//this is the current url and it exists, regardless of SSL issues
266 266
 								$button_url_to_try == $current_button_url &&
267 267
 								EEH_URL::remote_file_exists(
268 268
 										$button_url_to_try,
269 269
 										array(
270 270
 											'sslverify' => false,
271
-											'limit_response_size' => 4095,//we don't really care for a full response, but we do want headers at least. Lets just ask for a one block
271
+											'limit_response_size' => 4095, //we don't really care for a full response, but we do want headers at least. Lets just ask for a one block
272 272
 											) )
273 273
 							)
274 274
 							||
275 275
 							(//this is NOT the current url and it exists with a working SSL cert
276 276
 								$button_url_to_try != $current_button_url &&
277
-								EEH_URL::remote_file_exists( $button_url_to_try )
277
+								EEH_URL::remote_file_exists($button_url_to_try)
278 278
 							) ) {
279
-						if( $current_button_url != $button_url_to_try ){
280
-							$payment_method->save( array( 'PMD_button_url' => $button_url_to_try ) );
281
-							EE_Error::add_attention( sprintf( __( "Payment Method %s's button url was set to %s, because the old image either didnt exist or SSL was recently enabled.", "event_espresso" ), $payment_method->name(), $button_url_to_try ) );
279
+						if ($current_button_url != $button_url_to_try) {
280
+							$payment_method->save(array('PMD_button_url' => $button_url_to_try));
281
+							EE_Error::add_attention(sprintf(__("Payment Method %s's button url was set to %s, because the old image either didnt exist or SSL was recently enabled.", "event_espresso"), $payment_method->name(), $button_url_to_try));
282 282
 						}
283 283
 						//this image exists. So if wasn't set before, now it is;
284 284
 						//or if it was already set, we have nothing to do
@@ -286,8 +286,8 @@  discard block
 block discarded – undo
286 286
 					}
287 287
 				}
288 288
 			}
289
-			catch ( EE_Error $e ) {
290
-				$payment_method->set_active( FALSE );
289
+			catch (EE_Error $e) {
290
+				$payment_method->set_active(FALSE);
291 291
 			}
292 292
 		}
293 293
 	}
@@ -303,30 +303,30 @@  discard block
 block discarded – undo
303 303
      * @return EE_Payment_Method[]
304 304
      * @throws InvalidDataTypeException
305 305
      */
306
-	protected function _create_objects( $rows = array() ) {
307
-		EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
308
-		$payment_methods = parent::_create_objects( $rows );
306
+	protected function _create_objects($rows = array()) {
307
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
308
+		$payment_methods = parent::_create_objects($rows);
309 309
 		/* @var $payment_methods EE_Payment_Method[] */
310 310
 		$usable_payment_methods = array();
311
-		foreach ( $payment_methods as $key => $payment_method ) {
312
-			if ( EE_Payment_Method_Manager::instance()->payment_method_type_exists( $payment_method->type() ) ) {
313
-				$usable_payment_methods[ $key ] = $payment_method;
311
+		foreach ($payment_methods as $key => $payment_method) {
312
+			if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($payment_method->type())) {
313
+				$usable_payment_methods[$key] = $payment_method;
314 314
 				//some payment methods enqueue their scripts in EE_PMT_*::__construct
315 315
 				//which is kinda a no-no (just because it's being constructed doesn't mean we need to enqueue
316 316
 				//its scripts). but for backwards-compat we should continue to do that
317 317
 				$payment_method->type_obj();
318
-			} elseif( $payment_method->active() ) {
318
+			} elseif ($payment_method->active()) {
319 319
 				//only deactivate and notify the admin if the payment is active somewhere
320 320
 				$payment_method->deactivate();
321 321
 				$payment_method->save();
322 322
                 new PersistentAdminNotice(
323
-                    'auto-deactivated-' . $payment_method->type(),
323
+                    'auto-deactivated-'.$payment_method->type(),
324 324
                     sprintf(
325 325
                         __('The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
326 326
                             'event_espresso'),
327 327
                         $payment_method->admin_name(),
328 328
                         '<br />',
329
-                        '<a href="' . admin_url('plugins.php') . '">',
329
+                        '<a href="'.admin_url('plugins.php').'">',
330 330
                         '</a>'
331 331
                     ),
332 332
                     true
@@ -346,11 +346,11 @@  discard block
 block discarded – undo
346 346
 	 * @param string 	$scope @see EEM_Payment_Method::get_all_for_events
347 347
 	 * @return EE_Payment_Method[]
348 348
 	 */
349
-	public function get_all_for_transaction( $transaction, $scope ) {
349
+	public function get_all_for_transaction($transaction, $scope) {
350 350
 		//give addons a chance to override what payment methods are chosen based on the transaction
351 351
 		return apply_filters(
352 352
 			'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
353
-			$this->get_all_active( $scope, array( 'group_by' => 'PMD_type' ) ),
353
+			$this->get_all_active($scope, array('group_by' => 'PMD_type')),
354 354
 			$transaction,
355 355
 			$scope
356 356
 		);
@@ -366,16 +366,16 @@  discard block
 block discarded – undo
366 366
 	 * @param EE_Registration|int $registration_or_reg_id  Either the EE_Registration object or the id for the registration.
367 367
 	 * @return EE_Payment|null
368 368
 	 */
369
-	public function get_last_used_for_registration( $registration_or_reg_id ) {
370
-		$registration_id = EEM_Registration::instance()->ensure_is_ID( $registration_or_reg_id );
369
+	public function get_last_used_for_registration($registration_or_reg_id) {
370
+		$registration_id = EEM_Registration::instance()->ensure_is_ID($registration_or_reg_id);
371 371
 
372 372
 		$query_params = array(
373 373
 			0 => array(
374 374
 				'Payment.Registration.REG_ID' => $registration_id,
375 375
 			),
376
-			'order_by' => array( 'Payment.PAY_ID' => 'DESC' )
376
+			'order_by' => array('Payment.PAY_ID' => 'DESC')
377 377
 		);
378
-		return $this->get_one( $query_params );
378
+		return $this->get_one($query_params);
379 379
 	}
380 380
 
381 381
 }
Please login to merge, or discard this patch.
admin_pages/maintenance/Maintenance_Admin_Page.core.php 2 patches
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -262,13 +262,13 @@  discard block
 block discarded – undo
262 262
                 && $most_recent_migration->is_broken()
263 263
             )
264 264
         ) {
265
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
265
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_was_borked_page.template.php';
266 266
             $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
267 267
             $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
268 268
                                                                                         'success' => '0',
269 269
             ), EE_MAINTENANCE_ADMIN_URL);
270 270
         } elseif ($addons_should_be_upgraded_first) {
271
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
271
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_upgrade_addons_before_migrating.template.php';
272 272
         } else {
273 273
             if ($most_recent_migration
274 274
                 && $most_recent_migration instanceof EE_Data_Migration_Script_Base
@@ -298,7 +298,7 @@  discard block
 block discarded – undo
298 298
                 $this->_template_args['current_db_state'] = null;
299 299
                 $this->_template_args['next_db_state'] = null;
300 300
             }
301
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
301
+            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_migration_page.template.php';
302 302
             $this->_template_args = array_merge(
303 303
                 $this->_template_args,
304 304
                 array(
@@ -326,13 +326,13 @@  discard block
 block discarded – undo
326 326
             );
327 327
             //make sure we have the form fields helper available. It usually is, but sometimes it isn't
328 328
         }
329
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
329
+        $this->_template_args['most_recent_migration'] = $most_recent_migration; //the actual most recently ran migration
330 330
         //now render the migration options part, and put it in a variable
331 331
         $migration_options_template_file = apply_filters(
332 332
             'FHEE__ee_migration_page__migration_options_template',
333
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
333
+            EE_MAINTENANCE_TEMPLATE_PATH.'migration_options_from_ee4.template.php'
334 334
         );
335
-        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
335
+        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args, true);
336 336
         $this->_template_args['migration_options_html'] = $migration_options_html;
337 337
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
338 338
             $this->_template_args, true);
@@ -391,7 +391,7 @@  discard block
 block discarded – undo
391 391
      */
392 392
     public function _data_reset_and_delete()
393 393
     {
394
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
394
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_data_reset_and_delete.template.php';
395 395
         $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
396 396
             'reset_reservations',
397 397
             'reset_reservations',
@@ -428,7 +428,7 @@  discard block
 block discarded – undo
428 428
 
429 429
     protected function _reset_reservations()
430 430
     {
431
-        if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
431
+        if (\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
432 432
             EE_Error::add_success(
433 433
                 __(
434 434
                     'Ticket and datetime reserved counts have been successfully reset.',
@@ -476,7 +476,7 @@  discard block
 block discarded – undo
476 476
      */
477 477
     public function _system_status()
478 478
     {
479
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
479
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_system_stati_page.template.php';
480 480
         $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
481 481
         $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
482 482
             array(
@@ -495,11 +495,11 @@  discard block
 block discarded – undo
495 495
     public function _download_system_status()
496 496
     {
497 497
         $status_info = EEM_System_Status::instance()->get_system_stati();
498
-        header( 'Content-Disposition: attachment' );
499
-        header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
498
+        header('Content-Disposition: attachment');
499
+        header("Content-Disposition: attachment; filename=system_status_".sanitize_key(site_url()).".html");
500 500
         echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
501
-        echo "<h1>System Information for " . site_url() . "</h1>";
502
-        echo EEH_Template::layout_array_as_table( $status_info );
501
+        echo "<h1>System Information for ".site_url()."</h1>";
502
+        echo EEH_Template::layout_array_as_table($status_info);
503 503
         die;
504 504
     }
505 505
 
@@ -513,7 +513,7 @@  discard block
 block discarded – undo
513 513
         try {
514 514
             $success = wp_mail(EE_SUPPORT_EMAIL,
515 515
                 'Migration Crash Report',
516
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
516
+                $body."/r/n<br>".print_r(EEM_System_Status::instance()->get_system_stati(), true),
517 517
                 array(
518 518
                     "from:$from_name<$from>",
519 519
                     //					'content-type:text/html charset=UTF-8'
@@ -548,7 +548,7 @@  discard block
 block discarded – undo
548 548
             EE_MAINTENANCE_ADMIN_URL);
549 549
         $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
550 550
             EE_MAINTENANCE_ADMIN_URL);
551
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
551
+        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH.'ee_confirm_migration_crash_report_sent.template.php';
552 552
         $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
553 553
             $this->_template_args, true);
554 554
         $this->display_admin_page_with_sidebar();
@@ -649,9 +649,9 @@  discard block
 block discarded – undo
649 649
         wp_enqueue_script('ee_admin_js');
650 650
 //		wp_enqueue_media();
651 651
 //		wp_enqueue_script('media-upload');
652
-        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'),
652
+        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL.'ee-maintenance.js', array('jquery'),
653 653
             EVENT_ESPRESSO_VERSION, true);
654
-        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
654
+        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL.'ee-maintenance.css', array(),
655 655
             EVENT_ESPRESSO_VERSION);
656 656
         wp_enqueue_style('espresso_maintenance');
657 657
         //localize script stuff
@@ -718,8 +718,8 @@  discard block
 block discarded – undo
718 718
 
719 719
     protected function _get_datetime_offset_fix_form()
720 720
     {
721
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
722
-            $this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
721
+        if ( ! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
722
+            $this->datetime_fix_offset_form = new EE_Form_Section_Proper(
723 723
                 array(
724 724
                     'name' => 'datetime_offset_fix_option',
725 725
                     'layout_strategy' => new EE_Admin_Two_Column_Layout(),
@@ -823,12 +823,12 @@  discard block
 block discarded – undo
823 823
                 $utc_timezone = new DateTimeZone('UTC');
824 824
                 $date_range_start_date = DateTime::createFromFormat(
825 825
                     'm/d/Y H:i:s',
826
-                    $form->get_input_value('date_range_start_date') . ' 00:00:00',
826
+                    $form->get_input_value('date_range_start_date').' 00:00:00',
827 827
                     $utc_timezone
828 828
                 );
829 829
                 $date_range_end_date = DateTime::createFromFormat(
830 830
                         'm/d/Y H:i:s',
831
-                        $form->get_input_value('date_range_end_date') . ' 23:59:59',
831
+                        $form->get_input_value('date_range_end_date').' 23:59:59',
832 832
                         $utc_timezone
833 833
                 );
834 834
                 if ($date_range_start_date instanceof DateTime) {
Please login to merge, or discard this patch.
Indentation   +827 added lines, -827 removed lines patch added patch discarded remove patch
@@ -29,843 +29,843 @@
 block discarded – undo
29 29
 {
30 30
 
31 31
 
32
-    /**
33
-     * @var EE_Datetime_Offset_Fix_Form
34
-     */
35
-    protected $datetime_fix_offset_form;
36
-
37
-
38
-
39
-    protected function _init_page_props()
40
-    {
41
-        $this->page_slug = EE_MAINTENANCE_PG_SLUG;
42
-        $this->page_label = EE_MAINTENANCE_LABEL;
43
-        $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL;
44
-        $this->_admin_base_path = EE_MAINTENANCE_ADMIN;
45
-    }
46
-
47
-
48
-
49
-    protected function _ajax_hooks()
50
-    {
51
-        add_action('wp_ajax_migration_step', array($this, 'migration_step'));
52
-        add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran'));
53
-    }
54
-
55
-
56
-
57
-    protected function _define_page_props()
58
-    {
59
-        $this->_admin_page_title = EE_MAINTENANCE_LABEL;
60
-        $this->_labels = array(
61
-            'buttons' => array(
62
-                'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
63
-                'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
64
-            ),
65
-        );
66
-    }
67
-
68
-
69
-
70
-    protected function _set_page_routes()
71
-    {
72
-        $this->_page_routes = array(
73
-            'default'                             => array(
74
-                'func'       => '_maintenance',
75
-                'capability' => 'manage_options',
76
-            ),
77
-            'change_maintenance_level'            => array(
78
-                'func'       => '_change_maintenance_level',
79
-                'capability' => 'manage_options',
80
-                'noheader'   => true,
81
-            ),
82
-            'system_status'                       => array(
83
-                'func'       => '_system_status',
84
-                'capability' => 'manage_options',
85
-            ),
86
-            'download_system_status' => array(
87
-                'func'       => '_download_system_status',
88
-                'capability' => 'manage_options',
89
-                'noheader'   => true,
90
-            ),
91
-            'send_migration_crash_report'         => array(
92
-                'func'       => '_send_migration_crash_report',
93
-                'capability' => 'manage_options',
94
-                'noheader'   => true,
95
-            ),
96
-            'confirm_migration_crash_report_sent' => array(
97
-                'func'       => '_confirm_migration_crash_report_sent',
98
-                'capability' => 'manage_options',
99
-            ),
100
-            'data_reset'                          => array(
101
-                'func'       => '_data_reset_and_delete',
102
-                'capability' => 'manage_options',
103
-            ),
104
-            'reset_db'                            => array(
105
-                'func'       => '_reset_db',
106
-                'capability' => 'manage_options',
107
-                'noheader'   => true,
108
-                'args'       => array('nuke_old_ee4_data' => true),
109
-            ),
110
-            'start_with_fresh_ee4_db'             => array(
111
-                'func'       => '_reset_db',
112
-                'capability' => 'manage_options',
113
-                'noheader'   => true,
114
-                'args'       => array('nuke_old_ee4_data' => false),
115
-            ),
116
-            'delete_db'                           => array(
117
-                'func'       => '_delete_db',
118
-                'capability' => 'manage_options',
119
-                'noheader'   => true,
120
-            ),
121
-            'rerun_migration_from_ee3'            => array(
122
-                'func'       => '_rerun_migration_from_ee3',
123
-                'capability' => 'manage_options',
124
-                'noheader'   => true,
125
-            ),
126
-            'reset_reservations'                  => array(
127
-                'func'       => '_reset_reservations',
128
-                'capability' => 'manage_options',
129
-                'noheader'   => true,
130
-            ),
131
-            'reset_capabilities'                  => array(
132
-                'func'       => '_reset_capabilities',
133
-                'capability' => 'manage_options',
134
-                'noheader'   => true,
135
-            ),
136
-            'reattempt_migration'                 => array(
137
-                'func'       => '_reattempt_migration',
138
-                'capability' => 'manage_options',
139
-                'noheader'   => true,
140
-            ),
141
-            'datetime_tools' => array(
142
-                'func' => '_datetime_tools',
143
-                'capability' => 'manage_options'
144
-            ),
145
-            'run_datetime_offset_fix' => array(
146
-                'func' => '_apply_datetime_offset',
147
-                'noheader' => true,
148
-                'headers_sent_route' => 'datetime_tools',
149
-                'capability' => 'manage_options'
150
-            )
151
-        );
152
-    }
153
-
154
-
155
-
156
-    protected function _set_page_config()
157
-    {
158
-        $this->_page_config = array(
159
-            'default'       => array(
160
-                'nav'           => array(
161
-                    'label' => esc_html__('Maintenance', 'event_espresso'),
162
-                    'order' => 10,
163
-                ),
164
-                'require_nonce' => false,
165
-            ),
166
-            'data_reset'    => array(
167
-                'nav'           => array(
168
-                    'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
169
-                    'order' => 20,
170
-                ),
171
-                'require_nonce' => false,
172
-            ),
173
-            'datetime_tools' => array(
174
-                'nav' => array(
175
-                    'label' => esc_html__('Datetime Utilities', 'event_espresso'),
176
-                    'order' => 25
177
-                ),
178
-                'require_nonce' => false,
179
-            ),
180
-            'system_status' => array(
181
-                'nav'           => array(
182
-                    'label' => esc_html__("System Information", "event_espresso"),
183
-                    'order' => 30,
184
-                ),
185
-                'require_nonce' => false,
186
-            ),
187
-        );
188
-    }
189
-
190
-
191
-
192
-    /**
193
-     * default maintenance page. If we're in maintenance mode level 2, then we need to show
194
-     * the migration scripts and all that UI.
195
-     */
196
-    public function _maintenance()
197
-    {
198
-        //it all depends if we're in maintenance model level 1 (frontend-only) or
199
-        //level 2 (everything except maintenance page)
200
-        try {
201
-            //get the current maintenance level and check if
202
-            //we are removed
203
-            $mm = EE_Maintenance_Mode::instance()->level();
204
-            $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
205
-            if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) {
206
-                //we just took the site out of maintenance mode, so notify the user.
207
-                //unfortunately this message appears to be echoed on the NEXT page load...
208
-                //oh well, we should really be checking for this on addon deactivation anyways
209
-                EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required',
210
-                    'event_espresso'));
211
-                $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
212
-            }
213
-            //in case an exception is thrown while trying to handle migrations
214
-            switch (EE_Maintenance_Mode::instance()->level()) {
215
-                case EE_Maintenance_Mode::level_0_not_in_maintenance:
216
-                case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
217
-                    $show_maintenance_switch = true;
218
-                    $show_backup_db_text = false;
219
-                    $show_migration_progress = false;
220
-                    $script_names = array();
221
-                    $addons_should_be_upgraded_first = false;
222
-                    break;
223
-                case EE_Maintenance_Mode::level_2_complete_maintenance:
224
-                    $show_maintenance_switch = false;
225
-                    $show_migration_progress = true;
226
-                    if (isset($this->_req_data['continue_migration'])) {
227
-                        $show_backup_db_text = false;
228
-                    } else {
229
-                        $show_backup_db_text = true;
230
-                    }
231
-                    $scripts_needing_to_run = EE_Data_Migration_Manager::instance()
232
-                                                                       ->check_for_applicable_data_migration_scripts();
233
-                    $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
234
-                    $script_names = array();
235
-                    $current_script = null;
236
-                    foreach ($scripts_needing_to_run as $script) {
237
-                        if ($script instanceof EE_Data_Migration_Script_Base) {
238
-                            if ( ! $current_script) {
239
-                                $current_script = $script;
240
-                                $current_script->migration_page_hooks();
241
-                            }
242
-                            $script_names[] = $script->pretty_name();
243
-                        }
244
-                    }
245
-                    break;
246
-            }
247
-            $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
248
-            $exception_thrown = false;
249
-        } catch (EE_Error $e) {
250
-            EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
251
-            //now, just so we can display the page correctly, make a error migration script stage object
252
-            //and also put the error on it. It only persists for the duration of this request
253
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
254
-            $most_recent_migration->add_error($e->getMessage());
255
-            $exception_thrown = true;
256
-        }
257
-        $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
258
-        $current_db_state = str_replace('.decaf', '', $current_db_state);
259
-        if ($exception_thrown
260
-            || ($most_recent_migration
261
-                && $most_recent_migration instanceof EE_Data_Migration_Script_Base
262
-                && $most_recent_migration->is_broken()
263
-            )
264
-        ) {
265
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
266
-            $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
267
-            $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
268
-                                                                                        'success' => '0',
269
-            ), EE_MAINTENANCE_ADMIN_URL);
270
-        } elseif ($addons_should_be_upgraded_first) {
271
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
272
-        } else {
273
-            if ($most_recent_migration
274
-                && $most_recent_migration instanceof EE_Data_Migration_Script_Base
275
-                && $most_recent_migration->can_continue()
276
-            ) {
277
-                $show_backup_db_text = false;
278
-                $show_continue_current_migration_script = true;
279
-                $show_most_recent_migration = true;
280
-            } elseif (isset($this->_req_data['continue_migration'])) {
281
-                $show_most_recent_migration = true;
282
-                $show_continue_current_migration_script = false;
283
-            } else {
284
-                $show_most_recent_migration = false;
285
-                $show_continue_current_migration_script = false;
286
-            }
287
-            if (isset($current_script)) {
288
-                $migrates_to = $current_script->migrates_to_version();
289
-                $plugin_slug = $migrates_to['slug'];
290
-                $new_version = $migrates_to['version'];
291
-                $this->_template_args = array_merge($this->_template_args, array(
292
-                    'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"),
293
-                        isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug),
294
-                    'next_db_state'    => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'),
295
-                        $new_version, $plugin_slug) : null,
296
-                ));
297
-            } else {
298
-                $this->_template_args['current_db_state'] = null;
299
-                $this->_template_args['next_db_state'] = null;
300
-            }
301
-            $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
302
-            $this->_template_args = array_merge(
303
-                $this->_template_args,
304
-                array(
305
-                    'show_most_recent_migration'             => $show_most_recent_migration,
306
-                    //flag for showing the most recent migration's status and/or errors
307
-                    'show_migration_progress'                => $show_migration_progress,
308
-                    //flag for showing the option to run migrations and see their progress
309
-                    'show_backup_db_text'                    => $show_backup_db_text,
310
-                    //flag for showing text telling the user to backup their DB
311
-                    'show_maintenance_switch'                => $show_maintenance_switch,
312
-                    //flag for showing the option to change maintenance mode between levels 0 and 1
313
-                    'script_names'                           => $script_names,
314
-                    //array of names of scripts that have run
315
-                    'show_continue_current_migration_script' => $show_continue_current_migration_script,
316
-                    //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
317
-                    'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
318
-                        EE_MAINTENANCE_ADMIN_URL),
319
-                    'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
320
-                        EE_MAINTENANCE_ADMIN_URL),
321
-                    'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'),
322
-                        EE_MAINTENANCE_ADMIN_URL),
323
-                    'ultimate_db_state'                      => sprintf(__("EE%s", 'event_espresso'),
324
-                        espresso_version()),
325
-                )
326
-            );
327
-            //make sure we have the form fields helper available. It usually is, but sometimes it isn't
328
-        }
329
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
330
-        //now render the migration options part, and put it in a variable
331
-        $migration_options_template_file = apply_filters(
332
-            'FHEE__ee_migration_page__migration_options_template',
333
-            EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
334
-        );
335
-        $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
336
-        $this->_template_args['migration_options_html'] = $migration_options_html;
337
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
338
-            $this->_template_args, true);
339
-        $this->display_admin_page_with_sidebar();
340
-    }
341
-
342
-
343
-
344
-    /**
345
-     * returns JSON and executes another step of the currently-executing data migration (called via ajax)
346
-     */
347
-    public function migration_step()
348
-    {
349
-        $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request();
350
-        $this->_return_json();
351
-    }
352
-
353
-
354
-
355
-    /**
356
-     * Can be used by js when it notices a response with HTML in it in order
357
-     * to log the malformed response
358
-     */
359
-    public function add_error_to_migrations_ran()
360
-    {
361
-        EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']);
362
-        $this->_template_args['data'] = array('ok' => true);
363
-        $this->_return_json();
364
-    }
365
-
366
-
367
-
368
-    /**
369
-     * changes the maintenance level, provided there are still no migration scripts that should run
370
-     */
371
-    public function _change_maintenance_level()
372
-    {
373
-        $new_level = absint($this->_req_data['maintenance_mode_level']);
374
-        if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) {
375
-            EE_Maintenance_Mode::instance()->set_maintenance_level($new_level);
376
-            $success = true;
377
-        } else {
378
-            EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
379
-            $success = false;
380
-        }
381
-        $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
382
-    }
383
-
384
-
385
-
386
-    /**
387
-     * a tab with options for resetting and/or deleting EE data
388
-     *
389
-     * @throws \EE_Error
390
-     * @throws \DomainException
391
-     */
392
-    public function _data_reset_and_delete()
393
-    {
394
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
395
-        $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
396
-            'reset_reservations',
397
-            'reset_reservations',
398
-            array(),
399
-            'button button-primary ee-confirm',
400
-            '',
401
-            false
402
-        );
403
-        $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
404
-            'reset_capabilities',
405
-            'reset_capabilities',
406
-            array(),
407
-            'button button-primary ee-confirm',
408
-            '',
409
-            false
410
-        );
411
-        $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
412
-            array('action' => 'delete_db'),
413
-            EE_MAINTENANCE_ADMIN_URL
414
-        );
415
-        $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
416
-            array('action' => 'reset_db'),
417
-            EE_MAINTENANCE_ADMIN_URL
418
-        );
419
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
420
-            $this->_template_path,
421
-            $this->_template_args,
422
-            true
423
-        );
424
-        $this->display_admin_page_with_sidebar();
425
-    }
426
-
427
-
428
-
429
-    protected function _reset_reservations()
430
-    {
431
-        if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
432
-            EE_Error::add_success(
433
-                __(
434
-                    'Ticket and datetime reserved counts have been successfully reset.',
435
-                    'event_espresso'
436
-                )
437
-            );
438
-        } else {
439
-            EE_Error::add_success(
440
-                __(
441
-                    'Ticket and datetime reserved counts were correct and did not need resetting.',
442
-                    'event_espresso'
443
-                )
444
-            );
445
-        }
446
-        $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true);
447
-    }
448
-
449
-
450
-
451
-    protected function _reset_capabilities()
452
-    {
453
-        EE_Registry::instance()->CAP->init_caps(true);
454
-        EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.',
455
-            'event_espresso'));
456
-        $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true);
457
-    }
458
-
459
-
460
-
461
-    /**
462
-     * resets the DMSs so we can attempt to continue migrating after a fatal error
463
-     * (only a good idea when someone has somehow tried ot fix whatever caused
464
-     * the fatal error in teh first place)
465
-     */
466
-    protected function _reattempt_migration()
467
-    {
468
-        EE_Data_Migration_Manager::instance()->reattempt();
469
-        $this->_redirect_after_action(false, '', '', array('action' => 'default'), true);
470
-    }
471
-
472
-
473
-
474
-    /**
475
-     * shows the big ol' System Information page
476
-     */
477
-    public function _system_status()
478
-    {
479
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
480
-        $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
481
-        $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
482
-            array(
483
-                'action' => 'download_system_status',
484
-            ),
485
-            EE_MAINTENANCE_ADMIN_URL
486
-        );
487
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
488
-            $this->_template_args, true);
489
-        $this->display_admin_page_with_sidebar();
490
-    }
491
-
492
-    /**
493
-     * Downloads an HTML file of the system status that can be easily stored or emailed
494
-     */
495
-    public function _download_system_status()
496
-    {
497
-        $status_info = EEM_System_Status::instance()->get_system_stati();
498
-        header( 'Content-Disposition: attachment' );
499
-        header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
500
-        echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
501
-        echo "<h1>System Information for " . site_url() . "</h1>";
502
-        echo EEH_Template::layout_array_as_table( $status_info );
503
-        die;
504
-    }
505
-
506
-
507
-
508
-    public function _send_migration_crash_report()
509
-    {
510
-        $from = $this->_req_data['from'];
511
-        $from_name = $this->_req_data['from_name'];
512
-        $body = $this->_req_data['body'];
513
-        try {
514
-            $success = wp_mail(EE_SUPPORT_EMAIL,
515
-                'Migration Crash Report',
516
-                $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
517
-                array(
518
-                    "from:$from_name<$from>",
519
-                    //					'content-type:text/html charset=UTF-8'
520
-                ));
521
-        } catch (Exception $e) {
522
-            $success = false;
523
-        }
524
-        $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"),
525
-            esc_html__("sent", "event_espresso"),
526
-            array('success' => $success, 'action' => 'confirm_migration_crash_report_sent'));
527
-    }
528
-
529
-
530
-
531
-    public function _confirm_migration_crash_report_sent()
532
-    {
533
-        try {
534
-            $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
535
-        } catch (EE_Error $e) {
536
-            EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
537
-            //now, just so we can display the page correctly, make a error migration script stage object
538
-            //and also put the error on it. It only persists for the duration of this request
539
-            $most_recent_migration = new EE_DMS_Unknown_1_0_0();
540
-            $most_recent_migration->add_error($e->getMessage());
541
-        }
542
-        $success = $this->_req_data['success'] == '1' ? true : false;
543
-        $this->_template_args['success'] = $success;
544
-        $this->_template_args['most_recent_migration'] = $most_recent_migration;
545
-        $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
546
-            EE_MAINTENANCE_ADMIN_URL);
547
-        $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
548
-            EE_MAINTENANCE_ADMIN_URL);
549
-        $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
550
-            EE_MAINTENANCE_ADMIN_URL);
551
-        $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
552
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
553
-            $this->_template_args, true);
554
-        $this->display_admin_page_with_sidebar();
555
-    }
556
-
557
-
558
-
559
-    /**
560
-     * Resets the entire EE4 database.
561
-     * Currently basically only sets up ee4 database for a fresh install- doesn't
562
-     * actually clean out the old wp options, or cpts (although does erase old ee table data)
563
-     *
564
-     * @param boolean $nuke_old_ee4_data controls whether or not we
565
-     *                                   destroy the old ee4 data, or just try initializing ee4 default data
566
-     */
567
-    public function _reset_db($nuke_old_ee4_data = true)
568
-    {
569
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
570
-        if ($nuke_old_ee4_data) {
571
-            EEH_Activation::delete_all_espresso_cpt_data();
572
-            EEH_Activation::delete_all_espresso_tables_and_data(false);
573
-            EEH_Activation::remove_cron_tasks();
574
-        }
575
-        //make sure when we reset the registry's config that it
576
-        //switches to using the new singleton
577
-        EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
578
-        EE_System::instance()->initialize_db_if_no_migrations_required(true);
579
-        EE_System::instance()->redirect_to_about_ee();
580
-    }
581
-
582
-
583
-
584
-    /**
585
-     * Deletes ALL EE tables, Records, and Options from the database.
586
-     */
587
-    public function _delete_db()
588
-    {
589
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
590
-        EEH_Activation::delete_all_espresso_cpt_data();
591
-        EEH_Activation::delete_all_espresso_tables_and_data();
592
-        EEH_Activation::remove_cron_tasks();
593
-        EEH_Activation::deactivate_event_espresso();
594
-        wp_safe_redirect(admin_url('plugins.php'));
595
-        exit;
596
-    }
597
-
598
-
599
-
600
-    /**
601
-     * sets up EE4 to rerun the migrations from ee3 to ee4
602
-     */
603
-    public function _rerun_migration_from_ee3()
604
-    {
605
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
606
-        EEH_Activation::delete_all_espresso_cpt_data();
607
-        EEH_Activation::delete_all_espresso_tables_and_data(false);
608
-        //set the db state to something that will require migrations
609
-        update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
610
-        EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance);
611
-        $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso'));
612
-    }
613
-
614
-
615
-
616
-    //none of the below group are currently used for Gateway Settings
617
-    protected function _add_screen_options()
618
-    {
619
-    }
620
-
621
-
622
-
623
-    protected function _add_feature_pointers()
624
-    {
625
-    }
626
-
32
+	/**
33
+	 * @var EE_Datetime_Offset_Fix_Form
34
+	 */
35
+	protected $datetime_fix_offset_form;
36
+
37
+
38
+
39
+	protected function _init_page_props()
40
+	{
41
+		$this->page_slug = EE_MAINTENANCE_PG_SLUG;
42
+		$this->page_label = EE_MAINTENANCE_LABEL;
43
+		$this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL;
44
+		$this->_admin_base_path = EE_MAINTENANCE_ADMIN;
45
+	}
46
+
47
+
48
+
49
+	protected function _ajax_hooks()
50
+	{
51
+		add_action('wp_ajax_migration_step', array($this, 'migration_step'));
52
+		add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran'));
53
+	}
54
+
55
+
56
+
57
+	protected function _define_page_props()
58
+	{
59
+		$this->_admin_page_title = EE_MAINTENANCE_LABEL;
60
+		$this->_labels = array(
61
+			'buttons' => array(
62
+				'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'),
63
+				'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'),
64
+			),
65
+		);
66
+	}
67
+
68
+
69
+
70
+	protected function _set_page_routes()
71
+	{
72
+		$this->_page_routes = array(
73
+			'default'                             => array(
74
+				'func'       => '_maintenance',
75
+				'capability' => 'manage_options',
76
+			),
77
+			'change_maintenance_level'            => array(
78
+				'func'       => '_change_maintenance_level',
79
+				'capability' => 'manage_options',
80
+				'noheader'   => true,
81
+			),
82
+			'system_status'                       => array(
83
+				'func'       => '_system_status',
84
+				'capability' => 'manage_options',
85
+			),
86
+			'download_system_status' => array(
87
+				'func'       => '_download_system_status',
88
+				'capability' => 'manage_options',
89
+				'noheader'   => true,
90
+			),
91
+			'send_migration_crash_report'         => array(
92
+				'func'       => '_send_migration_crash_report',
93
+				'capability' => 'manage_options',
94
+				'noheader'   => true,
95
+			),
96
+			'confirm_migration_crash_report_sent' => array(
97
+				'func'       => '_confirm_migration_crash_report_sent',
98
+				'capability' => 'manage_options',
99
+			),
100
+			'data_reset'                          => array(
101
+				'func'       => '_data_reset_and_delete',
102
+				'capability' => 'manage_options',
103
+			),
104
+			'reset_db'                            => array(
105
+				'func'       => '_reset_db',
106
+				'capability' => 'manage_options',
107
+				'noheader'   => true,
108
+				'args'       => array('nuke_old_ee4_data' => true),
109
+			),
110
+			'start_with_fresh_ee4_db'             => array(
111
+				'func'       => '_reset_db',
112
+				'capability' => 'manage_options',
113
+				'noheader'   => true,
114
+				'args'       => array('nuke_old_ee4_data' => false),
115
+			),
116
+			'delete_db'                           => array(
117
+				'func'       => '_delete_db',
118
+				'capability' => 'manage_options',
119
+				'noheader'   => true,
120
+			),
121
+			'rerun_migration_from_ee3'            => array(
122
+				'func'       => '_rerun_migration_from_ee3',
123
+				'capability' => 'manage_options',
124
+				'noheader'   => true,
125
+			),
126
+			'reset_reservations'                  => array(
127
+				'func'       => '_reset_reservations',
128
+				'capability' => 'manage_options',
129
+				'noheader'   => true,
130
+			),
131
+			'reset_capabilities'                  => array(
132
+				'func'       => '_reset_capabilities',
133
+				'capability' => 'manage_options',
134
+				'noheader'   => true,
135
+			),
136
+			'reattempt_migration'                 => array(
137
+				'func'       => '_reattempt_migration',
138
+				'capability' => 'manage_options',
139
+				'noheader'   => true,
140
+			),
141
+			'datetime_tools' => array(
142
+				'func' => '_datetime_tools',
143
+				'capability' => 'manage_options'
144
+			),
145
+			'run_datetime_offset_fix' => array(
146
+				'func' => '_apply_datetime_offset',
147
+				'noheader' => true,
148
+				'headers_sent_route' => 'datetime_tools',
149
+				'capability' => 'manage_options'
150
+			)
151
+		);
152
+	}
153
+
154
+
155
+
156
+	protected function _set_page_config()
157
+	{
158
+		$this->_page_config = array(
159
+			'default'       => array(
160
+				'nav'           => array(
161
+					'label' => esc_html__('Maintenance', 'event_espresso'),
162
+					'order' => 10,
163
+				),
164
+				'require_nonce' => false,
165
+			),
166
+			'data_reset'    => array(
167
+				'nav'           => array(
168
+					'label' => esc_html__('Reset/Delete Data', 'event_espresso'),
169
+					'order' => 20,
170
+				),
171
+				'require_nonce' => false,
172
+			),
173
+			'datetime_tools' => array(
174
+				'nav' => array(
175
+					'label' => esc_html__('Datetime Utilities', 'event_espresso'),
176
+					'order' => 25
177
+				),
178
+				'require_nonce' => false,
179
+			),
180
+			'system_status' => array(
181
+				'nav'           => array(
182
+					'label' => esc_html__("System Information", "event_espresso"),
183
+					'order' => 30,
184
+				),
185
+				'require_nonce' => false,
186
+			),
187
+		);
188
+	}
189
+
190
+
191
+
192
+	/**
193
+	 * default maintenance page. If we're in maintenance mode level 2, then we need to show
194
+	 * the migration scripts and all that UI.
195
+	 */
196
+	public function _maintenance()
197
+	{
198
+		//it all depends if we're in maintenance model level 1 (frontend-only) or
199
+		//level 2 (everything except maintenance page)
200
+		try {
201
+			//get the current maintenance level and check if
202
+			//we are removed
203
+			$mm = EE_Maintenance_Mode::instance()->level();
204
+			$placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
205
+			if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) {
206
+				//we just took the site out of maintenance mode, so notify the user.
207
+				//unfortunately this message appears to be echoed on the NEXT page load...
208
+				//oh well, we should really be checking for this on addon deactivation anyways
209
+				EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required',
210
+					'event_espresso'));
211
+				$this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
212
+			}
213
+			//in case an exception is thrown while trying to handle migrations
214
+			switch (EE_Maintenance_Mode::instance()->level()) {
215
+				case EE_Maintenance_Mode::level_0_not_in_maintenance:
216
+				case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
217
+					$show_maintenance_switch = true;
218
+					$show_backup_db_text = false;
219
+					$show_migration_progress = false;
220
+					$script_names = array();
221
+					$addons_should_be_upgraded_first = false;
222
+					break;
223
+				case EE_Maintenance_Mode::level_2_complete_maintenance:
224
+					$show_maintenance_switch = false;
225
+					$show_migration_progress = true;
226
+					if (isset($this->_req_data['continue_migration'])) {
227
+						$show_backup_db_text = false;
228
+					} else {
229
+						$show_backup_db_text = true;
230
+					}
231
+					$scripts_needing_to_run = EE_Data_Migration_Manager::instance()
232
+																	   ->check_for_applicable_data_migration_scripts();
233
+					$addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
234
+					$script_names = array();
235
+					$current_script = null;
236
+					foreach ($scripts_needing_to_run as $script) {
237
+						if ($script instanceof EE_Data_Migration_Script_Base) {
238
+							if ( ! $current_script) {
239
+								$current_script = $script;
240
+								$current_script->migration_page_hooks();
241
+							}
242
+							$script_names[] = $script->pretty_name();
243
+						}
244
+					}
245
+					break;
246
+			}
247
+			$most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
248
+			$exception_thrown = false;
249
+		} catch (EE_Error $e) {
250
+			EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
251
+			//now, just so we can display the page correctly, make a error migration script stage object
252
+			//and also put the error on it. It only persists for the duration of this request
253
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
254
+			$most_recent_migration->add_error($e->getMessage());
255
+			$exception_thrown = true;
256
+		}
257
+		$current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
258
+		$current_db_state = str_replace('.decaf', '', $current_db_state);
259
+		if ($exception_thrown
260
+			|| ($most_recent_migration
261
+				&& $most_recent_migration instanceof EE_Data_Migration_Script_Base
262
+				&& $most_recent_migration->is_broken()
263
+			)
264
+		) {
265
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
266
+			$this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
267
+			$this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action'  => 'confirm_migration_crash_report_sent',
268
+																						'success' => '0',
269
+			), EE_MAINTENANCE_ADMIN_URL);
270
+		} elseif ($addons_should_be_upgraded_first) {
271
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
272
+		} else {
273
+			if ($most_recent_migration
274
+				&& $most_recent_migration instanceof EE_Data_Migration_Script_Base
275
+				&& $most_recent_migration->can_continue()
276
+			) {
277
+				$show_backup_db_text = false;
278
+				$show_continue_current_migration_script = true;
279
+				$show_most_recent_migration = true;
280
+			} elseif (isset($this->_req_data['continue_migration'])) {
281
+				$show_most_recent_migration = true;
282
+				$show_continue_current_migration_script = false;
283
+			} else {
284
+				$show_most_recent_migration = false;
285
+				$show_continue_current_migration_script = false;
286
+			}
287
+			if (isset($current_script)) {
288
+				$migrates_to = $current_script->migrates_to_version();
289
+				$plugin_slug = $migrates_to['slug'];
290
+				$new_version = $migrates_to['version'];
291
+				$this->_template_args = array_merge($this->_template_args, array(
292
+					'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"),
293
+						isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug),
294
+					'next_db_state'    => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'),
295
+						$new_version, $plugin_slug) : null,
296
+				));
297
+			} else {
298
+				$this->_template_args['current_db_state'] = null;
299
+				$this->_template_args['next_db_state'] = null;
300
+			}
301
+			$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
302
+			$this->_template_args = array_merge(
303
+				$this->_template_args,
304
+				array(
305
+					'show_most_recent_migration'             => $show_most_recent_migration,
306
+					//flag for showing the most recent migration's status and/or errors
307
+					'show_migration_progress'                => $show_migration_progress,
308
+					//flag for showing the option to run migrations and see their progress
309
+					'show_backup_db_text'                    => $show_backup_db_text,
310
+					//flag for showing text telling the user to backup their DB
311
+					'show_maintenance_switch'                => $show_maintenance_switch,
312
+					//flag for showing the option to change maintenance mode between levels 0 and 1
313
+					'script_names'                           => $script_names,
314
+					//array of names of scripts that have run
315
+					'show_continue_current_migration_script' => $show_continue_current_migration_script,
316
+					//flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0
317
+					'reset_db_page_link'                     => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
318
+						EE_MAINTENANCE_ADMIN_URL),
319
+					'data_reset_page'                        => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
320
+						EE_MAINTENANCE_ADMIN_URL),
321
+					'update_migration_script_page_link'      => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'),
322
+						EE_MAINTENANCE_ADMIN_URL),
323
+					'ultimate_db_state'                      => sprintf(__("EE%s", 'event_espresso'),
324
+						espresso_version()),
325
+				)
326
+			);
327
+			//make sure we have the form fields helper available. It usually is, but sometimes it isn't
328
+		}
329
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration
330
+		//now render the migration options part, and put it in a variable
331
+		$migration_options_template_file = apply_filters(
332
+			'FHEE__ee_migration_page__migration_options_template',
333
+			EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php'
334
+		);
335
+		$migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true);
336
+		$this->_template_args['migration_options_html'] = $migration_options_html;
337
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
338
+			$this->_template_args, true);
339
+		$this->display_admin_page_with_sidebar();
340
+	}
341
+
342
+
343
+
344
+	/**
345
+	 * returns JSON and executes another step of the currently-executing data migration (called via ajax)
346
+	 */
347
+	public function migration_step()
348
+	{
349
+		$this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request();
350
+		$this->_return_json();
351
+	}
352
+
353
+
354
+
355
+	/**
356
+	 * Can be used by js when it notices a response with HTML in it in order
357
+	 * to log the malformed response
358
+	 */
359
+	public function add_error_to_migrations_ran()
360
+	{
361
+		EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']);
362
+		$this->_template_args['data'] = array('ok' => true);
363
+		$this->_return_json();
364
+	}
365
+
366
+
367
+
368
+	/**
369
+	 * changes the maintenance level, provided there are still no migration scripts that should run
370
+	 */
371
+	public function _change_maintenance_level()
372
+	{
373
+		$new_level = absint($this->_req_data['maintenance_mode_level']);
374
+		if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) {
375
+			EE_Maintenance_Mode::instance()->set_maintenance_level($new_level);
376
+			$success = true;
377
+		} else {
378
+			EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
379
+			$success = false;
380
+		}
381
+		$this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso"));
382
+	}
383
+
384
+
385
+
386
+	/**
387
+	 * a tab with options for resetting and/or deleting EE data
388
+	 *
389
+	 * @throws \EE_Error
390
+	 * @throws \DomainException
391
+	 */
392
+	public function _data_reset_and_delete()
393
+	{
394
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php';
395
+		$this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button(
396
+			'reset_reservations',
397
+			'reset_reservations',
398
+			array(),
399
+			'button button-primary ee-confirm',
400
+			'',
401
+			false
402
+		);
403
+		$this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button(
404
+			'reset_capabilities',
405
+			'reset_capabilities',
406
+			array(),
407
+			'button button-primary ee-confirm',
408
+			'',
409
+			false
410
+		);
411
+		$this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
412
+			array('action' => 'delete_db'),
413
+			EE_MAINTENANCE_ADMIN_URL
414
+		);
415
+		$this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce(
416
+			array('action' => 'reset_db'),
417
+			EE_MAINTENANCE_ADMIN_URL
418
+		);
419
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
420
+			$this->_template_path,
421
+			$this->_template_args,
422
+			true
423
+		);
424
+		$this->display_admin_page_with_sidebar();
425
+	}
426
+
427
+
428
+
429
+	protected function _reset_reservations()
430
+	{
431
+		if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) {
432
+			EE_Error::add_success(
433
+				__(
434
+					'Ticket and datetime reserved counts have been successfully reset.',
435
+					'event_espresso'
436
+				)
437
+			);
438
+		} else {
439
+			EE_Error::add_success(
440
+				__(
441
+					'Ticket and datetime reserved counts were correct and did not need resetting.',
442
+					'event_espresso'
443
+				)
444
+			);
445
+		}
446
+		$this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true);
447
+	}
448
+
449
+
450
+
451
+	protected function _reset_capabilities()
452
+	{
453
+		EE_Registry::instance()->CAP->init_caps(true);
454
+		EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.',
455
+			'event_espresso'));
456
+		$this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true);
457
+	}
458
+
459
+
460
+
461
+	/**
462
+	 * resets the DMSs so we can attempt to continue migrating after a fatal error
463
+	 * (only a good idea when someone has somehow tried ot fix whatever caused
464
+	 * the fatal error in teh first place)
465
+	 */
466
+	protected function _reattempt_migration()
467
+	{
468
+		EE_Data_Migration_Manager::instance()->reattempt();
469
+		$this->_redirect_after_action(false, '', '', array('action' => 'default'), true);
470
+	}
471
+
472
+
473
+
474
+	/**
475
+	 * shows the big ol' System Information page
476
+	 */
477
+	public function _system_status()
478
+	{
479
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php';
480
+		$this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati();
481
+		$this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce(
482
+			array(
483
+				'action' => 'download_system_status',
484
+			),
485
+			EE_MAINTENANCE_ADMIN_URL
486
+		);
487
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
488
+			$this->_template_args, true);
489
+		$this->display_admin_page_with_sidebar();
490
+	}
491
+
492
+	/**
493
+	 * Downloads an HTML file of the system status that can be easily stored or emailed
494
+	 */
495
+	public function _download_system_status()
496
+	{
497
+		$status_info = EEM_System_Status::instance()->get_system_stati();
498
+		header( 'Content-Disposition: attachment' );
499
+		header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" );
500
+		echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>";
501
+		echo "<h1>System Information for " . site_url() . "</h1>";
502
+		echo EEH_Template::layout_array_as_table( $status_info );
503
+		die;
504
+	}
505
+
506
+
507
+
508
+	public function _send_migration_crash_report()
509
+	{
510
+		$from = $this->_req_data['from'];
511
+		$from_name = $this->_req_data['from_name'];
512
+		$body = $this->_req_data['body'];
513
+		try {
514
+			$success = wp_mail(EE_SUPPORT_EMAIL,
515
+				'Migration Crash Report',
516
+				$body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true),
517
+				array(
518
+					"from:$from_name<$from>",
519
+					//					'content-type:text/html charset=UTF-8'
520
+				));
521
+		} catch (Exception $e) {
522
+			$success = false;
523
+		}
524
+		$this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"),
525
+			esc_html__("sent", "event_espresso"),
526
+			array('success' => $success, 'action' => 'confirm_migration_crash_report_sent'));
527
+	}
528
+
529
+
530
+
531
+	public function _confirm_migration_crash_report_sent()
532
+	{
533
+		try {
534
+			$most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
535
+		} catch (EE_Error $e) {
536
+			EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
537
+			//now, just so we can display the page correctly, make a error migration script stage object
538
+			//and also put the error on it. It only persists for the duration of this request
539
+			$most_recent_migration = new EE_DMS_Unknown_1_0_0();
540
+			$most_recent_migration->add_error($e->getMessage());
541
+		}
542
+		$success = $this->_req_data['success'] == '1' ? true : false;
543
+		$this->_template_args['success'] = $success;
544
+		$this->_template_args['most_recent_migration'] = $most_recent_migration;
545
+		$this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'),
546
+			EE_MAINTENANCE_ADMIN_URL);
547
+		$this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'),
548
+			EE_MAINTENANCE_ADMIN_URL);
549
+		$this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'),
550
+			EE_MAINTENANCE_ADMIN_URL);
551
+		$this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php';
552
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path,
553
+			$this->_template_args, true);
554
+		$this->display_admin_page_with_sidebar();
555
+	}
556
+
557
+
558
+
559
+	/**
560
+	 * Resets the entire EE4 database.
561
+	 * Currently basically only sets up ee4 database for a fresh install- doesn't
562
+	 * actually clean out the old wp options, or cpts (although does erase old ee table data)
563
+	 *
564
+	 * @param boolean $nuke_old_ee4_data controls whether or not we
565
+	 *                                   destroy the old ee4 data, or just try initializing ee4 default data
566
+	 */
567
+	public function _reset_db($nuke_old_ee4_data = true)
568
+	{
569
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
570
+		if ($nuke_old_ee4_data) {
571
+			EEH_Activation::delete_all_espresso_cpt_data();
572
+			EEH_Activation::delete_all_espresso_tables_and_data(false);
573
+			EEH_Activation::remove_cron_tasks();
574
+		}
575
+		//make sure when we reset the registry's config that it
576
+		//switches to using the new singleton
577
+		EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true);
578
+		EE_System::instance()->initialize_db_if_no_migrations_required(true);
579
+		EE_System::instance()->redirect_to_about_ee();
580
+	}
581
+
582
+
583
+
584
+	/**
585
+	 * Deletes ALL EE tables, Records, and Options from the database.
586
+	 */
587
+	public function _delete_db()
588
+	{
589
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
590
+		EEH_Activation::delete_all_espresso_cpt_data();
591
+		EEH_Activation::delete_all_espresso_tables_and_data();
592
+		EEH_Activation::remove_cron_tasks();
593
+		EEH_Activation::deactivate_event_espresso();
594
+		wp_safe_redirect(admin_url('plugins.php'));
595
+		exit;
596
+	}
597
+
598
+
599
+
600
+	/**
601
+	 * sets up EE4 to rerun the migrations from ee3 to ee4
602
+	 */
603
+	public function _rerun_migration_from_ee3()
604
+	{
605
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance);
606
+		EEH_Activation::delete_all_espresso_cpt_data();
607
+		EEH_Activation::delete_all_espresso_tables_and_data(false);
608
+		//set the db state to something that will require migrations
609
+		update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0');
610
+		EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance);
611
+		$this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso'));
612
+	}
613
+
614
+
615
+
616
+	//none of the below group are currently used for Gateway Settings
617
+	protected function _add_screen_options()
618
+	{
619
+	}
620
+
621
+
622
+
623
+	protected function _add_feature_pointers()
624
+	{
625
+	}
626
+
627 627
 
628 628
 
629
-    public function admin_init()
630
-    {
631
-    }
632
-
633
-
634
-
635
-    public function admin_notices()
636
-    {
637
-    }
638
-
629
+	public function admin_init()
630
+	{
631
+	}
632
+
633
+
634
+
635
+	public function admin_notices()
636
+	{
637
+	}
638
+
639 639
 
640 640
 
641
-    public function admin_footer_scripts()
642
-    {
643
-    }
641
+	public function admin_footer_scripts()
642
+	{
643
+	}
644 644
 
645 645
 
646 646
 
647
-    public function load_scripts_styles()
648
-    {
649
-        wp_enqueue_script('ee_admin_js');
647
+	public function load_scripts_styles()
648
+	{
649
+		wp_enqueue_script('ee_admin_js');
650 650
 //		wp_enqueue_media();
651 651
 //		wp_enqueue_script('media-upload');
652
-        wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'),
653
-            EVENT_ESPRESSO_VERSION, true);
654
-        wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
655
-            EVENT_ESPRESSO_VERSION);
656
-        wp_enqueue_style('espresso_maintenance');
657
-        //localize script stuff
658
-        wp_localize_script('ee-maintenance', 'ee_maintenance', array(
659
-            'migrating'                        => esc_html__("Updating Database...", "event_espresso"),
660
-            'next'                             => esc_html__("Next", "event_espresso"),
661
-            'fatal_error'                      => esc_html__("A Fatal Error Has Occurred", "event_espresso"),
662
-            'click_next_when_ready'            => esc_html__(
663
-                "The current Database Update has ended. Click 'next' when ready to proceed",
664
-                "event_espresso"
665
-            ),
666
-            'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
667
-            'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
668
-            'status_completed'                 => EE_Data_Migration_Manager::status_completed,
669
-            'confirm'                          => esc_html__(
670
-                'Are you sure you want to do this? It CANNOT be undone!',
671
-                'event_espresso'
672
-            ),
673
-            'confirm_skip_migration' => esc_html__(
674
-                'You have chosen to NOT migrate your existing data. Are you sure you want to continue?',
675
-                'event_espresso'
676
-            )
677
-        ));
678
-    }
679
-
680
-
681
-
682
-    public function load_scripts_styles_default()
683
-    {
684
-        //styles
652
+		wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'),
653
+			EVENT_ESPRESSO_VERSION, true);
654
+		wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(),
655
+			EVENT_ESPRESSO_VERSION);
656
+		wp_enqueue_style('espresso_maintenance');
657
+		//localize script stuff
658
+		wp_localize_script('ee-maintenance', 'ee_maintenance', array(
659
+			'migrating'                        => esc_html__("Updating Database...", "event_espresso"),
660
+			'next'                             => esc_html__("Next", "event_espresso"),
661
+			'fatal_error'                      => esc_html__("A Fatal Error Has Occurred", "event_espresso"),
662
+			'click_next_when_ready'            => esc_html__(
663
+				"The current Database Update has ended. Click 'next' when ready to proceed",
664
+				"event_espresso"
665
+			),
666
+			'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts,
667
+			'status_fatal_error'               => EE_Data_Migration_Manager::status_fatal_error,
668
+			'status_completed'                 => EE_Data_Migration_Manager::status_completed,
669
+			'confirm'                          => esc_html__(
670
+				'Are you sure you want to do this? It CANNOT be undone!',
671
+				'event_espresso'
672
+			),
673
+			'confirm_skip_migration' => esc_html__(
674
+				'You have chosen to NOT migrate your existing data. Are you sure you want to continue?',
675
+				'event_espresso'
676
+			)
677
+		));
678
+	}
679
+
680
+
681
+
682
+	public function load_scripts_styles_default()
683
+	{
684
+		//styles
685 685
 //		wp_enqueue_style('ee-text-links');
686 686
 //		//scripts
687 687
 //		wp_enqueue_script('ee-text-links');
688
-    }
689
-
690
-
691
-    /**
692
-     * Enqueue scripts and styles for the datetime tools page.
693
-     */
694
-    public function load_scripts_styles_datetime_tools()
695
-    {
696
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
697
-    }
698
-
699
-
700
-    protected function _datetime_tools()
701
-    {
702
-        $form_action = EE_Admin_Page::add_query_args_and_nonce(
703
-            array(
704
-                'action' => 'run_datetime_offset_fix',
705
-                'return_action' => $this->_req_action
706
-            ),
707
-            EE_MAINTENANCE_ADMIN_URL
708
-        );
709
-        $form = $this->_get_datetime_offset_fix_form();
710
-        $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso');
711
-        $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
712
-                                                      . $form->get_html_and_js()
713
-                                                      . $form->form_close();
714
-        $this->display_admin_page_with_no_sidebar();
715
-    }
716
-
717
-
718
-
719
-    protected function _get_datetime_offset_fix_form()
720
-    {
721
-        if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
722
-            $this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
723
-                array(
724
-                    'name' => 'datetime_offset_fix_option',
725
-                    'layout_strategy' => new EE_Admin_Two_Column_Layout(),
726
-                    'subsections' => array(
727
-                        'title' => new EE_Form_Section_HTML(
728
-                            EEH_HTML::h2(
729
-                                esc_html__('Datetime Offset Tool', 'event_espresso')
730
-                            )
731
-                        ),
732
-                        'explanation' => new EE_Form_Section_HTML(
733
-                            EEH_HTML::p(
734
-                                esc_html__(
735
-                                    'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
736
-                                    'event_espresso'
737
-                                )
738
-                            )
739
-                            . EEH_HTML::p(
740
-                                esc_html__(
741
-                                    'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
742
-                                    'event_espresso'
743
-                                )
744
-                            )
745
-                        ),
746
-                        'offset_input' => new EE_Float_Input(
747
-                            array(
748
-                                'html_name' => 'offset_for_datetimes',
749
-                                'html_label_text' => esc_html__(
750
-                                    'Offset to apply (in hours):',
751
-                                    'event_espresso'
752
-                                ),
753
-                                'min_value' => '-12',
754
-                                'max_value' => '14',
755
-                                'step_value' => '.25',
756
-                                'default' => DatetimeOffsetFix::getOffset()
757
-                            )
758
-                        ),
759
-                        'date_range_explanation' => new EE_Form_Section_HTML(
760
-                            EEH_HTML::p(
761
-                                esc_html__(
762
-                                    'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.',
763
-                                    'event_espresso'
764
-                                )
765
-                            )
766
-                            . EEH_HTML::p(
767
-                                EEH_HTML::strong(
768
-                                    sprintf(
769
-                                        esc_html__(
770
-                                            'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).',
771
-                                            'event_espresso'
772
-                                        ),
773
-                                        '<a href="https://www.timeanddate.com/worldclock/converter.html">',
774
-                                        '</a>'
775
-                                    )
776
-                                )
777
-                            )
778
-                        ),
779
-                        'date_range_start_date' => new EE_Datepicker_Input(
780
-                            array(
781
-                                'html_name' => 'offset_date_start_range',
782
-                                'html_label_text' => esc_html__(
783
-                                    'Start Date for dates the offset applied to:',
784
-                                    'event_espresso'
785
-                                )
786
-                            )
787
-                        ),
788
-                        'date_range_end_date' => new EE_Datepicker_Input(
789
-                            array(
790
-                                'html_name' => 'offset_date_end_range',
791
-                                'html_label_text' => esc_html(
792
-                                    'End Date for dates the offset is applied to:',
793
-                                    'event_espresso'
794
-                                )
795
-                            )
796
-                        ),
797
-                        'submit' => new EE_Submit_Input(
798
-                            array(
799
-                                'html_label_text' => '',
800
-                                'default' => esc_html__('Apply Offset', 'event_espresso')
801
-                            )
802
-                        ),
803
-                    )
804
-                )
805
-            );
806
-        }
807
-        return $this->datetime_fix_offset_form;
808
-    }
809
-
810
-
811
-    /**
812
-     * Callback for the run_datetime_offset_fix route.
813
-     * @throws EE_Error
814
-     */
815
-    protected function _apply_datetime_offset()
816
-    {
817
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
818
-            $form = $this->_get_datetime_offset_fix_form();
819
-            $form->receive_form_submission($this->_req_data);
820
-            if ($form->is_valid()) {
821
-                //save offset data so batch processor can get it.
822
-                DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input'));
823
-                $utc_timezone = new DateTimeZone('UTC');
824
-                $date_range_start_date = DateTime::createFromFormat(
825
-                    'm/d/Y H:i:s',
826
-                    $form->get_input_value('date_range_start_date') . ' 00:00:00',
827
-                    $utc_timezone
828
-                );
829
-                $date_range_end_date = DateTime::createFromFormat(
830
-                        'm/d/Y H:i:s',
831
-                        $form->get_input_value('date_range_end_date') . ' 23:59:59',
832
-                        $utc_timezone
833
-                );
834
-                if ($date_range_start_date instanceof DateTime) {
835
-                    DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date));
836
-                }
837
-                if ($date_range_end_date instanceof DateTime) {
838
-                    DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date));
839
-                }
840
-                //redirect to batch tool
841
-                wp_redirect(
842
-                    EE_Admin_Page::add_query_args_and_nonce(
843
-                        array(
844
-                            'page' => 'espresso_batch',
845
-                            'batch' => 'job',
846
-                            'label' => esc_html__('Applying Offset', 'event_espresso'),
847
-                            'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'),
848
-                            'return_url' => urlencode(
849
-                                add_query_arg(
850
-                                    array(
851
-                                        'action' => 'datetime_tools',
852
-                                    ),
853
-                                    EEH_URL::current_url_without_query_paramaters(
854
-                                        array(
855
-                                            'return_action',
856
-                                            'run_datetime_offset_fix_nonce',
857
-                                            'return',
858
-                                            'datetime_tools_nonce'
859
-                                        )
860
-                                    )
861
-                                )
862
-                            )
863
-                        ),
864
-                        admin_url()
865
-                    )
866
-                );
867
-                exit;
868
-            }
869
-        }
870
-    }
688
+	}
689
+
690
+
691
+	/**
692
+	 * Enqueue scripts and styles for the datetime tools page.
693
+	 */
694
+	public function load_scripts_styles_datetime_tools()
695
+	{
696
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
697
+	}
698
+
699
+
700
+	protected function _datetime_tools()
701
+	{
702
+		$form_action = EE_Admin_Page::add_query_args_and_nonce(
703
+			array(
704
+				'action' => 'run_datetime_offset_fix',
705
+				'return_action' => $this->_req_action
706
+			),
707
+			EE_MAINTENANCE_ADMIN_URL
708
+		);
709
+		$form = $this->_get_datetime_offset_fix_form();
710
+		$this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso');
711
+		$this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post')
712
+													  . $form->get_html_and_js()
713
+													  . $form->form_close();
714
+		$this->display_admin_page_with_no_sidebar();
715
+	}
716
+
717
+
718
+
719
+	protected function _get_datetime_offset_fix_form()
720
+	{
721
+		if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) {
722
+			$this->datetime_fix_offset_form =  new EE_Form_Section_Proper(
723
+				array(
724
+					'name' => 'datetime_offset_fix_option',
725
+					'layout_strategy' => new EE_Admin_Two_Column_Layout(),
726
+					'subsections' => array(
727
+						'title' => new EE_Form_Section_HTML(
728
+							EEH_HTML::h2(
729
+								esc_html__('Datetime Offset Tool', 'event_espresso')
730
+							)
731
+						),
732
+						'explanation' => new EE_Form_Section_HTML(
733
+							EEH_HTML::p(
734
+								esc_html__(
735
+									'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.',
736
+									'event_espresso'
737
+								)
738
+							)
739
+							. EEH_HTML::p(
740
+								esc_html__(
741
+									'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied.  Decimals represent the fraction of hours, not minutes.',
742
+									'event_espresso'
743
+								)
744
+							)
745
+						),
746
+						'offset_input' => new EE_Float_Input(
747
+							array(
748
+								'html_name' => 'offset_for_datetimes',
749
+								'html_label_text' => esc_html__(
750
+									'Offset to apply (in hours):',
751
+									'event_espresso'
752
+								),
753
+								'min_value' => '-12',
754
+								'max_value' => '14',
755
+								'step_value' => '.25',
756
+								'default' => DatetimeOffsetFix::getOffset()
757
+							)
758
+						),
759
+						'date_range_explanation' => new EE_Form_Section_HTML(
760
+							EEH_HTML::p(
761
+								esc_html__(
762
+									'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.',
763
+									'event_espresso'
764
+								)
765
+							)
766
+							. EEH_HTML::p(
767
+								EEH_HTML::strong(
768
+									sprintf(
769
+										esc_html__(
770
+											'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).',
771
+											'event_espresso'
772
+										),
773
+										'<a href="https://www.timeanddate.com/worldclock/converter.html">',
774
+										'</a>'
775
+									)
776
+								)
777
+							)
778
+						),
779
+						'date_range_start_date' => new EE_Datepicker_Input(
780
+							array(
781
+								'html_name' => 'offset_date_start_range',
782
+								'html_label_text' => esc_html__(
783
+									'Start Date for dates the offset applied to:',
784
+									'event_espresso'
785
+								)
786
+							)
787
+						),
788
+						'date_range_end_date' => new EE_Datepicker_Input(
789
+							array(
790
+								'html_name' => 'offset_date_end_range',
791
+								'html_label_text' => esc_html(
792
+									'End Date for dates the offset is applied to:',
793
+									'event_espresso'
794
+								)
795
+							)
796
+						),
797
+						'submit' => new EE_Submit_Input(
798
+							array(
799
+								'html_label_text' => '',
800
+								'default' => esc_html__('Apply Offset', 'event_espresso')
801
+							)
802
+						),
803
+					)
804
+				)
805
+			);
806
+		}
807
+		return $this->datetime_fix_offset_form;
808
+	}
809
+
810
+
811
+	/**
812
+	 * Callback for the run_datetime_offset_fix route.
813
+	 * @throws EE_Error
814
+	 */
815
+	protected function _apply_datetime_offset()
816
+	{
817
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
818
+			$form = $this->_get_datetime_offset_fix_form();
819
+			$form->receive_form_submission($this->_req_data);
820
+			if ($form->is_valid()) {
821
+				//save offset data so batch processor can get it.
822
+				DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input'));
823
+				$utc_timezone = new DateTimeZone('UTC');
824
+				$date_range_start_date = DateTime::createFromFormat(
825
+					'm/d/Y H:i:s',
826
+					$form->get_input_value('date_range_start_date') . ' 00:00:00',
827
+					$utc_timezone
828
+				);
829
+				$date_range_end_date = DateTime::createFromFormat(
830
+						'm/d/Y H:i:s',
831
+						$form->get_input_value('date_range_end_date') . ' 23:59:59',
832
+						$utc_timezone
833
+				);
834
+				if ($date_range_start_date instanceof DateTime) {
835
+					DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date));
836
+				}
837
+				if ($date_range_end_date instanceof DateTime) {
838
+					DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date));
839
+				}
840
+				//redirect to batch tool
841
+				wp_redirect(
842
+					EE_Admin_Page::add_query_args_and_nonce(
843
+						array(
844
+							'page' => 'espresso_batch',
845
+							'batch' => 'job',
846
+							'label' => esc_html__('Applying Offset', 'event_espresso'),
847
+							'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'),
848
+							'return_url' => urlencode(
849
+								add_query_arg(
850
+									array(
851
+										'action' => 'datetime_tools',
852
+									),
853
+									EEH_URL::current_url_without_query_paramaters(
854
+										array(
855
+											'return_action',
856
+											'run_datetime_offset_fix_nonce',
857
+											'return',
858
+											'datetime_tools_nonce'
859
+										)
860
+									)
861
+								)
862
+							)
863
+						),
864
+						admin_url()
865
+					)
866
+				);
867
+				exit;
868
+			}
869
+		}
870
+	}
871 871
 } //end Maintenance_Admin_Page class
Please login to merge, or discard this patch.
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 1 patch
Indentation   +1260 added lines, -1260 removed lines patch added patch discarded remove patch
@@ -14,1264 +14,1264 @@
 block discarded – undo
14 14
 {
15 15
 
16 16
 
17
-    /**
18
-     * Extend_Events_Admin_Page constructor.
19
-     *
20
-     * @param bool $routing
21
-     */
22
-    public function __construct($routing = true)
23
-    {
24
-        parent::__construct($routing);
25
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
29
-        }
30
-    }
31
-
32
-
33
-    /**
34
-     * Sets routes.
35
-     */
36
-    protected function _extend_page_config()
37
-    {
38
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
39
-        //is there a evt_id in the request?
40
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
41
-            ? $this->_req_data['EVT_ID']
42
-            : 0;
43
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
44
-        //tkt_id?
45
-        $tkt_id             = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
46
-            ? $this->_req_data['TKT_ID']
47
-            : 0;
48
-        $new_page_routes    = array(
49
-            'duplicate_event'          => array(
50
-                'func'       => '_duplicate_event',
51
-                'capability' => 'ee_edit_event',
52
-                'obj_id'     => $evt_id,
53
-                'noheader'   => true,
54
-            ),
55
-            'ticket_list_table'        => array(
56
-                'func'       => '_tickets_overview_list_table',
57
-                'capability' => 'ee_read_default_tickets',
58
-            ),
59
-            'trash_ticket'             => array(
60
-                'func'       => '_trash_or_restore_ticket',
61
-                'capability' => 'ee_delete_default_ticket',
62
-                'obj_id'     => $tkt_id,
63
-                'noheader'   => true,
64
-                'args'       => array('trash' => true),
65
-            ),
66
-            'trash_tickets'            => array(
67
-                'func'       => '_trash_or_restore_ticket',
68
-                'capability' => 'ee_delete_default_tickets',
69
-                'noheader'   => true,
70
-                'args'       => array('trash' => true),
71
-            ),
72
-            'restore_ticket'           => array(
73
-                'func'       => '_trash_or_restore_ticket',
74
-                'capability' => 'ee_delete_default_ticket',
75
-                'obj_id'     => $tkt_id,
76
-                'noheader'   => true,
77
-            ),
78
-            'restore_tickets'          => array(
79
-                'func'       => '_trash_or_restore_ticket',
80
-                'capability' => 'ee_delete_default_tickets',
81
-                'noheader'   => true,
82
-            ),
83
-            'delete_ticket'            => array(
84
-                'func'       => '_delete_ticket',
85
-                'capability' => 'ee_delete_default_ticket',
86
-                'obj_id'     => $tkt_id,
87
-                'noheader'   => true,
88
-            ),
89
-            'delete_tickets'           => array(
90
-                'func'       => '_delete_ticket',
91
-                'capability' => 'ee_delete_default_tickets',
92
-                'noheader'   => true,
93
-            ),
94
-            'import_page'              => array(
95
-                'func'       => '_import_page',
96
-                'capability' => 'import',
97
-            ),
98
-            'import'                   => array(
99
-                'func'       => '_import_events',
100
-                'capability' => 'import',
101
-                'noheader'   => true,
102
-            ),
103
-            'import_events'            => array(
104
-                'func'       => '_import_events',
105
-                'capability' => 'import',
106
-                'noheader'   => true,
107
-            ),
108
-            'export_events'            => array(
109
-                'func'       => '_events_export',
110
-                'capability' => 'export',
111
-                'noheader'   => true,
112
-            ),
113
-            'export_categories'        => array(
114
-                'func'       => '_categories_export',
115
-                'capability' => 'export',
116
-                'noheader'   => true,
117
-            ),
118
-            'sample_export_file'       => array(
119
-                'func'       => '_sample_export_file',
120
-                'capability' => 'export',
121
-                'noheader'   => true,
122
-            ),
123
-            'update_template_settings' => array(
124
-                'func'       => '_update_template_settings',
125
-                'capability' => 'manage_options',
126
-                'noheader'   => true,
127
-            ),
128
-        );
129
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
130
-        //partial route/config override
131
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
132
-        $this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
133
-        $this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
134
-        $this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
135
-        $this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
136
-        $this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
137
-        //add tickets tab but only if there are more than one default ticket!
138
-        $tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
139
-            array(array('TKT_is_default' => 1)),
140
-            'TKT_ID',
141
-            true
142
-        );
143
-        if ($tkt_count > 1) {
144
-            $new_page_config = array(
145
-                'ticket_list_table' => array(
146
-                    'nav'           => array(
147
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
148
-                        'order' => 60,
149
-                    ),
150
-                    'list_table'    => 'Tickets_List_Table',
151
-                    'require_nonce' => false,
152
-                ),
153
-            );
154
-        }
155
-        //template settings
156
-        $new_page_config['template_settings'] = array(
157
-            'nav'           => array(
158
-                'label' => esc_html__('Templates', 'event_espresso'),
159
-                'order' => 30,
160
-            ),
161
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
162
-            'help_tabs'     => array(
163
-                'general_settings_templates_help_tab' => array(
164
-                    'title'    => esc_html__('Templates', 'event_espresso'),
165
-                    'filename' => 'general_settings_templates',
166
-                ),
167
-            ),
168
-            'help_tour'     => array('Templates_Help_Tour'),
169
-            'require_nonce' => false,
170
-        );
171
-        $this->_page_config                   = array_merge($this->_page_config, $new_page_config);
172
-        //add filters and actions
173
-        //modifying _views
174
-        add_filter(
175
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
176
-            array($this, 'add_additional_datetime_button'),
177
-            10,
178
-            2
179
-        );
180
-        add_filter(
181
-            'FHEE_event_datetime_metabox_clone_button_template',
182
-            array($this, 'add_datetime_clone_button'),
183
-            10,
184
-            2
185
-        );
186
-        add_filter(
187
-            'FHEE_event_datetime_metabox_timezones_template',
188
-            array($this, 'datetime_timezones_template'),
189
-            10,
190
-            2
191
-        );
192
-        //filters for event list table
193
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
194
-        add_filter(
195
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
196
-            array($this, 'extra_list_table_actions'),
197
-            10,
198
-            2
199
-        );
200
-        //legend item
201
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
202
-        add_action('admin_init', array($this, 'admin_init'));
203
-        //heartbeat stuff
204
-        add_filter('heartbeat_received', array($this, 'heartbeat_response'), 10, 2);
205
-    }
206
-
207
-
208
-    /**
209
-     * admin_init
210
-     */
211
-    public function admin_init()
212
-    {
213
-        EE_Registry::$i18n_js_strings = array_merge(
214
-            EE_Registry::$i18n_js_strings,
215
-            array(
216
-                'image_confirm'          => esc_html__(
217
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
218
-                    'event_espresso'
219
-                ),
220
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
221
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
222
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
223
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
224
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
225
-            )
226
-        );
227
-    }
228
-
229
-
230
-    /**
231
-     * This will be used to listen for any heartbeat data packages coming via the WordPress heartbeat API and handle
232
-     * accordingly.
233
-     *
234
-     * @param array $response The existing heartbeat response array.
235
-     * @param array $data     The incoming data package.
236
-     * @return array  possibly appended response.
237
-     */
238
-    public function heartbeat_response($response, $data)
239
-    {
240
-        /**
241
-         * check whether count of tickets is approaching the potential
242
-         * limits for the server.
243
-         */
244
-        if (! empty($data['input_count'])) {
245
-            $response['max_input_vars_check'] = EE_Registry::instance()->CFG->environment->max_input_vars_limit_check(
246
-                $data['input_count']
247
-            );
248
-        }
249
-        return $response;
250
-    }
251
-
252
-
253
-    /**
254
-     * Add per page screen options to the default ticket list table view.
255
-     */
256
-    protected function _add_screen_options_ticket_list_table()
257
-    {
258
-        $this->_per_page_screen_option();
259
-    }
260
-
261
-
262
-    /**
263
-     * @param string $return
264
-     * @param int    $id
265
-     * @param string $new_title
266
-     * @param string $new_slug
267
-     * @return string
268
-     */
269
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
270
-    {
271
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
272
-        //make sure this is only when editing
273
-        if (! empty($id)) {
274
-            $href   = EE_Admin_Page::add_query_args_and_nonce(
275
-                array('action' => 'duplicate_event', 'EVT_ID' => $id),
276
-                $this->_admin_base_url
277
-            );
278
-            $title  = esc_attr__('Duplicate Event', 'event_espresso');
279
-            $return .= '<a href="'
280
-                       . $href
281
-                       . '" title="'
282
-                       . $title
283
-                       . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
284
-                       . $title
285
-                       . '</a>';
286
-        }
287
-        return $return;
288
-    }
289
-
290
-
291
-    /**
292
-     * Set the list table views for the default ticket list table view.
293
-     */
294
-    public function _set_list_table_views_ticket_list_table()
295
-    {
296
-        $this->_views = array(
297
-            'all'     => array(
298
-                'slug'        => 'all',
299
-                'label'       => esc_html__('All', 'event_espresso'),
300
-                'count'       => 0,
301
-                'bulk_action' => array(
302
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
303
-                ),
304
-            ),
305
-            'trashed' => array(
306
-                'slug'        => 'trashed',
307
-                'label'       => esc_html__('Trash', 'event_espresso'),
308
-                'count'       => 0,
309
-                'bulk_action' => array(
310
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
311
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
312
-                ),
313
-            ),
314
-        );
315
-    }
316
-
317
-
318
-    /**
319
-     * Enqueue scripts and styles for the event editor.
320
-     */
321
-    public function load_scripts_styles_edit()
322
-    {
323
-        wp_register_script(
324
-            'ee-event-editor-heartbeat',
325
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
326
-            array('ee_admin_js', 'heartbeat'),
327
-            EVENT_ESPRESSO_VERSION,
328
-            true
329
-        );
330
-        wp_enqueue_script('ee-accounting');
331
-        //styles
332
-        wp_enqueue_style('espresso-ui-theme');
333
-        wp_enqueue_script('event_editor_js');
334
-        wp_enqueue_script('ee-event-editor-heartbeat');
335
-    }
336
-
337
-
338
-    /**
339
-     * Returns template for the additional datetime.
340
-     * @param $template
341
-     * @param $template_args
342
-     * @return mixed
343
-     * @throws DomainException
344
-     */
345
-    public function add_additional_datetime_button($template, $template_args)
346
-    {
347
-        return EEH_Template::display_template(
348
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
349
-            $template_args,
350
-            true
351
-        );
352
-    }
353
-
354
-
355
-    /**
356
-     * Returns the template for cloning a datetime.
357
-     * @param $template
358
-     * @param $template_args
359
-     * @return mixed
360
-     * @throws DomainException
361
-     */
362
-    public function add_datetime_clone_button($template, $template_args)
363
-    {
364
-        return EEH_Template::display_template(
365
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
366
-            $template_args,
367
-            true
368
-        );
369
-    }
370
-
371
-
372
-    /**
373
-     * Returns the template for datetime timezones.
374
-     * @param $template
375
-     * @param $template_args
376
-     * @return mixed
377
-     * @throws DomainException
378
-     */
379
-    public function datetime_timezones_template($template, $template_args)
380
-    {
381
-        return EEH_Template::display_template(
382
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
383
-            $template_args,
384
-            true
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Sets the views for the default list table view.
391
-     */
392
-    protected function _set_list_table_views_default()
393
-    {
394
-        parent::_set_list_table_views_default();
395
-        $new_views    = array(
396
-            'today' => array(
397
-                'slug'        => 'today',
398
-                'label'       => esc_html__('Today', 'event_espresso'),
399
-                'count'       => $this->total_events_today(),
400
-                'bulk_action' => array(
401
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
402
-                ),
403
-            ),
404
-            'month' => array(
405
-                'slug'        => 'month',
406
-                'label'       => esc_html__('This Month', 'event_espresso'),
407
-                'count'       => $this->total_events_this_month(),
408
-                'bulk_action' => array(
409
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
410
-                ),
411
-            ),
412
-        );
413
-        $this->_views = array_merge($this->_views, $new_views);
414
-    }
415
-
416
-
417
-    /**
418
-     * Returns the extra action links for the default list table view.
419
-     * @param array     $action_links
420
-     * @param \EE_Event $event
421
-     * @return array
422
-     * @throws EE_Error
423
-     */
424
-    public function extra_list_table_actions(array $action_links, \EE_Event $event)
425
-    {
426
-        if (EE_Registry::instance()->CAP->current_user_can(
427
-            'ee_read_registrations',
428
-            'espresso_registrations_reports',
429
-            $event->ID()
430
-        )
431
-        ) {
432
-            $reports_query_args = array(
433
-                'action' => 'reports',
434
-                'EVT_ID' => $event->ID(),
435
-            );
436
-            $reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
437
-            $action_links[]     = '<a href="'
438
-                                  . $reports_link
439
-                                  . '" title="'
440
-                                  . esc_attr__('View Report', 'event_espresso')
441
-                                  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
442
-                                  . "\n\t";
443
-        }
444
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
445
-            EE_Registry::instance()->load_helper('MSG_Template');
446
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
447
-                'see_notifications_for',
448
-                null,
449
-                array('EVT_ID' => $event->ID())
450
-            );
451
-        }
452
-        return $action_links;
453
-    }
454
-
455
-
456
-    /**
457
-     * @param $items
458
-     * @return mixed
459
-     */
460
-    public function additional_legend_items($items)
461
-    {
462
-        if (EE_Registry::instance()->CAP->current_user_can(
463
-            'ee_read_registrations',
464
-            'espresso_registrations_reports'
465
-        )
466
-        ) {
467
-            $items['reports'] = array(
468
-                'class' => 'dashicons dashicons-chart-bar',
469
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
470
-            );
471
-        }
472
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
473
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
474
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
475
-                $items['view_related_messages'] = array(
476
-                    'class' => $related_for_icon['css_class'],
477
-                    'desc'  => $related_for_icon['label'],
478
-                );
479
-            }
480
-        }
481
-        return $items;
482
-    }
483
-
484
-
485
-    /**
486
-     * This is the callback method for the duplicate event route
487
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
488
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
489
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
490
-     * After duplication the redirect is to the new event edit page.
491
-     *
492
-     * @return void
493
-     * @access protected
494
-     * @throws EE_Error If EE_Event is not available with given ID
495
-     */
496
-    protected function _duplicate_event()
497
-    {
498
-        // first make sure the ID for the event is in the request.
499
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
500
-        if (! isset($this->_req_data['EVT_ID'])) {
501
-            EE_Error::add_error(
502
-                esc_html__(
503
-                    'In order to duplicate an event an Event ID is required.  None was given.',
504
-                    'event_espresso'
505
-                ),
506
-                __FILE__,
507
-                __FUNCTION__,
508
-                __LINE__
509
-            );
510
-            $this->_redirect_after_action(false, '', '', array(), true);
511
-            return;
512
-        }
513
-        //k we've got EVT_ID so let's use that to get the event we'll duplicate
514
-        $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
515
-        if (! $orig_event instanceof EE_Event) {
516
-            throw new EE_Error(
517
-                sprintf(
518
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
519
-                    $this->_req_data['EVT_ID']
520
-                )
521
-            );
522
-        }
523
-        //k now let's clone the $orig_event before getting relations
524
-        $new_event = clone $orig_event;
525
-        //original datetimes
526
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
527
-        //other original relations
528
-        $orig_ven = $orig_event->get_many_related('Venue');
529
-        //reset the ID and modify other details to make it clear this is a dupe
530
-        $new_event->set('EVT_ID', 0);
531
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
532
-        $new_event->set('EVT_name', $new_name);
533
-        $new_event->set(
534
-            'EVT_slug',
535
-            wp_unique_post_slug(
536
-                sanitize_title($orig_event->name()),
537
-                0,
538
-                'publish',
539
-                'espresso_events',
540
-                0
541
-            )
542
-        );
543
-        $new_event->set('status', 'draft');
544
-        //duplicate discussion settings
545
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
546
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
547
-        //save the new event
548
-        $new_event->save();
549
-        //venues
550
-        foreach ($orig_ven as $ven) {
551
-            $new_event->_add_relation_to($ven, 'Venue');
552
-        }
553
-        $new_event->save();
554
-        //now we need to get the question group relations and handle that
555
-        //first primary question groups
556
-        $orig_primary_qgs = $orig_event->get_many_related(
557
-            'Question_Group',
558
-            array(array('Event_Question_Group.EQG_primary' => 1))
559
-        );
560
-        if (! empty($orig_primary_qgs)) {
561
-            foreach ($orig_primary_qgs as $id => $obj) {
562
-                if ($obj instanceof EE_Question_Group) {
563
-                    $new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 1));
564
-                }
565
-            }
566
-        }
567
-        //next additional attendee question groups
568
-        $orig_additional_qgs = $orig_event->get_many_related(
569
-            'Question_Group',
570
-            array(array('Event_Question_Group.EQG_primary' => 0))
571
-        );
572
-        if (! empty($orig_additional_qgs)) {
573
-            foreach ($orig_additional_qgs as $id => $obj) {
574
-                if ($obj instanceof EE_Question_Group) {
575
-                    $new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 0));
576
-                }
577
-            }
578
-        }
579
-
580
-        $new_event->save();
581
-
582
-        //k now that we have the new event saved we can loop through the datetimes and start adding relations.
583
-        $cloned_tickets = array();
584
-        foreach ($orig_datetimes as $orig_dtt) {
585
-            if (! $orig_dtt instanceof EE_Datetime) {
586
-                continue;
587
-            }
588
-            $new_dtt   = clone $orig_dtt;
589
-            $orig_tkts = $orig_dtt->tickets();
590
-            //save new dtt then add to event
591
-            $new_dtt->set('DTT_ID', 0);
592
-            $new_dtt->set('DTT_sold', 0);
593
-            $new_dtt->set_reserved(0);
594
-            $new_dtt->save();
595
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
596
-            $new_event->save();
597
-            //now let's get the ticket relations setup.
598
-            foreach ((array)$orig_tkts as $orig_tkt) {
599
-                //it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
600
-                if (! $orig_tkt instanceof EE_Ticket) {
601
-                    continue;
602
-                }
603
-                //is this ticket archived?  If it is then let's skip
604
-                if ($orig_tkt->get('TKT_deleted')) {
605
-                    continue;
606
-                }
607
-                // does this original ticket already exist in the clone_tickets cache?
608
-                //  If so we'll just use the new ticket from it.
609
-                if (isset($cloned_tickets[$orig_tkt->ID()])) {
610
-                    $new_tkt = $cloned_tickets[$orig_tkt->ID()];
611
-                } else {
612
-                    $new_tkt = clone $orig_tkt;
613
-                    //get relations on the $orig_tkt that we need to setup.
614
-                    $orig_prices = $orig_tkt->prices();
615
-                    $new_tkt->set('TKT_ID', 0);
616
-                    $new_tkt->set('TKT_sold', 0);
617
-                    $new_tkt->set('TKT_reserved', 0);
618
-                    $new_tkt->save(); //make sure new ticket has ID.
619
-                    //price relations on new ticket need to be setup.
620
-                    foreach ($orig_prices as $orig_price) {
621
-                        $new_price = clone $orig_price;
622
-                        $new_price->set('PRC_ID', 0);
623
-                        $new_price->save();
624
-                        $new_tkt->_add_relation_to($new_price, 'Price');
625
-                        $new_tkt->save();
626
-                    }
627
-
628
-                    do_action(
629
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
630
-                        $orig_tkt,
631
-                        $new_tkt,
632
-                        $orig_prices,
633
-                        $orig_event,
634
-                        $orig_dtt,
635
-                        $new_dtt
636
-                    );
637
-                }
638
-                // k now we can add the new ticket as a relation to the new datetime
639
-                // and make sure its added to our cached $cloned_tickets array
640
-                // for use with later datetimes that have the same ticket.
641
-                $new_dtt->_add_relation_to($new_tkt, 'Ticket');
642
-                $new_dtt->save();
643
-                $cloned_tickets[$orig_tkt->ID()] = $new_tkt;
644
-            }
645
-        }
646
-        //clone taxonomy information
647
-        $taxonomies_to_clone_with = apply_filters(
648
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
649
-            array('espresso_event_categories', 'espresso_event_type', 'post_tag')
650
-        );
651
-        //get terms for original event (notice)
652
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
653
-        //loop through terms and add them to new event.
654
-        foreach ($orig_terms as $term) {
655
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
656
-        }
657
-
658
-        //duplicate other core WP_Post items for this event.
659
-        //post thumbnail (feature image).
660
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
661
-        if ($feature_image_id) {
662
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
663
-        }
664
-
665
-        //duplicate page_template setting
666
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
667
-        if ($page_template) {
668
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
669
-        }
670
-
671
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
672
-        //now let's redirect to the edit page for this duplicated event if we have a new event id.
673
-        if ($new_event->ID()) {
674
-            $redirect_args = array(
675
-                'post'   => $new_event->ID(),
676
-                'action' => 'edit',
677
-            );
678
-            EE_Error::add_success(
679
-                esc_html__(
680
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
681
-                    'event_espresso'
682
-                )
683
-            );
684
-        } else {
685
-            $redirect_args = array(
686
-                'action' => 'default',
687
-            );
688
-            EE_Error::add_error(
689
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
690
-                __FILE__,
691
-                __FUNCTION__,
692
-                __LINE__
693
-            );
694
-        }
695
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
696
-    }
697
-
698
-
699
-    /**
700
-     * Generates output for the import page.
701
-     * @throws DomainException
702
-     */
703
-    protected function _import_page()
704
-    {
705
-        $title                                      = esc_html__('Import', 'event_espresso');
706
-        $intro                                      = esc_html__(
707
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
708
-            'event_espresso'
709
-        );
710
-        $form_url                                   = EVENTS_ADMIN_URL;
711
-        $action                                     = 'import_events';
712
-        $type                                       = 'csv';
713
-        $this->_template_args['form']               = EE_Import::instance()->upload_form(
714
-            $title, $intro, $form_url, $action, $type
715
-        );
716
-        $this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
717
-            array('action' => 'sample_export_file'),
718
-            $this->_admin_base_url
719
-        );
720
-        $content                                    = EEH_Template::display_template(
721
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
722
-            $this->_template_args,
723
-            true
724
-        );
725
-        $this->_template_args['admin_page_content'] = $content;
726
-        $this->display_admin_page_with_sidebar();
727
-    }
728
-
729
-
730
-    /**
731
-     * _import_events
732
-     * This handles displaying the screen and running imports for importing events.
733
-     *
734
-     * @return void
735
-     */
736
-    protected function _import_events()
737
-    {
738
-        require_once(EE_CLASSES . 'EE_Import.class.php');
739
-        $success = EE_Import::instance()->import();
740
-        $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
741
-    }
742
-
743
-
744
-    /**
745
-     * _events_export
746
-     * Will export all (or just the given event) to a Excel compatible file.
747
-     *
748
-     * @access protected
749
-     * @return void
750
-     */
751
-    protected function _events_export()
752
-    {
753
-        if (isset($this->_req_data['EVT_ID'])) {
754
-            $event_ids = $this->_req_data['EVT_ID'];
755
-        } elseif (isset($this->_req_data['EVT_IDs'])) {
756
-            $event_ids = $this->_req_data['EVT_IDs'];
757
-        } else {
758
-            $event_ids = null;
759
-        }
760
-        //todo: I don't like doing this but it'll do until we modify EE_Export Class.
761
-        $new_request_args = array(
762
-            'export' => 'report',
763
-            'action' => 'all_event_data',
764
-            'EVT_ID' => $event_ids,
765
-        );
766
-        $this->_req_data  = array_merge($this->_req_data, $new_request_args);
767
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
768
-            require_once(EE_CLASSES . 'EE_Export.class.php');
769
-            $EE_Export = EE_Export::instance($this->_req_data);
770
-            $EE_Export->export();
771
-        }
772
-    }
773
-
774
-
775
-    /**
776
-     * handle category exports()
777
-     *
778
-     * @return void
779
-     */
780
-    protected function _categories_export()
781
-    {
782
-        //todo: I don't like doing this but it'll do until we modify EE_Export Class.
783
-        $new_request_args = array(
784
-            'export'       => 'report',
785
-            'action'       => 'categories',
786
-            'category_ids' => $this->_req_data['EVT_CAT_ID'],
787
-        );
788
-        $this->_req_data  = array_merge($this->_req_data, $new_request_args);
789
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
790
-            require_once(EE_CLASSES . 'EE_Export.class.php');
791
-            $EE_Export = EE_Export::instance($this->_req_data);
792
-            $EE_Export->export();
793
-        }
794
-    }
795
-
796
-
797
-    /**
798
-     * Creates a sample CSV file for importing
799
-     */
800
-    protected function _sample_export_file()
801
-    {
802
-        //		require_once(EE_CLASSES . 'EE_Export.class.php');
803
-        EE_Export::instance()->export_sample();
804
-    }
805
-
806
-
807
-    /*************        Template Settings        *************/
808
-    /**
809
-     * Generates template settings page output
810
-     * @throws DomainException
811
-     * @throws EE_Error
812
-     */
813
-    protected function _template_settings()
814
-    {
815
-        $this->_template_args['values'] = $this->_yes_no_values;
816
-        /**
817
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
818
-         * from General_Settings_Admin_Page to here.
819
-         */
820
-        $this->_template_args = apply_filters(
821
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
822
-            $this->_template_args
823
-        );
824
-        $this->_set_add_edit_form_tags('update_template_settings');
825
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
826
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
827
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
828
-            $this->_template_args,
829
-            true
830
-        );
831
-        $this->display_admin_page_with_sidebar();
832
-    }
833
-
834
-
835
-    /**
836
-     * Handler for updating template settings.
837
-     */
838
-    protected function _update_template_settings()
839
-    {
840
-        /**
841
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
842
-         * from General_Settings_Admin_Page to here.
843
-         */
844
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
845
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
846
-            EE_Registry::instance()->CFG->template_settings,
847
-            $this->_req_data
848
-        );
849
-        //update custom post type slugs and detect if we need to flush rewrite rules
850
-        $old_slug                                          = EE_Registry::instance()->CFG->core->event_cpt_slug;
851
-        EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
852
-            ? EE_Registry::instance()->CFG->core->event_cpt_slug
853
-            : sanitize_title_with_dashes($this->_req_data['event_cpt_slug']);
854
-        $what                                              = 'Template Settings';
855
-        $success                                           = $this->_update_espresso_configuration(
856
-            $what,
857
-            EE_Registry::instance()->CFG->template_settings,
858
-            __FILE__,
859
-            __FUNCTION__,
860
-            __LINE__
861
-        );
862
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
863
-            update_option('ee_flush_rewrite_rules', true);
864
-        }
865
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
866
-    }
867
-
868
-
869
-    /**
870
-     * _premium_event_editor_meta_boxes
871
-     * add all metaboxes related to the event_editor
872
-     *
873
-     * @access protected
874
-     * @return void
875
-     * @throws EE_Error
876
-     */
877
-    protected function _premium_event_editor_meta_boxes()
878
-    {
879
-        $this->verify_cpt_object();
880
-        add_meta_box(
881
-            'espresso_event_editor_event_options',
882
-            esc_html__('Event Registration Options', 'event_espresso'),
883
-            array($this, 'registration_options_meta_box'),
884
-            $this->page_slug,
885
-            'side',
886
-            'core'
887
-        );
888
-    }
889
-
890
-
891
-    /**
892
-     * override caf metabox
893
-     *
894
-     * @return void
895
-     * @throws DomainException
896
-     */
897
-    public function registration_options_meta_box()
898
-    {
899
-        $yes_no_values                                    = array(
900
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
901
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
902
-        );
903
-        $default_reg_status_values                        = EEM_Registration::reg_status_array(
904
-            array(
905
-                EEM_Registration::status_id_cancelled,
906
-                EEM_Registration::status_id_declined,
907
-                EEM_Registration::status_id_incomplete,
908
-                EEM_Registration::status_id_wait_list,
909
-            ),
910
-            true
911
-        );
912
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
913
-        $template_args['_event']                          = $this->_cpt_model_obj;
914
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
915
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
916
-            'default_reg_status',
917
-            $default_reg_status_values,
918
-            $this->_cpt_model_obj->default_registration_status()
919
-        );
920
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
921
-            'display_desc',
922
-            $yes_no_values,
923
-            $this->_cpt_model_obj->display_description()
924
-        );
925
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
926
-            'display_ticket_selector',
927
-            $yes_no_values,
928
-            $this->_cpt_model_obj->display_ticket_selector(),
929
-            '',
930
-            '',
931
-            false
932
-        );
933
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
934
-            'EVT_default_registration_status',
935
-            $default_reg_status_values,
936
-            $this->_cpt_model_obj->default_registration_status()
937
-        );
938
-        $template_args['additional_registration_options'] = apply_filters(
939
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
940
-            '',
941
-            $template_args,
942
-            $yes_no_values,
943
-            $default_reg_status_values
944
-        );
945
-        EEH_Template::display_template(
946
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
947
-            $template_args
948
-        );
949
-    }
950
-
951
-
952
-
953
-    /**
954
-     * wp_list_table_mods for caf
955
-     * ============================
956
-     */
957
-    /**
958
-     * hook into list table filters and provide filters for caffeinated list table
959
-     *
960
-     * @param  array $old_filters    any existing filters present
961
-     * @param  array $list_table_obj the list table object
962
-     * @return array                  new filters
963
-     */
964
-    public function list_table_filters($old_filters, $list_table_obj)
965
-    {
966
-        $filters = array();
967
-        //first month/year filters
968
-        $filters[] = $this->espresso_event_months_dropdown();
969
-        $status    = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
970
-        //active status dropdown
971
-        if ($status !== 'draft') {
972
-            $filters[] = $this->active_status_dropdown(
973
-                isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
974
-            );
975
-        }
976
-        //category filter
977
-        $filters[] = $this->category_dropdown();
978
-        return array_merge($old_filters, $filters);
979
-    }
980
-
981
-
982
-    /**
983
-     * espresso_event_months_dropdown
984
-     *
985
-     * @access public
986
-     * @return string                dropdown listing month/year selections for events.
987
-     */
988
-    public function espresso_event_months_dropdown()
989
-    {
990
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
991
-        // Note we need to include any other filters that are set!
992
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
993
-        //categories?
994
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
995
-            ? $this->_req_data['EVT_CAT']
996
-            : null;
997
-        //active status?
998
-        $active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
999
-        $cur_date      = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1000
-        return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * returns a list of "active" statuses on the event
1006
-     *
1007
-     * @param  string $current_value whatever the current active status is
1008
-     * @return string
1009
-     */
1010
-    public function active_status_dropdown($current_value = '')
1011
-    {
1012
-        $select_name = 'active_status';
1013
-        $values      = array(
1014
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1015
-            'active'   => esc_html__('Active', 'event_espresso'),
1016
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1017
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1018
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1019
-        );
1020
-        $id          = 'id="espresso-active-status-dropdown-filter"';
1021
-        $class       = 'wide';
1022
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * output a dropdown of the categories for the category filter on the event admin list table
1028
-     *
1029
-     * @access  public
1030
-     * @return string html
1031
-     */
1032
-    public function category_dropdown()
1033
-    {
1034
-        $cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1035
-        return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * get total number of events today
1041
-     *
1042
-     * @access public
1043
-     * @return int
1044
-     * @throws EE_Error
1045
-     */
1046
-    public function total_events_today()
1047
-    {
1048
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1049
-            'DTT_EVT_start',
1050
-            date('Y-m-d') . ' 00:00:00',
1051
-            'Y-m-d H:i:s',
1052
-            'UTC'
1053
-        );
1054
-        $end   = EEM_Datetime::instance()->convert_datetime_for_query(
1055
-            'DTT_EVT_start',
1056
-            date('Y-m-d') . ' 23:59:59',
1057
-            'Y-m-d H:i:s',
1058
-            'UTC'
1059
-        );
1060
-        $where = array(
1061
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1062
-        );
1063
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1064
-        return $count;
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * get total number of events this month
1070
-     *
1071
-     * @access public
1072
-     * @return int
1073
-     * @throws EE_Error
1074
-     */
1075
-    public function total_events_this_month()
1076
-    {
1077
-        //Dates
1078
-        $this_year_r     = date('Y');
1079
-        $this_month_r    = date('m');
1080
-        $days_this_month = date('t');
1081
-        $start           = EEM_Datetime::instance()->convert_datetime_for_query(
1082
-            'DTT_EVT_start',
1083
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1084
-            'Y-m-d H:i:s',
1085
-            'UTC'
1086
-        );
1087
-        $end             = EEM_Datetime::instance()->convert_datetime_for_query(
1088
-            'DTT_EVT_start',
1089
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1090
-            'Y-m-d H:i:s',
1091
-            'UTC'
1092
-        );
1093
-        $where           = array(
1094
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1095
-        );
1096
-        $count           = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1097
-        return $count;
1098
-    }
1099
-
1100
-
1101
-    /** DEFAULT TICKETS STUFF **/
1102
-
1103
-    /**
1104
-     * Output default tickets list table view.
1105
-     */
1106
-    public function _tickets_overview_list_table()
1107
-    {
1108
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1109
-        $this->display_admin_list_table_page_with_no_sidebar();
1110
-    }
1111
-
1112
-
1113
-    /**
1114
-     * @param int  $per_page
1115
-     * @param bool $count
1116
-     * @param bool $trashed
1117
-     * @return \EE_Soft_Delete_Base_Class[]|int
1118
-     */
1119
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1120
-    {
1121
-        $orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1122
-        $order   = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1123
-        switch ($orderby) {
1124
-            case 'TKT_name':
1125
-                $orderby = array('TKT_name' => $order);
1126
-                break;
1127
-            case 'TKT_price':
1128
-                $orderby = array('TKT_price' => $order);
1129
-                break;
1130
-            case 'TKT_uses':
1131
-                $orderby = array('TKT_uses' => $order);
1132
-                break;
1133
-            case 'TKT_min':
1134
-                $orderby = array('TKT_min' => $order);
1135
-                break;
1136
-            case 'TKT_max':
1137
-                $orderby = array('TKT_max' => $order);
1138
-                break;
1139
-            case 'TKT_qty':
1140
-                $orderby = array('TKT_qty' => $order);
1141
-                break;
1142
-        }
1143
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1144
-            ? $this->_req_data['paged']
1145
-            : 1;
1146
-        $per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1147
-            ? $this->_req_data['perpage']
1148
-            : $per_page;
1149
-        $_where       = array(
1150
-            'TKT_is_default' => 1,
1151
-            'TKT_deleted'    => $trashed,
1152
-        );
1153
-        $offset       = ($current_page - 1) * $per_page;
1154
-        $limit        = array($offset, $per_page);
1155
-        if (isset($this->_req_data['s'])) {
1156
-            $sstr         = '%' . $this->_req_data['s'] . '%';
1157
-            $_where['OR'] = array(
1158
-                'TKT_name'        => array('LIKE', $sstr),
1159
-                'TKT_description' => array('LIKE', $sstr),
1160
-            );
1161
-        }
1162
-        $query_params = array(
1163
-            $_where,
1164
-            'order_by' => $orderby,
1165
-            'limit'    => $limit,
1166
-            'group_by' => 'TKT_ID',
1167
-        );
1168
-        if ($count) {
1169
-            return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1170
-        } else {
1171
-            return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1172
-        }
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * @param bool $trash
1178
-     * @throws EE_Error
1179
-     */
1180
-    protected function _trash_or_restore_ticket($trash = false)
1181
-    {
1182
-        $success = 1;
1183
-        $TKT     = EEM_Ticket::instance();
1184
-        //checkboxes?
1185
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1186
-            //if array has more than one element then success message should be plural
1187
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1188
-            //cycle thru the boxes
1189
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1190
-                if ($trash) {
1191
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1192
-                        $success = 0;
1193
-                    }
1194
-                } else {
1195
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1196
-                        $success = 0;
1197
-                    }
1198
-                }
1199
-            }
1200
-        } else {
1201
-            //grab single id and trash
1202
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1203
-            if ($trash) {
1204
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1205
-                    $success = 0;
1206
-                }
1207
-            } else {
1208
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1209
-                    $success = 0;
1210
-                }
1211
-            }
1212
-        }
1213
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1214
-        $query_args  = array(
1215
-            'action' => 'ticket_list_table',
1216
-            'status' => $trash ? '' : 'trashed',
1217
-        );
1218
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1219
-    }
1220
-
1221
-
1222
-    /**
1223
-     * Handles trashing default ticket.
1224
-     */
1225
-    protected function _delete_ticket()
1226
-    {
1227
-        $success = 1;
1228
-        //checkboxes?
1229
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1230
-            //if array has more than one element then success message should be plural
1231
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1232
-            //cycle thru the boxes
1233
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1234
-                //delete
1235
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1236
-                    $success = 0;
1237
-                }
1238
-            }
1239
-        } else {
1240
-            //grab single id and trash
1241
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1242
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1243
-                $success = 0;
1244
-            }
1245
-        }
1246
-        $action_desc = 'deleted';
1247
-        $query_args  = array(
1248
-            'action' => 'ticket_list_table',
1249
-            'status' => 'trashed',
1250
-        );
1251
-        //fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1252
-        if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1253
-            array(array('TKT_is_default' => 1)),
1254
-            'TKT_ID',
1255
-            true
1256
-        )
1257
-        ) {
1258
-            $query_args = array();
1259
-        }
1260
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1261
-    }
1262
-
1263
-
1264
-    /**
1265
-     * @param int $TKT_ID
1266
-     * @return bool|int
1267
-     * @throws EE_Error
1268
-     */
1269
-    protected function _delete_the_ticket($TKT_ID)
1270
-    {
1271
-        $tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1272
-        $tkt->_remove_relations('Datetime');
1273
-        //delete all related prices first
1274
-        $tkt->delete_related_permanently('Price');
1275
-        return $tkt->delete_permanently();
1276
-    }
17
+	/**
18
+	 * Extend_Events_Admin_Page constructor.
19
+	 *
20
+	 * @param bool $routing
21
+	 */
22
+	public function __construct($routing = true)
23
+	{
24
+		parent::__construct($routing);
25
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
26
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
27
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
28
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
29
+		}
30
+	}
31
+
32
+
33
+	/**
34
+	 * Sets routes.
35
+	 */
36
+	protected function _extend_page_config()
37
+	{
38
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
39
+		//is there a evt_id in the request?
40
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
41
+			? $this->_req_data['EVT_ID']
42
+			: 0;
43
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
44
+		//tkt_id?
45
+		$tkt_id             = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
46
+			? $this->_req_data['TKT_ID']
47
+			: 0;
48
+		$new_page_routes    = array(
49
+			'duplicate_event'          => array(
50
+				'func'       => '_duplicate_event',
51
+				'capability' => 'ee_edit_event',
52
+				'obj_id'     => $evt_id,
53
+				'noheader'   => true,
54
+			),
55
+			'ticket_list_table'        => array(
56
+				'func'       => '_tickets_overview_list_table',
57
+				'capability' => 'ee_read_default_tickets',
58
+			),
59
+			'trash_ticket'             => array(
60
+				'func'       => '_trash_or_restore_ticket',
61
+				'capability' => 'ee_delete_default_ticket',
62
+				'obj_id'     => $tkt_id,
63
+				'noheader'   => true,
64
+				'args'       => array('trash' => true),
65
+			),
66
+			'trash_tickets'            => array(
67
+				'func'       => '_trash_or_restore_ticket',
68
+				'capability' => 'ee_delete_default_tickets',
69
+				'noheader'   => true,
70
+				'args'       => array('trash' => true),
71
+			),
72
+			'restore_ticket'           => array(
73
+				'func'       => '_trash_or_restore_ticket',
74
+				'capability' => 'ee_delete_default_ticket',
75
+				'obj_id'     => $tkt_id,
76
+				'noheader'   => true,
77
+			),
78
+			'restore_tickets'          => array(
79
+				'func'       => '_trash_or_restore_ticket',
80
+				'capability' => 'ee_delete_default_tickets',
81
+				'noheader'   => true,
82
+			),
83
+			'delete_ticket'            => array(
84
+				'func'       => '_delete_ticket',
85
+				'capability' => 'ee_delete_default_ticket',
86
+				'obj_id'     => $tkt_id,
87
+				'noheader'   => true,
88
+			),
89
+			'delete_tickets'           => array(
90
+				'func'       => '_delete_ticket',
91
+				'capability' => 'ee_delete_default_tickets',
92
+				'noheader'   => true,
93
+			),
94
+			'import_page'              => array(
95
+				'func'       => '_import_page',
96
+				'capability' => 'import',
97
+			),
98
+			'import'                   => array(
99
+				'func'       => '_import_events',
100
+				'capability' => 'import',
101
+				'noheader'   => true,
102
+			),
103
+			'import_events'            => array(
104
+				'func'       => '_import_events',
105
+				'capability' => 'import',
106
+				'noheader'   => true,
107
+			),
108
+			'export_events'            => array(
109
+				'func'       => '_events_export',
110
+				'capability' => 'export',
111
+				'noheader'   => true,
112
+			),
113
+			'export_categories'        => array(
114
+				'func'       => '_categories_export',
115
+				'capability' => 'export',
116
+				'noheader'   => true,
117
+			),
118
+			'sample_export_file'       => array(
119
+				'func'       => '_sample_export_file',
120
+				'capability' => 'export',
121
+				'noheader'   => true,
122
+			),
123
+			'update_template_settings' => array(
124
+				'func'       => '_update_template_settings',
125
+				'capability' => 'manage_options',
126
+				'noheader'   => true,
127
+			),
128
+		);
129
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
130
+		//partial route/config override
131
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
132
+		$this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
133
+		$this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
134
+		$this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
135
+		$this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
136
+		$this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
137
+		//add tickets tab but only if there are more than one default ticket!
138
+		$tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
139
+			array(array('TKT_is_default' => 1)),
140
+			'TKT_ID',
141
+			true
142
+		);
143
+		if ($tkt_count > 1) {
144
+			$new_page_config = array(
145
+				'ticket_list_table' => array(
146
+					'nav'           => array(
147
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
148
+						'order' => 60,
149
+					),
150
+					'list_table'    => 'Tickets_List_Table',
151
+					'require_nonce' => false,
152
+				),
153
+			);
154
+		}
155
+		//template settings
156
+		$new_page_config['template_settings'] = array(
157
+			'nav'           => array(
158
+				'label' => esc_html__('Templates', 'event_espresso'),
159
+				'order' => 30,
160
+			),
161
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
162
+			'help_tabs'     => array(
163
+				'general_settings_templates_help_tab' => array(
164
+					'title'    => esc_html__('Templates', 'event_espresso'),
165
+					'filename' => 'general_settings_templates',
166
+				),
167
+			),
168
+			'help_tour'     => array('Templates_Help_Tour'),
169
+			'require_nonce' => false,
170
+		);
171
+		$this->_page_config                   = array_merge($this->_page_config, $new_page_config);
172
+		//add filters and actions
173
+		//modifying _views
174
+		add_filter(
175
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
176
+			array($this, 'add_additional_datetime_button'),
177
+			10,
178
+			2
179
+		);
180
+		add_filter(
181
+			'FHEE_event_datetime_metabox_clone_button_template',
182
+			array($this, 'add_datetime_clone_button'),
183
+			10,
184
+			2
185
+		);
186
+		add_filter(
187
+			'FHEE_event_datetime_metabox_timezones_template',
188
+			array($this, 'datetime_timezones_template'),
189
+			10,
190
+			2
191
+		);
192
+		//filters for event list table
193
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
194
+		add_filter(
195
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
196
+			array($this, 'extra_list_table_actions'),
197
+			10,
198
+			2
199
+		);
200
+		//legend item
201
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
202
+		add_action('admin_init', array($this, 'admin_init'));
203
+		//heartbeat stuff
204
+		add_filter('heartbeat_received', array($this, 'heartbeat_response'), 10, 2);
205
+	}
206
+
207
+
208
+	/**
209
+	 * admin_init
210
+	 */
211
+	public function admin_init()
212
+	{
213
+		EE_Registry::$i18n_js_strings = array_merge(
214
+			EE_Registry::$i18n_js_strings,
215
+			array(
216
+				'image_confirm'          => esc_html__(
217
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
218
+					'event_espresso'
219
+				),
220
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
221
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
222
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
223
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
224
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
225
+			)
226
+		);
227
+	}
228
+
229
+
230
+	/**
231
+	 * This will be used to listen for any heartbeat data packages coming via the WordPress heartbeat API and handle
232
+	 * accordingly.
233
+	 *
234
+	 * @param array $response The existing heartbeat response array.
235
+	 * @param array $data     The incoming data package.
236
+	 * @return array  possibly appended response.
237
+	 */
238
+	public function heartbeat_response($response, $data)
239
+	{
240
+		/**
241
+		 * check whether count of tickets is approaching the potential
242
+		 * limits for the server.
243
+		 */
244
+		if (! empty($data['input_count'])) {
245
+			$response['max_input_vars_check'] = EE_Registry::instance()->CFG->environment->max_input_vars_limit_check(
246
+				$data['input_count']
247
+			);
248
+		}
249
+		return $response;
250
+	}
251
+
252
+
253
+	/**
254
+	 * Add per page screen options to the default ticket list table view.
255
+	 */
256
+	protected function _add_screen_options_ticket_list_table()
257
+	{
258
+		$this->_per_page_screen_option();
259
+	}
260
+
261
+
262
+	/**
263
+	 * @param string $return
264
+	 * @param int    $id
265
+	 * @param string $new_title
266
+	 * @param string $new_slug
267
+	 * @return string
268
+	 */
269
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
270
+	{
271
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
272
+		//make sure this is only when editing
273
+		if (! empty($id)) {
274
+			$href   = EE_Admin_Page::add_query_args_and_nonce(
275
+				array('action' => 'duplicate_event', 'EVT_ID' => $id),
276
+				$this->_admin_base_url
277
+			);
278
+			$title  = esc_attr__('Duplicate Event', 'event_espresso');
279
+			$return .= '<a href="'
280
+					   . $href
281
+					   . '" title="'
282
+					   . $title
283
+					   . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
284
+					   . $title
285
+					   . '</a>';
286
+		}
287
+		return $return;
288
+	}
289
+
290
+
291
+	/**
292
+	 * Set the list table views for the default ticket list table view.
293
+	 */
294
+	public function _set_list_table_views_ticket_list_table()
295
+	{
296
+		$this->_views = array(
297
+			'all'     => array(
298
+				'slug'        => 'all',
299
+				'label'       => esc_html__('All', 'event_espresso'),
300
+				'count'       => 0,
301
+				'bulk_action' => array(
302
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
303
+				),
304
+			),
305
+			'trashed' => array(
306
+				'slug'        => 'trashed',
307
+				'label'       => esc_html__('Trash', 'event_espresso'),
308
+				'count'       => 0,
309
+				'bulk_action' => array(
310
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
311
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
312
+				),
313
+			),
314
+		);
315
+	}
316
+
317
+
318
+	/**
319
+	 * Enqueue scripts and styles for the event editor.
320
+	 */
321
+	public function load_scripts_styles_edit()
322
+	{
323
+		wp_register_script(
324
+			'ee-event-editor-heartbeat',
325
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
326
+			array('ee_admin_js', 'heartbeat'),
327
+			EVENT_ESPRESSO_VERSION,
328
+			true
329
+		);
330
+		wp_enqueue_script('ee-accounting');
331
+		//styles
332
+		wp_enqueue_style('espresso-ui-theme');
333
+		wp_enqueue_script('event_editor_js');
334
+		wp_enqueue_script('ee-event-editor-heartbeat');
335
+	}
336
+
337
+
338
+	/**
339
+	 * Returns template for the additional datetime.
340
+	 * @param $template
341
+	 * @param $template_args
342
+	 * @return mixed
343
+	 * @throws DomainException
344
+	 */
345
+	public function add_additional_datetime_button($template, $template_args)
346
+	{
347
+		return EEH_Template::display_template(
348
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
349
+			$template_args,
350
+			true
351
+		);
352
+	}
353
+
354
+
355
+	/**
356
+	 * Returns the template for cloning a datetime.
357
+	 * @param $template
358
+	 * @param $template_args
359
+	 * @return mixed
360
+	 * @throws DomainException
361
+	 */
362
+	public function add_datetime_clone_button($template, $template_args)
363
+	{
364
+		return EEH_Template::display_template(
365
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
366
+			$template_args,
367
+			true
368
+		);
369
+	}
370
+
371
+
372
+	/**
373
+	 * Returns the template for datetime timezones.
374
+	 * @param $template
375
+	 * @param $template_args
376
+	 * @return mixed
377
+	 * @throws DomainException
378
+	 */
379
+	public function datetime_timezones_template($template, $template_args)
380
+	{
381
+		return EEH_Template::display_template(
382
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
383
+			$template_args,
384
+			true
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Sets the views for the default list table view.
391
+	 */
392
+	protected function _set_list_table_views_default()
393
+	{
394
+		parent::_set_list_table_views_default();
395
+		$new_views    = array(
396
+			'today' => array(
397
+				'slug'        => 'today',
398
+				'label'       => esc_html__('Today', 'event_espresso'),
399
+				'count'       => $this->total_events_today(),
400
+				'bulk_action' => array(
401
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
402
+				),
403
+			),
404
+			'month' => array(
405
+				'slug'        => 'month',
406
+				'label'       => esc_html__('This Month', 'event_espresso'),
407
+				'count'       => $this->total_events_this_month(),
408
+				'bulk_action' => array(
409
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
410
+				),
411
+			),
412
+		);
413
+		$this->_views = array_merge($this->_views, $new_views);
414
+	}
415
+
416
+
417
+	/**
418
+	 * Returns the extra action links for the default list table view.
419
+	 * @param array     $action_links
420
+	 * @param \EE_Event $event
421
+	 * @return array
422
+	 * @throws EE_Error
423
+	 */
424
+	public function extra_list_table_actions(array $action_links, \EE_Event $event)
425
+	{
426
+		if (EE_Registry::instance()->CAP->current_user_can(
427
+			'ee_read_registrations',
428
+			'espresso_registrations_reports',
429
+			$event->ID()
430
+		)
431
+		) {
432
+			$reports_query_args = array(
433
+				'action' => 'reports',
434
+				'EVT_ID' => $event->ID(),
435
+			);
436
+			$reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
437
+			$action_links[]     = '<a href="'
438
+								  . $reports_link
439
+								  . '" title="'
440
+								  . esc_attr__('View Report', 'event_espresso')
441
+								  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
442
+								  . "\n\t";
443
+		}
444
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
445
+			EE_Registry::instance()->load_helper('MSG_Template');
446
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
447
+				'see_notifications_for',
448
+				null,
449
+				array('EVT_ID' => $event->ID())
450
+			);
451
+		}
452
+		return $action_links;
453
+	}
454
+
455
+
456
+	/**
457
+	 * @param $items
458
+	 * @return mixed
459
+	 */
460
+	public function additional_legend_items($items)
461
+	{
462
+		if (EE_Registry::instance()->CAP->current_user_can(
463
+			'ee_read_registrations',
464
+			'espresso_registrations_reports'
465
+		)
466
+		) {
467
+			$items['reports'] = array(
468
+				'class' => 'dashicons dashicons-chart-bar',
469
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
470
+			);
471
+		}
472
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
473
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
474
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
475
+				$items['view_related_messages'] = array(
476
+					'class' => $related_for_icon['css_class'],
477
+					'desc'  => $related_for_icon['label'],
478
+				);
479
+			}
480
+		}
481
+		return $items;
482
+	}
483
+
484
+
485
+	/**
486
+	 * This is the callback method for the duplicate event route
487
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
488
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
489
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
490
+	 * After duplication the redirect is to the new event edit page.
491
+	 *
492
+	 * @return void
493
+	 * @access protected
494
+	 * @throws EE_Error If EE_Event is not available with given ID
495
+	 */
496
+	protected function _duplicate_event()
497
+	{
498
+		// first make sure the ID for the event is in the request.
499
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
500
+		if (! isset($this->_req_data['EVT_ID'])) {
501
+			EE_Error::add_error(
502
+				esc_html__(
503
+					'In order to duplicate an event an Event ID is required.  None was given.',
504
+					'event_espresso'
505
+				),
506
+				__FILE__,
507
+				__FUNCTION__,
508
+				__LINE__
509
+			);
510
+			$this->_redirect_after_action(false, '', '', array(), true);
511
+			return;
512
+		}
513
+		//k we've got EVT_ID so let's use that to get the event we'll duplicate
514
+		$orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
515
+		if (! $orig_event instanceof EE_Event) {
516
+			throw new EE_Error(
517
+				sprintf(
518
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
519
+					$this->_req_data['EVT_ID']
520
+				)
521
+			);
522
+		}
523
+		//k now let's clone the $orig_event before getting relations
524
+		$new_event = clone $orig_event;
525
+		//original datetimes
526
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
527
+		//other original relations
528
+		$orig_ven = $orig_event->get_many_related('Venue');
529
+		//reset the ID and modify other details to make it clear this is a dupe
530
+		$new_event->set('EVT_ID', 0);
531
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
532
+		$new_event->set('EVT_name', $new_name);
533
+		$new_event->set(
534
+			'EVT_slug',
535
+			wp_unique_post_slug(
536
+				sanitize_title($orig_event->name()),
537
+				0,
538
+				'publish',
539
+				'espresso_events',
540
+				0
541
+			)
542
+		);
543
+		$new_event->set('status', 'draft');
544
+		//duplicate discussion settings
545
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
546
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
547
+		//save the new event
548
+		$new_event->save();
549
+		//venues
550
+		foreach ($orig_ven as $ven) {
551
+			$new_event->_add_relation_to($ven, 'Venue');
552
+		}
553
+		$new_event->save();
554
+		//now we need to get the question group relations and handle that
555
+		//first primary question groups
556
+		$orig_primary_qgs = $orig_event->get_many_related(
557
+			'Question_Group',
558
+			array(array('Event_Question_Group.EQG_primary' => 1))
559
+		);
560
+		if (! empty($orig_primary_qgs)) {
561
+			foreach ($orig_primary_qgs as $id => $obj) {
562
+				if ($obj instanceof EE_Question_Group) {
563
+					$new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 1));
564
+				}
565
+			}
566
+		}
567
+		//next additional attendee question groups
568
+		$orig_additional_qgs = $orig_event->get_many_related(
569
+			'Question_Group',
570
+			array(array('Event_Question_Group.EQG_primary' => 0))
571
+		);
572
+		if (! empty($orig_additional_qgs)) {
573
+			foreach ($orig_additional_qgs as $id => $obj) {
574
+				if ($obj instanceof EE_Question_Group) {
575
+					$new_event->_add_relation_to($obj, 'Question_Group', array('EQG_primary' => 0));
576
+				}
577
+			}
578
+		}
579
+
580
+		$new_event->save();
581
+
582
+		//k now that we have the new event saved we can loop through the datetimes and start adding relations.
583
+		$cloned_tickets = array();
584
+		foreach ($orig_datetimes as $orig_dtt) {
585
+			if (! $orig_dtt instanceof EE_Datetime) {
586
+				continue;
587
+			}
588
+			$new_dtt   = clone $orig_dtt;
589
+			$orig_tkts = $orig_dtt->tickets();
590
+			//save new dtt then add to event
591
+			$new_dtt->set('DTT_ID', 0);
592
+			$new_dtt->set('DTT_sold', 0);
593
+			$new_dtt->set_reserved(0);
594
+			$new_dtt->save();
595
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
596
+			$new_event->save();
597
+			//now let's get the ticket relations setup.
598
+			foreach ((array)$orig_tkts as $orig_tkt) {
599
+				//it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
600
+				if (! $orig_tkt instanceof EE_Ticket) {
601
+					continue;
602
+				}
603
+				//is this ticket archived?  If it is then let's skip
604
+				if ($orig_tkt->get('TKT_deleted')) {
605
+					continue;
606
+				}
607
+				// does this original ticket already exist in the clone_tickets cache?
608
+				//  If so we'll just use the new ticket from it.
609
+				if (isset($cloned_tickets[$orig_tkt->ID()])) {
610
+					$new_tkt = $cloned_tickets[$orig_tkt->ID()];
611
+				} else {
612
+					$new_tkt = clone $orig_tkt;
613
+					//get relations on the $orig_tkt that we need to setup.
614
+					$orig_prices = $orig_tkt->prices();
615
+					$new_tkt->set('TKT_ID', 0);
616
+					$new_tkt->set('TKT_sold', 0);
617
+					$new_tkt->set('TKT_reserved', 0);
618
+					$new_tkt->save(); //make sure new ticket has ID.
619
+					//price relations on new ticket need to be setup.
620
+					foreach ($orig_prices as $orig_price) {
621
+						$new_price = clone $orig_price;
622
+						$new_price->set('PRC_ID', 0);
623
+						$new_price->save();
624
+						$new_tkt->_add_relation_to($new_price, 'Price');
625
+						$new_tkt->save();
626
+					}
627
+
628
+					do_action(
629
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
630
+						$orig_tkt,
631
+						$new_tkt,
632
+						$orig_prices,
633
+						$orig_event,
634
+						$orig_dtt,
635
+						$new_dtt
636
+					);
637
+				}
638
+				// k now we can add the new ticket as a relation to the new datetime
639
+				// and make sure its added to our cached $cloned_tickets array
640
+				// for use with later datetimes that have the same ticket.
641
+				$new_dtt->_add_relation_to($new_tkt, 'Ticket');
642
+				$new_dtt->save();
643
+				$cloned_tickets[$orig_tkt->ID()] = $new_tkt;
644
+			}
645
+		}
646
+		//clone taxonomy information
647
+		$taxonomies_to_clone_with = apply_filters(
648
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
649
+			array('espresso_event_categories', 'espresso_event_type', 'post_tag')
650
+		);
651
+		//get terms for original event (notice)
652
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
653
+		//loop through terms and add them to new event.
654
+		foreach ($orig_terms as $term) {
655
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
656
+		}
657
+
658
+		//duplicate other core WP_Post items for this event.
659
+		//post thumbnail (feature image).
660
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
661
+		if ($feature_image_id) {
662
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
663
+		}
664
+
665
+		//duplicate page_template setting
666
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
667
+		if ($page_template) {
668
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
669
+		}
670
+
671
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
672
+		//now let's redirect to the edit page for this duplicated event if we have a new event id.
673
+		if ($new_event->ID()) {
674
+			$redirect_args = array(
675
+				'post'   => $new_event->ID(),
676
+				'action' => 'edit',
677
+			);
678
+			EE_Error::add_success(
679
+				esc_html__(
680
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
681
+					'event_espresso'
682
+				)
683
+			);
684
+		} else {
685
+			$redirect_args = array(
686
+				'action' => 'default',
687
+			);
688
+			EE_Error::add_error(
689
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
690
+				__FILE__,
691
+				__FUNCTION__,
692
+				__LINE__
693
+			);
694
+		}
695
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
696
+	}
697
+
698
+
699
+	/**
700
+	 * Generates output for the import page.
701
+	 * @throws DomainException
702
+	 */
703
+	protected function _import_page()
704
+	{
705
+		$title                                      = esc_html__('Import', 'event_espresso');
706
+		$intro                                      = esc_html__(
707
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
708
+			'event_espresso'
709
+		);
710
+		$form_url                                   = EVENTS_ADMIN_URL;
711
+		$action                                     = 'import_events';
712
+		$type                                       = 'csv';
713
+		$this->_template_args['form']               = EE_Import::instance()->upload_form(
714
+			$title, $intro, $form_url, $action, $type
715
+		);
716
+		$this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
717
+			array('action' => 'sample_export_file'),
718
+			$this->_admin_base_url
719
+		);
720
+		$content                                    = EEH_Template::display_template(
721
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
722
+			$this->_template_args,
723
+			true
724
+		);
725
+		$this->_template_args['admin_page_content'] = $content;
726
+		$this->display_admin_page_with_sidebar();
727
+	}
728
+
729
+
730
+	/**
731
+	 * _import_events
732
+	 * This handles displaying the screen and running imports for importing events.
733
+	 *
734
+	 * @return void
735
+	 */
736
+	protected function _import_events()
737
+	{
738
+		require_once(EE_CLASSES . 'EE_Import.class.php');
739
+		$success = EE_Import::instance()->import();
740
+		$this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
741
+	}
742
+
743
+
744
+	/**
745
+	 * _events_export
746
+	 * Will export all (or just the given event) to a Excel compatible file.
747
+	 *
748
+	 * @access protected
749
+	 * @return void
750
+	 */
751
+	protected function _events_export()
752
+	{
753
+		if (isset($this->_req_data['EVT_ID'])) {
754
+			$event_ids = $this->_req_data['EVT_ID'];
755
+		} elseif (isset($this->_req_data['EVT_IDs'])) {
756
+			$event_ids = $this->_req_data['EVT_IDs'];
757
+		} else {
758
+			$event_ids = null;
759
+		}
760
+		//todo: I don't like doing this but it'll do until we modify EE_Export Class.
761
+		$new_request_args = array(
762
+			'export' => 'report',
763
+			'action' => 'all_event_data',
764
+			'EVT_ID' => $event_ids,
765
+		);
766
+		$this->_req_data  = array_merge($this->_req_data, $new_request_args);
767
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
768
+			require_once(EE_CLASSES . 'EE_Export.class.php');
769
+			$EE_Export = EE_Export::instance($this->_req_data);
770
+			$EE_Export->export();
771
+		}
772
+	}
773
+
774
+
775
+	/**
776
+	 * handle category exports()
777
+	 *
778
+	 * @return void
779
+	 */
780
+	protected function _categories_export()
781
+	{
782
+		//todo: I don't like doing this but it'll do until we modify EE_Export Class.
783
+		$new_request_args = array(
784
+			'export'       => 'report',
785
+			'action'       => 'categories',
786
+			'category_ids' => $this->_req_data['EVT_CAT_ID'],
787
+		);
788
+		$this->_req_data  = array_merge($this->_req_data, $new_request_args);
789
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
790
+			require_once(EE_CLASSES . 'EE_Export.class.php');
791
+			$EE_Export = EE_Export::instance($this->_req_data);
792
+			$EE_Export->export();
793
+		}
794
+	}
795
+
796
+
797
+	/**
798
+	 * Creates a sample CSV file for importing
799
+	 */
800
+	protected function _sample_export_file()
801
+	{
802
+		//		require_once(EE_CLASSES . 'EE_Export.class.php');
803
+		EE_Export::instance()->export_sample();
804
+	}
805
+
806
+
807
+	/*************        Template Settings        *************/
808
+	/**
809
+	 * Generates template settings page output
810
+	 * @throws DomainException
811
+	 * @throws EE_Error
812
+	 */
813
+	protected function _template_settings()
814
+	{
815
+		$this->_template_args['values'] = $this->_yes_no_values;
816
+		/**
817
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
818
+		 * from General_Settings_Admin_Page to here.
819
+		 */
820
+		$this->_template_args = apply_filters(
821
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
822
+			$this->_template_args
823
+		);
824
+		$this->_set_add_edit_form_tags('update_template_settings');
825
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
826
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
827
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
828
+			$this->_template_args,
829
+			true
830
+		);
831
+		$this->display_admin_page_with_sidebar();
832
+	}
833
+
834
+
835
+	/**
836
+	 * Handler for updating template settings.
837
+	 */
838
+	protected function _update_template_settings()
839
+	{
840
+		/**
841
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
842
+		 * from General_Settings_Admin_Page to here.
843
+		 */
844
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
845
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
846
+			EE_Registry::instance()->CFG->template_settings,
847
+			$this->_req_data
848
+		);
849
+		//update custom post type slugs and detect if we need to flush rewrite rules
850
+		$old_slug                                          = EE_Registry::instance()->CFG->core->event_cpt_slug;
851
+		EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
852
+			? EE_Registry::instance()->CFG->core->event_cpt_slug
853
+			: sanitize_title_with_dashes($this->_req_data['event_cpt_slug']);
854
+		$what                                              = 'Template Settings';
855
+		$success                                           = $this->_update_espresso_configuration(
856
+			$what,
857
+			EE_Registry::instance()->CFG->template_settings,
858
+			__FILE__,
859
+			__FUNCTION__,
860
+			__LINE__
861
+		);
862
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
863
+			update_option('ee_flush_rewrite_rules', true);
864
+		}
865
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
866
+	}
867
+
868
+
869
+	/**
870
+	 * _premium_event_editor_meta_boxes
871
+	 * add all metaboxes related to the event_editor
872
+	 *
873
+	 * @access protected
874
+	 * @return void
875
+	 * @throws EE_Error
876
+	 */
877
+	protected function _premium_event_editor_meta_boxes()
878
+	{
879
+		$this->verify_cpt_object();
880
+		add_meta_box(
881
+			'espresso_event_editor_event_options',
882
+			esc_html__('Event Registration Options', 'event_espresso'),
883
+			array($this, 'registration_options_meta_box'),
884
+			$this->page_slug,
885
+			'side',
886
+			'core'
887
+		);
888
+	}
889
+
890
+
891
+	/**
892
+	 * override caf metabox
893
+	 *
894
+	 * @return void
895
+	 * @throws DomainException
896
+	 */
897
+	public function registration_options_meta_box()
898
+	{
899
+		$yes_no_values                                    = array(
900
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
901
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
902
+		);
903
+		$default_reg_status_values                        = EEM_Registration::reg_status_array(
904
+			array(
905
+				EEM_Registration::status_id_cancelled,
906
+				EEM_Registration::status_id_declined,
907
+				EEM_Registration::status_id_incomplete,
908
+				EEM_Registration::status_id_wait_list,
909
+			),
910
+			true
911
+		);
912
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
913
+		$template_args['_event']                          = $this->_cpt_model_obj;
914
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
915
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
916
+			'default_reg_status',
917
+			$default_reg_status_values,
918
+			$this->_cpt_model_obj->default_registration_status()
919
+		);
920
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
921
+			'display_desc',
922
+			$yes_no_values,
923
+			$this->_cpt_model_obj->display_description()
924
+		);
925
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
926
+			'display_ticket_selector',
927
+			$yes_no_values,
928
+			$this->_cpt_model_obj->display_ticket_selector(),
929
+			'',
930
+			'',
931
+			false
932
+		);
933
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
934
+			'EVT_default_registration_status',
935
+			$default_reg_status_values,
936
+			$this->_cpt_model_obj->default_registration_status()
937
+		);
938
+		$template_args['additional_registration_options'] = apply_filters(
939
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
940
+			'',
941
+			$template_args,
942
+			$yes_no_values,
943
+			$default_reg_status_values
944
+		);
945
+		EEH_Template::display_template(
946
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
947
+			$template_args
948
+		);
949
+	}
950
+
951
+
952
+
953
+	/**
954
+	 * wp_list_table_mods for caf
955
+	 * ============================
956
+	 */
957
+	/**
958
+	 * hook into list table filters and provide filters for caffeinated list table
959
+	 *
960
+	 * @param  array $old_filters    any existing filters present
961
+	 * @param  array $list_table_obj the list table object
962
+	 * @return array                  new filters
963
+	 */
964
+	public function list_table_filters($old_filters, $list_table_obj)
965
+	{
966
+		$filters = array();
967
+		//first month/year filters
968
+		$filters[] = $this->espresso_event_months_dropdown();
969
+		$status    = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
970
+		//active status dropdown
971
+		if ($status !== 'draft') {
972
+			$filters[] = $this->active_status_dropdown(
973
+				isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
974
+			);
975
+		}
976
+		//category filter
977
+		$filters[] = $this->category_dropdown();
978
+		return array_merge($old_filters, $filters);
979
+	}
980
+
981
+
982
+	/**
983
+	 * espresso_event_months_dropdown
984
+	 *
985
+	 * @access public
986
+	 * @return string                dropdown listing month/year selections for events.
987
+	 */
988
+	public function espresso_event_months_dropdown()
989
+	{
990
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
991
+		// Note we need to include any other filters that are set!
992
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
993
+		//categories?
994
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
995
+			? $this->_req_data['EVT_CAT']
996
+			: null;
997
+		//active status?
998
+		$active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
999
+		$cur_date      = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1000
+		return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * returns a list of "active" statuses on the event
1006
+	 *
1007
+	 * @param  string $current_value whatever the current active status is
1008
+	 * @return string
1009
+	 */
1010
+	public function active_status_dropdown($current_value = '')
1011
+	{
1012
+		$select_name = 'active_status';
1013
+		$values      = array(
1014
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1015
+			'active'   => esc_html__('Active', 'event_espresso'),
1016
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1017
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1018
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1019
+		);
1020
+		$id          = 'id="espresso-active-status-dropdown-filter"';
1021
+		$class       = 'wide';
1022
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * output a dropdown of the categories for the category filter on the event admin list table
1028
+	 *
1029
+	 * @access  public
1030
+	 * @return string html
1031
+	 */
1032
+	public function category_dropdown()
1033
+	{
1034
+		$cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1035
+		return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * get total number of events today
1041
+	 *
1042
+	 * @access public
1043
+	 * @return int
1044
+	 * @throws EE_Error
1045
+	 */
1046
+	public function total_events_today()
1047
+	{
1048
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1049
+			'DTT_EVT_start',
1050
+			date('Y-m-d') . ' 00:00:00',
1051
+			'Y-m-d H:i:s',
1052
+			'UTC'
1053
+		);
1054
+		$end   = EEM_Datetime::instance()->convert_datetime_for_query(
1055
+			'DTT_EVT_start',
1056
+			date('Y-m-d') . ' 23:59:59',
1057
+			'Y-m-d H:i:s',
1058
+			'UTC'
1059
+		);
1060
+		$where = array(
1061
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1062
+		);
1063
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1064
+		return $count;
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * get total number of events this month
1070
+	 *
1071
+	 * @access public
1072
+	 * @return int
1073
+	 * @throws EE_Error
1074
+	 */
1075
+	public function total_events_this_month()
1076
+	{
1077
+		//Dates
1078
+		$this_year_r     = date('Y');
1079
+		$this_month_r    = date('m');
1080
+		$days_this_month = date('t');
1081
+		$start           = EEM_Datetime::instance()->convert_datetime_for_query(
1082
+			'DTT_EVT_start',
1083
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1084
+			'Y-m-d H:i:s',
1085
+			'UTC'
1086
+		);
1087
+		$end             = EEM_Datetime::instance()->convert_datetime_for_query(
1088
+			'DTT_EVT_start',
1089
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1090
+			'Y-m-d H:i:s',
1091
+			'UTC'
1092
+		);
1093
+		$where           = array(
1094
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1095
+		);
1096
+		$count           = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1097
+		return $count;
1098
+	}
1099
+
1100
+
1101
+	/** DEFAULT TICKETS STUFF **/
1102
+
1103
+	/**
1104
+	 * Output default tickets list table view.
1105
+	 */
1106
+	public function _tickets_overview_list_table()
1107
+	{
1108
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1109
+		$this->display_admin_list_table_page_with_no_sidebar();
1110
+	}
1111
+
1112
+
1113
+	/**
1114
+	 * @param int  $per_page
1115
+	 * @param bool $count
1116
+	 * @param bool $trashed
1117
+	 * @return \EE_Soft_Delete_Base_Class[]|int
1118
+	 */
1119
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1120
+	{
1121
+		$orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1122
+		$order   = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1123
+		switch ($orderby) {
1124
+			case 'TKT_name':
1125
+				$orderby = array('TKT_name' => $order);
1126
+				break;
1127
+			case 'TKT_price':
1128
+				$orderby = array('TKT_price' => $order);
1129
+				break;
1130
+			case 'TKT_uses':
1131
+				$orderby = array('TKT_uses' => $order);
1132
+				break;
1133
+			case 'TKT_min':
1134
+				$orderby = array('TKT_min' => $order);
1135
+				break;
1136
+			case 'TKT_max':
1137
+				$orderby = array('TKT_max' => $order);
1138
+				break;
1139
+			case 'TKT_qty':
1140
+				$orderby = array('TKT_qty' => $order);
1141
+				break;
1142
+		}
1143
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1144
+			? $this->_req_data['paged']
1145
+			: 1;
1146
+		$per_page     = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1147
+			? $this->_req_data['perpage']
1148
+			: $per_page;
1149
+		$_where       = array(
1150
+			'TKT_is_default' => 1,
1151
+			'TKT_deleted'    => $trashed,
1152
+		);
1153
+		$offset       = ($current_page - 1) * $per_page;
1154
+		$limit        = array($offset, $per_page);
1155
+		if (isset($this->_req_data['s'])) {
1156
+			$sstr         = '%' . $this->_req_data['s'] . '%';
1157
+			$_where['OR'] = array(
1158
+				'TKT_name'        => array('LIKE', $sstr),
1159
+				'TKT_description' => array('LIKE', $sstr),
1160
+			);
1161
+		}
1162
+		$query_params = array(
1163
+			$_where,
1164
+			'order_by' => $orderby,
1165
+			'limit'    => $limit,
1166
+			'group_by' => 'TKT_ID',
1167
+		);
1168
+		if ($count) {
1169
+			return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1170
+		} else {
1171
+			return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1172
+		}
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * @param bool $trash
1178
+	 * @throws EE_Error
1179
+	 */
1180
+	protected function _trash_or_restore_ticket($trash = false)
1181
+	{
1182
+		$success = 1;
1183
+		$TKT     = EEM_Ticket::instance();
1184
+		//checkboxes?
1185
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1186
+			//if array has more than one element then success message should be plural
1187
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1188
+			//cycle thru the boxes
1189
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1190
+				if ($trash) {
1191
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1192
+						$success = 0;
1193
+					}
1194
+				} else {
1195
+					if (! $TKT->restore_by_ID($TKT_ID)) {
1196
+						$success = 0;
1197
+					}
1198
+				}
1199
+			}
1200
+		} else {
1201
+			//grab single id and trash
1202
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1203
+			if ($trash) {
1204
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1205
+					$success = 0;
1206
+				}
1207
+			} else {
1208
+				if (! $TKT->restore_by_ID($TKT_ID)) {
1209
+					$success = 0;
1210
+				}
1211
+			}
1212
+		}
1213
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1214
+		$query_args  = array(
1215
+			'action' => 'ticket_list_table',
1216
+			'status' => $trash ? '' : 'trashed',
1217
+		);
1218
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1219
+	}
1220
+
1221
+
1222
+	/**
1223
+	 * Handles trashing default ticket.
1224
+	 */
1225
+	protected function _delete_ticket()
1226
+	{
1227
+		$success = 1;
1228
+		//checkboxes?
1229
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1230
+			//if array has more than one element then success message should be plural
1231
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1232
+			//cycle thru the boxes
1233
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1234
+				//delete
1235
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1236
+					$success = 0;
1237
+				}
1238
+			}
1239
+		} else {
1240
+			//grab single id and trash
1241
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1242
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1243
+				$success = 0;
1244
+			}
1245
+		}
1246
+		$action_desc = 'deleted';
1247
+		$query_args  = array(
1248
+			'action' => 'ticket_list_table',
1249
+			'status' => 'trashed',
1250
+		);
1251
+		//fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1252
+		if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1253
+			array(array('TKT_is_default' => 1)),
1254
+			'TKT_ID',
1255
+			true
1256
+		)
1257
+		) {
1258
+			$query_args = array();
1259
+		}
1260
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1261
+	}
1262
+
1263
+
1264
+	/**
1265
+	 * @param int $TKT_ID
1266
+	 * @return bool|int
1267
+	 * @throws EE_Error
1268
+	 */
1269
+	protected function _delete_the_ticket($TKT_ID)
1270
+	{
1271
+		$tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1272
+		$tkt->_remove_relations('Datetime');
1273
+		//delete all related prices first
1274
+		$tkt->delete_related_permanently('Price');
1275
+		return $tkt->delete_permanently();
1276
+	}
1277 1277
 }
Please login to merge, or discard this patch.
core/EE_Cart.core.php 1 patch
Indentation   +416 added lines, -416 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\interfaces\ResettableInterface;
3 3
 
4 4
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
8 8
 
@@ -23,421 +23,421 @@  discard block
 block discarded – undo
23 23
 class EE_Cart implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * instance of the EE_Cart object
28
-     *
29
-     * @access    private
30
-     * @var EE_Cart $_instance
31
-     */
32
-    private static $_instance;
33
-
34
-    /**
35
-     * instance of the EE_Session object
36
-     *
37
-     * @access    protected
38
-     * @var EE_Session $_session
39
-     */
40
-    protected $_session;
41
-
42
-    /**
43
-     * The total Line item which comprises all the children line-item subtotals,
44
-     * which in turn each have their line items.
45
-     * Typically, the line item structure will look like:
46
-     * grand total
47
-     * -tickets-sub-total
48
-     * --ticket1
49
-     * --ticket2
50
-     * --...
51
-     * -taxes-sub-total
52
-     * --tax1
53
-     * --tax2
54
-     *
55
-     * @var EE_Line_Item
56
-     */
57
-    private $_grand_total;
58
-
59
-
60
-
61
-    /**
62
-     * @singleton method used to instantiate class object
63
-     * @access    public
64
-     * @param EE_Line_Item $grand_total
65
-     * @param EE_Session   $session
66
-     * @return \EE_Cart
67
-     * @throws \EE_Error
68
-     */
69
-    public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null)
70
-    {
71
-        if ( ! empty($grand_total)) {
72
-            self::$_instance = new self($grand_total, $session);
73
-        }
74
-        // or maybe retrieve an existing one ?
75
-        if ( ! self::$_instance instanceof EE_Cart) {
76
-            // try getting the cart out of the session
77
-            $saved_cart = $session instanceof EE_Session ? $session->cart() : null;
78
-            self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
79
-            unset($saved_cart);
80
-        }
81
-        // verify that cart is ok and grand total line item exists
82
-        if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
83
-            self::$_instance = new self($grand_total, $session);
84
-        }
85
-        self::$_instance->get_grand_total();
86
-        // once everything is all said and done, save the cart to the EE_Session
87
-        add_action('shutdown', array(self::$_instance, 'save_cart'), 90);
88
-        return self::$_instance;
89
-    }
90
-
91
-
92
-
93
-    /**
94
-     * private constructor to prevent direct creation
95
-     *
96
-     * @Constructor
97
-     * @access private
98
-     * @param EE_Line_Item $grand_total
99
-     * @param EE_Session   $session
100
-     */
101
-    private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null)
102
-    {
103
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
104
-        $this->set_session($session);
105
-        if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
106
-            $this->set_grand_total_line_item($grand_total);
107
-        }
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * Resets the cart completely (whereas empty_cart
114
-     *
115
-     * @param EE_Line_Item $grand_total
116
-     * @param EE_Session   $session
117
-     * @return EE_Cart
118
-     * @throws \EE_Error
119
-     */
120
-    public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null)
121
-    {
122
-        remove_action('shutdown', array(self::$_instance, 'save_cart'), 90);
123
-        if ($session instanceof EE_Session) {
124
-            $session->reset_cart();
125
-        }
126
-        self::$_instance = null;
127
-        return self::instance($grand_total, $session);
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     * @return \EE_Session
134
-     */
135
-    public function session()
136
-    {
137
-        if ( ! $this->_session instanceof EE_Session) {
138
-            $this->set_session();
139
-        }
140
-        return $this->_session;
141
-    }
142
-
143
-
144
-
145
-    /**
146
-     * @param EE_Session $session
147
-     */
148
-    public function set_session(EE_Session $session = null)
149
-    {
150
-        $this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * Sets the cart to match the line item. Especially handy for loading an old cart where you
157
-     *  know the grand total line item on it
158
-     *
159
-     * @param EE_Line_Item $line_item
160
-     */
161
-    public function set_grand_total_line_item(EE_Line_Item $line_item)
162
-    {
163
-        $this->_grand_total = $line_item;
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * get_cart_from_reg_url_link
170
-     *
171
-     * @access public
172
-     * @param EE_Transaction $transaction
173
-     * @param EE_Session     $session
174
-     * @return \EE_Cart
175
-     * @throws \EE_Error
176
-     */
177
-    public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null)
178
-    {
179
-        $grand_total = $transaction->total_line_item();
180
-        $grand_total->get_items();
181
-        $grand_total->tax_descendants();
182
-        return EE_Cart::instance($grand_total, $session);
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
189
-     *
190
-     * @return EE_Line_Item
191
-     * @throws \EE_Error
192
-     */
193
-    private function _create_grand_total()
194
-    {
195
-        $this->_grand_total = EEH_Line_Item::create_total_line_item();
196
-        return $this->_grand_total;
197
-    }
198
-
199
-
200
-
201
-    /**
202
-     * Gets all the line items of object type Ticket
203
-     *
204
-     * @access public
205
-     * @return \EE_Line_Item[]
206
-     */
207
-    public function get_tickets()
208
-    {
209
-        if ($this->_grand_total === null ) {
210
-            return array();
211
-        }
212
-        return EEH_Line_Item::get_ticket_line_items($this->_grand_total);
213
-    }
214
-
215
-
216
-
217
-    /**
218
-     * returns the total quantity of tickets in the cart
219
-     *
220
-     * @access public
221
-     * @return int
222
-     * @throws \EE_Error
223
-     */
224
-    public function all_ticket_quantity_count()
225
-    {
226
-        $tickets = $this->get_tickets();
227
-        if (empty($tickets)) {
228
-            return 0;
229
-        }
230
-        $count = 0;
231
-        foreach ($tickets as $ticket) {
232
-            $count += $ticket->get('LIN_quantity');
233
-        }
234
-        return $count;
235
-    }
236
-
237
-
238
-
239
-    /**
240
-     * Gets all the tax line items
241
-     *
242
-     * @return \EE_Line_Item[]
243
-     * @throws \EE_Error
244
-     */
245
-    public function get_taxes()
246
-    {
247
-        return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children();
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * Gets the total line item (which is a parent of all other line items) on this cart
254
-     *
255
-     * @return EE_Line_Item
256
-     * @throws \EE_Error
257
-     */
258
-    public function get_grand_total()
259
-    {
260
-        return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
261
-    }
262
-
263
-
264
-
265
-    /**
266
-     * @process items for adding to cart
267
-     * @access  public
268
-     * @param EE_Ticket $ticket
269
-     * @param int       $qty
270
-     * @return TRUE on success, FALSE on fail
271
-     * @throws \EE_Error
272
-     */
273
-    public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
274
-    {
275
-        EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty);
276
-        return $this->save_cart() ? true : false;
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * get_cart_total_before_tax
283
-     *
284
-     * @access public
285
-     * @return float
286
-     * @throws \EE_Error
287
-     */
288
-    public function get_cart_total_before_tax()
289
-    {
290
-        return $this->get_grand_total()->recalculate_pre_tax_total();
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     * gets the total amount of tax paid for items in this cart
297
-     *
298
-     * @access public
299
-     * @return float
300
-     * @throws \EE_Error
301
-     */
302
-    public function get_applied_taxes()
303
-    {
304
-        return EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
305
-    }
306
-
307
-
308
-
309
-    /**
310
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
311
-     *
312
-     * @access public
313
-     * @return float
314
-     * @throws \EE_Error
315
-     */
316
-    public function get_cart_grand_total()
317
-    {
318
-        EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
319
-        return $this->get_grand_total()->total();
320
-    }
321
-
322
-
323
-
324
-    /**
325
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
326
-     *
327
-     * @access public
328
-     * @return float
329
-     * @throws \EE_Error
330
-     */
331
-    public function recalculate_all_cart_totals()
332
-    {
333
-        $pre_tax_total = $this->get_cart_total_before_tax();
334
-        $taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
335
-        $this->_grand_total->set_total($pre_tax_total + $taxes_total);
336
-        $this->_grand_total->save_this_and_descendants_to_txn();
337
-        return $this->get_grand_total()->total();
338
-    }
339
-
340
-
341
-
342
-    /**
343
-     * deletes an item from the cart
344
-     *
345
-     * @access public
346
-     * @param array|bool|string $line_item_codes
347
-     * @return int on success, FALSE on fail
348
-     * @throws \EE_Error
349
-     */
350
-    public function delete_items($line_item_codes = false)
351
-    {
352
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
353
-        return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * @remove ALL items from cart and zero ALL totals
360
-     * @access public
361
-     * @return bool
362
-     * @throws \EE_Error
363
-     */
364
-    public function empty_cart()
365
-    {
366
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
367
-        $this->_grand_total = $this->_create_grand_total();
368
-        return $this->save_cart(true);
369
-    }
370
-
371
-
372
-
373
-    /**
374
-     * @remove ALL items from cart and delete total as well
375
-     * @access public
376
-     * @return bool
377
-     * @throws \EE_Error
378
-     */
379
-    public function delete_cart()
380
-    {
381
-        if ($this->_grand_total instanceof EE_Line_Item) {
382
-            $deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total);
383
-            if ($deleted) {
384
-                $deleted += $this->_grand_total->delete();
385
-                $this->_grand_total = null;
386
-                return true;
387
-            }
388
-        }
389
-        return false;
390
-    }
391
-
392
-
393
-
394
-    /**
395
-     * @save   cart to session
396
-     * @access public
397
-     * @param bool $apply_taxes
398
-     * @return TRUE on success, FALSE on fail
399
-     * @throws \EE_Error
400
-     */
401
-    public function save_cart($apply_taxes = true)
402
-    {
403
-        if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) {
404
-            EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
405
-            //make sure we don't cache the transaction because it can get stale
406
-            if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
407
-                && $this->_grand_total->get_one_from_cache('Transaction')->ID()
408
-            ) {
409
-                $this->_grand_total->clear_cache('Transaction', null, true);
410
-            }
411
-        }
412
-        if ($this->session() instanceof EE_Session) {
413
-            return $this->session()->set_cart($this);
414
-        } else {
415
-            return false;
416
-        }
417
-    }
418
-
419
-
420
-
421
-    public function __wakeup()
422
-    {
423
-        if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
424
-            // $this->_grand_total is actually just an ID, so use it to get the object from the db
425
-            $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
426
-        }
427
-    }
428
-
429
-
430
-
431
-    /**
432
-     * @return array
433
-     */
434
-    public function __sleep()
435
-    {
436
-        if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) {
437
-            $this->_grand_total = $this->_grand_total->ID();
438
-        }
439
-        return array('_grand_total');
440
-    }
26
+	/**
27
+	 * instance of the EE_Cart object
28
+	 *
29
+	 * @access    private
30
+	 * @var EE_Cart $_instance
31
+	 */
32
+	private static $_instance;
33
+
34
+	/**
35
+	 * instance of the EE_Session object
36
+	 *
37
+	 * @access    protected
38
+	 * @var EE_Session $_session
39
+	 */
40
+	protected $_session;
41
+
42
+	/**
43
+	 * The total Line item which comprises all the children line-item subtotals,
44
+	 * which in turn each have their line items.
45
+	 * Typically, the line item structure will look like:
46
+	 * grand total
47
+	 * -tickets-sub-total
48
+	 * --ticket1
49
+	 * --ticket2
50
+	 * --...
51
+	 * -taxes-sub-total
52
+	 * --tax1
53
+	 * --tax2
54
+	 *
55
+	 * @var EE_Line_Item
56
+	 */
57
+	private $_grand_total;
58
+
59
+
60
+
61
+	/**
62
+	 * @singleton method used to instantiate class object
63
+	 * @access    public
64
+	 * @param EE_Line_Item $grand_total
65
+	 * @param EE_Session   $session
66
+	 * @return \EE_Cart
67
+	 * @throws \EE_Error
68
+	 */
69
+	public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null)
70
+	{
71
+		if ( ! empty($grand_total)) {
72
+			self::$_instance = new self($grand_total, $session);
73
+		}
74
+		// or maybe retrieve an existing one ?
75
+		if ( ! self::$_instance instanceof EE_Cart) {
76
+			// try getting the cart out of the session
77
+			$saved_cart = $session instanceof EE_Session ? $session->cart() : null;
78
+			self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
79
+			unset($saved_cart);
80
+		}
81
+		// verify that cart is ok and grand total line item exists
82
+		if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) {
83
+			self::$_instance = new self($grand_total, $session);
84
+		}
85
+		self::$_instance->get_grand_total();
86
+		// once everything is all said and done, save the cart to the EE_Session
87
+		add_action('shutdown', array(self::$_instance, 'save_cart'), 90);
88
+		return self::$_instance;
89
+	}
90
+
91
+
92
+
93
+	/**
94
+	 * private constructor to prevent direct creation
95
+	 *
96
+	 * @Constructor
97
+	 * @access private
98
+	 * @param EE_Line_Item $grand_total
99
+	 * @param EE_Session   $session
100
+	 */
101
+	private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null)
102
+	{
103
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
104
+		$this->set_session($session);
105
+		if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
106
+			$this->set_grand_total_line_item($grand_total);
107
+		}
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * Resets the cart completely (whereas empty_cart
114
+	 *
115
+	 * @param EE_Line_Item $grand_total
116
+	 * @param EE_Session   $session
117
+	 * @return EE_Cart
118
+	 * @throws \EE_Error
119
+	 */
120
+	public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null)
121
+	{
122
+		remove_action('shutdown', array(self::$_instance, 'save_cart'), 90);
123
+		if ($session instanceof EE_Session) {
124
+			$session->reset_cart();
125
+		}
126
+		self::$_instance = null;
127
+		return self::instance($grand_total, $session);
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 * @return \EE_Session
134
+	 */
135
+	public function session()
136
+	{
137
+		if ( ! $this->_session instanceof EE_Session) {
138
+			$this->set_session();
139
+		}
140
+		return $this->_session;
141
+	}
142
+
143
+
144
+
145
+	/**
146
+	 * @param EE_Session $session
147
+	 */
148
+	public function set_session(EE_Session $session = null)
149
+	{
150
+		$this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * Sets the cart to match the line item. Especially handy for loading an old cart where you
157
+	 *  know the grand total line item on it
158
+	 *
159
+	 * @param EE_Line_Item $line_item
160
+	 */
161
+	public function set_grand_total_line_item(EE_Line_Item $line_item)
162
+	{
163
+		$this->_grand_total = $line_item;
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * get_cart_from_reg_url_link
170
+	 *
171
+	 * @access public
172
+	 * @param EE_Transaction $transaction
173
+	 * @param EE_Session     $session
174
+	 * @return \EE_Cart
175
+	 * @throws \EE_Error
176
+	 */
177
+	public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null)
178
+	{
179
+		$grand_total = $transaction->total_line_item();
180
+		$grand_total->get_items();
181
+		$grand_total->tax_descendants();
182
+		return EE_Cart::instance($grand_total, $session);
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
189
+	 *
190
+	 * @return EE_Line_Item
191
+	 * @throws \EE_Error
192
+	 */
193
+	private function _create_grand_total()
194
+	{
195
+		$this->_grand_total = EEH_Line_Item::create_total_line_item();
196
+		return $this->_grand_total;
197
+	}
198
+
199
+
200
+
201
+	/**
202
+	 * Gets all the line items of object type Ticket
203
+	 *
204
+	 * @access public
205
+	 * @return \EE_Line_Item[]
206
+	 */
207
+	public function get_tickets()
208
+	{
209
+		if ($this->_grand_total === null ) {
210
+			return array();
211
+		}
212
+		return EEH_Line_Item::get_ticket_line_items($this->_grand_total);
213
+	}
214
+
215
+
216
+
217
+	/**
218
+	 * returns the total quantity of tickets in the cart
219
+	 *
220
+	 * @access public
221
+	 * @return int
222
+	 * @throws \EE_Error
223
+	 */
224
+	public function all_ticket_quantity_count()
225
+	{
226
+		$tickets = $this->get_tickets();
227
+		if (empty($tickets)) {
228
+			return 0;
229
+		}
230
+		$count = 0;
231
+		foreach ($tickets as $ticket) {
232
+			$count += $ticket->get('LIN_quantity');
233
+		}
234
+		return $count;
235
+	}
236
+
237
+
238
+
239
+	/**
240
+	 * Gets all the tax line items
241
+	 *
242
+	 * @return \EE_Line_Item[]
243
+	 * @throws \EE_Error
244
+	 */
245
+	public function get_taxes()
246
+	{
247
+		return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children();
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * Gets the total line item (which is a parent of all other line items) on this cart
254
+	 *
255
+	 * @return EE_Line_Item
256
+	 * @throws \EE_Error
257
+	 */
258
+	public function get_grand_total()
259
+	{
260
+		return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
261
+	}
262
+
263
+
264
+
265
+	/**
266
+	 * @process items for adding to cart
267
+	 * @access  public
268
+	 * @param EE_Ticket $ticket
269
+	 * @param int       $qty
270
+	 * @return TRUE on success, FALSE on fail
271
+	 * @throws \EE_Error
272
+	 */
273
+	public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1)
274
+	{
275
+		EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty);
276
+		return $this->save_cart() ? true : false;
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * get_cart_total_before_tax
283
+	 *
284
+	 * @access public
285
+	 * @return float
286
+	 * @throws \EE_Error
287
+	 */
288
+	public function get_cart_total_before_tax()
289
+	{
290
+		return $this->get_grand_total()->recalculate_pre_tax_total();
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 * gets the total amount of tax paid for items in this cart
297
+	 *
298
+	 * @access public
299
+	 * @return float
300
+	 * @throws \EE_Error
301
+	 */
302
+	public function get_applied_taxes()
303
+	{
304
+		return EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
305
+	}
306
+
307
+
308
+
309
+	/**
310
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
311
+	 *
312
+	 * @access public
313
+	 * @return float
314
+	 * @throws \EE_Error
315
+	 */
316
+	public function get_cart_grand_total()
317
+	{
318
+		EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
319
+		return $this->get_grand_total()->total();
320
+	}
321
+
322
+
323
+
324
+	/**
325
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
326
+	 *
327
+	 * @access public
328
+	 * @return float
329
+	 * @throws \EE_Error
330
+	 */
331
+	public function recalculate_all_cart_totals()
332
+	{
333
+		$pre_tax_total = $this->get_cart_total_before_tax();
334
+		$taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
335
+		$this->_grand_total->set_total($pre_tax_total + $taxes_total);
336
+		$this->_grand_total->save_this_and_descendants_to_txn();
337
+		return $this->get_grand_total()->total();
338
+	}
339
+
340
+
341
+
342
+	/**
343
+	 * deletes an item from the cart
344
+	 *
345
+	 * @access public
346
+	 * @param array|bool|string $line_item_codes
347
+	 * @return int on success, FALSE on fail
348
+	 * @throws \EE_Error
349
+	 */
350
+	public function delete_items($line_item_codes = false)
351
+	{
352
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
353
+		return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * @remove ALL items from cart and zero ALL totals
360
+	 * @access public
361
+	 * @return bool
362
+	 * @throws \EE_Error
363
+	 */
364
+	public function empty_cart()
365
+	{
366
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
367
+		$this->_grand_total = $this->_create_grand_total();
368
+		return $this->save_cart(true);
369
+	}
370
+
371
+
372
+
373
+	/**
374
+	 * @remove ALL items from cart and delete total as well
375
+	 * @access public
376
+	 * @return bool
377
+	 * @throws \EE_Error
378
+	 */
379
+	public function delete_cart()
380
+	{
381
+		if ($this->_grand_total instanceof EE_Line_Item) {
382
+			$deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total);
383
+			if ($deleted) {
384
+				$deleted += $this->_grand_total->delete();
385
+				$this->_grand_total = null;
386
+				return true;
387
+			}
388
+		}
389
+		return false;
390
+	}
391
+
392
+
393
+
394
+	/**
395
+	 * @save   cart to session
396
+	 * @access public
397
+	 * @param bool $apply_taxes
398
+	 * @return TRUE on success, FALSE on fail
399
+	 * @throws \EE_Error
400
+	 */
401
+	public function save_cart($apply_taxes = true)
402
+	{
403
+		if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) {
404
+			EEH_Line_Item::ensure_taxes_applied($this->_grand_total);
405
+			//make sure we don't cache the transaction because it can get stale
406
+			if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
407
+				&& $this->_grand_total->get_one_from_cache('Transaction')->ID()
408
+			) {
409
+				$this->_grand_total->clear_cache('Transaction', null, true);
410
+			}
411
+		}
412
+		if ($this->session() instanceof EE_Session) {
413
+			return $this->session()->set_cart($this);
414
+		} else {
415
+			return false;
416
+		}
417
+	}
418
+
419
+
420
+
421
+	public function __wakeup()
422
+	{
423
+		if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) {
424
+			// $this->_grand_total is actually just an ID, so use it to get the object from the db
425
+			$this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total);
426
+		}
427
+	}
428
+
429
+
430
+
431
+	/**
432
+	 * @return array
433
+	 */
434
+	public function __sleep()
435
+	{
436
+		if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) {
437
+			$this->_grand_total = $this->_grand_total->ID();
438
+		}
439
+		return array('_grand_total');
440
+	}
441 441
 
442 442
 
443 443
 }
Please login to merge, or discard this patch.