Completed
Branch master (d4ace2)
by
unknown
04:43
created
modules/venues_archive/EED_Venues_Archive.module.php 1 patch
Indentation   +174 added lines, -174 removed lines patch added patch discarded remove patch
@@ -29,178 +29,178 @@
 block discarded – undo
29 29
  */
30 30
 class EED_Venues_Archive extends EED_Module
31 31
 {
32
-    /**
33
-     * @return EED_Venues_Archive
34
-     */
35
-    public static function instance()
36
-    {
37
-        return parent::get_instance(__CLASS__);
38
-    }
39
-
40
-
41
-    /**
42
-     * set_hooks - for hooking into EE Core, other modules, etc
43
-     *
44
-     * @return void
45
-     * @throws InvalidArgumentException
46
-     * @throws InvalidDataTypeException
47
-     * @throws InvalidInterfaceException
48
-     */
49
-    public static function set_hooks()
50
-    {
51
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
52
-        $custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
53
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
54
-        );
55
-        $custom_post_types = $custom_post_type_definitions->getDefinitions();
56
-        EE_Config::register_route(
57
-            $custom_post_types[EspressoPostType::VENUES]['plural_slug'],
58
-            'Venues_Archive',
59
-            'run'
60
-        );
61
-    }
62
-
63
-    /**
64
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
-     *
66
-     * @access    public
67
-     * @return    void
68
-     */
69
-    public static function set_hooks_admin()
70
-    {
71
-    }
72
-
73
-
74
-    /**
75
-     * run - initial module setup
76
-     *
77
-     * @access    public
78
-     * @param \WP $WP
79
-     */
80
-    public function run($WP)
81
-    {
82
-        // check what template is loaded
83
-        add_filter('template_include', array($this, 'template_include'), 999, 1);
84
-        add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
85
-    }
86
-
87
-
88
-    /**
89
-     * template_include
90
-     *
91
-     * @access public
92
-     * @param  string $template
93
-     * @return string
94
-     */
95
-    public function template_include($template)
96
-    {
97
-        // not a custom template?
98
-        if (
99
-            EE_Registry::instance()->load_core('Front_Controller', array(), false, true)
100
-                                   ->get_selected_template() != 'archive-espresso_venues.php'
101
-        ) {
102
-            EEH_Template::load_espresso_theme_functions();
103
-            // then add extra event data via hooks
104
-            add_filter('the_title', array($this, 'the_title'), 100, 1);
105
-            // don't know if theme uses the_excerpt
106
-            add_filter('the_excerpt', array($this, 'venue_details'), 100);
107
-            // or the_content
108
-            add_filter('the_content', array($this, 'venue_details'), 100);
109
-            // don't display entry meta because the existing theme will take care of that
110
-            add_filter('FHEE__content_espresso_venues_details_template__display_entry_meta', '__return_false');
111
-        }
112
-        return $template;
113
-    }
114
-
115
-
116
-    /**
117
-     * the_title
118
-     *
119
-     * @access public
120
-     * @param  string $title
121
-     * @return string
122
-     */
123
-    public function the_title($title = '')
124
-    {
125
-        return $title;
126
-    }
127
-
128
-
129
-    /**
130
-     *    venue_details
131
-     *
132
-     * @access public
133
-     * @param  string $content
134
-     * @return string
135
-     */
136
-    public function venue_details($content)
137
-    {
138
-        global $post;
139
-        if (
140
-            $post->post_type == EspressoPostType::VENUES
141
-            && ! post_password_required()
142
-        ) {
143
-            // since the 'content-espresso_venues-details.php' template might be used directly from within a theme,
144
-            // it uses the_content() for displaying the $post->post_content
145
-            // so in order to load a template that uses the_content() from within a callback being used to filter the_content(),
146
-            // we need to first remove this callback from being applied to the_content() (otherwise it will recurse and blow up the interweb)
147
-            remove_filter('the_excerpt', array($this, 'venue_details'), 100);
148
-            remove_filter('the_content', array($this, 'venue_details'), 100);
149
-            // add filters we want
150
-            add_filter('the_content', array($this, 'venue_location'), 110);
151
-            add_filter('the_excerpt', array($this, 'venue_location'), 110);
152
-            // now load our template
153
-            $template = EEH_Template::locate_template('content-espresso_venues-details.php');
154
-            // now add our filter back in, plus some others
155
-            add_filter('the_excerpt', array($this, 'venue_details'), 100);
156
-            add_filter('the_content', array($this, 'venue_details'), 100);
157
-            // remove other filters we added so they won't get applied to the next post
158
-            remove_filter('the_content', array($this, 'venue_location'), 110);
159
-            remove_filter('the_excerpt', array($this, 'venue_location'), 110);
160
-            // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
161
-        }
162
-        return ! empty($template) ? $template : $content;
163
-    }
164
-
165
-
166
-    /**
167
-     * venue_location
168
-     *
169
-     * @access public
170
-     * @param  string $content
171
-     * @return string
172
-     */
173
-    public function venue_location($content)
174
-    {
175
-        return $content . EEH_Template::locate_template('content-espresso_venues-location.php');
176
-    }
177
-
178
-
179
-    /**
180
-     *    wp_enqueue_scripts
181
-     *
182
-     * @access    public
183
-     * @return    void
184
-     */
185
-    public function wp_enqueue_scripts()
186
-    {
187
-        // get some style
188
-        if (apply_filters('FHEE_enable_default_espresso_css', true) && is_archive()) {
189
-            // first check theme folder
190
-            if (is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
191
-                wp_register_style(
192
-                    $this->theme,
193
-                    get_stylesheet_directory_uri() . $this->theme . '/style.css',
194
-                    array('dashicons', 'espresso_default')
195
-                );
196
-            } elseif (is_readable(EE_TEMPLATES . $this->theme . '/style.css')) {
197
-                wp_register_style(
198
-                    $this->theme,
199
-                    EE_TEMPLATES_URL . $this->theme . '/style.css',
200
-                    array('dashicons', 'espresso_default')
201
-                );
202
-            }
203
-            wp_enqueue_style($this->theme);
204
-        }
205
-    }
32
+	/**
33
+	 * @return EED_Venues_Archive
34
+	 */
35
+	public static function instance()
36
+	{
37
+		return parent::get_instance(__CLASS__);
38
+	}
39
+
40
+
41
+	/**
42
+	 * set_hooks - for hooking into EE Core, other modules, etc
43
+	 *
44
+	 * @return void
45
+	 * @throws InvalidArgumentException
46
+	 * @throws InvalidDataTypeException
47
+	 * @throws InvalidInterfaceException
48
+	 */
49
+	public static function set_hooks()
50
+	{
51
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
52
+		$custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
53
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
54
+		);
55
+		$custom_post_types = $custom_post_type_definitions->getDefinitions();
56
+		EE_Config::register_route(
57
+			$custom_post_types[EspressoPostType::VENUES]['plural_slug'],
58
+			'Venues_Archive',
59
+			'run'
60
+		);
61
+	}
62
+
63
+	/**
64
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
+	 *
66
+	 * @access    public
67
+	 * @return    void
68
+	 */
69
+	public static function set_hooks_admin()
70
+	{
71
+	}
72
+
73
+
74
+	/**
75
+	 * run - initial module setup
76
+	 *
77
+	 * @access    public
78
+	 * @param \WP $WP
79
+	 */
80
+	public function run($WP)
81
+	{
82
+		// check what template is loaded
83
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
84
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
85
+	}
86
+
87
+
88
+	/**
89
+	 * template_include
90
+	 *
91
+	 * @access public
92
+	 * @param  string $template
93
+	 * @return string
94
+	 */
95
+	public function template_include($template)
96
+	{
97
+		// not a custom template?
98
+		if (
99
+			EE_Registry::instance()->load_core('Front_Controller', array(), false, true)
100
+								   ->get_selected_template() != 'archive-espresso_venues.php'
101
+		) {
102
+			EEH_Template::load_espresso_theme_functions();
103
+			// then add extra event data via hooks
104
+			add_filter('the_title', array($this, 'the_title'), 100, 1);
105
+			// don't know if theme uses the_excerpt
106
+			add_filter('the_excerpt', array($this, 'venue_details'), 100);
107
+			// or the_content
108
+			add_filter('the_content', array($this, 'venue_details'), 100);
109
+			// don't display entry meta because the existing theme will take care of that
110
+			add_filter('FHEE__content_espresso_venues_details_template__display_entry_meta', '__return_false');
111
+		}
112
+		return $template;
113
+	}
114
+
115
+
116
+	/**
117
+	 * the_title
118
+	 *
119
+	 * @access public
120
+	 * @param  string $title
121
+	 * @return string
122
+	 */
123
+	public function the_title($title = '')
124
+	{
125
+		return $title;
126
+	}
127
+
128
+
129
+	/**
130
+	 *    venue_details
131
+	 *
132
+	 * @access public
133
+	 * @param  string $content
134
+	 * @return string
135
+	 */
136
+	public function venue_details($content)
137
+	{
138
+		global $post;
139
+		if (
140
+			$post->post_type == EspressoPostType::VENUES
141
+			&& ! post_password_required()
142
+		) {
143
+			// since the 'content-espresso_venues-details.php' template might be used directly from within a theme,
144
+			// it uses the_content() for displaying the $post->post_content
145
+			// so in order to load a template that uses the_content() from within a callback being used to filter the_content(),
146
+			// we need to first remove this callback from being applied to the_content() (otherwise it will recurse and blow up the interweb)
147
+			remove_filter('the_excerpt', array($this, 'venue_details'), 100);
148
+			remove_filter('the_content', array($this, 'venue_details'), 100);
149
+			// add filters we want
150
+			add_filter('the_content', array($this, 'venue_location'), 110);
151
+			add_filter('the_excerpt', array($this, 'venue_location'), 110);
152
+			// now load our template
153
+			$template = EEH_Template::locate_template('content-espresso_venues-details.php');
154
+			// now add our filter back in, plus some others
155
+			add_filter('the_excerpt', array($this, 'venue_details'), 100);
156
+			add_filter('the_content', array($this, 'venue_details'), 100);
157
+			// remove other filters we added so they won't get applied to the next post
158
+			remove_filter('the_content', array($this, 'venue_location'), 110);
159
+			remove_filter('the_excerpt', array($this, 'venue_location'), 110);
160
+			// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
161
+		}
162
+		return ! empty($template) ? $template : $content;
163
+	}
164
+
165
+
166
+	/**
167
+	 * venue_location
168
+	 *
169
+	 * @access public
170
+	 * @param  string $content
171
+	 * @return string
172
+	 */
173
+	public function venue_location($content)
174
+	{
175
+		return $content . EEH_Template::locate_template('content-espresso_venues-location.php');
176
+	}
177
+
178
+
179
+	/**
180
+	 *    wp_enqueue_scripts
181
+	 *
182
+	 * @access    public
183
+	 * @return    void
184
+	 */
185
+	public function wp_enqueue_scripts()
186
+	{
187
+		// get some style
188
+		if (apply_filters('FHEE_enable_default_espresso_css', true) && is_archive()) {
189
+			// first check theme folder
190
+			if (is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
191
+				wp_register_style(
192
+					$this->theme,
193
+					get_stylesheet_directory_uri() . $this->theme . '/style.css',
194
+					array('dashicons', 'espresso_default')
195
+				);
196
+			} elseif (is_readable(EE_TEMPLATES . $this->theme . '/style.css')) {
197
+				wp_register_style(
198
+					$this->theme,
199
+					EE_TEMPLATES_URL . $this->theme . '/style.css',
200
+					array('dashicons', 'espresso_default')
201
+				);
202
+			}
203
+			wp_enqueue_style($this->theme);
204
+		}
205
+	}
206 206
 }
Please login to merge, or discard this patch.
modules/batch/EED_Batch.module.php 1 patch
Indentation   +452 added lines, -452 removed lines patch added patch discarded remove patch
@@ -29,456 +29,456 @@
 block discarded – undo
29 29
  */
30 30
 class EED_Batch extends EED_Module
31 31
 {
32
-    public const PAGE_SLUG = 'espresso_batch';
33
-
34
-    /**
35
-     * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
36
-     * processes data only
37
-     */
38
-    const batch_job = 'job';
39
-
40
-    /**
41
-     * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
42
-     * produces a file for download
43
-     */
44
-    const batch_file_job = 'file';
45
-
46
-    /**
47
-     * Possibly value for $_REQUEST[ 'batch' ]. Indicates this request is NOT
48
-     * for a batch job. It's the same as not providing the $_REQUEST[ 'batch' ]
49
-     * at all
50
-     */
51
-    const batch_not_job = 'none';
52
-
53
-    /**
54
-     *
55
-     * @var string 'file', or 'job', or false to indicate its not a batch request at all
56
-     */
57
-    protected $_batch_request_type = '';
58
-
59
-    /**
60
-     * Because we want to use the response in both the localized JS and in the body
61
-     * we need to make this response available between method calls
62
-     *
63
-     * @var JobStepResponse|null
64
-     */
65
-    protected $_job_step_response = null;
66
-
67
-    /**
68
-     * @var LoaderInterface|null
69
-     */
70
-    protected $loader = null;
71
-
72
-
73
-    /**
74
-     * Gets the batch instance
75
-     *
76
-     * @return  EED_Module|EED_Batch
77
-     * @throws EE_Error
78
-     * @throws ReflectionException
79
-     */
80
-    public static function instance(): EED_Batch
81
-    {
82
-        return parent::get_instance(__CLASS__);
83
-    }
84
-
85
-
86
-    /**
87
-     * Sets hooks to enable batch jobs on the frontend. Disabled by default
88
-     * because it's an attack vector and there are currently no implementations
89
-     *
90
-     * @throws EE_Error
91
-     * @throws ReflectionException
92
-     */
93
-    public static function set_hooks()
94
-    {
95
-        // because this is a possible attack vector, let's have this disabled until
96
-        // we at least have a real use for it on the frontend
97
-        if (apply_filters('FHEE__EED_Batch__set_hooks__enable_frontend_batch', false)) {
98
-            add_action('wp_enqueue_scripts', [self::instance(), 'enqueue_scripts']);
99
-            add_filter('template_include', [self::instance(), 'override_template'], 99);
100
-        }
101
-    }
102
-
103
-
104
-    /**
105
-     * Initializes some hooks for the admin in order to run batch jobs
106
-     *
107
-     * @throws EE_Error
108
-     * @throws ReflectionException
109
-     */
110
-    public static function set_hooks_admin()
111
-    {
112
-        add_action('load-admin_page_espresso_batch', [self::instance(), 'setPageTitle']);
113
-        add_action('admin_menu', [self::instance(), 'register_admin_pages']);
114
-        add_action('admin_enqueue_scripts', [self::instance(), 'enqueue_scripts']);
115
-
116
-        // ajax
117
-        add_action('wp_ajax_espresso_batch_continue', [self::instance(), 'continueBatchJob']);
118
-        add_action('wp_ajax_espresso_batch_advance', [self::instance(), 'advanceBatchJob']);
119
-        add_action('wp_ajax_espresso_batch_cleanup', [self::instance(), 'cleanupBatchJob']);
120
-        add_action('wp_ajax_nopriv_espresso_batch_continue', [self::instance(), 'continueBatchJob']);
121
-        add_action('wp_ajax_nopriv_espresso_batch_advance', [self::instance(), 'advanceBatchJob']);
122
-        add_action('wp_ajax_nopriv_espresso_batch_cleanup', [self::instance(), 'cleanupBatchJob']);
123
-    }
124
-
125
-
126
-    /**
127
-     * @return LoaderInterface
128
-     * @throws InvalidArgumentException
129
-     * @throws InvalidDataTypeException
130
-     * @throws InvalidInterfaceException
131
-     * @since 4.9.80.p
132
-     */
133
-    protected function getLoader(): LoaderInterface
134
-    {
135
-        if (! $this->loader instanceof LoaderInterface) {
136
-            $this->loader = LoaderFactory::getLoader();
137
-        }
138
-        return $this->loader;
139
-    }
140
-
141
-
142
-    /**
143
-     * Enqueues batch scripts on the frontend or admin, and creates a job
144
-     */
145
-    public function enqueue_scripts()
146
-    {
147
-        $request = EED_Batch::getRequest();
148
-        if (
149
-            $request->getRequestParam(EED_Batch::PAGE_SLUG)
150
-            || $request->getRequestParam('page') === EED_Batch::PAGE_SLUG
151
-        ) {
152
-            if (
153
-                ! $request->requestParamIsSet('default_nonce')
154
-                || ! wp_verify_nonce($request->getRequestParam('default_nonce'), 'default_nonce')
155
-            ) {
156
-                wp_die(
157
-                    esc_html__(
158
-                        'The link you clicked to start the batch job has expired. Please go back and refresh the previous page.',
159
-                        'event_espresso'
160
-                    )
161
-                );
162
-            }
163
-            switch ($this->batch_request_type()) {
164
-                case self::batch_job:
165
-                    $this->enqueue_scripts_styles_batch_create();
166
-                    break;
167
-                case self::batch_file_job:
168
-                    $this->enqueue_scripts_styles_batch_file_create();
169
-                    break;
170
-            }
171
-        }
172
-    }
173
-
174
-
175
-    /**
176
-     * Create a batch job, enqueues a script to run it, and localizes some data for it
177
-     */
178
-    public function enqueue_scripts_styles_batch_create()
179
-    {
180
-        $job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
181
-        wp_enqueue_script(
182
-            'batch_runner_init',
183
-            BATCH_URL . 'assets/batch_runner_init.js',
184
-            ['batch_runner'],
185
-            date('Y-m-d-H:i', time()),
186
-            true
187
-        );
188
-        wp_localize_script('batch_runner_init', 'ee_job_response', $job_response->to_array());
189
-        wp_localize_script('batch_runner_init', 'eei18n', EE_Registry::$i18n_js_strings);
190
-
191
-        $return_url = EED_Batch::getRequest()->getRequestParam('return_url', '', DataType::URL);
192
-        if ($return_url) {
193
-            wp_localize_script(
194
-                'batch_runner_init',
195
-                'ee_job_i18n',
196
-                [
197
-                    'return_url'                => $return_url,
198
-                    'auto_redirect_on_complete' => EED_Batch::getRequest()->getRequestParam(
199
-                        'auto_redirect_on_complete'
200
-                    ),
201
-                    'user_message'              => EED_Batch::getRequest()->getRequestParam('assessment_notice')
202
-                        ?: EED_Batch::getRequest()->getRequestParam('job_start_notice'),
203
-                ]
204
-            );
205
-        }
206
-    }
207
-
208
-
209
-    /**
210
-     * Creates a batch job which will download a file, enqueues a script to run the job, and localizes some data for it
211
-     */
212
-    public function enqueue_scripts_styles_batch_file_create()
213
-    {
214
-        // creates a job based on the request variable
215
-        $job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
216
-        wp_enqueue_script(
217
-            'batch_file_runner_init',
218
-            BATCH_URL . 'assets/batch_file_runner_init.js',
219
-            ['batch_runner'],
220
-            date('Y-m-d-H:i', time()),
221
-            true
222
-        );
223
-        wp_localize_script('batch_file_runner_init', 'ee_job_response', $job_response->to_array());
224
-        wp_localize_script('batch_file_runner_init', 'eei18n', EE_Registry::$i18n_js_strings);
225
-
226
-        $return_url = EED_Batch::getRequest()->getRequestParam('return_url', '', DataType::URL);
227
-        if ($return_url) {
228
-            wp_localize_script(
229
-                'batch_file_runner_init',
230
-                'ee_job_i18n',
231
-                ['return_url' => $return_url]
232
-            );
233
-        }
234
-    }
235
-
236
-
237
-    /**
238
-     * Enqueues scripts and styles common to any batch job, and creates
239
-     * a job from the request data, and stores the response in the
240
-     * $this->_job_step_response property
241
-     *
242
-     * @return JobStepResponse
243
-     */
244
-    protected function _enqueue_batch_job_scripts_and_styles_and_start_job(): JobStepResponse
245
-    {
246
-        // just copy the bits of EE admin's eei18n that we need in the JS
247
-        EE_Registry::$i18n_js_strings['batchJobError'] = __(
248
-            'An error occurred and the job has been stopped. Please refresh the page to try again.',
249
-            'event_espresso'
250
-        );
251
-        EE_Registry::$i18n_js_strings['is_admin']      = is_admin();
252
-        wp_enqueue_style(
253
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN,
254
-            EE_ADMIN_URL . 'assets/ee-admin-page.css',
255
-            ['espresso_admin_base'],
256
-            EVENT_ESPRESSO_VERSION
257
-        );
258
-        wp_enqueue_style(
259
-            'batch_runner',
260
-            BATCH_URL . 'assets/batch_runner.css',
261
-            [EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
262
-            date('Y-m-d-H:i', time())
263
-        );
264
-        wp_register_script(
265
-            'progress_bar',
266
-            EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.js',
267
-            ['jquery'],
268
-            date('Y-m-d-H:i', time()),
269
-            true
270
-        );
271
-        wp_enqueue_style(
272
-            'progress_bar',
273
-            EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.css',
274
-            [],
275
-            date('Y-m-d-H:i', time())
276
-        );
277
-        wp_enqueue_script(
278
-            'batch_runner',
279
-            EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/batch_runner.js',
280
-            ['progress_bar', CoreAssetManager::JS_HANDLE_CORE],
281
-            date('Y-m-d-H:i', time()),
282
-            true
283
-        );
284
-        /** @var BatchRequestProcessor $batch_runner */
285
-        $batch_runner = $this->getLoader()->getShared('EventEspresso\core\libraries\batch\BatchRequestProcessor');
286
-        // eg 'EventEspresso\core\libraries\batch\JobHandlers\RegistrationsReport'
287
-        // remember the response for later. We need it to display the page body
288
-        $this->_job_step_response = $batch_runner->createJob();
289
-        return $this->_job_step_response;
290
-    }
291
-
292
-
293
-    /**
294
-     * If we are doing a frontend batch job, this makes it so WP shows our template's HTML
295
-     *
296
-     * @param string $template
297
-     * @return string
298
-     */
299
-    public function override_template(string $template): string
300
-    {
301
-        $request = EED_Batch::getRequest();
302
-        if ($request->requestParamIsSet('batch') && $request->requestParamIsSet(EED_Batch::PAGE_SLUG)) {
303
-            return EE_MODULES . 'batch/templates/batch_frontend_wrapper.template.php';
304
-        }
305
-        return $template;
306
-    }
307
-
308
-
309
-    /**
310
-     * Adds an admin page which doesn't appear in the admin menu
311
-     *
312
-     * @throws EE_Error
313
-     * @throws ReflectionException
314
-     */
315
-    public function register_admin_pages()
316
-    {
317
-        add_submenu_page(
318
-            // parent slug. we don't want this to actually appear in the menu
319
-            '',
320
-            // page title
321
-            esc_html__('Batch Job', 'event_espresso'),
322
-            // menu title
323
-            'n/a',
324
-            // we want this page to actually be accessible to anyone,
325
-            'read',
326
-            // menu slug
327
-            EED_Batch::PAGE_SLUG,
328
-            // callback
329
-            [self::instance(), 'show_admin_page']
330
-        );
331
-    }
332
-
333
-
334
-    /**
335
-     * prevents the following notice from appearing in the error log:
336
-     * PHP Deprecated:  strip_tags():
337
-     * Passing null to parameter #1 ($string) of type string is deprecated
338
-     * in /wp-admin/admin-header.php on line 36
339
-     *
340
-     * @return void
341
-     * @since 5.0.18.p
342
-     */
343
-    public function setPageTitle()
344
-    {
345
-        global $title;
346
-        $title = esc_html__('Batch Job', 'event_espresso');
347
-    }
348
-
349
-
350
-    /**
351
-     * Renders the admin page, after most of the work was already done during enqueuing scripts
352
-     * of creating the job and localizing some data
353
-     */
354
-    public function show_admin_page()
355
-    {
356
-        echo EEH_Template::locate_template(
357
-            EE_MODULES . 'batch/templates/batch_wrapper.template.php',
358
-            [
359
-                'batch_request_type'        => $this->batch_request_type(),
360
-                'auto_redirect_on_complete' => EED_Batch::getRequest()->getRequestParam('auto_redirect_on_complete'),
361
-                'user_message'              => EED_Batch::getRequest()->getRequestParam('assessment_notice')
362
-                    ?: EED_Batch::getRequest()->getRequestParam('job_start_notice'),
363
-            ]
364
-        );
365
-    }
366
-
367
-
368
-    private function runBatchRunnerJob(string $job)
369
-    {
370
-        $job_id = EED_Batch::getRequest()->getRequestParam('job_id');
371
-        /** @var BatchRequestProcessor $batch_runner */
372
-        $batch_runner = $this->getLoader()->getShared('EventEspresso\core\libraries\batch\BatchRequestProcessor');
373
-        $job_response = $batch_runner->{$job}($job_id);
374
-        $this->_return_json($job_response->to_array());
375
-    }
376
-
377
-
378
-    /**
379
-     * Receives ajax calls for continuing a job
380
-     */
381
-    public function continueBatchJob()
382
-    {
383
-        $this->runBatchRunnerJob('continueJob');
384
-    }
385
-
386
-
387
-    /**
388
-     * Receives ajax calls for continuing a job
389
-     */
390
-    public function advanceBatchJob()
391
-    {
392
-        $this->runBatchRunnerJob('advanceJob');
393
-    }
394
-
395
-
396
-    /**
397
-     * Receives the ajax call to cleanup a job
398
-     *
399
-     * @return void
400
-     */
401
-    public function cleanupBatchJob()
402
-    {
403
-        $this->runBatchRunnerJob('cleanupJob');
404
-    }
405
-
406
-
407
-    /**
408
-     * Returns a json response
409
-     *
410
-     * @param array $data The data we want to send echo via in the JSON response's "data" element
411
-     *
412
-     * The returned json object is created from an array in the following format:
413
-     * array(
414
-     *    'notices' => '', // - contains any EE_Error formatted notices
415
-     *    'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
416
-     *    We're also going to include the template args with every package (so js can pick out any specific template
417
-     *    args that might be included in here)
418
-     *    'isEEajax' => true,//indicates this is a response from EE
419
-     * )
420
-     */
421
-    protected function _return_json(array $data)
422
-    {
423
-        $json = [
424
-            'data'     => $data,
425
-            'isEEajax' => true,
426
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
427
-        ];
428
-
429
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
430
-        if (error_get_last() === null || ! headers_sent()) {
431
-            $notices = EE_Error::get_notices(false);
432
-            header('Content-Type: application/json; charset=UTF-8');
433
-            echo wp_json_encode($json + $notices);
434
-            exit();
435
-        }
436
-    }
437
-
438
-
439
-    /**
440
-     * Gets the job step response which was done during the enqueuing of scripts
441
-     *
442
-     * @return JobStepResponse
443
-     */
444
-    public function job_step_response(): JobStepResponse
445
-    {
446
-        return $this->_job_step_response;
447
-    }
448
-
449
-
450
-    /**
451
-     * Gets the batch request type indicated in the current request
452
-     *
453
-     * @return string: EED_Batch::batch_job, EED_Batch::batch_file_job, EED_Batch::batch_not_job
454
-     */
455
-    public function batch_request_type(): string
456
-    {
457
-        if (! $this->_batch_request_type) {
458
-            $request = EED_Batch::getRequest();
459
-            $batch   = $request->getRequestParam('batch');
460
-            switch ($batch) {
461
-                case self::batch_job:
462
-                    $this->_batch_request_type = self::batch_job;
463
-                    break;
464
-                case self::batch_file_job:
465
-                    $this->_batch_request_type = self::batch_file_job;
466
-                    break;
467
-                default:
468
-                    // if we didn't find that it was a batch request, indicate it wasn't
469
-                    $this->_batch_request_type = self::batch_not_job;
470
-            }
471
-        }
472
-        return $this->_batch_request_type;
473
-    }
474
-
475
-
476
-    /**
477
-     * Unnecessary
478
-     *
479
-     * @param WP $WP
480
-     */
481
-    public function run($WP)
482
-    {
483
-    }
32
+	public const PAGE_SLUG = 'espresso_batch';
33
+
34
+	/**
35
+	 * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
36
+	 * processes data only
37
+	 */
38
+	const batch_job = 'job';
39
+
40
+	/**
41
+	 * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
42
+	 * produces a file for download
43
+	 */
44
+	const batch_file_job = 'file';
45
+
46
+	/**
47
+	 * Possibly value for $_REQUEST[ 'batch' ]. Indicates this request is NOT
48
+	 * for a batch job. It's the same as not providing the $_REQUEST[ 'batch' ]
49
+	 * at all
50
+	 */
51
+	const batch_not_job = 'none';
52
+
53
+	/**
54
+	 *
55
+	 * @var string 'file', or 'job', or false to indicate its not a batch request at all
56
+	 */
57
+	protected $_batch_request_type = '';
58
+
59
+	/**
60
+	 * Because we want to use the response in both the localized JS and in the body
61
+	 * we need to make this response available between method calls
62
+	 *
63
+	 * @var JobStepResponse|null
64
+	 */
65
+	protected $_job_step_response = null;
66
+
67
+	/**
68
+	 * @var LoaderInterface|null
69
+	 */
70
+	protected $loader = null;
71
+
72
+
73
+	/**
74
+	 * Gets the batch instance
75
+	 *
76
+	 * @return  EED_Module|EED_Batch
77
+	 * @throws EE_Error
78
+	 * @throws ReflectionException
79
+	 */
80
+	public static function instance(): EED_Batch
81
+	{
82
+		return parent::get_instance(__CLASS__);
83
+	}
84
+
85
+
86
+	/**
87
+	 * Sets hooks to enable batch jobs on the frontend. Disabled by default
88
+	 * because it's an attack vector and there are currently no implementations
89
+	 *
90
+	 * @throws EE_Error
91
+	 * @throws ReflectionException
92
+	 */
93
+	public static function set_hooks()
94
+	{
95
+		// because this is a possible attack vector, let's have this disabled until
96
+		// we at least have a real use for it on the frontend
97
+		if (apply_filters('FHEE__EED_Batch__set_hooks__enable_frontend_batch', false)) {
98
+			add_action('wp_enqueue_scripts', [self::instance(), 'enqueue_scripts']);
99
+			add_filter('template_include', [self::instance(), 'override_template'], 99);
100
+		}
101
+	}
102
+
103
+
104
+	/**
105
+	 * Initializes some hooks for the admin in order to run batch jobs
106
+	 *
107
+	 * @throws EE_Error
108
+	 * @throws ReflectionException
109
+	 */
110
+	public static function set_hooks_admin()
111
+	{
112
+		add_action('load-admin_page_espresso_batch', [self::instance(), 'setPageTitle']);
113
+		add_action('admin_menu', [self::instance(), 'register_admin_pages']);
114
+		add_action('admin_enqueue_scripts', [self::instance(), 'enqueue_scripts']);
115
+
116
+		// ajax
117
+		add_action('wp_ajax_espresso_batch_continue', [self::instance(), 'continueBatchJob']);
118
+		add_action('wp_ajax_espresso_batch_advance', [self::instance(), 'advanceBatchJob']);
119
+		add_action('wp_ajax_espresso_batch_cleanup', [self::instance(), 'cleanupBatchJob']);
120
+		add_action('wp_ajax_nopriv_espresso_batch_continue', [self::instance(), 'continueBatchJob']);
121
+		add_action('wp_ajax_nopriv_espresso_batch_advance', [self::instance(), 'advanceBatchJob']);
122
+		add_action('wp_ajax_nopriv_espresso_batch_cleanup', [self::instance(), 'cleanupBatchJob']);
123
+	}
124
+
125
+
126
+	/**
127
+	 * @return LoaderInterface
128
+	 * @throws InvalidArgumentException
129
+	 * @throws InvalidDataTypeException
130
+	 * @throws InvalidInterfaceException
131
+	 * @since 4.9.80.p
132
+	 */
133
+	protected function getLoader(): LoaderInterface
134
+	{
135
+		if (! $this->loader instanceof LoaderInterface) {
136
+			$this->loader = LoaderFactory::getLoader();
137
+		}
138
+		return $this->loader;
139
+	}
140
+
141
+
142
+	/**
143
+	 * Enqueues batch scripts on the frontend or admin, and creates a job
144
+	 */
145
+	public function enqueue_scripts()
146
+	{
147
+		$request = EED_Batch::getRequest();
148
+		if (
149
+			$request->getRequestParam(EED_Batch::PAGE_SLUG)
150
+			|| $request->getRequestParam('page') === EED_Batch::PAGE_SLUG
151
+		) {
152
+			if (
153
+				! $request->requestParamIsSet('default_nonce')
154
+				|| ! wp_verify_nonce($request->getRequestParam('default_nonce'), 'default_nonce')
155
+			) {
156
+				wp_die(
157
+					esc_html__(
158
+						'The link you clicked to start the batch job has expired. Please go back and refresh the previous page.',
159
+						'event_espresso'
160
+					)
161
+				);
162
+			}
163
+			switch ($this->batch_request_type()) {
164
+				case self::batch_job:
165
+					$this->enqueue_scripts_styles_batch_create();
166
+					break;
167
+				case self::batch_file_job:
168
+					$this->enqueue_scripts_styles_batch_file_create();
169
+					break;
170
+			}
171
+		}
172
+	}
173
+
174
+
175
+	/**
176
+	 * Create a batch job, enqueues a script to run it, and localizes some data for it
177
+	 */
178
+	public function enqueue_scripts_styles_batch_create()
179
+	{
180
+		$job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
181
+		wp_enqueue_script(
182
+			'batch_runner_init',
183
+			BATCH_URL . 'assets/batch_runner_init.js',
184
+			['batch_runner'],
185
+			date('Y-m-d-H:i', time()),
186
+			true
187
+		);
188
+		wp_localize_script('batch_runner_init', 'ee_job_response', $job_response->to_array());
189
+		wp_localize_script('batch_runner_init', 'eei18n', EE_Registry::$i18n_js_strings);
190
+
191
+		$return_url = EED_Batch::getRequest()->getRequestParam('return_url', '', DataType::URL);
192
+		if ($return_url) {
193
+			wp_localize_script(
194
+				'batch_runner_init',
195
+				'ee_job_i18n',
196
+				[
197
+					'return_url'                => $return_url,
198
+					'auto_redirect_on_complete' => EED_Batch::getRequest()->getRequestParam(
199
+						'auto_redirect_on_complete'
200
+					),
201
+					'user_message'              => EED_Batch::getRequest()->getRequestParam('assessment_notice')
202
+						?: EED_Batch::getRequest()->getRequestParam('job_start_notice'),
203
+				]
204
+			);
205
+		}
206
+	}
207
+
208
+
209
+	/**
210
+	 * Creates a batch job which will download a file, enqueues a script to run the job, and localizes some data for it
211
+	 */
212
+	public function enqueue_scripts_styles_batch_file_create()
213
+	{
214
+		// creates a job based on the request variable
215
+		$job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
216
+		wp_enqueue_script(
217
+			'batch_file_runner_init',
218
+			BATCH_URL . 'assets/batch_file_runner_init.js',
219
+			['batch_runner'],
220
+			date('Y-m-d-H:i', time()),
221
+			true
222
+		);
223
+		wp_localize_script('batch_file_runner_init', 'ee_job_response', $job_response->to_array());
224
+		wp_localize_script('batch_file_runner_init', 'eei18n', EE_Registry::$i18n_js_strings);
225
+
226
+		$return_url = EED_Batch::getRequest()->getRequestParam('return_url', '', DataType::URL);
227
+		if ($return_url) {
228
+			wp_localize_script(
229
+				'batch_file_runner_init',
230
+				'ee_job_i18n',
231
+				['return_url' => $return_url]
232
+			);
233
+		}
234
+	}
235
+
236
+
237
+	/**
238
+	 * Enqueues scripts and styles common to any batch job, and creates
239
+	 * a job from the request data, and stores the response in the
240
+	 * $this->_job_step_response property
241
+	 *
242
+	 * @return JobStepResponse
243
+	 */
244
+	protected function _enqueue_batch_job_scripts_and_styles_and_start_job(): JobStepResponse
245
+	{
246
+		// just copy the bits of EE admin's eei18n that we need in the JS
247
+		EE_Registry::$i18n_js_strings['batchJobError'] = __(
248
+			'An error occurred and the job has been stopped. Please refresh the page to try again.',
249
+			'event_espresso'
250
+		);
251
+		EE_Registry::$i18n_js_strings['is_admin']      = is_admin();
252
+		wp_enqueue_style(
253
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN,
254
+			EE_ADMIN_URL . 'assets/ee-admin-page.css',
255
+			['espresso_admin_base'],
256
+			EVENT_ESPRESSO_VERSION
257
+		);
258
+		wp_enqueue_style(
259
+			'batch_runner',
260
+			BATCH_URL . 'assets/batch_runner.css',
261
+			[EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN],
262
+			date('Y-m-d-H:i', time())
263
+		);
264
+		wp_register_script(
265
+			'progress_bar',
266
+			EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.js',
267
+			['jquery'],
268
+			date('Y-m-d-H:i', time()),
269
+			true
270
+		);
271
+		wp_enqueue_style(
272
+			'progress_bar',
273
+			EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.css',
274
+			[],
275
+			date('Y-m-d-H:i', time())
276
+		);
277
+		wp_enqueue_script(
278
+			'batch_runner',
279
+			EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/batch_runner.js',
280
+			['progress_bar', CoreAssetManager::JS_HANDLE_CORE],
281
+			date('Y-m-d-H:i', time()),
282
+			true
283
+		);
284
+		/** @var BatchRequestProcessor $batch_runner */
285
+		$batch_runner = $this->getLoader()->getShared('EventEspresso\core\libraries\batch\BatchRequestProcessor');
286
+		// eg 'EventEspresso\core\libraries\batch\JobHandlers\RegistrationsReport'
287
+		// remember the response for later. We need it to display the page body
288
+		$this->_job_step_response = $batch_runner->createJob();
289
+		return $this->_job_step_response;
290
+	}
291
+
292
+
293
+	/**
294
+	 * If we are doing a frontend batch job, this makes it so WP shows our template's HTML
295
+	 *
296
+	 * @param string $template
297
+	 * @return string
298
+	 */
299
+	public function override_template(string $template): string
300
+	{
301
+		$request = EED_Batch::getRequest();
302
+		if ($request->requestParamIsSet('batch') && $request->requestParamIsSet(EED_Batch::PAGE_SLUG)) {
303
+			return EE_MODULES . 'batch/templates/batch_frontend_wrapper.template.php';
304
+		}
305
+		return $template;
306
+	}
307
+
308
+
309
+	/**
310
+	 * Adds an admin page which doesn't appear in the admin menu
311
+	 *
312
+	 * @throws EE_Error
313
+	 * @throws ReflectionException
314
+	 */
315
+	public function register_admin_pages()
316
+	{
317
+		add_submenu_page(
318
+			// parent slug. we don't want this to actually appear in the menu
319
+			'',
320
+			// page title
321
+			esc_html__('Batch Job', 'event_espresso'),
322
+			// menu title
323
+			'n/a',
324
+			// we want this page to actually be accessible to anyone,
325
+			'read',
326
+			// menu slug
327
+			EED_Batch::PAGE_SLUG,
328
+			// callback
329
+			[self::instance(), 'show_admin_page']
330
+		);
331
+	}
332
+
333
+
334
+	/**
335
+	 * prevents the following notice from appearing in the error log:
336
+	 * PHP Deprecated:  strip_tags():
337
+	 * Passing null to parameter #1 ($string) of type string is deprecated
338
+	 * in /wp-admin/admin-header.php on line 36
339
+	 *
340
+	 * @return void
341
+	 * @since 5.0.18.p
342
+	 */
343
+	public function setPageTitle()
344
+	{
345
+		global $title;
346
+		$title = esc_html__('Batch Job', 'event_espresso');
347
+	}
348
+
349
+
350
+	/**
351
+	 * Renders the admin page, after most of the work was already done during enqueuing scripts
352
+	 * of creating the job and localizing some data
353
+	 */
354
+	public function show_admin_page()
355
+	{
356
+		echo EEH_Template::locate_template(
357
+			EE_MODULES . 'batch/templates/batch_wrapper.template.php',
358
+			[
359
+				'batch_request_type'        => $this->batch_request_type(),
360
+				'auto_redirect_on_complete' => EED_Batch::getRequest()->getRequestParam('auto_redirect_on_complete'),
361
+				'user_message'              => EED_Batch::getRequest()->getRequestParam('assessment_notice')
362
+					?: EED_Batch::getRequest()->getRequestParam('job_start_notice'),
363
+			]
364
+		);
365
+	}
366
+
367
+
368
+	private function runBatchRunnerJob(string $job)
369
+	{
370
+		$job_id = EED_Batch::getRequest()->getRequestParam('job_id');
371
+		/** @var BatchRequestProcessor $batch_runner */
372
+		$batch_runner = $this->getLoader()->getShared('EventEspresso\core\libraries\batch\BatchRequestProcessor');
373
+		$job_response = $batch_runner->{$job}($job_id);
374
+		$this->_return_json($job_response->to_array());
375
+	}
376
+
377
+
378
+	/**
379
+	 * Receives ajax calls for continuing a job
380
+	 */
381
+	public function continueBatchJob()
382
+	{
383
+		$this->runBatchRunnerJob('continueJob');
384
+	}
385
+
386
+
387
+	/**
388
+	 * Receives ajax calls for continuing a job
389
+	 */
390
+	public function advanceBatchJob()
391
+	{
392
+		$this->runBatchRunnerJob('advanceJob');
393
+	}
394
+
395
+
396
+	/**
397
+	 * Receives the ajax call to cleanup a job
398
+	 *
399
+	 * @return void
400
+	 */
401
+	public function cleanupBatchJob()
402
+	{
403
+		$this->runBatchRunnerJob('cleanupJob');
404
+	}
405
+
406
+
407
+	/**
408
+	 * Returns a json response
409
+	 *
410
+	 * @param array $data The data we want to send echo via in the JSON response's "data" element
411
+	 *
412
+	 * The returned json object is created from an array in the following format:
413
+	 * array(
414
+	 *    'notices' => '', // - contains any EE_Error formatted notices
415
+	 *    'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
416
+	 *    We're also going to include the template args with every package (so js can pick out any specific template
417
+	 *    args that might be included in here)
418
+	 *    'isEEajax' => true,//indicates this is a response from EE
419
+	 * )
420
+	 */
421
+	protected function _return_json(array $data)
422
+	{
423
+		$json = [
424
+			'data'     => $data,
425
+			'isEEajax' => true,
426
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
427
+		];
428
+
429
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
430
+		if (error_get_last() === null || ! headers_sent()) {
431
+			$notices = EE_Error::get_notices(false);
432
+			header('Content-Type: application/json; charset=UTF-8');
433
+			echo wp_json_encode($json + $notices);
434
+			exit();
435
+		}
436
+	}
437
+
438
+
439
+	/**
440
+	 * Gets the job step response which was done during the enqueuing of scripts
441
+	 *
442
+	 * @return JobStepResponse
443
+	 */
444
+	public function job_step_response(): JobStepResponse
445
+	{
446
+		return $this->_job_step_response;
447
+	}
448
+
449
+
450
+	/**
451
+	 * Gets the batch request type indicated in the current request
452
+	 *
453
+	 * @return string: EED_Batch::batch_job, EED_Batch::batch_file_job, EED_Batch::batch_not_job
454
+	 */
455
+	public function batch_request_type(): string
456
+	{
457
+		if (! $this->_batch_request_type) {
458
+			$request = EED_Batch::getRequest();
459
+			$batch   = $request->getRequestParam('batch');
460
+			switch ($batch) {
461
+				case self::batch_job:
462
+					$this->_batch_request_type = self::batch_job;
463
+					break;
464
+				case self::batch_file_job:
465
+					$this->_batch_request_type = self::batch_file_job;
466
+					break;
467
+				default:
468
+					// if we didn't find that it was a batch request, indicate it wasn't
469
+					$this->_batch_request_type = self::batch_not_job;
470
+			}
471
+		}
472
+		return $this->_batch_request_type;
473
+	}
474
+
475
+
476
+	/**
477
+	 * Unnecessary
478
+	 *
479
+	 * @param WP $WP
480
+	 */
481
+	public function run($WP)
482
+	{
483
+	}
484 484
 }
Please login to merge, or discard this patch.
modules/venue_single/EED_Venue_Single.module.php 1 patch
Indentation   +169 added lines, -169 removed lines patch added patch discarded remove patch
@@ -29,173 +29,173 @@
 block discarded – undo
29 29
  */
30 30
 class EED_Venue_Single extends EED_Module
31 31
 {
32
-    /**
33
-     * @return EED_Venue_Single
34
-     */
35
-    public static function instance()
36
-    {
37
-        return parent::get_instance(__CLASS__);
38
-    }
39
-
40
-
41
-    /**
42
-     * set_hooks - for hooking into EE Core, other modules, etc
43
-     *
44
-     * @return void
45
-     * @throws InvalidArgumentException
46
-     * @throws InvalidDataTypeException
47
-     * @throws InvalidInterfaceException
48
-     */
49
-    public static function set_hooks()
50
-    {
51
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
52
-        $custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
53
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
54
-        );
55
-        $custom_post_types = $custom_post_type_definitions->getDefinitions();
56
-        EE_Config::register_route(
57
-            $custom_post_types[EspressoPostType::VENUES]['singular_slug'],
58
-            'Venue_Single',
59
-            'run'
60
-        );
61
-    }
62
-
63
-    /**
64
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
-     *
66
-     * @access    public
67
-     * @return    void
68
-     */
69
-    public static function set_hooks_admin()
70
-    {
71
-    }
72
-
73
-
74
-    /**
75
-     * run - initial module setup
76
-     *
77
-     * @access    public
78
-     * @param \WP $WP
79
-     */
80
-    public function run($WP)
81
-    {
82
-        // check what template is loaded
83
-        add_filter('template_include', array($this, 'template_include'), 999, 1);
84
-        add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
85
-    }
86
-
87
-
88
-    /**
89
-     * template_include
90
-     *
91
-     * @access public
92
-     * @param  string $template
93
-     * @return string
94
-     */
95
-    public function template_include($template)
96
-    {
97
-        // not a custom template?
98
-        if (
99
-            EE_Registry::instance()
100
-                       ->load_core('Front_Controller', array(), false, true)
101
-                       ->get_selected_template() != 'single-espresso_venues.php'
102
-        ) {
103
-            EEH_Template::load_espresso_theme_functions();
104
-            // then add extra event data via hooks
105
-            add_filter('the_title', array($this, 'the_title'), 100, 1);
106
-            add_filter('the_content', array($this, 'venue_details'), 100);
107
-            // don't display entry meta because the existing theme will take car of that
108
-            add_filter('FHEE__content_espresso_venues_details_template__display_entry_meta', '__return_false');
109
-        }
110
-        return $template;
111
-    }
112
-
113
-
114
-    /**
115
-     * the_title
116
-     *
117
-     * @access public
118
-     * @param  string $title
119
-     * @return string
120
-     */
121
-    public function the_title($title = '')
122
-    {
123
-        return $title;
124
-    }
125
-
126
-
127
-    /**
128
-     *    venue_details
129
-     *
130
-     * @access public
131
-     * @param  string $content
132
-     * @return string
133
-     */
134
-    public function venue_details($content)
135
-    {
136
-        global $post;
137
-        if (
138
-            $post->post_type == EspressoPostType::VENUES
139
-            && ! post_password_required()
140
-        ) {
141
-            // since the 'content-espresso_venues-details.php' template might be used directly from within a theme,
142
-            // it uses the_content() for displaying the $post->post_content
143
-            // so in order to load a template that uses the_content() from within a callback being used to filter the_content(),
144
-            // we need to first remove this callback from being applied to the_content() (otherwise it will recurse and blow up the interweb)
145
-            remove_filter('the_content', array($this, 'venue_details'), 100);
146
-            // add filters we want
147
-            add_filter('the_content', array($this, 'venue_location'), 110);
148
-            // now load our template
149
-            $template = EEH_Template::locate_template('content-espresso_venues-details.php');
150
-            // remove other filters we added so they won't get applied to the next post
151
-            remove_filter('the_content', array($this, 'venue_location'), 110);
152
-        }
153
-        // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
154
-        return ! empty($template) ? $template : $content;
155
-    }
156
-
157
-
158
-    /**
159
-     * venue_location
160
-     *
161
-     * @access public
162
-     * @param  string $content
163
-     * @return string
164
-     */
165
-    public function venue_location($content)
166
-    {
167
-        return $content . EEH_Template::locate_template('content-espresso_venues-location.php');
168
-    }
169
-
170
-
171
-    /**
172
-     *    wp_enqueue_scripts
173
-     *
174
-     * @access public
175
-     * @return void
176
-     */
177
-    public function wp_enqueue_scripts()
178
-    {
179
-        // get some style
180
-        if (apply_filters('FHEE_enable_default_espresso_css', true) && is_single()) {
181
-            // first check theme folder
182
-            if (is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
183
-                wp_register_style(
184
-                    $this->theme,
185
-                    get_stylesheet_directory_uri() . $this->theme . '/style.css',
186
-                    array('dashicons', 'espresso_default')
187
-                );
188
-            } elseif (is_readable(EE_TEMPLATES . $this->theme . '/style.css')) {
189
-                wp_register_style(
190
-                    $this->theme,
191
-                    EE_TEMPLATES_URL . $this->theme . '/style.css',
192
-                    array('dashicons', 'espresso_default')
193
-                );
194
-            }
195
-            wp_enqueue_style($this->theme);
196
-            if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
197
-                add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
198
-            }
199
-        }
200
-    }
32
+	/**
33
+	 * @return EED_Venue_Single
34
+	 */
35
+	public static function instance()
36
+	{
37
+		return parent::get_instance(__CLASS__);
38
+	}
39
+
40
+
41
+	/**
42
+	 * set_hooks - for hooking into EE Core, other modules, etc
43
+	 *
44
+	 * @return void
45
+	 * @throws InvalidArgumentException
46
+	 * @throws InvalidDataTypeException
47
+	 * @throws InvalidInterfaceException
48
+	 */
49
+	public static function set_hooks()
50
+	{
51
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
52
+		$custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
53
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
54
+		);
55
+		$custom_post_types = $custom_post_type_definitions->getDefinitions();
56
+		EE_Config::register_route(
57
+			$custom_post_types[EspressoPostType::VENUES]['singular_slug'],
58
+			'Venue_Single',
59
+			'run'
60
+		);
61
+	}
62
+
63
+	/**
64
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
+	 *
66
+	 * @access    public
67
+	 * @return    void
68
+	 */
69
+	public static function set_hooks_admin()
70
+	{
71
+	}
72
+
73
+
74
+	/**
75
+	 * run - initial module setup
76
+	 *
77
+	 * @access    public
78
+	 * @param \WP $WP
79
+	 */
80
+	public function run($WP)
81
+	{
82
+		// check what template is loaded
83
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
84
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
85
+	}
86
+
87
+
88
+	/**
89
+	 * template_include
90
+	 *
91
+	 * @access public
92
+	 * @param  string $template
93
+	 * @return string
94
+	 */
95
+	public function template_include($template)
96
+	{
97
+		// not a custom template?
98
+		if (
99
+			EE_Registry::instance()
100
+					   ->load_core('Front_Controller', array(), false, true)
101
+					   ->get_selected_template() != 'single-espresso_venues.php'
102
+		) {
103
+			EEH_Template::load_espresso_theme_functions();
104
+			// then add extra event data via hooks
105
+			add_filter('the_title', array($this, 'the_title'), 100, 1);
106
+			add_filter('the_content', array($this, 'venue_details'), 100);
107
+			// don't display entry meta because the existing theme will take car of that
108
+			add_filter('FHEE__content_espresso_venues_details_template__display_entry_meta', '__return_false');
109
+		}
110
+		return $template;
111
+	}
112
+
113
+
114
+	/**
115
+	 * the_title
116
+	 *
117
+	 * @access public
118
+	 * @param  string $title
119
+	 * @return string
120
+	 */
121
+	public function the_title($title = '')
122
+	{
123
+		return $title;
124
+	}
125
+
126
+
127
+	/**
128
+	 *    venue_details
129
+	 *
130
+	 * @access public
131
+	 * @param  string $content
132
+	 * @return string
133
+	 */
134
+	public function venue_details($content)
135
+	{
136
+		global $post;
137
+		if (
138
+			$post->post_type == EspressoPostType::VENUES
139
+			&& ! post_password_required()
140
+		) {
141
+			// since the 'content-espresso_venues-details.php' template might be used directly from within a theme,
142
+			// it uses the_content() for displaying the $post->post_content
143
+			// so in order to load a template that uses the_content() from within a callback being used to filter the_content(),
144
+			// we need to first remove this callback from being applied to the_content() (otherwise it will recurse and blow up the interweb)
145
+			remove_filter('the_content', array($this, 'venue_details'), 100);
146
+			// add filters we want
147
+			add_filter('the_content', array($this, 'venue_location'), 110);
148
+			// now load our template
149
+			$template = EEH_Template::locate_template('content-espresso_venues-details.php');
150
+			// remove other filters we added so they won't get applied to the next post
151
+			remove_filter('the_content', array($this, 'venue_location'), 110);
152
+		}
153
+		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
154
+		return ! empty($template) ? $template : $content;
155
+	}
156
+
157
+
158
+	/**
159
+	 * venue_location
160
+	 *
161
+	 * @access public
162
+	 * @param  string $content
163
+	 * @return string
164
+	 */
165
+	public function venue_location($content)
166
+	{
167
+		return $content . EEH_Template::locate_template('content-espresso_venues-location.php');
168
+	}
169
+
170
+
171
+	/**
172
+	 *    wp_enqueue_scripts
173
+	 *
174
+	 * @access public
175
+	 * @return void
176
+	 */
177
+	public function wp_enqueue_scripts()
178
+	{
179
+		// get some style
180
+		if (apply_filters('FHEE_enable_default_espresso_css', true) && is_single()) {
181
+			// first check theme folder
182
+			if (is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
183
+				wp_register_style(
184
+					$this->theme,
185
+					get_stylesheet_directory_uri() . $this->theme . '/style.css',
186
+					array('dashicons', 'espresso_default')
187
+				);
188
+			} elseif (is_readable(EE_TEMPLATES . $this->theme . '/style.css')) {
189
+				wp_register_style(
190
+					$this->theme,
191
+					EE_TEMPLATES_URL . $this->theme . '/style.css',
192
+					array('dashicons', 'espresso_default')
193
+				);
194
+			}
195
+			wp_enqueue_style($this->theme);
196
+			if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
197
+				add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
198
+			}
199
+		}
200
+	}
201 201
 }
Please login to merge, or discard this patch.
modules/ticket_selector/DisplayTicketSelector.php 1 patch
Indentation   +866 added lines, -866 removed lines patch added patch discarded remove patch
@@ -41,873 +41,873 @@
 block discarded – undo
41 41
  */
42 42
 class DisplayTicketSelector
43 43
 {
44
-    /**
45
-     * @var RequestInterface
46
-     */
47
-    protected $request;
48
-
49
-    /**
50
-     * @var EE_Ticket_Selector_Config
51
-     */
52
-    protected $config;
53
-
54
-    /**
55
-     * event that ticket selector is being generated for
56
-     *
57
-     * @access protected
58
-     * @var EE_Event $event
59
-     */
60
-    protected $event;
61
-
62
-    /**
63
-     * Used to flag when the ticket selector is being called from an external iframe.
64
-     *
65
-     * @var bool $iframe
66
-     */
67
-    protected $iframe = false;
68
-
69
-    /**
70
-     * max attendees that can register for event at one time
71
-     *
72
-     * @var int $max_attendees
73
-     */
74
-    private $max_attendees = EE_INF;
75
-
76
-    /**
77
-     * @var string $date_format
78
-     */
79
-    private $date_format;
80
-
81
-    /**
82
-     * @var string $time_format
83
-     */
84
-    private $time_format;
85
-
86
-    /**
87
-     * @var boolean $display_full_ui
88
-     */
89
-    private $display_full_ui;
90
-
91
-    /**
92
-     * @var CurrentUser
93
-     */
94
-    private $current_user;
95
-
96
-
97
-    /**
98
-     * DisplayTicketSelector constructor.
99
-     *
100
-     * @param CurrentUser $current_user
101
-     * @param RequestInterface          $request
102
-     * @param EE_Ticket_Selector_Config $config
103
-     * @param bool                      $iframe
104
-     */
105
-    public function __construct(
106
-        CurrentUser $current_user,
107
-        RequestInterface $request,
108
-        EE_Ticket_Selector_Config $config,
109
-        bool $iframe = false
110
-    ) {
111
-        $this->current_user = $current_user;
112
-        $this->request     = $request;
113
-        $this->config      = $config;
114
-        $this->setIframe($iframe);
115
-        $this->date_format = apply_filters(
116
-            'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format',
117
-            get_option('date_format')
118
-        );
119
-        $this->time_format  = apply_filters(
120
-            'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format',
121
-            get_option('time_format')
122
-        );
123
-    }
124
-
125
-
126
-    /**
127
-     * @return bool
128
-     */
129
-    public function isIframe(): bool
130
-    {
131
-        return $this->iframe;
132
-    }
133
-
134
-
135
-    /**
136
-     * @param boolean $iframe
137
-     */
138
-    public function setIframe(bool $iframe = true)
139
-    {
140
-        $this->iframe = filter_var($iframe, FILTER_VALIDATE_BOOLEAN);
141
-    }
142
-
143
-
144
-    /**
145
-     * finds and sets the \EE_Event object for use throughout class
146
-     *
147
-     * @param mixed $event
148
-     * @return bool
149
-     * @throws EE_Error
150
-     * @throws InvalidDataTypeException
151
-     * @throws InvalidInterfaceException
152
-     * @throws InvalidArgumentException
153
-     */
154
-    protected function setEvent($event = null): bool
155
-    {
156
-        if ($event === null) {
157
-            global $post;
158
-            $event = $post;
159
-        }
160
-        if ($event instanceof EE_Event) {
161
-            $this->event = $event;
162
-        } elseif ($event instanceof WP_Post) {
163
-            if (isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) {
164
-                $this->event = $event->EE_Event;
165
-            } elseif (isset($event->post_type) && $event->post_type === EspressoPostType::EVENTS) {
166
-                $event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event);
167
-                $this->event     = $event->EE_Event;
168
-            }
169
-        } else {
170
-            $user_msg = esc_html__('No Event object or an invalid Event object was supplied.', 'event_espresso');
171
-            $dev_msg  = $user_msg . esc_html__(
172
-                'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.',
173
-                'event_espresso'
174
-            );
175
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
176
-            return false;
177
-        }
178
-        return true;
179
-    }
180
-
181
-
182
-    /**
183
-     * @return int
184
-     */
185
-    public function getMaxAttendees(): int
186
-    {
187
-        return $this->max_attendees;
188
-    }
189
-
190
-
191
-    /**
192
-     * @param int $max_attendees
193
-     */
194
-    public function setMaxAttendees(int $max_attendees)
195
-    {
196
-        $this->max_attendees = absint(
197
-            apply_filters(
198
-                'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets',
199
-                $max_attendees
200
-            )
201
-        );
202
-    }
203
-
204
-
205
-    /**
206
-     * Returns whether or not the full ticket selector should be shown or not.
207
-     * Currently, it displays on the frontend (including ajax requests) but not the backend
208
-     *
209
-     * @return bool
210
-     */
211
-    private function display_full_ui(): bool
212
-    {
213
-        if ($this->display_full_ui === null) {
214
-            $this->display_full_ui = ! is_admin() || (defined('DOING_AJAX') && DOING_AJAX);
215
-        }
216
-        return $this->display_full_ui;
217
-    }
218
-
219
-
220
-    /**
221
-     * creates buttons for selecting number of attendees for an event
222
-     *
223
-     * @param WP_Post|int $event
224
-     * @param bool        $view_details
225
-     * @return string
226
-     * @throws EE_Error
227
-     * @throws InvalidArgumentException
228
-     * @throws InvalidDataTypeException
229
-     * @throws InvalidInterfaceException
230
-     * @throws ReflectionException
231
-     * @throws Exception
232
-     */
233
-    public function display($event = null, bool $view_details = false)
234
-    {
235
-        // reset filter for displaying submit button
236
-        remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
237
-        // poke and prod incoming event till it tells us what it is
238
-        if (! $this->setEvent($event)) {
239
-            return $this->handleMissingEvent();
240
-        }
241
-        // is the event expired ?
242
-        $template_args['event_is_expired'] = ! is_admin() && $this->event->is_expired();
243
-        if ($template_args['event_is_expired']) {
244
-            return is_single()
245
-                ? $this->expiredEventMessage()
246
-                : $this->expiredEventMessage() . $this->displayViewDetailsButton();
247
-        }
248
-        // begin gathering template arguments by getting event status
249
-        $template_args = ['event_status' => $this->event->get_active_status()];
250
-        if (
251
-            $this->activeEventAndShowTicketSelector(
252
-                $event,
253
-                $template_args['event_status'],
254
-                $view_details
255
-            )
256
-        ) {
257
-            return ! is_single() ? $this->displayViewDetailsButton() : '';
258
-        }
259
-        // filter the maximum qty that can appear in the Ticket Selector qty dropdowns
260
-        $this->setMaxAttendees($this->event->additional_limit());
261
-        if ($this->getMaxAttendees() < 1) {
262
-            return $this->ticketSalesClosedMessage();
263
-        }
264
-        // get all tickets for this event ordered by the datetime
265
-        $tickets = $this->getTickets();
266
-        if (count($tickets) < 1) {
267
-            return $this->noTicketAvailableMessage();
268
-        }
269
-        // redirecting to another site for registration ??
270
-        $external_url = (string) $this->event->external_url()
271
-                        && $this->event->external_url() !== get_the_permalink()
272
-            ? $this->event->external_url()
273
-            : '';
274
-        // if redirecting to another site for registration, then we don't load the TS
275
-        $ticket_selector = $external_url
276
-            ? $this->externalEventRegistration()
277
-            : $this->loadTicketSelector($tickets, $template_args);
278
-        // now set up the form (but not for the admin)
279
-        $ticket_selector = $this->display_full_ui()
280
-            ? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector
281
-            : $ticket_selector;
282
-        // submit button and form close tag
283
-        $ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : '';
284
-        return $ticket_selector;
285
-    }
286
-
287
-
288
-    /**
289
-     * displayTicketSelector
290
-     * examines the event properties and determines whether a Ticket Selector should be displayed
291
-     *
292
-     * @param WP_Post|int $event
293
-     * @param string      $_event_active_status
294
-     * @param bool        $view_details
295
-     * @return bool
296
-     * @throws EE_Error
297
-     * @throws ReflectionException
298
-     */
299
-    protected function activeEventAndShowTicketSelector($event, string $_event_active_status, bool $view_details): bool
300
-    {
301
-        $event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event;
302
-        return $this->display_full_ui()
303
-               && (
304
-                   ! $this->event->display_ticket_selector()
305
-                   || $view_details
306
-                   || post_password_required($event_post)
307
-                   || (
308
-                       $_event_active_status !== EE_Datetime::active
309
-                       && $_event_active_status !== EE_Datetime::upcoming
310
-                       && $_event_active_status !== EE_Datetime::sold_out
311
-                       && ! (
312
-                           $_event_active_status === EE_Datetime::inactive
313
-                           && is_user_logged_in()
314
-                       )
315
-                   )
316
-               );
317
-    }
318
-
319
-
320
-    /**
321
-     * noTicketAvailableMessage
322
-     * notice displayed if event is expired
323
-     *
324
-     * @return string
325
-     */
326
-    protected function expiredEventMessage(): string
327
-    {
328
-        return '<div class="ee-event-expired-notice"><span class="important-notice">'
329
-           . esc_html__(
330
-               'We\'re sorry, but all tickets sales have ended because the event is expired.',
331
-               'event_espresso'
332
-           )
333
-           . '</span></div><!-- .ee-event-expired-notice -->';
334
-    }
335
-
336
-
337
-    /**
338
-     * noTicketAvailableMessage
339
-     * notice displayed if event has no more tickets available
340
-     *
341
-     * @return string
342
-     * @throws EE_Error
343
-     * @throws ReflectionException
344
-     */
345
-    protected function noTicketAvailableMessage(): string
346
-    {
347
-        $no_ticket_available_msg = esc_html__('We\'re sorry, but all ticket sales have ended.', 'event_espresso');
348
-        if (current_user_can('edit_post', $this->event->ID())) {
349
-            $no_ticket_available_msg .= sprintf(
350
-                esc_html__(
351
-                    '%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s',
352
-                    'event_espresso'
353
-                ),
354
-                '<div class="ee-attention" style="text-align: left;"><b>',
355
-                '</b><br />',
356
-                '<span class="edit-link"><a class="post-edit-link" href="'
357
-                . get_edit_post_link($this->event->ID())
358
-                . '">',
359
-                '</a></span></div><!-- .ee-attention noTicketAvailableMessage -->'
360
-            );
361
-        }
362
-        return '
44
+	/**
45
+	 * @var RequestInterface
46
+	 */
47
+	protected $request;
48
+
49
+	/**
50
+	 * @var EE_Ticket_Selector_Config
51
+	 */
52
+	protected $config;
53
+
54
+	/**
55
+	 * event that ticket selector is being generated for
56
+	 *
57
+	 * @access protected
58
+	 * @var EE_Event $event
59
+	 */
60
+	protected $event;
61
+
62
+	/**
63
+	 * Used to flag when the ticket selector is being called from an external iframe.
64
+	 *
65
+	 * @var bool $iframe
66
+	 */
67
+	protected $iframe = false;
68
+
69
+	/**
70
+	 * max attendees that can register for event at one time
71
+	 *
72
+	 * @var int $max_attendees
73
+	 */
74
+	private $max_attendees = EE_INF;
75
+
76
+	/**
77
+	 * @var string $date_format
78
+	 */
79
+	private $date_format;
80
+
81
+	/**
82
+	 * @var string $time_format
83
+	 */
84
+	private $time_format;
85
+
86
+	/**
87
+	 * @var boolean $display_full_ui
88
+	 */
89
+	private $display_full_ui;
90
+
91
+	/**
92
+	 * @var CurrentUser
93
+	 */
94
+	private $current_user;
95
+
96
+
97
+	/**
98
+	 * DisplayTicketSelector constructor.
99
+	 *
100
+	 * @param CurrentUser $current_user
101
+	 * @param RequestInterface          $request
102
+	 * @param EE_Ticket_Selector_Config $config
103
+	 * @param bool                      $iframe
104
+	 */
105
+	public function __construct(
106
+		CurrentUser $current_user,
107
+		RequestInterface $request,
108
+		EE_Ticket_Selector_Config $config,
109
+		bool $iframe = false
110
+	) {
111
+		$this->current_user = $current_user;
112
+		$this->request     = $request;
113
+		$this->config      = $config;
114
+		$this->setIframe($iframe);
115
+		$this->date_format = apply_filters(
116
+			'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format',
117
+			get_option('date_format')
118
+		);
119
+		$this->time_format  = apply_filters(
120
+			'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format',
121
+			get_option('time_format')
122
+		);
123
+	}
124
+
125
+
126
+	/**
127
+	 * @return bool
128
+	 */
129
+	public function isIframe(): bool
130
+	{
131
+		return $this->iframe;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param boolean $iframe
137
+	 */
138
+	public function setIframe(bool $iframe = true)
139
+	{
140
+		$this->iframe = filter_var($iframe, FILTER_VALIDATE_BOOLEAN);
141
+	}
142
+
143
+
144
+	/**
145
+	 * finds and sets the \EE_Event object for use throughout class
146
+	 *
147
+	 * @param mixed $event
148
+	 * @return bool
149
+	 * @throws EE_Error
150
+	 * @throws InvalidDataTypeException
151
+	 * @throws InvalidInterfaceException
152
+	 * @throws InvalidArgumentException
153
+	 */
154
+	protected function setEvent($event = null): bool
155
+	{
156
+		if ($event === null) {
157
+			global $post;
158
+			$event = $post;
159
+		}
160
+		if ($event instanceof EE_Event) {
161
+			$this->event = $event;
162
+		} elseif ($event instanceof WP_Post) {
163
+			if (isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) {
164
+				$this->event = $event->EE_Event;
165
+			} elseif (isset($event->post_type) && $event->post_type === EspressoPostType::EVENTS) {
166
+				$event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event);
167
+				$this->event     = $event->EE_Event;
168
+			}
169
+		} else {
170
+			$user_msg = esc_html__('No Event object or an invalid Event object was supplied.', 'event_espresso');
171
+			$dev_msg  = $user_msg . esc_html__(
172
+				'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.',
173
+				'event_espresso'
174
+			);
175
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
176
+			return false;
177
+		}
178
+		return true;
179
+	}
180
+
181
+
182
+	/**
183
+	 * @return int
184
+	 */
185
+	public function getMaxAttendees(): int
186
+	{
187
+		return $this->max_attendees;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @param int $max_attendees
193
+	 */
194
+	public function setMaxAttendees(int $max_attendees)
195
+	{
196
+		$this->max_attendees = absint(
197
+			apply_filters(
198
+				'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets',
199
+				$max_attendees
200
+			)
201
+		);
202
+	}
203
+
204
+
205
+	/**
206
+	 * Returns whether or not the full ticket selector should be shown or not.
207
+	 * Currently, it displays on the frontend (including ajax requests) but not the backend
208
+	 *
209
+	 * @return bool
210
+	 */
211
+	private function display_full_ui(): bool
212
+	{
213
+		if ($this->display_full_ui === null) {
214
+			$this->display_full_ui = ! is_admin() || (defined('DOING_AJAX') && DOING_AJAX);
215
+		}
216
+		return $this->display_full_ui;
217
+	}
218
+
219
+
220
+	/**
221
+	 * creates buttons for selecting number of attendees for an event
222
+	 *
223
+	 * @param WP_Post|int $event
224
+	 * @param bool        $view_details
225
+	 * @return string
226
+	 * @throws EE_Error
227
+	 * @throws InvalidArgumentException
228
+	 * @throws InvalidDataTypeException
229
+	 * @throws InvalidInterfaceException
230
+	 * @throws ReflectionException
231
+	 * @throws Exception
232
+	 */
233
+	public function display($event = null, bool $view_details = false)
234
+	{
235
+		// reset filter for displaying submit button
236
+		remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
237
+		// poke and prod incoming event till it tells us what it is
238
+		if (! $this->setEvent($event)) {
239
+			return $this->handleMissingEvent();
240
+		}
241
+		// is the event expired ?
242
+		$template_args['event_is_expired'] = ! is_admin() && $this->event->is_expired();
243
+		if ($template_args['event_is_expired']) {
244
+			return is_single()
245
+				? $this->expiredEventMessage()
246
+				: $this->expiredEventMessage() . $this->displayViewDetailsButton();
247
+		}
248
+		// begin gathering template arguments by getting event status
249
+		$template_args = ['event_status' => $this->event->get_active_status()];
250
+		if (
251
+			$this->activeEventAndShowTicketSelector(
252
+				$event,
253
+				$template_args['event_status'],
254
+				$view_details
255
+			)
256
+		) {
257
+			return ! is_single() ? $this->displayViewDetailsButton() : '';
258
+		}
259
+		// filter the maximum qty that can appear in the Ticket Selector qty dropdowns
260
+		$this->setMaxAttendees($this->event->additional_limit());
261
+		if ($this->getMaxAttendees() < 1) {
262
+			return $this->ticketSalesClosedMessage();
263
+		}
264
+		// get all tickets for this event ordered by the datetime
265
+		$tickets = $this->getTickets();
266
+		if (count($tickets) < 1) {
267
+			return $this->noTicketAvailableMessage();
268
+		}
269
+		// redirecting to another site for registration ??
270
+		$external_url = (string) $this->event->external_url()
271
+						&& $this->event->external_url() !== get_the_permalink()
272
+			? $this->event->external_url()
273
+			: '';
274
+		// if redirecting to another site for registration, then we don't load the TS
275
+		$ticket_selector = $external_url
276
+			? $this->externalEventRegistration()
277
+			: $this->loadTicketSelector($tickets, $template_args);
278
+		// now set up the form (but not for the admin)
279
+		$ticket_selector = $this->display_full_ui()
280
+			? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector
281
+			: $ticket_selector;
282
+		// submit button and form close tag
283
+		$ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : '';
284
+		return $ticket_selector;
285
+	}
286
+
287
+
288
+	/**
289
+	 * displayTicketSelector
290
+	 * examines the event properties and determines whether a Ticket Selector should be displayed
291
+	 *
292
+	 * @param WP_Post|int $event
293
+	 * @param string      $_event_active_status
294
+	 * @param bool        $view_details
295
+	 * @return bool
296
+	 * @throws EE_Error
297
+	 * @throws ReflectionException
298
+	 */
299
+	protected function activeEventAndShowTicketSelector($event, string $_event_active_status, bool $view_details): bool
300
+	{
301
+		$event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event;
302
+		return $this->display_full_ui()
303
+			   && (
304
+				   ! $this->event->display_ticket_selector()
305
+				   || $view_details
306
+				   || post_password_required($event_post)
307
+				   || (
308
+					   $_event_active_status !== EE_Datetime::active
309
+					   && $_event_active_status !== EE_Datetime::upcoming
310
+					   && $_event_active_status !== EE_Datetime::sold_out
311
+					   && ! (
312
+						   $_event_active_status === EE_Datetime::inactive
313
+						   && is_user_logged_in()
314
+					   )
315
+				   )
316
+			   );
317
+	}
318
+
319
+
320
+	/**
321
+	 * noTicketAvailableMessage
322
+	 * notice displayed if event is expired
323
+	 *
324
+	 * @return string
325
+	 */
326
+	protected function expiredEventMessage(): string
327
+	{
328
+		return '<div class="ee-event-expired-notice"><span class="important-notice">'
329
+		   . esc_html__(
330
+			   'We\'re sorry, but all tickets sales have ended because the event is expired.',
331
+			   'event_espresso'
332
+		   )
333
+		   . '</span></div><!-- .ee-event-expired-notice -->';
334
+	}
335
+
336
+
337
+	/**
338
+	 * noTicketAvailableMessage
339
+	 * notice displayed if event has no more tickets available
340
+	 *
341
+	 * @return string
342
+	 * @throws EE_Error
343
+	 * @throws ReflectionException
344
+	 */
345
+	protected function noTicketAvailableMessage(): string
346
+	{
347
+		$no_ticket_available_msg = esc_html__('We\'re sorry, but all ticket sales have ended.', 'event_espresso');
348
+		if (current_user_can('edit_post', $this->event->ID())) {
349
+			$no_ticket_available_msg .= sprintf(
350
+				esc_html__(
351
+					'%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s',
352
+					'event_espresso'
353
+				),
354
+				'<div class="ee-attention" style="text-align: left;"><b>',
355
+				'</b><br />',
356
+				'<span class="edit-link"><a class="post-edit-link" href="'
357
+				. get_edit_post_link($this->event->ID())
358
+				. '">',
359
+				'</a></span></div><!-- .ee-attention noTicketAvailableMessage -->'
360
+			);
361
+		}
362
+		return '
363 363
             <div class="ee-event-expired-notice">
364 364
                 <span class="important-notice">' . $no_ticket_available_msg . '</span>
365 365
             </div><!-- .ee-event-expired-notice -->';
366
-    }
367
-
368
-
369
-    /**
370
-     * ticketSalesClosed
371
-     * notice displayed if event ticket sales are turned off
372
-     *
373
-     * @return string
374
-     * @throws EE_Error
375
-     * @throws ReflectionException
376
-     */
377
-    protected function ticketSalesClosedMessage(): string
378
-    {
379
-        $sales_closed_msg = esc_html__(
380
-            'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.',
381
-            'event_espresso'
382
-        );
383
-        if (current_user_can('edit_post', $this->event->ID())) {
384
-            $sales_closed_msg .= sprintf(
385
-                esc_html__(
386
-                    '%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s',
387
-                    'event_espresso'
388
-                ),
389
-                '<div class="ee-attention" style="text-align: left;"><b>',
390
-                '</b><br />',
391
-                '<span class="edit-link"><a class="post-edit-link" href="'
392
-                . get_edit_post_link($this->event->ID())
393
-                . '">',
394
-                '</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->'
395
-            );
396
-        }
397
-        return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
398
-    }
399
-
400
-
401
-    /**
402
-     * getTickets
403
-     *
404
-     * @return EE_Base_Class[]|EE_Ticket[]
405
-     * @throws EE_Error
406
-     * @throws InvalidDataTypeException
407
-     * @throws InvalidInterfaceException
408
-     * @throws InvalidArgumentException
409
-     * @throws ReflectionException
410
-     */
411
-    protected function getTickets()
412
-    {
413
-        $show_expired_tickets = is_admin() || $this->config->show_expired_tickets;
414
-
415
-        $ticket_query_args = [
416
-            [
417
-                'Datetime.EVT_ID' => $this->event->ID(),
418
-                'TKT_visibility'  => ['>', EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE],
419
-            ],
420
-            'order_by' => [
421
-                'TKT_required'           => 'DESC',
422
-                'TKT_order'              => 'ASC',
423
-                'TKT_start_date'         => 'ASC',
424
-                'TKT_end_date'           => 'ASC',
425
-                'Datetime.DTT_EVT_start' => 'DESC',
426
-            ],
427
-        ];
428
-
429
-        $datetime_id = $this->request->getRequestParam('datetime', 0, 'int');
430
-        if ($datetime_id) {
431
-            $ticket_query_args[0]['Datetime.DTT_ID'] = $datetime_id;
432
-        }
433
-
434
-        if (! $show_expired_tickets) {
435
-            // use the correct applicable time query depending on what version of core is being run.
436
-            $current_time                         = method_exists('EEM_Datetime', 'current_time_for_query')
437
-                ? time()
438
-                : current_time('timestamp');
439
-            $ticket_query_args[0]['TKT_end_date'] = ['>', $current_time];
440
-        }
441
-        /** @var EE_Ticket[] $tickets */
442
-        $tickets = EEM_Ticket::instance()->get_all($ticket_query_args);
443
-        // remove tickets based on their visibility and the current user's allowed access (crudely based on roles)
444
-        // and filter the returned results
445
-         $tickets = array_filter($tickets, [$this, 'ticketVisibilityFilter']);
446
-        return (array) apply_filters(
447
-            'FHEE__EventEspresso_modules_ticketSelector_DisplayTicketSelector__getTickets',
448
-            $tickets,
449
-            $ticket_query_args,
450
-            $this
451
-        );
452
-    }
453
-
454
-
455
-    /**
456
-     * returns true if any of the following is true:
457
-     *  - ticket visibility is PUBLIC
458
-     *  - ticket visibility is MEMBERS_ONLY and user is logged in
459
-     *  - ticket visibility is ADMINS_ONLY when user IS logged in as an admin
460
-     *  - ticket visibility is ADMIN_UI_ONLY when ticket selector is being viewed via an admin page UI
461
-     *
462
-     * @param EE_Ticket $ticket
463
-     * @return bool
464
-     * @throws EE_Error
465
-     * @throws ReflectionException
466
-     * @since   5.0.0.p
467
-     */
468
-    public function ticketVisibilityFilter(EE_Ticket $ticket): bool
469
-    {
470
-        return $ticket->isPublicOnly()
471
-               || ($ticket->isMembersOnly() && $this->current_user->isLoggedIn())
472
-               || (
473
-                   $ticket->isAdminsOnly()
474
-                   && ($this->current_user->isEventManager() || $this->current_user->isSuperAdmin())
475
-               )
476
-               || ($ticket->isAdminUiOnly() && is_admin());
477
-    }
478
-
479
-
480
-    /**
481
-     * loadTicketSelector
482
-     * begins to assemble template arguments
483
-     * and decides whether to load a "simple" ticket selector, or the standard
484
-     *
485
-     * @param EE_Ticket[] $tickets
486
-     * @param array       $template_args
487
-     * @return TicketSelectorSimple|TicketSelectorStandard
488
-     * @throws EE_Error
489
-     * @throws ReflectionException
490
-     */
491
-    protected function loadTicketSelector(array $tickets, array $template_args)
492
-    {
493
-        $template_args['event']            = $this->event;
494
-        $template_args['EVT_ID']           = $this->event->ID();
495
-        $template_args['event_is_expired'] = $this->event->is_expired();
496
-        $template_args['max_atndz']        = $this->getMaxAttendees();
497
-        $template_args['date_format']      = $this->date_format;
498
-        $template_args['time_format']      = $this->time_format;
499
-        /**
500
-         * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected
501
-         *
502
-         * @param string  '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to
503
-         * @param int $EVT_ID The Event ID
504
-         * @since 4.9.13
505
-         */
506
-        $template_args['anchor_id']    = apply_filters(
507
-            'FHEE__EE_Ticket_Selector__redirect_anchor_id',
508
-            '#tkt-slctr-tbl-' . $this->event->ID(),
509
-            $this->event->ID()
510
-        );
511
-        $template_args['tickets']      = $tickets;
512
-        $template_args['ticket_count'] = count($tickets);
513
-        $ticket_selector               = $this->simpleTicketSelector($tickets, $template_args);
514
-        if ($ticket_selector instanceof TicketSelectorSimple) {
515
-            return $ticket_selector;
516
-        }
517
-        return new TicketSelectorStandard(
518
-            $this->config,
519
-            $this->getTaxConfig(),
520
-            $this->event,
521
-            $tickets,
522
-            $this->getMaxAttendees(),
523
-            $template_args,
524
-            $this->date_format,
525
-            $this->time_format
526
-        );
527
-    }
528
-
529
-
530
-    /**
531
-     * simpleTicketSelector
532
-     * there's one ticket, and max attendees is set to one,
533
-     * so if the event is free, then this is a "simple" ticket selector
534
-     * a.k.a. "Dude Where's my Ticket Selector?"
535
-     *
536
-     * @param EE_Ticket[] $tickets
537
-     * @param array       $template_args
538
-     * @return string
539
-     * @throws EE_Error
540
-     * @throws ReflectionException
541
-     */
542
-    protected function simpleTicketSelector(array $tickets, array $template_args)
543
-    {
544
-        // if there is only ONE ticket with a max qty of ONE
545
-        if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) {
546
-            return '';
547
-        }
548
-        /** @var EE_Ticket $ticket */
549
-        $ticket = reset($tickets);
550
-        // if the ticket is free... then not much need for the ticket selector
551
-        if (
552
-            apply_filters(
553
-                'FHEE__ticket_selector_chart_template__hide_ticket_selector',
554
-                $ticket->is_free(),
555
-                $this->event->ID()
556
-            )
557
-        ) {
558
-            return new TicketSelectorSimple(
559
-                $this->event,
560
-                $ticket,
561
-                $this->getMaxAttendees(),
562
-                $template_args
563
-            );
564
-        }
565
-        return '';
566
-    }
567
-
568
-
569
-    /**
570
-     * externalEventRegistration
571
-     *
572
-     * @return string
573
-     */
574
-    public function externalEventRegistration(): string
575
-    {
576
-        // if not we still need to trigger the display of the submit button
577
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
578
-        // display notice to admin that registration is external
579
-        return $this->display_full_ui()
580
-            ? esc_html__(
581
-                'Registration is at an external URL for this event.',
582
-                'event_espresso'
583
-            )
584
-            : '';
585
-    }
586
-
587
-
588
-    /**
589
-     * formOpen
590
-     *
591
-     * @param int    $ID
592
-     * @param string $external_url
593
-     * @return        string
594
-     */
595
-    public function formOpen(int $ID = 0, string $external_url = ''): string
596
-    {
597
-        // if redirecting, we don't need any anything else
598
-        if ($external_url) {
599
-            $html = '<form method="GET" ';
600
-            $html .= 'action="' . EEH_URL::refactor_url($external_url) . '" ';
601
-            $html .= 'name="ticket-selector-form-' . $ID . '"';
602
-            // open link in new window ?
603
-            $html       .= apply_filters(
604
-                'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank',
605
-                $this->isIframe(),
606
-                $this
607
-            )
608
-                ? ' target="_blank"'
609
-                : '';
610
-            $html       .= '>';
611
-            $query_args = EEH_URL::get_query_string($external_url);
612
-            foreach ((array) $query_args as $query_arg => $value) {
613
-                $html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">';
614
-            }
615
-            return $html;
616
-        }
617
-        // if there is no submit button, then don't start building a form
618
-        // because the "View Details" button will build its own form
619
-        if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
620
-            return '';
621
-        }
622
-        $checkout_url = EEH_Event_View::event_link_url($ID);
623
-        if (! $checkout_url) {
624
-            EE_Error::add_error(
625
-                esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
626
-                __FILE__,
627
-                __FUNCTION__,
628
-                __LINE__
629
-            );
630
-        }
631
-        // set no cache headers and constants
632
-        EE_System::do_not_cache();
633
-        $html = '<form method="POST" ';
634
-        $html .= 'action="' . $checkout_url . '" ';
635
-        $html .= 'name="ticket-selector-form-' . $ID . '"';
636
-        $html .= $this->iframe ? ' target="_blank"' : '';
637
-        $html .= '>';
638
-        $html .= '<input type="hidden" name="ee" value="process_ticket_selections">';
639
-        return apply_filters('FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event);
640
-    }
641
-
642
-
643
-    /**
644
-     * displaySubmitButton
645
-     *
646
-     * @param string $external_url
647
-     * @return string
648
-     * @throws EE_Error
649
-     * @throws ReflectionException
650
-     */
651
-    public function displaySubmitButton(string $external_url = ''): string
652
-    {
653
-        $html = '';
654
-        if ($this->display_full_ui()) {
655
-            // standard TS displayed with submit button, ie: "Register Now"
656
-            if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
657
-                $html .= $this->displayRegisterNowButton();
658
-                $html .= empty($external_url)
659
-                    ? $this->ticketSelectorEndDiv()
660
-                    : $this->clearTicketSelector();
661
-                $html .= '<br/>' . $this->formClose();
662
-            } elseif ($this->getMaxAttendees() === 1) {
663
-                // its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1)
664
-                if ($this->event->is_sold_out()) {
665
-                    // then instead of a View Details or Submit button, just display a "Sold Out" message
666
-                    $html .= apply_filters(
667
-                        'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg',
668
-                        sprintf(
669
-                            esc_html__(
670
-                                '%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s',
671
-                                'event_espresso'
672
-                            ),
673
-                            '<p class="no-ticket-selector-msg clear-float">',
674
-                            $this->event->name(),
675
-                            '</p>',
676
-                            '<br />'
677
-                        ),
678
-                        $this->event
679
-                    );
680
-                    if (
681
-                        apply_filters(
682
-                            'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
683
-                            false,
684
-                            $this->event
685
-                        )
686
-                    ) {
687
-                        $html .= $this->displayRegisterNowButton();
688
-                    }
689
-                    // sold out DWMTS event, no TS, no submit or view details button, but has additional content
690
-                    $html .= $this->ticketSelectorEndDiv();
691
-                } elseif (
692
-                    apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false)
693
-                    && ! is_single()
694
-                ) {
695
-                    // this is a "Dude Where's my Ticket Selector?" (DWMTS) type event,
696
-                    // but no tickets are available, so display event's "View Details" button.
697
-                    // it is being viewed via somewhere other than a single post
698
-                    $html .= $this->displayViewDetailsButton(true);
699
-                } else {
700
-                    $html .= $this->ticketSelectorEndDiv();
701
-                }
702
-            } elseif (is_archive()) {
703
-                // event list, no tickets available so display event's "View Details" button
704
-                $html .= $this->ticketSelectorEndDiv();
705
-                $html .= $this->displayViewDetailsButton();
706
-            } else {
707
-                if (
708
-                    apply_filters(
709
-                        'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
710
-                        false,
711
-                        $this->event
712
-                    )
713
-                ) {
714
-                    $html .= $this->displayRegisterNowButton();
715
-                }
716
-                // no submit or view details button, and no additional content
717
-                $html .= $this->ticketSelectorEndDiv();
718
-            }
719
-            if (! $this->iframe && ! is_archive()) {
720
-                $html .= EEH_Template::powered_by_event_espresso('', '', ['utm_content' => 'ticket_selector']);
721
-            }
722
-        }
723
-        return apply_filters(
724
-            'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html',
725
-            $html,
726
-            $this->event,
727
-            $this
728
-        );
729
-    }
730
-
731
-
732
-    /**
733
-     * @return string
734
-     * @throws EE_Error
735
-     * @throws ReflectionException
736
-     */
737
-    public function displayRegisterNowButton(): string
738
-    {
739
-        $btn_text     = apply_filters(
740
-            'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text',
741
-            esc_html__('Register Now', 'event_espresso'),
742
-            $this->event
743
-        );
744
-        $external_url = (string) $this->event->external_url()
745
-                        && $this->event->external_url() !== get_the_permalink()
746
-            ? $this->event->external_url()
747
-            : '';
748
-        $html         = EEH_HTML::div(
749
-            '',
750
-            'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap',
751
-            'ticket-selector-submit-btn-wrap'
752
-        );
753
-        $html         .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"';
754
-        $html         .= ' class="ticket-selector-submit-btn ';
755
-        $html         .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"';
756
-        $html         .= ' type="submit" value="' . $btn_text . '" data-ee-disable-after-recaptcha="true" />';
757
-        $html         .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->';
758
-        $html         .= apply_filters(
759
-            'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
760
-            '',
761
-            $this->event,
762
-            $this->iframe
763
-        );
764
-        return $html;
765
-    }
766
-
767
-
768
-    /**
769
-     * displayViewDetailsButton
770
-     *
771
-     * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event
772
-     *                    (ie: $_max_atndz === 1) where there are no available tickets,
773
-     *                    either because they are sold out, expired, or not yet on sale.
774
-     *                    In this case, we need to close the form BEFORE adding any closing divs
775
-     * @return string
776
-     * @throws EE_Error
777
-     * @throws ReflectionException
778
-     */
779
-    public function displayViewDetailsButton(bool $DWMTS = false): string
780
-    {
781
-        if (! $this->event->get_permalink()) {
782
-            EE_Error::add_error(
783
-                esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
784
-                __FILE__,
785
-                __FUNCTION__,
786
-                __LINE__
787
-            );
788
-        }
789
-        $view_details_btn = '<form method="GET" action="';
790
-        $view_details_btn .= apply_filters(
791
-            'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url',
792
-            $this->event->get_permalink(),
793
-            $this->event
794
-        );
795
-        $view_details_btn .= '"';
796
-        // open link in new window ?
797
-        $view_details_btn .= apply_filters(
798
-            'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank',
799
-            $this->isIframe(),
800
-            $this
801
-        )
802
-            ? ' target="_blank"'
803
-            : '';
804
-        $view_details_btn .= '>';
805
-        $btn_text         = apply_filters(
806
-            'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text',
807
-            esc_html__('View Details', 'event_espresso'),
808
-            $this->event
809
-        );
810
-        $view_details_btn .= '<input id="ticket-selector-submit-'
811
-                             . $this->event->ID()
812
-                             . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="'
813
-                             . $btn_text
814
-                             . '" />';
815
-        $view_details_btn .= apply_filters('FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event);
816
-        if ($DWMTS) {
817
-            $view_details_btn .= $this->formClose();
818
-            $view_details_btn .= $this->ticketSelectorEndDiv();
819
-            $view_details_btn .= '<br/>';
820
-        } else {
821
-            $view_details_btn .= $this->clearTicketSelector();
822
-            $view_details_btn .= '<br/>';
823
-            $view_details_btn .= $this->formClose();
824
-        }
825
-        return $view_details_btn;
826
-    }
827
-
828
-
829
-    /**
830
-     * @return string
831
-     */
832
-    public function ticketSelectorEndDiv(): string
833
-    {
834
-        return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->';
835
-    }
836
-
837
-
838
-    /**
839
-     * @return string
840
-     */
841
-    public function clearTicketSelector(): string
842
-    {
843
-        // standard TS displayed, appears after a "Register Now" or "view Details" button
844
-        return '<div class="clear"></div><!-- clearTicketSelector -->';
845
-    }
846
-
847
-
848
-    /**
849
-     * @access        public
850
-     * @return        string
851
-     */
852
-    public function formClose(): string
853
-    {
854
-        return '</form>';
855
-    }
856
-
857
-
858
-    /**
859
-     * handleMissingEvent
860
-     * Returns either false or an error to display when no valid event is passed.
861
-     *
862
-     * @return string
863
-     * @throws ExceptionStackTraceDisplay
864
-     * @throws InvalidInterfaceException
865
-     * @throws Exception
866
-     */
867
-    protected function handleMissingEvent()
868
-    {
869
-        // If this is not an iFrame request, simply return false.
870
-        if (! $this->isIframe()) {
871
-            return '';
872
-        }
873
-        // This is an iFrame so return an error.
874
-        // Display stack trace if WP_DEBUG is enabled.
875
-        if (WP_DEBUG === true && current_user_can('edit_pages')) {
876
-            $event_id = $this->request->getRequestParam('event', 0, 'int');
877
-            new ExceptionStackTraceDisplay(
878
-                new InvalidArgumentException(
879
-                    sprintf(
880
-                        esc_html__(
881
-                            'A valid Event ID is required to display the ticket selector.%3$sAn Event with an ID of "%1$s" could not be found.%3$sPlease verify that the embed code added to this post\'s content includes an "%2$s" argument and that its value corresponds to a valid Event ID.',
882
-                            'event_espresso'
883
-                        ),
884
-                        $event_id,
885
-                        'event',
886
-                        '<br />'
887
-                    )
888
-                )
889
-            );
890
-            return '';
891
-        }
892
-        // If WP_DEBUG is not enabled, display a message stating the event could not be found.
893
-        return EEH_HTML::p(
894
-            esc_html__(
895
-                'A valid Event could not be found. Please contact the event administrator for assistance.',
896
-                'event_espresso'
897
-            )
898
-        );
899
-    }
900
-
901
-
902
-    /**
903
-     * @return EE_Tax_Config
904
-     * @since   4.10.14.p
905
-     */
906
-    protected function getTaxConfig()
907
-    {
908
-        return isset(EE_Registry::instance()->CFG->tax_settings)
909
-               && EE_Registry::instance()->CFG->tax_settings instanceof EE_Tax_Config
910
-            ? EE_Registry::instance()->CFG->tax_settings
911
-            : new EE_Tax_Config();
912
-    }
366
+	}
367
+
368
+
369
+	/**
370
+	 * ticketSalesClosed
371
+	 * notice displayed if event ticket sales are turned off
372
+	 *
373
+	 * @return string
374
+	 * @throws EE_Error
375
+	 * @throws ReflectionException
376
+	 */
377
+	protected function ticketSalesClosedMessage(): string
378
+	{
379
+		$sales_closed_msg = esc_html__(
380
+			'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.',
381
+			'event_espresso'
382
+		);
383
+		if (current_user_can('edit_post', $this->event->ID())) {
384
+			$sales_closed_msg .= sprintf(
385
+				esc_html__(
386
+					'%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s',
387
+					'event_espresso'
388
+				),
389
+				'<div class="ee-attention" style="text-align: left;"><b>',
390
+				'</b><br />',
391
+				'<span class="edit-link"><a class="post-edit-link" href="'
392
+				. get_edit_post_link($this->event->ID())
393
+				. '">',
394
+				'</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->'
395
+			);
396
+		}
397
+		return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
398
+	}
399
+
400
+
401
+	/**
402
+	 * getTickets
403
+	 *
404
+	 * @return EE_Base_Class[]|EE_Ticket[]
405
+	 * @throws EE_Error
406
+	 * @throws InvalidDataTypeException
407
+	 * @throws InvalidInterfaceException
408
+	 * @throws InvalidArgumentException
409
+	 * @throws ReflectionException
410
+	 */
411
+	protected function getTickets()
412
+	{
413
+		$show_expired_tickets = is_admin() || $this->config->show_expired_tickets;
414
+
415
+		$ticket_query_args = [
416
+			[
417
+				'Datetime.EVT_ID' => $this->event->ID(),
418
+				'TKT_visibility'  => ['>', EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE],
419
+			],
420
+			'order_by' => [
421
+				'TKT_required'           => 'DESC',
422
+				'TKT_order'              => 'ASC',
423
+				'TKT_start_date'         => 'ASC',
424
+				'TKT_end_date'           => 'ASC',
425
+				'Datetime.DTT_EVT_start' => 'DESC',
426
+			],
427
+		];
428
+
429
+		$datetime_id = $this->request->getRequestParam('datetime', 0, 'int');
430
+		if ($datetime_id) {
431
+			$ticket_query_args[0]['Datetime.DTT_ID'] = $datetime_id;
432
+		}
433
+
434
+		if (! $show_expired_tickets) {
435
+			// use the correct applicable time query depending on what version of core is being run.
436
+			$current_time                         = method_exists('EEM_Datetime', 'current_time_for_query')
437
+				? time()
438
+				: current_time('timestamp');
439
+			$ticket_query_args[0]['TKT_end_date'] = ['>', $current_time];
440
+		}
441
+		/** @var EE_Ticket[] $tickets */
442
+		$tickets = EEM_Ticket::instance()->get_all($ticket_query_args);
443
+		// remove tickets based on their visibility and the current user's allowed access (crudely based on roles)
444
+		// and filter the returned results
445
+		 $tickets = array_filter($tickets, [$this, 'ticketVisibilityFilter']);
446
+		return (array) apply_filters(
447
+			'FHEE__EventEspresso_modules_ticketSelector_DisplayTicketSelector__getTickets',
448
+			$tickets,
449
+			$ticket_query_args,
450
+			$this
451
+		);
452
+	}
453
+
454
+
455
+	/**
456
+	 * returns true if any of the following is true:
457
+	 *  - ticket visibility is PUBLIC
458
+	 *  - ticket visibility is MEMBERS_ONLY and user is logged in
459
+	 *  - ticket visibility is ADMINS_ONLY when user IS logged in as an admin
460
+	 *  - ticket visibility is ADMIN_UI_ONLY when ticket selector is being viewed via an admin page UI
461
+	 *
462
+	 * @param EE_Ticket $ticket
463
+	 * @return bool
464
+	 * @throws EE_Error
465
+	 * @throws ReflectionException
466
+	 * @since   5.0.0.p
467
+	 */
468
+	public function ticketVisibilityFilter(EE_Ticket $ticket): bool
469
+	{
470
+		return $ticket->isPublicOnly()
471
+			   || ($ticket->isMembersOnly() && $this->current_user->isLoggedIn())
472
+			   || (
473
+				   $ticket->isAdminsOnly()
474
+				   && ($this->current_user->isEventManager() || $this->current_user->isSuperAdmin())
475
+			   )
476
+			   || ($ticket->isAdminUiOnly() && is_admin());
477
+	}
478
+
479
+
480
+	/**
481
+	 * loadTicketSelector
482
+	 * begins to assemble template arguments
483
+	 * and decides whether to load a "simple" ticket selector, or the standard
484
+	 *
485
+	 * @param EE_Ticket[] $tickets
486
+	 * @param array       $template_args
487
+	 * @return TicketSelectorSimple|TicketSelectorStandard
488
+	 * @throws EE_Error
489
+	 * @throws ReflectionException
490
+	 */
491
+	protected function loadTicketSelector(array $tickets, array $template_args)
492
+	{
493
+		$template_args['event']            = $this->event;
494
+		$template_args['EVT_ID']           = $this->event->ID();
495
+		$template_args['event_is_expired'] = $this->event->is_expired();
496
+		$template_args['max_atndz']        = $this->getMaxAttendees();
497
+		$template_args['date_format']      = $this->date_format;
498
+		$template_args['time_format']      = $this->time_format;
499
+		/**
500
+		 * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected
501
+		 *
502
+		 * @param string  '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to
503
+		 * @param int $EVT_ID The Event ID
504
+		 * @since 4.9.13
505
+		 */
506
+		$template_args['anchor_id']    = apply_filters(
507
+			'FHEE__EE_Ticket_Selector__redirect_anchor_id',
508
+			'#tkt-slctr-tbl-' . $this->event->ID(),
509
+			$this->event->ID()
510
+		);
511
+		$template_args['tickets']      = $tickets;
512
+		$template_args['ticket_count'] = count($tickets);
513
+		$ticket_selector               = $this->simpleTicketSelector($tickets, $template_args);
514
+		if ($ticket_selector instanceof TicketSelectorSimple) {
515
+			return $ticket_selector;
516
+		}
517
+		return new TicketSelectorStandard(
518
+			$this->config,
519
+			$this->getTaxConfig(),
520
+			$this->event,
521
+			$tickets,
522
+			$this->getMaxAttendees(),
523
+			$template_args,
524
+			$this->date_format,
525
+			$this->time_format
526
+		);
527
+	}
528
+
529
+
530
+	/**
531
+	 * simpleTicketSelector
532
+	 * there's one ticket, and max attendees is set to one,
533
+	 * so if the event is free, then this is a "simple" ticket selector
534
+	 * a.k.a. "Dude Where's my Ticket Selector?"
535
+	 *
536
+	 * @param EE_Ticket[] $tickets
537
+	 * @param array       $template_args
538
+	 * @return string
539
+	 * @throws EE_Error
540
+	 * @throws ReflectionException
541
+	 */
542
+	protected function simpleTicketSelector(array $tickets, array $template_args)
543
+	{
544
+		// if there is only ONE ticket with a max qty of ONE
545
+		if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) {
546
+			return '';
547
+		}
548
+		/** @var EE_Ticket $ticket */
549
+		$ticket = reset($tickets);
550
+		// if the ticket is free... then not much need for the ticket selector
551
+		if (
552
+			apply_filters(
553
+				'FHEE__ticket_selector_chart_template__hide_ticket_selector',
554
+				$ticket->is_free(),
555
+				$this->event->ID()
556
+			)
557
+		) {
558
+			return new TicketSelectorSimple(
559
+				$this->event,
560
+				$ticket,
561
+				$this->getMaxAttendees(),
562
+				$template_args
563
+			);
564
+		}
565
+		return '';
566
+	}
567
+
568
+
569
+	/**
570
+	 * externalEventRegistration
571
+	 *
572
+	 * @return string
573
+	 */
574
+	public function externalEventRegistration(): string
575
+	{
576
+		// if not we still need to trigger the display of the submit button
577
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
578
+		// display notice to admin that registration is external
579
+		return $this->display_full_ui()
580
+			? esc_html__(
581
+				'Registration is at an external URL for this event.',
582
+				'event_espresso'
583
+			)
584
+			: '';
585
+	}
586
+
587
+
588
+	/**
589
+	 * formOpen
590
+	 *
591
+	 * @param int    $ID
592
+	 * @param string $external_url
593
+	 * @return        string
594
+	 */
595
+	public function formOpen(int $ID = 0, string $external_url = ''): string
596
+	{
597
+		// if redirecting, we don't need any anything else
598
+		if ($external_url) {
599
+			$html = '<form method="GET" ';
600
+			$html .= 'action="' . EEH_URL::refactor_url($external_url) . '" ';
601
+			$html .= 'name="ticket-selector-form-' . $ID . '"';
602
+			// open link in new window ?
603
+			$html       .= apply_filters(
604
+				'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank',
605
+				$this->isIframe(),
606
+				$this
607
+			)
608
+				? ' target="_blank"'
609
+				: '';
610
+			$html       .= '>';
611
+			$query_args = EEH_URL::get_query_string($external_url);
612
+			foreach ((array) $query_args as $query_arg => $value) {
613
+				$html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">';
614
+			}
615
+			return $html;
616
+		}
617
+		// if there is no submit button, then don't start building a form
618
+		// because the "View Details" button will build its own form
619
+		if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
620
+			return '';
621
+		}
622
+		$checkout_url = EEH_Event_View::event_link_url($ID);
623
+		if (! $checkout_url) {
624
+			EE_Error::add_error(
625
+				esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
626
+				__FILE__,
627
+				__FUNCTION__,
628
+				__LINE__
629
+			);
630
+		}
631
+		// set no cache headers and constants
632
+		EE_System::do_not_cache();
633
+		$html = '<form method="POST" ';
634
+		$html .= 'action="' . $checkout_url . '" ';
635
+		$html .= 'name="ticket-selector-form-' . $ID . '"';
636
+		$html .= $this->iframe ? ' target="_blank"' : '';
637
+		$html .= '>';
638
+		$html .= '<input type="hidden" name="ee" value="process_ticket_selections">';
639
+		return apply_filters('FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event);
640
+	}
641
+
642
+
643
+	/**
644
+	 * displaySubmitButton
645
+	 *
646
+	 * @param string $external_url
647
+	 * @return string
648
+	 * @throws EE_Error
649
+	 * @throws ReflectionException
650
+	 */
651
+	public function displaySubmitButton(string $external_url = ''): string
652
+	{
653
+		$html = '';
654
+		if ($this->display_full_ui()) {
655
+			// standard TS displayed with submit button, ie: "Register Now"
656
+			if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
657
+				$html .= $this->displayRegisterNowButton();
658
+				$html .= empty($external_url)
659
+					? $this->ticketSelectorEndDiv()
660
+					: $this->clearTicketSelector();
661
+				$html .= '<br/>' . $this->formClose();
662
+			} elseif ($this->getMaxAttendees() === 1) {
663
+				// its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1)
664
+				if ($this->event->is_sold_out()) {
665
+					// then instead of a View Details or Submit button, just display a "Sold Out" message
666
+					$html .= apply_filters(
667
+						'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg',
668
+						sprintf(
669
+							esc_html__(
670
+								'%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s',
671
+								'event_espresso'
672
+							),
673
+							'<p class="no-ticket-selector-msg clear-float">',
674
+							$this->event->name(),
675
+							'</p>',
676
+							'<br />'
677
+						),
678
+						$this->event
679
+					);
680
+					if (
681
+						apply_filters(
682
+							'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
683
+							false,
684
+							$this->event
685
+						)
686
+					) {
687
+						$html .= $this->displayRegisterNowButton();
688
+					}
689
+					// sold out DWMTS event, no TS, no submit or view details button, but has additional content
690
+					$html .= $this->ticketSelectorEndDiv();
691
+				} elseif (
692
+					apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false)
693
+					&& ! is_single()
694
+				) {
695
+					// this is a "Dude Where's my Ticket Selector?" (DWMTS) type event,
696
+					// but no tickets are available, so display event's "View Details" button.
697
+					// it is being viewed via somewhere other than a single post
698
+					$html .= $this->displayViewDetailsButton(true);
699
+				} else {
700
+					$html .= $this->ticketSelectorEndDiv();
701
+				}
702
+			} elseif (is_archive()) {
703
+				// event list, no tickets available so display event's "View Details" button
704
+				$html .= $this->ticketSelectorEndDiv();
705
+				$html .= $this->displayViewDetailsButton();
706
+			} else {
707
+				if (
708
+					apply_filters(
709
+						'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
710
+						false,
711
+						$this->event
712
+					)
713
+				) {
714
+					$html .= $this->displayRegisterNowButton();
715
+				}
716
+				// no submit or view details button, and no additional content
717
+				$html .= $this->ticketSelectorEndDiv();
718
+			}
719
+			if (! $this->iframe && ! is_archive()) {
720
+				$html .= EEH_Template::powered_by_event_espresso('', '', ['utm_content' => 'ticket_selector']);
721
+			}
722
+		}
723
+		return apply_filters(
724
+			'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html',
725
+			$html,
726
+			$this->event,
727
+			$this
728
+		);
729
+	}
730
+
731
+
732
+	/**
733
+	 * @return string
734
+	 * @throws EE_Error
735
+	 * @throws ReflectionException
736
+	 */
737
+	public function displayRegisterNowButton(): string
738
+	{
739
+		$btn_text     = apply_filters(
740
+			'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text',
741
+			esc_html__('Register Now', 'event_espresso'),
742
+			$this->event
743
+		);
744
+		$external_url = (string) $this->event->external_url()
745
+						&& $this->event->external_url() !== get_the_permalink()
746
+			? $this->event->external_url()
747
+			: '';
748
+		$html         = EEH_HTML::div(
749
+			'',
750
+			'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap',
751
+			'ticket-selector-submit-btn-wrap'
752
+		);
753
+		$html         .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"';
754
+		$html         .= ' class="ticket-selector-submit-btn ';
755
+		$html         .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"';
756
+		$html         .= ' type="submit" value="' . $btn_text . '" data-ee-disable-after-recaptcha="true" />';
757
+		$html         .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->';
758
+		$html         .= apply_filters(
759
+			'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
760
+			'',
761
+			$this->event,
762
+			$this->iframe
763
+		);
764
+		return $html;
765
+	}
766
+
767
+
768
+	/**
769
+	 * displayViewDetailsButton
770
+	 *
771
+	 * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event
772
+	 *                    (ie: $_max_atndz === 1) where there are no available tickets,
773
+	 *                    either because they are sold out, expired, or not yet on sale.
774
+	 *                    In this case, we need to close the form BEFORE adding any closing divs
775
+	 * @return string
776
+	 * @throws EE_Error
777
+	 * @throws ReflectionException
778
+	 */
779
+	public function displayViewDetailsButton(bool $DWMTS = false): string
780
+	{
781
+		if (! $this->event->get_permalink()) {
782
+			EE_Error::add_error(
783
+				esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
784
+				__FILE__,
785
+				__FUNCTION__,
786
+				__LINE__
787
+			);
788
+		}
789
+		$view_details_btn = '<form method="GET" action="';
790
+		$view_details_btn .= apply_filters(
791
+			'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url',
792
+			$this->event->get_permalink(),
793
+			$this->event
794
+		);
795
+		$view_details_btn .= '"';
796
+		// open link in new window ?
797
+		$view_details_btn .= apply_filters(
798
+			'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank',
799
+			$this->isIframe(),
800
+			$this
801
+		)
802
+			? ' target="_blank"'
803
+			: '';
804
+		$view_details_btn .= '>';
805
+		$btn_text         = apply_filters(
806
+			'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text',
807
+			esc_html__('View Details', 'event_espresso'),
808
+			$this->event
809
+		);
810
+		$view_details_btn .= '<input id="ticket-selector-submit-'
811
+							 . $this->event->ID()
812
+							 . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="'
813
+							 . $btn_text
814
+							 . '" />';
815
+		$view_details_btn .= apply_filters('FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event);
816
+		if ($DWMTS) {
817
+			$view_details_btn .= $this->formClose();
818
+			$view_details_btn .= $this->ticketSelectorEndDiv();
819
+			$view_details_btn .= '<br/>';
820
+		} else {
821
+			$view_details_btn .= $this->clearTicketSelector();
822
+			$view_details_btn .= '<br/>';
823
+			$view_details_btn .= $this->formClose();
824
+		}
825
+		return $view_details_btn;
826
+	}
827
+
828
+
829
+	/**
830
+	 * @return string
831
+	 */
832
+	public function ticketSelectorEndDiv(): string
833
+	{
834
+		return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->';
835
+	}
836
+
837
+
838
+	/**
839
+	 * @return string
840
+	 */
841
+	public function clearTicketSelector(): string
842
+	{
843
+		// standard TS displayed, appears after a "Register Now" or "view Details" button
844
+		return '<div class="clear"></div><!-- clearTicketSelector -->';
845
+	}
846
+
847
+
848
+	/**
849
+	 * @access        public
850
+	 * @return        string
851
+	 */
852
+	public function formClose(): string
853
+	{
854
+		return '</form>';
855
+	}
856
+
857
+
858
+	/**
859
+	 * handleMissingEvent
860
+	 * Returns either false or an error to display when no valid event is passed.
861
+	 *
862
+	 * @return string
863
+	 * @throws ExceptionStackTraceDisplay
864
+	 * @throws InvalidInterfaceException
865
+	 * @throws Exception
866
+	 */
867
+	protected function handleMissingEvent()
868
+	{
869
+		// If this is not an iFrame request, simply return false.
870
+		if (! $this->isIframe()) {
871
+			return '';
872
+		}
873
+		// This is an iFrame so return an error.
874
+		// Display stack trace if WP_DEBUG is enabled.
875
+		if (WP_DEBUG === true && current_user_can('edit_pages')) {
876
+			$event_id = $this->request->getRequestParam('event', 0, 'int');
877
+			new ExceptionStackTraceDisplay(
878
+				new InvalidArgumentException(
879
+					sprintf(
880
+						esc_html__(
881
+							'A valid Event ID is required to display the ticket selector.%3$sAn Event with an ID of "%1$s" could not be found.%3$sPlease verify that the embed code added to this post\'s content includes an "%2$s" argument and that its value corresponds to a valid Event ID.',
882
+							'event_espresso'
883
+						),
884
+						$event_id,
885
+						'event',
886
+						'<br />'
887
+					)
888
+				)
889
+			);
890
+			return '';
891
+		}
892
+		// If WP_DEBUG is not enabled, display a message stating the event could not be found.
893
+		return EEH_HTML::p(
894
+			esc_html__(
895
+				'A valid Event could not be found. Please contact the event administrator for assistance.',
896
+				'event_espresso'
897
+			)
898
+		);
899
+	}
900
+
901
+
902
+	/**
903
+	 * @return EE_Tax_Config
904
+	 * @since   4.10.14.p
905
+	 */
906
+	protected function getTaxConfig()
907
+	{
908
+		return isset(EE_Registry::instance()->CFG->tax_settings)
909
+			   && EE_Registry::instance()->CFG->tax_settings instanceof EE_Tax_Config
910
+			? EE_Registry::instance()->CFG->tax_settings
911
+			: new EE_Tax_Config();
912
+	}
913 913
 }
Please login to merge, or discard this patch.
modules/event_single/EED_Event_Single.module.php 1 patch
Indentation   +470 added lines, -470 removed lines patch added patch discarded remove patch
@@ -14,475 +14,475 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class EED_Event_Single extends EED_Module
16 16
 {
17
-    const EVENT_DETAILS_PRIORITY = 100;
18
-    const EVENT_DATETIMES_PRIORITY = 110;
19
-    const EVENT_TICKETS_PRIORITY = 120;
20
-    const EVENT_VENUES_PRIORITY = 130;
21
-
22
-    /**
23
-     * @type bool $using_get_the_excerpt
24
-     */
25
-    protected static $using_get_the_excerpt = false;
26
-
27
-
28
-    /**
29
-     * @type EE_Template_Part_Manager $template_parts
30
-     */
31
-    protected $template_parts;
32
-
33
-
34
-    /**
35
-     * @return EED_Module|EED_Event_Single
36
-     */
37
-    public static function instance()
38
-    {
39
-        return parent::get_instance(__CLASS__);
40
-    }
41
-
42
-
43
-    /**
44
-     * set_hooks - for hooking into EE Core, other modules, etc
45
-     *
46
-     * @return void
47
-     * @throws InvalidArgumentException
48
-     * @throws InvalidDataTypeException
49
-     * @throws InvalidInterfaceException
50
-     */
51
-    public static function set_hooks()
52
-    {
53
-        add_filter('FHEE_run_EE_wp', '__return_true');
54
-        add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
55
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
56
-        $custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
57
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
58
-        );
59
-        $custom_post_types = $custom_post_type_definitions->getDefinitions();
60
-        EE_Config::register_route(
61
-            $custom_post_types[EspressoPostType::EVENTS]['singular_slug'],
62
-            'Event_Single',
63
-            'run'
64
-        );
65
-    }
66
-
67
-    /**
68
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
69
-     *
70
-     * @return    void
71
-     */
72
-    public static function set_hooks_admin()
73
-    {
74
-        add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
75
-    }
76
-
77
-
78
-    /**
79
-     * set_definitions
80
-     *
81
-     * @static
82
-     * @return void
83
-     */
84
-    public static function set_definitions()
85
-    {
86
-        define('EVENT_SINGLE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
87
-        define('EVENT_SINGLE_TEMPLATES_PATH', plugin_dir_path(__FILE__) . 'templates/');
88
-    }
89
-
90
-
91
-    /**
92
-     * set_config
93
-     *
94
-     * @void
95
-     */
96
-    protected function set_config()
97
-    {
98
-        $this->set_config_section('template_settings');
99
-        $this->set_config_class('EE_Event_Single_Config');
100
-        $this->set_config_name('EED_Event_Single');
101
-    }
102
-
103
-
104
-    /**
105
-     * initialize_template_parts
106
-     *
107
-     * @param EE_Config_Base|EE_Event_Single_Config $config
108
-     * @return EE_Template_Part_Manager
109
-     * @throws EE_Error
110
-     */
111
-    public function initialize_template_parts(EE_Event_Single_Config $config = null)
112
-    {
113
-        /** @type EE_Event_Single_Config $config */
114
-        $config = $config instanceof EE_Event_Single_Config ? $config : $this->config();
115
-        EEH_Autoloader::register_template_part_autoloaders();
116
-        $template_parts = new EE_Template_Part_Manager();
117
-        $template_parts->add_template_part(
118
-            'tickets',
119
-            esc_html__('Ticket Selector', 'event_espresso'),
120
-            'content-espresso_events-tickets.php',
121
-            $config->display_order_tickets
122
-        );
123
-        $template_parts->add_template_part(
124
-            'datetimes',
125
-            esc_html__('Dates and Times', 'event_espresso'),
126
-            'content-espresso_events-datetimes.php',
127
-            $config->display_order_datetimes
128
-        );
129
-        $template_parts->add_template_part(
130
-            'event',
131
-            esc_html__('Event Description', 'event_espresso'),
132
-            'content-espresso_events-details.php',
133
-            $config->display_order_event
134
-        );
135
-        $template_parts->add_template_part(
136
-            'venue',
137
-            esc_html__('Venue Information', 'event_espresso'),
138
-            'content-espresso_events-venues.php',
139
-            $config->display_order_venue
140
-        );
141
-        do_action('AHEE__EED_Event_Single__initialize_template_parts', $template_parts);
142
-        return $template_parts;
143
-    }
144
-
145
-
146
-    /**
147
-     * run - initial module setup
148
-     *
149
-     * @param WP $WP
150
-     * @return    void
151
-     */
152
-    public function run($WP)
153
-    {
154
-        // ensure valid EE_Events_Single_Config() object exists
155
-        $this->set_config();
156
-        // check what template is loaded
157
-        add_filter('template_include', array($this, 'template_include'), 999, 1);
158
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
159
-        // load css
160
-        add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
161
-    }
162
-
163
-
164
-    /**
165
-     * template_include
166
-     *
167
-     * @param    string $template
168
-     * @return    string
169
-     */
170
-    public function template_include($template)
171
-    {
172
-        global $post;
173
-        /** @type EE_Event_Single_Config $config */
174
-        $config = $this->config();
175
-        if ($config->display_status_banner_single) {
176
-            add_filter('the_title', array('EED_Event_Single', 'the_title'), 100, 2);
177
-        }
178
-        // not a custom template?
179
-        if (
180
-            ! post_password_required($post)
181
-            && (
182
-                apply_filters('FHEE__EED_Event_Single__template_include__allow_custom_selected_template', false)
183
-                || EE_Registry::instance()
184
-                              ->load_core('Front_Controller')
185
-                              ->get_selected_template() !== 'single-espresso_events.php'
186
-            )
187
-        ) {
188
-            EEH_Template::load_espresso_theme_functions();
189
-            // then add extra event data via hooks
190
-            add_action('loop_start', array('EED_Event_Single', 'loop_start'));
191
-            add_filter('get_the_excerpt', array('EED_Event_Single', 'get_the_excerpt'), 1, 1);
192
-            add_filter(
193
-                'the_content',
194
-                array('EED_Event_Single', 'event_details'),
195
-                EED_Event_Single::EVENT_DETAILS_PRIORITY
196
-            );
197
-            add_action('loop_end', array('EED_Event_Single', 'loop_end'));
198
-            // don't display entry meta because the existing theme will take car of that
199
-            add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
200
-        }
201
-        return $template;
202
-    }
203
-
204
-
205
-    /**
206
-     * loop_start
207
-     *
208
-     * @param    array $wp_query_array an array containing the WP_Query object
209
-     * @return    void
210
-     */
211
-    public static function loop_start($wp_query_array)
212
-    {
213
-        global $post;
214
-        do_action('AHEE_event_details_before_post', $post, $wp_query_array);
215
-    }
216
-
217
-
218
-    /**
219
-     * the_title
220
-     *
221
-     * @param    string $title
222
-     * @param    int    $id
223
-     * @return    string
224
-     */
225
-    public static function the_title($title = '', $id = 0)
226
-    {
227
-        global $post;
228
-        return ((function_exists('wp_is_block_theme') && wp_is_block_theme()) || in_the_loop()) && $post->ID === (int) $id
229
-            ? espresso_event_status_banner($post->ID) . $title
230
-            : $title;
231
-    }
232
-
233
-
234
-    /**
235
-     * get_the_excerpt
236
-     * kinda hacky, but if a theme is using get_the_excerpt(),
237
-     * then we need to remove our filters on the_content()
238
-     *
239
-     * @param        string $excerpt
240
-     * @return        string
241
-     */
242
-    public static function get_the_excerpt($excerpt = '')
243
-    {
244
-        EED_Event_Single::$using_get_the_excerpt = true;
245
-        add_filter('wp_trim_excerpt', array('EED_Event_Single', 'end_get_the_excerpt'), 999, 1);
246
-        return $excerpt;
247
-    }
248
-
249
-
250
-    /**
251
-     * end_get_the_excerpt
252
-     *
253
-     * @param  string $text
254
-     * @return string
255
-     */
256
-    public static function end_get_the_excerpt($text = '')
257
-    {
258
-        EED_Event_Single::$using_get_the_excerpt = false;
259
-        return $text;
260
-    }
261
-
262
-
263
-    /**
264
-     * event_details
265
-     *
266
-     * @param    string $content
267
-     * @return    string
268
-     */
269
-    public static function event_details($content)
270
-    {
271
-        global $post;
272
-        static $current_post_ID = 0;
273
-        if (
274
-            $current_post_ID !== $post->ID
275
-            && $post->post_type === EspressoPostType::EVENTS
276
-            && ! EED_Event_Single::$using_get_the_excerpt
277
-            && ! post_password_required()
278
-        ) {
279
-            // Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
280
-            // Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
281
-            // BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
282
-            // We want to allow those plugins to still do their thing and have access to our content, but depending on
283
-            // how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
284
-            // so the following allows this filter to be applied multiple times, but only once for real
285
-            $current_post_ID = did_action('loop_start') ? $post->ID : 0;
286
-            if (EE_Registry::instance()->CFG->template_settings->EED_Event_Single->use_sortable_display_order) {
287
-                // we need to first remove this callback from being applied to the_content()
288
-                // (otherwise it will recurse and blow up the interweb)
289
-                remove_filter(
290
-                    'the_content',
291
-                    array('EED_Event_Single', 'event_details'),
292
-                    EED_Event_Single::EVENT_DETAILS_PRIORITY
293
-                );
294
-                EED_Event_Single::instance()->template_parts = EED_Event_Single::instance()->initialize_template_parts(
295
-                );
296
-                $content = EEH_Template::locate_template('content-espresso_events-details.php');
297
-                $content = EED_Event_Single::instance()->template_parts->apply_template_part_filters($content);
298
-                add_filter(
299
-                    'the_content',
300
-                    array('EED_Event_Single', 'event_details'),
301
-                    EED_Event_Single::EVENT_DETAILS_PRIORITY
302
-                );
303
-            } else {
304
-                $content = EED_Event_Single::use_filterable_display_order();
305
-            }
306
-        }
307
-        return $content;
308
-    }
309
-
310
-
311
-    /**
312
-     * use_filterable_display_order
313
-     *
314
-     * @return string
315
-     */
316
-    protected static function use_filterable_display_order()
317
-    {
318
-        // since the 'content-espresso_events-details.php' template might be used directly from within a theme,
319
-        // it uses the_content() for displaying the $post->post_content
320
-        // so in order to load a template that uses the_content()
321
-        // from within a callback being used to filter the_content(),
322
-        // we need to first remove this callback from being applied to the_content()
323
-        // (otherwise it will recurse and blow up the interweb)
324
-        remove_filter(
325
-            'the_content',
326
-            array('EED_Event_Single', 'event_details'),
327
-            EED_Event_Single::EVENT_DETAILS_PRIORITY
328
-        );
329
-        // now add additional content
330
-        add_filter(
331
-            'the_content',
332
-            array('EED_Event_Single', 'event_datetimes'),
333
-            EED_Event_Single::EVENT_DATETIMES_PRIORITY,
334
-            1
335
-        );
336
-        add_filter(
337
-            'the_content',
338
-            array('EED_Event_Single', 'event_tickets'),
339
-            EED_Event_Single::EVENT_TICKETS_PRIORITY,
340
-            1
341
-        );
342
-        add_filter(
343
-            'the_content',
344
-            array('EED_Event_Single', 'event_venues'),
345
-            EED_Event_Single::EVENT_VENUES_PRIORITY,
346
-            1
347
-        );
348
-        do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_add_filters');
349
-        // now load our template
350
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
351
-        // now add our filter back in, plus some others
352
-        add_filter(
353
-            'the_content',
354
-            array('EED_Event_Single', 'event_details'),
355
-            EED_Event_Single::EVENT_DETAILS_PRIORITY
356
-        );
357
-        remove_filter(
358
-            'the_content',
359
-            array('EED_Event_Single', 'event_datetimes'),
360
-            EED_Event_Single::EVENT_DATETIMES_PRIORITY
361
-        );
362
-        remove_filter(
363
-            'the_content',
364
-            array('EED_Event_Single', 'event_tickets'),
365
-            EED_Event_Single::EVENT_TICKETS_PRIORITY
366
-        );
367
-        remove_filter(
368
-            'the_content',
369
-            array('EED_Event_Single', 'event_venues'),
370
-            EED_Event_Single::EVENT_VENUES_PRIORITY
371
-        );
372
-        do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_remove_filters');
373
-        // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
374
-        return $content;
375
-    }
376
-
377
-
378
-    /**
379
-     * event_datetimes - adds datetimes ABOVE content
380
-     *
381
-     * @param        string $content
382
-     * @return        string
383
-     */
384
-    public static function event_datetimes($content)
385
-    {
386
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
387
-    }
388
-
389
-
390
-    /**
391
-     * event_tickets - adds tickets ABOVE content (which includes datetimes)
392
-     *
393
-     * @param        string $content
394
-     * @return        string
395
-     */
396
-    public static function event_tickets($content)
397
-    {
398
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
399
-    }
400
-
401
-
402
-    /**
403
-     * event_venues
404
-     *
405
-     * @param    string $content
406
-     * @return    string
407
-     */
408
-    public static function event_venue($content)
409
-    {
410
-        return EED_Event_Single::event_venues($content);
411
-    }
412
-
413
-
414
-    /**
415
-     * event_venues - adds venues BELOW content
416
-     *
417
-     * @param        string $content
418
-     * @return        string
419
-     */
420
-    public static function event_venues($content)
421
-    {
422
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
423
-    }
424
-
425
-
426
-    /**
427
-     * loop_end
428
-     *
429
-     * @param        array $wp_query_array an array containing the WP_Query object
430
-     * @return        void
431
-     */
432
-    public static function loop_end($wp_query_array)
433
-    {
434
-        global $post;
435
-        do_action('AHEE_event_details_after_post', $post, $wp_query_array);
436
-    }
437
-
438
-
439
-    /**
440
-     * wp_enqueue_scripts
441
-     *
442
-     * @return    void
443
-     */
444
-    public function wp_enqueue_scripts()
445
-    {
446
-        // get some style
447
-        if (
448
-            apply_filters('FHEE_enable_default_espresso_css', true)
449
-            && apply_filters('FHEE__EED_Event_Single__wp_enqueue_scripts__enable_css', true)
450
-        ) {
451
-            // first check uploads folder
452
-            if (is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
453
-                wp_register_style(
454
-                    $this->theme,
455
-                    get_stylesheet_directory_uri() . $this->theme . '/style.css',
456
-                    array('dashicons', 'espresso_default')
457
-                );
458
-            } else {
459
-                wp_register_style(
460
-                    $this->theme,
461
-                    EE_TEMPLATES_URL . $this->theme . '/style.css',
462
-                    array('dashicons', 'espresso_default')
463
-                );
464
-            }
465
-            wp_enqueue_script($this->theme);
466
-            if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
467
-                add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
468
-            }
469
-        }
470
-    }
471
-
472
-
473
-    /**
474
-     * display_venue
475
-     *
476
-     * @return    bool
477
-     */
478
-    public static function display_venue()
479
-    {
480
-        /** @type EE_Event_Single_Config $config */
481
-        $config = EED_Event_Single::instance()->config();
482
-        $display_venue = $config->display_venue === null ? true : $config->display_venue;
483
-        $venue_name = EEH_Venue_View::venue_name();
484
-        return $display_venue && ! empty($venue_name);
485
-    }
17
+	const EVENT_DETAILS_PRIORITY = 100;
18
+	const EVENT_DATETIMES_PRIORITY = 110;
19
+	const EVENT_TICKETS_PRIORITY = 120;
20
+	const EVENT_VENUES_PRIORITY = 130;
21
+
22
+	/**
23
+	 * @type bool $using_get_the_excerpt
24
+	 */
25
+	protected static $using_get_the_excerpt = false;
26
+
27
+
28
+	/**
29
+	 * @type EE_Template_Part_Manager $template_parts
30
+	 */
31
+	protected $template_parts;
32
+
33
+
34
+	/**
35
+	 * @return EED_Module|EED_Event_Single
36
+	 */
37
+	public static function instance()
38
+	{
39
+		return parent::get_instance(__CLASS__);
40
+	}
41
+
42
+
43
+	/**
44
+	 * set_hooks - for hooking into EE Core, other modules, etc
45
+	 *
46
+	 * @return void
47
+	 * @throws InvalidArgumentException
48
+	 * @throws InvalidDataTypeException
49
+	 * @throws InvalidInterfaceException
50
+	 */
51
+	public static function set_hooks()
52
+	{
53
+		add_filter('FHEE_run_EE_wp', '__return_true');
54
+		add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
55
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
56
+		$custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
57
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
58
+		);
59
+		$custom_post_types = $custom_post_type_definitions->getDefinitions();
60
+		EE_Config::register_route(
61
+			$custom_post_types[EspressoPostType::EVENTS]['singular_slug'],
62
+			'Event_Single',
63
+			'run'
64
+		);
65
+	}
66
+
67
+	/**
68
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
69
+	 *
70
+	 * @return    void
71
+	 */
72
+	public static function set_hooks_admin()
73
+	{
74
+		add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
75
+	}
76
+
77
+
78
+	/**
79
+	 * set_definitions
80
+	 *
81
+	 * @static
82
+	 * @return void
83
+	 */
84
+	public static function set_definitions()
85
+	{
86
+		define('EVENT_SINGLE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
87
+		define('EVENT_SINGLE_TEMPLATES_PATH', plugin_dir_path(__FILE__) . 'templates/');
88
+	}
89
+
90
+
91
+	/**
92
+	 * set_config
93
+	 *
94
+	 * @void
95
+	 */
96
+	protected function set_config()
97
+	{
98
+		$this->set_config_section('template_settings');
99
+		$this->set_config_class('EE_Event_Single_Config');
100
+		$this->set_config_name('EED_Event_Single');
101
+	}
102
+
103
+
104
+	/**
105
+	 * initialize_template_parts
106
+	 *
107
+	 * @param EE_Config_Base|EE_Event_Single_Config $config
108
+	 * @return EE_Template_Part_Manager
109
+	 * @throws EE_Error
110
+	 */
111
+	public function initialize_template_parts(EE_Event_Single_Config $config = null)
112
+	{
113
+		/** @type EE_Event_Single_Config $config */
114
+		$config = $config instanceof EE_Event_Single_Config ? $config : $this->config();
115
+		EEH_Autoloader::register_template_part_autoloaders();
116
+		$template_parts = new EE_Template_Part_Manager();
117
+		$template_parts->add_template_part(
118
+			'tickets',
119
+			esc_html__('Ticket Selector', 'event_espresso'),
120
+			'content-espresso_events-tickets.php',
121
+			$config->display_order_tickets
122
+		);
123
+		$template_parts->add_template_part(
124
+			'datetimes',
125
+			esc_html__('Dates and Times', 'event_espresso'),
126
+			'content-espresso_events-datetimes.php',
127
+			$config->display_order_datetimes
128
+		);
129
+		$template_parts->add_template_part(
130
+			'event',
131
+			esc_html__('Event Description', 'event_espresso'),
132
+			'content-espresso_events-details.php',
133
+			$config->display_order_event
134
+		);
135
+		$template_parts->add_template_part(
136
+			'venue',
137
+			esc_html__('Venue Information', 'event_espresso'),
138
+			'content-espresso_events-venues.php',
139
+			$config->display_order_venue
140
+		);
141
+		do_action('AHEE__EED_Event_Single__initialize_template_parts', $template_parts);
142
+		return $template_parts;
143
+	}
144
+
145
+
146
+	/**
147
+	 * run - initial module setup
148
+	 *
149
+	 * @param WP $WP
150
+	 * @return    void
151
+	 */
152
+	public function run($WP)
153
+	{
154
+		// ensure valid EE_Events_Single_Config() object exists
155
+		$this->set_config();
156
+		// check what template is loaded
157
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
158
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
159
+		// load css
160
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
161
+	}
162
+
163
+
164
+	/**
165
+	 * template_include
166
+	 *
167
+	 * @param    string $template
168
+	 * @return    string
169
+	 */
170
+	public function template_include($template)
171
+	{
172
+		global $post;
173
+		/** @type EE_Event_Single_Config $config */
174
+		$config = $this->config();
175
+		if ($config->display_status_banner_single) {
176
+			add_filter('the_title', array('EED_Event_Single', 'the_title'), 100, 2);
177
+		}
178
+		// not a custom template?
179
+		if (
180
+			! post_password_required($post)
181
+			&& (
182
+				apply_filters('FHEE__EED_Event_Single__template_include__allow_custom_selected_template', false)
183
+				|| EE_Registry::instance()
184
+							  ->load_core('Front_Controller')
185
+							  ->get_selected_template() !== 'single-espresso_events.php'
186
+			)
187
+		) {
188
+			EEH_Template::load_espresso_theme_functions();
189
+			// then add extra event data via hooks
190
+			add_action('loop_start', array('EED_Event_Single', 'loop_start'));
191
+			add_filter('get_the_excerpt', array('EED_Event_Single', 'get_the_excerpt'), 1, 1);
192
+			add_filter(
193
+				'the_content',
194
+				array('EED_Event_Single', 'event_details'),
195
+				EED_Event_Single::EVENT_DETAILS_PRIORITY
196
+			);
197
+			add_action('loop_end', array('EED_Event_Single', 'loop_end'));
198
+			// don't display entry meta because the existing theme will take car of that
199
+			add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
200
+		}
201
+		return $template;
202
+	}
203
+
204
+
205
+	/**
206
+	 * loop_start
207
+	 *
208
+	 * @param    array $wp_query_array an array containing the WP_Query object
209
+	 * @return    void
210
+	 */
211
+	public static function loop_start($wp_query_array)
212
+	{
213
+		global $post;
214
+		do_action('AHEE_event_details_before_post', $post, $wp_query_array);
215
+	}
216
+
217
+
218
+	/**
219
+	 * the_title
220
+	 *
221
+	 * @param    string $title
222
+	 * @param    int    $id
223
+	 * @return    string
224
+	 */
225
+	public static function the_title($title = '', $id = 0)
226
+	{
227
+		global $post;
228
+		return ((function_exists('wp_is_block_theme') && wp_is_block_theme()) || in_the_loop()) && $post->ID === (int) $id
229
+			? espresso_event_status_banner($post->ID) . $title
230
+			: $title;
231
+	}
232
+
233
+
234
+	/**
235
+	 * get_the_excerpt
236
+	 * kinda hacky, but if a theme is using get_the_excerpt(),
237
+	 * then we need to remove our filters on the_content()
238
+	 *
239
+	 * @param        string $excerpt
240
+	 * @return        string
241
+	 */
242
+	public static function get_the_excerpt($excerpt = '')
243
+	{
244
+		EED_Event_Single::$using_get_the_excerpt = true;
245
+		add_filter('wp_trim_excerpt', array('EED_Event_Single', 'end_get_the_excerpt'), 999, 1);
246
+		return $excerpt;
247
+	}
248
+
249
+
250
+	/**
251
+	 * end_get_the_excerpt
252
+	 *
253
+	 * @param  string $text
254
+	 * @return string
255
+	 */
256
+	public static function end_get_the_excerpt($text = '')
257
+	{
258
+		EED_Event_Single::$using_get_the_excerpt = false;
259
+		return $text;
260
+	}
261
+
262
+
263
+	/**
264
+	 * event_details
265
+	 *
266
+	 * @param    string $content
267
+	 * @return    string
268
+	 */
269
+	public static function event_details($content)
270
+	{
271
+		global $post;
272
+		static $current_post_ID = 0;
273
+		if (
274
+			$current_post_ID !== $post->ID
275
+			&& $post->post_type === EspressoPostType::EVENTS
276
+			&& ! EED_Event_Single::$using_get_the_excerpt
277
+			&& ! post_password_required()
278
+		) {
279
+			// Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
280
+			// Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
281
+			// BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
282
+			// We want to allow those plugins to still do their thing and have access to our content, but depending on
283
+			// how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
284
+			// so the following allows this filter to be applied multiple times, but only once for real
285
+			$current_post_ID = did_action('loop_start') ? $post->ID : 0;
286
+			if (EE_Registry::instance()->CFG->template_settings->EED_Event_Single->use_sortable_display_order) {
287
+				// we need to first remove this callback from being applied to the_content()
288
+				// (otherwise it will recurse and blow up the interweb)
289
+				remove_filter(
290
+					'the_content',
291
+					array('EED_Event_Single', 'event_details'),
292
+					EED_Event_Single::EVENT_DETAILS_PRIORITY
293
+				);
294
+				EED_Event_Single::instance()->template_parts = EED_Event_Single::instance()->initialize_template_parts(
295
+				);
296
+				$content = EEH_Template::locate_template('content-espresso_events-details.php');
297
+				$content = EED_Event_Single::instance()->template_parts->apply_template_part_filters($content);
298
+				add_filter(
299
+					'the_content',
300
+					array('EED_Event_Single', 'event_details'),
301
+					EED_Event_Single::EVENT_DETAILS_PRIORITY
302
+				);
303
+			} else {
304
+				$content = EED_Event_Single::use_filterable_display_order();
305
+			}
306
+		}
307
+		return $content;
308
+	}
309
+
310
+
311
+	/**
312
+	 * use_filterable_display_order
313
+	 *
314
+	 * @return string
315
+	 */
316
+	protected static function use_filterable_display_order()
317
+	{
318
+		// since the 'content-espresso_events-details.php' template might be used directly from within a theme,
319
+		// it uses the_content() for displaying the $post->post_content
320
+		// so in order to load a template that uses the_content()
321
+		// from within a callback being used to filter the_content(),
322
+		// we need to first remove this callback from being applied to the_content()
323
+		// (otherwise it will recurse and blow up the interweb)
324
+		remove_filter(
325
+			'the_content',
326
+			array('EED_Event_Single', 'event_details'),
327
+			EED_Event_Single::EVENT_DETAILS_PRIORITY
328
+		);
329
+		// now add additional content
330
+		add_filter(
331
+			'the_content',
332
+			array('EED_Event_Single', 'event_datetimes'),
333
+			EED_Event_Single::EVENT_DATETIMES_PRIORITY,
334
+			1
335
+		);
336
+		add_filter(
337
+			'the_content',
338
+			array('EED_Event_Single', 'event_tickets'),
339
+			EED_Event_Single::EVENT_TICKETS_PRIORITY,
340
+			1
341
+		);
342
+		add_filter(
343
+			'the_content',
344
+			array('EED_Event_Single', 'event_venues'),
345
+			EED_Event_Single::EVENT_VENUES_PRIORITY,
346
+			1
347
+		);
348
+		do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_add_filters');
349
+		// now load our template
350
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
351
+		// now add our filter back in, plus some others
352
+		add_filter(
353
+			'the_content',
354
+			array('EED_Event_Single', 'event_details'),
355
+			EED_Event_Single::EVENT_DETAILS_PRIORITY
356
+		);
357
+		remove_filter(
358
+			'the_content',
359
+			array('EED_Event_Single', 'event_datetimes'),
360
+			EED_Event_Single::EVENT_DATETIMES_PRIORITY
361
+		);
362
+		remove_filter(
363
+			'the_content',
364
+			array('EED_Event_Single', 'event_tickets'),
365
+			EED_Event_Single::EVENT_TICKETS_PRIORITY
366
+		);
367
+		remove_filter(
368
+			'the_content',
369
+			array('EED_Event_Single', 'event_venues'),
370
+			EED_Event_Single::EVENT_VENUES_PRIORITY
371
+		);
372
+		do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_remove_filters');
373
+		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
374
+		return $content;
375
+	}
376
+
377
+
378
+	/**
379
+	 * event_datetimes - adds datetimes ABOVE content
380
+	 *
381
+	 * @param        string $content
382
+	 * @return        string
383
+	 */
384
+	public static function event_datetimes($content)
385
+	{
386
+		return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
387
+	}
388
+
389
+
390
+	/**
391
+	 * event_tickets - adds tickets ABOVE content (which includes datetimes)
392
+	 *
393
+	 * @param        string $content
394
+	 * @return        string
395
+	 */
396
+	public static function event_tickets($content)
397
+	{
398
+		return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
399
+	}
400
+
401
+
402
+	/**
403
+	 * event_venues
404
+	 *
405
+	 * @param    string $content
406
+	 * @return    string
407
+	 */
408
+	public static function event_venue($content)
409
+	{
410
+		return EED_Event_Single::event_venues($content);
411
+	}
412
+
413
+
414
+	/**
415
+	 * event_venues - adds venues BELOW content
416
+	 *
417
+	 * @param        string $content
418
+	 * @return        string
419
+	 */
420
+	public static function event_venues($content)
421
+	{
422
+		return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
423
+	}
424
+
425
+
426
+	/**
427
+	 * loop_end
428
+	 *
429
+	 * @param        array $wp_query_array an array containing the WP_Query object
430
+	 * @return        void
431
+	 */
432
+	public static function loop_end($wp_query_array)
433
+	{
434
+		global $post;
435
+		do_action('AHEE_event_details_after_post', $post, $wp_query_array);
436
+	}
437
+
438
+
439
+	/**
440
+	 * wp_enqueue_scripts
441
+	 *
442
+	 * @return    void
443
+	 */
444
+	public function wp_enqueue_scripts()
445
+	{
446
+		// get some style
447
+		if (
448
+			apply_filters('FHEE_enable_default_espresso_css', true)
449
+			&& apply_filters('FHEE__EED_Event_Single__wp_enqueue_scripts__enable_css', true)
450
+		) {
451
+			// first check uploads folder
452
+			if (is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
453
+				wp_register_style(
454
+					$this->theme,
455
+					get_stylesheet_directory_uri() . $this->theme . '/style.css',
456
+					array('dashicons', 'espresso_default')
457
+				);
458
+			} else {
459
+				wp_register_style(
460
+					$this->theme,
461
+					EE_TEMPLATES_URL . $this->theme . '/style.css',
462
+					array('dashicons', 'espresso_default')
463
+				);
464
+			}
465
+			wp_enqueue_script($this->theme);
466
+			if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
467
+				add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
468
+			}
469
+		}
470
+	}
471
+
472
+
473
+	/**
474
+	 * display_venue
475
+	 *
476
+	 * @return    bool
477
+	 */
478
+	public static function display_venue()
479
+	{
480
+		/** @type EE_Event_Single_Config $config */
481
+		$config = EED_Event_Single::instance()->config();
482
+		$display_venue = $config->display_venue === null ? true : $config->display_venue;
483
+		$venue_name = EEH_Venue_View::venue_name();
484
+		return $display_venue && ! empty($venue_name);
485
+	}
486 486
 }
487 487
 
488 488
 
@@ -494,5 +494,5 @@  discard block
 block discarded – undo
494 494
  */
495 495
 function espresso_display_venue_in_event_details()
496 496
 {
497
-    return EED_Event_Single::display_venue();
497
+	return EED_Event_Single::display_venue();
498 498
 }
Please login to merge, or discard this patch.
modules/feeds/EED_Feeds.module.php 2 patches
Indentation   +207 added lines, -207 removed lines patch added patch discarded remove patch
@@ -11,211 +11,211 @@
 block discarded – undo
11 11
  */
12 12
 class EED_Feeds extends EED_Module
13 13
 {
14
-    /**
15
-     * @return EED_Feeds
16
-     * @throws EE_Error
17
-     * @throws ReflectionException
18
-     */
19
-    public static function instance()
20
-    {
21
-        return parent::get_instance(__CLASS__);
22
-    }
23
-
24
-
25
-    /**
26
-     *    set_hooks - for hooking into EE Core, other modules, etc
27
-     *
28
-     * @return    void
29
-     */
30
-    public static function set_hooks()
31
-    {
32
-        add_action('parse_request', ['EED_Feeds', 'parse_request']);
33
-        add_filter('default_feed', ['EED_Feeds', 'default_feed']);
34
-        add_filter('comment_feed_join', ['EED_Feeds', 'comment_feed_join'], 10, 2);
35
-        add_filter('comment_feed_where', ['EED_Feeds', 'comment_feed_where'], 10, 2);
36
-    }
37
-
38
-
39
-    /**
40
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
41
-     *
42
-     * @return    void
43
-     */
44
-    public static function set_hooks_admin()
45
-    {
46
-    }
47
-
48
-
49
-    /**
50
-     *    run - initial module setup
51
-     *
52
-     * @return    void
53
-     */
54
-    public function run($WP)
55
-    {
56
-    }
57
-
58
-
59
-    /**
60
-     *    default_feed
61
-     *
62
-     * @param type    rss2, atom, rss, rdf, rssjs
63
-     * @return    string
64
-     */
65
-    public static function default_feed($type = 'rss2')
66
-    {
67
-        // rss2, atom, rss, rdf, rssjs
68
-        $type = 'rss2';
69
-        return $type;
70
-    }
71
-
72
-
73
-    /**
74
-     *    parse_request
75
-     *
76
-     * @return    void
77
-     */
78
-    public static function parse_request()
79
-    {
80
-        $request = self::getRequest();
81
-        if (! $request->requestParamIsSet('post_type')) {
82
-            return;
83
-        }
84
-        // define path to templates
85
-        define('RSS_FEEDS_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
86
-        // what kinda post_type are we dealing with ?
87
-        switch ($request->getRequestParam('post_type')) {
88
-            case EspressoPostType::EVENTS:
89
-                // for rss2, atom, rss, rdf
90
-                add_filter('the_excerpt_rss', ['EED_Feeds', 'the_event_feed']);
91
-                add_filter('the_content_feed', ['EED_Feeds', 'the_event_feed']);
92
-                // for json ( also uses the above filter )
93
-                add_filter('rssjs_feed_item', ['EED_Feeds', 'the_event_rssjs_feed']);
94
-                break;
95
-            case EspressoPostType::VENUES:
96
-                // for rss2, atom, rss, rdf
97
-                add_filter('the_excerpt_rss', ['EED_Feeds', 'the_venue_feed']);
98
-                add_filter('the_content_feed', ['EED_Feeds', 'the_venue_feed']);
99
-                // for json ( also uses the above filter )
100
-                add_filter('rssjs_feed_item', ['EED_Feeds', 'the_venue_rssjs_feed']);
101
-                break;
102
-        }
103
-    }
104
-
105
-
106
-    /**
107
-     *    comment_feed_join - EVEN THOUGH... our espresso_attendees custom post type is set to NOT PUBLIC
108
-     *    WordPress thought it would be a good idea to display the comments for them in the RSS feeds... we think NOT
109
-     *    so this little snippet of SQL taps into the comment feed query and removes comments for the
110
-     *    espresso_attendees post_type
111
-     *
112
-     * @param string $SQL the JOIN clause for the comment feed query
113
-     * @return string
114
-     */
115
-    public static function comment_feed_join($SQL)
116
-    {
117
-        global $wpdb;
118
-        // check for wp_posts table in JOIN clause
119
-        if (strpos($SQL, $wpdb->posts) !== false) {
120
-            add_filter('EED_Feeds__comment_feed_where__espresso_attendees', '__return_true');
121
-        }
122
-        return $SQL;
123
-    }
124
-
125
-
126
-    /**
127
-     *    comment_feed_where - EVEN THOUGH... our espresso_attendees custom post type is set to NOT PUBLIC
128
-     *    WordPress thought it would be a good idea to display the comments for them in the RSS feeds... we think NOT
129
-     *    so this little snippet of SQL taps into the comment feed query and removes comments for the
130
-     *    espresso_attendees post_type
131
-     *
132
-     * @param string $SQL the WHERE clause for the comment feed query
133
-     * @return string
134
-     */
135
-    public static function comment_feed_where($SQL)
136
-    {
137
-        global $wp_query, $wpdb;
138
-        if ($wp_query->is_comment_feed && apply_filters('EED_Feeds__comment_feed_where__espresso_attendees', false)) {
139
-            $SQL .= " AND $wpdb->posts.post_type != " . EspressoPostType::ATTENDEES;
140
-        }
141
-        return $SQL;
142
-    }
143
-
144
-
145
-    /**
146
-     *    the_event_feed
147
-     *
148
-     * @param string $content
149
-     * @return string
150
-     */
151
-    public static function the_event_feed($content)
152
-    {
153
-        if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH . 'espresso_events_feed.template.php')) {
154
-            global $post;
155
-            $template_args = [
156
-                'EVT_ID'            => $post->ID,
157
-                'event_description' => get_option('rss_use_excerpt') ? $post->post_excerpt : $post->post_content,
158
-            ];
159
-            $content       = EEH_Template::display_template(
160
-                RSS_FEEDS_TEMPLATES_PATH . 'espresso_events_feed.template.php',
161
-                $template_args,
162
-                true
163
-            );
164
-        }
165
-        return $content;
166
-    }
167
-
168
-
169
-    /**
170
-     *    the_event_rssjs_feed
171
-     *
172
-     * @param object $item
173
-     * @return object
174
-     */
175
-    public static function the_event_rssjs_feed($item)
176
-    {
177
-        if (is_feed() && isset($item->description)) {
178
-            $item->description = EED_Feeds::the_event_feed($item->description);
179
-        }
180
-        return $item;
181
-    }
182
-
183
-
184
-    /**
185
-     *    the_venue_feed
186
-     *
187
-     * @param string $content
188
-     * @return string
189
-     */
190
-    public static function the_venue_feed($content)
191
-    {
192
-        if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH . 'espresso_venues_feed.template.php')) {
193
-            global $post;
194
-            $template_args = [
195
-                'VNU_ID'            => $post->ID,
196
-                'venue_description' => get_option('rss_use_excerpt') ? $post->post_excerpt : $post->post_content,
197
-            ];
198
-            $content       = EEH_Template::display_template(
199
-                RSS_FEEDS_TEMPLATES_PATH . 'espresso_venues_feed.template.php',
200
-                $template_args,
201
-                true
202
-            );
203
-        }
204
-        return $content;
205
-    }
206
-
207
-
208
-    /**
209
-     *    the_venue_rssjs_feed
210
-     *
211
-     * @param object $item
212
-     * @return object
213
-     */
214
-    public static function the_venue_rssjs_feed($item)
215
-    {
216
-        if (is_feed() && isset($item->description)) {
217
-            $item->description = EED_Feeds::the_venue_feed($item->description);
218
-        }
219
-        return $item;
220
-    }
14
+	/**
15
+	 * @return EED_Feeds
16
+	 * @throws EE_Error
17
+	 * @throws ReflectionException
18
+	 */
19
+	public static function instance()
20
+	{
21
+		return parent::get_instance(__CLASS__);
22
+	}
23
+
24
+
25
+	/**
26
+	 *    set_hooks - for hooking into EE Core, other modules, etc
27
+	 *
28
+	 * @return    void
29
+	 */
30
+	public static function set_hooks()
31
+	{
32
+		add_action('parse_request', ['EED_Feeds', 'parse_request']);
33
+		add_filter('default_feed', ['EED_Feeds', 'default_feed']);
34
+		add_filter('comment_feed_join', ['EED_Feeds', 'comment_feed_join'], 10, 2);
35
+		add_filter('comment_feed_where', ['EED_Feeds', 'comment_feed_where'], 10, 2);
36
+	}
37
+
38
+
39
+	/**
40
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
41
+	 *
42
+	 * @return    void
43
+	 */
44
+	public static function set_hooks_admin()
45
+	{
46
+	}
47
+
48
+
49
+	/**
50
+	 *    run - initial module setup
51
+	 *
52
+	 * @return    void
53
+	 */
54
+	public function run($WP)
55
+	{
56
+	}
57
+
58
+
59
+	/**
60
+	 *    default_feed
61
+	 *
62
+	 * @param type    rss2, atom, rss, rdf, rssjs
63
+	 * @return    string
64
+	 */
65
+	public static function default_feed($type = 'rss2')
66
+	{
67
+		// rss2, atom, rss, rdf, rssjs
68
+		$type = 'rss2';
69
+		return $type;
70
+	}
71
+
72
+
73
+	/**
74
+	 *    parse_request
75
+	 *
76
+	 * @return    void
77
+	 */
78
+	public static function parse_request()
79
+	{
80
+		$request = self::getRequest();
81
+		if (! $request->requestParamIsSet('post_type')) {
82
+			return;
83
+		}
84
+		// define path to templates
85
+		define('RSS_FEEDS_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
86
+		// what kinda post_type are we dealing with ?
87
+		switch ($request->getRequestParam('post_type')) {
88
+			case EspressoPostType::EVENTS:
89
+				// for rss2, atom, rss, rdf
90
+				add_filter('the_excerpt_rss', ['EED_Feeds', 'the_event_feed']);
91
+				add_filter('the_content_feed', ['EED_Feeds', 'the_event_feed']);
92
+				// for json ( also uses the above filter )
93
+				add_filter('rssjs_feed_item', ['EED_Feeds', 'the_event_rssjs_feed']);
94
+				break;
95
+			case EspressoPostType::VENUES:
96
+				// for rss2, atom, rss, rdf
97
+				add_filter('the_excerpt_rss', ['EED_Feeds', 'the_venue_feed']);
98
+				add_filter('the_content_feed', ['EED_Feeds', 'the_venue_feed']);
99
+				// for json ( also uses the above filter )
100
+				add_filter('rssjs_feed_item', ['EED_Feeds', 'the_venue_rssjs_feed']);
101
+				break;
102
+		}
103
+	}
104
+
105
+
106
+	/**
107
+	 *    comment_feed_join - EVEN THOUGH... our espresso_attendees custom post type is set to NOT PUBLIC
108
+	 *    WordPress thought it would be a good idea to display the comments for them in the RSS feeds... we think NOT
109
+	 *    so this little snippet of SQL taps into the comment feed query and removes comments for the
110
+	 *    espresso_attendees post_type
111
+	 *
112
+	 * @param string $SQL the JOIN clause for the comment feed query
113
+	 * @return string
114
+	 */
115
+	public static function comment_feed_join($SQL)
116
+	{
117
+		global $wpdb;
118
+		// check for wp_posts table in JOIN clause
119
+		if (strpos($SQL, $wpdb->posts) !== false) {
120
+			add_filter('EED_Feeds__comment_feed_where__espresso_attendees', '__return_true');
121
+		}
122
+		return $SQL;
123
+	}
124
+
125
+
126
+	/**
127
+	 *    comment_feed_where - EVEN THOUGH... our espresso_attendees custom post type is set to NOT PUBLIC
128
+	 *    WordPress thought it would be a good idea to display the comments for them in the RSS feeds... we think NOT
129
+	 *    so this little snippet of SQL taps into the comment feed query and removes comments for the
130
+	 *    espresso_attendees post_type
131
+	 *
132
+	 * @param string $SQL the WHERE clause for the comment feed query
133
+	 * @return string
134
+	 */
135
+	public static function comment_feed_where($SQL)
136
+	{
137
+		global $wp_query, $wpdb;
138
+		if ($wp_query->is_comment_feed && apply_filters('EED_Feeds__comment_feed_where__espresso_attendees', false)) {
139
+			$SQL .= " AND $wpdb->posts.post_type != " . EspressoPostType::ATTENDEES;
140
+		}
141
+		return $SQL;
142
+	}
143
+
144
+
145
+	/**
146
+	 *    the_event_feed
147
+	 *
148
+	 * @param string $content
149
+	 * @return string
150
+	 */
151
+	public static function the_event_feed($content)
152
+	{
153
+		if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH . 'espresso_events_feed.template.php')) {
154
+			global $post;
155
+			$template_args = [
156
+				'EVT_ID'            => $post->ID,
157
+				'event_description' => get_option('rss_use_excerpt') ? $post->post_excerpt : $post->post_content,
158
+			];
159
+			$content       = EEH_Template::display_template(
160
+				RSS_FEEDS_TEMPLATES_PATH . 'espresso_events_feed.template.php',
161
+				$template_args,
162
+				true
163
+			);
164
+		}
165
+		return $content;
166
+	}
167
+
168
+
169
+	/**
170
+	 *    the_event_rssjs_feed
171
+	 *
172
+	 * @param object $item
173
+	 * @return object
174
+	 */
175
+	public static function the_event_rssjs_feed($item)
176
+	{
177
+		if (is_feed() && isset($item->description)) {
178
+			$item->description = EED_Feeds::the_event_feed($item->description);
179
+		}
180
+		return $item;
181
+	}
182
+
183
+
184
+	/**
185
+	 *    the_venue_feed
186
+	 *
187
+	 * @param string $content
188
+	 * @return string
189
+	 */
190
+	public static function the_venue_feed($content)
191
+	{
192
+		if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH . 'espresso_venues_feed.template.php')) {
193
+			global $post;
194
+			$template_args = [
195
+				'VNU_ID'            => $post->ID,
196
+				'venue_description' => get_option('rss_use_excerpt') ? $post->post_excerpt : $post->post_content,
197
+			];
198
+			$content       = EEH_Template::display_template(
199
+				RSS_FEEDS_TEMPLATES_PATH . 'espresso_venues_feed.template.php',
200
+				$template_args,
201
+				true
202
+			);
203
+		}
204
+		return $content;
205
+	}
206
+
207
+
208
+	/**
209
+	 *    the_venue_rssjs_feed
210
+	 *
211
+	 * @param object $item
212
+	 * @return object
213
+	 */
214
+	public static function the_venue_rssjs_feed($item)
215
+	{
216
+		if (is_feed() && isset($item->description)) {
217
+			$item->description = EED_Feeds::the_venue_feed($item->description);
218
+		}
219
+		return $item;
220
+	}
221 221
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -78,11 +78,11 @@  discard block
 block discarded – undo
78 78
     public static function parse_request()
79 79
     {
80 80
         $request = self::getRequest();
81
-        if (! $request->requestParamIsSet('post_type')) {
81
+        if ( ! $request->requestParamIsSet('post_type')) {
82 82
             return;
83 83
         }
84 84
         // define path to templates
85
-        define('RSS_FEEDS_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
85
+        define('RSS_FEEDS_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)).'templates/');
86 86
         // what kinda post_type are we dealing with ?
87 87
         switch ($request->getRequestParam('post_type')) {
88 88
             case EspressoPostType::EVENTS:
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
     {
137 137
         global $wp_query, $wpdb;
138 138
         if ($wp_query->is_comment_feed && apply_filters('EED_Feeds__comment_feed_where__espresso_attendees', false)) {
139
-            $SQL .= " AND $wpdb->posts.post_type != " . EspressoPostType::ATTENDEES;
139
+            $SQL .= " AND $wpdb->posts.post_type != ".EspressoPostType::ATTENDEES;
140 140
         }
141 141
         return $SQL;
142 142
     }
@@ -150,14 +150,14 @@  discard block
 block discarded – undo
150 150
      */
151 151
     public static function the_event_feed($content)
152 152
     {
153
-        if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH . 'espresso_events_feed.template.php')) {
153
+        if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH.'espresso_events_feed.template.php')) {
154 154
             global $post;
155 155
             $template_args = [
156 156
                 'EVT_ID'            => $post->ID,
157 157
                 'event_description' => get_option('rss_use_excerpt') ? $post->post_excerpt : $post->post_content,
158 158
             ];
159
-            $content       = EEH_Template::display_template(
160
-                RSS_FEEDS_TEMPLATES_PATH . 'espresso_events_feed.template.php',
159
+            $content = EEH_Template::display_template(
160
+                RSS_FEEDS_TEMPLATES_PATH.'espresso_events_feed.template.php',
161 161
                 $template_args,
162 162
                 true
163 163
             );
@@ -189,14 +189,14 @@  discard block
 block discarded – undo
189 189
      */
190 190
     public static function the_venue_feed($content)
191 191
     {
192
-        if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH . 'espresso_venues_feed.template.php')) {
192
+        if (is_feed() && is_readable(RSS_FEEDS_TEMPLATES_PATH.'espresso_venues_feed.template.php')) {
193 193
             global $post;
194 194
             $template_args = [
195 195
                 'VNU_ID'            => $post->ID,
196 196
                 'venue_description' => get_option('rss_use_excerpt') ? $post->post_excerpt : $post->post_content,
197 197
             ];
198
-            $content       = EEH_Template::display_template(
199
-                RSS_FEEDS_TEMPLATES_PATH . 'espresso_venues_feed.template.php',
198
+            $content = EEH_Template::display_template(
199
+                RSS_FEEDS_TEMPLATES_PATH.'espresso_venues_feed.template.php',
200 200
                 $template_args,
201 201
                 true
202 202
             );
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Indentation   +1714 added lines, -1714 removed lines patch added patch discarded remove patch
@@ -20,1718 +20,1718 @@
 block discarded – undo
20 20
  */
21 21
 class EED_Single_Page_Checkout extends EED_Module
22 22
 {
23
-    /**
24
-     * $_initialized - has the SPCO controller already been initialized ?
25
-     */
26
-    private static bool $_initialized = false;
27
-
28
-
29
-    /**
30
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
31
-     */
32
-    private static bool $_checkout_verified = true;
33
-
34
-    /**
35
-     * $_reg_steps_array - holds initial array of reg steps
36
-     *
37
-     * @var array $_reg_steps_array
38
-     */
39
-    private static array $_reg_steps_array = [];
40
-
41
-    /**
42
-     * $checkout - EE_Checkout object for handling the properties of the current checkout process
43
-     */
44
-    public ?EE_Checkout $checkout = null;
45
-
46
-    protected ?RequestInterface $request = null;
47
-
48
-    private bool $debug = false;    //  true    false
49
-
50
-
51
-    /**
52
-     * @return EED_Single_Page_Checkout|EED_Module
53
-     * @throws EE_Error
54
-     * @throws ReflectionException
55
-     */
56
-    public static function instance()
57
-    {
58
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
59
-        return parent::get_instance(__CLASS__);
60
-    }
61
-
62
-
63
-    /**
64
-     * @return EE_CART
65
-     */
66
-    public function cart(): EE_CART
67
-    {
68
-        return $this->checkout->cart;
69
-    }
70
-
71
-
72
-    /**
73
-     * @return RequestInterface
74
-     * @since   4.10.14.p
75
-     */
76
-    public static function getRequest(): RequestInterface
77
-    {
78
-        return LoaderFactory::getLoader()->getShared(RequestInterface::class);
79
-    }
80
-
81
-
82
-    /**
83
-     * @return EE_Transaction
84
-     */
85
-    public function transaction(): EE_Transaction
86
-    {
87
-        return $this->checkout->transaction;
88
-    }
89
-
90
-
91
-    /**
92
-     *    set_hooks - for hooking into EE Core, other modules, etc
93
-     *
94
-     * @return    void
95
-     * @throws EE_Error
96
-     */
97
-    public static function set_hooks()
98
-    {
99
-        EED_Single_Page_Checkout::set_definitions();
100
-    }
101
-
102
-
103
-    /**
104
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
-     *
106
-     * @return    void
107
-     * @throws EE_Error
108
-     */
109
-    public static function set_hooks_admin()
110
-    {
111
-        EED_Single_Page_Checkout::set_definitions();
112
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
113
-            return;
114
-        }
115
-        // going to start an output buffer in case anything gets accidentally output
116
-        // that might disrupt our JSON response
117
-        ob_start();
118
-        EED_Single_Page_Checkout::load_reg_steps();
119
-        // set ajax hooks
120
-        add_action('wp_ajax_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
121
-        add_action('wp_ajax_nopriv_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
122
-        add_action('wp_ajax_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
123
-        add_action('wp_ajax_nopriv_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
124
-        add_action('wp_ajax_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
125
-        add_action('wp_ajax_nopriv_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
126
-    }
127
-
128
-
129
-    /**
130
-     *    process ajax request
131
-     *
132
-     * @param string $ajax_action
133
-     * @throws EE_Error
134
-     * @throws ReflectionException
135
-     */
136
-    public static function process_ajax_request(string $ajax_action)
137
-    {
138
-        $request = EED_Single_Page_Checkout::getRequest();
139
-        $request->setRequestParam('action', $ajax_action);
140
-        EED_Single_Page_Checkout::instance()->_initialize();
141
-    }
142
-
143
-
144
-    /**
145
-     * ajax display registration step
146
-     *
147
-     * @throws EE_Error
148
-     * @throws ReflectionException
149
-     */
150
-    public static function display_reg_step()
151
-    {
152
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
153
-    }
154
-
155
-
156
-    /**
157
-     * ajax process registration step
158
-     *
159
-     * @throws EE_Error
160
-     * @throws ReflectionException
161
-     */
162
-    public static function process_reg_step()
163
-    {
164
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
165
-    }
166
-
167
-
168
-    /**
169
-     * ajax process registration step
170
-     *
171
-     * @throws EE_Error
172
-     * @throws ReflectionException
173
-     */
174
-    public static function update_reg_step()
175
-    {
176
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
177
-    }
178
-
179
-
180
-    /**
181
-     * update_checkout
182
-     *
183
-     * @return void
184
-     * @throws ReflectionException
185
-     * @throws EE_Error
186
-     */
187
-    public static function update_checkout()
188
-    {
189
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
190
-    }
191
-
192
-
193
-    /**
194
-     *    set_definitions
195
-     *
196
-     * @return    void
197
-     * @throws EE_Error
198
-     */
199
-    public static function set_definitions()
200
-    {
201
-        if (defined('SPCO_BASE_PATH')) {
202
-            return;
203
-        }
204
-        define(
205
-            'SPCO_BASE_PATH',
206
-            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
207
-        );
208
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
209
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
210
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
211
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
212
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
213
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
214
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
215
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
216
-            EED_Single_Page_Checkout::getRegistrationExpirationNotice();
217
-    }
218
-
219
-
220
-    /**
221
-     * load_reg_steps
222
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
223
-     *
224
-     * @throws EE_Error
225
-     */
226
-    public static function load_reg_steps()
227
-    {
228
-        static $reg_steps_loaded = false;
229
-        if ($reg_steps_loaded) {
230
-            return;
231
-        }
232
-        // filter list of reg_steps
233
-        $reg_steps_to_load = (array) apply_filters(
234
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
235
-            EED_Single_Page_Checkout::get_reg_steps()
236
-        );
237
-        // sort by key (order)
238
-        ksort($reg_steps_to_load);
239
-        // loop through folders
240
-        foreach ($reg_steps_to_load as $order => $reg_step) {
241
-            // we need a
242
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
243
-                // copy over to the reg_steps_array
244
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
245
-                // register custom key route for each reg step
246
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
247
-                EE_Config::register_route(
248
-                    $reg_step['slug'],
249
-                    'EED_Single_Page_Checkout',
250
-                    'run',
251
-                    'step'
252
-                );
253
-                // add AJAX or other hooks
254
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
255
-                    // setup autoloaders if necessary
256
-                    if (! class_exists($reg_step['class_name'])) {
257
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
258
-                            $reg_step['file_path'],
259
-                            true
260
-                        );
261
-                    }
262
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
263
-                        call_user_func([$reg_step['class_name'], 'set_hooks']);
264
-                    }
265
-                }
266
-            }
267
-        }
268
-        $reg_steps_loaded = true;
269
-    }
270
-
271
-
272
-    /**
273
-     *    get_reg_steps
274
-     *
275
-     * @return    array
276
-     */
277
-    public static function get_reg_steps(): array
278
-    {
279
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
280
-        if (empty($reg_steps)) {
281
-            $reg_steps = [
282
-                10  => [
283
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
284
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
285
-                    'slug'       => 'attendee_information',
286
-                    'has_hooks'  => false,
287
-                ],
288
-                30  => [
289
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
290
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
291
-                    'slug'       => 'payment_options',
292
-                    'has_hooks'  => true,
293
-                ],
294
-                999 => [
295
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
296
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
297
-                    'slug'       => 'finalize_registration',
298
-                    'has_hooks'  => false,
299
-                ],
300
-            ];
301
-        }
302
-        return $reg_steps;
303
-    }
304
-
305
-
306
-    /**
307
-     * @return array|string
308
-     * @throws EE_Error
309
-     * @throws ReflectionException
310
-     */
311
-    public static function registration_checkout_for_admin()
312
-    {
313
-        $request = EED_Single_Page_Checkout::getRequest();
314
-        $request->setRequestParam('step', 'attendee_information');
315
-        $request->setRequestParam('action', 'display_spco_reg_step');
316
-        $request->setRequestParam('process_form_submission', false);
317
-        EED_Single_Page_Checkout::instance()->_initialize();
318
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
319
-        return EED_Single_Page_Checkout::getResponse()->getOutput();
320
-    }
321
-
322
-
323
-    /**
324
-     * @return EE_Transaction|null
325
-     * @throws EE_Error
326
-     * @throws ReflectionException
327
-     */
328
-    public static function process_registration_from_admin(): ?EE_Transaction
329
-    {
330
-        $request = EED_Single_Page_Checkout::getRequest();
331
-        $request->setRequestParam('step', 'attendee_information');
332
-        $request->setRequestParam('action', 'process_reg_step');
333
-        $request->setRequestParam('process_form_submission', true);
334
-        EED_Single_Page_Checkout::instance()->_initialize();
335
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
336
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
337
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
338
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
339
-                if ($final_reg_step->process_reg_step()) {
340
-                    $final_reg_step->set_completed();
341
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
342
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
343
-                }
344
-            }
345
-        }
346
-        return null;
347
-    }
348
-
349
-
350
-    /**
351
-     *    run
352
-     *
353
-     * @param WP_Query|null $WP_Query
354
-     * @return    void
355
-     */
356
-    public function run($WP_Query)
357
-    {
358
-        if (
359
-            $WP_Query instanceof WP_Query
360
-            && $WP_Query->is_main_query()
361
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
362
-            && $this->_is_reg_checkout()
363
-        ) {
364
-            $this->_initialize();
365
-        }
366
-    }
367
-
368
-
369
-    /**
370
-     * determines whether current url matches reg page url
371
-     *
372
-     * @return bool
373
-     */
374
-    protected function _is_reg_checkout(): bool
375
-    {
376
-        // get current permalink for reg page without any extra query args
377
-        $reg_page_url = get_permalink(EE_Config::instance()->core->reg_page_id);
378
-        // get request URI for current request, but without the scheme or host
379
-        $current_request_uri = EEH_URL::filter_input_server_url();
380
-        $current_request_uri = html_entity_decode($current_request_uri);
381
-        // get array of query args from the current request URI
382
-        $query_args = EEH_URL::get_query_string($current_request_uri);
383
-        // grab page id if it is set
384
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
385
-        // and remove the page id from the query args (we will re-add it later)
386
-        unset($query_args['page_id']);
387
-        // now strip all query args from current request URI
388
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
389
-        // and re-add the page id if it was set
390
-        if ($page_id) {
391
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
392
-        }
393
-        // remove slashes and ?
394
-        $current_request_uri = trim($current_request_uri, '?/');
395
-        // is current request URI part of the known full reg page URL ?
396
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
397
-    }
398
-
399
-
400
-    /**
401
-     * @param WP_Query $wp_query
402
-     * @return    void
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    public static function init(WP_Query $wp_query)
407
-    {
408
-        EED_Single_Page_Checkout::instance()->run($wp_query);
409
-    }
410
-
411
-
412
-    /**
413
-     * @return void
414
-     */
415
-    private function _initialize()
416
-    {
417
-        // ensure SPCO doesn't run twice
418
-        if (EED_Single_Page_Checkout::$_initialized) {
419
-            return;
420
-        }
421
-        try {
422
-            $this->request = EED_Single_Page_Checkout::getRequest();
423
-            EED_Single_Page_Checkout::load_reg_steps();
424
-            $this->_verify_session();
425
-            // set up the EE_Checkout object
426
-            $this->checkout = $this->_initialize_checkout();
427
-            // filter checkout
428
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
429
-            // get the $_GET
430
-            $this->_get_request_vars();
431
-            if ($this->_block_bots()) {
432
-                return;
433
-            }
434
-            // filter continue_reg
435
-            $this->checkout->continue_reg = apply_filters(
436
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
437
-                true,
438
-                $this->checkout
439
-            );
440
-            // load the reg steps array
441
-            if (! $this->_load_and_instantiate_reg_steps()) {
442
-                EED_Single_Page_Checkout::$_initialized = true;
443
-                return;
444
-            }
445
-            // set the current step
446
-            $this->checkout->set_current_step($this->checkout->step);
447
-            // and the next step
448
-            $this->checkout->set_next_step();
449
-            // verify that everything has been set up correctly
450
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
451
-                EED_Single_Page_Checkout::$_initialized = true;
452
-                return;
453
-            }
454
-            do_action('AHEE__Single_Page_Checkout___initialize__after_final_verifications', $this->checkout);
455
-            // lock the transaction
456
-            $this->checkout->transaction->lock();
457
-            // make sure all of our cached objects are added to their respective model entity mappers
458
-            $this->checkout->refresh_all_entities();
459
-            // set amount owing
460
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
461
-            // initialize each reg step, which gives them the chance to potentially alter the process
462
-            $this->_initialize_reg_steps();
463
-            // DEBUG LOG
464
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
465
-            // get reg form
466
-            if (! $this->_check_form_submission()) {
467
-                EED_Single_Page_Checkout::$_initialized = true;
468
-                return;
469
-            }
470
-            // checkout the action!!!
471
-            $this->_process_form_action();
472
-            // add some style and make it dance
473
-            $this->add_styles_and_scripts($this);
474
-            // kk... SPCO has successfully run
475
-            EED_Single_Page_Checkout::$_initialized = true;
476
-            // set no cache headers and constants
477
-            EE_System::do_not_cache();
478
-            // add anchor
479
-            add_action('loop_start', [$this, 'set_checkout_anchor'], 1);
480
-            // remove transaction lock
481
-            add_action('shutdown', [$this, 'unlock_transaction'], 1);
482
-        } catch (Exception $e) {
483
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
484
-        }
485
-    }
486
-
487
-
488
-    /**
489
-     * checks that the session is valid and not expired
490
-     *
491
-     * @throws EE_Error
492
-     * @throws ReflectionException
493
-     */
494
-    private function _verify_session()
495
-    {
496
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
497
-            throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
498
-        }
499
-        $clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
500
-        // is session still valid ?
501
-        if (
502
-            $clear_session_requested
503
-            || (
504
-                EE_Registry::instance()->SSN->expired()
505
-                && $this->request->getRequestParam('e_reg_url_link') === ''
506
-            )
507
-        ) {
508
-            $this->checkout = new EE_Checkout();
509
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
510
-            // EE_Registry::instance()->SSN->reset_cart();
511
-            // EE_Registry::instance()->SSN->reset_checkout();
512
-            // EE_Registry::instance()->SSN->reset_transaction();
513
-            if (! $clear_session_requested) {
514
-                EE_Error::add_attention(
515
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
516
-                    __FILE__,
517
-                    __FUNCTION__,
518
-                    __LINE__
519
-                );
520
-            }
521
-            // EE_Registry::instance()->SSN->reset_expired();
522
-        }
523
-    }
524
-
525
-
526
-    /**
527
-     * loads and instantiates EE_Checkout
528
-     *
529
-     * @return EE_Checkout
530
-     * @throws EE_Error
531
-     * @throws ReflectionException
532
-     */
533
-    private function _initialize_checkout(): EE_Checkout
534
-    {
535
-        // look in session for existing checkout
536
-        /** @type EE_Checkout $checkout */
537
-        $checkout = EE_Registry::instance()->SSN->checkout();
538
-        // verify
539
-        if (! $checkout instanceof EE_Checkout) {
540
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
541
-            $checkout = EE_Registry::instance()->load_file(
542
-                SPCO_INC_PATH,
543
-                'EE_Checkout',
544
-                'class',
545
-                [],
546
-                false
547
-            );
548
-        } else {
549
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
550
-                $this->unlock_transaction();
551
-                wp_safe_redirect($checkout->redirect_url);
552
-                exit();
553
-            }
554
-        }
555
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
556
-        // verify again
557
-        if (! $checkout instanceof EE_Checkout) {
558
-            throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
559
-        }
560
-        // reset anything that needs a clean slate for each request
561
-        $checkout->reset_for_current_request();
562
-        return $checkout;
563
-    }
564
-
565
-
566
-    /**
567
-     * @return void
568
-     */
569
-    private function _get_request_vars()
570
-    {
571
-        // make sure this request is marked as belonging to EE
572
-        /** @var CurrentPage $current_page */
573
-        $current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class);
574
-        $current_page->setEspressoPage(true);
575
-        // which step is being requested ?
576
-        $this->checkout->step = $this->request->getRequestParam('step', $this->_get_first_step());
577
-        // which step is being edited ?
578
-        $this->checkout->edit_step = $this->request->getRequestParam('edit_step');
579
-        // and what we're doing on the current step
580
-        $this->checkout->action = $this->request->getRequestParam('action', 'display_spco_reg_step');
581
-        // timestamp
582
-        $this->checkout->uts = $this->request->getRequestParam('uts', 0, 'int');
583
-        // returning to edit ?
584
-        $this->checkout->reg_url_link = $this->request->getRequestParam('e_reg_url_link');
585
-        // add reg url link to registration query params
586
-        if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
587
-            $this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
588
-        }
589
-        // or some other kind of revisit ?
590
-        $this->checkout->revisit = $this->request->getRequestParam('revisit', false, 'bool');
591
-        // and whether to generate a reg form for this request
592
-        $this->checkout->generate_reg_form = $this->request->getRequestParam('generate_reg_form', true, 'bool');
593
-        // and whether to process a reg form submission for this request
594
-        $this->checkout->process_form_submission = $this->request->getRequestParam(
595
-            'process_form_submission',
596
-            $this->checkout->action === 'process_reg_step',
597
-            'bool'
598
-        );
599
-        $this->checkout->process_form_submission = filter_var(
600
-            $this->checkout->action !== 'display_spco_reg_step'
601
-                ? $this->checkout->process_form_submission
602
-                : false,
603
-            FILTER_VALIDATE_BOOLEAN
604
-        );
605
-        $this->_display_request_vars();
606
-    }
607
-
608
-
609
-    /**
610
-     * @return void
611
-     */
612
-    protected function _display_request_vars()
613
-    {
614
-        if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
615
-            return;
616
-        }
617
-        EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
618
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
619
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
620
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
621
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
622
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
623
-        EEH_Debug_Tools::printr(
624
-            $this->checkout->generate_reg_form,
625
-            '$this->checkout->generate_reg_form',
626
-            __FILE__,
627
-            __LINE__
628
-        );
629
-        EEH_Debug_Tools::printr(
630
-            $this->checkout->process_form_submission,
631
-            '$this->checkout->process_form_submission',
632
-            __FILE__,
633
-            __LINE__
634
-        );
635
-    }
636
-
637
-
638
-    /**
639
-     * _block_bots
640
-     * checks that the incoming request has either of the following set:
641
-     *  a UTS (unix timestamp) which indicates that the request was redirected from the Ticket Selector
642
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
643
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
644
-     * then where you coming from man?
645
-     *
646
-     * @return boolean
647
-     */
648
-    private function _block_bots(): bool
649
-    {
650
-        return EED_Invalid_Checkout_Access::getInvalidCheckoutAccess()->checkoutAccessIsInvalid($this->checkout);
651
-    }
652
-
653
-
654
-    /**
655
-     *  gets slug for first step in $_reg_steps_array
656
-     *
657
-     * @return string
658
-     */
659
-    private function _get_first_step(): string
660
-    {
661
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
662
-        return $first_step['slug'] ?? 'attendee_information';
663
-    }
664
-
665
-
666
-    /**
667
-     * instantiates each reg step based on the loaded reg_steps array
668
-     *
669
-     * @return bool
670
-     * @throws EE_Error
671
-     * @throws InvalidArgumentException
672
-     * @throws InvalidDataTypeException
673
-     * @throws InvalidInterfaceException
674
-     * @throws ReflectionException
675
-     */
676
-    private function _load_and_instantiate_reg_steps(): bool
677
-    {
678
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
679
-        // have reg_steps already been instantiated ?
680
-        if (
681
-            empty($this->checkout->reg_steps)
682
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
683
-        ) {
684
-            // if not, then loop through raw reg steps array
685
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
686
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
687
-                    return false;
688
-                }
689
-            }
690
-            if (isset($this->checkout->reg_steps['registration_confirmation'])) {
691
-                // skip the registration_confirmation page ?
692
-                // just remove it from the reg steps array
693
-                $this->checkout->remove_reg_step('registration_confirmation', false);
694
-            }
695
-            // filter the array for good luck
696
-            $this->checkout->reg_steps = apply_filters(
697
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
698
-                $this->checkout->reg_steps
699
-            );
700
-            // finally re-sort based on the reg step class order properties
701
-            $this->checkout->sort_reg_steps();
702
-        } else {
703
-            foreach ($this->checkout->reg_steps as $reg_step) {
704
-                // set all current step stati to FALSE
705
-                $reg_step->set_is_current_step(false);
706
-            }
707
-        }
708
-        if (empty($this->checkout->reg_steps)) {
709
-            EE_Error::add_error(
710
-                esc_html__('No Reg Steps were loaded..', 'event_espresso'),
711
-                __FILE__,
712
-                __FUNCTION__,
713
-                __LINE__
714
-            );
715
-            return false;
716
-        }
717
-        // make reg step details available to JS
718
-        $this->checkout->set_reg_step_JSON_info();
719
-        return true;
720
-    }
721
-
722
-
723
-    /**
724
-     * @param array $reg_step
725
-     * @param int   $order
726
-     * @return bool
727
-     * @throws EE_Error
728
-     * @throws ReflectionException
729
-     */
730
-    private function _load_and_instantiate_reg_step(array $reg_step = [], int $order = 0): bool
731
-    {
732
-        // we need a file_path, class_name, and slug to add a reg step
733
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
734
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
735
-            if (
736
-                $this->checkout->reg_url_link
737
-                && $this->checkout->step !== $reg_step['slug']
738
-                && $reg_step['slug'] !== 'finalize_registration'
739
-                // normally at this point we would NOT load the reg step, but this filter can change that
740
-                && apply_filters(
741
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
742
-                    true,
743
-                    $reg_step,
744
-                    $this->checkout
745
-                )
746
-            ) {
747
-                return true;
748
-            }
749
-
750
-            // instantiate step class using file path and class name
751
-            $reg_step_obj = EE_Registry::instance()->load_file(
752
-                $reg_step['file_path'],
753
-                $reg_step['class_name'],
754
-                'class',
755
-                [$this->checkout],
756
-                false
757
-            );
758
-            // did we get the goods ?
759
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
760
-                // set reg step order based on config
761
-                $reg_step_obj->set_order($order);
762
-                // add instantiated reg step object to the master reg steps array
763
-                $this->checkout->add_reg_step($reg_step_obj);
764
-            } else {
765
-                EE_Error::add_error(
766
-                    esc_html__('The current step could not be set.', 'event_espresso'),
767
-                    __FILE__,
768
-                    __FUNCTION__,
769
-                    __LINE__
770
-                );
771
-                return false;
772
-            }
773
-        } else {
774
-            if (WP_DEBUG) {
775
-                EE_Error::add_error(
776
-                    sprintf(
777
-                        esc_html__(
778
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
779
-                            'event_espresso'
780
-                        ),
781
-                        $reg_step['file_path'] ?? '',
782
-                        $reg_step['class_name'] ?? '',
783
-                        $reg_step['slug'] ?? '',
784
-                        '<ul>',
785
-                        '<li>',
786
-                        '</li>',
787
-                        '</ul>'
788
-                    ),
789
-                    __FILE__,
790
-                    __FUNCTION__,
791
-                    __LINE__
792
-                );
793
-            }
794
-            return false;
795
-        }
796
-        return true;
797
-    }
798
-
799
-
800
-    /**
801
-     * @return bool
802
-     * @throws EE_Error
803
-     * @throws ReflectionException
804
-     */
805
-    private function _verify_transaction_and_get_registrations(): bool
806
-    {
807
-        // was there already a valid transaction in the checkout from the session ?
808
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
809
-            // get transaction from db or session
810
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
811
-                ? $this->_get_transaction_and_cart_for_previous_visit()
812
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
813
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
814
-                EE_Error::add_error(
815
-                    esc_html__(
816
-                        'Your Registration and Transaction information could not be retrieved from the db.',
817
-                        'event_espresso'
818
-                    ),
819
-                    __FILE__,
820
-                    __FUNCTION__,
821
-                    __LINE__
822
-                );
823
-                $this->checkout->transaction = EE_Transaction::new_instance();
824
-                // add some style and make it dance
825
-                $this->add_styles_and_scripts($this);
826
-                EED_Single_Page_Checkout::$_initialized = true;
827
-                return false;
828
-            }
829
-            // and the registrations for the transaction
830
-            $this->_get_registrations($this->checkout->transaction);
831
-        }
832
-        return true;
833
-    }
834
-
835
-
836
-    /**
837
-     * @return EE_Transaction|null
838
-     * @throws EE_Error
839
-     * @throws ReflectionException
840
-     */
841
-    private function _get_transaction_and_cart_for_previous_visit(): ?EE_Transaction
842
-    {
843
-        /** @var $TXN_model EEM_Transaction */
844
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
845
-        // because the reg_url_link is present in the request,
846
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
847
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
848
-        // verify transaction
849
-        if ($transaction instanceof EE_Transaction) {
850
-            // and get the cart that was used for that transaction
851
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
852
-            return $transaction;
853
-        }
854
-        EE_Error::add_error(
855
-            esc_html__(
856
-                'Your Registration and Transaction information could not be retrieved from the db.',
857
-                'event_espresso'
858
-            ),
859
-            __FILE__,
860
-            __FUNCTION__,
861
-            __LINE__
862
-        );
863
-        return null;
864
-    }
865
-
866
-
867
-    /**
868
-     * @param EE_Transaction|null $transaction
869
-     * @return EE_Cart
870
-     */
871
-    private function _get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
872
-    {
873
-        return $this->checkout->get_cart_for_transaction($transaction);
874
-    }
875
-
876
-
877
-    /**
878
-     * @param EE_Transaction|null $transaction
879
-     * @return EE_Cart
880
-     */
881
-    public function get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
882
-    {
883
-        return $this->checkout->get_cart_for_transaction($transaction);
884
-    }
885
-
886
-
887
-    /**
888
-     * generates a new EE_Transaction object and adds it to the $_transaction property.
889
-     *
890
-     * @return EE_Transaction|null
891
-     * @throws EE_Error
892
-     * @throws ReflectionException
893
-     */
894
-    private function _get_cart_for_current_session_and_setup_new_transaction(): ?EE_Transaction
895
-    {
896
-        //  if there's no transaction, then this is the FIRST visit to SPCO
897
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
898
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
899
-        // and then create a new transaction
900
-        $transaction = $this->_initialize_transaction();
901
-        // verify transaction
902
-        if ($transaction instanceof EE_Transaction) {
903
-            // and save TXN data to the cart
904
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
905
-        } else {
906
-            EE_Error::add_error(
907
-                esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
908
-                __FILE__,
909
-                __FUNCTION__,
910
-                __LINE__
911
-            );
912
-        }
913
-        return $transaction;
914
-    }
915
-
916
-
917
-    /**
918
-     * generates a new EE_Transaction object and adds it to the $_transaction property.
919
-     *
920
-     * @return EE_Transaction|null
921
-     */
922
-    private function _initialize_transaction(): ?EE_Transaction
923
-    {
924
-        try {
925
-            // ensure cart totals have been calculated
926
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
927
-            // grab the cart grand total
928
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
929
-            // create new TXN
930
-            $transaction = EE_Transaction::new_instance(
931
-                [
932
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
933
-                    'TXN_total'     => max($cart_total, 0),
934
-                    'TXN_paid'      => 0,
935
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
936
-                ]
937
-            );
938
-            // save it so that we have an ID for other objects to use
939
-            $transaction->save();
940
-            // set cron job for following up on TXNs after their session has expired
941
-            EE_Cron_Tasks::schedule_expired_transaction_check(
942
-                EE_Registry::instance()->SSN->expiration() + 1,
943
-                $transaction->ID()
944
-            );
945
-            return $transaction;
946
-        } catch (Exception $e) {
947
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
948
-        }
949
-        return null;
950
-    }
951
-
952
-
953
-    /**
954
-     * _get_registrations
955
-     *
956
-     * @param EE_Transaction $transaction
957
-     * @return void
958
-     * @throws EE_Error
959
-     * @throws ReflectionException
960
-     */
961
-    private function _get_registrations(EE_Transaction $transaction)
962
-    {
963
-        // first step: grab the registrants  { : o
964
-        $registrations                      = $transaction->registrations($this->checkout->reg_cache_where_params);
965
-        $this->checkout->total_ticket_count = count($registrations);
966
-        // verify registrations have been set
967
-        if (empty($registrations)) {
968
-            // if no cached registrations, then check the db
969
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params);
970
-            // still nothing ? well as long as this isn't a revisit
971
-            if (empty($registrations) && ! $this->checkout->revisit) {
972
-                // generate new registrations from scratch
973
-                $registrations = $this->_initialize_registrations($transaction);
974
-            }
975
-        }
976
-        // sort by their original registration order
977
-        usort($registrations, ['EED_Single_Page_Checkout', 'sort_registrations_by_REG_count']);
978
-        // then loop thru the array
979
-        foreach ($registrations as $registration) {
980
-            // verify each registration
981
-            if ($registration instanceof EE_Registration) {
982
-                // we display all attendee info for the primary registrant
983
-                if (
984
-                    $this->checkout->reg_url_link === $registration->reg_url_link()
985
-                    && $registration->is_primary_registrant()
986
-                ) {
987
-                    $this->checkout->primary_revisit = true;
988
-                    break;
989
-                }
990
-                if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
991
-                    // but hide info if it doesn't belong to you
992
-                    $transaction->clear_cache('Registration', $registration->ID());
993
-                    $this->checkout->total_ticket_count--;
994
-                }
995
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
996
-            }
997
-        }
998
-    }
999
-
1000
-
1001
-    /**
1002
-     * adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1003
-     *
1004
-     * @param EE_Transaction $transaction
1005
-     * @return array
1006
-     * @throws EE_Error
1007
-     * @throws ReflectionException
1008
-     */
1009
-    private function _initialize_registrations(EE_Transaction $transaction): array
1010
-    {
1011
-        $att_nmbr      = 0;
1012
-        $registrations = [];
1013
-        /** @type EE_Registration_Processor $registration_processor */
1014
-        $registration_processor             = EE_Registry::instance()->load_class('Registration_Processor');
1015
-        $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1016
-        // now let's add the cart items to the $transaction
1017
-        foreach ($this->checkout->cart->get_tickets() as $line_item) {
1018
-            // do the following for each ticket of this type they selected
1019
-            for ($x = 1; $x <= $line_item->quantity(); $x++) {
1020
-                $att_nmbr++;
1021
-                /** @var CreateRegistrationCommand $CreateRegistrationCommand */
1022
-                $CreateRegistrationCommand = EE_Registry::instance()->create(
1023
-                    CreateRegistrationCommand::class,
1024
-                    [
1025
-                        $transaction,
1026
-                        $line_item,
1027
-                        $att_nmbr,
1028
-                        $this->checkout->total_ticket_count,
1029
-                    ]
1030
-                );
1031
-                // override capabilities for frontend registrations
1032
-                if ($this->request->isFrontend()) {
1033
-                    $CreateRegistrationCommand->setCapCheck(
1034
-                        new PublicCapabilities('', 'create_new_registration')
1035
-                    );
1036
-                }
1037
-                $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1038
-                if (! $registration instanceof EE_Registration) {
1039
-                    throw new InvalidEntityException($registration, 'EE_Registration');
1040
-                }
1041
-                $registrations[ $registration->ID() ] = $registration;
1042
-            }
1043
-        }
1044
-        $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1045
-        return $registrations;
1046
-    }
1047
-
1048
-
1049
-    /**
1050
-     * @param EE_Registration $reg_A
1051
-     * @param EE_Registration $reg_B
1052
-     * @return int
1053
-     * @throws EE_Error
1054
-     * @throws ReflectionException
1055
-     */
1056
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B): int
1057
-    {
1058
-        // this shouldn't ever happen within the same TXN, but oh well
1059
-        if ($reg_A->count() === $reg_B->count()) {
1060
-            return 0;
1061
-        }
1062
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * just makes sure that everything is set up correctly before proceeding
1068
-     *
1069
-     * @return bool
1070
-     * @throws EE_Error
1071
-     * @throws ReflectionException
1072
-     */
1073
-    private function _final_verifications(): bool
1074
-    {
1075
-        // filter checkout
1076
-        $this->checkout = apply_filters(
1077
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1078
-            $this->checkout
1079
-        );
1080
-        // verify that current step is still set correctly
1081
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1082
-            EE_Error::add_error(
1083
-                esc_html__(
1084
-                    'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1085
-                    'event_espresso'
1086
-                ),
1087
-                __FILE__,
1088
-                __FUNCTION__,
1089
-                __LINE__
1090
-            );
1091
-            return false;
1092
-        }
1093
-        // if returning to SPCO, then verify that primary registrant is set
1094
-        if (! empty($this->checkout->reg_url_link)) {
1095
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1096
-            if (! $valid_registrant instanceof EE_Registration) {
1097
-                EE_Error::add_error(
1098
-                    esc_html__(
1099
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1100
-                        'event_espresso'
1101
-                    ),
1102
-                    __FILE__,
1103
-                    __FUNCTION__,
1104
-                    __LINE__
1105
-                );
1106
-                return false;
1107
-            }
1108
-            $valid_registrant = null;
1109
-            foreach (
1110
-                $this->checkout->transaction->registrations(
1111
-                    $this->checkout->reg_cache_where_params
1112
-                ) as $registration
1113
-            ) {
1114
-                if (
1115
-                    $registration instanceof EE_Registration
1116
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1117
-                ) {
1118
-                    $valid_registrant = $registration;
1119
-                }
1120
-            }
1121
-            if (! $valid_registrant instanceof EE_Registration) {
1122
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1123
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1124
-                    // clear the session, mark the checkout as unverified, and try again
1125
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1126
-                    EED_Single_Page_Checkout::$_initialized       = false;
1127
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1128
-                    $this->_initialize();
1129
-                    EE_Error::reset_notices();
1130
-                    return false;
1131
-                }
1132
-                EE_Error::add_error(
1133
-                    esc_html__(
1134
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1135
-                        'event_espresso'
1136
-                    ),
1137
-                    __FILE__,
1138
-                    __FUNCTION__,
1139
-                    __LINE__
1140
-                );
1141
-                return false;
1142
-            }
1143
-        }
1144
-        // now that things have been kinda sufficiently verified,
1145
-        // let's add the checkout to the session so that it's available to other systems
1146
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1147
-        return true;
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1153
-     * then loops thru all the active reg steps and calls the initialize_reg_step() method
1154
-     *
1155
-     * @param bool $reinitializing
1156
-     * @throws EE_Error
1157
-     */
1158
-    private function _initialize_reg_steps(bool $reinitializing = false)
1159
-    {
1160
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1161
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1162
-        foreach ($this->checkout->reg_steps as $reg_step) {
1163
-            if (! $reg_step->initialize_reg_step()) {
1164
-                // if not initialized then maybe this step is being removed...
1165
-                if (! $reinitializing && $reg_step->is_current_step()) {
1166
-                    // if it was the current step, then we need to start over here
1167
-                    $this->_initialize_reg_steps(true);
1168
-                    return;
1169
-                }
1170
-                continue;
1171
-            }
1172
-            // add css and JS for current step
1173
-            $this->add_styles_and_scripts($reg_step);
1174
-            if ($reg_step->is_current_step()) {
1175
-                // the text that appears on the reg step form submit button
1176
-                $reg_step->set_submit_button_text();
1177
-            }
1178
-        }
1179
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1180
-        do_action(
1181
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1182
-            $this->checkout->current_step
1183
-        );
1184
-    }
1185
-
1186
-
1187
-    /**
1188
-     * @return boolean
1189
-     * @throws EE_Error
1190
-     * @throws ReflectionException
1191
-     */
1192
-    private function _check_form_submission(): bool
1193
-    {
1194
-        // does this request require the reg form to be generated ?
1195
-        if ($this->checkout->generate_reg_form) {
1196
-            // ever heard that song by Blue Rodeo ?
1197
-            try {
1198
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1199
-                // if not displaying a form, then check for form submission
1200
-                if (
1201
-                    $this->checkout->process_form_submission
1202
-                    && $this->checkout->current_step->reg_form->was_submitted()
1203
-                ) {
1204
-                    // clear out any old data in case this step is being run again
1205
-                    $this->checkout->current_step->set_valid_data([]);
1206
-                    // capture submitted form data
1207
-                    $request_data = $this->request->requestParams();
1208
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1209
-                        (array) apply_filters(
1210
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1211
-                            $request_data,
1212
-                            $this->checkout
1213
-                        )
1214
-                    );
1215
-                    // validate submitted form data
1216
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1217
-                        // thou shall not pass !!!
1218
-                        $this->checkout->continue_reg = false;
1219
-                        // any form validation errors?
1220
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1221
-                            EE_Error::add_error(
1222
-                                $this->checkout->current_step->reg_form->submission_error_message(),
1223
-                                __FILE__,
1224
-                                __FUNCTION__,
1225
-                                __LINE__
1226
-                            );
1227
-                        }
1228
-                        // well not really... what will happen is
1229
-                        // we'll just get redirected back to redo the current step
1230
-                        $this->go_to_next_step();
1231
-                        return false;
1232
-                    }
1233
-                }
1234
-            } catch (EE_Error $e) {
1235
-                $e->get_error();
1236
-            }
1237
-        }
1238
-        return true;
1239
-    }
1240
-
1241
-
1242
-    /**
1243
-     * @return void
1244
-     * @throws EE_Error
1245
-     * @throws ReflectionException
1246
-     */
1247
-    private function _process_form_action()
1248
-    {
1249
-        // what cha wanna do?
1250
-        switch ($this->checkout->action) {
1251
-            // AJAX next step reg form
1252
-            case 'display_spco_reg_step':
1253
-                $this->checkout->redirect = false;
1254
-                if ($this->request->isAjax()) {
1255
-                    $this->checkout->json_response->set_reg_step_html(
1256
-                        $this->checkout->current_step->display_reg_form()
1257
-                    );
1258
-                }
1259
-                break;
1260
-            default:
1261
-                // meh... do one of those other steps first
1262
-                if (
1263
-                    ! empty($this->checkout->action)
1264
-                    && is_callable([$this->checkout->current_step, $this->checkout->action])
1265
-                ) {
1266
-                    // dynamically creates hook point like:
1267
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1268
-                    do_action(
1269
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1270
-                        $this->checkout->current_step
1271
-                    );
1272
-                    $process_reg_step = apply_filters(
1273
-                        "AHEE__Single_Page_Checkout__process_reg_step__{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1274
-                        true,
1275
-                        $this->checkout->current_step,
1276
-                        $this
1277
-                    );
1278
-                    // call action on current step
1279
-                    if ($process_reg_step && call_user_func([$this->checkout->current_step, $this->checkout->action])) {
1280
-                        // good registrant, you get to proceed
1281
-                        if (
1282
-                            $this->checkout->current_step->success_message() !== ''
1283
-                            && apply_filters(
1284
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1285
-                                false
1286
-                            )
1287
-                        ) {
1288
-                            EE_Error::add_success(
1289
-                                $this->checkout->current_step->success_message()
1290
-                                . '<br />' . $this->checkout->next_step->_instructions()
1291
-                            );
1292
-                        }
1293
-                        // pack it up, pack it in...
1294
-                        $this->_setup_redirect();
1295
-                    }
1296
-                    // dynamically creates hook point like:
1297
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1298
-                    do_action(
1299
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1300
-                        $this->checkout->current_step
1301
-                    );
1302
-                } else {
1303
-                    EE_Error::add_error(
1304
-                        sprintf(
1305
-                            esc_html__(
1306
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1307
-                                'event_espresso'
1308
-                            ),
1309
-                            $this->checkout->action,
1310
-                            $this->checkout->current_step->name()
1311
-                        ),
1312
-                        __FILE__,
1313
-                        __FUNCTION__,
1314
-                        __LINE__
1315
-                    );
1316
-                }
1317
-            // end default
1318
-        }
1319
-        // store our progress so far
1320
-        $this->checkout->stash_transaction_and_checkout();
1321
-        // advance to the next step! If you pass GO, collect $200
1322
-        $this->go_to_next_step();
1323
-    }
1324
-
1325
-
1326
-    /**
1327
-     * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target an object with the method `translate_js_strings` and
1328
-     *                                                          `enqueue_styles_and_scripts`.
1329
-     * @return void
1330
-     */
1331
-    public function add_styles_and_scripts($target)
1332
-    {
1333
-        // i18n
1334
-        $target->translate_js_strings();
1335
-        if ($this->checkout->admin_request) {
1336
-            add_action('admin_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1337
-        } else {
1338
-            add_action('wp_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1339
-        }
1340
-    }
1341
-
1342
-
1343
-    /**
1344
-     * @return void
1345
-     */
1346
-    public function translate_js_strings()
1347
-    {
1348
-        EE_Registry::$i18n_js_strings['revisit']                        = $this->checkout->revisit;
1349
-        EE_Registry::$i18n_js_strings['e_reg_url_link']                 = $this->checkout->reg_url_link;
1350
-        EE_Registry::$i18n_js_strings['server_error']                   = esc_html__(
1351
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1352
-            'event_espresso'
1353
-        );
1354
-        EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1355
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1356
-            'event_espresso'
1357
-        );
1358
-        EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1359
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1360
-            'event_espresso'
1361
-        );
1362
-        EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1363
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1364
-            'event_espresso'
1365
-        );
1366
-        EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1367
-            'This registration step could not be completed. Please refresh the page and try again.',
1368
-            'event_espresso'
1369
-        );
1370
-        EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1371
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1372
-            'event_espresso'
1373
-        );
1374
-        EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1375
-            esc_html__(
1376
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1377
-                'event_espresso'
1378
-            ),
1379
-            '<br/>',
1380
-            '<br/>'
1381
-        );
1382
-        EE_Registry::$i18n_js_strings['language']                       = get_bloginfo('language');
1383
-        EE_Registry::$i18n_js_strings['EESID']                          = EE_Registry::instance()->SSN->id();
1384
-        EE_Registry::$i18n_js_strings['currency']                       = EE_Registry::instance()->CFG->currency;
1385
-        EE_Registry::$i18n_js_strings['datepicker_yearRange']           = '-150:+20';
1386
-        EE_Registry::$i18n_js_strings['timer_years']                    = esc_html__('years', 'event_espresso');
1387
-        EE_Registry::$i18n_js_strings['timer_months']                   = esc_html__('months', 'event_espresso');
1388
-        EE_Registry::$i18n_js_strings['timer_weeks']                    = esc_html__('weeks', 'event_espresso');
1389
-        EE_Registry::$i18n_js_strings['timer_days']                     = esc_html__('days', 'event_espresso');
1390
-        EE_Registry::$i18n_js_strings['timer_hours']                    = esc_html__('hours', 'event_espresso');
1391
-        EE_Registry::$i18n_js_strings['timer_minutes']                  = esc_html__('minutes', 'event_espresso');
1392
-        EE_Registry::$i18n_js_strings['timer_seconds']                  = esc_html__('seconds', 'event_espresso');
1393
-        EE_Registry::$i18n_js_strings['timer_year']                     = esc_html__('year', 'event_espresso');
1394
-        EE_Registry::$i18n_js_strings['timer_month']                    = esc_html__('month', 'event_espresso');
1395
-        EE_Registry::$i18n_js_strings['timer_week']                     = esc_html__('week', 'event_espresso');
1396
-        EE_Registry::$i18n_js_strings['timer_day']                      = esc_html__('day', 'event_espresso');
1397
-        EE_Registry::$i18n_js_strings['timer_hour']                     = esc_html__('hour', 'event_espresso');
1398
-        EE_Registry::$i18n_js_strings['timer_minute']                   = esc_html__('minute', 'event_espresso');
1399
-        EE_Registry::$i18n_js_strings['timer_second']                   = esc_html__('second', 'event_espresso');
1400
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
1401
-            EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1402
-        EE_Registry::$i18n_js_strings['ajax_submit']                    = apply_filters(
1403
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1404
-            true
1405
-        );
1406
-        EE_Registry::$i18n_js_strings['session_extension']              = absint(
1407
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1408
-        );
1409
-        EE_Registry::$i18n_js_strings['session_expiration']             = gmdate(
1410
-            'M d, Y H:i:s',
1411
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1412
-        );
1413
-    }
1414
-
1415
-
1416
-    /**
1417
-     * @return void
1418
-     * @throws EE_Error
1419
-     */
1420
-    public function enqueue_styles_and_scripts()
1421
-    {
1422
-        // load css
1423
-        wp_register_style(
1424
-            'single_page_checkout',
1425
-            SPCO_CSS_URL . 'single_page_checkout.css',
1426
-            ['espresso_default'],
1427
-            EVENT_ESPRESSO_VERSION
1428
-        );
1429
-        wp_enqueue_style('single_page_checkout');
1430
-        // load JS
1431
-        wp_register_script(
1432
-            'jquery_plugin',
1433
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1434
-            ['jquery'],
1435
-            '1.0.1',
1436
-            true
1437
-        );
1438
-        wp_register_script(
1439
-            'jquery_countdown',
1440
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1441
-            ['jquery_plugin'],
1442
-            '2.1.0',
1443
-            true
1444
-        );
1445
-        wp_register_script(
1446
-            'single_page_checkout',
1447
-            SPCO_JS_URL . 'single_page_checkout.js',
1448
-            ['espresso_core', 'underscore', 'ee_form_section_validation'],
1449
-            EVENT_ESPRESSO_VERSION,
1450
-            true
1451
-        );
1452
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1453
-            $this->checkout->registration_form->enqueue_js();
1454
-        }
1455
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1456
-            $this->checkout->current_step->reg_form->enqueue_js();
1457
-        }
1458
-        wp_enqueue_script('single_page_checkout');
1459
-        if (apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)) {
1460
-            wp_enqueue_script('jquery_countdown');
1461
-        }
1462
-        /**
1463
-         * global action hook for enqueueing styles and scripts with
1464
-         * spco calls.
1465
-         */
1466
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1467
-        /**
1468
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1469
-         * The hook will end up being something like:
1470
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1471
-         */
1472
-        do_action(
1473
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1474
-            $this
1475
-        );
1476
-    }
1477
-
1478
-
1479
-    /**
1480
-     * display the Registration Single Page Checkout Form
1481
-     *
1482
-     * @return void
1483
-     * @throws EE_Error
1484
-     * @throws ReflectionException
1485
-     */
1486
-    private function _display_spco_reg_form()
1487
-    {
1488
-        // if registering via the admin, just display the reg form for the current step
1489
-        if ($this->checkout->admin_request) {
1490
-            EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->current_step->display_reg_form());
1491
-        } else {
1492
-            // add powered by EE msg
1493
-            add_action('AHEE__SPCO__reg_form_footer', ['EED_Single_Page_Checkout', 'display_registration_footer']);
1494
-            $empty_cart                                 = count(
1495
-                    $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1496
-                ) < 1;
1497
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1498
-            $cookies_not_set_msg                        = '';
1499
-            if ($empty_cart) {
1500
-                $cookies_not_set_msg = apply_filters(
1501
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1502
-                    sprintf(
1503
-                        esc_html__(
1504
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1505
-                            'event_espresso'
1506
-                        ),
1507
-                        '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1508
-                        '</div>',
1509
-                        '<h6 class="important-notice">',
1510
-                        '</h6>',
1511
-                        '<p>',
1512
-                        '</p>',
1513
-                        '<br />',
1514
-                        '<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
1515
-                        '</a>'
1516
-                    )
1517
-                );
1518
-            }
1519
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1520
-                [
1521
-                    'name'            => 'single-page-checkout',
1522
-                    'html_id'         => 'ee-single-page-checkout-dv',
1523
-                    'layout_strategy' =>
1524
-                        new EE_Template_Layout(
1525
-                            [
1526
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1527
-                                'template_args'        => [
1528
-                                    'empty_cart'              => $empty_cart,
1529
-                                    'revisit'                 => $this->checkout->revisit,
1530
-                                    'reg_steps'               => $this->checkout->reg_steps,
1531
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1532
-                                        ? $this->checkout->next_step->slug()
1533
-                                        : '',
1534
-                                    'empty_msg'               => apply_filters(
1535
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1536
-                                        sprintf(
1537
-                                            esc_html__(
1538
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1539
-                                                'event_espresso'
1540
-                                            ),
1541
-                                            '<a href="'
1542
-                                            . get_post_type_archive_link(EspressoPostType::EVENTS)
1543
-                                            . '" title="',
1544
-                                            '">',
1545
-                                            '</a>'
1546
-                                        )
1547
-                                    ),
1548
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1549
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1550
-                                    'session_expiration'      => gmdate(
1551
-                                        'M d, Y H:i:s',
1552
-                                        EE_Registry::instance()->SSN->expiration()
1553
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1554
-                                    ),
1555
-                                ],
1556
-                            ]
1557
-                        ),
1558
-                ]
1559
-            );
1560
-            // load template and add to output sent that gets filtered into the_content()
1561
-            EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->registration_form->get_html());
1562
-        }
1563
-    }
1564
-
1565
-
1566
-    /**
1567
-     * @param $next_step
1568
-     * @return void
1569
-     */
1570
-    public function add_extra_finalize_registration_inputs($next_step)
1571
-    {
1572
-        if ($next_step === 'finalize_registration') {
1573
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1574
-        }
1575
-    }
1576
-
1577
-
1578
-    /**
1579
-     * @return void
1580
-     */
1581
-    public static function display_registration_footer()
1582
-    {
1583
-        if (
1584
-            apply_filters(
1585
-                'FHEE__EE_Front__Controller__show_reg_footer',
1586
-                EE_Registry::instance()->CFG->admin->show_reg_footer
1587
-            )
1588
-        ) {
1589
-            add_filter(
1590
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1591
-                function ($url) {
1592
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1593
-                }
1594
-            );
1595
-            echo apply_filters(
1596
-                'FHEE__EE_Front_Controller__display_registration_footer',
1597
-                EEH_Template::powered_by_event_espresso(
1598
-                    '',
1599
-                    'espresso-registration-footer-dv',
1600
-                    ['utm_content' => 'registration_checkout']
1601
-                )
1602
-            );
1603
-        }
1604
-    }
1605
-
1606
-
1607
-    /**
1608
-     * @return void
1609
-     * @throws EE_Error
1610
-     * @throws ReflectionException
1611
-     */
1612
-    public function unlock_transaction()
1613
-    {
1614
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1615
-            $this->checkout->transaction->unlock();
1616
-        }
1617
-    }
1618
-
1619
-
1620
-    /**
1621
-     * @return void
1622
-     */
1623
-    private function _setup_redirect()
1624
-    {
1625
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1626
-            $this->checkout->redirect = true;
1627
-            if (empty($this->checkout->redirect_url)) {
1628
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1629
-            }
1630
-            $this->checkout->redirect_url = apply_filters(
1631
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1632
-                $this->checkout->redirect_url,
1633
-                $this->checkout
1634
-            );
1635
-        }
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     * handle ajax message responses and redirects
1641
-     *
1642
-     * @return void
1643
-     * @throws EE_Error
1644
-     * @throws ReflectionException
1645
-     */
1646
-    public function go_to_next_step()
1647
-    {
1648
-        if ($this->request->isAjax()) {
1649
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1650
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1651
-        }
1652
-        $this->unlock_transaction();
1653
-        // just return for these conditions
1654
-        if (
1655
-            $this->checkout->admin_request
1656
-            || $this->checkout->action === 'redirect_form'
1657
-            || $this->checkout->action === 'update_checkout'
1658
-        ) {
1659
-            return;
1660
-        }
1661
-        // AJAX response
1662
-        $this->_handle_json_response();
1663
-        // redirect to next step or the Thank-You page
1664
-        $this->_handle_html_redirects();
1665
-        // hmmm... must be something wrong, so let's just display the form again !
1666
-        $this->_display_spco_reg_form();
1667
-    }
1668
-
1669
-
1670
-    /**
1671
-     * @return void
1672
-     * @throws EE_Error
1673
-     */
1674
-    protected function _handle_json_response()
1675
-    {
1676
-        // if this is an ajax request
1677
-        if ($this->request->isAjax()) {
1678
-            $this->checkout->json_response->set_registration_time_limit(
1679
-                $this->checkout->get_registration_time_limit()
1680
-            );
1681
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1682
-            // just send the ajax (
1683
-            $json_response = apply_filters(
1684
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1685
-                $this->checkout->json_response
1686
-            );
1687
-            exit($json_response);
1688
-        }
1689
-    }
1690
-
1691
-
1692
-    /**
1693
-     * @return void
1694
-     */
1695
-    protected function _handle_html_redirects()
1696
-    {
1697
-        // going somewhere ?
1698
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1699
-            // store notices in a transient
1700
-            EE_Error::get_notices(false, true);
1701
-            wp_safe_redirect($this->checkout->redirect_url);
1702
-            exit();
1703
-        }
1704
-    }
1705
-
1706
-
1707
-    /**
1708
-     * @return void
1709
-     */
1710
-    public function set_checkout_anchor()
1711
-    {
1712
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1713
-    }
1714
-
1715
-
1716
-    /**
1717
-     * @return string
1718
-     * @since 4.9.59.p
1719
-     */
1720
-    public static function getRegistrationExpirationNotice(): string
1721
-    {
1722
-        return sprintf(
1723
-            esc_html__(
1724
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1725
-                'event_espresso'
1726
-            ),
1727
-            '<h4 class="important-notice">',
1728
-            '</h4>',
1729
-            '<br />',
1730
-            '<p>',
1731
-            '<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" title="',
1732
-            '">',
1733
-            '</a>',
1734
-            '</p>'
1735
-        );
1736
-    }
23
+	/**
24
+	 * $_initialized - has the SPCO controller already been initialized ?
25
+	 */
26
+	private static bool $_initialized = false;
27
+
28
+
29
+	/**
30
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
31
+	 */
32
+	private static bool $_checkout_verified = true;
33
+
34
+	/**
35
+	 * $_reg_steps_array - holds initial array of reg steps
36
+	 *
37
+	 * @var array $_reg_steps_array
38
+	 */
39
+	private static array $_reg_steps_array = [];
40
+
41
+	/**
42
+	 * $checkout - EE_Checkout object for handling the properties of the current checkout process
43
+	 */
44
+	public ?EE_Checkout $checkout = null;
45
+
46
+	protected ?RequestInterface $request = null;
47
+
48
+	private bool $debug = false;    //  true    false
49
+
50
+
51
+	/**
52
+	 * @return EED_Single_Page_Checkout|EED_Module
53
+	 * @throws EE_Error
54
+	 * @throws ReflectionException
55
+	 */
56
+	public static function instance()
57
+	{
58
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
59
+		return parent::get_instance(__CLASS__);
60
+	}
61
+
62
+
63
+	/**
64
+	 * @return EE_CART
65
+	 */
66
+	public function cart(): EE_CART
67
+	{
68
+		return $this->checkout->cart;
69
+	}
70
+
71
+
72
+	/**
73
+	 * @return RequestInterface
74
+	 * @since   4.10.14.p
75
+	 */
76
+	public static function getRequest(): RequestInterface
77
+	{
78
+		return LoaderFactory::getLoader()->getShared(RequestInterface::class);
79
+	}
80
+
81
+
82
+	/**
83
+	 * @return EE_Transaction
84
+	 */
85
+	public function transaction(): EE_Transaction
86
+	{
87
+		return $this->checkout->transaction;
88
+	}
89
+
90
+
91
+	/**
92
+	 *    set_hooks - for hooking into EE Core, other modules, etc
93
+	 *
94
+	 * @return    void
95
+	 * @throws EE_Error
96
+	 */
97
+	public static function set_hooks()
98
+	{
99
+		EED_Single_Page_Checkout::set_definitions();
100
+	}
101
+
102
+
103
+	/**
104
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
+	 *
106
+	 * @return    void
107
+	 * @throws EE_Error
108
+	 */
109
+	public static function set_hooks_admin()
110
+	{
111
+		EED_Single_Page_Checkout::set_definitions();
112
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
113
+			return;
114
+		}
115
+		// going to start an output buffer in case anything gets accidentally output
116
+		// that might disrupt our JSON response
117
+		ob_start();
118
+		EED_Single_Page_Checkout::load_reg_steps();
119
+		// set ajax hooks
120
+		add_action('wp_ajax_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
121
+		add_action('wp_ajax_nopriv_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
122
+		add_action('wp_ajax_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
123
+		add_action('wp_ajax_nopriv_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
124
+		add_action('wp_ajax_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
125
+		add_action('wp_ajax_nopriv_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
126
+	}
127
+
128
+
129
+	/**
130
+	 *    process ajax request
131
+	 *
132
+	 * @param string $ajax_action
133
+	 * @throws EE_Error
134
+	 * @throws ReflectionException
135
+	 */
136
+	public static function process_ajax_request(string $ajax_action)
137
+	{
138
+		$request = EED_Single_Page_Checkout::getRequest();
139
+		$request->setRequestParam('action', $ajax_action);
140
+		EED_Single_Page_Checkout::instance()->_initialize();
141
+	}
142
+
143
+
144
+	/**
145
+	 * ajax display registration step
146
+	 *
147
+	 * @throws EE_Error
148
+	 * @throws ReflectionException
149
+	 */
150
+	public static function display_reg_step()
151
+	{
152
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
153
+	}
154
+
155
+
156
+	/**
157
+	 * ajax process registration step
158
+	 *
159
+	 * @throws EE_Error
160
+	 * @throws ReflectionException
161
+	 */
162
+	public static function process_reg_step()
163
+	{
164
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
165
+	}
166
+
167
+
168
+	/**
169
+	 * ajax process registration step
170
+	 *
171
+	 * @throws EE_Error
172
+	 * @throws ReflectionException
173
+	 */
174
+	public static function update_reg_step()
175
+	{
176
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
177
+	}
178
+
179
+
180
+	/**
181
+	 * update_checkout
182
+	 *
183
+	 * @return void
184
+	 * @throws ReflectionException
185
+	 * @throws EE_Error
186
+	 */
187
+	public static function update_checkout()
188
+	{
189
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
190
+	}
191
+
192
+
193
+	/**
194
+	 *    set_definitions
195
+	 *
196
+	 * @return    void
197
+	 * @throws EE_Error
198
+	 */
199
+	public static function set_definitions()
200
+	{
201
+		if (defined('SPCO_BASE_PATH')) {
202
+			return;
203
+		}
204
+		define(
205
+			'SPCO_BASE_PATH',
206
+			rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
207
+		);
208
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
209
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
210
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
211
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
212
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
213
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
214
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
215
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
216
+			EED_Single_Page_Checkout::getRegistrationExpirationNotice();
217
+	}
218
+
219
+
220
+	/**
221
+	 * load_reg_steps
222
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
223
+	 *
224
+	 * @throws EE_Error
225
+	 */
226
+	public static function load_reg_steps()
227
+	{
228
+		static $reg_steps_loaded = false;
229
+		if ($reg_steps_loaded) {
230
+			return;
231
+		}
232
+		// filter list of reg_steps
233
+		$reg_steps_to_load = (array) apply_filters(
234
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
235
+			EED_Single_Page_Checkout::get_reg_steps()
236
+		);
237
+		// sort by key (order)
238
+		ksort($reg_steps_to_load);
239
+		// loop through folders
240
+		foreach ($reg_steps_to_load as $order => $reg_step) {
241
+			// we need a
242
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
243
+				// copy over to the reg_steps_array
244
+				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
245
+				// register custom key route for each reg step
246
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
247
+				EE_Config::register_route(
248
+					$reg_step['slug'],
249
+					'EED_Single_Page_Checkout',
250
+					'run',
251
+					'step'
252
+				);
253
+				// add AJAX or other hooks
254
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
255
+					// setup autoloaders if necessary
256
+					if (! class_exists($reg_step['class_name'])) {
257
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
258
+							$reg_step['file_path'],
259
+							true
260
+						);
261
+					}
262
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
263
+						call_user_func([$reg_step['class_name'], 'set_hooks']);
264
+					}
265
+				}
266
+			}
267
+		}
268
+		$reg_steps_loaded = true;
269
+	}
270
+
271
+
272
+	/**
273
+	 *    get_reg_steps
274
+	 *
275
+	 * @return    array
276
+	 */
277
+	public static function get_reg_steps(): array
278
+	{
279
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
280
+		if (empty($reg_steps)) {
281
+			$reg_steps = [
282
+				10  => [
283
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
284
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
285
+					'slug'       => 'attendee_information',
286
+					'has_hooks'  => false,
287
+				],
288
+				30  => [
289
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
290
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
291
+					'slug'       => 'payment_options',
292
+					'has_hooks'  => true,
293
+				],
294
+				999 => [
295
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
296
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
297
+					'slug'       => 'finalize_registration',
298
+					'has_hooks'  => false,
299
+				],
300
+			];
301
+		}
302
+		return $reg_steps;
303
+	}
304
+
305
+
306
+	/**
307
+	 * @return array|string
308
+	 * @throws EE_Error
309
+	 * @throws ReflectionException
310
+	 */
311
+	public static function registration_checkout_for_admin()
312
+	{
313
+		$request = EED_Single_Page_Checkout::getRequest();
314
+		$request->setRequestParam('step', 'attendee_information');
315
+		$request->setRequestParam('action', 'display_spco_reg_step');
316
+		$request->setRequestParam('process_form_submission', false);
317
+		EED_Single_Page_Checkout::instance()->_initialize();
318
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
319
+		return EED_Single_Page_Checkout::getResponse()->getOutput();
320
+	}
321
+
322
+
323
+	/**
324
+	 * @return EE_Transaction|null
325
+	 * @throws EE_Error
326
+	 * @throws ReflectionException
327
+	 */
328
+	public static function process_registration_from_admin(): ?EE_Transaction
329
+	{
330
+		$request = EED_Single_Page_Checkout::getRequest();
331
+		$request->setRequestParam('step', 'attendee_information');
332
+		$request->setRequestParam('action', 'process_reg_step');
333
+		$request->setRequestParam('process_form_submission', true);
334
+		EED_Single_Page_Checkout::instance()->_initialize();
335
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
336
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
337
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
338
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
339
+				if ($final_reg_step->process_reg_step()) {
340
+					$final_reg_step->set_completed();
341
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
342
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
343
+				}
344
+			}
345
+		}
346
+		return null;
347
+	}
348
+
349
+
350
+	/**
351
+	 *    run
352
+	 *
353
+	 * @param WP_Query|null $WP_Query
354
+	 * @return    void
355
+	 */
356
+	public function run($WP_Query)
357
+	{
358
+		if (
359
+			$WP_Query instanceof WP_Query
360
+			&& $WP_Query->is_main_query()
361
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
362
+			&& $this->_is_reg_checkout()
363
+		) {
364
+			$this->_initialize();
365
+		}
366
+	}
367
+
368
+
369
+	/**
370
+	 * determines whether current url matches reg page url
371
+	 *
372
+	 * @return bool
373
+	 */
374
+	protected function _is_reg_checkout(): bool
375
+	{
376
+		// get current permalink for reg page without any extra query args
377
+		$reg_page_url = get_permalink(EE_Config::instance()->core->reg_page_id);
378
+		// get request URI for current request, but without the scheme or host
379
+		$current_request_uri = EEH_URL::filter_input_server_url();
380
+		$current_request_uri = html_entity_decode($current_request_uri);
381
+		// get array of query args from the current request URI
382
+		$query_args = EEH_URL::get_query_string($current_request_uri);
383
+		// grab page id if it is set
384
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
385
+		// and remove the page id from the query args (we will re-add it later)
386
+		unset($query_args['page_id']);
387
+		// now strip all query args from current request URI
388
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
389
+		// and re-add the page id if it was set
390
+		if ($page_id) {
391
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
392
+		}
393
+		// remove slashes and ?
394
+		$current_request_uri = trim($current_request_uri, '?/');
395
+		// is current request URI part of the known full reg page URL ?
396
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
397
+	}
398
+
399
+
400
+	/**
401
+	 * @param WP_Query $wp_query
402
+	 * @return    void
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	public static function init(WP_Query $wp_query)
407
+	{
408
+		EED_Single_Page_Checkout::instance()->run($wp_query);
409
+	}
410
+
411
+
412
+	/**
413
+	 * @return void
414
+	 */
415
+	private function _initialize()
416
+	{
417
+		// ensure SPCO doesn't run twice
418
+		if (EED_Single_Page_Checkout::$_initialized) {
419
+			return;
420
+		}
421
+		try {
422
+			$this->request = EED_Single_Page_Checkout::getRequest();
423
+			EED_Single_Page_Checkout::load_reg_steps();
424
+			$this->_verify_session();
425
+			// set up the EE_Checkout object
426
+			$this->checkout = $this->_initialize_checkout();
427
+			// filter checkout
428
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
429
+			// get the $_GET
430
+			$this->_get_request_vars();
431
+			if ($this->_block_bots()) {
432
+				return;
433
+			}
434
+			// filter continue_reg
435
+			$this->checkout->continue_reg = apply_filters(
436
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
437
+				true,
438
+				$this->checkout
439
+			);
440
+			// load the reg steps array
441
+			if (! $this->_load_and_instantiate_reg_steps()) {
442
+				EED_Single_Page_Checkout::$_initialized = true;
443
+				return;
444
+			}
445
+			// set the current step
446
+			$this->checkout->set_current_step($this->checkout->step);
447
+			// and the next step
448
+			$this->checkout->set_next_step();
449
+			// verify that everything has been set up correctly
450
+			if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
451
+				EED_Single_Page_Checkout::$_initialized = true;
452
+				return;
453
+			}
454
+			do_action('AHEE__Single_Page_Checkout___initialize__after_final_verifications', $this->checkout);
455
+			// lock the transaction
456
+			$this->checkout->transaction->lock();
457
+			// make sure all of our cached objects are added to their respective model entity mappers
458
+			$this->checkout->refresh_all_entities();
459
+			// set amount owing
460
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
461
+			// initialize each reg step, which gives them the chance to potentially alter the process
462
+			$this->_initialize_reg_steps();
463
+			// DEBUG LOG
464
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
465
+			// get reg form
466
+			if (! $this->_check_form_submission()) {
467
+				EED_Single_Page_Checkout::$_initialized = true;
468
+				return;
469
+			}
470
+			// checkout the action!!!
471
+			$this->_process_form_action();
472
+			// add some style and make it dance
473
+			$this->add_styles_and_scripts($this);
474
+			// kk... SPCO has successfully run
475
+			EED_Single_Page_Checkout::$_initialized = true;
476
+			// set no cache headers and constants
477
+			EE_System::do_not_cache();
478
+			// add anchor
479
+			add_action('loop_start', [$this, 'set_checkout_anchor'], 1);
480
+			// remove transaction lock
481
+			add_action('shutdown', [$this, 'unlock_transaction'], 1);
482
+		} catch (Exception $e) {
483
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
484
+		}
485
+	}
486
+
487
+
488
+	/**
489
+	 * checks that the session is valid and not expired
490
+	 *
491
+	 * @throws EE_Error
492
+	 * @throws ReflectionException
493
+	 */
494
+	private function _verify_session()
495
+	{
496
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
497
+			throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
498
+		}
499
+		$clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
500
+		// is session still valid ?
501
+		if (
502
+			$clear_session_requested
503
+			|| (
504
+				EE_Registry::instance()->SSN->expired()
505
+				&& $this->request->getRequestParam('e_reg_url_link') === ''
506
+			)
507
+		) {
508
+			$this->checkout = new EE_Checkout();
509
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
510
+			// EE_Registry::instance()->SSN->reset_cart();
511
+			// EE_Registry::instance()->SSN->reset_checkout();
512
+			// EE_Registry::instance()->SSN->reset_transaction();
513
+			if (! $clear_session_requested) {
514
+				EE_Error::add_attention(
515
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
516
+					__FILE__,
517
+					__FUNCTION__,
518
+					__LINE__
519
+				);
520
+			}
521
+			// EE_Registry::instance()->SSN->reset_expired();
522
+		}
523
+	}
524
+
525
+
526
+	/**
527
+	 * loads and instantiates EE_Checkout
528
+	 *
529
+	 * @return EE_Checkout
530
+	 * @throws EE_Error
531
+	 * @throws ReflectionException
532
+	 */
533
+	private function _initialize_checkout(): EE_Checkout
534
+	{
535
+		// look in session for existing checkout
536
+		/** @type EE_Checkout $checkout */
537
+		$checkout = EE_Registry::instance()->SSN->checkout();
538
+		// verify
539
+		if (! $checkout instanceof EE_Checkout) {
540
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
541
+			$checkout = EE_Registry::instance()->load_file(
542
+				SPCO_INC_PATH,
543
+				'EE_Checkout',
544
+				'class',
545
+				[],
546
+				false
547
+			);
548
+		} else {
549
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
550
+				$this->unlock_transaction();
551
+				wp_safe_redirect($checkout->redirect_url);
552
+				exit();
553
+			}
554
+		}
555
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
556
+		// verify again
557
+		if (! $checkout instanceof EE_Checkout) {
558
+			throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
559
+		}
560
+		// reset anything that needs a clean slate for each request
561
+		$checkout->reset_for_current_request();
562
+		return $checkout;
563
+	}
564
+
565
+
566
+	/**
567
+	 * @return void
568
+	 */
569
+	private function _get_request_vars()
570
+	{
571
+		// make sure this request is marked as belonging to EE
572
+		/** @var CurrentPage $current_page */
573
+		$current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class);
574
+		$current_page->setEspressoPage(true);
575
+		// which step is being requested ?
576
+		$this->checkout->step = $this->request->getRequestParam('step', $this->_get_first_step());
577
+		// which step is being edited ?
578
+		$this->checkout->edit_step = $this->request->getRequestParam('edit_step');
579
+		// and what we're doing on the current step
580
+		$this->checkout->action = $this->request->getRequestParam('action', 'display_spco_reg_step');
581
+		// timestamp
582
+		$this->checkout->uts = $this->request->getRequestParam('uts', 0, 'int');
583
+		// returning to edit ?
584
+		$this->checkout->reg_url_link = $this->request->getRequestParam('e_reg_url_link');
585
+		// add reg url link to registration query params
586
+		if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
587
+			$this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
588
+		}
589
+		// or some other kind of revisit ?
590
+		$this->checkout->revisit = $this->request->getRequestParam('revisit', false, 'bool');
591
+		// and whether to generate a reg form for this request
592
+		$this->checkout->generate_reg_form = $this->request->getRequestParam('generate_reg_form', true, 'bool');
593
+		// and whether to process a reg form submission for this request
594
+		$this->checkout->process_form_submission = $this->request->getRequestParam(
595
+			'process_form_submission',
596
+			$this->checkout->action === 'process_reg_step',
597
+			'bool'
598
+		);
599
+		$this->checkout->process_form_submission = filter_var(
600
+			$this->checkout->action !== 'display_spco_reg_step'
601
+				? $this->checkout->process_form_submission
602
+				: false,
603
+			FILTER_VALIDATE_BOOLEAN
604
+		);
605
+		$this->_display_request_vars();
606
+	}
607
+
608
+
609
+	/**
610
+	 * @return void
611
+	 */
612
+	protected function _display_request_vars()
613
+	{
614
+		if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
615
+			return;
616
+		}
617
+		EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
618
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
619
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
620
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
621
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
622
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
623
+		EEH_Debug_Tools::printr(
624
+			$this->checkout->generate_reg_form,
625
+			'$this->checkout->generate_reg_form',
626
+			__FILE__,
627
+			__LINE__
628
+		);
629
+		EEH_Debug_Tools::printr(
630
+			$this->checkout->process_form_submission,
631
+			'$this->checkout->process_form_submission',
632
+			__FILE__,
633
+			__LINE__
634
+		);
635
+	}
636
+
637
+
638
+	/**
639
+	 * _block_bots
640
+	 * checks that the incoming request has either of the following set:
641
+	 *  a UTS (unix timestamp) which indicates that the request was redirected from the Ticket Selector
642
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
643
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
644
+	 * then where you coming from man?
645
+	 *
646
+	 * @return boolean
647
+	 */
648
+	private function _block_bots(): bool
649
+	{
650
+		return EED_Invalid_Checkout_Access::getInvalidCheckoutAccess()->checkoutAccessIsInvalid($this->checkout);
651
+	}
652
+
653
+
654
+	/**
655
+	 *  gets slug for first step in $_reg_steps_array
656
+	 *
657
+	 * @return string
658
+	 */
659
+	private function _get_first_step(): string
660
+	{
661
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
662
+		return $first_step['slug'] ?? 'attendee_information';
663
+	}
664
+
665
+
666
+	/**
667
+	 * instantiates each reg step based on the loaded reg_steps array
668
+	 *
669
+	 * @return bool
670
+	 * @throws EE_Error
671
+	 * @throws InvalidArgumentException
672
+	 * @throws InvalidDataTypeException
673
+	 * @throws InvalidInterfaceException
674
+	 * @throws ReflectionException
675
+	 */
676
+	private function _load_and_instantiate_reg_steps(): bool
677
+	{
678
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
679
+		// have reg_steps already been instantiated ?
680
+		if (
681
+			empty($this->checkout->reg_steps)
682
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
683
+		) {
684
+			// if not, then loop through raw reg steps array
685
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
686
+				if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
687
+					return false;
688
+				}
689
+			}
690
+			if (isset($this->checkout->reg_steps['registration_confirmation'])) {
691
+				// skip the registration_confirmation page ?
692
+				// just remove it from the reg steps array
693
+				$this->checkout->remove_reg_step('registration_confirmation', false);
694
+			}
695
+			// filter the array for good luck
696
+			$this->checkout->reg_steps = apply_filters(
697
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
698
+				$this->checkout->reg_steps
699
+			);
700
+			// finally re-sort based on the reg step class order properties
701
+			$this->checkout->sort_reg_steps();
702
+		} else {
703
+			foreach ($this->checkout->reg_steps as $reg_step) {
704
+				// set all current step stati to FALSE
705
+				$reg_step->set_is_current_step(false);
706
+			}
707
+		}
708
+		if (empty($this->checkout->reg_steps)) {
709
+			EE_Error::add_error(
710
+				esc_html__('No Reg Steps were loaded..', 'event_espresso'),
711
+				__FILE__,
712
+				__FUNCTION__,
713
+				__LINE__
714
+			);
715
+			return false;
716
+		}
717
+		// make reg step details available to JS
718
+		$this->checkout->set_reg_step_JSON_info();
719
+		return true;
720
+	}
721
+
722
+
723
+	/**
724
+	 * @param array $reg_step
725
+	 * @param int   $order
726
+	 * @return bool
727
+	 * @throws EE_Error
728
+	 * @throws ReflectionException
729
+	 */
730
+	private function _load_and_instantiate_reg_step(array $reg_step = [], int $order = 0): bool
731
+	{
732
+		// we need a file_path, class_name, and slug to add a reg step
733
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
734
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
735
+			if (
736
+				$this->checkout->reg_url_link
737
+				&& $this->checkout->step !== $reg_step['slug']
738
+				&& $reg_step['slug'] !== 'finalize_registration'
739
+				// normally at this point we would NOT load the reg step, but this filter can change that
740
+				&& apply_filters(
741
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
742
+					true,
743
+					$reg_step,
744
+					$this->checkout
745
+				)
746
+			) {
747
+				return true;
748
+			}
749
+
750
+			// instantiate step class using file path and class name
751
+			$reg_step_obj = EE_Registry::instance()->load_file(
752
+				$reg_step['file_path'],
753
+				$reg_step['class_name'],
754
+				'class',
755
+				[$this->checkout],
756
+				false
757
+			);
758
+			// did we get the goods ?
759
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
760
+				// set reg step order based on config
761
+				$reg_step_obj->set_order($order);
762
+				// add instantiated reg step object to the master reg steps array
763
+				$this->checkout->add_reg_step($reg_step_obj);
764
+			} else {
765
+				EE_Error::add_error(
766
+					esc_html__('The current step could not be set.', 'event_espresso'),
767
+					__FILE__,
768
+					__FUNCTION__,
769
+					__LINE__
770
+				);
771
+				return false;
772
+			}
773
+		} else {
774
+			if (WP_DEBUG) {
775
+				EE_Error::add_error(
776
+					sprintf(
777
+						esc_html__(
778
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
779
+							'event_espresso'
780
+						),
781
+						$reg_step['file_path'] ?? '',
782
+						$reg_step['class_name'] ?? '',
783
+						$reg_step['slug'] ?? '',
784
+						'<ul>',
785
+						'<li>',
786
+						'</li>',
787
+						'</ul>'
788
+					),
789
+					__FILE__,
790
+					__FUNCTION__,
791
+					__LINE__
792
+				);
793
+			}
794
+			return false;
795
+		}
796
+		return true;
797
+	}
798
+
799
+
800
+	/**
801
+	 * @return bool
802
+	 * @throws EE_Error
803
+	 * @throws ReflectionException
804
+	 */
805
+	private function _verify_transaction_and_get_registrations(): bool
806
+	{
807
+		// was there already a valid transaction in the checkout from the session ?
808
+		if (! $this->checkout->transaction instanceof EE_Transaction) {
809
+			// get transaction from db or session
810
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
811
+				? $this->_get_transaction_and_cart_for_previous_visit()
812
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
813
+			if (! $this->checkout->transaction instanceof EE_Transaction) {
814
+				EE_Error::add_error(
815
+					esc_html__(
816
+						'Your Registration and Transaction information could not be retrieved from the db.',
817
+						'event_espresso'
818
+					),
819
+					__FILE__,
820
+					__FUNCTION__,
821
+					__LINE__
822
+				);
823
+				$this->checkout->transaction = EE_Transaction::new_instance();
824
+				// add some style and make it dance
825
+				$this->add_styles_and_scripts($this);
826
+				EED_Single_Page_Checkout::$_initialized = true;
827
+				return false;
828
+			}
829
+			// and the registrations for the transaction
830
+			$this->_get_registrations($this->checkout->transaction);
831
+		}
832
+		return true;
833
+	}
834
+
835
+
836
+	/**
837
+	 * @return EE_Transaction|null
838
+	 * @throws EE_Error
839
+	 * @throws ReflectionException
840
+	 */
841
+	private function _get_transaction_and_cart_for_previous_visit(): ?EE_Transaction
842
+	{
843
+		/** @var $TXN_model EEM_Transaction */
844
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
845
+		// because the reg_url_link is present in the request,
846
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
847
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
848
+		// verify transaction
849
+		if ($transaction instanceof EE_Transaction) {
850
+			// and get the cart that was used for that transaction
851
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
852
+			return $transaction;
853
+		}
854
+		EE_Error::add_error(
855
+			esc_html__(
856
+				'Your Registration and Transaction information could not be retrieved from the db.',
857
+				'event_espresso'
858
+			),
859
+			__FILE__,
860
+			__FUNCTION__,
861
+			__LINE__
862
+		);
863
+		return null;
864
+	}
865
+
866
+
867
+	/**
868
+	 * @param EE_Transaction|null $transaction
869
+	 * @return EE_Cart
870
+	 */
871
+	private function _get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
872
+	{
873
+		return $this->checkout->get_cart_for_transaction($transaction);
874
+	}
875
+
876
+
877
+	/**
878
+	 * @param EE_Transaction|null $transaction
879
+	 * @return EE_Cart
880
+	 */
881
+	public function get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
882
+	{
883
+		return $this->checkout->get_cart_for_transaction($transaction);
884
+	}
885
+
886
+
887
+	/**
888
+	 * generates a new EE_Transaction object and adds it to the $_transaction property.
889
+	 *
890
+	 * @return EE_Transaction|null
891
+	 * @throws EE_Error
892
+	 * @throws ReflectionException
893
+	 */
894
+	private function _get_cart_for_current_session_and_setup_new_transaction(): ?EE_Transaction
895
+	{
896
+		//  if there's no transaction, then this is the FIRST visit to SPCO
897
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
898
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
899
+		// and then create a new transaction
900
+		$transaction = $this->_initialize_transaction();
901
+		// verify transaction
902
+		if ($transaction instanceof EE_Transaction) {
903
+			// and save TXN data to the cart
904
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
905
+		} else {
906
+			EE_Error::add_error(
907
+				esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
908
+				__FILE__,
909
+				__FUNCTION__,
910
+				__LINE__
911
+			);
912
+		}
913
+		return $transaction;
914
+	}
915
+
916
+
917
+	/**
918
+	 * generates a new EE_Transaction object and adds it to the $_transaction property.
919
+	 *
920
+	 * @return EE_Transaction|null
921
+	 */
922
+	private function _initialize_transaction(): ?EE_Transaction
923
+	{
924
+		try {
925
+			// ensure cart totals have been calculated
926
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
927
+			// grab the cart grand total
928
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
929
+			// create new TXN
930
+			$transaction = EE_Transaction::new_instance(
931
+				[
932
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
933
+					'TXN_total'     => max($cart_total, 0),
934
+					'TXN_paid'      => 0,
935
+					'STS_ID'        => EEM_Transaction::failed_status_code,
936
+				]
937
+			);
938
+			// save it so that we have an ID for other objects to use
939
+			$transaction->save();
940
+			// set cron job for following up on TXNs after their session has expired
941
+			EE_Cron_Tasks::schedule_expired_transaction_check(
942
+				EE_Registry::instance()->SSN->expiration() + 1,
943
+				$transaction->ID()
944
+			);
945
+			return $transaction;
946
+		} catch (Exception $e) {
947
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
948
+		}
949
+		return null;
950
+	}
951
+
952
+
953
+	/**
954
+	 * _get_registrations
955
+	 *
956
+	 * @param EE_Transaction $transaction
957
+	 * @return void
958
+	 * @throws EE_Error
959
+	 * @throws ReflectionException
960
+	 */
961
+	private function _get_registrations(EE_Transaction $transaction)
962
+	{
963
+		// first step: grab the registrants  { : o
964
+		$registrations                      = $transaction->registrations($this->checkout->reg_cache_where_params);
965
+		$this->checkout->total_ticket_count = count($registrations);
966
+		// verify registrations have been set
967
+		if (empty($registrations)) {
968
+			// if no cached registrations, then check the db
969
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params);
970
+			// still nothing ? well as long as this isn't a revisit
971
+			if (empty($registrations) && ! $this->checkout->revisit) {
972
+				// generate new registrations from scratch
973
+				$registrations = $this->_initialize_registrations($transaction);
974
+			}
975
+		}
976
+		// sort by their original registration order
977
+		usort($registrations, ['EED_Single_Page_Checkout', 'sort_registrations_by_REG_count']);
978
+		// then loop thru the array
979
+		foreach ($registrations as $registration) {
980
+			// verify each registration
981
+			if ($registration instanceof EE_Registration) {
982
+				// we display all attendee info for the primary registrant
983
+				if (
984
+					$this->checkout->reg_url_link === $registration->reg_url_link()
985
+					&& $registration->is_primary_registrant()
986
+				) {
987
+					$this->checkout->primary_revisit = true;
988
+					break;
989
+				}
990
+				if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
991
+					// but hide info if it doesn't belong to you
992
+					$transaction->clear_cache('Registration', $registration->ID());
993
+					$this->checkout->total_ticket_count--;
994
+				}
995
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
996
+			}
997
+		}
998
+	}
999
+
1000
+
1001
+	/**
1002
+	 * adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1003
+	 *
1004
+	 * @param EE_Transaction $transaction
1005
+	 * @return array
1006
+	 * @throws EE_Error
1007
+	 * @throws ReflectionException
1008
+	 */
1009
+	private function _initialize_registrations(EE_Transaction $transaction): array
1010
+	{
1011
+		$att_nmbr      = 0;
1012
+		$registrations = [];
1013
+		/** @type EE_Registration_Processor $registration_processor */
1014
+		$registration_processor             = EE_Registry::instance()->load_class('Registration_Processor');
1015
+		$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1016
+		// now let's add the cart items to the $transaction
1017
+		foreach ($this->checkout->cart->get_tickets() as $line_item) {
1018
+			// do the following for each ticket of this type they selected
1019
+			for ($x = 1; $x <= $line_item->quantity(); $x++) {
1020
+				$att_nmbr++;
1021
+				/** @var CreateRegistrationCommand $CreateRegistrationCommand */
1022
+				$CreateRegistrationCommand = EE_Registry::instance()->create(
1023
+					CreateRegistrationCommand::class,
1024
+					[
1025
+						$transaction,
1026
+						$line_item,
1027
+						$att_nmbr,
1028
+						$this->checkout->total_ticket_count,
1029
+					]
1030
+				);
1031
+				// override capabilities for frontend registrations
1032
+				if ($this->request->isFrontend()) {
1033
+					$CreateRegistrationCommand->setCapCheck(
1034
+						new PublicCapabilities('', 'create_new_registration')
1035
+					);
1036
+				}
1037
+				$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1038
+				if (! $registration instanceof EE_Registration) {
1039
+					throw new InvalidEntityException($registration, 'EE_Registration');
1040
+				}
1041
+				$registrations[ $registration->ID() ] = $registration;
1042
+			}
1043
+		}
1044
+		$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1045
+		return $registrations;
1046
+	}
1047
+
1048
+
1049
+	/**
1050
+	 * @param EE_Registration $reg_A
1051
+	 * @param EE_Registration $reg_B
1052
+	 * @return int
1053
+	 * @throws EE_Error
1054
+	 * @throws ReflectionException
1055
+	 */
1056
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B): int
1057
+	{
1058
+		// this shouldn't ever happen within the same TXN, but oh well
1059
+		if ($reg_A->count() === $reg_B->count()) {
1060
+			return 0;
1061
+		}
1062
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * just makes sure that everything is set up correctly before proceeding
1068
+	 *
1069
+	 * @return bool
1070
+	 * @throws EE_Error
1071
+	 * @throws ReflectionException
1072
+	 */
1073
+	private function _final_verifications(): bool
1074
+	{
1075
+		// filter checkout
1076
+		$this->checkout = apply_filters(
1077
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1078
+			$this->checkout
1079
+		);
1080
+		// verify that current step is still set correctly
1081
+		if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1082
+			EE_Error::add_error(
1083
+				esc_html__(
1084
+					'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1085
+					'event_espresso'
1086
+				),
1087
+				__FILE__,
1088
+				__FUNCTION__,
1089
+				__LINE__
1090
+			);
1091
+			return false;
1092
+		}
1093
+		// if returning to SPCO, then verify that primary registrant is set
1094
+		if (! empty($this->checkout->reg_url_link)) {
1095
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1096
+			if (! $valid_registrant instanceof EE_Registration) {
1097
+				EE_Error::add_error(
1098
+					esc_html__(
1099
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1100
+						'event_espresso'
1101
+					),
1102
+					__FILE__,
1103
+					__FUNCTION__,
1104
+					__LINE__
1105
+				);
1106
+				return false;
1107
+			}
1108
+			$valid_registrant = null;
1109
+			foreach (
1110
+				$this->checkout->transaction->registrations(
1111
+					$this->checkout->reg_cache_where_params
1112
+				) as $registration
1113
+			) {
1114
+				if (
1115
+					$registration instanceof EE_Registration
1116
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1117
+				) {
1118
+					$valid_registrant = $registration;
1119
+				}
1120
+			}
1121
+			if (! $valid_registrant instanceof EE_Registration) {
1122
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1123
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1124
+					// clear the session, mark the checkout as unverified, and try again
1125
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1126
+					EED_Single_Page_Checkout::$_initialized       = false;
1127
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1128
+					$this->_initialize();
1129
+					EE_Error::reset_notices();
1130
+					return false;
1131
+				}
1132
+				EE_Error::add_error(
1133
+					esc_html__(
1134
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1135
+						'event_espresso'
1136
+					),
1137
+					__FILE__,
1138
+					__FUNCTION__,
1139
+					__LINE__
1140
+				);
1141
+				return false;
1142
+			}
1143
+		}
1144
+		// now that things have been kinda sufficiently verified,
1145
+		// let's add the checkout to the session so that it's available to other systems
1146
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1147
+		return true;
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1153
+	 * then loops thru all the active reg steps and calls the initialize_reg_step() method
1154
+	 *
1155
+	 * @param bool $reinitializing
1156
+	 * @throws EE_Error
1157
+	 */
1158
+	private function _initialize_reg_steps(bool $reinitializing = false)
1159
+	{
1160
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1161
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1162
+		foreach ($this->checkout->reg_steps as $reg_step) {
1163
+			if (! $reg_step->initialize_reg_step()) {
1164
+				// if not initialized then maybe this step is being removed...
1165
+				if (! $reinitializing && $reg_step->is_current_step()) {
1166
+					// if it was the current step, then we need to start over here
1167
+					$this->_initialize_reg_steps(true);
1168
+					return;
1169
+				}
1170
+				continue;
1171
+			}
1172
+			// add css and JS for current step
1173
+			$this->add_styles_and_scripts($reg_step);
1174
+			if ($reg_step->is_current_step()) {
1175
+				// the text that appears on the reg step form submit button
1176
+				$reg_step->set_submit_button_text();
1177
+			}
1178
+		}
1179
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1180
+		do_action(
1181
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1182
+			$this->checkout->current_step
1183
+		);
1184
+	}
1185
+
1186
+
1187
+	/**
1188
+	 * @return boolean
1189
+	 * @throws EE_Error
1190
+	 * @throws ReflectionException
1191
+	 */
1192
+	private function _check_form_submission(): bool
1193
+	{
1194
+		// does this request require the reg form to be generated ?
1195
+		if ($this->checkout->generate_reg_form) {
1196
+			// ever heard that song by Blue Rodeo ?
1197
+			try {
1198
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1199
+				// if not displaying a form, then check for form submission
1200
+				if (
1201
+					$this->checkout->process_form_submission
1202
+					&& $this->checkout->current_step->reg_form->was_submitted()
1203
+				) {
1204
+					// clear out any old data in case this step is being run again
1205
+					$this->checkout->current_step->set_valid_data([]);
1206
+					// capture submitted form data
1207
+					$request_data = $this->request->requestParams();
1208
+					$this->checkout->current_step->reg_form->receive_form_submission(
1209
+						(array) apply_filters(
1210
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1211
+							$request_data,
1212
+							$this->checkout
1213
+						)
1214
+					);
1215
+					// validate submitted form data
1216
+					if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1217
+						// thou shall not pass !!!
1218
+						$this->checkout->continue_reg = false;
1219
+						// any form validation errors?
1220
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1221
+							EE_Error::add_error(
1222
+								$this->checkout->current_step->reg_form->submission_error_message(),
1223
+								__FILE__,
1224
+								__FUNCTION__,
1225
+								__LINE__
1226
+							);
1227
+						}
1228
+						// well not really... what will happen is
1229
+						// we'll just get redirected back to redo the current step
1230
+						$this->go_to_next_step();
1231
+						return false;
1232
+					}
1233
+				}
1234
+			} catch (EE_Error $e) {
1235
+				$e->get_error();
1236
+			}
1237
+		}
1238
+		return true;
1239
+	}
1240
+
1241
+
1242
+	/**
1243
+	 * @return void
1244
+	 * @throws EE_Error
1245
+	 * @throws ReflectionException
1246
+	 */
1247
+	private function _process_form_action()
1248
+	{
1249
+		// what cha wanna do?
1250
+		switch ($this->checkout->action) {
1251
+			// AJAX next step reg form
1252
+			case 'display_spco_reg_step':
1253
+				$this->checkout->redirect = false;
1254
+				if ($this->request->isAjax()) {
1255
+					$this->checkout->json_response->set_reg_step_html(
1256
+						$this->checkout->current_step->display_reg_form()
1257
+					);
1258
+				}
1259
+				break;
1260
+			default:
1261
+				// meh... do one of those other steps first
1262
+				if (
1263
+					! empty($this->checkout->action)
1264
+					&& is_callable([$this->checkout->current_step, $this->checkout->action])
1265
+				) {
1266
+					// dynamically creates hook point like:
1267
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1268
+					do_action(
1269
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1270
+						$this->checkout->current_step
1271
+					);
1272
+					$process_reg_step = apply_filters(
1273
+						"AHEE__Single_Page_Checkout__process_reg_step__{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1274
+						true,
1275
+						$this->checkout->current_step,
1276
+						$this
1277
+					);
1278
+					// call action on current step
1279
+					if ($process_reg_step && call_user_func([$this->checkout->current_step, $this->checkout->action])) {
1280
+						// good registrant, you get to proceed
1281
+						if (
1282
+							$this->checkout->current_step->success_message() !== ''
1283
+							&& apply_filters(
1284
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1285
+								false
1286
+							)
1287
+						) {
1288
+							EE_Error::add_success(
1289
+								$this->checkout->current_step->success_message()
1290
+								. '<br />' . $this->checkout->next_step->_instructions()
1291
+							);
1292
+						}
1293
+						// pack it up, pack it in...
1294
+						$this->_setup_redirect();
1295
+					}
1296
+					// dynamically creates hook point like:
1297
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1298
+					do_action(
1299
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1300
+						$this->checkout->current_step
1301
+					);
1302
+				} else {
1303
+					EE_Error::add_error(
1304
+						sprintf(
1305
+							esc_html__(
1306
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1307
+								'event_espresso'
1308
+							),
1309
+							$this->checkout->action,
1310
+							$this->checkout->current_step->name()
1311
+						),
1312
+						__FILE__,
1313
+						__FUNCTION__,
1314
+						__LINE__
1315
+					);
1316
+				}
1317
+			// end default
1318
+		}
1319
+		// store our progress so far
1320
+		$this->checkout->stash_transaction_and_checkout();
1321
+		// advance to the next step! If you pass GO, collect $200
1322
+		$this->go_to_next_step();
1323
+	}
1324
+
1325
+
1326
+	/**
1327
+	 * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target an object with the method `translate_js_strings` and
1328
+	 *                                                          `enqueue_styles_and_scripts`.
1329
+	 * @return void
1330
+	 */
1331
+	public function add_styles_and_scripts($target)
1332
+	{
1333
+		// i18n
1334
+		$target->translate_js_strings();
1335
+		if ($this->checkout->admin_request) {
1336
+			add_action('admin_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1337
+		} else {
1338
+			add_action('wp_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1339
+		}
1340
+	}
1341
+
1342
+
1343
+	/**
1344
+	 * @return void
1345
+	 */
1346
+	public function translate_js_strings()
1347
+	{
1348
+		EE_Registry::$i18n_js_strings['revisit']                        = $this->checkout->revisit;
1349
+		EE_Registry::$i18n_js_strings['e_reg_url_link']                 = $this->checkout->reg_url_link;
1350
+		EE_Registry::$i18n_js_strings['server_error']                   = esc_html__(
1351
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1352
+			'event_espresso'
1353
+		);
1354
+		EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1355
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1356
+			'event_espresso'
1357
+		);
1358
+		EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1359
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1360
+			'event_espresso'
1361
+		);
1362
+		EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1363
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1364
+			'event_espresso'
1365
+		);
1366
+		EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1367
+			'This registration step could not be completed. Please refresh the page and try again.',
1368
+			'event_espresso'
1369
+		);
1370
+		EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1371
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1372
+			'event_espresso'
1373
+		);
1374
+		EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1375
+			esc_html__(
1376
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1377
+				'event_espresso'
1378
+			),
1379
+			'<br/>',
1380
+			'<br/>'
1381
+		);
1382
+		EE_Registry::$i18n_js_strings['language']                       = get_bloginfo('language');
1383
+		EE_Registry::$i18n_js_strings['EESID']                          = EE_Registry::instance()->SSN->id();
1384
+		EE_Registry::$i18n_js_strings['currency']                       = EE_Registry::instance()->CFG->currency;
1385
+		EE_Registry::$i18n_js_strings['datepicker_yearRange']           = '-150:+20';
1386
+		EE_Registry::$i18n_js_strings['timer_years']                    = esc_html__('years', 'event_espresso');
1387
+		EE_Registry::$i18n_js_strings['timer_months']                   = esc_html__('months', 'event_espresso');
1388
+		EE_Registry::$i18n_js_strings['timer_weeks']                    = esc_html__('weeks', 'event_espresso');
1389
+		EE_Registry::$i18n_js_strings['timer_days']                     = esc_html__('days', 'event_espresso');
1390
+		EE_Registry::$i18n_js_strings['timer_hours']                    = esc_html__('hours', 'event_espresso');
1391
+		EE_Registry::$i18n_js_strings['timer_minutes']                  = esc_html__('minutes', 'event_espresso');
1392
+		EE_Registry::$i18n_js_strings['timer_seconds']                  = esc_html__('seconds', 'event_espresso');
1393
+		EE_Registry::$i18n_js_strings['timer_year']                     = esc_html__('year', 'event_espresso');
1394
+		EE_Registry::$i18n_js_strings['timer_month']                    = esc_html__('month', 'event_espresso');
1395
+		EE_Registry::$i18n_js_strings['timer_week']                     = esc_html__('week', 'event_espresso');
1396
+		EE_Registry::$i18n_js_strings['timer_day']                      = esc_html__('day', 'event_espresso');
1397
+		EE_Registry::$i18n_js_strings['timer_hour']                     = esc_html__('hour', 'event_espresso');
1398
+		EE_Registry::$i18n_js_strings['timer_minute']                   = esc_html__('minute', 'event_espresso');
1399
+		EE_Registry::$i18n_js_strings['timer_second']                   = esc_html__('second', 'event_espresso');
1400
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
1401
+			EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1402
+		EE_Registry::$i18n_js_strings['ajax_submit']                    = apply_filters(
1403
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1404
+			true
1405
+		);
1406
+		EE_Registry::$i18n_js_strings['session_extension']              = absint(
1407
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1408
+		);
1409
+		EE_Registry::$i18n_js_strings['session_expiration']             = gmdate(
1410
+			'M d, Y H:i:s',
1411
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1412
+		);
1413
+	}
1414
+
1415
+
1416
+	/**
1417
+	 * @return void
1418
+	 * @throws EE_Error
1419
+	 */
1420
+	public function enqueue_styles_and_scripts()
1421
+	{
1422
+		// load css
1423
+		wp_register_style(
1424
+			'single_page_checkout',
1425
+			SPCO_CSS_URL . 'single_page_checkout.css',
1426
+			['espresso_default'],
1427
+			EVENT_ESPRESSO_VERSION
1428
+		);
1429
+		wp_enqueue_style('single_page_checkout');
1430
+		// load JS
1431
+		wp_register_script(
1432
+			'jquery_plugin',
1433
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1434
+			['jquery'],
1435
+			'1.0.1',
1436
+			true
1437
+		);
1438
+		wp_register_script(
1439
+			'jquery_countdown',
1440
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1441
+			['jquery_plugin'],
1442
+			'2.1.0',
1443
+			true
1444
+		);
1445
+		wp_register_script(
1446
+			'single_page_checkout',
1447
+			SPCO_JS_URL . 'single_page_checkout.js',
1448
+			['espresso_core', 'underscore', 'ee_form_section_validation'],
1449
+			EVENT_ESPRESSO_VERSION,
1450
+			true
1451
+		);
1452
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1453
+			$this->checkout->registration_form->enqueue_js();
1454
+		}
1455
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1456
+			$this->checkout->current_step->reg_form->enqueue_js();
1457
+		}
1458
+		wp_enqueue_script('single_page_checkout');
1459
+		if (apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)) {
1460
+			wp_enqueue_script('jquery_countdown');
1461
+		}
1462
+		/**
1463
+		 * global action hook for enqueueing styles and scripts with
1464
+		 * spco calls.
1465
+		 */
1466
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1467
+		/**
1468
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1469
+		 * The hook will end up being something like:
1470
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1471
+		 */
1472
+		do_action(
1473
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1474
+			$this
1475
+		);
1476
+	}
1477
+
1478
+
1479
+	/**
1480
+	 * display the Registration Single Page Checkout Form
1481
+	 *
1482
+	 * @return void
1483
+	 * @throws EE_Error
1484
+	 * @throws ReflectionException
1485
+	 */
1486
+	private function _display_spco_reg_form()
1487
+	{
1488
+		// if registering via the admin, just display the reg form for the current step
1489
+		if ($this->checkout->admin_request) {
1490
+			EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->current_step->display_reg_form());
1491
+		} else {
1492
+			// add powered by EE msg
1493
+			add_action('AHEE__SPCO__reg_form_footer', ['EED_Single_Page_Checkout', 'display_registration_footer']);
1494
+			$empty_cart                                 = count(
1495
+					$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1496
+				) < 1;
1497
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1498
+			$cookies_not_set_msg                        = '';
1499
+			if ($empty_cart) {
1500
+				$cookies_not_set_msg = apply_filters(
1501
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1502
+					sprintf(
1503
+						esc_html__(
1504
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1505
+							'event_espresso'
1506
+						),
1507
+						'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1508
+						'</div>',
1509
+						'<h6 class="important-notice">',
1510
+						'</h6>',
1511
+						'<p>',
1512
+						'</p>',
1513
+						'<br />',
1514
+						'<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
1515
+						'</a>'
1516
+					)
1517
+				);
1518
+			}
1519
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1520
+				[
1521
+					'name'            => 'single-page-checkout',
1522
+					'html_id'         => 'ee-single-page-checkout-dv',
1523
+					'layout_strategy' =>
1524
+						new EE_Template_Layout(
1525
+							[
1526
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1527
+								'template_args'        => [
1528
+									'empty_cart'              => $empty_cart,
1529
+									'revisit'                 => $this->checkout->revisit,
1530
+									'reg_steps'               => $this->checkout->reg_steps,
1531
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1532
+										? $this->checkout->next_step->slug()
1533
+										: '',
1534
+									'empty_msg'               => apply_filters(
1535
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1536
+										sprintf(
1537
+											esc_html__(
1538
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1539
+												'event_espresso'
1540
+											),
1541
+											'<a href="'
1542
+											. get_post_type_archive_link(EspressoPostType::EVENTS)
1543
+											. '" title="',
1544
+											'">',
1545
+											'</a>'
1546
+										)
1547
+									),
1548
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1549
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1550
+									'session_expiration'      => gmdate(
1551
+										'M d, Y H:i:s',
1552
+										EE_Registry::instance()->SSN->expiration()
1553
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1554
+									),
1555
+								],
1556
+							]
1557
+						),
1558
+				]
1559
+			);
1560
+			// load template and add to output sent that gets filtered into the_content()
1561
+			EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->registration_form->get_html());
1562
+		}
1563
+	}
1564
+
1565
+
1566
+	/**
1567
+	 * @param $next_step
1568
+	 * @return void
1569
+	 */
1570
+	public function add_extra_finalize_registration_inputs($next_step)
1571
+	{
1572
+		if ($next_step === 'finalize_registration') {
1573
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1574
+		}
1575
+	}
1576
+
1577
+
1578
+	/**
1579
+	 * @return void
1580
+	 */
1581
+	public static function display_registration_footer()
1582
+	{
1583
+		if (
1584
+			apply_filters(
1585
+				'FHEE__EE_Front__Controller__show_reg_footer',
1586
+				EE_Registry::instance()->CFG->admin->show_reg_footer
1587
+			)
1588
+		) {
1589
+			add_filter(
1590
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1591
+				function ($url) {
1592
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1593
+				}
1594
+			);
1595
+			echo apply_filters(
1596
+				'FHEE__EE_Front_Controller__display_registration_footer',
1597
+				EEH_Template::powered_by_event_espresso(
1598
+					'',
1599
+					'espresso-registration-footer-dv',
1600
+					['utm_content' => 'registration_checkout']
1601
+				)
1602
+			);
1603
+		}
1604
+	}
1605
+
1606
+
1607
+	/**
1608
+	 * @return void
1609
+	 * @throws EE_Error
1610
+	 * @throws ReflectionException
1611
+	 */
1612
+	public function unlock_transaction()
1613
+	{
1614
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1615
+			$this->checkout->transaction->unlock();
1616
+		}
1617
+	}
1618
+
1619
+
1620
+	/**
1621
+	 * @return void
1622
+	 */
1623
+	private function _setup_redirect()
1624
+	{
1625
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1626
+			$this->checkout->redirect = true;
1627
+			if (empty($this->checkout->redirect_url)) {
1628
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1629
+			}
1630
+			$this->checkout->redirect_url = apply_filters(
1631
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1632
+				$this->checkout->redirect_url,
1633
+				$this->checkout
1634
+			);
1635
+		}
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 * handle ajax message responses and redirects
1641
+	 *
1642
+	 * @return void
1643
+	 * @throws EE_Error
1644
+	 * @throws ReflectionException
1645
+	 */
1646
+	public function go_to_next_step()
1647
+	{
1648
+		if ($this->request->isAjax()) {
1649
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1650
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1651
+		}
1652
+		$this->unlock_transaction();
1653
+		// just return for these conditions
1654
+		if (
1655
+			$this->checkout->admin_request
1656
+			|| $this->checkout->action === 'redirect_form'
1657
+			|| $this->checkout->action === 'update_checkout'
1658
+		) {
1659
+			return;
1660
+		}
1661
+		// AJAX response
1662
+		$this->_handle_json_response();
1663
+		// redirect to next step or the Thank-You page
1664
+		$this->_handle_html_redirects();
1665
+		// hmmm... must be something wrong, so let's just display the form again !
1666
+		$this->_display_spco_reg_form();
1667
+	}
1668
+
1669
+
1670
+	/**
1671
+	 * @return void
1672
+	 * @throws EE_Error
1673
+	 */
1674
+	protected function _handle_json_response()
1675
+	{
1676
+		// if this is an ajax request
1677
+		if ($this->request->isAjax()) {
1678
+			$this->checkout->json_response->set_registration_time_limit(
1679
+				$this->checkout->get_registration_time_limit()
1680
+			);
1681
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1682
+			// just send the ajax (
1683
+			$json_response = apply_filters(
1684
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1685
+				$this->checkout->json_response
1686
+			);
1687
+			exit($json_response);
1688
+		}
1689
+	}
1690
+
1691
+
1692
+	/**
1693
+	 * @return void
1694
+	 */
1695
+	protected function _handle_html_redirects()
1696
+	{
1697
+		// going somewhere ?
1698
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1699
+			// store notices in a transient
1700
+			EE_Error::get_notices(false, true);
1701
+			wp_safe_redirect($this->checkout->redirect_url);
1702
+			exit();
1703
+		}
1704
+	}
1705
+
1706
+
1707
+	/**
1708
+	 * @return void
1709
+	 */
1710
+	public function set_checkout_anchor()
1711
+	{
1712
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1713
+	}
1714
+
1715
+
1716
+	/**
1717
+	 * @return string
1718
+	 * @since 4.9.59.p
1719
+	 */
1720
+	public static function getRegistrationExpirationNotice(): string
1721
+	{
1722
+		return sprintf(
1723
+			esc_html__(
1724
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1725
+				'event_espresso'
1726
+			),
1727
+			'<h4 class="important-notice">',
1728
+			'</h4>',
1729
+			'<br />',
1730
+			'<p>',
1731
+			'<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" title="',
1732
+			'">',
1733
+			'</a>',
1734
+			'</p>'
1735
+		);
1736
+	}
1737 1737
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
 
46 46
     protected ?RequestInterface $request = null;
47 47
 
48
-    private bool $debug = false;    //  true    false
48
+    private bool $debug = false; //  true    false
49 49
 
50 50
 
51 51
     /**
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
     public static function set_hooks_admin()
110 110
     {
111 111
         EED_Single_Page_Checkout::set_definitions();
112
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
112
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
113 113
             return;
114 114
         }
115 115
         // going to start an output buffer in case anything gets accidentally output
@@ -203,14 +203,14 @@  discard block
 block discarded – undo
203 203
         }
204 204
         define(
205 205
             'SPCO_BASE_PATH',
206
-            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
206
+            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/').'/'
207 207
         );
208
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
209
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
210
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
211
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
212
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
213
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
208
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css/');
209
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img/');
210
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js/');
211
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc/');
212
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps/');
213
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates/');
214 214
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
215 215
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
216 216
             EED_Single_Page_Checkout::getRegistrationExpirationNotice();
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
             // we need a
242 242
             if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
243 243
                 // copy over to the reg_steps_array
244
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
244
+                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
245 245
                 // register custom key route for each reg step
246 246
                 // ie: step=>"slug" - this is the entire reason we load the reg steps array now
247 247
                 EE_Config::register_route(
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
                 // add AJAX or other hooks
254 254
                 if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
255 255
                     // setup autoloaders if necessary
256
-                    if (! class_exists($reg_step['class_name'])) {
256
+                    if ( ! class_exists($reg_step['class_name'])) {
257 257
                         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
258 258
                             $reg_step['file_path'],
259 259
                             true
@@ -280,19 +280,19 @@  discard block
 block discarded – undo
280 280
         if (empty($reg_steps)) {
281 281
             $reg_steps = [
282 282
                 10  => [
283
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
283
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
284 284
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
285 285
                     'slug'       => 'attendee_information',
286 286
                     'has_hooks'  => false,
287 287
                 ],
288 288
                 30  => [
289
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
289
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
290 290
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
291 291
                     'slug'       => 'payment_options',
292 292
                     'has_hooks'  => true,
293 293
                 ],
294 294
                 999 => [
295
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
295
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
296 296
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
297 297
                     'slug'       => 'finalize_registration',
298 298
                     'has_hooks'  => false,
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
                 $this->checkout
439 439
             );
440 440
             // load the reg steps array
441
-            if (! $this->_load_and_instantiate_reg_steps()) {
441
+            if ( ! $this->_load_and_instantiate_reg_steps()) {
442 442
                 EED_Single_Page_Checkout::$_initialized = true;
443 443
                 return;
444 444
             }
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
             // and the next step
448 448
             $this->checkout->set_next_step();
449 449
             // verify that everything has been set up correctly
450
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
450
+            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
451 451
                 EED_Single_Page_Checkout::$_initialized = true;
452 452
                 return;
453 453
             }
@@ -463,7 +463,7 @@  discard block
 block discarded – undo
463 463
             // DEBUG LOG
464 464
             // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
465 465
             // get reg form
466
-            if (! $this->_check_form_submission()) {
466
+            if ( ! $this->_check_form_submission()) {
467 467
                 EED_Single_Page_Checkout::$_initialized = true;
468 468
                 return;
469 469
             }
@@ -493,7 +493,7 @@  discard block
 block discarded – undo
493 493
      */
494 494
     private function _verify_session()
495 495
     {
496
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
496
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
497 497
             throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
498 498
         }
499 499
         $clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
             // EE_Registry::instance()->SSN->reset_cart();
511 511
             // EE_Registry::instance()->SSN->reset_checkout();
512 512
             // EE_Registry::instance()->SSN->reset_transaction();
513
-            if (! $clear_session_requested) {
513
+            if ( ! $clear_session_requested) {
514 514
                 EE_Error::add_attention(
515 515
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
516 516
                     __FILE__,
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
         /** @type EE_Checkout $checkout */
537 537
         $checkout = EE_Registry::instance()->SSN->checkout();
538 538
         // verify
539
-        if (! $checkout instanceof EE_Checkout) {
539
+        if ( ! $checkout instanceof EE_Checkout) {
540 540
             // instantiate EE_Checkout object for handling the properties of the current checkout process
541 541
             $checkout = EE_Registry::instance()->load_file(
542 542
                 SPCO_INC_PATH,
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
         }
555 555
         $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
556 556
         // verify again
557
-        if (! $checkout instanceof EE_Checkout) {
557
+        if ( ! $checkout instanceof EE_Checkout) {
558 558
             throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
559 559
         }
560 560
         // reset anything that needs a clean slate for each request
@@ -611,7 +611,7 @@  discard block
 block discarded – undo
611 611
      */
612 612
     protected function _display_request_vars()
613 613
     {
614
-        if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
614
+        if ( ! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
615 615
             return;
616 616
         }
617 617
         EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
@@ -683,7 +683,7 @@  discard block
 block discarded – undo
683 683
         ) {
684 684
             // if not, then loop through raw reg steps array
685 685
             foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
686
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
686
+                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
687 687
                     return false;
688 688
                 }
689 689
             }
@@ -805,12 +805,12 @@  discard block
 block discarded – undo
805 805
     private function _verify_transaction_and_get_registrations(): bool
806 806
     {
807 807
         // was there already a valid transaction in the checkout from the session ?
808
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
808
+        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
809 809
             // get transaction from db or session
810 810
             $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
811 811
                 ? $this->_get_transaction_and_cart_for_previous_visit()
812 812
                 : $this->_get_cart_for_current_session_and_setup_new_transaction();
813
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
813
+            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
814 814
                 EE_Error::add_error(
815 815
                     esc_html__(
816 816
                         'Your Registration and Transaction information could not be retrieved from the db.',
@@ -1035,10 +1035,10 @@  discard block
 block discarded – undo
1035 1035
                     );
1036 1036
                 }
1037 1037
                 $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1038
-                if (! $registration instanceof EE_Registration) {
1038
+                if ( ! $registration instanceof EE_Registration) {
1039 1039
                     throw new InvalidEntityException($registration, 'EE_Registration');
1040 1040
                 }
1041
-                $registrations[ $registration->ID() ] = $registration;
1041
+                $registrations[$registration->ID()] = $registration;
1042 1042
             }
1043 1043
         }
1044 1044
         $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1078,7 +1078,7 @@  discard block
 block discarded – undo
1078 1078
             $this->checkout
1079 1079
         );
1080 1080
         // verify that current step is still set correctly
1081
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1081
+        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1082 1082
             EE_Error::add_error(
1083 1083
                 esc_html__(
1084 1084
                     'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
@@ -1091,9 +1091,9 @@  discard block
 block discarded – undo
1091 1091
             return false;
1092 1092
         }
1093 1093
         // if returning to SPCO, then verify that primary registrant is set
1094
-        if (! empty($this->checkout->reg_url_link)) {
1094
+        if ( ! empty($this->checkout->reg_url_link)) {
1095 1095
             $valid_registrant = $this->checkout->transaction->primary_registration();
1096
-            if (! $valid_registrant instanceof EE_Registration) {
1096
+            if ( ! $valid_registrant instanceof EE_Registration) {
1097 1097
                 EE_Error::add_error(
1098 1098
                     esc_html__(
1099 1099
                         'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
@@ -1118,7 +1118,7 @@  discard block
 block discarded – undo
1118 1118
                     $valid_registrant = $registration;
1119 1119
                 }
1120 1120
             }
1121
-            if (! $valid_registrant instanceof EE_Registration) {
1121
+            if ( ! $valid_registrant instanceof EE_Registration) {
1122 1122
                 // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1123 1123
                 if (EED_Single_Page_Checkout::$_checkout_verified) {
1124 1124
                     // clear the session, mark the checkout as unverified, and try again
@@ -1160,9 +1160,9 @@  discard block
 block discarded – undo
1160 1160
         $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1161 1161
         // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1162 1162
         foreach ($this->checkout->reg_steps as $reg_step) {
1163
-            if (! $reg_step->initialize_reg_step()) {
1163
+            if ( ! $reg_step->initialize_reg_step()) {
1164 1164
                 // if not initialized then maybe this step is being removed...
1165
-                if (! $reinitializing && $reg_step->is_current_step()) {
1165
+                if ( ! $reinitializing && $reg_step->is_current_step()) {
1166 1166
                     // if it was the current step, then we need to start over here
1167 1167
                     $this->_initialize_reg_steps(true);
1168 1168
                     return;
@@ -1213,7 +1213,7 @@  discard block
 block discarded – undo
1213 1213
                         )
1214 1214
                     );
1215 1215
                     // validate submitted form data
1216
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1216
+                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1217 1217
                         // thou shall not pass !!!
1218 1218
                         $this->checkout->continue_reg = false;
1219 1219
                         // any form validation errors?
@@ -1287,7 +1287,7 @@  discard block
 block discarded – undo
1287 1287
                         ) {
1288 1288
                             EE_Error::add_success(
1289 1289
                                 $this->checkout->current_step->success_message()
1290
-                                . '<br />' . $this->checkout->next_step->_instructions()
1290
+                                . '<br />'.$this->checkout->next_step->_instructions()
1291 1291
                             );
1292 1292
                         }
1293 1293
                         // pack it up, pack it in...
@@ -1351,27 +1351,27 @@  discard block
 block discarded – undo
1351 1351
             'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1352 1352
             'event_espresso'
1353 1353
         );
1354
-        EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1354
+        EE_Registry::$i18n_js_strings['invalid_json_response'] = esc_html__(
1355 1355
             'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1356 1356
             'event_espresso'
1357 1357
         );
1358
-        EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1358
+        EE_Registry::$i18n_js_strings['validation_error'] = esc_html__(
1359 1359
             'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1360 1360
             'event_espresso'
1361 1361
         );
1362
-        EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1362
+        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
1363 1363
             'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1364 1364
             'event_espresso'
1365 1365
         );
1366
-        EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1366
+        EE_Registry::$i18n_js_strings['reg_step_error'] = esc_html__(
1367 1367
             'This registration step could not be completed. Please refresh the page and try again.',
1368 1368
             'event_espresso'
1369 1369
         );
1370
-        EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1370
+        EE_Registry::$i18n_js_strings['invalid_coupon'] = esc_html__(
1371 1371
             'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1372 1372
             'event_espresso'
1373 1373
         );
1374
-        EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1374
+        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1375 1375
             esc_html__(
1376 1376
                 'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1377 1377
                 'event_espresso'
@@ -1422,7 +1422,7 @@  discard block
 block discarded – undo
1422 1422
         // load css
1423 1423
         wp_register_style(
1424 1424
             'single_page_checkout',
1425
-            SPCO_CSS_URL . 'single_page_checkout.css',
1425
+            SPCO_CSS_URL.'single_page_checkout.css',
1426 1426
             ['espresso_default'],
1427 1427
             EVENT_ESPRESSO_VERSION
1428 1428
         );
@@ -1430,21 +1430,21 @@  discard block
 block discarded – undo
1430 1430
         // load JS
1431 1431
         wp_register_script(
1432 1432
             'jquery_plugin',
1433
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1433
+            EE_THIRD_PARTY_URL.'jquery	.plugin.min.js',
1434 1434
             ['jquery'],
1435 1435
             '1.0.1',
1436 1436
             true
1437 1437
         );
1438 1438
         wp_register_script(
1439 1439
             'jquery_countdown',
1440
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1440
+            EE_THIRD_PARTY_URL.'jquery	.countdown.min.js',
1441 1441
             ['jquery_plugin'],
1442 1442
             '2.1.0',
1443 1443
             true
1444 1444
         );
1445 1445
         wp_register_script(
1446 1446
             'single_page_checkout',
1447
-            SPCO_JS_URL . 'single_page_checkout.js',
1447
+            SPCO_JS_URL.'single_page_checkout.js',
1448 1448
             ['espresso_core', 'underscore', 'ee_form_section_validation'],
1449 1449
             EVENT_ESPRESSO_VERSION,
1450 1450
             true
@@ -1470,7 +1470,7 @@  discard block
 block discarded – undo
1470 1470
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1471 1471
          */
1472 1472
         do_action(
1473
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1473
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1474 1474
             $this
1475 1475
         );
1476 1476
     }
@@ -1523,7 +1523,7 @@  discard block
 block discarded – undo
1523 1523
                     'layout_strategy' =>
1524 1524
                         new EE_Template_Layout(
1525 1525
                             [
1526
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1526
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1527 1527
                                 'template_args'        => [
1528 1528
                                     'empty_cart'              => $empty_cart,
1529 1529
                                     'revisit'                 => $this->checkout->revisit,
@@ -1588,7 +1588,7 @@  discard block
 block discarded – undo
1588 1588
         ) {
1589 1589
             add_filter(
1590 1590
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1591
-                function ($url) {
1591
+                function($url) {
1592 1592
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1593 1593
                 }
1594 1594
             );
@@ -1728,7 +1728,7 @@  discard block
 block discarded – undo
1728 1728
             '</h4>',
1729 1729
             '<br />',
1730 1730
             '<p>',
1731
-            '<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" title="',
1731
+            '<a href="'.get_post_type_archive_link(EspressoPostType::EVENTS).'" title="',
1732 1732
             '">',
1733 1733
             '</a>',
1734 1734
             '</p>'
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 2 patches
Indentation   +858 added lines, -858 removed lines patch added patch discarded remove patch
@@ -23,862 +23,862 @@
 block discarded – undo
23 23
  */
24 24
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step
25 25
 {
26
-    /**
27
-     * @var RegForm
28
-     */
29
-    public $reg_form;
30
-
31
-    /**
32
-     * @var int
33
-     */
34
-    protected $reg_form_count = 0;
35
-
36
-
37
-    /**
38
-     *    class constructor
39
-     *
40
-     * @access    public
41
-     * @param EE_Checkout $checkout
42
-     */
43
-    public function __construct(EE_Checkout $checkout)
44
-    {
45
-        $this->_slug    = 'attendee_information';
46
-        $this->_name    = esc_html__('Attendee Information', 'event_espresso');
47
-        $this->checkout = $checkout;
48
-        $this->_reset_success_message();
49
-        $this->set_instructions(
50
-            esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
51
-        );
52
-    }
53
-
54
-
55
-    public function translate_js_strings()
56
-    {
57
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
58
-            ' is a required question.',
59
-            'event_espresso'
60
-        );
61
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
62
-            ' is a required question. Please enter a value for at least one of the options.',
63
-            'event_espresso'
64
-        );
65
-        EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
66
-            'Please answer all required questions correctly before proceeding.',
67
-            'event_espresso'
68
-        );
69
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
70
-            esc_html_x(
71
-                'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
72
-                'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
73
-                'event_espresso'
74
-            ),
75
-            '<br/>'
76
-        );
77
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
78
-            'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
79
-            'event_espresso'
80
-        );
81
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
82
-            'You must enter a valid email address.',
83
-            'event_espresso'
84
-        );
85
-        EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
86
-            'You must enter a valid email address and answer all other required questions before you can proceed.',
87
-            'event_espresso'
88
-        );
89
-    }
90
-
91
-
92
-    public function enqueue_styles_and_scripts()
93
-    {
94
-    }
95
-
96
-
97
-    /**
98
-     * @return boolean
99
-     */
100
-    public function initialize_reg_step(): bool
101
-    {
102
-        return true;
103
-    }
104
-
105
-
106
-    /**
107
-     * @return RegForm
108
-     * @throws DomainException
109
-     * @throws InvalidArgumentException
110
-     * @throws EntityNotFoundException
111
-     * @throws InvalidDataTypeException
112
-     * @throws InvalidInterfaceException
113
-     */
114
-    public function generate_reg_form(): RegForm
115
-    {
116
-        $this->setLegacyFiltersForRegFormGeneration();
117
-        /** @var RegFormDependencyHandler $dependency_handler */
118
-        $dependency_handler = LoaderFactory::getShared(RegFormDependencyHandler::class);
119
-        $dependency_handler->registerDependencies();
120
-        // TODO detect if event has a reg form UUID and swap this out for form generated by new reg form builder
121
-        return LoaderFactory::getShared(RegForm::class, [$this]);
122
-    }
123
-
124
-
125
-    /**
126
-     * @since   5.0.0.p
127
-     */
128
-    private function setLegacyFiltersForRegFormGeneration()
129
-    {
130
-        add_filter(
131
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_groups_query_parameters',
132
-            [$this, 'registrationQuestionGroupsQueryParameters'],
133
-            1,
134
-            2
135
-        );
136
-        add_filter(
137
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_group_reg_form',
138
-            [$this, 'registrationQuestionGroupsRegForm'],
139
-            1,
140
-            3
141
-        );
142
-        add_filter(
143
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__printCopyInfo',
144
-            [$this, 'registrationRegFormPrintCopyInfo'],
145
-            1,
146
-            2
147
-        );
148
-        add_filter(
149
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__related_questions_query_params',
150
-            [$this, 'registrationRegFormRelatedQuestionsQueryParams'],
151
-            1,
152
-            3
153
-        );
154
-        add_filter(
155
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__before_question_group_questions',
156
-            [$this, 'registrationRegFormBeforeQuestionGroupQuestions'],
157
-            1,
158
-            3
159
-        );
160
-        add_filter(
161
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__subsections_array',
162
-            [$this, 'registrationRegFormSubsections'],
163
-            1,
164
-            3
165
-        );
166
-        add_filter(
167
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__after_question_group_questions',
168
-            [$this, 'registrationRegFormAfterQuestionGroupQuestions'],
169
-            1,
170
-            3
171
-        );
172
-        add_filter(
173
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_AutoCopyAttendeeInfoForm__construct__template_args',
174
-            [$this, 'autoCopyAttendeeInfoTemplateArgs'],
175
-            1
176
-        );
177
-        add_filter(
178
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_CountryOptions__generateLegacyCountryOptions__country_options',
179
-            [$this, 'generateQuestionInputCountryOptions'],
180
-            1,
181
-            4
182
-        );
183
-        add_filter(
184
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_StateOptions__generateLegacyStateOptions__state_options',
185
-            [$this, 'generateQuestionInputStateOptions'],
186
-            1,
187
-            4
188
-        );
189
-    }
190
-
191
-
192
-    /**
193
-     * @param array           $query_params
194
-     * @param EE_Registration $registration
195
-     * @return mixed|void
196
-     * @since   5.0.0.p
197
-     */
198
-    public function registrationQuestionGroupsQueryParameters(
199
-        array $query_params,
200
-        EE_Registration $registration
201
-    ) {
202
-        return apply_filters(
203
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
204
-            $query_params,
205
-            $registration,
206
-            $this
207
-        );
208
-    }
209
-
210
-
211
-    /**
212
-     * @param RegFormQuestionGroup $question_group_reg_form
213
-     * @param EE_Registration      $registration
214
-     * @param EE_Question_Group    $question_group
215
-     * @return mixed|void
216
-     * @since   5.0.0.p
217
-     */
218
-    public function registrationQuestionGroupsRegForm(
219
-        RegFormQuestionGroup $question_group_reg_form,
220
-        EE_Registration $registration,
221
-        EE_Question_Group $question_group
222
-    ) {
223
-        return apply_filters(
224
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
225
-            $question_group_reg_form,
226
-            $registration,
227
-            $question_group,
228
-            $this
229
-        );
230
-    }
231
-
232
-
233
-    /**
234
-     * @param int $print_copy_info
235
-     * @param int $attendee_nmbr
236
-     * @return mixed|void
237
-     * @since   5.0.0.p
238
-     */
239
-    public function registrationRegFormPrintCopyInfo(
240
-        int $print_copy_info,
241
-        int $attendee_nmbr
242
-    ) {
243
-        return apply_filters(
244
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form___printCopyInfo',
245
-            $print_copy_info,
246
-            $attendee_nmbr
247
-        );
248
-    }
249
-
250
-
251
-    /**
252
-     * @param array             $query_params
253
-     * @param EE_Question_Group $question_group
254
-     * @param EE_Registration   $registration
255
-     * @return mixed|void
256
-     * @since   5.0.0.p
257
-     */
258
-    public function registrationRegFormRelatedQuestionsQueryParams(
259
-        array $query_params,
260
-        EE_Question_Group $question_group,
261
-        EE_Registration $registration
262
-    ) {
263
-        return apply_filters(
264
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
265
-            $query_params,
266
-            $question_group,
267
-            $registration,
268
-            $this
269
-        );
270
-    }
271
-
272
-
273
-    /**
274
-     * @param                   $html
275
-     * @param EE_Registration   $registration
276
-     * @param EE_Question_Group $question_group
277
-     * @return mixed|void
278
-     * @since   5.0.0.p
279
-     */
280
-    public function registrationRegFormBeforeQuestionGroupQuestions(
281
-        $html,
282
-        EE_Registration $registration,
283
-        EE_Question_Group $question_group
284
-    ) {
285
-        return apply_filters(
286
-            'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
287
-            $html,
288
-            $registration,
289
-            $question_group,
290
-            $this
291
-        );
292
-    }
293
-
294
-
295
-    /**
296
-     * @param array             $form_subsections
297
-     * @param EE_Registration   $registration
298
-     * @param EE_Question_Group $question_group
299
-     * @return mixed|void
300
-     * @since   5.0.0.p
301
-     */
302
-    public function registrationRegFormSubsections(
303
-        array $form_subsections,
304
-        EE_Registration $registration,
305
-        EE_Question_Group $question_group
306
-    ) {
307
-        return apply_filters(
308
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
309
-            $form_subsections,
310
-            $registration,
311
-            $question_group,
312
-            $this
313
-        );
314
-    }
315
-
316
-
317
-    /**
318
-     * @param                   $html
319
-     * @param EE_Registration   $registration
320
-     * @param EE_Question_Group $question_group
321
-     * @return mixed|void
322
-     * @since   5.0.0.p
323
-     */
324
-    public function registrationRegFormAfterQuestionGroupQuestions(
325
-        $html,
326
-        EE_Registration $registration,
327
-        EE_Question_Group $question_group
328
-    ) {
329
-        return apply_filters(
330
-            'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
331
-            $html,
332
-            $registration,
333
-            $question_group,
334
-            $this
335
-        );
336
-    }
337
-
338
-
339
-    /**
340
-     * @param array $template_args
341
-     * @return mixed|void
342
-     * @since   5.0.0.p
343
-     */
344
-    public function autoCopyAttendeeInfoTemplateArgs(array $template_args = [])
345
-    {
346
-        return apply_filters(
347
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
348
-            $template_args
349
-        );
350
-    }
351
-
352
-
353
-    /**
354
-     * @param array           $country_options
355
-     * @param EE_Registration $registration
356
-     * @param EE_Question     $question
357
-     * @param EE_Answer|null  $answer
358
-     * @return mixed|void
359
-     * @since   5.0.0.p
360
-     */
361
-    public function generateQuestionInputCountryOptions(
362
-        array $country_options,
363
-        EE_Registration $registration,
364
-        EE_Question $question,
365
-        ?EE_Answer $answer
366
-    ) {
367
-        return apply_filters(
368
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
369
-            $country_options,
370
-            $this,
371
-            $registration,
372
-            $question,
373
-            $answer
374
-        );
375
-    }
376
-
377
-
378
-    /**
379
-     * @param array           $state_options
380
-     * @param EE_Registration $registration
381
-     * @param EE_Question     $question
382
-     * @param EE_Answer|null  $answer
383
-     * @return mixed|void
384
-     * @since   5.0.0.p
385
-     */
386
-    public function generateQuestionInputStateOptions(
387
-        array $state_options,
388
-        EE_Registration $registration,
389
-        EE_Question $question,
390
-        ?EE_Answer $answer
391
-    ) {
392
-        return apply_filters(
393
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
394
-            $state_options,
395
-            $this,
396
-            $registration,
397
-            $question,
398
-            $answer
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     * looking for hooks?
405
-     * this method has been replaced by:
406
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::getRegForm()
407
-     *
408
-     * @deprecated   5.0.0.p
409
-     */
410
-    private function _registrations_reg_form()
411
-    {
412
-    }
413
-
414
-
415
-    /**
416
-     * looking for hooks?
417
-     * this method has been replaced by:
418
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalAttendeeRegInfoInput()
419
-     *
420
-     * @deprecated   5.0.0.p
421
-     */
422
-    private function _additional_attendee_reg_info_input()
423
-    {
424
-    }
425
-
426
-
427
-    /**
428
-     * looking for hooks?
429
-     * this method has been replaced by:
430
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupRegForm()
431
-     *
432
-     * @deprecated   5.0.0.p
433
-     */
434
-    private function _question_group_reg_form()
435
-    {
436
-    }
437
-
438
-
439
-    /**
440
-     * looking for hooks?
441
-     * this method has been replaced by:
442
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupHeader()
443
-     *
444
-     * @deprecated   5.0.0.p
445
-     */
446
-    private function _question_group_header()
447
-    {
448
-    }
449
-
450
-
451
-    /**
452
-     * looking for hooks?
453
-     * this method has been replaced by:
454
-     * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
455
-     *
456
-     * @deprecated   5.0.0.p
457
-     */
458
-    private function _copy_attendee_info_form()
459
-    {
460
-    }
461
-
462
-
463
-    /**
464
-     * looking for hooks?
465
-     * this method has been replaced by:
466
-     * EventEspresso\core\domain\services\registration\form\v1\AutoCopyAttendeeInfoForm
467
-     *
468
-     * @deprecated   5.0.0.p
469
-     */
470
-    private function _auto_copy_attendee_info()
471
-    {
472
-    }
473
-
474
-
475
-    /**
476
-     * looking for hooks?
477
-     * this method has been replaced by:
478
-     * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
479
-     *
480
-     * @deprecated   5.0.0.p
481
-     */
482
-    private function _copy_attendee_info_inputs()
483
-    {
484
-    }
485
-
486
-
487
-    /**
488
-     * looking for hooks?
489
-     * this method has been replaced by:
490
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalPrimaryRegistrantInputs()
491
-     *
492
-     * @deprecated   5.0.0.p
493
-     */
494
-    private function _additional_primary_registrant_inputs()
495
-    {
496
-    }
497
-
498
-
499
-    /**
500
-     * looking for hooks?
501
-     * this method has been replaced by:
502
-     * EventEspresso\core\domain\services\registration\form\v1\RegFormQuestionFactory::create()
503
-     *
504
-     * @param EE_Registration $registration
505
-     * @param EE_Question     $question
506
-     * @return EE_Form_Input_Base
507
-     * @throws EE_Error
508
-     * @throws ReflectionException
509
-     * @deprecated   5.0.0.p
510
-     */
511
-    public function reg_form_question(EE_Registration $registration, EE_Question $question): EE_Form_Input_Base
512
-    {
513
-        /** @var RegFormQuestionFactory $reg_form_question_factory */
514
-        $reg_form_question_factory = LoaderFactory::getShared(RegFormQuestionFactory::class);
515
-        return $reg_form_question_factory->create($registration, $question);
516
-    }
517
-
518
-
519
-    /**
520
-     * looking for hooks?
521
-     * this method has been replaced by:
522
-     * EventEspresso\core\domain\services\registration\form\v1\RegForm::generateQuestionInput()
523
-     *
524
-     * @deprecated   5.0.0.p
525
-     */
526
-    private function _generate_question_input()
527
-    {
528
-    }
529
-
530
-
531
-    /**
532
-     * looking for hooks?
533
-     * this method has been replaced by:
534
-     * EventEspresso\core\domain\services\registration\form\v1\CountryOptions::forLegacyFormInput()
535
-     *
536
-     * @param array|null           $countries_list
537
-     * @param EE_Question|null     $question
538
-     * @param EE_Registration|null $registration
539
-     * @param EE_Answer|null       $answer
540
-     * @return array 2d keys are country IDs, values are their names
541
-     * @throws EE_Error
542
-     * @throws ReflectionException
543
-     * @deprecated   5.0.0.p
544
-     */
545
-    public function use_cached_countries_for_form_input(
546
-        array $countries_list = null,
547
-        EE_Question $question = null,
548
-        EE_Registration $registration = null,
549
-        EE_Answer $answer = null
550
-    ): array {
551
-        /** @var CountryOptions $country_options */
552
-        $country_options = LoaderFactory::getShared(CountryOptions::class, [$this->checkout->action]);
553
-        return $country_options->forLegacyFormInput($countries_list, $question, $registration, $answer);
554
-    }
555
-
556
-
557
-    /**
558
-     * looking for hooks?
559
-     * this method has been replaced by:
560
-     * EventEspresso\core\domain\services\registration\form\v1\StateOptions::forLegacyFormInput()
561
-     *
562
-     * @param array|null           $states_list
563
-     * @param EE_Question|null     $question
564
-     * @param EE_Registration|null $registration
565
-     * @param EE_Answer|null       $answer
566
-     * @return array 2d keys are state IDs, values are their names
567
-     * @throws EE_Error
568
-     * @throws ReflectionException
569
-     * @deprecated   5.0.0.p
570
-     */
571
-    public function use_cached_states_for_form_input(
572
-        array $states_list = null,
573
-        EE_Question $question = null,
574
-        EE_Registration $registration = null,
575
-        EE_Answer $answer = null
576
-    ): array {
577
-        /** @var StateOptions $state_options */
578
-        $state_options = LoaderFactory::getShared(StateOptions::class, [$this->checkout->action]);
579
-        return $state_options->forLegacyFormInput($states_list, $question, $registration, $answer);
580
-    }
581
-
582
-
583
-    /********************************************************************************************************/
584
-    /****************************************  PROCESS REG STEP  ****************************************/
585
-    /********************************************************************************************************/
586
-
587
-
588
-    /**
589
-     * @return bool
590
-     * @throws EE_Error
591
-     * @throws InvalidArgumentException
592
-     * @throws ReflectionException
593
-     * @throws RuntimeException
594
-     * @throws InvalidDataTypeException
595
-     * @throws InvalidInterfaceException
596
-     */
597
-    public function process_reg_step(): bool
598
-    {
599
-        $this->setLegacyFiltersForRegFormProcessing();
600
-        // grab validated data from form
601
-        $valid_data = $this->checkout->current_step->valid_data();
602
-        // if we don't have any $valid_data then something went TERRIBLY WRONG !!!
603
-        if (empty($valid_data)) {
604
-            return $this->inValidDataError();
605
-        }
606
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
607
-            return $this->inValidTransactionError();
608
-        }
609
-        // get cached registrations
610
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
611
-        // verify we got the goods
612
-        if (empty($registrations)) {
613
-            return $this->noRegistrationsError();
614
-        }
615
-        /** @var RegFormHandler $reg_form_handler */
616
-        $reg_form_handler = LoaderFactory::getNew(RegFormHandler::class, [$this->checkout]);
617
-        // extract attendee info from form data and save to model objects
618
-        if (! $reg_form_handler->processRegistrations($registrations, $valid_data)) {
619
-            // return immediately if the previous step exited early due to errors
620
-            return false;
621
-        }
622
-        // if first pass thru SPCO,
623
-        // then let's check processed registrations against the total number of tickets in the cart
624
-        $registrations_processed = $reg_form_handler->attendeeCount();
625
-        if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
626
-            return $this->registrationProcessingError($registrations_processed);
627
-        }
628
-        // mark this reg step as completed
629
-        $this->set_completed();
630
-        $this->_set_success_message(
631
-            esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
632
-        );
633
-        // do action in case a plugin wants to do something with the data submitted in step 1.
634
-        // passes EE_Single_Page_Checkout, and it's posted data
635
-        do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
636
-        return true;
637
-    }
638
-
639
-
640
-    /**
641
-     * @since   5.0.0.p
642
-     */
643
-    private function setLegacyFiltersForRegFormProcessing()
644
-    {
645
-        add_filter(
646
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegistrations__bypass',
647
-            [$this, 'preRegistrationProcess'],
648
-            1,
649
-            5
650
-        );
651
-        add_filter(
652
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegFormData__registrant_form_data',
653
-            [$this, 'validDataLineItem'],
654
-            1,
655
-            2
656
-        );
657
-        add_filter(
658
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormInputHandler__saveRegistrationFormInput',
659
-            [$this, 'saveRegistrationFormInput'],
660
-            1,
661
-            4
662
-        );
663
-        add_filter(
664
-            'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantData__ensureCriticalRegistrantDataIsSet',
665
-            [$this, 'mergeAddressDetailsWithCriticalAttendeeDetails'],
666
-            1
667
-        );
668
-    }
669
-
670
-
671
-    /**
672
-     * @param bool            $bypass
673
-     * @param int             $attendee_count
674
-     * @param EE_Registration $registration
675
-     * @param array           $registrations
676
-     * @param array           $reg_form_data
677
-     * @return mixed|void
678
-     * @since   5.0.0.p
679
-     */
680
-    public function preRegistrationProcess(
681
-        bool $bypass,
682
-        int $attendee_count,
683
-        EE_Registration $registration,
684
-        array $registrations,
685
-        array $reg_form_data
686
-    ) {
687
-        return apply_filters(
688
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
689
-            $bypass,
690
-            $attendee_count,
691
-            $registration,
692
-            $registrations,
693
-            $reg_form_data,
694
-            $this
695
-        );
696
-    }
697
-
698
-
699
-    /**
700
-     * @param array           $reg_form_data
701
-     * @param EE_Registration $registration
702
-     * @return mixed|void
703
-     * @since   5.0.0.p
704
-     */
705
-    public function validDataLineItem(array $reg_form_data, EE_Registration $registration)
706
-    {
707
-        return apply_filters(
708
-            'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
709
-            $reg_form_data,
710
-            $registration
711
-        );
712
-    }
713
-
714
-
715
-    /**
716
-     * @param bool            $save
717
-     * @param EE_Registration $registration
718
-     * @param                 $form_input
719
-     * @param                 $input_value
720
-     * @return mixed|void
721
-     * @since   5.0.0.p
722
-     */
723
-    public function saveRegistrationFormInput(bool $save, EE_Registration $registration, $form_input, $input_value)
724
-    {
725
-        return apply_filters(
726
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
727
-            $save,
728
-            $registration,
729
-            $form_input,
730
-            $input_value,
731
-            $this
732
-        );
733
-    }
734
-
735
-
736
-    /**
737
-     * @param bool $merge_data
738
-     * @return mixed|void
739
-     * @since   5.0.0.p
740
-     */
741
-    public function mergeAddressDetailsWithCriticalAttendeeDetails(bool $merge_data)
742
-    {
743
-        return apply_filters(
744
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
745
-            $merge_data
746
-        );
747
-    }
748
-
749
-
750
-    /**
751
-     * @return bool
752
-     * @since   5.0.0.p
753
-     */
754
-    private function inValidDataError(): bool
755
-    {
756
-        EE_Error::add_error(
757
-            esc_html__('No valid question responses were received.', 'event_espresso'),
758
-            __FILE__,
759
-            __FUNCTION__,
760
-            __LINE__
761
-        );
762
-        return false;
763
-    }
764
-
765
-
766
-    /**
767
-     * @return bool
768
-     * @since   5.0.0.p
769
-     */
770
-    private function inValidTransactionError(): bool
771
-    {
772
-        EE_Error::add_error(
773
-            esc_html__(
774
-                'A valid transaction could not be initiated for processing your registrations.',
775
-                'event_espresso'
776
-            ),
777
-            __FILE__,
778
-            __FUNCTION__,
779
-            __LINE__
780
-        );
781
-        return false;
782
-    }
783
-
784
-
785
-    /**
786
-     * @return bool
787
-     * @since   5.0.0.p
788
-     */
789
-    private function noRegistrationsError(): bool
790
-    {
791
-        // combine the old translated string with a new one, in order to not break translations
792
-        $error_message = esc_html__(
793
-            'Your form data could not be applied to any valid registrations.',
794
-            'event_espresso'
795
-        );
796
-        $error_message .= sprintf(
797
-            esc_html_x(
798
-                '%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.',
799
-                '(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
800
-                'event_espresso'
801
-            ),
802
-            '<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" >',
803
-            '</a>',
804
-            '<br />'
805
-        );
806
-        EE_Error::add_error($error_message, __FILE__, __FUNCTION__, __LINE__);
807
-        return false;
808
-    }
809
-
810
-
811
-    /**
812
-     * @param int $registrations_processed
813
-     * @return bool
814
-     * @since   5.0.0.p
815
-     */
816
-    private function registrationProcessingError(int $registrations_processed): bool
817
-    {
818
-        // generate a correctly translated string for all possible singular/plural combinations
819
-        if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
820
-            $error_msg = sprintf(
821
-                esc_html_x(
822
-                    'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
823
-                    'There was 1 ticket in the Event Queue, but 2 registrations were processed',
824
-                    'event_espresso'
825
-                ),
826
-                $this->checkout->total_ticket_count,
827
-                $registrations_processed
828
-            );
829
-        } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
830
-            $error_msg = sprintf(
831
-                esc_html_x(
832
-                    'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
833
-                    'There was a total of 2 tickets in the Event Queue, but only 1 registration was processed',
834
-                    'event_espresso'
835
-                ),
836
-                $this->checkout->total_ticket_count,
837
-                $registrations_processed
838
-            );
839
-        } else {
840
-            $error_msg = sprintf(
841
-                esc_html__(
842
-                    'There was a total of 2 tickets in the Event Queue, but 2 registrations were processed',
843
-                    'event_espresso'
844
-                ),
845
-                $this->checkout->total_ticket_count,
846
-                $registrations_processed
847
-            );
848
-        }
849
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
850
-        return false;
851
-    }
852
-
853
-
854
-    /**
855
-     *    update_reg_step
856
-     *    this is the final step after a user  revisits the site to edit their attendee information
857
-     *    this gets called AFTER the process_reg_step() method above
858
-     *
859
-     * @return bool
860
-     * @throws EE_Error
861
-     * @throws InvalidArgumentException
862
-     * @throws ReflectionException
863
-     * @throws RuntimeException
864
-     * @throws InvalidDataTypeException
865
-     * @throws InvalidInterfaceException
866
-     */
867
-    public function update_reg_step(): bool
868
-    {
869
-        // save everything
870
-        if ($this->process_reg_step()) {
871
-            $this->checkout->redirect     = true;
872
-            $this->checkout->redirect_url = add_query_arg(
873
-                [
874
-                    'e_reg_url_link' => $this->checkout->reg_url_link,
875
-                    'revisit'        => true,
876
-                ],
877
-                $this->checkout->thank_you_page_url
878
-            );
879
-            $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
880
-            return true;
881
-        }
882
-        return false;
883
-    }
26
+	/**
27
+	 * @var RegForm
28
+	 */
29
+	public $reg_form;
30
+
31
+	/**
32
+	 * @var int
33
+	 */
34
+	protected $reg_form_count = 0;
35
+
36
+
37
+	/**
38
+	 *    class constructor
39
+	 *
40
+	 * @access    public
41
+	 * @param EE_Checkout $checkout
42
+	 */
43
+	public function __construct(EE_Checkout $checkout)
44
+	{
45
+		$this->_slug    = 'attendee_information';
46
+		$this->_name    = esc_html__('Attendee Information', 'event_espresso');
47
+		$this->checkout = $checkout;
48
+		$this->_reset_success_message();
49
+		$this->set_instructions(
50
+			esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
51
+		);
52
+	}
53
+
54
+
55
+	public function translate_js_strings()
56
+	{
57
+		EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
58
+			' is a required question.',
59
+			'event_espresso'
60
+		);
61
+		EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
62
+			' is a required question. Please enter a value for at least one of the options.',
63
+			'event_espresso'
64
+		);
65
+		EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
66
+			'Please answer all required questions correctly before proceeding.',
67
+			'event_espresso'
68
+		);
69
+		EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
70
+			esc_html_x(
71
+				'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
72
+				'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
73
+				'event_espresso'
74
+			),
75
+			'<br/>'
76
+		);
77
+		EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
78
+			'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
79
+			'event_espresso'
80
+		);
81
+		EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
82
+			'You must enter a valid email address.',
83
+			'event_espresso'
84
+		);
85
+		EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
86
+			'You must enter a valid email address and answer all other required questions before you can proceed.',
87
+			'event_espresso'
88
+		);
89
+	}
90
+
91
+
92
+	public function enqueue_styles_and_scripts()
93
+	{
94
+	}
95
+
96
+
97
+	/**
98
+	 * @return boolean
99
+	 */
100
+	public function initialize_reg_step(): bool
101
+	{
102
+		return true;
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return RegForm
108
+	 * @throws DomainException
109
+	 * @throws InvalidArgumentException
110
+	 * @throws EntityNotFoundException
111
+	 * @throws InvalidDataTypeException
112
+	 * @throws InvalidInterfaceException
113
+	 */
114
+	public function generate_reg_form(): RegForm
115
+	{
116
+		$this->setLegacyFiltersForRegFormGeneration();
117
+		/** @var RegFormDependencyHandler $dependency_handler */
118
+		$dependency_handler = LoaderFactory::getShared(RegFormDependencyHandler::class);
119
+		$dependency_handler->registerDependencies();
120
+		// TODO detect if event has a reg form UUID and swap this out for form generated by new reg form builder
121
+		return LoaderFactory::getShared(RegForm::class, [$this]);
122
+	}
123
+
124
+
125
+	/**
126
+	 * @since   5.0.0.p
127
+	 */
128
+	private function setLegacyFiltersForRegFormGeneration()
129
+	{
130
+		add_filter(
131
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_groups_query_parameters',
132
+			[$this, 'registrationQuestionGroupsQueryParameters'],
133
+			1,
134
+			2
135
+		);
136
+		add_filter(
137
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__question_group_reg_form',
138
+			[$this, 'registrationQuestionGroupsRegForm'],
139
+			1,
140
+			3
141
+		);
142
+		add_filter(
143
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantForm__generateFormArgs__printCopyInfo',
144
+			[$this, 'registrationRegFormPrintCopyInfo'],
145
+			1,
146
+			2
147
+		);
148
+		add_filter(
149
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__related_questions_query_params',
150
+			[$this, 'registrationRegFormRelatedQuestionsQueryParams'],
151
+			1,
152
+			3
153
+		);
154
+		add_filter(
155
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__before_question_group_questions',
156
+			[$this, 'registrationRegFormBeforeQuestionGroupQuestions'],
157
+			1,
158
+			3
159
+		);
160
+		add_filter(
161
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__subsections_array',
162
+			[$this, 'registrationRegFormSubsections'],
163
+			1,
164
+			3
165
+		);
166
+		add_filter(
167
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormQuestionGroup__generateFormArgs__after_question_group_questions',
168
+			[$this, 'registrationRegFormAfterQuestionGroupQuestions'],
169
+			1,
170
+			3
171
+		);
172
+		add_filter(
173
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_AutoCopyAttendeeInfoForm__construct__template_args',
174
+			[$this, 'autoCopyAttendeeInfoTemplateArgs'],
175
+			1
176
+		);
177
+		add_filter(
178
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_CountryOptions__generateLegacyCountryOptions__country_options',
179
+			[$this, 'generateQuestionInputCountryOptions'],
180
+			1,
181
+			4
182
+		);
183
+		add_filter(
184
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_StateOptions__generateLegacyStateOptions__state_options',
185
+			[$this, 'generateQuestionInputStateOptions'],
186
+			1,
187
+			4
188
+		);
189
+	}
190
+
191
+
192
+	/**
193
+	 * @param array           $query_params
194
+	 * @param EE_Registration $registration
195
+	 * @return mixed|void
196
+	 * @since   5.0.0.p
197
+	 */
198
+	public function registrationQuestionGroupsQueryParameters(
199
+		array $query_params,
200
+		EE_Registration $registration
201
+	) {
202
+		return apply_filters(
203
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
204
+			$query_params,
205
+			$registration,
206
+			$this
207
+		);
208
+	}
209
+
210
+
211
+	/**
212
+	 * @param RegFormQuestionGroup $question_group_reg_form
213
+	 * @param EE_Registration      $registration
214
+	 * @param EE_Question_Group    $question_group
215
+	 * @return mixed|void
216
+	 * @since   5.0.0.p
217
+	 */
218
+	public function registrationQuestionGroupsRegForm(
219
+		RegFormQuestionGroup $question_group_reg_form,
220
+		EE_Registration $registration,
221
+		EE_Question_Group $question_group
222
+	) {
223
+		return apply_filters(
224
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
225
+			$question_group_reg_form,
226
+			$registration,
227
+			$question_group,
228
+			$this
229
+		);
230
+	}
231
+
232
+
233
+	/**
234
+	 * @param int $print_copy_info
235
+	 * @param int $attendee_nmbr
236
+	 * @return mixed|void
237
+	 * @since   5.0.0.p
238
+	 */
239
+	public function registrationRegFormPrintCopyInfo(
240
+		int $print_copy_info,
241
+		int $attendee_nmbr
242
+	) {
243
+		return apply_filters(
244
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form___printCopyInfo',
245
+			$print_copy_info,
246
+			$attendee_nmbr
247
+		);
248
+	}
249
+
250
+
251
+	/**
252
+	 * @param array             $query_params
253
+	 * @param EE_Question_Group $question_group
254
+	 * @param EE_Registration   $registration
255
+	 * @return mixed|void
256
+	 * @since   5.0.0.p
257
+	 */
258
+	public function registrationRegFormRelatedQuestionsQueryParams(
259
+		array $query_params,
260
+		EE_Question_Group $question_group,
261
+		EE_Registration $registration
262
+	) {
263
+		return apply_filters(
264
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
265
+			$query_params,
266
+			$question_group,
267
+			$registration,
268
+			$this
269
+		);
270
+	}
271
+
272
+
273
+	/**
274
+	 * @param                   $html
275
+	 * @param EE_Registration   $registration
276
+	 * @param EE_Question_Group $question_group
277
+	 * @return mixed|void
278
+	 * @since   5.0.0.p
279
+	 */
280
+	public function registrationRegFormBeforeQuestionGroupQuestions(
281
+		$html,
282
+		EE_Registration $registration,
283
+		EE_Question_Group $question_group
284
+	) {
285
+		return apply_filters(
286
+			'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
287
+			$html,
288
+			$registration,
289
+			$question_group,
290
+			$this
291
+		);
292
+	}
293
+
294
+
295
+	/**
296
+	 * @param array             $form_subsections
297
+	 * @param EE_Registration   $registration
298
+	 * @param EE_Question_Group $question_group
299
+	 * @return mixed|void
300
+	 * @since   5.0.0.p
301
+	 */
302
+	public function registrationRegFormSubsections(
303
+		array $form_subsections,
304
+		EE_Registration $registration,
305
+		EE_Question_Group $question_group
306
+	) {
307
+		return apply_filters(
308
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
309
+			$form_subsections,
310
+			$registration,
311
+			$question_group,
312
+			$this
313
+		);
314
+	}
315
+
316
+
317
+	/**
318
+	 * @param                   $html
319
+	 * @param EE_Registration   $registration
320
+	 * @param EE_Question_Group $question_group
321
+	 * @return mixed|void
322
+	 * @since   5.0.0.p
323
+	 */
324
+	public function registrationRegFormAfterQuestionGroupQuestions(
325
+		$html,
326
+		EE_Registration $registration,
327
+		EE_Question_Group $question_group
328
+	) {
329
+		return apply_filters(
330
+			'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
331
+			$html,
332
+			$registration,
333
+			$question_group,
334
+			$this
335
+		);
336
+	}
337
+
338
+
339
+	/**
340
+	 * @param array $template_args
341
+	 * @return mixed|void
342
+	 * @since   5.0.0.p
343
+	 */
344
+	public function autoCopyAttendeeInfoTemplateArgs(array $template_args = [])
345
+	{
346
+		return apply_filters(
347
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
348
+			$template_args
349
+		);
350
+	}
351
+
352
+
353
+	/**
354
+	 * @param array           $country_options
355
+	 * @param EE_Registration $registration
356
+	 * @param EE_Question     $question
357
+	 * @param EE_Answer|null  $answer
358
+	 * @return mixed|void
359
+	 * @since   5.0.0.p
360
+	 */
361
+	public function generateQuestionInputCountryOptions(
362
+		array $country_options,
363
+		EE_Registration $registration,
364
+		EE_Question $question,
365
+		?EE_Answer $answer
366
+	) {
367
+		return apply_filters(
368
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
369
+			$country_options,
370
+			$this,
371
+			$registration,
372
+			$question,
373
+			$answer
374
+		);
375
+	}
376
+
377
+
378
+	/**
379
+	 * @param array           $state_options
380
+	 * @param EE_Registration $registration
381
+	 * @param EE_Question     $question
382
+	 * @param EE_Answer|null  $answer
383
+	 * @return mixed|void
384
+	 * @since   5.0.0.p
385
+	 */
386
+	public function generateQuestionInputStateOptions(
387
+		array $state_options,
388
+		EE_Registration $registration,
389
+		EE_Question $question,
390
+		?EE_Answer $answer
391
+	) {
392
+		return apply_filters(
393
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
394
+			$state_options,
395
+			$this,
396
+			$registration,
397
+			$question,
398
+			$answer
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 * looking for hooks?
405
+	 * this method has been replaced by:
406
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::getRegForm()
407
+	 *
408
+	 * @deprecated   5.0.0.p
409
+	 */
410
+	private function _registrations_reg_form()
411
+	{
412
+	}
413
+
414
+
415
+	/**
416
+	 * looking for hooks?
417
+	 * this method has been replaced by:
418
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalAttendeeRegInfoInput()
419
+	 *
420
+	 * @deprecated   5.0.0.p
421
+	 */
422
+	private function _additional_attendee_reg_info_input()
423
+	{
424
+	}
425
+
426
+
427
+	/**
428
+	 * looking for hooks?
429
+	 * this method has been replaced by:
430
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupRegForm()
431
+	 *
432
+	 * @deprecated   5.0.0.p
433
+	 */
434
+	private function _question_group_reg_form()
435
+	{
436
+	}
437
+
438
+
439
+	/**
440
+	 * looking for hooks?
441
+	 * this method has been replaced by:
442
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::questionGroupHeader()
443
+	 *
444
+	 * @deprecated   5.0.0.p
445
+	 */
446
+	private function _question_group_header()
447
+	{
448
+	}
449
+
450
+
451
+	/**
452
+	 * looking for hooks?
453
+	 * this method has been replaced by:
454
+	 * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
455
+	 *
456
+	 * @deprecated   5.0.0.p
457
+	 */
458
+	private function _copy_attendee_info_form()
459
+	{
460
+	}
461
+
462
+
463
+	/**
464
+	 * looking for hooks?
465
+	 * this method has been replaced by:
466
+	 * EventEspresso\core\domain\services\registration\form\v1\AutoCopyAttendeeInfoForm
467
+	 *
468
+	 * @deprecated   5.0.0.p
469
+	 */
470
+	private function _auto_copy_attendee_info()
471
+	{
472
+	}
473
+
474
+
475
+	/**
476
+	 * looking for hooks?
477
+	 * this method has been replaced by:
478
+	 * EventEspresso\core\domain\services\registration\form\v1\CopyAttendeeInfoForm
479
+	 *
480
+	 * @deprecated   5.0.0.p
481
+	 */
482
+	private function _copy_attendee_info_inputs()
483
+	{
484
+	}
485
+
486
+
487
+	/**
488
+	 * looking for hooks?
489
+	 * this method has been replaced by:
490
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::additionalPrimaryRegistrantInputs()
491
+	 *
492
+	 * @deprecated   5.0.0.p
493
+	 */
494
+	private function _additional_primary_registrant_inputs()
495
+	{
496
+	}
497
+
498
+
499
+	/**
500
+	 * looking for hooks?
501
+	 * this method has been replaced by:
502
+	 * EventEspresso\core\domain\services\registration\form\v1\RegFormQuestionFactory::create()
503
+	 *
504
+	 * @param EE_Registration $registration
505
+	 * @param EE_Question     $question
506
+	 * @return EE_Form_Input_Base
507
+	 * @throws EE_Error
508
+	 * @throws ReflectionException
509
+	 * @deprecated   5.0.0.p
510
+	 */
511
+	public function reg_form_question(EE_Registration $registration, EE_Question $question): EE_Form_Input_Base
512
+	{
513
+		/** @var RegFormQuestionFactory $reg_form_question_factory */
514
+		$reg_form_question_factory = LoaderFactory::getShared(RegFormQuestionFactory::class);
515
+		return $reg_form_question_factory->create($registration, $question);
516
+	}
517
+
518
+
519
+	/**
520
+	 * looking for hooks?
521
+	 * this method has been replaced by:
522
+	 * EventEspresso\core\domain\services\registration\form\v1\RegForm::generateQuestionInput()
523
+	 *
524
+	 * @deprecated   5.0.0.p
525
+	 */
526
+	private function _generate_question_input()
527
+	{
528
+	}
529
+
530
+
531
+	/**
532
+	 * looking for hooks?
533
+	 * this method has been replaced by:
534
+	 * EventEspresso\core\domain\services\registration\form\v1\CountryOptions::forLegacyFormInput()
535
+	 *
536
+	 * @param array|null           $countries_list
537
+	 * @param EE_Question|null     $question
538
+	 * @param EE_Registration|null $registration
539
+	 * @param EE_Answer|null       $answer
540
+	 * @return array 2d keys are country IDs, values are their names
541
+	 * @throws EE_Error
542
+	 * @throws ReflectionException
543
+	 * @deprecated   5.0.0.p
544
+	 */
545
+	public function use_cached_countries_for_form_input(
546
+		array $countries_list = null,
547
+		EE_Question $question = null,
548
+		EE_Registration $registration = null,
549
+		EE_Answer $answer = null
550
+	): array {
551
+		/** @var CountryOptions $country_options */
552
+		$country_options = LoaderFactory::getShared(CountryOptions::class, [$this->checkout->action]);
553
+		return $country_options->forLegacyFormInput($countries_list, $question, $registration, $answer);
554
+	}
555
+
556
+
557
+	/**
558
+	 * looking for hooks?
559
+	 * this method has been replaced by:
560
+	 * EventEspresso\core\domain\services\registration\form\v1\StateOptions::forLegacyFormInput()
561
+	 *
562
+	 * @param array|null           $states_list
563
+	 * @param EE_Question|null     $question
564
+	 * @param EE_Registration|null $registration
565
+	 * @param EE_Answer|null       $answer
566
+	 * @return array 2d keys are state IDs, values are their names
567
+	 * @throws EE_Error
568
+	 * @throws ReflectionException
569
+	 * @deprecated   5.0.0.p
570
+	 */
571
+	public function use_cached_states_for_form_input(
572
+		array $states_list = null,
573
+		EE_Question $question = null,
574
+		EE_Registration $registration = null,
575
+		EE_Answer $answer = null
576
+	): array {
577
+		/** @var StateOptions $state_options */
578
+		$state_options = LoaderFactory::getShared(StateOptions::class, [$this->checkout->action]);
579
+		return $state_options->forLegacyFormInput($states_list, $question, $registration, $answer);
580
+	}
581
+
582
+
583
+	/********************************************************************************************************/
584
+	/****************************************  PROCESS REG STEP  ****************************************/
585
+	/********************************************************************************************************/
586
+
587
+
588
+	/**
589
+	 * @return bool
590
+	 * @throws EE_Error
591
+	 * @throws InvalidArgumentException
592
+	 * @throws ReflectionException
593
+	 * @throws RuntimeException
594
+	 * @throws InvalidDataTypeException
595
+	 * @throws InvalidInterfaceException
596
+	 */
597
+	public function process_reg_step(): bool
598
+	{
599
+		$this->setLegacyFiltersForRegFormProcessing();
600
+		// grab validated data from form
601
+		$valid_data = $this->checkout->current_step->valid_data();
602
+		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
603
+		if (empty($valid_data)) {
604
+			return $this->inValidDataError();
605
+		}
606
+		if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
607
+			return $this->inValidTransactionError();
608
+		}
609
+		// get cached registrations
610
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
611
+		// verify we got the goods
612
+		if (empty($registrations)) {
613
+			return $this->noRegistrationsError();
614
+		}
615
+		/** @var RegFormHandler $reg_form_handler */
616
+		$reg_form_handler = LoaderFactory::getNew(RegFormHandler::class, [$this->checkout]);
617
+		// extract attendee info from form data and save to model objects
618
+		if (! $reg_form_handler->processRegistrations($registrations, $valid_data)) {
619
+			// return immediately if the previous step exited early due to errors
620
+			return false;
621
+		}
622
+		// if first pass thru SPCO,
623
+		// then let's check processed registrations against the total number of tickets in the cart
624
+		$registrations_processed = $reg_form_handler->attendeeCount();
625
+		if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
626
+			return $this->registrationProcessingError($registrations_processed);
627
+		}
628
+		// mark this reg step as completed
629
+		$this->set_completed();
630
+		$this->_set_success_message(
631
+			esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
632
+		);
633
+		// do action in case a plugin wants to do something with the data submitted in step 1.
634
+		// passes EE_Single_Page_Checkout, and it's posted data
635
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
636
+		return true;
637
+	}
638
+
639
+
640
+	/**
641
+	 * @since   5.0.0.p
642
+	 */
643
+	private function setLegacyFiltersForRegFormProcessing()
644
+	{
645
+		add_filter(
646
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegistrations__bypass',
647
+			[$this, 'preRegistrationProcess'],
648
+			1,
649
+			5
650
+		);
651
+		add_filter(
652
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormHandler__processRegFormData__registrant_form_data',
653
+			[$this, 'validDataLineItem'],
654
+			1,
655
+			2
656
+		);
657
+		add_filter(
658
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegFormInputHandler__saveRegistrationFormInput',
659
+			[$this, 'saveRegistrationFormInput'],
660
+			1,
661
+			4
662
+		);
663
+		add_filter(
664
+			'FHEE__EventEspresso_core_domain_services_registration_form_v1_RegistrantData__ensureCriticalRegistrantDataIsSet',
665
+			[$this, 'mergeAddressDetailsWithCriticalAttendeeDetails'],
666
+			1
667
+		);
668
+	}
669
+
670
+
671
+	/**
672
+	 * @param bool            $bypass
673
+	 * @param int             $attendee_count
674
+	 * @param EE_Registration $registration
675
+	 * @param array           $registrations
676
+	 * @param array           $reg_form_data
677
+	 * @return mixed|void
678
+	 * @since   5.0.0.p
679
+	 */
680
+	public function preRegistrationProcess(
681
+		bool $bypass,
682
+		int $attendee_count,
683
+		EE_Registration $registration,
684
+		array $registrations,
685
+		array $reg_form_data
686
+	) {
687
+		return apply_filters(
688
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
689
+			$bypass,
690
+			$attendee_count,
691
+			$registration,
692
+			$registrations,
693
+			$reg_form_data,
694
+			$this
695
+		);
696
+	}
697
+
698
+
699
+	/**
700
+	 * @param array           $reg_form_data
701
+	 * @param EE_Registration $registration
702
+	 * @return mixed|void
703
+	 * @since   5.0.0.p
704
+	 */
705
+	public function validDataLineItem(array $reg_form_data, EE_Registration $registration)
706
+	{
707
+		return apply_filters(
708
+			'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
709
+			$reg_form_data,
710
+			$registration
711
+		);
712
+	}
713
+
714
+
715
+	/**
716
+	 * @param bool            $save
717
+	 * @param EE_Registration $registration
718
+	 * @param                 $form_input
719
+	 * @param                 $input_value
720
+	 * @return mixed|void
721
+	 * @since   5.0.0.p
722
+	 */
723
+	public function saveRegistrationFormInput(bool $save, EE_Registration $registration, $form_input, $input_value)
724
+	{
725
+		return apply_filters(
726
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
727
+			$save,
728
+			$registration,
729
+			$form_input,
730
+			$input_value,
731
+			$this
732
+		);
733
+	}
734
+
735
+
736
+	/**
737
+	 * @param bool $merge_data
738
+	 * @return mixed|void
739
+	 * @since   5.0.0.p
740
+	 */
741
+	public function mergeAddressDetailsWithCriticalAttendeeDetails(bool $merge_data)
742
+	{
743
+		return apply_filters(
744
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
745
+			$merge_data
746
+		);
747
+	}
748
+
749
+
750
+	/**
751
+	 * @return bool
752
+	 * @since   5.0.0.p
753
+	 */
754
+	private function inValidDataError(): bool
755
+	{
756
+		EE_Error::add_error(
757
+			esc_html__('No valid question responses were received.', 'event_espresso'),
758
+			__FILE__,
759
+			__FUNCTION__,
760
+			__LINE__
761
+		);
762
+		return false;
763
+	}
764
+
765
+
766
+	/**
767
+	 * @return bool
768
+	 * @since   5.0.0.p
769
+	 */
770
+	private function inValidTransactionError(): bool
771
+	{
772
+		EE_Error::add_error(
773
+			esc_html__(
774
+				'A valid transaction could not be initiated for processing your registrations.',
775
+				'event_espresso'
776
+			),
777
+			__FILE__,
778
+			__FUNCTION__,
779
+			__LINE__
780
+		);
781
+		return false;
782
+	}
783
+
784
+
785
+	/**
786
+	 * @return bool
787
+	 * @since   5.0.0.p
788
+	 */
789
+	private function noRegistrationsError(): bool
790
+	{
791
+		// combine the old translated string with a new one, in order to not break translations
792
+		$error_message = esc_html__(
793
+			'Your form data could not be applied to any valid registrations.',
794
+			'event_espresso'
795
+		);
796
+		$error_message .= sprintf(
797
+			esc_html_x(
798
+				'%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.',
799
+				'(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
800
+				'event_espresso'
801
+			),
802
+			'<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" >',
803
+			'</a>',
804
+			'<br />'
805
+		);
806
+		EE_Error::add_error($error_message, __FILE__, __FUNCTION__, __LINE__);
807
+		return false;
808
+	}
809
+
810
+
811
+	/**
812
+	 * @param int $registrations_processed
813
+	 * @return bool
814
+	 * @since   5.0.0.p
815
+	 */
816
+	private function registrationProcessingError(int $registrations_processed): bool
817
+	{
818
+		// generate a correctly translated string for all possible singular/plural combinations
819
+		if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
820
+			$error_msg = sprintf(
821
+				esc_html_x(
822
+					'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
823
+					'There was 1 ticket in the Event Queue, but 2 registrations were processed',
824
+					'event_espresso'
825
+				),
826
+				$this->checkout->total_ticket_count,
827
+				$registrations_processed
828
+			);
829
+		} elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
830
+			$error_msg = sprintf(
831
+				esc_html_x(
832
+					'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
833
+					'There was a total of 2 tickets in the Event Queue, but only 1 registration was processed',
834
+					'event_espresso'
835
+				),
836
+				$this->checkout->total_ticket_count,
837
+				$registrations_processed
838
+			);
839
+		} else {
840
+			$error_msg = sprintf(
841
+				esc_html__(
842
+					'There was a total of 2 tickets in the Event Queue, but 2 registrations were processed',
843
+					'event_espresso'
844
+				),
845
+				$this->checkout->total_ticket_count,
846
+				$registrations_processed
847
+			);
848
+		}
849
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
850
+		return false;
851
+	}
852
+
853
+
854
+	/**
855
+	 *    update_reg_step
856
+	 *    this is the final step after a user  revisits the site to edit their attendee information
857
+	 *    this gets called AFTER the process_reg_step() method above
858
+	 *
859
+	 * @return bool
860
+	 * @throws EE_Error
861
+	 * @throws InvalidArgumentException
862
+	 * @throws ReflectionException
863
+	 * @throws RuntimeException
864
+	 * @throws InvalidDataTypeException
865
+	 * @throws InvalidInterfaceException
866
+	 */
867
+	public function update_reg_step(): bool
868
+	{
869
+		// save everything
870
+		if ($this->process_reg_step()) {
871
+			$this->checkout->redirect     = true;
872
+			$this->checkout->redirect_url = add_query_arg(
873
+				[
874
+					'e_reg_url_link' => $this->checkout->reg_url_link,
875
+					'revisit'        => true,
876
+				],
877
+				$this->checkout->thank_you_page_url
878
+			);
879
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
880
+			return true;
881
+		}
882
+		return false;
883
+	}
884 884
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -54,11 +54,11 @@  discard block
 block discarded – undo
54 54
 
55 55
     public function translate_js_strings()
56 56
     {
57
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
57
+        EE_Registry::$i18n_js_strings['required_field'] = esc_html__(
58 58
             ' is a required question.',
59 59
             'event_espresso'
60 60
         );
61
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
61
+        EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__(
62 62
             ' is a required question. Please enter a value for at least one of the options.',
63 63
             'event_espresso'
64 64
         );
@@ -66,7 +66,7 @@  discard block
 block discarded – undo
66 66
             'Please answer all required questions correctly before proceeding.',
67 67
             'event_espresso'
68 68
         );
69
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
69
+        EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf(
70 70
             esc_html_x(
71 71
                 'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
72 72
                 'The attendee information was successfully copied.(line break)Please ensure the rest of the registration form is completed before proceeding.',
@@ -74,11 +74,11 @@  discard block
 block discarded – undo
74 74
             ),
75 75
             '<br/>'
76 76
         );
77
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
77
+        EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__(
78 78
             'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
79 79
             'event_espresso'
80 80
         );
81
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
81
+        EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__(
82 82
             'You must enter a valid email address.',
83 83
             'event_espresso'
84 84
         );
@@ -603,7 +603,7 @@  discard block
 block discarded – undo
603 603
         if (empty($valid_data)) {
604 604
             return $this->inValidDataError();
605 605
         }
606
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
606
+        if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
607 607
             return $this->inValidTransactionError();
608 608
         }
609 609
         // get cached registrations
@@ -615,14 +615,14 @@  discard block
 block discarded – undo
615 615
         /** @var RegFormHandler $reg_form_handler */
616 616
         $reg_form_handler = LoaderFactory::getNew(RegFormHandler::class, [$this->checkout]);
617 617
         // extract attendee info from form data and save to model objects
618
-        if (! $reg_form_handler->processRegistrations($registrations, $valid_data)) {
618
+        if ( ! $reg_form_handler->processRegistrations($registrations, $valid_data)) {
619 619
             // return immediately if the previous step exited early due to errors
620 620
             return false;
621 621
         }
622 622
         // if first pass thru SPCO,
623 623
         // then let's check processed registrations against the total number of tickets in the cart
624 624
         $registrations_processed = $reg_form_handler->attendeeCount();
625
-        if (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
625
+        if ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
626 626
             return $this->registrationProcessingError($registrations_processed);
627 627
         }
628 628
         // mark this reg step as completed
@@ -799,7 +799,7 @@  discard block
 block discarded – undo
799 799
                 '(line break)This can sometimes happen if too much time has been taken to complete the registration process.(line break)Please return to the (link)Event List(end link) and reselect your tickets. If the problem continues, please contact the site administrator.',
800 800
                 'event_espresso'
801 801
             ),
802
-            '<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" >',
802
+            '<a href="'.get_post_type_archive_link(EspressoPostType::EVENTS).'" >',
803 803
             '</a>',
804 804
             '<br />'
805 805
         );
Please login to merge, or discard this patch.
admin_pages/venues/Venues_Admin_Page.core.php 1 patch
Indentation   +1547 added lines, -1547 removed lines patch added patch discarded remove patch
@@ -14,1557 +14,1557 @@
 block discarded – undo
14 14
  */
15 15
 class Venues_Admin_Page extends EE_Admin_Page_CPT
16 16
 {
17
-    /**
18
-     * primary key for the venue model
19
-     */
20
-    private int $VNU_ID = 0;
21
-
22
-    /**
23
-     * This will hold the venue object for venue_details screen.
24
-     *
25
-     * @var EE_Venue|EE_CPT_Base|null $_cpt_model_obj
26
-     */
27
-    protected $_cpt_model_obj;
28
-
29
-
30
-    /**
31
-     * This will hold the category object for category_details screen.
32
-     *
33
-     * @var stdClass|null $_category
34
-     */
35
-    protected ?stdClass $_category = null;
36
-
37
-
38
-    /**
39
-     * This property will hold the venue model instance
40
-     *
41
-     * @var EEM_Venue|null $_venue_model
42
-     */
43
-    protected ?EEM_Venue $_venue_model = null;
44
-
45
-
46
-    /**
47
-     * @throws EE_Error
48
-     * @throws ReflectionException
49
-     */
50
-    protected function _init_page_props()
51
-    {
52
-        // is there a vnu_id in the request?
53
-        $this->VNU_ID = $this->request->getRequestParam('VNU_ID', 0, DataType::INT);
54
-        $this->VNU_ID = $this->request->getRequestParam('post', $this->VNU_ID, DataType::INT);
55
-        $this->VNU_ID = $this->request->getRequestParam('post_ID', $this->VNU_ID, DataType::INT);
56
-
57
-        $this->page_slug        = EE_VENUES_PG_SLUG;
58
-        $this->_admin_base_url  = EE_VENUES_ADMIN_URL;
59
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
60
-        $this->page_label       = esc_html__('Event Venues', 'event_espresso');
61
-        $this->_cpt_model_names = [
62
-            'create_new' => 'EEM_Venue',
63
-            'edit'       => 'EEM_Venue',
64
-        ];
65
-        $this->_cpt_edit_routes = [
66
-            'espresso_venues' => 'edit',
67
-        ];
68
-        $this->_venue_model     = EEM_Venue::instance();
69
-    }
70
-
71
-
72
-    protected function _ajax_hooks()
73
-    {
74
-        // todo: all hooks for ee_venues ajax goes in here.
75
-    }
76
-
77
-
78
-    protected function _define_page_props()
79
-    {
80
-        $this->_admin_page_title = $this->page_label;
81
-        $this->_labels           = [
82
-            'buttons'      => [
83
-                'add'             => esc_html__('Add New Venue', 'event_espresso'),
84
-                'edit'            => esc_html__('Edit Venue', 'event_espresso'),
85
-                'delete'          => esc_html__('Delete Venue', 'event_espresso'),
86
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
87
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
88
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
89
-            ],
90
-            'editor_title' => [
91
-                'espresso_venues' => esc_html__('Edit Venue', 'event_espresso'),
92
-            ],
93
-            'publishbox'   => [
94
-                'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
95
-                'edit'                => esc_html__('Update Venue', 'event_espresso'),
96
-                'add_category'        => esc_html__('Save New Category', 'event_espresso'),
97
-                'edit_category'       => esc_html__('Update Category', 'event_espresso'),
98
-                'google_map_settings' => esc_html__('Update Settings', 'event_espresso'),
99
-            ],
100
-        ];
101
-    }
102
-
103
-
104
-    protected function _set_page_routes()
105
-    {
106
-        // load formatter helper
107
-        // load field generator helper
108
-
109
-
110
-        $this->_page_routes = [
111
-            'default'                    => [
112
-                'func'       => [$this, '_overview_list_table'],
113
-                'capability' => 'ee_read_venues',
114
-            ],
115
-            'create_new'                 => [
116
-                'func'       => [$this, '_create_new_cpt_item'],
117
-                'capability' => 'ee_edit_venues',
118
-            ],
119
-            'edit'                       => [
120
-                'func'       => [$this, '_edit_cpt_item'],
121
-                'capability' => 'ee_edit_venue',
122
-                'obj_id'     => $this->VNU_ID,
123
-            ],
124
-            'trash_venue'                => [
125
-                'func'       => [$this, '_trash_or_restore_venue'],
126
-                'args'       => ['venue_status' => 'trash'],
127
-                'noheader'   => true,
128
-                'capability' => 'ee_delete_venue',
129
-                'obj_id'     => $this->VNU_ID,
130
-            ],
131
-            'trash_venues'               => [
132
-                'func'       => [$this, '_trash_or_restore_venues'],
133
-                'args'       => ['venue_status' => 'trash'],
134
-                'noheader'   => true,
135
-                'capability' => 'ee_delete_venues',
136
-            ],
137
-            'restore_venue'              => [
138
-                'func'       => [$this, '_trash_or_restore_venue'],
139
-                'args'       => ['venue_status' => 'draft'],
140
-                'noheader'   => true,
141
-                'capability' => 'ee_delete_venue',
142
-                'obj_id'     => $this->VNU_ID,
143
-            ],
144
-            'restore_venues'             => [
145
-                'func'       => [$this, '_trash_or_restore_venues'],
146
-                'args'       => ['venue_status' => 'draft'],
147
-                'noheader'   => true,
148
-                'capability' => 'ee_delete_venues',
149
-            ],
150
-            'delete_venues'              => [
151
-                'func'       => [$this, '_delete_venues'],
152
-                'noheader'   => true,
153
-                'capability' => 'ee_delete_venues',
154
-            ],
155
-            'delete_venue'               => [
156
-                'func'       => [$this, '_delete_venue'],
157
-                'args'       => ['redirect_after' => true],
158
-                'noheader'   => true,
159
-                'capability' => 'ee_delete_venue',
160
-                'obj_id'     => $this->VNU_ID,
161
-            ],
162
-            // settings related
163
-            'google_map_settings'        => [
164
-                'func'       => [$this, '_google_map_settings'],
165
-                'capability' => 'manage_options',
166
-            ],
167
-            'update_google_map_settings' => [
168
-                'func'       => [$this, '_update_google_map_settings'],
169
-                'capability' => 'manage_options',
170
-                'noheader'   => true,
171
-            ],
172
-            // venue category tab related
173
-            'add_category'               => [
174
-                'func'       => [$this, '_category_details'],
175
-                'args'       => ['add'],
176
-                'capability' => 'ee_edit_venue_category',
177
-            ],
178
-            'edit_category'              => [
179
-                'func'       => [$this, '_category_details'],
180
-                'args'       => ['edit'],
181
-                'capability' => 'ee_edit_venue_category',
182
-            ],
183
-            'delete_categories'          => [
184
-                'func'       => [$this, '_delete_categories'],
185
-                'noheader'   => true,
186
-                'capability' => 'ee_delete_venue_category',
187
-            ],
188
-
189
-            'delete_category' => [
190
-                'func'       => [$this, '_delete_categories'],
191
-                'noheader'   => true,
192
-                'capability' => 'ee_delete_venue_category',
193
-            ],
194
-
195
-            'insert_category' => [
196
-                'func'       => [$this, '_insert_or_update_category'],
197
-                'args'       => ['new_category' => true],
198
-                'noheader'   => true,
199
-                'capability' => 'ee_edit_venue_category',
200
-            ],
201
-
202
-            'update_category'   => [
203
-                'func'       => [$this, '_insert_or_update_category'],
204
-                'args'       => ['new_category' => false],
205
-                'noheader'   => true,
206
-                'capability' => 'ee_edit_venue_category',
207
-            ],
208
-            'export_categories' => [
209
-                'func'       => [$this, '_categories_export'],
210
-                'noheader'   => true,
211
-                'capability' => 'export',
212
-            ],
213
-            'import_categories' => [
214
-                'func'       => [$this, '_import_categories'],
215
-                'capability' => 'import',
216
-            ],
217
-            'category_list'     => [
218
-                'func'       => [$this, '_category_list_table'],
219
-                'capability' => 'ee_manage_venue_categories',
220
-            ],
221
-        ];
222
-    }
223
-
224
-
225
-    protected function _set_page_config()
226
-    {
227
-        $EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
228
-        $help_tabs  = [
229
-            'venues_editor_help_tab'                                               => [
230
-                'title'    => esc_html__('Venue Editor', 'event_espresso'),
231
-                'filename' => 'venues_editor',
232
-            ],
233
-            'venues_editor_title_richtexteditor_help_tab'                          => [
234
-                'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
235
-                'filename' => 'venues_editor_title_richtexteditor',
236
-            ],
237
-            'venues_editor_tags_categories_help_tab'                               => [
238
-                'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
239
-                'filename' => 'venues_editor_tags_categories',
240
-            ],
241
-            'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
242
-                'title'    => esc_html__(
243
-                    'Venue Editor Physical Location & Google Map & Virtual Location',
244
-                    'event_espresso'
245
-                ),
246
-                'filename' => 'venues_editor_physical_location_google_map_virtual_location',
247
-            ],
248
-            'venues_editor_save_new_venue_help_tab'                                => [
249
-                'title'    => esc_html__('Save New Venue', 'event_espresso'),
250
-                'filename' => 'venues_editor_save_new_venue',
251
-            ],
252
-            'venues_editor_other_help_tab'                                         => [
253
-                'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
254
-                'filename' => 'venues_editor_other',
255
-            ],
256
-        ];
257
-
258
-        $this->_page_config = [
259
-            'default'             => [
260
-                'nav'           => [
261
-                    'label' => esc_html__('Overview', 'event_espresso'),
262
-                    'icon'  => 'dashicons-list-view',
263
-                    'order' => 10,
264
-                ],
265
-                'list_table'    => 'Venues_Admin_List_Table',
266
-                'help_tabs'     => [
267
-                    'venues_overview_help_tab'                           => [
268
-                        'title'    => esc_html__('Venues Overview', 'event_espresso'),
269
-                        'filename' => 'venues_overview',
270
-                    ],
271
-                    'venues_overview_table_column_headings_help_tab'     => [
272
-                        'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
273
-                        'filename' => 'venues_overview_table_column_headings',
274
-                    ],
275
-                    'venues_overview_views_bulk_actions_search_help_tab' => [
276
-                        'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
277
-                        'filename' => 'venues_overview_views_bulk_actions_search',
278
-                    ],
279
-                ],
280
-                'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
281
-                'require_nonce' => false,
282
-            ],
283
-            'create_new'          => [
284
-                'nav'           => [
285
-                    'label'      => esc_html__('Add Venue', 'event_espresso'),
286
-                    'icon'       => 'dashicons-plus-alt',
287
-                    'order'      => 15,
288
-                    'persistent' => false,
289
-                ],
290
-                'help_tabs'     => $help_tabs,
291
-                'metaboxes'     => ['_venue_editor_metaboxes'],
292
-                'require_nonce' => false,
293
-            ],
294
-            'edit'                => [
295
-                'nav'           => [
296
-                    'label'      => esc_html__('Edit Venue', 'event_espresso'),
297
-                    'icon'       => 'dashicons-edit-large',
298
-                    'order'      => 15,
299
-                    'persistent' => false,
300
-                    'url'        => $this->VNU_ID
301
-                        ? add_query_arg(['post' => $this->VNU_ID], $this->_current_page_view_url)
302
-                        : $this->_admin_base_url,
303
-                ],
304
-                'help_tabs'     => $help_tabs,
305
-                'metaboxes'     => ['_venue_editor_metaboxes'],
306
-                'require_nonce' => false,
307
-            ],
308
-            'google_map_settings' => [
309
-                'nav'           => [
310
-                    'label' => esc_html__('Google Maps', 'event_espresso'),
311
-                    'icon'  => 'dashicons-location-alt',
312
-                    'order' => 40,
313
-                ],
314
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
315
-                'help_tabs'     => [
316
-                    'general_settings_google_maps_help_tab' => [
317
-                        'title'    => esc_html__('Google Maps', 'event_espresso'),
318
-                        'filename' => 'general_settings_google_maps',
319
-                    ],
320
-                ],
321
-                'require_nonce' => false,
322
-            ],
323
-            // venue category stuff
324
-            'add_category'        => [
325
-                'nav'           => [
326
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
327
-                    'icon'       => 'dashicons-plus-alt',
328
-                    'order'      => 25,
329
-                    'persistent' => false,
330
-                ],
331
-                'metaboxes'     => ['_publish_post_box'],
332
-                'help_tabs'     => [
333
-                    'venues_add_category_help_tab' => [
334
-                        'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
335
-                        'filename' => 'venues_add_category',
336
-                    ],
337
-                ],
338
-                'require_nonce' => false,
339
-            ],
340
-            'edit_category'       => [
341
-                'nav'           => [
342
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
343
-                    'icon'       => 'dashicons-edit-large',
344
-                    'order'      => 25,
345
-                    'persistent' => false,
346
-                    'url'        => $EVT_CAT_ID
347
-                        ? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
348
-                        : $this->_admin_base_url,
349
-                ],
350
-                'metaboxes'     => ['_publish_post_box'],
351
-                'help_tabs'     => [
352
-                    'venues_edit_category_help_tab' => [
353
-                        'title'    => esc_html__('Edit Venue Category', 'event_espresso'),
354
-                        'filename' => 'venues_edit_category',
355
-                    ],
356
-                ],
357
-                'require_nonce' => false,
358
-            ],
359
-            'category_list'       => [
360
-                'nav'           => [
361
-                    'label' => esc_html__('Categories', 'event_espresso'),
362
-                    'icon'  => 'dashicons-networking',
363
-                    'order' => 20,
364
-                ],
365
-                'list_table'    => 'Venue_Categories_Admin_List_Table',
366
-                'help_tabs'     => [
367
-                    'venues_categories_help_tab'                       => [
368
-                        'title'    => esc_html__('Venue Categories', 'event_espresso'),
369
-                        'filename' => 'venues_categories',
370
-                    ],
371
-                    'venues_categories_table_column_headings_help_tab' => [
372
-                        'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
373
-                        'filename' => 'venues_categories_table_column_headings',
374
-                    ],
375
-                    'venues_categories_views_help_tab'                 => [
376
-                        'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
377
-                        'filename' => 'venues_categories_views',
378
-                    ],
379
-                    'venues_categories_other_help_tab'                 => [
380
-                        'title'    => esc_html__('Venue Categories Other', 'event_espresso'),
381
-                        'filename' => 'venues_categories_other',
382
-                    ],
383
-                ],
384
-                'metaboxes'     => $this->_default_espresso_metaboxes,
385
-                'require_nonce' => false,
386
-            ],
387
-        ];
388
-    }
389
-
390
-
391
-    protected function _add_screen_options()
392
-    {
393
-        // todo
394
-    }
395
-
396
-
397
-    protected function _add_screen_options_default()
398
-    {
399
-        $this->_per_page_screen_option();
400
-    }
401
-
402
-
403
-    protected function _add_screen_options_category_list()
404
-    {
405
-        $page_title              = $this->_admin_page_title;
406
-        $this->_admin_page_title = esc_html__('Venue Categories', 'event_espresso');
407
-        $this->_per_page_screen_option();
408
-        $this->_admin_page_title = $page_title;
409
-    }
410
-
411
-
412
-    // none of the below group are currently used for Event Venues
413
-    protected function _add_feature_pointers()
414
-    {
415
-    }
416
-
417
-
418
-    public function admin_init()
419
-    {
420
-    }
421
-
422
-
423
-    public function admin_notices()
424
-    {
425
-    }
426
-
427
-
428
-    public function admin_footer_scripts()
429
-    {
430
-    }
431
-
432
-
433
-    public function load_scripts_styles_create_new()
434
-    {
435
-        $this->load_scripts_styles_edit();
436
-    }
437
-
438
-
439
-    public function load_scripts_styles()
440
-    {
441
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
442
-        wp_enqueue_style('ee-cat-admin');
443
-    }
444
-
445
-
446
-    public function load_scripts_styles_add_category()
447
-    {
448
-        $this->load_scripts_styles_edit_category();
449
-    }
450
-
451
-
452
-    public function load_scripts_styles_edit_category()
453
-    {
454
-    }
455
-
456
-
457
-    public function load_scripts_styles_edit()
458
-    {
459
-        // styles
460
-        wp_enqueue_style('espresso-ui-theme');
461
-        wp_register_style(
462
-            'espresso_venues',
463
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
464
-            [],
465
-            EVENT_ESPRESSO_VERSION
466
-        );
467
-        wp_enqueue_style('espresso_venues');
468
-    }
469
-
470
-
471
-    protected function _set_list_table_views_default()
472
-    {
473
-        $this->_views = [
474
-            'all' => [
475
-                'slug'        => 'all',
476
-                'label'       => esc_html__('View All Venues', 'event_espresso'),
477
-                'count'       => 0,
478
-                'bulk_action' => [],
479
-            ],
480
-        ];
481
-
482
-        if ($this->capabilities->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
483
-            $this->_views['all']['bulk_action'] = [
484
-                'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
485
-            ];
486
-            $this->_views['trash']              = [
487
-                'slug'        => 'trash',
488
-                'label'       => esc_html__('Trash', 'event_espresso'),
489
-                'count'       => 0,
490
-                'bulk_action' => [
491
-                    'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
492
-                    'delete_venues'  => esc_html__('Delete', 'event_espresso'),
493
-                ],
494
-            ];
495
-        }
496
-    }
497
-
498
-
499
-    protected function _set_list_table_views_category_list()
500
-    {
501
-        $this->_views = [
502
-            'all' => [
503
-                'slug'        => 'all',
504
-                'label'       => esc_html__('All', 'event_espresso'),
505
-                'count'       => 0,
506
-                'bulk_action' => [
507
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
508
-                ],
509
-            ],
510
-        ];
511
-    }
512
-
513
-
514
-    /**
515
-     * @throws EE_Error
516
-     */
517
-    protected function _overview_list_table()
518
-    {
519
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
520
-        $this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
521
-            get_post_type_archive_link(EspressoPostType::VENUES),
522
-            esc_html__("View Venue Archive Page", "event_espresso"),
523
-            'button'
524
-        );
525
-
526
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
527
-                'create_new',
528
-                'add',
529
-                [],
530
-                'add-new-h2'
531
-            );
532
-
533
-        $this->_search_btn_label = esc_html__('Venues', 'event_espresso');
534
-        $this->display_admin_list_table_page_with_sidebar();
535
-    }
536
-
537
-
538
-    /**
539
-     * @throws EE_Error
540
-     * @throws ReflectionException
541
-     */
542
-    public function extra_misc_actions_publish_box()
543
-    {
544
-        $extra_rows = [
545
-            'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
546
-            'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
547
-            'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
548
-        ];
549
-        $template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
550
-        EEH_Template::display_template($template, $extra_rows);
551
-    }
552
-
553
-
554
-    /*************        Google Maps        *************
17
+	/**
18
+	 * primary key for the venue model
19
+	 */
20
+	private int $VNU_ID = 0;
21
+
22
+	/**
23
+	 * This will hold the venue object for venue_details screen.
24
+	 *
25
+	 * @var EE_Venue|EE_CPT_Base|null $_cpt_model_obj
26
+	 */
27
+	protected $_cpt_model_obj;
28
+
29
+
30
+	/**
31
+	 * This will hold the category object for category_details screen.
32
+	 *
33
+	 * @var stdClass|null $_category
34
+	 */
35
+	protected ?stdClass $_category = null;
36
+
37
+
38
+	/**
39
+	 * This property will hold the venue model instance
40
+	 *
41
+	 * @var EEM_Venue|null $_venue_model
42
+	 */
43
+	protected ?EEM_Venue $_venue_model = null;
44
+
45
+
46
+	/**
47
+	 * @throws EE_Error
48
+	 * @throws ReflectionException
49
+	 */
50
+	protected function _init_page_props()
51
+	{
52
+		// is there a vnu_id in the request?
53
+		$this->VNU_ID = $this->request->getRequestParam('VNU_ID', 0, DataType::INT);
54
+		$this->VNU_ID = $this->request->getRequestParam('post', $this->VNU_ID, DataType::INT);
55
+		$this->VNU_ID = $this->request->getRequestParam('post_ID', $this->VNU_ID, DataType::INT);
56
+
57
+		$this->page_slug        = EE_VENUES_PG_SLUG;
58
+		$this->_admin_base_url  = EE_VENUES_ADMIN_URL;
59
+		$this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
60
+		$this->page_label       = esc_html__('Event Venues', 'event_espresso');
61
+		$this->_cpt_model_names = [
62
+			'create_new' => 'EEM_Venue',
63
+			'edit'       => 'EEM_Venue',
64
+		];
65
+		$this->_cpt_edit_routes = [
66
+			'espresso_venues' => 'edit',
67
+		];
68
+		$this->_venue_model     = EEM_Venue::instance();
69
+	}
70
+
71
+
72
+	protected function _ajax_hooks()
73
+	{
74
+		// todo: all hooks for ee_venues ajax goes in here.
75
+	}
76
+
77
+
78
+	protected function _define_page_props()
79
+	{
80
+		$this->_admin_page_title = $this->page_label;
81
+		$this->_labels           = [
82
+			'buttons'      => [
83
+				'add'             => esc_html__('Add New Venue', 'event_espresso'),
84
+				'edit'            => esc_html__('Edit Venue', 'event_espresso'),
85
+				'delete'          => esc_html__('Delete Venue', 'event_espresso'),
86
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
87
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
88
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
89
+			],
90
+			'editor_title' => [
91
+				'espresso_venues' => esc_html__('Edit Venue', 'event_espresso'),
92
+			],
93
+			'publishbox'   => [
94
+				'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
95
+				'edit'                => esc_html__('Update Venue', 'event_espresso'),
96
+				'add_category'        => esc_html__('Save New Category', 'event_espresso'),
97
+				'edit_category'       => esc_html__('Update Category', 'event_espresso'),
98
+				'google_map_settings' => esc_html__('Update Settings', 'event_espresso'),
99
+			],
100
+		];
101
+	}
102
+
103
+
104
+	protected function _set_page_routes()
105
+	{
106
+		// load formatter helper
107
+		// load field generator helper
108
+
109
+
110
+		$this->_page_routes = [
111
+			'default'                    => [
112
+				'func'       => [$this, '_overview_list_table'],
113
+				'capability' => 'ee_read_venues',
114
+			],
115
+			'create_new'                 => [
116
+				'func'       => [$this, '_create_new_cpt_item'],
117
+				'capability' => 'ee_edit_venues',
118
+			],
119
+			'edit'                       => [
120
+				'func'       => [$this, '_edit_cpt_item'],
121
+				'capability' => 'ee_edit_venue',
122
+				'obj_id'     => $this->VNU_ID,
123
+			],
124
+			'trash_venue'                => [
125
+				'func'       => [$this, '_trash_or_restore_venue'],
126
+				'args'       => ['venue_status' => 'trash'],
127
+				'noheader'   => true,
128
+				'capability' => 'ee_delete_venue',
129
+				'obj_id'     => $this->VNU_ID,
130
+			],
131
+			'trash_venues'               => [
132
+				'func'       => [$this, '_trash_or_restore_venues'],
133
+				'args'       => ['venue_status' => 'trash'],
134
+				'noheader'   => true,
135
+				'capability' => 'ee_delete_venues',
136
+			],
137
+			'restore_venue'              => [
138
+				'func'       => [$this, '_trash_or_restore_venue'],
139
+				'args'       => ['venue_status' => 'draft'],
140
+				'noheader'   => true,
141
+				'capability' => 'ee_delete_venue',
142
+				'obj_id'     => $this->VNU_ID,
143
+			],
144
+			'restore_venues'             => [
145
+				'func'       => [$this, '_trash_or_restore_venues'],
146
+				'args'       => ['venue_status' => 'draft'],
147
+				'noheader'   => true,
148
+				'capability' => 'ee_delete_venues',
149
+			],
150
+			'delete_venues'              => [
151
+				'func'       => [$this, '_delete_venues'],
152
+				'noheader'   => true,
153
+				'capability' => 'ee_delete_venues',
154
+			],
155
+			'delete_venue'               => [
156
+				'func'       => [$this, '_delete_venue'],
157
+				'args'       => ['redirect_after' => true],
158
+				'noheader'   => true,
159
+				'capability' => 'ee_delete_venue',
160
+				'obj_id'     => $this->VNU_ID,
161
+			],
162
+			// settings related
163
+			'google_map_settings'        => [
164
+				'func'       => [$this, '_google_map_settings'],
165
+				'capability' => 'manage_options',
166
+			],
167
+			'update_google_map_settings' => [
168
+				'func'       => [$this, '_update_google_map_settings'],
169
+				'capability' => 'manage_options',
170
+				'noheader'   => true,
171
+			],
172
+			// venue category tab related
173
+			'add_category'               => [
174
+				'func'       => [$this, '_category_details'],
175
+				'args'       => ['add'],
176
+				'capability' => 'ee_edit_venue_category',
177
+			],
178
+			'edit_category'              => [
179
+				'func'       => [$this, '_category_details'],
180
+				'args'       => ['edit'],
181
+				'capability' => 'ee_edit_venue_category',
182
+			],
183
+			'delete_categories'          => [
184
+				'func'       => [$this, '_delete_categories'],
185
+				'noheader'   => true,
186
+				'capability' => 'ee_delete_venue_category',
187
+			],
188
+
189
+			'delete_category' => [
190
+				'func'       => [$this, '_delete_categories'],
191
+				'noheader'   => true,
192
+				'capability' => 'ee_delete_venue_category',
193
+			],
194
+
195
+			'insert_category' => [
196
+				'func'       => [$this, '_insert_or_update_category'],
197
+				'args'       => ['new_category' => true],
198
+				'noheader'   => true,
199
+				'capability' => 'ee_edit_venue_category',
200
+			],
201
+
202
+			'update_category'   => [
203
+				'func'       => [$this, '_insert_or_update_category'],
204
+				'args'       => ['new_category' => false],
205
+				'noheader'   => true,
206
+				'capability' => 'ee_edit_venue_category',
207
+			],
208
+			'export_categories' => [
209
+				'func'       => [$this, '_categories_export'],
210
+				'noheader'   => true,
211
+				'capability' => 'export',
212
+			],
213
+			'import_categories' => [
214
+				'func'       => [$this, '_import_categories'],
215
+				'capability' => 'import',
216
+			],
217
+			'category_list'     => [
218
+				'func'       => [$this, '_category_list_table'],
219
+				'capability' => 'ee_manage_venue_categories',
220
+			],
221
+		];
222
+	}
223
+
224
+
225
+	protected function _set_page_config()
226
+	{
227
+		$EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
228
+		$help_tabs  = [
229
+			'venues_editor_help_tab'                                               => [
230
+				'title'    => esc_html__('Venue Editor', 'event_espresso'),
231
+				'filename' => 'venues_editor',
232
+			],
233
+			'venues_editor_title_richtexteditor_help_tab'                          => [
234
+				'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
235
+				'filename' => 'venues_editor_title_richtexteditor',
236
+			],
237
+			'venues_editor_tags_categories_help_tab'                               => [
238
+				'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
239
+				'filename' => 'venues_editor_tags_categories',
240
+			],
241
+			'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
242
+				'title'    => esc_html__(
243
+					'Venue Editor Physical Location & Google Map & Virtual Location',
244
+					'event_espresso'
245
+				),
246
+				'filename' => 'venues_editor_physical_location_google_map_virtual_location',
247
+			],
248
+			'venues_editor_save_new_venue_help_tab'                                => [
249
+				'title'    => esc_html__('Save New Venue', 'event_espresso'),
250
+				'filename' => 'venues_editor_save_new_venue',
251
+			],
252
+			'venues_editor_other_help_tab'                                         => [
253
+				'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
254
+				'filename' => 'venues_editor_other',
255
+			],
256
+		];
257
+
258
+		$this->_page_config = [
259
+			'default'             => [
260
+				'nav'           => [
261
+					'label' => esc_html__('Overview', 'event_espresso'),
262
+					'icon'  => 'dashicons-list-view',
263
+					'order' => 10,
264
+				],
265
+				'list_table'    => 'Venues_Admin_List_Table',
266
+				'help_tabs'     => [
267
+					'venues_overview_help_tab'                           => [
268
+						'title'    => esc_html__('Venues Overview', 'event_espresso'),
269
+						'filename' => 'venues_overview',
270
+					],
271
+					'venues_overview_table_column_headings_help_tab'     => [
272
+						'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
273
+						'filename' => 'venues_overview_table_column_headings',
274
+					],
275
+					'venues_overview_views_bulk_actions_search_help_tab' => [
276
+						'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
277
+						'filename' => 'venues_overview_views_bulk_actions_search',
278
+					],
279
+				],
280
+				'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
281
+				'require_nonce' => false,
282
+			],
283
+			'create_new'          => [
284
+				'nav'           => [
285
+					'label'      => esc_html__('Add Venue', 'event_espresso'),
286
+					'icon'       => 'dashicons-plus-alt',
287
+					'order'      => 15,
288
+					'persistent' => false,
289
+				],
290
+				'help_tabs'     => $help_tabs,
291
+				'metaboxes'     => ['_venue_editor_metaboxes'],
292
+				'require_nonce' => false,
293
+			],
294
+			'edit'                => [
295
+				'nav'           => [
296
+					'label'      => esc_html__('Edit Venue', 'event_espresso'),
297
+					'icon'       => 'dashicons-edit-large',
298
+					'order'      => 15,
299
+					'persistent' => false,
300
+					'url'        => $this->VNU_ID
301
+						? add_query_arg(['post' => $this->VNU_ID], $this->_current_page_view_url)
302
+						: $this->_admin_base_url,
303
+				],
304
+				'help_tabs'     => $help_tabs,
305
+				'metaboxes'     => ['_venue_editor_metaboxes'],
306
+				'require_nonce' => false,
307
+			],
308
+			'google_map_settings' => [
309
+				'nav'           => [
310
+					'label' => esc_html__('Google Maps', 'event_espresso'),
311
+					'icon'  => 'dashicons-location-alt',
312
+					'order' => 40,
313
+				],
314
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
315
+				'help_tabs'     => [
316
+					'general_settings_google_maps_help_tab' => [
317
+						'title'    => esc_html__('Google Maps', 'event_espresso'),
318
+						'filename' => 'general_settings_google_maps',
319
+					],
320
+				],
321
+				'require_nonce' => false,
322
+			],
323
+			// venue category stuff
324
+			'add_category'        => [
325
+				'nav'           => [
326
+					'label'      => esc_html__('Add Category', 'event_espresso'),
327
+					'icon'       => 'dashicons-plus-alt',
328
+					'order'      => 25,
329
+					'persistent' => false,
330
+				],
331
+				'metaboxes'     => ['_publish_post_box'],
332
+				'help_tabs'     => [
333
+					'venues_add_category_help_tab' => [
334
+						'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
335
+						'filename' => 'venues_add_category',
336
+					],
337
+				],
338
+				'require_nonce' => false,
339
+			],
340
+			'edit_category'       => [
341
+				'nav'           => [
342
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
343
+					'icon'       => 'dashicons-edit-large',
344
+					'order'      => 25,
345
+					'persistent' => false,
346
+					'url'        => $EVT_CAT_ID
347
+						? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
348
+						: $this->_admin_base_url,
349
+				],
350
+				'metaboxes'     => ['_publish_post_box'],
351
+				'help_tabs'     => [
352
+					'venues_edit_category_help_tab' => [
353
+						'title'    => esc_html__('Edit Venue Category', 'event_espresso'),
354
+						'filename' => 'venues_edit_category',
355
+					],
356
+				],
357
+				'require_nonce' => false,
358
+			],
359
+			'category_list'       => [
360
+				'nav'           => [
361
+					'label' => esc_html__('Categories', 'event_espresso'),
362
+					'icon'  => 'dashicons-networking',
363
+					'order' => 20,
364
+				],
365
+				'list_table'    => 'Venue_Categories_Admin_List_Table',
366
+				'help_tabs'     => [
367
+					'venues_categories_help_tab'                       => [
368
+						'title'    => esc_html__('Venue Categories', 'event_espresso'),
369
+						'filename' => 'venues_categories',
370
+					],
371
+					'venues_categories_table_column_headings_help_tab' => [
372
+						'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
373
+						'filename' => 'venues_categories_table_column_headings',
374
+					],
375
+					'venues_categories_views_help_tab'                 => [
376
+						'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
377
+						'filename' => 'venues_categories_views',
378
+					],
379
+					'venues_categories_other_help_tab'                 => [
380
+						'title'    => esc_html__('Venue Categories Other', 'event_espresso'),
381
+						'filename' => 'venues_categories_other',
382
+					],
383
+				],
384
+				'metaboxes'     => $this->_default_espresso_metaboxes,
385
+				'require_nonce' => false,
386
+			],
387
+		];
388
+	}
389
+
390
+
391
+	protected function _add_screen_options()
392
+	{
393
+		// todo
394
+	}
395
+
396
+
397
+	protected function _add_screen_options_default()
398
+	{
399
+		$this->_per_page_screen_option();
400
+	}
401
+
402
+
403
+	protected function _add_screen_options_category_list()
404
+	{
405
+		$page_title              = $this->_admin_page_title;
406
+		$this->_admin_page_title = esc_html__('Venue Categories', 'event_espresso');
407
+		$this->_per_page_screen_option();
408
+		$this->_admin_page_title = $page_title;
409
+	}
410
+
411
+
412
+	// none of the below group are currently used for Event Venues
413
+	protected function _add_feature_pointers()
414
+	{
415
+	}
416
+
417
+
418
+	public function admin_init()
419
+	{
420
+	}
421
+
422
+
423
+	public function admin_notices()
424
+	{
425
+	}
426
+
427
+
428
+	public function admin_footer_scripts()
429
+	{
430
+	}
431
+
432
+
433
+	public function load_scripts_styles_create_new()
434
+	{
435
+		$this->load_scripts_styles_edit();
436
+	}
437
+
438
+
439
+	public function load_scripts_styles()
440
+	{
441
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
442
+		wp_enqueue_style('ee-cat-admin');
443
+	}
444
+
445
+
446
+	public function load_scripts_styles_add_category()
447
+	{
448
+		$this->load_scripts_styles_edit_category();
449
+	}
450
+
451
+
452
+	public function load_scripts_styles_edit_category()
453
+	{
454
+	}
455
+
456
+
457
+	public function load_scripts_styles_edit()
458
+	{
459
+		// styles
460
+		wp_enqueue_style('espresso-ui-theme');
461
+		wp_register_style(
462
+			'espresso_venues',
463
+			EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
464
+			[],
465
+			EVENT_ESPRESSO_VERSION
466
+		);
467
+		wp_enqueue_style('espresso_venues');
468
+	}
469
+
470
+
471
+	protected function _set_list_table_views_default()
472
+	{
473
+		$this->_views = [
474
+			'all' => [
475
+				'slug'        => 'all',
476
+				'label'       => esc_html__('View All Venues', 'event_espresso'),
477
+				'count'       => 0,
478
+				'bulk_action' => [],
479
+			],
480
+		];
481
+
482
+		if ($this->capabilities->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
483
+			$this->_views['all']['bulk_action'] = [
484
+				'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
485
+			];
486
+			$this->_views['trash']              = [
487
+				'slug'        => 'trash',
488
+				'label'       => esc_html__('Trash', 'event_espresso'),
489
+				'count'       => 0,
490
+				'bulk_action' => [
491
+					'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
492
+					'delete_venues'  => esc_html__('Delete', 'event_espresso'),
493
+				],
494
+			];
495
+		}
496
+	}
497
+
498
+
499
+	protected function _set_list_table_views_category_list()
500
+	{
501
+		$this->_views = [
502
+			'all' => [
503
+				'slug'        => 'all',
504
+				'label'       => esc_html__('All', 'event_espresso'),
505
+				'count'       => 0,
506
+				'bulk_action' => [
507
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
508
+				],
509
+			],
510
+		];
511
+	}
512
+
513
+
514
+	/**
515
+	 * @throws EE_Error
516
+	 */
517
+	protected function _overview_list_table()
518
+	{
519
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
520
+		$this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
521
+			get_post_type_archive_link(EspressoPostType::VENUES),
522
+			esc_html__("View Venue Archive Page", "event_espresso"),
523
+			'button'
524
+		);
525
+
526
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
527
+				'create_new',
528
+				'add',
529
+				[],
530
+				'add-new-h2'
531
+			);
532
+
533
+		$this->_search_btn_label = esc_html__('Venues', 'event_espresso');
534
+		$this->display_admin_list_table_page_with_sidebar();
535
+	}
536
+
537
+
538
+	/**
539
+	 * @throws EE_Error
540
+	 * @throws ReflectionException
541
+	 */
542
+	public function extra_misc_actions_publish_box()
543
+	{
544
+		$extra_rows = [
545
+			'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
546
+			'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
547
+			'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
548
+		];
549
+		$template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
550
+		EEH_Template::display_template($template, $extra_rows);
551
+	}
552
+
553
+
554
+	/*************        Google Maps        *************
555 555
      *
556 556
      * @throws EE_Error
557 557
      * @throws EE_Error
558 558
      */
559 559
 
560 560
 
561
-    protected function _google_map_settings()
562
-    {
563
-        $this->_template_args['values']           = $this->_yes_no_values;
564
-        $default_map_settings                     = new stdClass();
565
-        $default_map_settings->use_google_maps    = true;
566
-        $default_map_settings->google_map_api_key = '';
567
-        // for event details pages (reg page)
568
-        $default_map_settings->event_details_map_width = 585;
569
-        // ee_map_width_single
570
-        $default_map_settings->event_details_map_height = 362;
571
-        // ee_map_height_single
572
-        $default_map_settings->event_details_map_zoom = 14;
573
-        // ee_map_zoom_single
574
-        $default_map_settings->event_details_display_nav = true;
575
-        // ee_map_nav_display_single
576
-        $default_map_settings->event_details_nav_size = false;
577
-        // ee_map_nav_size_single
578
-        $default_map_settings->event_details_control_type = 'default';
579
-        // ee_map_type_control_single
580
-        $default_map_settings->event_details_map_align = 'center';
581
-        // ee_map_align_single
582
-
583
-        // for event list pages
584
-        $default_map_settings->event_list_map_width = 300;
585
-        // ee_map_width
586
-        $default_map_settings->event_list_map_height = 185;
587
-        // ee_map_height
588
-        $default_map_settings->event_list_map_zoom = 12;
589
-        // ee_map_zoom
590
-        $default_map_settings->event_list_display_nav = false;
591
-        // ee_map_nav_display
592
-        $default_map_settings->event_list_nav_size = true;
593
-        // ee_map_nav_size
594
-        $default_map_settings->event_list_control_type = 'dropdown';
595
-        // ee_map_type_control
596
-        $default_map_settings->event_list_map_align = 'center';
597
-        // ee_map_align
598
-
599
-        $this->_template_args['map_settings'] =
600
-            isset(EE_Registry::instance()->CFG->map_settings)
601
-            && ! empty(EE_Registry::instance()->CFG->map_settings)
602
-                ? (object) array_merge(
603
-                (array) $default_map_settings,
604
-                (array) EE_Registry::instance()->CFG->map_settings
605
-            )
606
-                : $default_map_settings;
607
-
608
-        $this->_set_add_edit_form_tags('update_google_map_settings');
609
-        $this->_set_publish_post_box_vars();
610
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
611
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
612
-            $this->_template_args,
613
-            true
614
-        );
615
-        $this->display_admin_page_with_sidebar();
616
-    }
617
-
618
-
619
-    /**
620
-     * @throws EE_Error
621
-     */
622
-    protected function _update_google_map_settings()
623
-    {
624
-        $map_settings = EE_Registry::instance()->CFG->map_settings;
625
-
626
-        $settings = [
627
-            'use_google_maps'            => 'int',
628
-            'google_map_api_key'         => 'string',
629
-            'event_details_map_width'    => 'int',
630
-            'event_details_map_zoom'     => 'int',
631
-            'event_details_display_nav'  => 'int',
632
-            'event_details_nav_size'     => 'int',
633
-            'event_details_control_type' => 'string',
634
-            'event_details_map_align'    => 'string',
635
-            'event_list_map_width'       => 'int',
636
-            'event_list_map_height'      => 'int',
637
-            'event_list_map_zoom'        => 'int',
638
-            'event_list_display_nav'     => 'int',
639
-            'event_list_nav_size'        => 'int',
640
-            'event_list_control_type'    => 'string',
641
-            'event_list_map_align'       => 'string',
642
-        ];
643
-
644
-        foreach ($settings as $setting => $type) {
645
-            $map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
646
-        }
647
-
648
-        EE_Registry::instance()->CFG->map_settings = apply_filters(
649
-            'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
650
-            $map_settings
651
-        );
652
-
653
-        $what    = 'Google Map Settings';
654
-        $success = $this->_update_espresso_configuration(
655
-            $what,
656
-            EE_Registry::instance()->CFG->map_settings,
657
-            __FILE__,
658
-            __FUNCTION__,
659
-            __LINE__
660
-        );
661
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
662
-    }
663
-
664
-
665
-    /**
666
-     * @throws EE_Error
667
-     * @throws ReflectionException
668
-     */
669
-    protected function _venue_editor_metaboxes()
670
-    {
671
-        $this->verify_cpt_object();
672
-
673
-        $this->addMetaBox(
674
-            'espresso_venue_address_options',
675
-            esc_html__('Physical Location', 'event_espresso'),
676
-            [$this, 'venue_address_metabox'],
677
-            $this->page_slug,
678
-            'side',
679
-            'core'
680
-        );
681
-        $this->addMetaBox(
682
-            'espresso_venue_gmap_options',
683
-            esc_html__('Google Map', 'event_espresso'),
684
-            [$this, 'venue_gmap_metabox'],
685
-            $this->page_slug,
686
-            'side'
687
-        );
688
-        $this->addMetaBox(
689
-            'espresso_venue_virtual_loc_options',
690
-            esc_html__('Virtual Location', 'event_espresso'),
691
-            [$this, 'venue_virtual_loc_metabox'],
692
-            $this->page_slug,
693
-            'side'
694
-        );
695
-    }
696
-
697
-
698
-    /**
699
-     * @throws EE_Error
700
-     * @throws ReflectionException
701
-     */
702
-    public function venue_gmap_metabox()
703
-    {
704
-        $template_args = [
705
-            'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
706
-                'vnu_enable_for_gmap',
707
-                $this->get_yes_no_values(),
708
-                $this->_cpt_model_obj instanceof EE_Venue && $this->_cpt_model_obj->enable_for_gmap()
709
-            ),
710
-            'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
711
-        ];
712
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
713
-        EEH_Template::display_template($template, $template_args);
714
-    }
715
-
716
-
717
-    /**
718
-     * @throws EE_Error
719
-     * @throws ReflectionException
720
-     */
721
-    public function venue_address_metabox()
722
-    {
723
-        $template_args['_venue'] = $this->_cpt_model_obj;
724
-
725
-        $template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
726
-            new EE_Question_Form_Input(
727
-                EE_Question::new_instance(
728
-                    ['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
729
-                ),
730
-                EE_Answer::new_instance(
731
-                    [
732
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
733
-                            ? $this->_cpt_model_obj->state_ID()
734
-                            : 0,
735
-                    ]
736
-                ),
737
-                [
738
-                    'input_name'     => 'sta_id',
739
-                    'input_id'       => 'sta_id',
740
-                    'input_class'    => '',
741
-                    'input_prefix'   => '',
742
-                    'append_qstn_id' => false,
743
-                ]
744
-            )
745
-        );
746
-        $template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
747
-            new EE_Question_Form_Input(
748
-                EE_Question::new_instance(
749
-                    ['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
750
-                ),
751
-                EE_Answer::new_instance(
752
-                    [
753
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
754
-                            ? $this->_cpt_model_obj->country_ID()
755
-                            : 0,
756
-                    ]
757
-                ),
758
-                [
759
-                    'input_name'     => 'cnt_iso',
760
-                    'input_id'       => 'cnt_iso',
761
-                    'input_class'    => '',
762
-                    'input_prefix'   => '',
763
-                    'append_qstn_id' => false,
764
-                ]
765
-            )
766
-        );
767
-
768
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
769
-        EEH_Template::display_template($template, $template_args);
770
-    }
771
-
772
-
773
-    public function venue_virtual_loc_metabox()
774
-    {
775
-        $template_args = [
776
-            '_venue' => $this->_cpt_model_obj,
777
-        ];
778
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
779
-        EEH_Template::display_template($template, $template_args);
780
-    }
781
-
782
-
783
-    /**
784
-     * @throws EE_Error
785
-     * @throws ReflectionException
786
-     */
787
-    protected function _restore_cpt_item($post_id, $revision_id)
788
-    {
789
-        $this->_cpt_model_obj = $this->_venue_model->get_one_by_ID($post_id);
790
-        // meta revision restore
791
-        $this->_cpt_model_obj->restore_revision($revision_id);
792
-    }
793
-
794
-
795
-    /**
796
-     * Handles updates for venue cpts
797
-     *
798
-     * @param int     $post_id ID of Venue CPT
799
-     * @param WP_Post $post    Post object (with "blessed" WP properties)
800
-     * @return void
801
-     * @throws EE_Error
802
-     * @throws ReflectionException
803
-     */
804
-    protected function _insert_update_cpt_item($post_id, $post)
805
-    {
806
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
807
-            return;// get out we're not processing the saving of venues.
808
-        }
809
-
810
-        $wheres = [$this->_venue_model->primary_key_name() => $post_id];
811
-
812
-        $venue_values = [
813
-            'VNU_address'         => $this->request->getRequestParam('vnu_address'),
814
-            'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
815
-            'VNU_city'            => $this->request->getRequestParam('vnu_city'),
816
-            'STA_ID'              => $this->request->getRequestParam('sta_id'),
817
-            'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
818
-            'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
819
-            'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
820
-            'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
821
-                ? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
822
-                : EE_INF,
823
-            'VNU_url'             => $this->request->getRequestParam('vnu_url'),
824
-            'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
825
-            'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
826
-            'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
827
-            'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
828
-        ];
829
-
830
-        // update venue
831
-        $success = $this->_venue_model->update($venue_values, [$wheres]);
832
-
833
-        // get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
834
-        $get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
835
-        $venue         = $this->_venue_model->get_one([$get_one_where]);
836
-
837
-        // notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
838
-        $venue_update_callbacks = apply_filters(
839
-            'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
840
-            []
841
-        );
842
-        $att_success            = true;
843
-        foreach ($venue_update_callbacks as $v_callback) {
844
-            // if ANY of these updates fail then we want the appropriate global error message
845
-            $att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
846
-                ? $att_success
847
-                : false;
848
-        }
849
-
850
-        // any errors?
851
-        if ($success && ! $att_success) {
852
-            EE_Error::add_error(
853
-                esc_html__(
854
-                    'Venue Details saved successfully but something went wrong with saving attachments.',
855
-                    'event_espresso'
856
-                ),
857
-                __FILE__,
858
-                __FUNCTION__,
859
-                __LINE__
860
-            );
861
-        } elseif ($success === false) {
862
-            EE_Error::add_error(
863
-                esc_html__('Venue Details did not save successfully.', 'event_espresso'),
864
-                __FILE__,
865
-                __FUNCTION__,
866
-                __LINE__
867
-            );
868
-        }
869
-    }
870
-
871
-
872
-    /**
873
-     * @param int $post_id
874
-     * @throws EE_Error
875
-     * @throws ReflectionException
876
-     */
877
-    public function trash_cpt_item($post_id)
878
-    {
879
-        $this->request->setRequestParam('VNU_ID', $post_id);
880
-        $this->_trash_or_restore_venue('trash', false);
881
-    }
882
-
883
-
884
-    /**
885
-     * @param int $post_id
886
-     * @throws EE_Error
887
-     * @throws ReflectionException
888
-     */
889
-    public function restore_cpt_item($post_id)
890
-    {
891
-        $this->request->setRequestParam('VNU_ID', $post_id);
892
-        $this->_trash_or_restore_venue('draft', false);
893
-    }
894
-
895
-
896
-    /**
897
-     * @param int $post_id
898
-     * @throws EE_Error
899
-     * @throws ReflectionException
900
-     */
901
-    public function delete_cpt_item($post_id)
902
-    {
903
-        $this->request->setRequestParam('VNU_ID', $post_id);
904
-        $this->_delete_venue(false);
905
-    }
906
-
907
-
908
-    public function get_venue_object()
909
-    {
910
-        return $this->_cpt_model_obj;
911
-    }
912
-
913
-
914
-    /**
915
-     * @param string    $venue_status
916
-     * @param bool|null $redirect_after
917
-     * @throws EE_Error
918
-     * @throws ReflectionException
919
-     */
920
-    protected function _trash_or_restore_venue(string $venue_status = 'trash', ?bool $redirect_after = true)
921
-    {
922
-        // loop thru venues
923
-        if ($this->VNU_ID) {
924
-            // clean status
925
-            $venue_status = sanitize_key($venue_status);
926
-            // grab status
927
-            if (! empty($venue_status)) {
928
-                $success = $this->_change_venue_status($this->VNU_ID, $venue_status);
929
-            } else {
930
-                $success = false;
931
-                $msg     = esc_html__(
932
-                    'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
933
-                    'event_espresso'
934
-                );
935
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
936
-            }
937
-        } else {
938
-            $success = false;
939
-            $msg     = esc_html__(
940
-                'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
941
-                'event_espresso'
942
-            );
943
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
944
-        }
945
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
946
-
947
-        if ($redirect_after) {
948
-            $this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
949
-        }
950
-    }
951
-
952
-
953
-    /**
954
-     * @param string $venue_status
955
-     * @throws EE_Error
956
-     * @throws ReflectionException
957
-     */
958
-    protected function _trash_or_restore_venues(string $venue_status = 'trash')
959
-    {
960
-        // clean status
961
-        $venue_status = sanitize_key($venue_status);
962
-        // grab status
963
-        if (! empty($venue_status)) {
964
-            $success = true;
965
-            // determine the event id and set to array.
966
-            $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
967
-            // loop thru events
968
-            foreach ($VNU_IDs as $VNU_ID) {
969
-                if ($VNU_ID = absint($VNU_ID)) {
970
-                    $results = $this->_change_venue_status($VNU_ID, $venue_status);
971
-                    $success = $results !== false ? $success : false;
972
-                } else {
973
-                    $msg = sprintf(
974
-                        esc_html__(
975
-                            'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
976
-                            'event_espresso'
977
-                        ),
978
-                        $VNU_ID
979
-                    );
980
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
981
-                    $success = false;
982
-                }
983
-            }
984
-        } else {
985
-            $success = false;
986
-            $msg     = esc_html__(
987
-                'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
988
-                'event_espresso'
989
-            );
990
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
991
-        }
992
-        // in order to force a pluralized result message we need to send back a success status greater than 1
993
-        $success = $success ? 2 : false;
994
-        $action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
995
-        $this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
996
-    }
997
-
998
-
999
-    /**
1000
-     * _trash_or_restore_venues
1001
-     * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1002
-     * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1003
-     * accepting a certain number of params.
1004
-     *
1005
-     * @param int|null $VNU_ID
1006
-     * @param string   $venue_status
1007
-     * @return bool
1008
-     * @throws EE_Error
1009
-     * @throws ReflectionException
1010
-     */
1011
-    private function _change_venue_status(?int $VNU_ID = 0, string $venue_status = ''): bool
1012
-    {
1013
-        // grab venue id
1014
-        if (! $VNU_ID) {
1015
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1016
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1017
-            return false;
1018
-        }
1019
-
1020
-        $this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1021
-
1022
-        // clean status
1023
-        $venue_status = sanitize_key($venue_status);
1024
-        // grab status
1025
-        if (! $venue_status) {
1026
-            $msg = esc_html__(
1027
-                'An error occurred. No Venue Status or an invalid Venue Status was received.',
1028
-                'event_espresso'
1029
-            );
1030
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1031
-            return false;
1032
-        }
1033
-
1034
-        // was event trashed or restored ?
1035
-        switch ($venue_status) {
1036
-            case 'draft':
1037
-                $action = 'restored from the trash';
1038
-                $hook   = 'AHEE_venue_restored_from_trash';
1039
-                break;
1040
-            case 'trash':
1041
-                $action = 'moved to the trash';
1042
-                $hook   = 'AHEE_venue_moved_to_trash';
1043
-                break;
1044
-            default:
1045
-                $action = 'updated';
1046
-                $hook   = false;
1047
-        }
1048
-        // use class to change status
1049
-        $this->_cpt_model_obj->set_status($venue_status);
1050
-        $success = $this->_cpt_model_obj->save();
1051
-
1052
-        if ($success === false) {
1053
-            $msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1054
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1055
-            return false;
1056
-        }
1057
-        if ($hook) {
1058
-            do_action($hook);
1059
-        }
1060
-        return true;
1061
-    }
1062
-
1063
-
1064
-    /**
1065
-     * @param bool $redirect_after
1066
-     * @return void
1067
-     * @throws EE_Error
1068
-     * @throws ReflectionException
1069
-     */
1070
-    protected function _delete_venue(bool $redirect_after = true)
1071
-    {
1072
-        // loop thru venues
1073
-        if ($this->VNU_ID) {
1074
-            $success = $this->_delete_or_trash_venue($this->VNU_ID);
1075
-        } else {
1076
-            $success = false;
1077
-            $msg     = esc_html__(
1078
-                'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1079
-                'event_espresso'
1080
-            );
1081
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1082
-        }
1083
-        if ($redirect_after) {
1084
-            $this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1085
-        }
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * @throws EE_Error
1091
-     * @throws ReflectionException
1092
-     */
1093
-    protected function _delete_venues()
1094
-    {
1095
-        $success = true;
1096
-        // determine the event id and set to array.
1097
-        $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1098
-        // loop thru events
1099
-        foreach ($VNU_IDs as $VNU_ID) {
1100
-            if ($VNU_ID = absint($VNU_ID)) {
1101
-                $results = $this->_delete_or_trash_venue($VNU_ID);
1102
-                $success = $results !== false ? $success : false;
1103
-            } else {
1104
-                $success = false;
1105
-                $msg     = esc_html__(
1106
-                    'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1107
-                    'event_espresso'
1108
-                );
1109
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1110
-            }
1111
-        }
1112
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1113
-        $success = $success ? 2 : false;
1114
-        $this->_redirect_after_action(
1115
-            $success,
1116
-            esc_html__('Venues', 'event_espresso'),
1117
-            esc_html__('deleted', 'event_espresso'),
1118
-            ['action' => 'default']
1119
-        );
1120
-    }
1121
-
1122
-
1123
-    // todo: put in parent
1124
-
1125
-
1126
-    /**
1127
-     * @param int|null $VNU_ID
1128
-     * @return bool
1129
-     * @throws EE_Error
1130
-     * @throws ReflectionException
1131
-     */
1132
-    private function _delete_or_trash_venue(?int $VNU_ID = 0): bool
1133
-    {
1134
-        // grab event id
1135
-        if (! $VNU_ID = absint($VNU_ID)) {
1136
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1137
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1138
-            return false;
1139
-        }
1140
-
1141
-
1142
-        $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1143
-        // first need to remove all term relationships
1144
-        $venue->_remove_relations('Term_Taxonomy');
1145
-        $success = $venue->delete_permanently();
1146
-        // did it all go as planned ?
1147
-        if (! $success) {
1148
-            EE_Error::add_error(
1149
-                sprintf(
1150
-                    esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1151
-                    $VNU_ID
1152
-                ),
1153
-                __FILE__,
1154
-                __FUNCTION__,
1155
-                __LINE__
1156
-            );
1157
-            return false;
1158
-        }
1159
-        EE_Error::add_success(
1160
-            sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID)
1161
-        );
1162
-        do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1163
-        return true;
1164
-    }
1165
-
1166
-
1167
-
1168
-
1169
-    /***********/
1170
-    /* QUERIES */
1171
-
1172
-
1173
-    /**
1174
-     * @throws EE_Error
1175
-     * @throws ReflectionException
1176
-     */
1177
-    public function get_venues($per_page = 10, $count = false)
1178
-    {
1179
-        $orderby = $this->request->getRequestParam('orderby', '');
1180
-
1181
-        switch ($orderby) {
1182
-            case 'id':
1183
-                $orderby = 'VNU_ID';
1184
-                break;
1185
-
1186
-            case 'capacity':
1187
-                $orderby = 'VNU_capacity';
1188
-                break;
1189
-
1190
-            case 'city':
1191
-                $orderby = 'VNU_city';
1192
-                break;
1193
-
1194
-            default:
1195
-                $orderby = 'VNU_name';
1196
-        }
1197
-
1198
-        $sort         = $this->request->getRequestParam('order', 'ASC');
1199
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1200
-        $per_page     = ! empty($per_page) ? $per_page : 10;
1201
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1202
-
1203
-        $offset = ($current_page - 1) * $per_page;
1204
-        $limit  = [$offset, $per_page];
1205
-
1206
-        $category = $this->request->getRequestParam('category');
1207
-        $category = $category > 0 ? $category : null;
1208
-
1209
-        $where = [];
1210
-
1211
-        // only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1212
-        $status = $this->request->getRequestParam('status');
1213
-        if ($status && $status !== 'all') {
1214
-            $where['status'] = $status;
1215
-        }
1216
-
1217
-        $venue_status = $this->request->getRequestParam('venue_status');
1218
-        if ($venue_status) {
1219
-            $where['status'] = $venue_status;
1220
-        }
1221
-
1222
-
1223
-        if ($category) {
1224
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1225
-            $where['Term_Taxonomy.term_id']  = $category;
1226
-        }
1227
-
1228
-
1229
-        if (! $this->capabilities->current_user_can('ee_read_others_venues', 'get_venues')) {
1230
-            $where['VNU_wp_user'] = get_current_user_id();
1231
-        } else {
1232
-            if (! $this->capabilities->current_user_can('ee_read_private_venues', 'get_venues')) {
1233
-                $where['OR'] = [
1234
-                    'status*restrict_private' => ['!=', 'private'],
1235
-                    'AND'                     => [
1236
-                        'status*inclusive' => ['=', 'private'],
1237
-                        'VNU_wp_user'      => get_current_user_id(),
1238
-                    ],
1239
-                ];
1240
-            }
1241
-        }
1242
-
1243
-        $search_term = $this->request->getRequestParam('s');
1244
-        if ($search_term) {
1245
-            $search_term = '%' . $search_term . '%';
1246
-            $where['OR'] = [
1247
-                'VNU_name'               => ['LIKE', $search_term],
1248
-                'VNU_desc'               => ['LIKE', $search_term],
1249
-                'VNU_short_desc'         => ['LIKE', $search_term],
1250
-                'VNU_address'            => ['LIKE', $search_term],
1251
-                'VNU_address2'           => ['LIKE', $search_term],
1252
-                'VNU_city'               => ['LIKE', $search_term],
1253
-                'VNU_zip'                => ['LIKE', $search_term],
1254
-                'VNU_phone'              => ['LIKE', $search_term],
1255
-                'VNU_url'                => ['LIKE', $search_term],
1256
-                'VNU_virtual_phone'      => ['LIKE', $search_term],
1257
-                'VNU_virtual_url'        => ['LIKE', $search_term],
1258
-                'VNU_google_map_link'    => ['LIKE', $search_term],
1259
-                'Event.EVT_name'         => ['LIKE', $search_term],
1260
-                'Event.EVT_desc'         => ['LIKE', $search_term],
1261
-                'Event.EVT_phone'        => ['LIKE', $search_term],
1262
-                'Event.EVT_external_URL' => ['LIKE', $search_term],
1263
-            ];
1264
-        }
1265
-
1266
-
1267
-        return $count
1268
-            ? $this->_venue_model->count([$where], 'VNU_ID')
1269
-            : $this->_venue_model->get_all(
1270
-                [$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1271
-            );
1272
-    }
1273
-
1274
-
1275
-
1276
-
1277
-    /** Venue Category Stuff **/
1278
-
1279
-    /**
1280
-     * set the _category property with the category object for the loaded page.
1281
-     *
1282
-     * @access private
1283
-     * @return void
1284
-     */
1285
-    private function _set_category_object()
1286
-    {
1287
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
1288
-            return;
1289
-        } // already have the category object so get out.
1290
-
1291
-        // set default category object
1292
-        $this->_set_empty_category_object();
1293
-
1294
-        // only set if we've got an id
1295
-        $category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1296
-        if (! $category_ID) {
1297
-            return;
1298
-        }
1299
-
1300
-        $term = get_term($category_ID, 'espresso_venue_categories');
1301
-
1302
-
1303
-        if (! empty($term)) {
1304
-            $this->_category->category_name       = $term->name;
1305
-            $this->_category->category_identifier = $term->slug;
1306
-            $this->_category->category_desc       = $term->description;
1307
-            $this->_category->id                  = $term->term_id;
1308
-            $this->_category->parent              = $term->parent;
1309
-        }
1310
-    }
1311
-
1312
-
1313
-    private function _set_empty_category_object()
1314
-    {
1315
-        $this->_category                = new stdClass();
1316
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1317
-        $this->_category->id            = $this->_category->parent = 0;
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     * @throws EE_Error
1323
-     */
1324
-    protected function _category_list_table()
1325
-    {
1326
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1327
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1328
-                'add_category',
1329
-                'add_category',
1330
-                [],
1331
-                'add-new-h2'
1332
-            );
1333
-        $this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1334
-        $this->display_admin_list_table_page_with_sidebar();
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     * @throws EE_Error
1340
-     */
1341
-    protected function _category_details($view)
1342
-    {
1343
-        // load formatter helper
1344
-        // load field generator helper
1345
-
1346
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
1347
-        $this->_set_add_edit_form_tags($route);
1348
-
1349
-        $this->_set_category_object();
1350
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
1351
-
1352
-        $delete_action = 'delete_category';
1353
-
1354
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1355
-
1356
-        $this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1357
-
1358
-        // take care of contents
1359
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
1360
-        $this->display_admin_page_with_sidebar();
1361
-    }
1362
-
1363
-
1364
-    protected function _category_details_content(): string
1365
-    {
1366
-        $editor_args['category_desc'] = [
1367
-            'type'          => 'wp_editor',
1368
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1369
-            'class'         => 'my_editor_custom',
1370
-            'wpeditor_args' => ['media_buttons' => false],
1371
-        ];
1372
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1373
-
1374
-        $all_terms = get_terms(
1375
-            ['espresso_venue_categories'],
1376
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1377
-        );
1378
-
1379
-        // setup category select for term parents.
1380
-        $category_select_values[] = [
1381
-            'text' => esc_html__('No Parent', 'event_espresso'),
1382
-            'id'   => 0,
1383
-        ];
1384
-        foreach ($all_terms as $term) {
1385
-            $category_select_values[] = [
1386
-                'text' => $term->name,
1387
-                'id'   => $term->term_id,
1388
-            ];
1389
-        }
1390
-
1391
-        $category_select = EEH_Form_Fields::select_input(
1392
-            'category_parent',
1393
-            $category_select_values,
1394
-            $this->_category->parent
1395
-        );
1396
-        $template_args   = [
1397
-            'category'                 => $this->_category,
1398
-            'category_select'          => $category_select,
1399
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1400
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1401
-            'disable'                  => '',
1402
-            'disabled_message'         => false,
1403
-        ];
1404
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1405
-        return EEH_Template::display_template($template, $template_args, true);
1406
-    }
1407
-
1408
-
1409
-    /**
1410
-     * @throws EE_Error
1411
-     */
1412
-    protected function _delete_categories()
1413
-    {
1414
-        $category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1415
-        $category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1416
-
1417
-        foreach ($category_IDs as $cat_id) {
1418
-            $this->_delete_category($cat_id);
1419
-        }
1420
-
1421
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
1422
-        $query_args = [
1423
-            'action' => 'category_list',
1424
-        ];
1425
-        $this->_redirect_after_action(0, '', '', $query_args);
1426
-    }
1427
-
1428
-
1429
-    protected function _delete_category($cat_id)
1430
-    {
1431
-        $cat_id = absint($cat_id);
1432
-        wp_delete_term($cat_id, 'espresso_venue_categories');
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * @throws EE_Error
1438
-     */
1439
-    protected function _insert_or_update_category($new_category)
1440
-    {
1441
-        $cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1442
-        $success = 0; // we already have a success message so lets not send another.
1443
-        if ($cat_id) {
1444
-            $query_args = [
1445
-                'action'     => 'edit_category',
1446
-                'VEN_CAT_ID' => $cat_id,
1447
-            ];
1448
-        } else {
1449
-            $query_args = ['action' => 'add_category'];
1450
-        }
1451
-        $this->_redirect_after_action($success, '', '', $query_args, true);
1452
-    }
1453
-
1454
-
1455
-    private function _insert_category($update = false)
1456
-    {
1457
-        $category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1458
-        $category_name   = $this->request->getRequestParam('category_name', '');
1459
-        $category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1460
-        $category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1461
-
1462
-        if (empty($category_name)) {
1463
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
1464
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1465
-            return false;
1466
-        }
1467
-
1468
-
1469
-        $term_args = [
1470
-            'name'        => $category_name,
1471
-            'description' => $category_desc,
1472
-            'parent'      => $category_parent,
1473
-        ];
1474
-
1475
-        $insert_ids = $update
1476
-            ? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1477
-            : wp_insert_term(
1478
-                $category_name,
1479
-                'espresso_venue_categories',
1480
-                $term_args
1481
-            );
1482
-
1483
-        if (! is_array($insert_ids)) {
1484
-            EE_Error::add_error(
1485
-                esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1486
-                __FILE__,
1487
-                __FUNCTION__,
1488
-                __LINE__
1489
-            );
1490
-        } else {
1491
-            $category_ID = $insert_ids['term_id'];
1492
-            EE_Error::add_success(
1493
-                sprintf(
1494
-                    esc_html__('The category %s was successfully created', 'event_espresso'),
1495
-                    $category_name
1496
-                )
1497
-            );
1498
-        }
1499
-
1500
-        return $category_ID;
1501
-    }
1502
-
1503
-
1504
-    /**
1505
-     * TODO handle category exports()
1506
-     *
1507
-     * @return void
1508
-     */
1509
-    protected function _categories_export()
1510
-    {
1511
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
1512
-        $this->request->mergeRequestParams(
1513
-            [
1514
-                'export'       => 'report',
1515
-                'action'       => 'categories',
1516
-                'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1517
-            ]
1518
-        );
1519
-
1520
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1521
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1522
-            $EE_Export = EE_Export::instance($this->request->requestParams());
1523
-            $EE_Export->export();
1524
-        }
1525
-    }
1526
-
1527
-
1528
-    protected function _import_categories()
1529
-    {
1530
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1531
-        EE_Import::instance()->import();
1532
-    }
1533
-
1534
-
1535
-    /**
1536
-     * @throws EE_Error
1537
-     * @throws ReflectionException
1538
-     */
1539
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
1540
-    {
1541
-        // testing term stuff
1542
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1543
-        $order       = $this->request->getRequestParam('order', 'DESC');
1544
-        $limit       = ($current_page - 1) * $per_page;
1545
-        $where       = ['taxonomy' => 'espresso_venue_categories'];
1546
-        $search_term = $this->request->getRequestParam('s');
1547
-        if ($search_term) {
1548
-            $search_term = '%' . $search_term . '%';
1549
-            $where['OR'] = [
1550
-                'Term.name'   => ['LIKE', $search_term],
1551
-                'description' => ['LIKE', $search_term],
1552
-            ];
1553
-        }
1554
-
1555
-        $query_params = [
1556
-            $where,
1557
-            'order_by'   => [$orderby => $order],
1558
-            'limit'      => $limit . ',' . $per_page,
1559
-            'force_join' => ['Term'],
1560
-        ];
1561
-
1562
-        return $count
1563
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1564
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
1565
-    }
1566
-
1567
-
1568
-    /* end category stuff */
1569
-    /**************/
561
+	protected function _google_map_settings()
562
+	{
563
+		$this->_template_args['values']           = $this->_yes_no_values;
564
+		$default_map_settings                     = new stdClass();
565
+		$default_map_settings->use_google_maps    = true;
566
+		$default_map_settings->google_map_api_key = '';
567
+		// for event details pages (reg page)
568
+		$default_map_settings->event_details_map_width = 585;
569
+		// ee_map_width_single
570
+		$default_map_settings->event_details_map_height = 362;
571
+		// ee_map_height_single
572
+		$default_map_settings->event_details_map_zoom = 14;
573
+		// ee_map_zoom_single
574
+		$default_map_settings->event_details_display_nav = true;
575
+		// ee_map_nav_display_single
576
+		$default_map_settings->event_details_nav_size = false;
577
+		// ee_map_nav_size_single
578
+		$default_map_settings->event_details_control_type = 'default';
579
+		// ee_map_type_control_single
580
+		$default_map_settings->event_details_map_align = 'center';
581
+		// ee_map_align_single
582
+
583
+		// for event list pages
584
+		$default_map_settings->event_list_map_width = 300;
585
+		// ee_map_width
586
+		$default_map_settings->event_list_map_height = 185;
587
+		// ee_map_height
588
+		$default_map_settings->event_list_map_zoom = 12;
589
+		// ee_map_zoom
590
+		$default_map_settings->event_list_display_nav = false;
591
+		// ee_map_nav_display
592
+		$default_map_settings->event_list_nav_size = true;
593
+		// ee_map_nav_size
594
+		$default_map_settings->event_list_control_type = 'dropdown';
595
+		// ee_map_type_control
596
+		$default_map_settings->event_list_map_align = 'center';
597
+		// ee_map_align
598
+
599
+		$this->_template_args['map_settings'] =
600
+			isset(EE_Registry::instance()->CFG->map_settings)
601
+			&& ! empty(EE_Registry::instance()->CFG->map_settings)
602
+				? (object) array_merge(
603
+				(array) $default_map_settings,
604
+				(array) EE_Registry::instance()->CFG->map_settings
605
+			)
606
+				: $default_map_settings;
607
+
608
+		$this->_set_add_edit_form_tags('update_google_map_settings');
609
+		$this->_set_publish_post_box_vars();
610
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
611
+			EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
612
+			$this->_template_args,
613
+			true
614
+		);
615
+		$this->display_admin_page_with_sidebar();
616
+	}
617
+
618
+
619
+	/**
620
+	 * @throws EE_Error
621
+	 */
622
+	protected function _update_google_map_settings()
623
+	{
624
+		$map_settings = EE_Registry::instance()->CFG->map_settings;
625
+
626
+		$settings = [
627
+			'use_google_maps'            => 'int',
628
+			'google_map_api_key'         => 'string',
629
+			'event_details_map_width'    => 'int',
630
+			'event_details_map_zoom'     => 'int',
631
+			'event_details_display_nav'  => 'int',
632
+			'event_details_nav_size'     => 'int',
633
+			'event_details_control_type' => 'string',
634
+			'event_details_map_align'    => 'string',
635
+			'event_list_map_width'       => 'int',
636
+			'event_list_map_height'      => 'int',
637
+			'event_list_map_zoom'        => 'int',
638
+			'event_list_display_nav'     => 'int',
639
+			'event_list_nav_size'        => 'int',
640
+			'event_list_control_type'    => 'string',
641
+			'event_list_map_align'       => 'string',
642
+		];
643
+
644
+		foreach ($settings as $setting => $type) {
645
+			$map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
646
+		}
647
+
648
+		EE_Registry::instance()->CFG->map_settings = apply_filters(
649
+			'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
650
+			$map_settings
651
+		);
652
+
653
+		$what    = 'Google Map Settings';
654
+		$success = $this->_update_espresso_configuration(
655
+			$what,
656
+			EE_Registry::instance()->CFG->map_settings,
657
+			__FILE__,
658
+			__FUNCTION__,
659
+			__LINE__
660
+		);
661
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
662
+	}
663
+
664
+
665
+	/**
666
+	 * @throws EE_Error
667
+	 * @throws ReflectionException
668
+	 */
669
+	protected function _venue_editor_metaboxes()
670
+	{
671
+		$this->verify_cpt_object();
672
+
673
+		$this->addMetaBox(
674
+			'espresso_venue_address_options',
675
+			esc_html__('Physical Location', 'event_espresso'),
676
+			[$this, 'venue_address_metabox'],
677
+			$this->page_slug,
678
+			'side',
679
+			'core'
680
+		);
681
+		$this->addMetaBox(
682
+			'espresso_venue_gmap_options',
683
+			esc_html__('Google Map', 'event_espresso'),
684
+			[$this, 'venue_gmap_metabox'],
685
+			$this->page_slug,
686
+			'side'
687
+		);
688
+		$this->addMetaBox(
689
+			'espresso_venue_virtual_loc_options',
690
+			esc_html__('Virtual Location', 'event_espresso'),
691
+			[$this, 'venue_virtual_loc_metabox'],
692
+			$this->page_slug,
693
+			'side'
694
+		);
695
+	}
696
+
697
+
698
+	/**
699
+	 * @throws EE_Error
700
+	 * @throws ReflectionException
701
+	 */
702
+	public function venue_gmap_metabox()
703
+	{
704
+		$template_args = [
705
+			'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
706
+				'vnu_enable_for_gmap',
707
+				$this->get_yes_no_values(),
708
+				$this->_cpt_model_obj instanceof EE_Venue && $this->_cpt_model_obj->enable_for_gmap()
709
+			),
710
+			'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
711
+		];
712
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
713
+		EEH_Template::display_template($template, $template_args);
714
+	}
715
+
716
+
717
+	/**
718
+	 * @throws EE_Error
719
+	 * @throws ReflectionException
720
+	 */
721
+	public function venue_address_metabox()
722
+	{
723
+		$template_args['_venue'] = $this->_cpt_model_obj;
724
+
725
+		$template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
726
+			new EE_Question_Form_Input(
727
+				EE_Question::new_instance(
728
+					['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
729
+				),
730
+				EE_Answer::new_instance(
731
+					[
732
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
733
+							? $this->_cpt_model_obj->state_ID()
734
+							: 0,
735
+					]
736
+				),
737
+				[
738
+					'input_name'     => 'sta_id',
739
+					'input_id'       => 'sta_id',
740
+					'input_class'    => '',
741
+					'input_prefix'   => '',
742
+					'append_qstn_id' => false,
743
+				]
744
+			)
745
+		);
746
+		$template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
747
+			new EE_Question_Form_Input(
748
+				EE_Question::new_instance(
749
+					['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
750
+				),
751
+				EE_Answer::new_instance(
752
+					[
753
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
754
+							? $this->_cpt_model_obj->country_ID()
755
+							: 0,
756
+					]
757
+				),
758
+				[
759
+					'input_name'     => 'cnt_iso',
760
+					'input_id'       => 'cnt_iso',
761
+					'input_class'    => '',
762
+					'input_prefix'   => '',
763
+					'append_qstn_id' => false,
764
+				]
765
+			)
766
+		);
767
+
768
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
769
+		EEH_Template::display_template($template, $template_args);
770
+	}
771
+
772
+
773
+	public function venue_virtual_loc_metabox()
774
+	{
775
+		$template_args = [
776
+			'_venue' => $this->_cpt_model_obj,
777
+		];
778
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
779
+		EEH_Template::display_template($template, $template_args);
780
+	}
781
+
782
+
783
+	/**
784
+	 * @throws EE_Error
785
+	 * @throws ReflectionException
786
+	 */
787
+	protected function _restore_cpt_item($post_id, $revision_id)
788
+	{
789
+		$this->_cpt_model_obj = $this->_venue_model->get_one_by_ID($post_id);
790
+		// meta revision restore
791
+		$this->_cpt_model_obj->restore_revision($revision_id);
792
+	}
793
+
794
+
795
+	/**
796
+	 * Handles updates for venue cpts
797
+	 *
798
+	 * @param int     $post_id ID of Venue CPT
799
+	 * @param WP_Post $post    Post object (with "blessed" WP properties)
800
+	 * @return void
801
+	 * @throws EE_Error
802
+	 * @throws ReflectionException
803
+	 */
804
+	protected function _insert_update_cpt_item($post_id, $post)
805
+	{
806
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
807
+			return;// get out we're not processing the saving of venues.
808
+		}
809
+
810
+		$wheres = [$this->_venue_model->primary_key_name() => $post_id];
811
+
812
+		$venue_values = [
813
+			'VNU_address'         => $this->request->getRequestParam('vnu_address'),
814
+			'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
815
+			'VNU_city'            => $this->request->getRequestParam('vnu_city'),
816
+			'STA_ID'              => $this->request->getRequestParam('sta_id'),
817
+			'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
818
+			'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
819
+			'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
820
+			'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
821
+				? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
822
+				: EE_INF,
823
+			'VNU_url'             => $this->request->getRequestParam('vnu_url'),
824
+			'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
825
+			'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
826
+			'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
827
+			'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
828
+		];
829
+
830
+		// update venue
831
+		$success = $this->_venue_model->update($venue_values, [$wheres]);
832
+
833
+		// get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
834
+		$get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
835
+		$venue         = $this->_venue_model->get_one([$get_one_where]);
836
+
837
+		// notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
838
+		$venue_update_callbacks = apply_filters(
839
+			'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
840
+			[]
841
+		);
842
+		$att_success            = true;
843
+		foreach ($venue_update_callbacks as $v_callback) {
844
+			// if ANY of these updates fail then we want the appropriate global error message
845
+			$att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
846
+				? $att_success
847
+				: false;
848
+		}
849
+
850
+		// any errors?
851
+		if ($success && ! $att_success) {
852
+			EE_Error::add_error(
853
+				esc_html__(
854
+					'Venue Details saved successfully but something went wrong with saving attachments.',
855
+					'event_espresso'
856
+				),
857
+				__FILE__,
858
+				__FUNCTION__,
859
+				__LINE__
860
+			);
861
+		} elseif ($success === false) {
862
+			EE_Error::add_error(
863
+				esc_html__('Venue Details did not save successfully.', 'event_espresso'),
864
+				__FILE__,
865
+				__FUNCTION__,
866
+				__LINE__
867
+			);
868
+		}
869
+	}
870
+
871
+
872
+	/**
873
+	 * @param int $post_id
874
+	 * @throws EE_Error
875
+	 * @throws ReflectionException
876
+	 */
877
+	public function trash_cpt_item($post_id)
878
+	{
879
+		$this->request->setRequestParam('VNU_ID', $post_id);
880
+		$this->_trash_or_restore_venue('trash', false);
881
+	}
882
+
883
+
884
+	/**
885
+	 * @param int $post_id
886
+	 * @throws EE_Error
887
+	 * @throws ReflectionException
888
+	 */
889
+	public function restore_cpt_item($post_id)
890
+	{
891
+		$this->request->setRequestParam('VNU_ID', $post_id);
892
+		$this->_trash_or_restore_venue('draft', false);
893
+	}
894
+
895
+
896
+	/**
897
+	 * @param int $post_id
898
+	 * @throws EE_Error
899
+	 * @throws ReflectionException
900
+	 */
901
+	public function delete_cpt_item($post_id)
902
+	{
903
+		$this->request->setRequestParam('VNU_ID', $post_id);
904
+		$this->_delete_venue(false);
905
+	}
906
+
907
+
908
+	public function get_venue_object()
909
+	{
910
+		return $this->_cpt_model_obj;
911
+	}
912
+
913
+
914
+	/**
915
+	 * @param string    $venue_status
916
+	 * @param bool|null $redirect_after
917
+	 * @throws EE_Error
918
+	 * @throws ReflectionException
919
+	 */
920
+	protected function _trash_or_restore_venue(string $venue_status = 'trash', ?bool $redirect_after = true)
921
+	{
922
+		// loop thru venues
923
+		if ($this->VNU_ID) {
924
+			// clean status
925
+			$venue_status = sanitize_key($venue_status);
926
+			// grab status
927
+			if (! empty($venue_status)) {
928
+				$success = $this->_change_venue_status($this->VNU_ID, $venue_status);
929
+			} else {
930
+				$success = false;
931
+				$msg     = esc_html__(
932
+					'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
933
+					'event_espresso'
934
+				);
935
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
936
+			}
937
+		} else {
938
+			$success = false;
939
+			$msg     = esc_html__(
940
+				'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
941
+				'event_espresso'
942
+			);
943
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
944
+		}
945
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
946
+
947
+		if ($redirect_after) {
948
+			$this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
949
+		}
950
+	}
951
+
952
+
953
+	/**
954
+	 * @param string $venue_status
955
+	 * @throws EE_Error
956
+	 * @throws ReflectionException
957
+	 */
958
+	protected function _trash_or_restore_venues(string $venue_status = 'trash')
959
+	{
960
+		// clean status
961
+		$venue_status = sanitize_key($venue_status);
962
+		// grab status
963
+		if (! empty($venue_status)) {
964
+			$success = true;
965
+			// determine the event id and set to array.
966
+			$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
967
+			// loop thru events
968
+			foreach ($VNU_IDs as $VNU_ID) {
969
+				if ($VNU_ID = absint($VNU_ID)) {
970
+					$results = $this->_change_venue_status($VNU_ID, $venue_status);
971
+					$success = $results !== false ? $success : false;
972
+				} else {
973
+					$msg = sprintf(
974
+						esc_html__(
975
+							'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
976
+							'event_espresso'
977
+						),
978
+						$VNU_ID
979
+					);
980
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
981
+					$success = false;
982
+				}
983
+			}
984
+		} else {
985
+			$success = false;
986
+			$msg     = esc_html__(
987
+				'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
988
+				'event_espresso'
989
+			);
990
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
991
+		}
992
+		// in order to force a pluralized result message we need to send back a success status greater than 1
993
+		$success = $success ? 2 : false;
994
+		$action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
995
+		$this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
996
+	}
997
+
998
+
999
+	/**
1000
+	 * _trash_or_restore_venues
1001
+	 * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1002
+	 * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1003
+	 * accepting a certain number of params.
1004
+	 *
1005
+	 * @param int|null $VNU_ID
1006
+	 * @param string   $venue_status
1007
+	 * @return bool
1008
+	 * @throws EE_Error
1009
+	 * @throws ReflectionException
1010
+	 */
1011
+	private function _change_venue_status(?int $VNU_ID = 0, string $venue_status = ''): bool
1012
+	{
1013
+		// grab venue id
1014
+		if (! $VNU_ID) {
1015
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1016
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1017
+			return false;
1018
+		}
1019
+
1020
+		$this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1021
+
1022
+		// clean status
1023
+		$venue_status = sanitize_key($venue_status);
1024
+		// grab status
1025
+		if (! $venue_status) {
1026
+			$msg = esc_html__(
1027
+				'An error occurred. No Venue Status or an invalid Venue Status was received.',
1028
+				'event_espresso'
1029
+			);
1030
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1031
+			return false;
1032
+		}
1033
+
1034
+		// was event trashed or restored ?
1035
+		switch ($venue_status) {
1036
+			case 'draft':
1037
+				$action = 'restored from the trash';
1038
+				$hook   = 'AHEE_venue_restored_from_trash';
1039
+				break;
1040
+			case 'trash':
1041
+				$action = 'moved to the trash';
1042
+				$hook   = 'AHEE_venue_moved_to_trash';
1043
+				break;
1044
+			default:
1045
+				$action = 'updated';
1046
+				$hook   = false;
1047
+		}
1048
+		// use class to change status
1049
+		$this->_cpt_model_obj->set_status($venue_status);
1050
+		$success = $this->_cpt_model_obj->save();
1051
+
1052
+		if ($success === false) {
1053
+			$msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1054
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1055
+			return false;
1056
+		}
1057
+		if ($hook) {
1058
+			do_action($hook);
1059
+		}
1060
+		return true;
1061
+	}
1062
+
1063
+
1064
+	/**
1065
+	 * @param bool $redirect_after
1066
+	 * @return void
1067
+	 * @throws EE_Error
1068
+	 * @throws ReflectionException
1069
+	 */
1070
+	protected function _delete_venue(bool $redirect_after = true)
1071
+	{
1072
+		// loop thru venues
1073
+		if ($this->VNU_ID) {
1074
+			$success = $this->_delete_or_trash_venue($this->VNU_ID);
1075
+		} else {
1076
+			$success = false;
1077
+			$msg     = esc_html__(
1078
+				'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1079
+				'event_espresso'
1080
+			);
1081
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1082
+		}
1083
+		if ($redirect_after) {
1084
+			$this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1085
+		}
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * @throws EE_Error
1091
+	 * @throws ReflectionException
1092
+	 */
1093
+	protected function _delete_venues()
1094
+	{
1095
+		$success = true;
1096
+		// determine the event id and set to array.
1097
+		$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1098
+		// loop thru events
1099
+		foreach ($VNU_IDs as $VNU_ID) {
1100
+			if ($VNU_ID = absint($VNU_ID)) {
1101
+				$results = $this->_delete_or_trash_venue($VNU_ID);
1102
+				$success = $results !== false ? $success : false;
1103
+			} else {
1104
+				$success = false;
1105
+				$msg     = esc_html__(
1106
+					'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1107
+					'event_espresso'
1108
+				);
1109
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1110
+			}
1111
+		}
1112
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1113
+		$success = $success ? 2 : false;
1114
+		$this->_redirect_after_action(
1115
+			$success,
1116
+			esc_html__('Venues', 'event_espresso'),
1117
+			esc_html__('deleted', 'event_espresso'),
1118
+			['action' => 'default']
1119
+		);
1120
+	}
1121
+
1122
+
1123
+	// todo: put in parent
1124
+
1125
+
1126
+	/**
1127
+	 * @param int|null $VNU_ID
1128
+	 * @return bool
1129
+	 * @throws EE_Error
1130
+	 * @throws ReflectionException
1131
+	 */
1132
+	private function _delete_or_trash_venue(?int $VNU_ID = 0): bool
1133
+	{
1134
+		// grab event id
1135
+		if (! $VNU_ID = absint($VNU_ID)) {
1136
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1137
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1138
+			return false;
1139
+		}
1140
+
1141
+
1142
+		$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1143
+		// first need to remove all term relationships
1144
+		$venue->_remove_relations('Term_Taxonomy');
1145
+		$success = $venue->delete_permanently();
1146
+		// did it all go as planned ?
1147
+		if (! $success) {
1148
+			EE_Error::add_error(
1149
+				sprintf(
1150
+					esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1151
+					$VNU_ID
1152
+				),
1153
+				__FILE__,
1154
+				__FUNCTION__,
1155
+				__LINE__
1156
+			);
1157
+			return false;
1158
+		}
1159
+		EE_Error::add_success(
1160
+			sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID)
1161
+		);
1162
+		do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1163
+		return true;
1164
+	}
1165
+
1166
+
1167
+
1168
+
1169
+	/***********/
1170
+	/* QUERIES */
1171
+
1172
+
1173
+	/**
1174
+	 * @throws EE_Error
1175
+	 * @throws ReflectionException
1176
+	 */
1177
+	public function get_venues($per_page = 10, $count = false)
1178
+	{
1179
+		$orderby = $this->request->getRequestParam('orderby', '');
1180
+
1181
+		switch ($orderby) {
1182
+			case 'id':
1183
+				$orderby = 'VNU_ID';
1184
+				break;
1185
+
1186
+			case 'capacity':
1187
+				$orderby = 'VNU_capacity';
1188
+				break;
1189
+
1190
+			case 'city':
1191
+				$orderby = 'VNU_city';
1192
+				break;
1193
+
1194
+			default:
1195
+				$orderby = 'VNU_name';
1196
+		}
1197
+
1198
+		$sort         = $this->request->getRequestParam('order', 'ASC');
1199
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1200
+		$per_page     = ! empty($per_page) ? $per_page : 10;
1201
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1202
+
1203
+		$offset = ($current_page - 1) * $per_page;
1204
+		$limit  = [$offset, $per_page];
1205
+
1206
+		$category = $this->request->getRequestParam('category');
1207
+		$category = $category > 0 ? $category : null;
1208
+
1209
+		$where = [];
1210
+
1211
+		// only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1212
+		$status = $this->request->getRequestParam('status');
1213
+		if ($status && $status !== 'all') {
1214
+			$where['status'] = $status;
1215
+		}
1216
+
1217
+		$venue_status = $this->request->getRequestParam('venue_status');
1218
+		if ($venue_status) {
1219
+			$where['status'] = $venue_status;
1220
+		}
1221
+
1222
+
1223
+		if ($category) {
1224
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1225
+			$where['Term_Taxonomy.term_id']  = $category;
1226
+		}
1227
+
1228
+
1229
+		if (! $this->capabilities->current_user_can('ee_read_others_venues', 'get_venues')) {
1230
+			$where['VNU_wp_user'] = get_current_user_id();
1231
+		} else {
1232
+			if (! $this->capabilities->current_user_can('ee_read_private_venues', 'get_venues')) {
1233
+				$where['OR'] = [
1234
+					'status*restrict_private' => ['!=', 'private'],
1235
+					'AND'                     => [
1236
+						'status*inclusive' => ['=', 'private'],
1237
+						'VNU_wp_user'      => get_current_user_id(),
1238
+					],
1239
+				];
1240
+			}
1241
+		}
1242
+
1243
+		$search_term = $this->request->getRequestParam('s');
1244
+		if ($search_term) {
1245
+			$search_term = '%' . $search_term . '%';
1246
+			$where['OR'] = [
1247
+				'VNU_name'               => ['LIKE', $search_term],
1248
+				'VNU_desc'               => ['LIKE', $search_term],
1249
+				'VNU_short_desc'         => ['LIKE', $search_term],
1250
+				'VNU_address'            => ['LIKE', $search_term],
1251
+				'VNU_address2'           => ['LIKE', $search_term],
1252
+				'VNU_city'               => ['LIKE', $search_term],
1253
+				'VNU_zip'                => ['LIKE', $search_term],
1254
+				'VNU_phone'              => ['LIKE', $search_term],
1255
+				'VNU_url'                => ['LIKE', $search_term],
1256
+				'VNU_virtual_phone'      => ['LIKE', $search_term],
1257
+				'VNU_virtual_url'        => ['LIKE', $search_term],
1258
+				'VNU_google_map_link'    => ['LIKE', $search_term],
1259
+				'Event.EVT_name'         => ['LIKE', $search_term],
1260
+				'Event.EVT_desc'         => ['LIKE', $search_term],
1261
+				'Event.EVT_phone'        => ['LIKE', $search_term],
1262
+				'Event.EVT_external_URL' => ['LIKE', $search_term],
1263
+			];
1264
+		}
1265
+
1266
+
1267
+		return $count
1268
+			? $this->_venue_model->count([$where], 'VNU_ID')
1269
+			: $this->_venue_model->get_all(
1270
+				[$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1271
+			);
1272
+	}
1273
+
1274
+
1275
+
1276
+
1277
+	/** Venue Category Stuff **/
1278
+
1279
+	/**
1280
+	 * set the _category property with the category object for the loaded page.
1281
+	 *
1282
+	 * @access private
1283
+	 * @return void
1284
+	 */
1285
+	private function _set_category_object()
1286
+	{
1287
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
1288
+			return;
1289
+		} // already have the category object so get out.
1290
+
1291
+		// set default category object
1292
+		$this->_set_empty_category_object();
1293
+
1294
+		// only set if we've got an id
1295
+		$category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1296
+		if (! $category_ID) {
1297
+			return;
1298
+		}
1299
+
1300
+		$term = get_term($category_ID, 'espresso_venue_categories');
1301
+
1302
+
1303
+		if (! empty($term)) {
1304
+			$this->_category->category_name       = $term->name;
1305
+			$this->_category->category_identifier = $term->slug;
1306
+			$this->_category->category_desc       = $term->description;
1307
+			$this->_category->id                  = $term->term_id;
1308
+			$this->_category->parent              = $term->parent;
1309
+		}
1310
+	}
1311
+
1312
+
1313
+	private function _set_empty_category_object()
1314
+	{
1315
+		$this->_category                = new stdClass();
1316
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1317
+		$this->_category->id            = $this->_category->parent = 0;
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 * @throws EE_Error
1323
+	 */
1324
+	protected function _category_list_table()
1325
+	{
1326
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1327
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1328
+				'add_category',
1329
+				'add_category',
1330
+				[],
1331
+				'add-new-h2'
1332
+			);
1333
+		$this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1334
+		$this->display_admin_list_table_page_with_sidebar();
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 * @throws EE_Error
1340
+	 */
1341
+	protected function _category_details($view)
1342
+	{
1343
+		// load formatter helper
1344
+		// load field generator helper
1345
+
1346
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
1347
+		$this->_set_add_edit_form_tags($route);
1348
+
1349
+		$this->_set_category_object();
1350
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
1351
+
1352
+		$delete_action = 'delete_category';
1353
+
1354
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1355
+
1356
+		$this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1357
+
1358
+		// take care of contents
1359
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
1360
+		$this->display_admin_page_with_sidebar();
1361
+	}
1362
+
1363
+
1364
+	protected function _category_details_content(): string
1365
+	{
1366
+		$editor_args['category_desc'] = [
1367
+			'type'          => 'wp_editor',
1368
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1369
+			'class'         => 'my_editor_custom',
1370
+			'wpeditor_args' => ['media_buttons' => false],
1371
+		];
1372
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1373
+
1374
+		$all_terms = get_terms(
1375
+			['espresso_venue_categories'],
1376
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1377
+		);
1378
+
1379
+		// setup category select for term parents.
1380
+		$category_select_values[] = [
1381
+			'text' => esc_html__('No Parent', 'event_espresso'),
1382
+			'id'   => 0,
1383
+		];
1384
+		foreach ($all_terms as $term) {
1385
+			$category_select_values[] = [
1386
+				'text' => $term->name,
1387
+				'id'   => $term->term_id,
1388
+			];
1389
+		}
1390
+
1391
+		$category_select = EEH_Form_Fields::select_input(
1392
+			'category_parent',
1393
+			$category_select_values,
1394
+			$this->_category->parent
1395
+		);
1396
+		$template_args   = [
1397
+			'category'                 => $this->_category,
1398
+			'category_select'          => $category_select,
1399
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1400
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1401
+			'disable'                  => '',
1402
+			'disabled_message'         => false,
1403
+		];
1404
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1405
+		return EEH_Template::display_template($template, $template_args, true);
1406
+	}
1407
+
1408
+
1409
+	/**
1410
+	 * @throws EE_Error
1411
+	 */
1412
+	protected function _delete_categories()
1413
+	{
1414
+		$category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1415
+		$category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1416
+
1417
+		foreach ($category_IDs as $cat_id) {
1418
+			$this->_delete_category($cat_id);
1419
+		}
1420
+
1421
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
1422
+		$query_args = [
1423
+			'action' => 'category_list',
1424
+		];
1425
+		$this->_redirect_after_action(0, '', '', $query_args);
1426
+	}
1427
+
1428
+
1429
+	protected function _delete_category($cat_id)
1430
+	{
1431
+		$cat_id = absint($cat_id);
1432
+		wp_delete_term($cat_id, 'espresso_venue_categories');
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * @throws EE_Error
1438
+	 */
1439
+	protected function _insert_or_update_category($new_category)
1440
+	{
1441
+		$cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1442
+		$success = 0; // we already have a success message so lets not send another.
1443
+		if ($cat_id) {
1444
+			$query_args = [
1445
+				'action'     => 'edit_category',
1446
+				'VEN_CAT_ID' => $cat_id,
1447
+			];
1448
+		} else {
1449
+			$query_args = ['action' => 'add_category'];
1450
+		}
1451
+		$this->_redirect_after_action($success, '', '', $query_args, true);
1452
+	}
1453
+
1454
+
1455
+	private function _insert_category($update = false)
1456
+	{
1457
+		$category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1458
+		$category_name   = $this->request->getRequestParam('category_name', '');
1459
+		$category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1460
+		$category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1461
+
1462
+		if (empty($category_name)) {
1463
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
1464
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1465
+			return false;
1466
+		}
1467
+
1468
+
1469
+		$term_args = [
1470
+			'name'        => $category_name,
1471
+			'description' => $category_desc,
1472
+			'parent'      => $category_parent,
1473
+		];
1474
+
1475
+		$insert_ids = $update
1476
+			? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1477
+			: wp_insert_term(
1478
+				$category_name,
1479
+				'espresso_venue_categories',
1480
+				$term_args
1481
+			);
1482
+
1483
+		if (! is_array($insert_ids)) {
1484
+			EE_Error::add_error(
1485
+				esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1486
+				__FILE__,
1487
+				__FUNCTION__,
1488
+				__LINE__
1489
+			);
1490
+		} else {
1491
+			$category_ID = $insert_ids['term_id'];
1492
+			EE_Error::add_success(
1493
+				sprintf(
1494
+					esc_html__('The category %s was successfully created', 'event_espresso'),
1495
+					$category_name
1496
+				)
1497
+			);
1498
+		}
1499
+
1500
+		return $category_ID;
1501
+	}
1502
+
1503
+
1504
+	/**
1505
+	 * TODO handle category exports()
1506
+	 *
1507
+	 * @return void
1508
+	 */
1509
+	protected function _categories_export()
1510
+	{
1511
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
1512
+		$this->request->mergeRequestParams(
1513
+			[
1514
+				'export'       => 'report',
1515
+				'action'       => 'categories',
1516
+				'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1517
+			]
1518
+		);
1519
+
1520
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1521
+			require_once(EE_CLASSES . 'EE_Export.class.php');
1522
+			$EE_Export = EE_Export::instance($this->request->requestParams());
1523
+			$EE_Export->export();
1524
+		}
1525
+	}
1526
+
1527
+
1528
+	protected function _import_categories()
1529
+	{
1530
+		require_once(EE_CLASSES . 'EE_Import.class.php');
1531
+		EE_Import::instance()->import();
1532
+	}
1533
+
1534
+
1535
+	/**
1536
+	 * @throws EE_Error
1537
+	 * @throws ReflectionException
1538
+	 */
1539
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
1540
+	{
1541
+		// testing term stuff
1542
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1543
+		$order       = $this->request->getRequestParam('order', 'DESC');
1544
+		$limit       = ($current_page - 1) * $per_page;
1545
+		$where       = ['taxonomy' => 'espresso_venue_categories'];
1546
+		$search_term = $this->request->getRequestParam('s');
1547
+		if ($search_term) {
1548
+			$search_term = '%' . $search_term . '%';
1549
+			$where['OR'] = [
1550
+				'Term.name'   => ['LIKE', $search_term],
1551
+				'description' => ['LIKE', $search_term],
1552
+			];
1553
+		}
1554
+
1555
+		$query_params = [
1556
+			$where,
1557
+			'order_by'   => [$orderby => $order],
1558
+			'limit'      => $limit . ',' . $per_page,
1559
+			'force_join' => ['Term'],
1560
+		];
1561
+
1562
+		return $count
1563
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1564
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
1565
+	}
1566
+
1567
+
1568
+	/* end category stuff */
1569
+	/**************/
1570 1570
 }
Please login to merge, or discard this patch.